Skip to content

Generating SSL Certificates

Passkeys and several other Calagopus features require a valid SSL certificate for your Panel and Wings. This guide walks you through generating one.

This is also a prerequisite if you plan to set up a Reverse Proxy or want to add an SSL certificate directly to your Wings machine.

All methods below use Let's Encrypt, which issues free certificates valid for 90 days.

This is the most common method and works well if your server has port 80 open to the internet.

1. Install certbot

Commands below are for Debian-based distributions using APT. For other systems, see the official certbot website.

bash
sudo apt update
sudo apt install -y certbot
# Only if you use Nginx
sudo apt install -y python3-certbot-nginx
# Only if you use Apache
sudo apt install -y python3-certbot-apache

2. Generate the certificate

Replace example.com with the domain you're issuing a certificate for. To cover multiple domains, repeat the -d flag (e.g. -d example.com -d www.example.com).

bash
# If using Nginx
sudo certbot certonly --nginx -d example.com
# If using Apache
sudo certbot certonly --apache -d example.com
# Standalone — use this if you don't run a webserver or the options above don't work.
# Stop any service already bound to port 80 first (nginx, apache etc.).
sudo certbot certonly --standalone -d example.com

You'll be prompted for an email address (used for renewal/expiry notices), then certbot issues the certificate automatically. Certificates are saved to /etc/letsencrypt/live/example.com/.

3. Renewal

Certbot installs a systemd timer (or cron job) that checks twice daily and renews when the certificate is close to expiry. If you used the --nginx or --apache plugin, that's all you need. The plugin reloads your webserver as part of the renewal itself.

If you used --standalone, or want Wings to also restart so it picks up a renewed certificate, add a deploy hook:

bash
sudo nano /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh
bash
#!/bin/bash
systemctl restart wings 2>/dev/null
bash
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-services.sh

Certbot runs every script in renewal-hooks/deploy/ automatically after a successful renewal. Test the whole flow without waiting for actual expiry:

bash
sudo certbot renew --dry-run

Troubleshooting

An Insecure Connection or SSL/TLS error in the browser almost always means the certificate has expired. If certbot renew fails with something like:

Error: Attempting to renew cert (domain) from /etc/letsencrypt/renew/domain.conf produced an unexpected error

…it's usually because port 80 is already in use. Using the --nginx / --apache plugin flags (as above) avoids this. Otherwise, stop the webserver, renew, then start it again:

bash
sudo systemctl stop nginx
sudo certbot renew
sudo systemctl start nginx

If Wings doesn't pick up the renewed certificate automatically, restart it manually:

bash
sudo systemctl restart wings

Which method should I use?

SituationRecommended method
Public webserver, port 80 openCertbot (HTTP Challenge)
Internal/NAT'd node, using a provider with a certbot DNS pluginCertbot (DNS Challenge)
Want a lighter, dependency-free tool?acme.sh