SSL certificates
Keep your panel on HTTPS, and fix it when the certificate does not renew.
The installer sets this up for you. This page covers what it did, and what to do later.
What the installer does
During the installation, the installer asks how HTTPS is handled:
- Let's Encrypt (Automatic Renewal). The installer installs certbot and requests a certificate for your one panel domain. The challenge is HTTP-01 on port 80.
- External Certificate / Proxy / No Certificate. The installer requests nothing, and the panel answers on port 80. Put your own certificate in
docker/nginx/ssl/to have the panel serve HTTPS itself, or leave the panel on port 80 to put your own proxy in front of it. See Your own certificate.
On the Let's Encrypt path the installer then:
- Copies the certificate to
docker/nginx/ssl/badgerpanel.crtin your installation directory. - Copies the private key to
docker/nginx/ssl/badgerpanel.keyin the same directory. - Switches the panel to HTTPS, and sends port 80 to port 443.
- Adds a renewal job to the root crontab. It runs
certbot renewevery day at 03:00. - Installs the renewal steps that free port 80, put the new files in place, and reload the web server.
TIP
The certificate covers one domain. BadgerPanel does not request a wildcard certificate, and it does not use the Let's Encrypt staging environment.
Automatic renewal
A Let's Encrypt certificate is valid for 90 days. When less than 30 days remain, the daily job renews it.
A renewal runs in this order:
- The job frees port 80 for the HTTP-01 challenge.
- Certbot gets the new certificate from Let's Encrypt.
- The job copies the new certificate and key into
docker/nginx/ssl/. - The web server starts again with the new files.
The panel is unreachable for a few seconds during each renewal. The job runs at 03:00 to keep that pause outside your busy hours.
Certificate warnings in the panel
The panel reads the certificate file every 6 hours. A banner appears across the top of the admin area when the certificate needs attention:
- An amber banner reads "TLS certificate expires in N days". It appears when less than 14 days remain.
- A red banner reads "TLS certificate has expired".
Both banners have a Renew now button. This button runs certbot renew at once. The panel also attempts a renewal on its own when the certificate enters the 14-day window.
The panel allows one renewal attempt per hour. If you click Renew now again inside that hour, the panel refuses and shows the remaining time. When a renewal fails, the banner shows the certbot error under "Last renew error".
You can dismiss the amber banner. The red banner comes back until the certificate is valid again.
Manual renewal
The daily job keeps the certificate valid. If you want the new certificate at once, renew it by hand:
sudo certbot renewIt does the same as the daily job: frees port 80, puts the new files in place, and starts the web server again.
Certbot keeps a certificate that has more than 30 days left. To replace such a certificate, add --force-renewal.
To see the expiry date of the certificate that certbot holds, run:
sudo certbot certificatesYour own certificate
To use a certificate from somebody else, replace the two files the panel reads.
- Copy your certificate chain to
docker/nginx/ssl/badgerpanel.crtin your installation directory. - Copy your private key to
docker/nginx/ssl/badgerpanel.keyin the same directory. - Restart the web server.
cd ~/badgerpanel
docker compose restart nginxThe file names must be exactly badgerpanel.crt and badgerpanel.key. The certificate must cover the domain in your APP_URL value. The .crt file must hold the full chain, not the leaf certificate on its own.
Common errors
The certificate request fails during installation
| Cause | What to do |
|---|---|
| DNS does not point to this server | Run dig panel.example.com. The A record must hold the public IP of your server. |
| Port 80 is blocked or in use | Let's Encrypt needs port 80 for the HTTP-01 challenge. Open it, and stop any other web server. |
| Rate limit reached | Let's Encrypt limits how many certificates one domain can get. Wait one hour, then try again. |
The browser shows a certificate warning
- The certificate is expired. Run
sudo certbot certificatesto read the expiry date, then renew. - The address in the browser is not the domain of the certificate. Open the panel with the exact domain.
- Your own certificate holds only the leaf. Put the full chain in
badgerpanel.crt.
The browser reports mixed content
Open the .env file in your installation directory. Make sure that APP_URL, APP_BASE_URL, API_URL, and NEXT_PUBLIC_API_URL all start with https://. Then restart the panel.
