diff --git a/inventories/all.yml b/inventories/all.yml index acadcee..3558c67 100644 --- a/inventories/all.yml +++ b/inventories/all.yml @@ -1,20 +1,20 @@ all: - hosts: - webserver: - ansible_host: 192.168.2.15 - ansible_user: root - nextcloud: - ansible_host: 192.168.2.120 - ansible_user: root - pihole: - ansible_host: 192.168.2.2 - ansible_user: root - docker: - ansible_host: 192.168.2.10 - ansible_user: root - # eve: - # ansible_host: 192.168.2.12 - # ansible_user: root - storage: - ansible_host: 192.168.2.115 - ansible_user: root \ No newline at end of file + vars: + ansible_user: root + children: + ubuntu: + hosts: + webserver: + ansible_host: 192.168.2.15 + docker: + ansible_host: 192.168.2.10 + rocky: + hosts: + pihole: + ansible_host: 192.168.2.2 + bot: + ansible_host: 192.168.2.174 + storage: + ansible_host: 192.168.2.115 + nextcloud: + ansible_host: 192.168.2.120 \ No newline at end of file diff --git a/playbooks/backup_docker.yml b/playbooks/backup_docker.yml new file mode 100644 index 0000000..e59690f --- /dev/null +++ b/playbooks/backup_docker.yml @@ -0,0 +1,62 @@ +--- +- name: Backup Docker containers and volumes to storage + hosts: docker + become: true + + vars: + backup_dest: "192.168.2.115:/mnt/storage/Docker_backups" + compose_dir: "/home/harry" + volumes_dir: "/var/lib/docker/volumes" + + tasks: + - name: Ensure backup destination directories exist + ansible.builtin.command: + cmd: ssh -o StrictHostKeyChecking=no root@192.168.2.115 "mkdir -p /mnt/storage/Docker_backups/compose /mnt/storage/Docker_backups/volumes" + changed_when: false + + - name: Rsync compose files and configs (safe while running) + ansible.builtin.shell: | + rsync -az --delete \ + --include='*/' \ + --include='docker-compose.yml' \ + --include='compose.yml' \ + --include='.env' \ + --include='*.conf' \ + --include='*.yml' \ + --include='*.yaml' \ + --include='*.json' \ + --exclude='node_modules/' \ + --exclude='.git/' \ + --exclude='__pycache__/' \ + {{ compose_dir }}/ root@{{ backup_dest }}/compose/ + register: compose_sync + + - name: Get list of running containers + ansible.builtin.command: docker ps -q + register: running_containers + changed_when: false + + - name: Stop all containers + ansible.builtin.command: docker stop $(docker ps -q) + when: running_containers.stdout | length > 0 + + - name: Rsync Docker volumes to storage + ansible.builtin.shell: | + rsync -az --delete \ + {{ volumes_dir }}/ root@{{ backup_dest }}/volumes/ + register: volume_sync + + - name: Start all containers back up + ansible.builtin.command: docker start $(docker ps -aq) + + - name: Verify containers are running + ansible.builtin.command: docker ps --format "{{ '{{' }}.Names{{ '}}' }} - {{ '{{' }}.Status{{ '}}' }}" + register: container_status + changed_when: false + + - name: Backup summary + ansible.builtin.debug: + msg: + - "Compose sync: {{ 'OK' if compose_sync.rc == 0 else 'FAILED' }}" + - "Volume sync: {{ 'OK' if volume_sync.rc == 0 else 'FAILED' }}" + - "Containers running: {{ container_status.stdout_lines | length }}" diff --git a/playbooks/bootstrap_lxc.yml b/playbooks/bootstrap_lxc.yml index 3d10dec..b920207 100644 --- a/playbooks/bootstrap_lxc.yml +++ b/playbooks/bootstrap_lxc.yml @@ -1,11 +1,10 @@ -- name: Bootstrap new Linux servers - hosts: all - become: yes +- name: Bootstrap - Install packages on Ubuntu + hosts: ubuntu + become: true tasks: - - - name: Install packages on Debian/Ubuntu - apt: + - name: Install packages via apt + ansible.builtin.apt: name: - vim - htop @@ -34,17 +33,20 @@ - mtr - tar state: present - update_cache: yes - when: ansible_facts['os_family'] == "Debian" + update_cache: true - - name: Ensure EPEL repo is enabled (RHEL/CentOS/AlmaLinux) - yum: +- name: Bootstrap - Install packages on Rocky Linux + hosts: rocky + become: true + + tasks: + - name: Ensure EPEL repo is enabled + ansible.builtin.dnf: name: epel-release state: present - when: ansible_facts['os_family'] == "RedHat" - - name: Install packages on RHEL/CentOS/AlmaLinux - yum: + - name: Install packages via dnf + ansible.builtin.dnf: name: - tar - vim @@ -65,7 +67,7 @@ - tree - bash-completion - traceroute - - bind-utils # provides dig, nslookup + - bind-utils - ca-certificates - python3 - python3-pip @@ -73,11 +75,15 @@ - sysstat - screen state: present - update_cache: yes - when: ansible_facts['os_family'] == "RedHat" + update_cache: true +- name: Bootstrap - Configure SSH access + hosts: all + become: true + + tasks: - name: Ensure root's .ssh directory exists - file: + ansible.builtin.file: path: /root/.ssh state: directory owner: root @@ -85,7 +91,7 @@ mode: '0700' - name: Set authorized_keys for root - copy: + ansible.builtin.copy: dest: /root/.ssh/authorized_keys content: | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINegitHaQG8i+s412h3wTWf/KvpeX1CEpYFva9MhHR+7 ansible-key @@ -94,35 +100,43 @@ mode: '0600' - name: Permit root login via public key - lineinfile: + ansible.builtin.lineinfile: path: /etc/ssh/sshd_config regexp: '^#?PermitRootLogin\s+' line: 'PermitRootLogin prohibit-password' state: present - backup: yes + backup: true - name: Ensure PubkeyAuthentication is enabled - lineinfile: + ansible.builtin.lineinfile: path: /etc/ssh/sshd_config regexp: '^#?PubkeyAuthentication\s+' line: 'PubkeyAuthentication yes' state: present - name: Ensure PasswordAuthentication is enabled - lineinfile: + ansible.builtin.lineinfile: path: /etc/ssh/sshd_config regexp: '^#?PasswordAuthentication\s+' line: 'PasswordAuthentication yes' state: present - - name: Restart SSH service (Debian) - service: +- name: Bootstrap - Restart SSH on Ubuntu + hosts: ubuntu + become: true + + tasks: + - name: Restart ssh service + ansible.builtin.service: name: ssh state: restarted - when: ansible_facts['os_family'] == "Debian" - - name: Restart SSH service (RHEL) - service: +- name: Bootstrap - Restart SSH on Rocky Linux + hosts: rocky + become: true + + tasks: + - name: Restart sshd service + ansible.builtin.service: name: sshd state: restarted - when: ansible_facts['os_family'] == "RedHat" diff --git a/playbooks/time-region.yml b/playbooks/time-region.yml index dd9ca46..a0c4c86 100644 --- a/playbooks/time-region.yml +++ b/playbooks/time-region.yml @@ -1,120 +1,115 @@ --- -- name: Configure timezone and NTP (LXC-Aware) +- name: Configure timezone on all hosts hosts: all - become: yes + become: true + gather_facts: true vars: timezone_region: "America/New_York" - ntp_server: "time.google.com" tasks: - # ---------------------------------------------------------- - # SETUP FACTS - # ---------------------------------------------------------- - - name: Ensure virtualization facts are gathered - ansible.builtin.setup: - gather_subset: - - virtual - - # ---------------------------------------------------------- - # TIMEZONE (Required for ALL systems, LXC and VMs) - # ---------------------------------------------------------- - name: Copy timezone file ansible.builtin.copy: src: "/usr/share/zoneinfo/{{ timezone_region }}" dest: /etc/localtime - remote_src: yes - register: tz_copy + remote_src: true - name: Write /etc/timezone ansible.builtin.copy: dest: /etc/timezone content: "{{ timezone_region }}\n" - register: tz_write - # ---------------------------------------------------------- - # LXC CONTAINER HANDLING (Disable NTP) - # ---------------------------------------------------------- - - name: Stop and mask timesyncd on LXC (Ubuntu/Debian) +- name: Disable NTP on Ubuntu LXC containers + hosts: ubuntu + become: true + + tasks: + - name: Stop and mask timesyncd on LXC ansible.builtin.systemd: name: systemd-timesyncd state: stopped - enabled: no - masked: yes - when: - - ansible_os_family == "Debian" - - ansible_virtualization_type == "lxc" + enabled: false + masked: true + when: ansible_virtualization_type == "lxc" - - name: Stop and mask chronyd on LXC (RHEL-based) +- name: Disable NTP on Rocky Linux LXC containers + hosts: rocky + become: true + + tasks: + - name: Stop and mask chronyd on LXC ansible.builtin.systemd: name: chronyd state: stopped - enabled: no - masked: yes - when: - - ansible_os_family == "RedHat" - - ansible_virtualization_type == "lxc" + enabled: false + masked: true + when: ansible_virtualization_type == "lxc" - # ---------------------------------------------------------- - # FULL VM / HARDWARE HANDLING (Configure NTP) - # ---------------------------------------------------------- - - name: Configure timesyncd on VMs (Ubuntu/Debian) +- name: Configure NTP on Ubuntu VMs + hosts: ubuntu + become: true + + vars: + ntp_server: "time.google.com" + + tasks: + - name: Configure timesyncd ansible.builtin.lineinfile: path: /etc/systemd/timesyncd.conf regexp: '^#?NTP=' line: "NTP={{ ntp_server }}" state: present - when: - - ansible_os_family == "Debian" - - ansible_virtualization_type != "lxc" + when: ansible_virtualization_type != "lxc" notify: Restart timesyncd - - name: Disable default chrony pools on VMs (RHEL-based) - ansible.builtin.replace: - path: /etc/chrony.conf - regexp: '^(pool|server) .*' - replace: '# \1 removed by Ansible' - when: - - ansible_os_family == "RedHat" - - ansible_virtualization_type != "lxc" - - - name: Configure chrony on VMs (RHEL-based) - ansible.builtin.lineinfile: - path: /etc/chrony.conf - line: "server {{ ntp_server }} iburst" - insertafter: EOF - state: present - when: - - ansible_os_family == "RedHat" - - ansible_virtualization_type != "lxc" - notify: Restart chronyd - - # ---------------------------------------------------------- - # FINAL SUMMARY - # ---------------------------------------------------------- - - name: Verify current system time - ansible.builtin.command: date - register: check_time - changed_when: false - - - name: Final summary - ansible.builtin.debug: - msg: - - "Setup complete on {{ inventory_hostname }} (Environment: {{ ansible_virtualization_type | default('unknown') }})" - - "System Time: {{ check_time.stdout }}" - - # ---------------------------------------------------------- - # HANDLERS (Only triggers for VMs) - # ---------------------------------------------------------- handlers: - name: Restart timesyncd ansible.builtin.systemd: name: systemd-timesyncd state: restarted - enabled: yes + enabled: true +- name: Configure NTP on Rocky Linux VMs + hosts: rocky + become: true + + vars: + ntp_server: "time.google.com" + + tasks: + - name: Disable default chrony pools + ansible.builtin.replace: + path: /etc/chrony.conf + regexp: '^(pool|server) .*' + replace: '# \1 removed by Ansible' + when: ansible_virtualization_type != "lxc" + + - name: Configure chrony NTP server + ansible.builtin.lineinfile: + path: /etc/chrony.conf + line: "server {{ ntp_server }} iburst" + insertafter: EOF + state: present + when: ansible_virtualization_type != "lxc" + notify: Restart chronyd + + handlers: - name: Restart chronyd ansible.builtin.systemd: name: chronyd state: restarted - enabled: yes \ No newline at end of file + enabled: true + +- name: Verify time configuration + hosts: all + become: true + + tasks: + - name: Check current system time + ansible.builtin.command: date + register: check_time + changed_when: false + + - name: Summary + ansible.builtin.debug: + msg: "{{ inventory_hostname }} ({{ ansible_virtualization_type | default('unknown') }}) - {{ check_time.stdout }}" \ No newline at end of file diff --git a/playbooks/update_system.yml b/playbooks/update_system.yml index 7313c09..4848cef 100644 --- a/playbooks/update_system.yml +++ b/playbooks/update_system.yml @@ -21,33 +21,26 @@ when: ping_result is not succeeded delegate_to: localhost -- name: Update and Upgrade Packages - hosts: reachable_hosts +- name: Update and Upgrade - Ubuntu + hosts: ubuntu:&reachable_hosts become: true - gather_facts: true + gather_facts: false tasks: - - name: Update & Upgrade - Debian-based systems + - name: Update & Upgrade via apt ansible.builtin.apt: update_cache: true cache_valid_time: 3600 upgrade: dist - when: ansible_os_family == "Debian" - - name: Update & Upgrade - Modern RHEL-based systems (DNF) +- name: Update and Upgrade - Rocky Linux + hosts: rocky:&reachable_hosts + become: true + gather_facts: false + + tasks: + - name: Update & Upgrade via dnf ansible.builtin.dnf: name: "*" state: latest - update_cache: true - when: - - ansible_os_family == "RedHat" - - ansible_pkg_mgr == "dnf" - - - name: Update & Upgrade - Legacy RHEL-based systems (YUM) - ansible.builtin.yum: - name: "*" - state: latest - update_cache: true - when: - - ansible_os_family == "RedHat" - - ansible_pkg_mgr == "yum" \ No newline at end of file + update_cache: true \ No newline at end of file