Add nginx_prune_sites to remove sites dropped from nginx_sites

This commit is contained in:
2026-07-08 13:00:46 -04:00
parent 72b96c06a4
commit 5aaf1fd9bf
3 changed files with 55 additions and 5 deletions
+8 -5
View File
@@ -9,8 +9,7 @@ shared shape, so each new service is a few lines of YAML instead of a copy-paste
server block.
**Not for production.** No Let's Encrypt automation, no per-vhost cert provisioning,
no cleanup for sites removed from inventory, snakeoil cert as default. Override what
you need.
snakeoil cert as default. Override what you need.
Tested on Debian (bookworm/trixie) and Ubuntu (jammy/noble).
@@ -78,6 +77,7 @@ uses the shared cert, and proxies everything to `192.168.1.10:8080`.
| `nginx_resolver_timeout` | `5s` | |
| `nginx_site_enabled_by_default` | `true` | Whether sites without an explicit `enabled` get symlinked. |
| `nginx_delete_default_site_config` | `false` | Delete Debian's `sites-available/default` (only matters if you remove the `default` entry from `nginx_sites`). |
| `nginx_prune_sites` | `false` | Remove any file in `sites-available/` or `sites-enabled/` whose basename isn't in `nginx_sites`. Off by default so hand-placed configs survive. |
| `nginx_site_config_template` | `nginx-site.conf.j2` | Default template used when a site has no `template_path`/`conf_file`.|
| `nginx_sites` | one entry (the catch-all `default` site) | Your list of sites. |
| `nginx_snippets` | `[proxy-headers, ssl-params, websockets, fastcgi-php]` | Static snippets dropped into `/etc/nginx/snippets/`. |
@@ -125,9 +125,12 @@ The role copies it verbatim into `sites-available/`.
- **One shared cert by default.** A single wildcard is the assumed homelab pattern.
Per-site override via `ssl_certificate` / `ssl_certificate_key` works for the
exceptions.
- **No removal cleanup.** If you delete a site from `nginx_sites`, the existing
`sites-available/<name>` and `sites-enabled/<name>` are not removed. Clean up
manually or set `enabled: false` and let the symlink task remove the link.
- **No removal cleanup by default.** If you delete a site from `nginx_sites`, the
existing `sites-available/<name>` and `sites-enabled/<name>` are left in place.
Set `nginx_prune_sites: true` to have the role remove any file in those
directories whose basename isn't in `nginx_sites` — but note this will also
wipe hand-placed configs the role didn't create (including
`sites-available/default` unless you keep the `default` entry in `nginx_sites`).
- **Debian/Ubuntu only.** Paths assume the Debian-style `sites-available/` +
`sites-enabled/` split. Won't work on Alpine, RHEL, etc. without surgery.
- **No Let's Encrypt / ACME.** Bring your own certs.
+5
View File
@@ -10,6 +10,11 @@ nginx_conf_d_path: /etc/nginx/conf.d
nginx_delete_default_site_config: false
nginx_site_config_extra_options: ""
# When true, any file in nginx_site_config_path or nginx_site_enabled_path
# whose basename is not listed in nginx_sites will be removed. Off by
# default so hand-placed configs aren't wiped by a role run.
nginx_prune_sites: false
# Default SSL cert used by all sites unless overridden per-site
# via item.ssl_certificate / item.ssl_certificate_key. Points at the
# Debian snakeoil cert (shipped by the ssl-cert package, an nginx dep)
+42
View File
@@ -8,6 +8,48 @@
- Validate nginx configuration
- Reload nginx
- name: Find existing site configs
ansible.builtin.find:
paths: "{{ nginx_site_config_path }}"
file_type: file
register: nginx_existing_site_configs
when: nginx_prune_sites
- name: Remove site configs no longer in nginx_sites
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ nginx_existing_site_configs.files | default([]) }}"
loop_control:
label: "{{ item.path | basename }}"
when:
- nginx_prune_sites
- (item.path | basename) not in (nginx_sites | map(attribute='name') | list)
notify:
- Validate nginx configuration
- Reload nginx
- name: Find existing enabled-site symlinks
ansible.builtin.find:
paths: "{{ nginx_site_enabled_path }}"
file_type: any
register: nginx_existing_enabled_sites
when: nginx_prune_sites
- name: Remove enabled-site symlinks no longer in nginx_sites
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ nginx_existing_enabled_sites.files | default([]) }}"
loop_control:
label: "{{ item.path | basename }}"
when:
- nginx_prune_sites
- (item.path | basename) not in (nginx_sites | map(attribute='name') | list)
notify:
- Validate nginx configuration
- Reload nginx
- name: Add all the template site configurations
ansible.builtin.template:
src: "{{ item.template_path | default(nginx_site_config_template) }}"