Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ After=network.target
[Service]
Type=oneshot
ExecStart=/bin/bash -c '/usr/bin/rsync -av --delete {{ cloudlinux_rsync_source }} {{ cloudlinux_mirror_path }}/ && /usr/bin/rsync -av --delete {{ swng_rsync_source }} {{ swng_mirror_path }}/'
ExecStartPost=/usr/bin/python3 /opt/healthcheck/healthcheck_update.py --service sync --field repo --value {{ healthcheck_source_name }} --status OK
StandardOutput=append:{{ combined_sync_log }}
StandardError=append:{{ combined_sync_log }}
5 changes: 5 additions & 0 deletions ansible/combined-mirror/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,8 @@ certbot_cron_enabled: true
certbot_cron_schedule:
minute: 0
hour: 3

# /healthcheck endpoint (required by cl-mirrors mirrorservice)
healthcheck_file: /var/www/healthcheck.html
healthcheck_json_file: /var/www/healthcheck.json
healthcheck_source_name: swng.cloudlinux.com
13 changes: 13 additions & 0 deletions ansible/combined-mirror/nginx-https.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ server {
autoindex on;
}

# Required by cl-mirrors mirrorservice (health-check)
location = /healthcheck {
alias {{ healthcheck_file }};
default_type text/html;
}

# Required by cl-mirrors mirrorservice (machine-readable JSON, post-2026-06-12 contract)
location = /healthcheck.json {
alias {{ healthcheck_json_file }};
default_type application/json;
add_header Cache-Control "no-store";
}

# SWNG repositories
location /swng/ {
alias {{ swng_mirror_path }}/;
Expand Down
13 changes: 13 additions & 0 deletions ansible/combined-mirror/nginx.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,19 @@ server {
autoindex on;
}

# Required by cl-mirrors mirrorservice (health-check)
location = /healthcheck {
alias {{ healthcheck_file }};
default_type text/html;
}

# Required by cl-mirrors mirrorservice (machine-readable JSON, post-2026-06-12 contract)
location = /healthcheck.json {
alias {{ healthcheck_json_file }};
default_type application/json;
add_header Cache-Control "no-store";
}

# SWNG repositories
location /swng/ {
alias {{ swng_mirror_path }}/;
Expand Down
55 changes: 55 additions & 0 deletions ansible/combined-mirror/playbook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
ignore_errors: yes

- name: Create combined systemd service (when sync_mode is combined)
tags: healthcheck
template:
src: cloudlinux-complete-mirror.service.j2
dest: "/etc/systemd/system/{{ service_name }}.service"
Expand Down Expand Up @@ -93,6 +94,7 @@
notify: reload systemd

- name: Create separate SWNG service (when sync_mode is separate)
tags: healthcheck
template:
src: swng-mirror.service.j2
dest: /etc/systemd/system/swng-mirror.service
Expand Down Expand Up @@ -141,12 +143,63 @@
debug:
msg: "{{ timer_status.stdout_lines }}"

- name: Install epel-release (required for python3-dotenv on RedHat-family)
tags: healthcheck
ansible.builtin.package:
name: epel-release
state: present
when: ansible_facts['os_family'] == 'RedHat'
ignore_errors: true

- name: Install python3-dotenv (required by healthcheck_update.py)
tags: healthcheck
ansible.builtin.package:
name: python3-dotenv
state: present

- name: Ensure /opt/healthcheck directory exists
tags: healthcheck
ansible.builtin.file:
path: /opt/healthcheck
state: directory
mode: '0755'

- name: Install healthcheck_update.py (shared from ansible/healthcheck/)
tags: healthcheck
ansible.builtin.copy:
src: "{{ playbook_dir }}/../healthcheck/healthcheck_update.py"
dest: /opt/healthcheck/healthcheck_update.py
mode: '0755'

- name: Deploy /opt/healthcheck/.env (idempotent, preserves customer edits)
tags: healthcheck
ansible.builtin.copy:
src: "{{ playbook_dir }}/../healthcheck/.env"
dest: /opt/healthcheck/.env
mode: '0644'
force: false

- name: Ensure /var/www directory exists (serves /healthcheck HTML)
tags: healthcheck
ansible.builtin.file:
path: /var/www
state: directory
mode: '0755'

- name: Generate initial /healthcheck so it is available before first sync completes
tags: healthcheck
ansible.builtin.command:
cmd: /usr/bin/python3 /opt/healthcheck/healthcheck_update.py --service sync --field repo --value {{ healthcheck_source_name }} --status PENDING
args:
creates: /var/www/healthcheck.html

- name: Install Nginx
package:
name: nginx
state: present

- name: Create Nginx configuration for combined mirror
tags: healthcheck
template:
src: nginx.conf.j2
dest: /etc/nginx/conf.d/combined-mirror.conf
Expand Down Expand Up @@ -238,6 +291,7 @@
when: certbot_enabled | bool and certbot_authenticator == 'standalone'

- name: Create Nginx HTTPS configuration for combined mirror
tags: healthcheck
template:
src: nginx-https.conf.j2
dest: /etc/nginx/conf.d/combined-mirror-https.conf
Expand All @@ -246,6 +300,7 @@
when: certbot_enabled | bool

- name: Update HTTP Nginx configuration to redirect to HTTPS
tags: healthcheck
template:
src: nginx.conf.j2
dest: /etc/nginx/conf.d/combined-mirror.conf
Expand Down
1 change: 1 addition & 0 deletions ansible/combined-mirror/swng-mirror.service.j2
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ After=network.target
[Service]
Type=oneshot
ExecStart=/usr/bin/rsync -av --delete {{ swng_rsync_source }} {{ swng_mirror_path }}/
ExecStartPost=/usr/bin/python3 /opt/healthcheck/healthcheck_update.py --service sync --field repo --value {{ healthcheck_source_name }} --status OK
StandardOutput=append:{{ swng_sync_log }}
StandardError=append:{{ swng_sync_log }}
5 changes: 5 additions & 0 deletions ansible/complete-swng-rsync/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,8 @@ certbot_cron_schedule:
minute: 0
hour: 3


# /healthcheck endpoint (required by cl-mirrors mirrorservice)
healthcheck_file: /var/www/healthcheck.html
healthcheck_json_file: /var/www/healthcheck.json
healthcheck_source_name: swng.cloudlinux.com
13 changes: 13 additions & 0 deletions ansible/complete-swng-rsync/nginx-https.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,19 @@ server {
access_log /var/log/nginx/swng-mirror-https-access.log;
error_log /var/log/nginx/swng-mirror-https-error.log;

# Required by cl-mirrors mirrorservice (health-check)
location = /healthcheck {
alias {{ healthcheck_file }};
default_type text/html;
}

# Required by cl-mirrors mirrorservice (machine-readable JSON, post-2026-06-12 contract)
location = /healthcheck.json {
alias {{ healthcheck_json_file }};
default_type application/json;
add_header Cache-Control "no-store";
}

# SWNG repositories
location / {
try_files $uri $uri/ =404;
Expand Down
26 changes: 26 additions & 0 deletions ansible/complete-swng-rsync/nginx.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@ server {
root {{ certbot_webroot | default('/var/www/mirrors/acme') }};
}

# Required by cl-mirrors mirrorservice (health-check)
location = /healthcheck {
alias {{ healthcheck_file }};
default_type text/html;
}

# Required by cl-mirrors mirrorservice (machine-readable JSON, post-2026-06-12 contract)
location = /healthcheck.json {
alias {{ healthcheck_json_file }};
default_type application/json;
add_header Cache-Control "no-store";
}

# Normalize SWNG path (no trailing slash)
location = /swng {
return 301 https://$server_name/swng/;
Expand Down Expand Up @@ -37,6 +50,19 @@ server {
access_log /var/log/nginx/swng-mirror-access.log;
error_log /var/log/nginx/swng-mirror-error.log;

# Required by cl-mirrors mirrorservice (health-check)
location = /healthcheck {
alias {{ healthcheck_file }};
default_type text/html;
}

# Required by cl-mirrors mirrorservice (machine-readable JSON, post-2026-06-12 contract)
location = /healthcheck.json {
alias {{ healthcheck_json_file }};
default_type application/json;
add_header Cache-Control "no-store";
}

# SWNG repositories
location / {
try_files $uri $uri/ =404;
Expand Down
54 changes: 54 additions & 0 deletions ansible/complete-swng-rsync/playbook.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
command: chmod -R o+rx {{ swng_mirror_path }}

- name: Create systemd service for SWNG mirror sync
tags: healthcheck
template:
src: swng-mirror.service.j2
dest: /etc/systemd/system/swng-mirror.service
Expand Down Expand Up @@ -73,12 +74,63 @@
debug:
msg: "{{ timer_status.stdout_lines }}"

- name: Install epel-release (required for python3-dotenv on RedHat-family)
tags: healthcheck
ansible.builtin.package:
name: epel-release
state: present
when: ansible_facts['os_family'] == 'RedHat'
ignore_errors: true

- name: Install python3-dotenv (required by healthcheck_update.py)
tags: healthcheck
ansible.builtin.package:
name: python3-dotenv
state: present

- name: Ensure /opt/healthcheck directory exists
tags: healthcheck
ansible.builtin.file:
path: /opt/healthcheck
state: directory
mode: '0755'

- name: Install healthcheck_update.py (shared from ansible/healthcheck/)
tags: healthcheck
ansible.builtin.copy:
src: "{{ playbook_dir }}/../healthcheck/healthcheck_update.py"
dest: /opt/healthcheck/healthcheck_update.py
mode: '0755'

- name: Deploy /opt/healthcheck/.env (idempotent, preserves customer edits)
tags: healthcheck
ansible.builtin.copy:
src: "{{ playbook_dir }}/../healthcheck/.env"
dest: /opt/healthcheck/.env
mode: '0644'
force: false

- name: Ensure /var/www directory exists (serves /healthcheck HTML)
tags: healthcheck
ansible.builtin.file:
path: /var/www
state: directory
mode: '0755'

- name: Generate initial /healthcheck so it is available before first sync completes
tags: healthcheck
ansible.builtin.command:
cmd: /usr/bin/python3 /opt/healthcheck/healthcheck_update.py --service sync --field repo --value {{ healthcheck_source_name }} --status PENDING
args:
creates: /var/www/healthcheck.html

- name: Install Nginx
package:
name: nginx
state: present

- name: Create Nginx configuration for SWNG mirror
tags: healthcheck
template:
src: nginx.conf.j2
dest: /etc/nginx/conf.d/swng-mirror.conf
Expand Down Expand Up @@ -170,6 +222,7 @@
when: certbot_enabled | bool and certbot_authenticator == 'standalone'

- name: Create Nginx HTTPS configuration for SWNG mirror
tags: healthcheck
template:
src: nginx-https.conf.j2
dest: /etc/nginx/conf.d/swng-mirror-https.conf
Expand All @@ -178,6 +231,7 @@
when: certbot_enabled | bool

- name: Update HTTP Nginx configuration to redirect to HTTPS
tags: healthcheck
template:
src: nginx.conf.j2
dest: /etc/nginx/conf.d/swng-mirror.conf
Expand Down
1 change: 1 addition & 0 deletions ansible/complete-swng-rsync/swng-mirror.service.j2
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ After=network.target
[Service]
Type=oneshot
ExecStart=/usr/bin/rsync -av --delete {{ rsync_source }} {{ swng_mirror_path }}/
ExecStartPost=/usr/bin/python3 /opt/healthcheck/healthcheck_update.py --service sync --field repo --value {{ healthcheck_source_name }} --status OK
StandardOutput=append:{{ sync_log_file }}
StandardError=append:{{ sync_log_file }}
10 changes: 10 additions & 0 deletions ansible/healthcheck/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Default values for customer-deployed SWNG mirrors.
# Nginx in this repo aliases /healthcheck to /var/www/healthcheck.html, so
# point the renderer at /var/www by default.
HEALTHCHECK_JSON=/var/www/healthcheck.json
HEALTHCHECK_HTML=/var/www/healthcheck.html

# To use storage-rooted paths (matches internal CloudLinux mirror convention),
# uncomment these and comment the two lines above:
# HEALTHCHECK_JSON=/storage/$HOSTNAME/healthcheck.json
# HEALTHCHECK_HTML=/storage/$HOSTNAME/healthcheck.html
Loading