fix: resolve best practice and lint violations

- Convert ~290 short module names to FQCNs across all roles
- Change become: yes/no to become: true/false, gather_facts: no to false
- Remove deprecated inject_facts_as_vars from ansible.cfg
- Add missing task names to import_tasks/include_role calls
- Add become: yes to librenms clone task (partial-become fix)
- Add pipefail to risky shell command in udp-gro-fix.yml
- Quote all octal mode values
- Harden .ansible-lint with production profile and empty skip_list
- Update findings.md with all fixes
This commit is contained in:
Graham McIntire 2026-06-04 14:34:23 -05:00
parent 6f0d308fea
commit ee72c64246
No known key found for this signature in database
GPG key ID: F4ABF488E6029E59
35 changed files with 263 additions and 247 deletions

View file

@ -1,2 +1,8 @@
skip_list: ---
- '403' # ansible-lint configuration
profile: production
exclude_paths:
- .ansible/
- collections/
skip_list: []

View file

@ -1,6 +1,5 @@
[defaults] [defaults]
forks = 20 forks = 20
inject_facts_as_vars = True
# display_skipped_hosts=False # display_skipped_hosts=False
# deprecation_warnings=False # deprecation_warnings=False

View file

@ -1,7 +1,7 @@
--- ---
- name: Initial setup for proxmox servers - name: Initial setup for proxmox servers
hosts: proxmox hosts: proxmox
user: root ansible.builtin.user:
become: true become: true
tasks: tasks:

View file

@ -3,7 +3,7 @@
hosts: all hosts: all
tags: bootstrap tags: bootstrap
remote_user: graham remote_user: graham
gather_facts: no gather_facts: false
vars: vars:
ansible_user: graham ansible_user: graham
tasks: tasks:
@ -12,7 +12,7 @@
# password prompt that the Makefile's `-K` is designed to feed — and on a # password prompt that the Makefile's `-K` is designed to feed — and on a
# passwordless-sudo host with no `-K` provided, hang indefinitely. # passwordless-sudo host with no `-K` provided, hang indefinitely.
- name: Probe sudo state - name: Probe sudo state
raw: | ansible.builtin.raw: |
if command -v sudo >/dev/null 2>&1; then if command -v sudo >/dev/null 2>&1; then
if sudo -n true 2>/dev/null; then if sudo -n true 2>/dev/null; then
echo "sudo-passwordless" echo "sudo-passwordless"
@ -26,7 +26,7 @@
changed_when: false changed_when: false
- name: Ensure sudo is present - name: Ensure sudo is present
raw: | ansible.builtin.raw: |
if command -v apt-get >/dev/null 2>&1; then if command -v apt-get >/dev/null 2>&1; then
apt-get update && apt-get install -y sudo apt-get update && apt-get install -y sudo
elif command -v dnf >/dev/null 2>&1; then elif command -v dnf >/dev/null 2>&1; then
@ -39,13 +39,13 @@
echo "Unsupported package manager for sudo installation" >&2 echo "Unsupported package manager for sudo installation" >&2
exit 1 exit 1
fi fi
become: yes become: true
become_method: su become_method: su
become_user: root become_user: root
when: "'sudo-missing' in sudo_state.stdout" when: "'sudo-missing' in sudo_state.stdout"
- name: Ensure Python 3 is present - name: Ensure Python 3 is present
raw: | ansible.builtin.raw: |
if command -v python3 >/dev/null 2>&1; then if command -v python3 >/dev/null 2>&1; then
exit 0 exit 0
fi fi
@ -62,7 +62,7 @@
exit 1 exit 1
fi fi
changed_when: false changed_when: false
become: yes become: true
# Once sudo exists (newly installed or pre-existing) prefer it; only fall # Once sudo exists (newly installed or pre-existing) prefer it; only fall
# back to `su` if sudo really isn't there. # back to `su` if sudo really isn't there.
become_method: "{{ 'su' if 'sudo-missing' in sudo_state.stdout else 'sudo' }}" become_method: "{{ 'su' if 'sudo-missing' in sudo_state.stdout else 'sudo' }}"
@ -72,7 +72,7 @@
hosts: all hosts: all
tags: bootstrap tags: bootstrap
remote_user: graham remote_user: graham
become: yes become: true
become_method: sudo become_method: sudo
vars: vars:
ansible_user: graham ansible_user: graham

View file

@ -10,6 +10,14 @@
- **Removed broken `setup-user` Makefile target** — referenced non-existent `setup-user.sh`. - **Removed broken `setup-user` Makefile target** — referenced non-existent `setup-user.sh`.
- **Fixed tracking issues**`git rm --cached` for 5 `.DS_Store` files and `.vscode/settings.json`; added `.ansible/` to `.gitignore`. - **Fixed tracking issues**`git rm --cached` for 5 `.DS_Store` files and `.vscode/settings.json`; added `.ansible/` to `.gitignore`.
- **Fixed stale documentation** — updated `CLAUDE.md` and `README.md` to reflect actual playbook structure, roles, inventory groups, and collections. - **Fixed stale documentation** — updated `CLAUDE.md` and `README.md` to reflect actual playbook structure, roles, inventory groups, and collections.
- **Fixed non-FQCN module references** — converted ~290 short module names (`apt:`, `service:`, `template:`, etc.) to FQCNs (`ansible.builtin.apt:`, etc.) across all roles and playbooks.
- **Fixed `become:`/`gather_facts:` boolean forms**`become: yes``become: true`, `gather_facts: no``gather_facts: false` in all plays.
- **Removed deprecated `inject_facts_as_vars`** from `ansible.cfg`.
- **Added missing task names**`import_tasks`/`include_role` calls in `base/tasks/main.yml` and `general/tasks/main.yml` now have descriptive names.
- **Fixed `partial-become` bug** — added `become: yes` to librenms clone task.
- **Added `pipefail`** to risky shell command in `udp-gro-fix.yml`.
- **Quoted octal mode values**`mode: 0755``mode: '0755'`, etc.
- **Hardened `.ansible-lint` config** — set `profile: production`, added exclude paths, removed all skip_list entries.
--- ---
@ -68,16 +76,7 @@
## 🟡 Best Practice / Lint Violations ## 🟡 Best Practice / Lint Violations
| # | Issue | Location | All items in this section have been fixed.
|---|-------|----------|
| 29 | **~100+ non-FQCN module references** — `apt:`, `service:`, `template:` instead of `ansible.builtin.*` throughout every role. | All roles |
| 30 | **`mode` values without proper quoting** — `644`, `0755`, `00644` used instead of `'0644'`, `'0755'`. | Multiple files |
| 31 | **`become: yes` / `gather_facts: no`** — Uses deprecated `yes`/`no` forms instead of `true`/`false`. | `playbook.yml`, `bootstrap.yml`, `netbox.yml` |
| 32 | **`inject_facts_as_vars` is deprecated** — Will be removed in future Ansible. | `ansible.cfg:3` |
| 33 | **Tasks missing `name:`** — Several unnamed task lists. | `roles/base/tasks/users.yml`, `roles/general/tasks/debian/motd.yml`, `roles/debug/tasks/main.yml` |
| 34 | **`partial-become` bug** — `become_user: librenms` without `become: yes`. | `roles/librenms/tasks/main.yml:78` |
| 35 | **`risky-shell-pipe` without pipefail** | `roles/general/tasks/udp-gro-fix.yml:13` |
| 36 | **`.ansible-lint` config is minimal** — Profile `min`, no excluded paths, no `warn_list`. Skips deprecated rule `403`. | `.ansible-lint` |
--- ---
@ -108,18 +107,23 @@
| 47 | `.ansible/` directory not in `.gitignore` | Added to `.gitignore` | | 47 | `.ansible/` directory not in `.gitignore` | Added to `.gitignore` |
| 48 | Stale `CLAUDE.md` (references `general.yml`, missing roles, wrong commands) | Rewritten with accurate playbooks, roles, collections, commands | | 48 | Stale `CLAUDE.md` (references `general.yml`, missing roles, wrong commands) | Rewritten with accurate playbooks, roles, collections, commands |
| 49 | Stale `README.md` (wrong directory tree, incomplete groups) | Rewritten with accurate structure and inventory groups | | 49 | Stale `README.md` (wrong directory tree, incomplete groups) | Rewritten with accurate structure and inventory groups |
| 29 | Non-FQCN module references (~290 instances) | Converted all to FQCNs across all roles and playbooks |
| 30 | Unquoted octal mode values (9 instances) | All quoted with single quotes |
| 31 | `become: yes` / `gather_facts: no` | Changed to `become: true` / `gather_facts: false` |
| 32 | `inject_facts_as_vars` deprecated | Removed from `ansible.cfg` |
| 33 | Missing task names on `import_tasks`/`include_role` | Added descriptive names |
| 34 | `partial-become` bug in librenms | Added `become: yes` |
| 35 | `risky-shell-pipe` without pipefail | Added `set -o pipefail` |
| 36 | Minimal `.ansible-lint` config | Set `profile: production`, added exclude paths, empty skip_list |
--- ---
## Recommended Top 10 Fixes ## Recommended Top 5 Fixes
## Recommended Top 5 Fixes
1. **Rotate all 4 plaintext secrets in `.envrc`** and move to `ansible-vault` 1. **Rotate all 4 plaintext secrets in `.envrc`** and move to `ansible-vault`
2. **Add `geerlingguy.postgresql` to `requirements.yml`** — will crash otherwise 2. **Add `geerlingguy.postgresql` to `requirements.yml`** — will crash otherwise
3. **Restore `general.yml` or update Makefile/docs** to point to `playbook.yml` 3. **Add defaults for 4 undefined template variables** (`ntpserver`, `template_run_date`, `deb_mirror`, `sshd.*`) — will crash at runtime
4. **Add defaults for 4 undefined template variables** (`ntpserver`, `template_run_date`, `deb_mirror`, `sshd.*`) — will crash at runtime 4. **Remove `alpine` role reference** in `roles/base/tasks/main.yml` or create the role
5. **Remove `alpine` role reference** in `roles/base/tasks/main.yml` or create the role 5. **Fix SSH `-t` flag placement** in Makefile reboot targets
6. **Fix SSH `-t` flag placement** in Makefile reboot targets
7. **Fix `ansible.cfg`** — move `ansible_user` to `[defaults]` as `remote_user`
8. **Add `set -o pipefail`** to `run.sh`
9. **Add `become: yes`** to the librenms clone task at `roles/librenms/tasks/main.yml:78`
10. Fix firewall role double-run or remove duplicate

View file

@ -2,7 +2,7 @@
# Playbook to deploy NetBox # Playbook to deploy NetBox
- name: Deploy NetBox - name: Deploy NetBox
hosts: netbox.vntx.net hosts: netbox.vntx.net
become: yes become: true
roles: roles:
- base - base
- netbox - netbox

View file

@ -170,7 +170,7 @@
state: started state: started
- name: Wait for VM to be accessible via SSH - name: Wait for VM to be accessible via SSH
wait_for: ansible.builtin.wait_for:
host: "{{ vm_ip }}" host: "{{ vm_ip }}"
port: 22 port: 22
delay: 30 delay: 30
@ -178,14 +178,14 @@
state: started state: started
- name: Add VM to in-memory inventory - name: Add VM to in-memory inventory
add_host: ansible.builtin.add_host:
name: "{{ vm_name }}" name: "{{ vm_name }}"
ansible_host: "{{ vm_ip }}" ansible_host: "{{ vm_ip }}"
groups: bind9_servers groups: bind9_servers
- name: Configure BIND9 Servers - name: Configure BIND9 Servers
hosts: bind9_servers hosts: bind9_servers
become: yes become: true
gather_facts: true gather_facts: true
tags: tags:
- dns - dns
@ -196,10 +196,9 @@
- role: ns - role: ns
tags: ns tags: ns
# Plays from general.yml
- name: Apply general configuration to all nodes - name: Apply general configuration to all nodes
hosts: all hosts: all
become: yes become: true
become_method: sudo become_method: sudo
roles: roles:
- general - general
@ -208,7 +207,7 @@
- name: Configure LibreNMS servers - name: Configure LibreNMS servers
hosts: librenms_servers hosts: librenms_servers
become: yes become: true
gather_facts: true gather_facts: true
tags: tags:
- librenms - librenms
@ -217,7 +216,7 @@
- name: Configure aprsc servers - name: Configure aprsc servers
hosts: aprsc_servers hosts: aprsc_servers
become: yes become: true
gather_facts: true gather_facts: true
tags: tags:
- aprsc - aprsc
@ -226,7 +225,7 @@
- name: Configure UISP servers - name: Configure UISP servers
hosts: uisp_servers hosts: uisp_servers
become: yes become: true
gather_facts: true gather_facts: true
tags: tags:
- uisp - uisp
@ -235,7 +234,7 @@
- name: Configure Dokku servers - name: Configure Dokku servers
hosts: dokku_servers hosts: dokku_servers
become: yes become: true
gather_facts: true gather_facts: true
tags: tags:
- dokku - dokku
@ -244,7 +243,7 @@
- name: Configure node_exporter targets - name: Configure node_exporter targets
hosts: node_exporter_servers hosts: node_exporter_servers
become: yes become: true
gather_facts: true gather_facts: true
tags: tags:
- node_exporter - node_exporter
@ -254,7 +253,7 @@
- name: Configure Prometheus monitoring stack - name: Configure Prometheus monitoring stack
hosts: prometheus_servers hosts: prometheus_servers
become: yes become: true
gather_facts: true gather_facts: true
tags: tags:
- prometheus_stack - prometheus_stack

View file

@ -1,5 +1,5 @@
--- ---
- name: restart aprsc - name: restart aprsc
systemd: ansible.builtin.systemd:
name: aprsc name: aprsc
state: restarted state: restarted

View file

@ -1,18 +1,18 @@
--- ---
- name: Add aprsc APT repository - name: Add aprsc APT repository
apt_repository: ansible.builtin.apt_repository:
repo: "{{ aprsc_apt_repo }}" repo: "{{ aprsc_apt_repo }}"
state: present state: present
filename: aprsc filename: aprsc
- name: Install aprsc - name: Install aprsc
apt: ansible.builtin.apt:
name: aprsc name: aprsc
state: present state: present
update_cache: true update_cache: true
- name: Deploy aprsc configuration - name: Deploy aprsc configuration
template: ansible.builtin.template:
src: aprsc.conf.j2 src: aprsc.conf.j2
dest: "{{ aprsc_path }}/etc/aprsc.conf" dest: "{{ aprsc_path }}/etc/aprsc.conf"
owner: root owner: root
@ -21,13 +21,13 @@
notify: restart aprsc notify: restart aprsc
- name: Enable and start aprsc-chroot service - name: Enable and start aprsc-chroot service
systemd: ansible.builtin.systemd:
name: aprsc-chroot name: aprsc-chroot
enabled: true enabled: true
state: started state: started
- name: Enable and start aprsc service - name: Enable and start aprsc service
systemd: ansible.builtin.systemd:
name: aprsc name: aprsc
state: started state: started
enabled: true enabled: true

View file

@ -1,10 +1,10 @@
--- ---
- name: restart ntp - name: restart ntp
service: ansible.builtin.service:
name: "{{ ntp_service | default('ntp') }}" name: "{{ ntp_service | default('ntp') }}"
state: restarted state: restarted
- name: restart ssh - name: restart ssh
service: ansible.builtin.service:
name: "{{ ssh_service | default('sshd') }}" name: "{{ ssh_service | default('sshd') }}"
state: restarted state: restarted

View file

@ -3,47 +3,49 @@
# Initial system information # Initial system information
- name: Show hostname - name: Show hostname
debug: ansible.builtin.debug:
msg: "{{ ansible_facts['hostname'] }}" msg: "{{ ansible_facts['hostname'] }}"
- name: Show IPv4 address - name: Show IPv4 address
debug: ansible.builtin.debug:
msg: "{{ ansible_facts['default_ipv4']['address'] }}" msg: "{{ ansible_facts['default_ipv4']['address'] }}"
when: ansible_facts['default_ipv4']['address'] is defined when: ansible_facts['default_ipv4']['address'] is defined
- name: Show IPv6 address - name: Show IPv6 address
debug: ansible.builtin.debug:
msg: "{{ ansible_facts['default_ipv6']['address'] }}" msg: "{{ ansible_facts['default_ipv6']['address'] }}"
when: ansible_facts['default_ipv6']['address'] is defined when: ansible_facts['default_ipv6']['address'] is defined
# Base package installation - name: Install base packages
- import_tasks: packages.yml ansible.builtin.import_tasks: packages.yml
tags: tags:
- packages - packages
- common - common
# User and group setup - name: Configure users and groups
- import_tasks: users.yml ansible.builtin.import_tasks: users.yml
tags: tags:
- users - users
- bootstrap - bootstrap
# Base system configuration - name: Configure system settings
- import_tasks: system.yml ansible.builtin.import_tasks: system.yml
tags: tags:
- system - system
- common - common
# OS-specific configurations - name: Apply AlmaLinux-specific configuration
- include_role: ansible.builtin.include_role:
name: almalinux name: almalinux
when: ansible_facts['os_family'] == "RedHat" when: ansible_facts['os_family'] == "RedHat"
- include_role: - name: Apply Debian-specific configuration
ansible.builtin.include_role:
name: debian name: debian
when: ansible_facts['os_family'] == "Debian" when: ansible_facts['os_family'] == "Debian"
- include_role: - name: Apply Alpine-specific configuration
ansible.builtin.include_role:
name: alpine name: alpine
when: ansible_facts['os_family'] == "Alpine" when: ansible_facts['os_family'] == "Alpine"

View file

@ -4,7 +4,7 @@
# SSH host key regeneration for cloned VMs # SSH host key regeneration for cloned VMs
# Only runs once per host (marker file prevents re-running) # Only runs once per host (marker file prevents re-running)
- name: Check if SSH host keys have been regenerated - name: Check if SSH host keys have been regenerated
stat: ansible.builtin.stat:
path: /etc/ssh/.host_keys_regenerated path: /etc/ssh/.host_keys_regenerated
register: ssh_keys_marker register: ssh_keys_marker
@ -12,7 +12,7 @@
when: not ssh_keys_marker.stat.exists when: not ssh_keys_marker.stat.exists
block: block:
- name: Remove existing SSH host keys - name: Remove existing SSH host keys
file: ansible.builtin.file:
path: "{{ item }}" path: "{{ item }}"
state: absent state: absent
loop: loop:
@ -26,14 +26,14 @@
- /etc/ssh/ssh_host_dsa_key.pub - /etc/ssh/ssh_host_dsa_key.pub
- name: Regenerate SSH host keys - name: Regenerate SSH host keys
command: dpkg-reconfigure openssh-server ansible.builtin.command:
args: args:
creates: /etc/ssh/ssh_host_ed25519_key creates: /etc/ssh/ssh_host_ed25519_key
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
notify: restart ssh notify: restart ssh
- name: Regenerate SSH host keys (RHEL) - name: Regenerate SSH host keys (RHEL)
shell: | ansible.builtin.shell:
ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N '' ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N ''
ssh-keygen -t ecdsa -b 521 -f /etc/ssh/ssh_host_ecdsa_key -N '' ssh-keygen -t ecdsa -b 521 -f /etc/ssh/ssh_host_ecdsa_key -N ''
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N '' ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ''
@ -43,7 +43,7 @@
notify: restart ssh notify: restart ssh
- name: Regenerate SSH host keys (Alpine) - name: Regenerate SSH host keys (Alpine)
shell: | ansible.builtin.shell:
ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N '' ssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key -N ''
ssh-keygen -t ecdsa -b 521 -f /etc/ssh/ssh_host_ecdsa_key -N '' ssh-keygen -t ecdsa -b 521 -f /etc/ssh/ssh_host_ecdsa_key -N ''
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N '' ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ''
@ -53,13 +53,13 @@
notify: restart ssh notify: restart ssh
- name: Create marker file to prevent re-running - name: Create marker file to prevent re-running
file: ansible.builtin.file:
path: /etc/ssh/.host_keys_regenerated path: /etc/ssh/.host_keys_regenerated
state: touch state: touch
mode: '0644' mode: '0644'
- name: Install SSH banner - name: Install SSH banner
template: ansible.builtin.template:
src: issue.net.j2 src: issue.net.j2
dest: /etc/issue.net dest: /etc/issue.net
mode: '0644' mode: '0644'
@ -67,7 +67,7 @@
- ssh - ssh
- name: Configure SSH to use banner - name: Configure SSH to use banner
lineinfile: ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config path: /etc/ssh/sshd_config
regexp: '^Banner' regexp: '^Banner'
line: 'Banner /etc/issue.net' line: 'Banner /etc/issue.net'

View file

@ -1,9 +1,9 @@
--- ---
- name: restart caddy - name: restart caddy
service: ansible.builtin.service:
name: caddy name: caddy
state: restarted state: restarted
- name: update apt cache - name: update apt cache
apt: ansible.builtin.apt:
update_cache: true update_cache: true

View file

@ -1,14 +1,14 @@
--- ---
# --- Install: Debian/Ubuntu --- # --- Install: Debian/Ubuntu ---
- name: Check if Caddy is already installed - name: Check if Caddy is already installed
command: which caddy ansible.builtin.command: which caddy
register: caddy_installed register: caddy_installed
changed_when: false changed_when: false
failed_when: false failed_when: false
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
- name: Install required packages (Debian/Ubuntu) - name: Install required packages (Debian/Ubuntu)
apt: ansible.builtin.apt:
name: name:
- debian-keyring - debian-keyring
- debian-archive-keyring - debian-archive-keyring
@ -20,13 +20,13 @@
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
- name: Check for conflicting Caddy repositories - name: Check for conflicting Caddy repositories
stat: ansible.builtin.stat:
path: /usr/share/keyrings/caddy-stable-archive-keyring.gpg path: /usr/share/keyrings/caddy-stable-archive-keyring.gpg
register: old_keyring register: old_keyring
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
- name: Remove old Caddy repository files if they exist - name: Remove old Caddy repository files if they exist
file: ansible.builtin.file:
path: "{{ item }}" path: "{{ item }}"
state: absent state: absent
loop: loop:
@ -39,7 +39,7 @@
notify: update apt cache notify: update apt cache
- name: Check if Caddy GPG key exists and is valid - name: Check if Caddy GPG key exists and is valid
stat: ansible.builtin.stat:
path: /etc/apt/trusted.gpg.d/caddy-stable.asc path: /etc/apt/trusted.gpg.d/caddy-stable.asc
register: caddy_gpg_key register: caddy_gpg_key
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
@ -63,7 +63,7 @@
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
- name: Install Caddy (Debian/Ubuntu) - name: Install Caddy (Debian/Ubuntu)
apt: ansible.builtin.apt:
name: caddy name: caddy
state: present state: present
update_cache: true update_cache: true
@ -100,13 +100,13 @@
mode: '0755' mode: '0755'
- name: Ensure Caddy service is enabled and started - name: Ensure Caddy service is enabled and started
service: ansible.builtin.service:
name: caddy name: caddy
state: started state: started
enabled: true enabled: true
- name: Configure Caddy (shared template via caddy_template) - name: Configure Caddy (shared template via caddy_template)
template: ansible.builtin.template:
src: "{{ caddy_template }}" src: "{{ caddy_template }}"
dest: /etc/caddy/Caddyfile dest: /etc/caddy/Caddyfile
owner: root owner: root
@ -116,7 +116,7 @@
when: caddy_template is defined when: caddy_template is defined
- name: Check if host-specific Caddyfile template exists - name: Check if host-specific Caddyfile template exists
stat: ansible.builtin.stat:
path: "{{ playbook_dir }}/roles/caddy/templates/Caddyfile-{{ inventory_hostname }}.j2" path: "{{ playbook_dir }}/roles/caddy/templates/Caddyfile-{{ inventory_hostname }}.j2"
register: host_specific_template register: host_specific_template
delegate_to: localhost delegate_to: localhost
@ -124,7 +124,7 @@
when: caddy_template is not defined when: caddy_template is not defined
- name: Configure Caddy (host-specific template) - name: Configure Caddy (host-specific template)
template: ansible.builtin.template:
src: "Caddyfile-{{ inventory_hostname }}.j2" src: "Caddyfile-{{ inventory_hostname }}.j2"
dest: /etc/caddy/Caddyfile dest: /etc/caddy/Caddyfile
owner: root owner: root
@ -136,7 +136,7 @@
- host_specific_template.stat.exists | default(false) - host_specific_template.stat.exists | default(false)
- name: Configure Caddy (default template) - name: Configure Caddy (default template)
template: ansible.builtin.template:
src: Caddyfile.j2 src: Caddyfile.j2
dest: /etc/caddy/Caddyfile dest: /etc/caddy/Caddyfile
owner: root owner: root

View file

@ -1,10 +1,10 @@
- name: create /tmp/ansible-debug - name: create /tmp/ansible-debug
file: ansible.builtin.file:
path: /tmp/ansible-debug path: /tmp/ansible-debug
state: directory state: directory
- name: collect vars - name: collect vars
template: ansible.builtin.template:
src: templates/data.j2 src: templates/data.j2
dest: "/tmp/ansible-debug/{{ item.key }}.json" dest: "/tmp/ansible-debug/{{ item.key }}.json"
vars: vars:

View file

@ -1,3 +1,3 @@
--- ---
- name: restart dokku nginx - name: restart dokku nginx
command: dokku nginx:reload ansible.builtin.command: dokku nginx:reload

View file

@ -1,7 +1,7 @@
--- ---
# Install Docker (required by Dokku) # Install Docker (required by Dokku)
- name: Install prerequisites - name: Install prerequisites
apt: ansible.builtin.apt:
name: name:
- ca-certificates - ca-certificates
- curl - curl
@ -28,7 +28,7 @@
state: present state: present
- name: Install Docker packages - name: Install Docker packages
apt: ansible.builtin.apt:
name: name:
- docker-ce - docker-ce
- docker-ce-cli - docker-ce-cli
@ -39,7 +39,7 @@
update_cache: true update_cache: true
- name: Ensure Docker service is started and enabled - name: Ensure Docker service is started and enabled
systemd: ansible.builtin.systemd:
name: docker name: docker
state: started state: started
enabled: true enabled: true
@ -81,13 +81,13 @@
label: "{{ item.question }}" label: "{{ item.question }}"
- name: Install Dokku - name: Install Dokku
apt: ansible.builtin.apt:
name: dokku name: dokku
state: present state: present
update_cache: true update_cache: true
- name: Set Dokku global domain - name: Set Dokku global domain
command: dokku domains:set-global {{ dokku_domain }} ansible.builtin.command: dokku domains:set-global {{ dokku_domain }}
register: dokku_domain_result register: dokku_domain_result
changed_when: "'Set' in dokku_domain_result.stdout" changed_when: "'Set' in dokku_domain_result.stdout"
@ -104,13 +104,13 @@
become: false become: false
- name: Check existing Dokku SSH keys - name: Check existing Dokku SSH keys
command: dokku ssh-keys:list ansible.builtin.command: dokku ssh-keys:list
register: dokku_existing_keys register: dokku_existing_keys
changed_when: false changed_when: false
failed_when: false failed_when: false
- name: Add SSH keys to Dokku - name: Add SSH keys to Dokku
shell: | ansible.builtin.shell: |
echo '{{ item.content.split("\n") | first }}' | dokku ssh-keys:add {{ item.item.name }} echo '{{ item.content.split("\n") | first }}' | dokku ssh-keys:add {{ item.item.name }}
when: "item.item.name not in dokku_existing_keys.stdout" when: "item.item.name not in dokku_existing_keys.stdout"
loop: "{{ ssh_key_responses.results }}" loop: "{{ ssh_key_responses.results }}"
@ -119,37 +119,37 @@
# Install dokku-postgres plugin # Install dokku-postgres plugin
- name: Check if postgres plugin is installed - name: Check if postgres plugin is installed
command: dokku plugin:list ansible.builtin.command: dokku plugin:list
register: dokku_plugins register: dokku_plugins
changed_when: false changed_when: false
- name: Install dokku-postgres plugin - name: Install dokku-postgres plugin
command: dokku plugin:install {{ dokku_postgres_plugin_url }} ansible.builtin.command: dokku plugin:install {{ dokku_postgres_plugin_url }}
when: "'postgres' not in dokku_plugins.stdout" when: "'postgres' not in dokku_plugins.stdout"
- name: Install dokku-redis plugin - name: Install dokku-redis plugin
command: dokku plugin:install {{ dokku_redis_plugin_url }} ansible.builtin.command: dokku plugin:install {{ dokku_redis_plugin_url }}
when: "'redis' not in dokku_plugins.stdout" when: "'redis' not in dokku_plugins.stdout"
- name: Install dokku-letsencrypt plugin - name: Install dokku-letsencrypt plugin
command: dokku plugin:install {{ dokku_letsencrypt_plugin_url }} ansible.builtin.command: dokku plugin:install {{ dokku_letsencrypt_plugin_url }}
when: "'letsencrypt' not in dokku_plugins.stdout" when: "'letsencrypt' not in dokku_plugins.stdout"
# Create apps and postgres services # Create apps and postgres services
- name: Check existing apps - name: Check existing apps
command: dokku apps:list ansible.builtin.command: dokku apps:list
register: dokku_apps_list register: dokku_apps_list
changed_when: false changed_when: false
- name: Create Dokku apps - name: Create Dokku apps
command: "dokku apps:create {{ item.name }}" ansible.builtin.command: "dokku apps:create {{ item.name }}"
when: "item.name not in dokku_apps_list.stdout_lines" when: "item.name not in dokku_apps_list.stdout_lines"
loop: "{{ dokku_apps }}" loop: "{{ dokku_apps }}"
loop_control: loop_control:
label: "{{ item.name }}" label: "{{ item.name }}"
- name: Set app domains - name: Set app domains
shell: | ansible.builtin.shell: |
current=$(dokku domains:report {{ item.name }} --domains-app-vhosts) current=$(dokku domains:report {{ item.name }} --domains-app-vhosts)
for domain in {{ item.domains | join(' ') }}; do for domain in {{ item.domains | join(' ') }}; do
if ! echo "$current" | grep -q "$domain"; then if ! echo "$current" | grep -q "$domain"; then
@ -164,7 +164,7 @@
changed_when: "'added' in domains_result.stdout | default('')" changed_when: "'added' in domains_result.stdout | default('')"
- name: Check if app has SSL cert - name: Check if app has SSL cert
shell: "dokku certs:report {{ item.name }} --ssl-enabled 2>&1" ansible.builtin.shell: "dokku certs:report {{ item.name }} --ssl-enabled 2>&1"
loop: "{{ dokku_apps }}" loop: "{{ dokku_apps }}"
loop_control: loop_control:
label: "{{ item.name }}" label: "{{ item.name }}"
@ -173,7 +173,7 @@
failed_when: false failed_when: false
- name: Generate self-signed SSL cert for apps - name: Generate self-signed SSL cert for apps
shell: | ansible.builtin.shell: |
mkdir -p /home/dokku/{{ item.item.name }}/tls mkdir -p /home/dokku/{{ item.item.name }}/tls
openssl req -new -x509 -days 3650 -nodes \ openssl req -new -x509 -days 3650 -nodes \
-out /home/dokku/{{ item.item.name }}/tls/server.crt \ -out /home/dokku/{{ item.item.name }}/tls/server.crt \
@ -190,13 +190,13 @@
label: "{{ item.item.name }}" label: "{{ item.item.name }}"
- name: Check existing postgres services - name: Check existing postgres services
command: dokku postgres:list ansible.builtin.command: dokku postgres:list
register: dokku_postgres_list register: dokku_postgres_list
changed_when: false changed_when: false
failed_when: false failed_when: false
- name: Create postgres services with TimescaleDB - name: Create postgres services with TimescaleDB
command: > ansible.builtin.command: >
dokku postgres:create {{ item.postgres.service_name }} dokku postgres:create {{ item.postgres.service_name }}
--image {{ dokku_postgres_image }} --image {{ dokku_postgres_image }}
--image-version {{ dokku_postgres_image_version }} --image-version {{ dokku_postgres_image_version }}
@ -210,12 +210,12 @@
# Handle TimescaleDB SSL cert issue - container may get stuck restarting without certs # Handle TimescaleDB SSL cert issue - container may get stuck restarting without certs
- name: Wait for postgres services to stabilize - name: Wait for postgres services to stabilize
pause: ansible.builtin.pause:
seconds: 10 seconds: 10
when: postgres_create_result.changed | default(false) when: postgres_create_result.changed | default(false)
- name: Check postgres service status - name: Check postgres service status
command: "dokku postgres:info {{ item.postgres.service_name }}" ansible.builtin.command: "dokku postgres:info {{ item.postgres.service_name }}"
when: when:
- item.postgres is defined - item.postgres is defined
- postgres_create_result.changed | default(false) - postgres_create_result.changed | default(false)
@ -227,7 +227,7 @@
failed_when: false failed_when: false
- name: Fix TimescaleDB SSL certs if container is restarting - name: Fix TimescaleDB SSL certs if container is restarting
shell: | ansible.builtin.shell: |
CONTAINER_ID=$(docker ps -a --filter "name=dokku.postgres.{{ item.postgres.service_name }}" --format '{{"{{"}}.ID{{"}}"}}') CONTAINER_ID=$(docker ps -a --filter "name=dokku.postgres.{{ item.postgres.service_name }}" --format '{{"{{"}}.ID{{"}}"}}')
if [ -n "$CONTAINER_ID" ]; then if [ -n "$CONTAINER_ID" ]; then
DATA_DIR=$(docker inspect "$CONTAINER_ID" --format '{{"{{" }}range .Mounts{{"}}"}}{{"{{"}}if eq .Destination "/var/lib/postgresql/data"{{"}}"}}{{"{{"}} .Source {{"}}"}}{{"{{"}}end{{"}}"}}{{"{{"}}end{{"}}"}}') DATA_DIR=$(docker inspect "$CONTAINER_ID" --format '{{"{{" }}range .Mounts{{"}}"}}{{"{{"}}if eq .Destination "/var/lib/postgresql/data"{{"}}"}}{{"{{"}} .Source {{"}}"}}{{"{{"}}end{{"}}"}}{{"{{"}}end{{"}}"}}')
@ -251,7 +251,7 @@
# Enable TimescaleDB extension # Enable TimescaleDB extension
- name: Enable timescaledb extension - name: Enable timescaledb extension
shell: | ansible.builtin.shell: |
echo "CREATE EXTENSION IF NOT EXISTS timescaledb;" | dokku postgres:connect {{ item.postgres.service_name }} echo "CREATE EXTENSION IF NOT EXISTS timescaledb;" | dokku postgres:connect {{ item.postgres.service_name }}
when: when:
- item.postgres is defined - item.postgres is defined
@ -266,7 +266,7 @@
# Link postgres to apps # Link postgres to apps
- name: Check postgres links - name: Check postgres links
shell: "dokku postgres:linked {{ item.postgres.service_name }} {{ item.name }} && echo linked || echo not_linked" ansible.builtin.shell: "dokku postgres:linked {{ item.postgres.service_name }} {{ item.name }} && echo linked || echo not_linked"
when: when:
- item.postgres is defined - item.postgres is defined
loop: "{{ dokku_apps }}" loop: "{{ dokku_apps }}"
@ -277,7 +277,7 @@
failed_when: false failed_when: false
- name: Link postgres to apps - name: Link postgres to apps
command: "dokku postgres:link {{ item.item.postgres.service_name }} {{ item.item.name }}" ansible.builtin.command: "dokku postgres:link {{ item.item.postgres.service_name }} {{ item.item.name }}"
when: when:
- item.item.postgres is defined - item.item.postgres is defined
- "'not_linked' in item.stdout" - "'not_linked' in item.stdout"
@ -287,13 +287,13 @@
# Redis/Valkey services # Redis/Valkey services
- name: Check existing redis services - name: Check existing redis services
command: dokku redis:list ansible.builtin.command: dokku redis:list
register: dokku_redis_list register: dokku_redis_list
changed_when: false changed_when: false
failed_when: false failed_when: false
- name: Create redis services with Valkey - name: Create redis services with Valkey
command: > ansible.builtin.command: >
dokku redis:create {{ item.redis.service_name }} dokku redis:create {{ item.redis.service_name }}
--image {{ dokku_redis_image }} --image {{ dokku_redis_image }}
--image-version {{ dokku_redis_image_version }} --image-version {{ dokku_redis_image_version }}
@ -305,7 +305,7 @@
label: "{{ item.name }}" label: "{{ item.name }}"
- name: Check redis links - name: Check redis links
shell: "dokku redis:linked {{ item.redis.service_name }} {{ item.name }} && echo linked || echo not_linked" ansible.builtin.shell: "dokku redis:linked {{ item.redis.service_name }} {{ item.name }} && echo linked || echo not_linked"
when: when:
- item.redis is defined - item.redis is defined
loop: "{{ dokku_apps }}" loop: "{{ dokku_apps }}"
@ -316,7 +316,7 @@
failed_when: false failed_when: false
- name: Link redis to apps - name: Link redis to apps
command: "dokku redis:link {{ item.item.redis.service_name }} {{ item.item.name }}" ansible.builtin.command: "dokku redis:link {{ item.item.redis.service_name }} {{ item.item.name }}"
when: when:
- item.item.redis is defined - item.item.redis is defined
- "'not_linked' in item.stdout" - "'not_linked' in item.stdout"

View file

@ -1,4 +1,4 @@
--- ---
- name: Reload ufw - name: Reload ufw
ufw: community.general.ufw:
state: reloaded state: reloaded

View file

@ -5,20 +5,20 @@
# Per-host rules for publicly exposed services # Per-host rules for publicly exposed services
- name: Install ufw - name: Install ufw
apt: ansible.builtin.apt:
name: ufw name: ufw
state: present state: present
update_cache: true update_cache: true
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
- name: Install firewalld - name: Install firewalld
dnf: ansible.builtin.dnf:
name: firewalld name: firewalld
state: present state: present
when: ansible_os_family == "RedHat" when: ansible_os_family == "RedHat"
- name: Ensure firewalld is started and enabled - name: Ensure firewalld is started and enabled
systemd: ansible.builtin.systemd:
name: firewalld name: firewalld
state: started state: started
enabled: true enabled: true
@ -73,7 +73,7 @@
# --- UFW (Debian/Ubuntu) - Disable when firewall not managed --- # --- UFW (Debian/Ubuntu) - Disable when firewall not managed ---
- name: Disable ufw - name: Disable ufw
ufw: community.general.ufw:
state: disabled state: disabled
when: when:
- ansible_os_family == "Debian" - ansible_os_family == "Debian"
@ -84,7 +84,7 @@
# --- UFW (Debian/Ubuntu) - Configure when firewall managed --- # --- UFW (Debian/Ubuntu) - Configure when firewall managed ---
- name: Set default incoming policy to deny - name: Set default incoming policy to deny
ufw: community.general.ufw:
direction: incoming direction: incoming
policy: "{{ firewall_default_incoming }}" policy: "{{ firewall_default_incoming }}"
when: when:
@ -92,7 +92,7 @@
- firewall_enabled | default(true) - firewall_enabled | default(true)
- name: Set default outgoing policy to allow - name: Set default outgoing policy to allow
ufw: community.general.ufw:
direction: outgoing direction: outgoing
policy: "{{ firewall_default_outgoing }}" policy: "{{ firewall_default_outgoing }}"
when: when:
@ -100,7 +100,7 @@
- firewall_enabled | default(true) - firewall_enabled | default(true)
- name: Set default routed policy - name: Set default routed policy
ufw: community.general.ufw:
direction: routed direction: routed
policy: "{{ firewall_default_routed }}" policy: "{{ firewall_default_routed }}"
when: when:
@ -120,7 +120,7 @@
- "'Status: active' in _fw_ufw_active.stdout" - "'Status: active' in _fw_ufw_active.stdout"
- name: Allow all traffic from trusted subnets - name: Allow all traffic from trusted subnets
ufw: community.general.ufw:
rule: allow rule: allow
from_ip: "{{ item.subnet }}" from_ip: "{{ item.subnet }}"
comment: "{{ item.comment }}" comment: "{{ item.comment }}"
@ -131,7 +131,7 @@
- _fw_ufw_rules.skipped | default(true) or item.subnet not in _fw_ufw_rules.stdout - _fw_ufw_rules.skipped | default(true) or item.subnet not in _fw_ufw_rules.stdout
- name: Allow SSH from specific IPs - name: Allow SSH from specific IPs
ufw: community.general.ufw:
rule: allow rule: allow
port: "22" port: "22"
proto: tcp proto: tcp
@ -145,7 +145,7 @@
- _fw_ufw_rules.skipped | default(true) or item.ip not in _fw_ufw_rules.stdout - _fw_ufw_rules.skipped | default(true) or item.ip not in _fw_ufw_rules.stdout
- name: Allow per-host public services - name: Allow per-host public services
ufw: community.general.ufw:
rule: allow rule: allow
port: "{{ item.port | string }}" port: "{{ item.port | string }}"
proto: "{{ item.proto }}" proto: "{{ item.proto }}"
@ -188,7 +188,7 @@
notify: Reload ufw notify: Reload ufw
- name: Enable ufw - name: Enable ufw
ufw: community.general.ufw:
state: enabled state: enabled
when: when:
- ansible_os_family == "Debian" - ansible_os_family == "Debian"

View file

@ -1,3 +1,3 @@
--- ---
- name: Re-export NFS shares - name: Re-export NFS shares
command: exportfs -ra ansible.builtin.command: exportfs -ra

View file

@ -2,7 +2,7 @@
# K3s server configuration tasks # K3s server configuration tasks
- name: Install K3s required packages - name: Install K3s required packages
apt: ansible.builtin.apt:
name: "{{ k3s_packages }}" name: "{{ k3s_packages }}"
state: present state: present
update_cache: true update_cache: true
@ -13,7 +13,7 @@
- k3s_packages - k3s_packages
- name: Enable and start iscsid service - name: Enable and start iscsid service
systemd: ansible.builtin.systemd:
name: iscsid name: iscsid
enabled: true enabled: true
state: started state: started

View file

@ -1,4 +1,4 @@
--- ---
- name: install apt-transport-https - name: install apt-transport-https
apt: ansible.builtin.apt:
name: apt-transport-https name: apt-transport-https

View file

@ -1,15 +1,14 @@
- name: Configure MOTD banner update script - name: Configure MOTD banner update script
copy: ansible.builtin.copy:
src: etc/update-motd.d/20-banner src: etc/update-motd.d/20-banner
dest: /etc/update-motd.d/20-banner dest: /etc/update-motd.d/20-banner
owner: root owner: root
group: root group: root
mode: 0755 mode: '0755'
- name: Configure MOTD tail - name: Configure MOTD tail
template: ansible.builtin.template:
src: templates/etc/motd.j2 src: templates/etc/motd.j2
dest: /etc/motd dest: /etc/motd
owner: root owner: root
group: root group: root
mode: 0644 mode: '0644'

View file

@ -9,12 +9,12 @@
# - network_interfaces # - network_interfaces
- name: "Create systemd interface files" - name: "Create systemd interface files"
template: ansible.builtin.template:
src: templates/etc/systemd/network/link.j2 src: templates/etc/systemd/network/link.j2
dest: "/etc/systemd/network/10-{{ interface.name }}-nic.link" dest: "/etc/systemd/network/10-{{ interface.name }}-nic.link"
owner: root owner: root
group: root group: root
mode: 00644 mode: '0644'
loop: "{{ interfaces }}" loop: "{{ interfaces }}"
loop_control: loop_control:
loop_var: interface loop_var: interface
@ -26,12 +26,12 @@
when: network.skip | default(False) != True when: network.skip | default(False) != True
- name: "Build split network configuration (interfaces)" - name: "Build split network configuration (interfaces)"
template: ansible.builtin.template:
src: templates/etc/network/interfaces.d/interface.j2 src: templates/etc/network/interfaces.d/interface.j2
dest: "/etc/network/interfaces.d/{{ interface.name }}" dest: "/etc/network/interfaces.d/{{ interface.name }}"
owner: root owner: root
group: root group: root
mode: 00644 mode: '0644'
loop: "{{ interfaces }}" loop: "{{ interfaces }}"
loop_control: loop_control:
loop_var: interface loop_var: interface
@ -44,12 +44,12 @@
- network_interfaces - network_interfaces
- name: "Build split network configuration (main)" - name: "Build split network configuration (main)"
template: ansible.builtin.template:
src: templates/etc/network/interfaces.j2 src: templates/etc/network/interfaces.j2
dest: "/etc/network/interfaces" dest: "/etc/network/interfaces"
owner: root owner: root
group: root group: root
mode: 00644 mode: '0644'
vars: vars:
interfaces: "{{ [] }}" interfaces: "{{ [] }}"
register: network_interfaces_split_main register: network_interfaces_split_main
@ -58,12 +58,12 @@
- network_interfaces - network_interfaces
- name: "Build combined network configuration" - name: "Build combined network configuration"
template: ansible.builtin.template:
src: templates/etc/network/interfaces.j2 src: templates/etc/network/interfaces.j2
dest: "/etc/network/interfaces" dest: "/etc/network/interfaces"
owner: root owner: root
group: root group: root
mode: 00644 mode: '0644'
vars: vars:
interfaces: "{{ network.interfaces | default([]) }}" interfaces: "{{ network.interfaces | default([]) }}"
register: network_interfaces_single register: network_interfaces_single
@ -72,7 +72,7 @@
- network_interfaces - network_interfaces
- name: "Remove split network configuration files" - name: "Remove split network configuration files"
file: ansible.builtin.file:
path: "/etc/network/interfaces.d/{{ interface.name }}" path: "/etc/network/interfaces.d/{{ interface.name }}"
state: absent state: absent
loop: "{{ interfaces }}" loop: "{{ interfaces }}"
@ -87,29 +87,29 @@
- network_interfaces - network_interfaces
- name: "Set hostname (/etc/hosts)" - name: "Set hostname (/etc/hosts)"
template: ansible.builtin.template:
src: templates/etc/hosts.j2 src: templates/etc/hosts.j2
dest: "/etc/hosts" dest: "/etc/hosts"
owner: root owner: root
group: root group: root
mode: 00644 mode: '0644'
when: network.skip | default(False) != True when: network.skip | default(False) != True
tags: tags:
- network_hostname - network_hostname
- name: "Set hostname (/etc/hostname)" - name: "Set hostname (/etc/hostname)"
template: ansible.builtin.template:
src: templates/etc/hostname.j2 src: templates/etc/hostname.j2
dest: "/etc/hostname" dest: "/etc/hostname"
owner: root owner: root
group: root group: root
mode: 00644 mode: '0644'
when: network.skip | default(False) != True when: network.skip | default(False) != True
tags: tags:
- network_hostname - network_hostname
- name: "Restart networking" - name: "Restart networking"
systemd_service: ansible.builtin.systemd:
name: networking name: networking
daemon_reload: true daemon_reload: true
state: restarted state: restarted
@ -118,12 +118,12 @@
- network_restart - network_restart
- name: "Configure /etc/resolv.conf" - name: "Configure /etc/resolv.conf"
template: ansible.builtin.template:
src: templates/etc/resolv.conf.j2 src: templates/etc/resolv.conf.j2
dest: /etc/resolv.conf dest: /etc/resolv.conf
owner: root owner: root
group: root group: root
mode: 00644 mode: '0644'
follow: yes follow: yes
vars: vars:
domain: "{{ network.domain | default('local') }}" domain: "{{ network.domain | default('local') }}"

View file

@ -1,6 +1,6 @@
--- ---
- name: Install NFS server packages - name: Install NFS server packages
apt: ansible.builtin.apt:
name: nfs-kernel-server name: nfs-kernel-server
state: present state: present
update_cache: true update_cache: true
@ -8,7 +8,7 @@
when: nfs_exports is defined when: nfs_exports is defined
- name: Configure /etc/exports - name: Configure /etc/exports
template: ansible.builtin.template:
src: templates/etc/exports.j2 src: templates/etc/exports.j2
dest: /etc/exports dest: /etc/exports
owner: root owner: root
@ -18,7 +18,7 @@
notify: Re-export NFS shares notify: Re-export NFS shares
- name: Enable and start nfs-server - name: Enable and start nfs-server
systemd: ansible.builtin.systemd:
name: nfs-server name: nfs-server
enabled: true enabled: true
state: started state: started

View file

@ -1,40 +1,44 @@
--- ---
# General role - system-wide configurations - name: Install misc Debian packages
ansible.builtin.import_tasks: debian/misc.yml
# Import Debian-specific tasks
- import_tasks: debian/misc.yml
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
tags: tags:
- misc - misc
- import_tasks: debian/motd.yml - name: Configure MOTD
ansible.builtin.import_tasks: debian/motd.yml
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
tags: tags:
- motd - motd
- import_tasks: debian/network.yml - name: Configure networking
ansible.builtin.import_tasks: debian/network.yml
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
tags: tags:
- network - network
- import_tasks: udp-gro-fix.yml - name: Apply UDP GRO fix for Tailscale
ansible.builtin.import_tasks: udp-gro-fix.yml
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
tags: tags:
- network - network
- tailscale - tailscale
- import_tasks: debian/k3s.yml - name: Install K3s packages
ansible.builtin.import_tasks: debian/k3s.yml
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
tags: tags:
- k3s - k3s
- import_tasks: debian/icinga2.yml - name: Uninstall Icinga2 on non-monitor hosts
ansible.builtin.import_tasks: debian/icinga2.yml
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
tags: tags:
- icinga2 - icinga2
- monitoring - monitoring
- import_tasks: debian/nfs.yml - name: Configure NFS mounts
ansible.builtin.import_tasks: debian/nfs.yml
when: ansible_os_family == "Debian" when: ansible_os_family == "Debian"
tags: tags:
- nfs - nfs

View file

@ -3,7 +3,7 @@
# See https://tailscale.com/s/ethtool-config-udp-gro # See https://tailscale.com/s/ethtool-config-udp-gro
- name: Check if ethtool is installed - name: Check if ethtool is installed
package: ansible.builtin.package:
name: ethtool name: ethtool
state: present state: present
tags: tags:
@ -11,7 +11,9 @@
- tailscale - tailscale
- name: Get list of bridge interfaces - name: Get list of bridge interfaces
shell: "ip link show type bridge | grep -E '^[0-9]+:' | cut -d: -f2 | tr -d ' '" ansible.builtin.shell:
cmd: "set -o pipefail; ip link show type bridge | grep -E '^[0-9]+:' | cut -d: -f2 | tr -d ' '"
executable: /bin/bash
register: bridge_interfaces register: bridge_interfaces
changed_when: false changed_when: false
failed_when: false failed_when: false
@ -20,7 +22,7 @@
- tailscale - tailscale
- name: Disable UDP GRO on bridge interfaces - name: Disable UDP GRO on bridge interfaces
command: "ethtool -K {{ item }} rx-udp-gro-forwarding off rx-gro-list off" ansible.builtin.command: "ethtool -K {{ item }} rx-udp-gro-forwarding off rx-gro-list off"
loop: "{{ bridge_interfaces.stdout_lines }}" loop: "{{ bridge_interfaces.stdout_lines }}"
when: bridge_interfaces.stdout_lines is defined and bridge_interfaces.stdout_lines | length > 0 when: bridge_interfaces.stdout_lines is defined and bridge_interfaces.stdout_lines | length > 0
failed_when: false failed_when: false
@ -30,7 +32,7 @@
- tailscale - tailscale
- name: Create systemd service to persist UDP GRO settings - name: Create systemd service to persist UDP GRO settings
copy: ansible.builtin.copy:
dest: /etc/systemd/system/disable-udp-gro@.service dest: /etc/systemd/system/disable-udp-gro@.service
content: | content: |
[Unit] [Unit]
@ -52,7 +54,7 @@
- tailscale - tailscale
- name: Enable systemd service for each bridge interface - name: Enable systemd service for each bridge interface
systemd: ansible.builtin.systemd:
name: "disable-udp-gro@{{ item }}.service" name: "disable-udp-gro@{{ item }}.service"
enabled: true enabled: true
daemon_reload: true daemon_reload: true

View file

@ -1,29 +1,29 @@
--- ---
- name: restart php-fpm - name: restart php-fpm
service: ansible.builtin.service:
name: "php{{ librenms_php_version }}-fpm" name: "php{{ librenms_php_version }}-fpm"
state: restarted state: restarted
- name: restart caddy - name: restart caddy
service: ansible.builtin.service:
name: caddy name: caddy
state: restarted state: restarted
- name: restart snmpd - name: restart snmpd
service: ansible.builtin.service:
name: snmpd name: snmpd
state: restarted state: restarted
- name: restart postfix - name: restart postfix
service: ansible.builtin.service:
name: postfix name: postfix
state: restarted state: restarted
- name: reload systemd - name: reload systemd
systemd: ansible.builtin.systemd:
daemon_reload: true daemon_reload: true
- name: restart librenms-scheduler - name: restart librenms-scheduler
systemd: ansible.builtin.systemd:
name: librenms-scheduler.timer name: librenms-scheduler.timer
state: restarted state: restarted

View file

@ -20,7 +20,7 @@
state: present state: present
- name: Install required packages - name: Install required packages
apt: ansible.builtin.apt:
name: name:
- acl - acl
- curl - curl
@ -55,13 +55,13 @@
update_cache: true update_cache: true
- name: Create librenms group - name: Create librenms group
group: ansible.builtin.group:
name: "{{ librenms_group }}" name: "{{ librenms_group }}"
system: true system: true
state: present state: present
- name: Create librenms user - name: Create librenms user
user: ansible.builtin.user:
name: "{{ librenms_user }}" name: "{{ librenms_user }}"
group: "{{ librenms_group }}" group: "{{ librenms_group }}"
home: "{{ librenms_path }}" home: "{{ librenms_path }}"
@ -71,21 +71,22 @@
state: present state: present
- name: Check if LibreNMS is already installed - name: Check if LibreNMS is already installed
stat: ansible.builtin.stat:
path: "{{ librenms_path }}/lnms" path: "{{ librenms_path }}/lnms"
register: librenms_installed register: librenms_installed
- name: Clone LibreNMS repository - name: Clone LibreNMS repository
git: ansible.builtin.git:
repo: https://github.com/librenms/librenms.git repo: https://github.com/librenms/librenms.git
dest: "{{ librenms_path }}" dest: "{{ librenms_path }}"
version: master version: master
depth: 1 depth: 1
become: true
become_user: "{{ librenms_user }}" become_user: "{{ librenms_user }}"
when: not librenms_installed.stat.exists when: not librenms_installed.stat.exists
- name: Set LibreNMS directory ownership - name: Set LibreNMS directory ownership
file: ansible.builtin.file:
path: "{{ librenms_path }}" path: "{{ librenms_path }}"
owner: "{{ librenms_user }}" owner: "{{ librenms_user }}"
group: "{{ librenms_group }}" group: "{{ librenms_group }}"
@ -93,13 +94,13 @@
changed_when: false changed_when: false
- name: Set LibreNMS directory permissions - name: Set LibreNMS directory permissions
file: ansible.builtin.file:
path: "{{ librenms_path }}" path: "{{ librenms_path }}"
mode: '0771' mode: '0771'
state: directory state: directory
- name: Ensure writable directories exist - name: Ensure writable directories exist
file: ansible.builtin.file:
path: "{{ librenms_path }}/{{ item }}" path: "{{ librenms_path }}/{{ item }}"
owner: "{{ librenms_user }}" owner: "{{ librenms_user }}"
group: "{{ librenms_group }}" group: "{{ librenms_group }}"
@ -112,7 +113,7 @@
- bootstrap/cache - bootstrap/cache
- name: Set ACLs for LibreNMS directories - name: Set ACLs for LibreNMS directories
acl: ansible.posix.acl:
path: "{{ librenms_path }}/{{ item }}" path: "{{ librenms_path }}/{{ item }}"
entry: "default:group::rwx" entry: "default:group::rwx"
state: present state: present
@ -123,7 +124,7 @@
- bootstrap/cache - bootstrap/cache
- name: Deploy LibreNMS .env file - name: Deploy LibreNMS .env file
template: ansible.builtin.template:
src: env.j2 src: env.j2
dest: "{{ librenms_path }}/.env" dest: "{{ librenms_path }}/.env"
owner: "{{ librenms_user }}" owner: "{{ librenms_user }}"
@ -131,7 +132,7 @@
mode: '0640' mode: '0640'
- name: Configure PHP-FPM pool for LibreNMS - name: Configure PHP-FPM pool for LibreNMS
template: ansible.builtin.template:
src: php-fpm-librenms.conf.j2 src: php-fpm-librenms.conf.j2
dest: "/etc/php/{{ librenms_php_version }}/fpm/pool.d/librenms.conf" dest: "/etc/php/{{ librenms_php_version }}/fpm/pool.d/librenms.conf"
owner: root owner: root
@ -140,14 +141,14 @@
notify: restart php-fpm notify: restart php-fpm
- name: Set PHP memory_limit - name: Set PHP memory_limit
lineinfile: ansible.builtin.lineinfile:
path: "/etc/php/{{ librenms_php_version }}/fpm/php.ini" path: "/etc/php/{{ librenms_php_version }}/fpm/php.ini"
regexp: '^memory_limit\s*=' regexp: '^memory_limit\s*='
line: 'memory_limit = 512M' line: 'memory_limit = 512M'
notify: restart php-fpm notify: restart php-fpm
- name: Configure Caddy for LibreNMS - name: Configure Caddy for LibreNMS
template: ansible.builtin.template:
src: Caddyfile.j2 src: Caddyfile.j2
dest: /etc/caddy/Caddyfile dest: /etc/caddy/Caddyfile
owner: root owner: root
@ -156,7 +157,7 @@
notify: restart caddy notify: restart caddy
- name: Deploy LibreNMS cron jobs - name: Deploy LibreNMS cron jobs
template: ansible.builtin.template:
src: cron-librenms.j2 src: cron-librenms.j2
dest: /etc/cron.d/librenms dest: /etc/cron.d/librenms
owner: root owner: root
@ -164,7 +165,7 @@
mode: '0644' mode: '0644'
- name: Deploy LibreNMS scheduler service - name: Deploy LibreNMS scheduler service
template: ansible.builtin.template:
src: librenms-scheduler.service.j2 src: librenms-scheduler.service.j2
dest: /etc/systemd/system/librenms-scheduler.service dest: /etc/systemd/system/librenms-scheduler.service
owner: root owner: root
@ -173,7 +174,7 @@
notify: reload systemd notify: reload systemd
- name: Deploy LibreNMS scheduler timer - name: Deploy LibreNMS scheduler timer
template: ansible.builtin.template:
src: librenms-scheduler.timer.j2 src: librenms-scheduler.timer.j2
dest: /etc/systemd/system/librenms-scheduler.timer dest: /etc/systemd/system/librenms-scheduler.timer
owner: root owner: root
@ -184,13 +185,13 @@
- restart librenms-scheduler - restart librenms-scheduler
- name: Enable and start LibreNMS scheduler timer - name: Enable and start LibreNMS scheduler timer
systemd: ansible.builtin.systemd:
name: librenms-scheduler.timer name: librenms-scheduler.timer
state: started state: started
enabled: true enabled: true
- name: Configure SNMPD - name: Configure SNMPD
template: ansible.builtin.template:
src: snmpd.conf.j2 src: snmpd.conf.j2
dest: /etc/snmp/snmpd.conf dest: /etc/snmp/snmpd.conf
owner: root owner: root
@ -199,7 +200,7 @@
notify: restart snmpd notify: restart snmpd
- name: Configure Postfix for local-only delivery - name: Configure Postfix for local-only delivery
lineinfile: ansible.builtin.lineinfile:
path: /etc/postfix/main.cf path: /etc/postfix/main.cf
regexp: "{{ item.regexp }}" regexp: "{{ item.regexp }}"
line: "{{ item.line }}" line: "{{ item.line }}"
@ -211,31 +212,31 @@
notify: restart postfix notify: restart postfix
- name: Ensure MariaDB is running - name: Ensure MariaDB is running
service: ansible.builtin.service:
name: mariadb name: mariadb
state: started state: started
enabled: true enabled: true
- name: Ensure Caddy is running - name: Ensure Caddy is running
service: ansible.builtin.service:
name: caddy name: caddy
state: started state: started
enabled: true enabled: true
- name: Ensure PHP-FPM is running - name: Ensure PHP-FPM is running
service: ansible.builtin.service:
name: "php{{ librenms_php_version }}-fpm" name: "php{{ librenms_php_version }}-fpm"
state: started state: started
enabled: true enabled: true
- name: Ensure SNMPD is running - name: Ensure SNMPD is running
service: ansible.builtin.service:
name: snmpd name: snmpd
state: started state: started
enabled: true enabled: true
- name: Ensure Postfix is running - name: Ensure Postfix is running
service: ansible.builtin.service:
name: postfix name: postfix
state: started state: started
enabled: true enabled: true

View file

@ -2,14 +2,14 @@
# Handlers for Mailcow # Handlers for Mailcow
- name: restart mailcow - name: restart mailcow
systemd: ansible.builtin.systemd:
name: mailcow name: mailcow
state: restarted state: restarted
daemon_reload: true daemon_reload: true
become: true become: true
- name: reload mailcow - name: reload mailcow
command: docker compose restart ansible.builtin.command: docker compose restart
args: args:
chdir: "{{ mailcow_base_path }}" chdir: "{{ mailcow_base_path }}"

View file

@ -2,7 +2,7 @@
# Install and configure Mailcow # Install and configure Mailcow
- name: Install required packages - name: Install required packages
apt: ansible.builtin.apt:
name: name:
- git - git
- curl - curl
@ -15,13 +15,13 @@
update_cache: true update_cache: true
- name: Ensure docker service is running - name: Ensure docker service is running
systemd: ansible.builtin.systemd:
name: docker name: docker
state: started state: started
enabled: true enabled: true
- name: Create mailcow user - name: Create mailcow user
user: ansible.builtin.user:
name: mailcow name: mailcow
groups: docker groups: docker
shell: /bin/bash shell: /bin/bash
@ -30,7 +30,7 @@
state: present state: present
- name: Ensure mailcow base directory exists - name: Ensure mailcow base directory exists
file: ansible.builtin.file:
path: "{{ mailcow_base_path }}" path: "{{ mailcow_base_path }}"
state: directory state: directory
owner: mailcow owner: mailcow
@ -38,12 +38,12 @@
mode: '0755' mode: '0755'
- name: Check if Mailcow repository exists - name: Check if Mailcow repository exists
stat: ansible.builtin.stat:
path: "{{ mailcow_base_path }}/.git" path: "{{ mailcow_base_path }}/.git"
register: mailcow_repo register: mailcow_repo
- name: Remove non-git Mailcow directory - name: Remove non-git Mailcow directory
file: ansible.builtin.file:
path: "{{ mailcow_base_path }}" path: "{{ mailcow_base_path }}"
state: absent state: absent
when: when:
@ -51,7 +51,7 @@
- not mailcow_repo.stat.exists - not mailcow_repo.stat.exists
- name: Clone Mailcow repository - name: Clone Mailcow repository
git: ansible.builtin.git:
repo: "{{ mailcow_git_repo }}" repo: "{{ mailcow_git_repo }}"
dest: "{{ mailcow_base_path }}" dest: "{{ mailcow_base_path }}"
version: "{{ mailcow_git_branch }}" version: "{{ mailcow_git_branch }}"
@ -71,7 +71,7 @@
when: mailcow_repo.stat.exists when: mailcow_repo.stat.exists
- name: Update Mailcow repository - name: Update Mailcow repository
git: ansible.builtin.git:
repo: "{{ mailcow_git_repo }}" repo: "{{ mailcow_git_repo }}"
dest: "{{ mailcow_base_path }}" dest: "{{ mailcow_base_path }}"
version: "{{ mailcow_git_branch }}" version: "{{ mailcow_git_branch }}"
@ -83,7 +83,7 @@
- "'Local modifications exist' not in git_update_result.msg | default('')" - "'Local modifications exist' not in git_update_result.msg | default('')"
- name: Change ownership of Mailcow directory - name: Change ownership of Mailcow directory
file: ansible.builtin.file:
path: "{{ mailcow_base_path }}" path: "{{ mailcow_base_path }}"
owner: mailcow owner: mailcow
group: mailcow group: mailcow
@ -92,7 +92,7 @@
# Let generate_config.sh create the default configuration # Let generate_config.sh create the default configuration
- name: Create docker-compose override file - name: Create docker-compose override file
template: ansible.builtin.template:
src: docker-compose.override.yml.j2 src: docker-compose.override.yml.j2
dest: "{{ mailcow_base_path }}/docker-compose.override.yml" dest: "{{ mailcow_base_path }}/docker-compose.override.yml"
owner: mailcow owner: mailcow
@ -102,19 +102,19 @@
notify: restart mailcow notify: restart mailcow
- name: Make generate_config.sh executable - name: Make generate_config.sh executable
file: ansible.builtin.file:
path: "{{ mailcow_base_path }}/generate_config.sh" path: "{{ mailcow_base_path }}/generate_config.sh"
mode: '0755' mode: '0755'
owner: mailcow owner: mailcow
group: mailcow group: mailcow
- name: Check if mailcow is already configured - name: Check if mailcow is already configured
stat: ansible.builtin.stat:
path: "{{ mailcow_base_path }}/mailcow.conf" path: "{{ mailcow_base_path }}/mailcow.conf"
register: mailcow_configured register: mailcow_configured
- name: Remove incomplete mailcow.conf - name: Remove incomplete mailcow.conf
file: ansible.builtin.file:
path: "{{ mailcow_base_path }}/mailcow.conf" path: "{{ mailcow_base_path }}/mailcow.conf"
state: absent state: absent
when: when:
@ -122,7 +122,7 @@
- mailcow_configured.stat.size < 1000 # If config is too small, it's incomplete - mailcow_configured.stat.size < 1000 # If config is too small, it's incomplete
- name: Run generate_config.sh script - name: Run generate_config.sh script
shell: | ansible.builtin.shell: |
cd {{ mailcow_base_path }} cd {{ mailcow_base_path }}
./generate_config.sh << EOF ./generate_config.sh << EOF
{{ mailcow_hostname }} {{ mailcow_hostname }}
@ -132,7 +132,7 @@
creates: "{{ mailcow_base_path }}/mailcow.conf" creates: "{{ mailcow_base_path }}/mailcow.conf"
- name: Update mailcow.conf with secure passwords - name: Update mailcow.conf with secure passwords
lineinfile: ansible.builtin.lineinfile:
path: "{{ mailcow_base_path }}/mailcow.conf" path: "{{ mailcow_base_path }}/mailcow.conf"
regexp: "^{{ item.key }}=" regexp: "^{{ item.key }}="
line: "{{ item.key }}={{ item.value }}" line: "{{ item.key }}={{ item.value }}"
@ -145,38 +145,38 @@
no_log: true no_log: true
- name: Stop any running Mailcow containers - name: Stop any running Mailcow containers
command: docker compose down ansible.builtin.command: docker compose down
args: args:
chdir: "{{ mailcow_base_path }}" chdir: "{{ mailcow_base_path }}"
failed_when: false failed_when: false
changed_when: false changed_when: false
- name: Prune unused Docker networks - name: Prune unused Docker networks
command: docker network prune -f ansible.builtin.command: docker network prune -f
changed_when: true changed_when: true
- name: Pull docker images - name: Pull docker images
command: docker compose pull ansible.builtin.command: docker compose pull
args: args:
chdir: "{{ mailcow_base_path }}" chdir: "{{ mailcow_base_path }}"
register: mailcow_pull_result register: mailcow_pull_result
changed_when: "'Pulling' in mailcow_pull_result.stdout or 'Downloaded' in mailcow_pull_result.stderr" changed_when: "'Pulling' in mailcow_pull_result.stdout or 'Downloaded' in mailcow_pull_result.stderr"
- name: Start Mailcow services - name: Start Mailcow services
command: docker compose up -d ansible.builtin.command: docker compose up -d
args: args:
chdir: "{{ mailcow_base_path }}" chdir: "{{ mailcow_base_path }}"
register: mailcow_up_result register: mailcow_up_result
changed_when: "'Created' in mailcow_up_result.stdout or 'Starting' in mailcow_up_result.stdout" changed_when: "'Created' in mailcow_up_result.stdout or 'Starting' in mailcow_up_result.stdout"
- name: Check if ufw is installed - name: Check if ufw is installed
command: which ufw ansible.builtin.command: which ufw
register: ufw_check register: ufw_check
changed_when: false changed_when: false
failed_when: false failed_when: false
- name: Configure firewall for mail services - name: Configure firewall for mail services
ufw: community.general.ufw:
rule: allow rule: allow
port: "{{ item.port }}" port: "{{ item.port }}"
proto: "{{ item.proto }}" proto: "{{ item.proto }}"
@ -195,7 +195,7 @@
- ufw_check.rc == 0 - ufw_check.rc == 0
- name: Create systemd service for Mailcow - name: Create systemd service for Mailcow
template: ansible.builtin.template:
src: mailcow.service.j2 src: mailcow.service.j2
dest: /etc/systemd/system/mailcow.service dest: /etc/systemd/system/mailcow.service
owner: root owner: root
@ -204,7 +204,7 @@
notify: restart mailcow notify: restart mailcow
- name: Enable Mailcow service - name: Enable Mailcow service
systemd: ansible.builtin.systemd:
name: mailcow name: mailcow
enabled: true enabled: true
daemon_reload: true daemon_reload: true

View file

@ -25,19 +25,19 @@
- name: Add Icinga apt signing key - name: Add Icinga apt signing key
block: block:
- name: Download Icinga signing key (ASCII-armored) - name: Download Icinga signing key (ASCII-armored)
ansible.builtin.get_url: get_url:
url: "{{ icinga2_apt_key_url }}" url: "{{ icinga2_apt_key_url }}"
dest: /tmp/icinga-key.asc dest: /tmp/icinga-key.asc
mode: "0644" mode: "0644"
force: false force: false
- name: Convert key to binary format for apt - name: Convert key to binary format for apt
ansible.builtin.shell: shell:
cmd: gpg --dearmor --yes -o "{{ icinga2_apt_keyring }}" /tmp/icinga-key.asc cmd: gpg --dearmor --yes -o "{{ icinga2_apt_keyring }}" /tmp/icinga-key.asc
creates: "{{ icinga2_apt_keyring }}" creates: "{{ icinga2_apt_keyring }}"
- name: Set keyring permissions - name: Set keyring permissions
ansible.builtin.file: file:
path: "{{ icinga2_apt_keyring }}" path: "{{ icinga2_apt_keyring }}"
mode: "0644" mode: "0644"
@ -76,19 +76,19 @@
- name: Add PagerDuty apt signing key - name: Add PagerDuty apt signing key
block: block:
- name: Download PagerDuty signing key (ASCII-armored) - name: Download PagerDuty signing key (ASCII-armored)
ansible.builtin.get_url: get_url:
url: "{{ pdagent_apt_key_url }}" url: "{{ pdagent_apt_key_url }}"
dest: /tmp/pdagent-key.asc dest: /tmp/pdagent-key.asc
mode: "0644" mode: "0644"
force: false force: false
- name: Convert key to binary format for apt - name: Convert key to binary format for apt
ansible.builtin.shell: shell:
cmd: gpg --dearmor --yes -o "{{ pdagent_apt_keyring }}" /tmp/pdagent-key.asc cmd: gpg --dearmor --yes -o "{{ pdagent_apt_keyring }}" /tmp/pdagent-key.asc
creates: "{{ pdagent_apt_keyring }}" creates: "{{ pdagent_apt_keyring }}"
- name: Set keyring permissions - name: Set keyring permissions
ansible.builtin.file: file:
path: "{{ pdagent_apt_keyring }}" path: "{{ pdagent_apt_keyring }}"
mode: "0644" mode: "0644"
@ -113,7 +113,7 @@
- name: Ensure PHP MySQL extension matches Apache PHP version - name: Ensure PHP MySQL extension matches Apache PHP version
block: block:
- name: Find Apache PHP version - name: Find Apache PHP version
ansible.builtin.shell: shell:
cmd: a2query -m 2>/dev/null | grep -oP 'php\d+\.\d+' | head -1 cmd: a2query -m 2>/dev/null | grep -oP 'php\d+\.\d+' | head -1
executable: /bin/bash executable: /bin/bash
register: apache_php_version register: apache_php_version
@ -121,7 +121,7 @@
check_mode: false check_mode: false
- name: Install MySQL module for Apache PHP - name: Install MySQL module for Apache PHP
ansible.builtin.apt: apt:
name: "{{ apache_php_version.stdout }}-mysql" name: "{{ apache_php_version.stdout }}-mysql"
state: present state: present
when: apache_php_version.stdout | length > 0 when: apache_php_version.stdout | length > 0

View file

@ -73,7 +73,7 @@
register: pq_sshd_dropin register: pq_sshd_dropin
- name: Validate sshd configuration - name: Validate sshd configuration
ansible.builtin.command: sshd -t ansible.builtin.command:
changed_when: false changed_when: false
- name: Restart sshd to apply key-exchange change - name: Restart sshd to apply key-exchange change

View file

@ -1,6 +1,6 @@
--- ---
- name: restart syncthing - name: restart syncthing
systemd: ansible.builtin.systemd:
name: syncthing@graham name: syncthing@graham
state: restarted state: restarted
daemon_reload: true daemon_reload: true

View file

@ -2,7 +2,7 @@
# Install and configure Syncthing # Install and configure Syncthing
- name: Install required packages - name: Install required packages
apt: ansible.builtin.apt:
name: name:
- apt-transport-https - apt-transport-https
- curl - curl
@ -27,18 +27,18 @@
state: present state: present
- name: Install Syncthing - name: Install Syncthing
apt: ansible.builtin.apt:
name: syncthing name: syncthing
state: present state: present
update_cache: true update_cache: true
- name: Ensure graham user exists - name: Ensure graham user exists
user: ansible.builtin.user:
name: graham name: graham
state: present state: present
- name: Create Syncthing configuration directory - name: Create Syncthing configuration directory
file: ansible.builtin.file:
path: /home/graham/.config/syncthing path: /home/graham/.config/syncthing
state: directory state: directory
owner: graham owner: graham
@ -46,7 +46,7 @@
mode: '0755' mode: '0755'
- name: Deploy Syncthing configuration - name: Deploy Syncthing configuration
template: ansible.builtin.template:
src: config.xml.j2 src: config.xml.j2
dest: /home/graham/.config/syncthing/config.xml dest: /home/graham/.config/syncthing/config.xml
owner: graham owner: graham
@ -56,7 +56,7 @@
notify: restart syncthing notify: restart syncthing
- name: Create Syncthing systemd service - name: Create Syncthing systemd service
copy: ansible.builtin.copy:
content: | content: |
[Unit] [Unit]
Description=Syncthing - Open Source Continuous File Synchronization Description=Syncthing - Open Source Continuous File Synchronization
@ -86,27 +86,27 @@
notify: restart syncthing notify: restart syncthing
- name: Stop old syncthing service if exists - name: Stop old syncthing service if exists
systemd: ansible.builtin.systemd:
name: syncthing@syncthing name: syncthing@syncthing
state: stopped state: stopped
enabled: false enabled: false
failed_when: false failed_when: false
- name: Enable and start Syncthing service - name: Enable and start Syncthing service
systemd: ansible.builtin.systemd:
name: syncthing@graham name: syncthing@graham
enabled: true enabled: true
state: started state: started
daemon_reload: true daemon_reload: true
- name: Check if ufw is installed - name: Check if ufw is installed
command: which ufw ansible.builtin.command: which ufw
register: ufw_check register: ufw_check
changed_when: false changed_when: false
failed_when: false failed_when: false
- name: Configure firewall for Syncthing web UI - name: Configure firewall for Syncthing web UI
ufw: community.general.ufw:
rule: allow rule: allow
port: '8384' port: '8384'
proto: tcp proto: tcp
@ -116,7 +116,7 @@
- ufw_check.rc == 0 - ufw_check.rc == 0
- name: Configure firewall for Syncthing sync protocol - name: Configure firewall for Syncthing sync protocol
ufw: community.general.ufw:
rule: allow rule: allow
port: '22000' port: '22000'
proto: tcp proto: tcp
@ -126,7 +126,7 @@
- ufw_check.rc == 0 - ufw_check.rc == 0
- name: Configure firewall for Syncthing discovery - name: Configure firewall for Syncthing discovery
ufw: community.general.ufw:
rule: allow rule: allow
port: '21027' port: '21027'
proto: udp proto: udp