feat(ensure_apache): synchronize website content from local temp staging
Replace remote git checkouts on target web nodes with an orchestrated
local staging and rsync deployment pipeline.
Recent OpenSSH updates in Fedora dropped agent forwarding into remote
sessions, breaking remote git fetch operations. Furthermore, pulling
directly from Git on production servers exposed .git repositories in
public webroots and required target servers to hold Git credentials.
- Create an ephemeral, unguessable local staging directory (0700) on
localhost via ansible.builtin.tempfile scoped by inventory_hostname.
- Stage checkouts using repo hash prefixes to prevent collision when
public and private servers share identical FQDNs.
- Execute shallow checkouts (depth: 1) on the control node using local
credentials.
- Push website content to /srv/http/{fqdn}/ via ansible.posix.synchronize
with checksum delta comparisons and automated cleanup (--delete).
- Introduce ensure_apache_rsync_excludes in role defaults to strip
.git*, .env*, CI/CD pipelines (.gitea, .github), editor swap files,
and OS metadata while preserving .htaccess and /.well-known/.
- Enforce httpd_sys_content_t SELinux context recursively across webroots.
- Guarantee staging directory cleanup on localhost via an always block.
This commit is contained in:
@@ -2,3 +2,15 @@
|
|||||||
# defaults file for ensure_apache
|
# defaults file for ensure_apache
|
||||||
lets_encrypt_admin: root@example.com
|
lets_encrypt_admin: root@example.com
|
||||||
lets_encrypt_url: https://acme-v02.api.letsencrypt.org/directory
|
lets_encrypt_url: https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
ensure_apache_rsync_excludes:
|
||||||
|
- --exclude=*.bak
|
||||||
|
- --exclude=*.swo
|
||||||
|
- --exclude=*.swp
|
||||||
|
- --exclude=*~
|
||||||
|
- --exclude=.DS_Store
|
||||||
|
- --exclude=.env*
|
||||||
|
- --exclude=.git*
|
||||||
|
- --exclude=.gitea
|
||||||
|
- --exclude=.github
|
||||||
|
- --exclude=.gitlab-ci.yml
|
||||||
|
- --exclude=Thumbs.db
|
||||||
|
|||||||
@@ -187,25 +187,80 @@
|
|||||||
- Ensure_Apache.Service_Facts
|
- Ensure_Apache.Service_Facts
|
||||||
- Ensure_Apache.Service_Reload
|
- Ensure_Apache.Service_Reload
|
||||||
- Ensure_Apache.Service_Reload_Config
|
- Ensure_Apache.Service_Reload_Config
|
||||||
- name: Ensure Website Content From Git Repos
|
- name: Synchronize Website Content From Git Repositories
|
||||||
when:
|
when:
|
||||||
- ensure_apache is defined
|
- ensure_apache is defined
|
||||||
- http_vhost is defined
|
- http_vhost is defined
|
||||||
- http_vhost is iterable
|
- http_vhost is iterable
|
||||||
- item.fqdn is defined
|
- http_vhost | selectattr('repo', 'defined') | list | length > 0
|
||||||
- item.repo is defined
|
block:
|
||||||
ansible.builtin.git:
|
- name: Create Temporary Local Staging Directory
|
||||||
accept_hostkey: 'yes'
|
become: false
|
||||||
dest: /srv/http/{{ item.fqdn }}
|
delegate_to: localhost
|
||||||
repo: '{{ item.repo }}'
|
ansible.builtin.tempfile:
|
||||||
loop: '{{ http_vhost }}'
|
prefix: 'ansible_web_{{ inventory_hostname }}_'
|
||||||
loop_control:
|
state: directory
|
||||||
label: /srv/http/{{ item.fqdn }} will be populated...
|
register: ensure_apache_local_tempdir
|
||||||
notify:
|
|
||||||
- Ensure_Apache.Package_Facts
|
- name: Ensure Website Content Cloned Locally # noqa: latest[git]
|
||||||
- Ensure_Apache.Service_Facts
|
when:
|
||||||
- Ensure_Apache.Service_Reload
|
- item.fqdn is defined
|
||||||
- Ensure_Apache.Service_Reload_Config
|
- item.repo is defined
|
||||||
|
become: false
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.git:
|
||||||
|
accept_hostkey: true
|
||||||
|
depth: 1
|
||||||
|
dest: '{{ ensure_apache_local_tempdir.path }}/{{ (item.repo | hash("sha256"))[:8] }}_{{ item.fqdn }}'
|
||||||
|
repo: '{{ item.repo }}'
|
||||||
|
version: '{{ item.version | default("HEAD") }}'
|
||||||
|
loop: '{{ http_vhost }}'
|
||||||
|
loop_control:
|
||||||
|
label: '{{ item.fqdn }} local clone'
|
||||||
|
|
||||||
|
- name: Ensure Website Content Synchronized To Target
|
||||||
|
when:
|
||||||
|
- item.fqdn is defined
|
||||||
|
- item.repo is defined
|
||||||
|
ansible.posix.synchronize:
|
||||||
|
archive: true
|
||||||
|
checksum: true
|
||||||
|
delete: true
|
||||||
|
dest: '/srv/http/{{ item.fqdn }}/'
|
||||||
|
rsync_opts: '{{ item.rsync_opts | default(ensure_apache_rsync_excludes) }}'
|
||||||
|
src: '{{ ensure_apache_local_tempdir.path }}/{{ (item.repo | hash("sha256"))[:8] }}_{{ item.fqdn }}/'
|
||||||
|
loop: '{{ http_vhost }}'
|
||||||
|
loop_control:
|
||||||
|
label: '/srv/http/{{ item.fqdn }} will be synchronized'
|
||||||
|
notify:
|
||||||
|
- Ensure_Apache.Service_Reload
|
||||||
|
- Ensure_Apache.Service_Reload_Config
|
||||||
|
|
||||||
|
- name: Ensure SELinux Context On Web Content
|
||||||
|
when:
|
||||||
|
- item.fqdn is defined
|
||||||
|
- item.repo is defined
|
||||||
|
ansible.builtin.file:
|
||||||
|
dest: '/srv/http/{{ item.fqdn }}'
|
||||||
|
group: root
|
||||||
|
mode: '0755'
|
||||||
|
owner: root
|
||||||
|
recurse: true
|
||||||
|
setype: httpd_sys_content_t
|
||||||
|
loop: '{{ http_vhost }}'
|
||||||
|
loop_control:
|
||||||
|
label: '/srv/http/{{ item.fqdn }} SELinux context'
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: Remove Temporary Local Staging Directory
|
||||||
|
when:
|
||||||
|
- ensure_apache_local_tempdir is defined
|
||||||
|
- ensure_apache_local_tempdir.path is defined
|
||||||
|
become: false
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: '{{ ensure_apache_local_tempdir.path }}'
|
||||||
|
state: absent
|
||||||
- name: Ensure Services
|
- name: Ensure Services
|
||||||
when:
|
when:
|
||||||
- ensure_apache is defined
|
- ensure_apache is defined
|
||||||
|
|||||||
Reference in New Issue
Block a user