diff --git a/README.md b/README.md index f861b69..1f5386a 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,12 @@ This Ansible playbook automates the setup of development environments across mul ## 🚀 Usage +### Prerequisites +```bash +# Install required collections +ansible-galaxy collection install -r collections/requirements.yml +``` + ### Basic Setup ```bash # Run on all development machines @@ -40,6 +46,21 @@ ansible-playbook dev-playbook.yml --limit devVM ansible-playbook dev-playbook.yml --limit bottom ``` +### Selective Execution with Tags +```bash +# Security-related roles only +ansible-playbook dev-playbook.yml --tags security + +# Development tools only +ansible-playbook dev-playbook.yml --tags development,docker + +# Applications only +ansible-playbook dev-playbook.yml --tags apps + +# Skip maintenance +ansible-playbook dev-playbook.yml --skip-tags maintenance +``` + ### Skip Reboots Add `skip_reboot=true` to host variables: ```ini diff --git a/collections/requirements.yml b/collections/requirements.yml new file mode 100644 index 0000000..2ea3420 --- /dev/null +++ b/collections/requirements.yml @@ -0,0 +1,6 @@ +--- +collections: + - name: community.general + version: ">=6.0.0" + - name: ansible.posix + version: ">=1.4.0" diff --git a/dev-playbook.yml b/dev-playbook.yml index 964a2b3..12b6136 100644 --- a/dev-playbook.yml +++ b/dev-playbook.yml @@ -2,21 +2,20 @@ become: true roles: - - maintenance - - base - - development - - shell - - docker - - ssh - - user - - applications - - snap + - { role: maintenance, tags: ['maintenance'] } + - { role: base, tags: ['base', 'security'] } + - { role: user, tags: ['user'] } + - { role: ssh, tags: ['ssh', 'security'] } + - { role: shell, tags: ['shell'] } + - { role: development, tags: ['development', 'dev'] } + - { role: docker, tags: ['docker'] } + - { role: applications, tags: ['applications', 'apps'] } + - { role: snap, tags: ['snap', 'apps'] } pre_tasks: - name: Update apt cache apt: update_cache: yes - run_once: true tasks: # Additional tasks can be added here if needed diff --git a/roles/applications/tasks/main.yml b/roles/applications/tasks/main.yml index 46d7555..066b896 100644 --- a/roles/applications/tasks/main.yml +++ b/roles/applications/tasks/main.yml @@ -1,4 +1,14 @@ --- +- name: Check if desktop applications are installed + apt: + list: "{{ item }}" + register: app_check + loop: + - redshift + - libreoffice + - evince + changed_when: false + - name: Install desktop applications apt: name: @@ -6,20 +16,63 @@ - libreoffice - evince state: present + when: + - app_check.results[0].installed is not defined or + - app_check.results[1].installed is not defined or + - app_check.results[2].installed is not defined + +- name: Check if Brave is already installed + command: brave-browser --version + register: brave_check + ignore_errors: true + changed_when: false + +- name: Check if Brave package is installed via apt + apt: + list: brave-browser + register: brave_apt_check + changed_when: false + +- name: Remove old Brave repository files + file: + path: "{{ item }}" + state: absent + loop: + - /etc/apt/sources.list.d/brave-browser.list + - /etc/apt/sources.list.d/brave-browser-release.sources + when: brave_check.rc != 0 or brave_apt_check.results[0].installed is not defined - name: Download Brave APT key get_url: url: https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg dest: /usr/share/keyrings/brave-browser-archive-keyring.gpg mode: '0644' + when: brave_check.rc != 0 or brave_apt_check.results[0].installed is not defined - name: Add Brave repo (all Debian family) apt_repository: repo: "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main" filename: brave-browser state: present + when: brave_check.rc != 0 or brave_apt_check.results[0].installed is not defined + +- name: Update apt cache after Brave repo add + apt: + update_cache: yes + when: brave_check.rc != 0 or brave_apt_check.results[0].installed is not defined - name: Install Brave browser apt: name: brave-browser state: present + when: brave_check.rc != 0 or brave_apt_check.results[0].installed is not defined + +- name: Display application status + debug: + msg: + - "Redshift installed: {{ 'Yes' if app_check.results[0].installed is defined else 'No' }}" + - "LibreOffice installed: {{ 'Yes' if app_check.results[1].installed is defined else 'No' }}" + - "Evince installed: {{ 'Yes' if app_check.results[2].installed is defined else 'No' }}" + - "Brave already installed: {{ brave_check.stdout if brave_check.rc == 0 else 'Not found' }}" + - "Brave package installed: {{ 'Yes' if brave_apt_check.results[0].installed is defined else 'No' }}" + - "Actions taken: {{ 'None - All apps already present' if app_check.results[0].installed is defined and app_check.results[1].installed is defined and app_check.results[2].installed is defined and brave_check.rc == 0 and brave_apt_check.results[0].installed is defined else 'Some applications installed/updated' }}" diff --git a/roles/base/handlers/main.yml b/roles/base/handlers/main.yml index e38df8a..13dc1ea 100644 --- a/roles/base/handlers/main.yml +++ b/roles/base/handlers/main.yml @@ -7,5 +7,4 @@ state: restarted - name: reload ufw - ufw: - state: reloaded + command: ufw reload diff --git a/roles/base/tasks/main.yml b/roles/base/tasks/main.yml index da83d22..3826f97 100644 --- a/roles/base/tasks/main.yml +++ b/roles/base/tasks/main.yml @@ -16,6 +16,7 @@ - net-tools - ufw - fail2ban + - mailutils state: present - name: Install monitoring tools @@ -33,10 +34,7 @@ mode: '0644' notify: restart fail2ban -- name: Enable UFW - ufw: - state: enabled - policy: deny +# UFW enablement moved to ssh role to avoid lockout - name: Set timezone timezone: diff --git a/roles/docker/tasks/main.yml b/roles/docker/tasks/main.yml index 74bfd86..620bdf8 100644 --- a/roles/docker/tasks/main.yml +++ b/roles/docker/tasks/main.yml @@ -1,4 +1,24 @@ --- +- name: Debug distribution information + debug: + msg: + - "Distribution: {{ ansible_facts['distribution'] }}" + - "Distribution Release: {{ ansible_facts['distribution_release'] }}" + - "Distribution Version: {{ ansible_facts['distribution_version'] }}" + - "OS Family: {{ ansible_facts['os_family'] }}" + +- name: Check if Docker is already installed + command: docker --version + register: docker_check + ignore_errors: true + changed_when: false + +- name: Check if Docker packages are installed via apt + apt: + list: docker-ce + register: docker_apt_check + changed_when: false + - name: Install Docker requirements apt: name: @@ -10,15 +30,57 @@ state: present update_cache: yes -- name: Add Docker's official GPG key - apt_key: - url: https://download.docker.com/linux/ubuntu/gpg - state: present +- name: Remove old Docker repository files + file: + path: "{{ item }}" + state: absent + loop: + - /etc/apt/sources.list.d/docker.list + - /etc/apt/sources.list.d/docker-ce.list + when: docker_check.rc != 0 or docker_apt_check.results[0].installed is not defined -- name: Add Docker repository +- name: Create keyrings directory + file: + path: /etc/apt/keyrings + state: directory + mode: '0755' + when: docker_check.rc != 0 or docker_apt_check.results[0].installed is not defined + +- name: Download Docker's official GPG key + get_url: + url: https://download.docker.com/linux/ubuntu/gpg + dest: /etc/apt/keyrings/docker.gpg + mode: '0644' + when: docker_check.rc != 0 or docker_apt_check.results[0].installed is not defined + +- name: Add Docker repository for Ubuntu apt_repository: - repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable" + repo: "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable" state: present + when: + - ansible_facts['distribution'] == "Ubuntu" + - docker_check.rc != 0 or docker_apt_check.results[0].installed is not defined + +- name: Add Docker repository for Debian + apt_repository: + repo: "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian {{ ansible_distribution_release }} stable" + state: present + when: + - ansible_facts['distribution'] == "Debian" + - docker_check.rc != 0 or docker_apt_check.results[0].installed is not defined + +- name: Add Docker repository for Linux Mint + apt_repository: + repo: "deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable" + state: present + when: + - ansible_facts['distribution'] == "Linux Mint" + - docker_check.rc != 0 or docker_apt_check.results[0].installed is not defined + +- name: Update apt cache after Docker repo add + apt: + update_cache: yes + when: docker_check.rc != 0 or docker_apt_check.results[0].installed is not defined - name: Install Docker CE apt: @@ -30,16 +92,26 @@ - docker-compose-plugin state: present update_cache: yes + when: docker_check.rc != 0 or docker_apt_check.results[0].installed is not defined - name: Start and enable Docker service systemd: name: docker state: started enabled: yes + when: docker_check.rc != 0 or docker_apt_check.results[0].installed is not defined - name: Add user to docker group user: name: "{{ ansible_user }}" groups: docker append: yes + when: docker_check.rc != 0 or docker_apt_check.results[0].installed is not defined + +- name: Display Docker status + debug: + msg: + - "Docker already installed: {{ docker_check.stdout if docker_check.rc == 0 else 'Not found' }}" + - "Docker CE package installed: {{ 'Yes' if docker_apt_check.results[0].installed is defined else 'No' }}" + - "Actions taken: {{ 'None - Docker already present' if docker_check.rc == 0 and docker_apt_check.results[0].installed is defined else 'Docker installation/configuration performed' }}" diff --git a/roles/maintenance/tasks/main.yml b/roles/maintenance/tasks/main.yml index b0a5aed..cebd7bf 100644 --- a/roles/maintenance/tasks/main.yml +++ b/roles/maintenance/tasks/main.yml @@ -15,9 +15,15 @@ apt: autoclean: yes -- name: Reboot if tasks changed things +- name: Check if reboot is required + stat: + path: /var/run/reboot-required + register: reboot_required + +- name: Reboot if required reboot: msg: "Reboot triggered by Ansible after system changes." - when: + when: - ansible_facts['pkg_mgr'] == "apt" - - skip_reboot is not defined or skip_reboot != "true" \ No newline at end of file + - reboot_required.stat.exists + - skip_reboot | default(false) | bool == false \ No newline at end of file diff --git a/roles/ssh/handlers/main.yml b/roles/ssh/handlers/main.yml index 7e51bf6..c567a5b 100644 --- a/roles/ssh/handlers/main.yml +++ b/roles/ssh/handlers/main.yml @@ -1,2 +1,5 @@ --- -# handlers file for ssh +- name: restart ssh + systemd: + name: ssh + state: restarted \ No newline at end of file diff --git a/roles/ssh/tasks/main.yml b/roles/ssh/tasks/main.yml index 40fd4c1..d3c7818 100644 --- a/roles/ssh/tasks/main.yml +++ b/roles/ssh/tasks/main.yml @@ -9,3 +9,8 @@ rule: allow name: OpenSSH +- name: Enable UFW with deny default policy + ufw: + state: enabled + policy: deny +