This guide provides a Ansible playbook to deploy Statping-ng with Docker Compose on Debian 10+, Ubuntu 20.04+, and RHEL 9+ compatible hosts. The playbook includes security hardening, firewall configuration, automatic SSL certificates, and backup automation.
| Component | Minimum | Recommended |
|---|---|---|
| OS | Debian 10+, Ubuntu 20.04+, RHEL 9+ | Debian 12, Ubuntu 24.04, RHEL 9+ |
| CPU | 2 cores | 4+ cores |
| RAM | 1 GB | 2+ GB |
| Disk | 10 GB | 20+ GB SSD |
| Network | Public IP, domain name | Static IP, DNS configured |
Configure DNS A/AAAA records before deployment:
status.example.com A <your-server-ip>
statping-ng-ansible/
βββ inventory.ini # Host inventory
βββ group_vars/
β βββ all.yml # Global variables
βββ host_vars/
β βββ statping-server.yml # Host-specific variables
βββ roles/
β βββ docker/ # Docker installation
β βββ statping-ng/ # Statping-ng deployment
β βββ nginx/ # Nginx reverse proxy
β βββ ssl/ # SSL certificate management
β βββ firewall/ # UFW/firewalld configuration
β βββ backup/ # Backup automation
β βββ hardening/ # OS security hardening
βββ playbooks/
β βββ deploy.yml # Main deployment playbook
β βββ backup.yml # Backup playbook
β βββ restore.yml # Restore playbook
βββ files/
βββ nginx/
β βββ statping.conf # Nginx configuration
βββ backup/
βββ backup.sh # Backup script
[statping-ng]
statping-server ansible_host=192.168.1.100 ansible_user=ubuntu ansible_ssh_private_key_file=~/.ssh/id_ed25519
[statping-ng:vars]
ansible_python_interpreter=/usr/bin/python3
# aws_ec2.yml
plugin: amazon.aws.aws_ec2
regions:
- eu-west-1
filters:
tag:Environment: production
tag:Application: statping-ng
keyed_groups:
- key: tags.Role
prefix: role
---
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Application Configuration
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
statping_ng_version: "0.93.0"
statping_ng_image: "adamboutcher/statping-ng:{{ statping_ng_version }}"
statping_ng_name: "My Status Page"
statping_ng_description: "Service monitoring and uptime dashboard"
statping_ng_domain: "status.example.com"
statping_ng_email: "admin@example.com"
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Database Configuration
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
statping_ng_db_type: "postgres" # postgres, mysql, sqlite
statping_ng_db_name: "statping"
statping_ng_db_user: "statping"
statping_ng_db_password: "{{ vault_statping_db_password }}"
statping_ng_db_root_password: "{{ vault_statping_db_root_password }}"
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Directory Structure
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
statping_ng_base_dir: "/opt/statping-ng"
statping_ng_data_dir: "/var/lib/statping-ng"
statping_ng_backup_dir: "/backup/statping-ng"
statping_ng_logs_dir: "/var/log/statping-ng"
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Docker Configuration
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
docker_install_compose: true
docker_compose_version: "v2.24.0"
docker_users:
- "{{ ansible_user }}"
docker_daemon_options:
storage-driver: overlay2
log-driver: json-file
log-opts:
max-size: "10m"
max-file: "3"
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Nginx Configuration
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
nginx_install: true
nginx_ssl_enabled: true
nginx_ssl_redirect: true
nginx_ssl_protocols: "TLSv1.2 TLSv1.3"
nginx_ssl_ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384"
nginx_hsts_enabled: true
nginx_hsts_max_age: 31536000
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Firewall Configuration
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
firewall_enabled: true
firewall_type: "ufw" # ufw or firewalld
firewall_allowed_tcp_ports:
- 22
- 80
- 443
firewall_rate_limit_ssh: true
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Backup Configuration
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
backup_enabled: true
backup_retention_days: 30
backup_schedule: "0 2 * * *" # Daily at 2 AM
backup_encrypt: true
backup_gpg_recipient: "admin@example.com"
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Security Hardening
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
security_ssh_port: 22
security_fail2ban_enabled: true
security_automatic_updates: true
security_audit_logging: true
---
# Host-specific overrides
statping_ng_domain: "status.prod.example.com"
statping_ng_email: "ops@example.com"
# Custom resource limits for this host
statping_ng_memory_limit: "512M"
statping_ng_cpu_limit: "0.5"
# Specific backup destination
statping_ng_backup_s3_bucket: "s3://example-backups/statping-ng"
---
vault_statping_db_password: "SecureDbPassword123!"
vault_statping_db_root_password: "SecureRootPassword456!"
vault_letsencrypt_email: "admin@example.com"
Encrypt with:
ansible-vault encrypt group_vars/all.yml
---
- name: Deploy Statping-ng Status Page
hosts: statping-ng
become: true
gather_facts: true
vars_files:
- ../group_vars/all.yml
- ../host_vars/{{ inventory_hostname }}.yml
- ../vault.yml
pre_tasks:
- name: Validate Ansible version
ansible.builtin.assert:
that:
- ansible_version.full is version('2.10', '>=')
fail_msg: "Ansible 2.10+ is required"
- name: Update apt cache (Debian/Ubuntu)
ansible.builtin.apt:
update_cache: true
cache_valid_time: 3600
when: ansible_os_family == "Debian"
- name: Update dnf cache (RHEL)
ansible.builtin.dnf:
update_cache: true
when: ansible_os_family == "RedHat"
roles:
- role: docker
tags: ['docker', 'base']
- role: firewall
tags: ['firewall', 'security']
- role: hardening
tags: ['hardening', 'security']
- role: statping-ng
tags: ['statping-ng', 'app']
- role: nginx
tags: ['nginx', 'proxy']
when: nginx_install | bool
- role: ssl
tags: ['ssl', 'security']
when: nginx_ssl_enabled | bool
- role: backup
tags: ['backup']
when: backup_enabled | bool
post_tasks:
- name: Verify Statping-ng is running
ansible.builtin.uri:
url: "http://127.0.0.1:8080/health"
status_code: 200
register: health_check
retries: 5
delay: 10
until: health_check.status == 200
- name: Display deployment summary
ansible.builtin.debug:
msg: |
Statping-ng deployment completed!
URL: https://{{ statping_ng_domain }}
Admin Setup: Complete the wizard at the URL above
Database: {{ statping_ng_db_type }}
Backup: {{ 'Enabled' if backup_enabled else 'Disabled' }}
Firewall: {{ 'Enabled' if firewall_enabled else 'Disabled' }}
---
- name: Install Docker prerequisites
ansible.builtin.package:
name:
- apt-transport-https
- ca-certificates
- curl
- gnupg
- lsb-release
state: present
when: ansible_os_family == "Debian"
- name: Add Docker GPG key (Debian/Ubuntu)
ansible.builtin.apt_key:
url: https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg
state: present
when: ansible_os_family == "Debian"
- name: Add Docker repository (Debian/Ubuntu)
ansible.builtin.apt_repository:
repo: "deb [arch=amd64] https://download.docker.com/linux/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} stable"
state: present
when: ansible_os_family == "Debian"
- name: Install Docker Engine
ansible.builtin.package:
name:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-compose-plugin
state: present
notify: Restart Docker
- name: Create Docker configuration directory
ansible.builtin.file:
path: /etc/docker
state: directory
mode: '0755'
- name: Configure Docker daemon
ansible.builtin.copy:
dest: /etc/docker/daemon.json
content: |
{
"storage-driver": "overlay2",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"userland-proxy": false
}
mode: '0644'
notify: Restart Docker
- name: Enable and start Docker
ansible.builtin.systemd:
name: docker
enabled: true
state: started
- name: Add users to docker group
ansible.builtin.user:
name: "{{ item }}"
groups: docker
append: true
loop: "{{ docker_users | default([]) }}"
---
- name: Create application directory
ansible.builtin.file:
path: "{{ statping_ng_base_dir }}"
state: directory
mode: '0755'
owner: root
group: root
- name: Create data directory
ansible.builtin.file:
path: "{{ statping_ng_data_dir }}"
state: directory
mode: '0755'
owner: root
group: root
- name: Create logs directory
ansible.builtin.file:
path: "{{ statping_ng_logs_dir }}"
state: directory
mode: '0755'
owner: root
group: root
- name: Generate .env file
ansible.builtin.template:
src: env.j2
dest: "{{ statping_ng_base_dir }}/.env"
mode: '0600'
- name: Deploy Docker Compose configuration
ansible.builtin.template:
src: docker-compose.yml.j2
dest: "{{ statping_ng_base_dir }}/docker-compose.yml"
mode: '0644'
- name: Deploy Docker Compose override (production)
ansible.builtin.template:
src: docker-compose.override.yml.j2
dest: "{{ statping_ng_base_dir }}/docker-compose.override.yml"
mode: '0644'
when: nginx_install | bool
- name: Start Statping-ng stack
community.docker.docker_compose:
project_src: "{{ statping_ng_base_dir }}"
state: present
remove_orphans: true
- name: Wait for Statping-ng to be healthy
ansible.builtin.uri:
url: "http://127.0.0.1:8080/health"
status_code: 200
register: result
retries: 10
delay: 15
until: result.status == 200
version: '3.8'
services:
statping-ng:
image: {{ statping_ng_image }}
container_name: statping-ng
restart: unless-stopped
depends_on:
{{ statping_ng_db_type }}:
condition: service_healthy
networks:
- statping_frontend
- statping_backend
volumes:
- {{ statping_ng_data_dir }}:/app
- {{ statping_ng_logs_dir }}:/app/logs
environment:
- NAME={{ statping_ng_name }}
- DESCRIPTION={{ statping_ng_description }}
- VIRTUAL_HOST={{ statping_ng_domain }}
- VIRTUAL_PORT=8080
- LETSENCRYPT_HOST={{ statping_ng_domain }}
- LETSENCRYPT_EMAIL={{ statping_ng_email }}
- DB_CONN={{ statping_ng_db_type }}
- DB_HOST={{ statping_ng_db_type }}
- DB_PORT={{ '5432' if statping_ng_db_type == 'postgres' else '3306' }}
- DB_USER={{ statping_ng_db_user }}
- DB_PASS={{ statping_ng_db_password }}
- DB_DATABASE={{ statping_ng_db_name }}
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
deploy:
resources:
limits:
memory: {{ statping_ng_memory_limit | default('512M') }}
cpus: '{{ statping_ng_cpu_limit | default('0.5') }}'
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- CHOWN
- SETUID
- SETGID
{% if statping_ng_db_type == 'postgres' %}
postgres:
image: postgres:15-alpine
container_name: statping-postgres
restart: unless-stopped
networks:
- statping_backend
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
- POSTGRES_USER={{ statping_ng_db_user }}
- POSTGRES_PASSWORD={{ statping_ng_db_password }}
- POSTGRES_DB={{ statping_ng_db_name }}
- POSTGRES_INITDB_ARGS=--encoding=UTF8 --lc-collate=C --lc-ctype=C
healthcheck:
test: ["CMD-SHELL", "pg_isready -U {{ statping_ng_db_user }} -d {{ statping_ng_db_name }}"]
interval: 10s
timeout: 5s
retries: 5
deploy:
resources:
limits:
memory: 1G
cpus: '1.0'
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- CHOWN
- SETUID
- SETGID
- DAC_OVERRIDE
{% elif statping_ng_db_type == 'mysql' %}
mysql:
image: mysql:8.0
container_name: statping-mysql
restart: unless-stopped
networks:
- statping_backend
volumes:
- mysql_data:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD={{ statping_ng_db_root_password }}
- MYSQL_USER={{ statping_ng_db_user }}
- MYSQL_PASSWORD={{ statping_ng_db_password }}
- MYSQL_DATABASE={{ statping_ng_db_name }}
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p{{ statping_ng_db_root_password }}"]
interval: 10s
timeout: 5s
retries: 5
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- CHOWN
- SETUID
- SETGID
{% endif %}
nginx-proxy:
image: nginxproxy/nginx-proxy:1.4
container_name: nginx-proxy
restart: unless-stopped
ports:
- "0.0.0.0:80:80"
- "0.0.0.0:443:443"
networks:
- statping_frontend
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- nginx_certs:/etc/nginx/certs:ro
- nginx_vhost:/etc/nginx/vhost.d
- nginx_html:/usr/share/nginx/html
environment:
- DEFAULT_HOST={{ statping_ng_domain }}
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- CHOWN
- SETUID
- SETGID
- NET_BIND_SERVICE
letsencrypt-companion:
image: nginxproxy/acme-companion:2.2
container_name: letsencrypt-companion
restart: unless-stopped
depends_on:
- nginx-proxy
networks:
- statping_frontend
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- nginx_certs:/etc/nginx/certs:rw
- nginx_vhost:/etc/nginx/vhost.d
- nginx_html:/usr/share/nginx/html
- acme_data:/etc/acme.sh
environment:
- DEFAULT_EMAIL={{ statping_ng_email }}
- NGINX_PROXY_CONTAINER=nginx-proxy
networks:
statping_frontend:
driver: bridge
statping_backend:
driver: bridge
internal: true
volumes:
postgres_data:
driver: local
{% if statping_ng_db_type == 'mysql' %}
mysql_data:
driver: local
{% endif %}
nginx_certs:
driver: local
nginx_vhost:
driver: local
nginx_html:
driver: local
acme_data:
driver: local
---
- name: Install UFW (Debian/Ubuntu)
ansible.builtin.package:
name: ufw
state: present
when:
- firewall_enabled | bool
- firewall_type == "ufw"
- ansible_os_family == "Debian"
- name: Install firewalld (RHEL)
ansible.builtin.package:
name: firewalld
state: present
when:
- firewall_enabled | bool
- firewall_type == "firewalld"
- ansible_os_family == "RedHat"
- name: Configure UFW defaults
ansible.builtin.lineinfile:
path: /etc/default/ufw
regexp: "^DEFAULT_FORWARD_POLICY"
line: "DEFAULT_FORWARD_POLICY=\"DROP\""
when:
- firewall_enabled | bool
- firewall_type == "ufw"
- name: Allow SSH through UFW
community.general.ufw:
rule: allow
port: "{{ security_ssh_port | string }}"
proto: tcp
when:
- firewall_enabled | bool
- firewall_type == "ufw"
- name: Allow HTTP through UFW
community.general.ufw:
rule: allow
port: "80"
proto: tcp
when:
- firewall_enabled | bool
- firewall_type == "ufw"
- name: Allow HTTPS through UFW
community.general.ufw:
rule: allow
port: "443"
proto: tcp
when:
- firewall_enabled | bool
- firewall_type == "ufw"
- name: Enable UFW
community.general.ufw:
state: enabled
policy: deny
when:
- firewall_enabled | bool
- firewall_type == "ufw"
- name: Configure firewalld (RHEL)
ansible.posix.firewalld:
service: "{{ item }}"
permanent: true
state: enabled
immediate: true
loop:
- ssh
- http
- https
when:
- firewall_enabled | bool
- firewall_type == "firewalld"
- ansible_os_family == "RedHat"
---
- name: Create backup directory
ansible.builtin.file:
path: "{{ statping_ng_backup_dir }}"
state: directory
mode: '0700'
owner: root
group: root
- name: Deploy backup script
ansible.builtin.template:
src: backup.sh.j2
dest: /usr/local/bin/statping-backup
mode: '0755'
- name: Deploy backup systemd service
ansible.builtin.template:
src: statping-backup.service.j2
dest: /etc/systemd/system/statping-backup.service
mode: '0644'
notify: Reload systemd
- name: Deploy backup systemd timer
ansible.builtin.template:
src: statping-backup.timer.j2
dest: /etc/systemd/system/statping-backup.timer
mode: '0644'
notify:
- Reload systemd
- Enable backup timer
- name: Enable backup timer
ansible.builtin.systemd:
name: statping-backup.timer
enabled: true
state: started
#!/bin/bash
set -euo pipefail
# Statping-ng Backup Script
# Generated by Ansible
BACKUP_DIR="{{ statping_ng_backup_dir }}"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS={{ backup_retention_days }}
DB_TYPE="{{ statping_ng_db_type }}"
DB_USER="{{ statping_ng_db_user }}"
DB_NAME="{{ statping_ng_db_name }}"
ENCRYPT={{ backup_encrypt | lower }}
# Create backup directory
mkdir -p "$BACKUP_DIR"
echo "[$(date)] Starting Statping-ng backup..."
# Backup database
if [ "$DB_TYPE" = "postgres" ]; then
docker exec statping-postgres pg_dump -U "$DB_USER" -d "$DB_NAME" | \
gzip > "$BACKUP_DIR/statping_db_$DATE.sql.gz"
elif [ "$DB_TYPE" = "mysql" ]; then
docker exec statping-mysql mysqldump -u "$DB_USER" -p"{{ statping_ng_db_password }}" "$DB_NAME" | \
gzip > "$BACKUP_DIR/statping_db_$DATE.sql.gz"
fi
# Backup application data
docker run --rm \
-v {{ statping_ng_data_dir }}:/data:ro \
-v "$BACKUP_DIR:/backup" \
alpine tar -czf "/backup/statping_data_$DATE.tar.gz" -C /data .
# Encrypt backups if enabled
if [ "$ENCRYPT" = "true" ]; then
echo "[$(date)] Encrypting backups..."
gpg --batch --yes --symmetric --cipher-algo AES256 \
--passphrase "{{ vault_statping_db_password }}" \
"$BACKUP_DIR/statping_db_$DATE.sql.gz"
gpg --batch --yes --symmetric --cipher-algo AES256 \
--passphrase "{{ vault_statping_db_password }}" \
"$BACKUP_DIR/statping_data_$DATE.tar.gz"
rm -f "$BACKUP_DIR/statping_db_$DATE.sql.gz"
rm -f "$BACKUP_DIR/statping_data_$DATE.tar.gz"
fi
# Cleanup old backups
echo "[$(date)] Cleaning up backups older than $RETENTION_DAYS days..."
find "$BACKUP_DIR" -name "statping_*.gz*" -mtime +$RETENTION_DAYS -delete
echo "[$(date)] Backup completed successfully!"
---
- name: Install security updates automatically
ansible.builtin.package:
name:
- unattended-upgrades
- apt-listchanges
state: present
when:
- security_automatic_updates | bool
- ansible_os_family == "Debian"
- name: Configure unattended upgrades
ansible.builtin.debconf:
name: unattended-upgrades
question: unattended-upgrades/enable_auto_updates
value: "true"
vtype: boolean
when:
- security_automatic_updates | bool
- ansible_os_family == "Debian"
- name: Install fail2ban
ansible.builtin.package:
name: fail2ban
state: present
when: security_fail2ban_enabled | bool
- name: Configure fail2ban jail
ansible.builtin.template:
src: jail.local.j2
dest: /etc/fail2ban/jail.local
mode: '0644'
notify: Restart fail2ban
- name: Enable and start fail2ban
ansible.builtin.systemd:
name: fail2ban
enabled: true
state: started
when: security_fail2ban_enabled | bool
- name: Configure sysctl security parameters
ansible.posix.sysctl:
name: "{{ item.name }}"
value: "{{ item.value }}"
sysctl_set: true
state: present
reload: true
loop:
- { name: 'net.ipv4.ip_forward', value: '0' }
- { name: 'net.ipv4.conf.all.send_redirects', value: '0' }
- { name: 'net.ipv4.conf.default.send_redirects', value: '0' }
- { name: 'net.ipv4.conf.all.accept_source_route', value: '0' }
- { name: 'net.ipv4.conf.default.accept_source_route', value: '0' }
- { name: 'net.ipv4.conf.all.accept_redirects', value: '0' }
- { name: 'net.ipv4.conf.default.accept_redirects', value: '0' }
- { name: 'net.ipv4.conf.all.secure_redirects', value: '0' }
- { name: 'net.ipv4.conf.default.secure_redirects', value: '0' }
- { name: 'net.ipv4.conf.all.log_martians', value: '1' }
- { name: 'net.ipv4.conf.default.log_martians', value: '1' }
- { name: 'net.ipv4.icmp_echo_ignore_broadcasts', value: '1' }
- { name: 'net.ipv4.icmp_ignore_bogus_error_responses', value: '1' }
- { name: 'net.ipv4.conf.all.rp_filter', value: '1' }
- { name: 'net.ipv4.conf.default.rp_filter', value: '1' }
- { name: 'net.ipv4.tcp_syncookies', value: '1' }
# Test playbook (dry-run)
ansible-playbook -i inventory.ini playbooks/deploy.yml --check
# Run deployment
ansible-playbook -i inventory.ini playbooks/deploy.yml
# Run with vault password
ansible-playbook -i inventory.ini playbooks/deploy.yml --ask-vault-pass
# Run specific tags
ansible-playbook -i inventory.ini playbooks/deploy.yml --tags 'docker,statping-ng'
ansible-playbook -i inventory.ini playbooks/deploy.yml --tags 'backup'
ansible-playbook -i inventory.ini playbooks/deploy.yml --tags 'hardening'
# Run backup playbook
ansible-playbook -i inventory.ini playbooks/backup.yml
# Restore from backup
ansible-playbook -i inventory.ini playbooks/restore.yml \
-e "backup_file=/backup/statping-ng/statping_db_20260216_020000.sql.gz"
# Upgrade Statping-ng
ansible-playbook -i inventory.ini playbooks/deploy.yml \
-e "statping_ng_version=0.94.0" --tags 'statping-ng'
# Renew SSL certificates
ansible-playbook -i inventory.ini playbooks/deploy.yml --tags 'ssl'
# Apply security updates
ansible-playbook -i inventory.ini playbooks/deploy.yml --tags 'hardening'
# Check deployment status
ansible statping-ng -m ping
ansible statping-ng -a "docker compose ps"
# Verify health endpoint
ansible statping-ng -m uri -a "url=http://127.0.0.1:8080/health"
# Check SSL certificate
ansible statping-ng -a "openssl s_client -connect {{ statping_ng_domain }}:443"
Docker not starting:
ansible statping-ng -a "systemctl status docker"
ansible statping-ng -a "journalctl -u docker -n 50"
Statping-ng container failing:
ansible statping-ng -a "docker compose logs statping-ng"
ansible statping-ng -a "docker compose ps -a"
SSL certificate not issued:
ansible statping-ng -a "docker compose logs letsencrypt-companion"
ansible statping-ng -a "ls -la /opt/statping-ng/nginx/certs/"
Any questions?
Feel free to contact us. Find all contact information on our contact page.