SSL / TLS Guide
AidiPanel uses Let's Encrypt (via Certbot) for free SSL certificates with automatic renewal.
Quick Start
# Install SSL for a domain
aidipanel ssl:install --domain example.com --email admin@example.com
# Check SSL status
aidipanel ssl:status
# Renew all certificates
aidipanel ssl:renewPrerequisites
Before installing SSL:
- Domain must point to your server —
example.comA record → server IP - Port 80 must be open — Let's Encrypt verifies via HTTP challenge
- Site must exist —
aidipanel site:add --domain example.comfirst
Check DNS:
dig +short example.com
# Should return your server's public IPInstalling a Certificate
Via CLI
aidipanel ssl:install --domain example.com --email admin@example.comThis:
- Runs
certbot --nginx -d example.com -d www.example.com - Obtains Let's Encrypt certificate
- Updates the Nginx vhost to use the new cert
- Reloads Nginx
- Sets up auto-renewal
Via Web Panel
- Go to Sites and open the domain
- Open the SSL tab
- Enter your email
- Click Install Certificate
Certificate Location
Let's Encrypt certificates are stored in:
/etc/letsencrypt/live/example.com/
├── fullchain.pem ← Certificate + chain (use this in Nginx)
├── privkey.pem ← Private key
├── cert.pem ← Certificate only
└── chain.pem ← Intermediate chain onlyNginx config references:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;Auto-Renewal
AidiPanel configures automatic renewal via cron:
# /etc/cron.d/aidipanel
30 2 * * * root certbot renew --quiet --nginx >> /var/log/aidipanel-certbot.log 2>&1Certbot renews certificates automatically when they are within 30 days of expiry.
Check renewal logs:
tail -f /var/log/aidipanel-certbot.logTest renewal manually:
certbot renew --dry-runSSL Status
aidipanel ssl:statusOutput example:
SSL Certificates
────────────────────────────────────────────────────────────
example.com Let's Encrypt Expires: 2025-08-12 ✓ Valid
shop.example.com Let's Encrypt Expires: 2025-07-30 ✓ Valid
old.example.com Self-signed Expires: 2034-01-01 ⚠ Self-signedSelf-Signed Certificate (Initial Setup)
Before you have a domain pointing to your server, AidiPanel uses a self-signed certificate for the panel UI itself:
/etc/ssl/aidipanel/aidipanel.crt
/etc/ssl/aidipanel/aidipanel.keyThe panel uses this certificate on port 8443, and new site vhosts use it as a temporary fallback until a trusted certificate is installed. It is not intended as the final public certificate for user sites.
Your browser will show a warning for self-signed certs — this is expected. Click "Advanced" → "Proceed" to access the panel.
HTTPS Redirect and HSTS
New sites initially serve HTTP and use a self-signed HTTPS certificate so DNS and content can be prepared without forcing visitors through a certificate warning. After installing a trusted certificate, enable Force HTTPS from the site's SSL tab or CLI:
aidipanel ssl:force-https --domain example.com --action onThe resulting HTTP redirect is:
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}HSTS is also off by default. Enable it only after HTTPS is trusted and stable:
aidipanel ssl:hsts --domain example.com --action onSSL Security Configuration
AidiPanel configures TLS 1.2/1.3, OCSP stapling, and common security headers. HSTS is shown below as an optional line rather than a new-site default:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:
ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_stapling on;
ssl_stapling_verify on;
# Optional after a trusted certificate is active:
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always;TLS results depend on the active certificate, DNS, Nginx build, and any manual vhost changes. Validate public sites with a current external TLS scanner rather than relying on a fixed grade claim.
Wildcard Certificates
For wildcard certs (*.example.com), you need DNS challenge instead of HTTP challenge:
certbot certonly \
--manual \
--preferred-challenges dns \
-d example.com \
-d "*.example.com" \
--email admin@example.com \
--agree-tosFollow the prompts to add a DNS TXT record. Then update your Nginx vhost to use the new cert path.
Multiple Domains on One Certificate
certbot --nginx \
-d example.com \
-d www.example.com \
-d shop.example.com \
--email admin@example.comRevoking / Deleting a Certificate
# Delete certificate for a domain
certbot delete --cert-name example.com
# List all certificates
certbot certificatesTroubleshooting
"Challenge failed" / Port 80 not accessible
# Check UFW allows port 80
ufw status
ufw allow 80/tcp
# Check Nginx is running and port 80 is active
systemctl status nginx
ss -tlnp | grep :80"Too many certificates" (Let's Encrypt rate limit)
Let's Encrypt allows 5 certificates per domain per week. If you hit the limit, wait a week or use --staging for testing:
certbot --nginx --staging -d example.comCertificate not renewing
# Check certbot can access your domain
certbot renew --dry-run
# Check cron is running
systemctl status cron
cat /etc/cron.d/aidipanel
# Manual renewal
certbot renew --force-renewal --nginx"Name or service not known" during renewal
Your domain's DNS is not resolving. Check DNS records and TTL.