This guide covers setting up SSL certificates for secure HTTPS connections to your Frappe sites using Let’s Encrypt, wildcard certificates, or custom SSL certificates.
Prerequisites
Before setting up SSL:
- Production bench configured (see Production Deployment)
- Domain name(s) pointing to your server
- DNS-based multitenancy enabled for Let’s Encrypt
- Certbot installed (automatic during setup)
- Port 80 and 443 accessible
SSL setup requires DNS-based multitenancy. Port-based sites cannot use Let’s Encrypt certificates.
Enable DNS Multitenancy
SSL setup requires DNS multitenancy to be enabled:
bench config dns_multitenant on
Regenerate NGINX configuration:
bench setup nginx
sudo bench setup reload-nginx
With DNS multitenancy enabled, sites are accessed by their domain name (e.g., mysite.com) rather than by port number.
Let’s Encrypt SSL Setup
Let’s Encrypt provides free, automated SSL certificates with 90-day validity and automatic renewal.
Ensure your domain points to your server:
dig mysite.com +short
# Should return your server's IP address
sudo bench setup lets-encrypt [sitename]
sudo bench setup lets-encrypt mysite.com
Running this will stop the nginx service temporarily causing your sites to go offline
Do you want to continue?
Setup completes automatically
Stop NGINX temporarily
Run Certbot to obtain certificates
Configure NGINX for HTTPS
Set up automatic renewal cron job
Restart NGINX
Non-interactive mode
For automation or scripting:
sudo bench setup lets-encrypt mysite.com --non-interactive
Non-interactive mode should only be used after you’ve successfully run the command once manually.
Custom Domain SSL
For sites with custom domains configured via bench setup add-domain:
Add custom domain to site
bench setup add-domain custom.example.com --site mysite.com
Setup SSL for custom domain
sudo bench setup lets-encrypt mysite.com --custom-domain custom.example.com
Wildcard SSL Certificates
Wildcard certificates cover all subdomains under a domain (e.g., *.example.com).
Wildcard certificates require DNS validation via manual TXT record creation.
For wildcard without base domain:
sudo bench setup wildcard-ssl *.example.com --email [email protected] --exclude-base-domain
Certbot will display TXT records to add to your DNS:
Please deploy a DNS TXT record under the name
_acme-challenge.example.com with the following value:
ABC123XYZ789...
Before continuing, verify the record is deployed.
Name: _acme-challenge.example.com
Type: TXT
Value: The value provided by Certbot
dig _acme-challenge.example.com TXT +short
Press Enter in the terminal to continue after DNS is updated.
Wildcard certificate configuration
Wildcard configuration is stored in sites/common_site_config.json:
{
"wildcard": {
"domain": "*.example.com",
"ssl_certificate": "/etc/letsencrypt/live/example.com/fullchain.pem",
"ssl_certificate_key": "/etc/letsencrypt/live/example.com/privkey.pem"
}
}
All sites matching the wildcard pattern automatically use this certificate.
Custom SSL Certificates
For commercial or self-signed certificates:
Certificate file (.crt or .pem)
Private key file (.key)
Certificate chain/intermediate certificates (optional)
Combine certificate and chain
If you have separate certificate and chain files:
cat certificate.crt intermediate.crt > fullchain.pem
Set certificate paths for site
bench set-ssl-certificate mysite.com /path/to/fullchain.pem
bench set-ssl-key mysite.com /path/to/privkey.key
Or edit sites/mysite.com/site_config.json directly:
{
"ssl_certificate": "/path/to/fullchain.pem",
"ssl_certificate_key": "/path/to/privkey.key"
}
bench setup nginx
sudo bench setup reload-nginx
Custom domain certificates
For custom domains:
bench setup add-domain custom.example.com --site mysite.com \
--ssl-certificate /path/to/fullchain.pem \
--ssl-certificate-key /path/to/privkey.key
Certificate Renewal
Automatic renewal
Let’s Encrypt setup automatically configures a cron job for renewal:
# Runs daily at midnight
0 0 */1 * * /usr/bin/certbot renew -a nginx --post-hook "systemctl reload nginx"
View the cron job:
Manual renewal
To manually renew all certificates:
sudo bench renew-lets-encrypt
Or use Certbot directly:
sudo certbot renew
sudo systemctl reload nginx
Check certificate expiry
sudo certbot certificates
Example output:
Certificate Name: mysite.com
Domains: mysite.com
Expiry Date: 2026-06-01 12:34:56+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/mysite.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/mysite.com/privkey.pem
Or using OpenSSL:
echo | openssl s_client -servername mysite.com -connect mysite.com:443 2>/dev/null | openssl x509 -noout -dates
Testing SSL Configuration
Verify HTTPS access
curl -I https://mysite.com
Expected response:
HTTP/2 200
server: nginx
...
Check SSL certificate
openssl s_client -connect mysite.com:443 -servername mysite.com < /dev/null
Test SSL strength
Use SSL Labs for comprehensive testing:
https://www.ssllabs.com/ssltest/
Verify automatic redirect
HTTP should redirect to HTTPS:
curl -I http://mysite.com
Expected:
HTTP/1.1 301 Moved Permanently
Location: https://mysite.com/
Troubleshooting SSL Issues
Certificate verification failed
Issue: Let’s Encrypt cannot verify domain ownership
Solutions:
-
Verify DNS points to server:
-
Ensure port 80 is accessible:
sudo netstat -tlnp | grep :80
-
Check firewall:
sudo ufw status
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
-
Verify NGINX is configured correctly:
DNS multitenancy not enabled
Error: “You cannot setup SSL without DNS Multitenancy”
Solution:
bench config dns_multitenant on
bench setup nginx
sudo bench setup reload-nginx
Certificate not found
Issue: NGINX reports certificate file not found
Solution:
-
Check certificate paths:
ls -la /etc/letsencrypt/live/mysite.com/
-
Verify site_config.json paths:
cat sites/mysite.com/site_config.json
-
Ensure proper permissions:
sudo chmod 755 /etc/letsencrypt/live/
sudo chmod 755 /etc/letsencrypt/archive/
Mixed content warnings
Issue: Browser shows “Not Secure” despite SSL certificate
Solution:
Update site URL in site config:
bench --site mysite.com set-config host_name "https://mysite.com"
Clear cache:
bench --site mysite.com clear-cache
Certificate renewal fails
Issue: Automatic renewal fails
Solutions:
-
Check Certbot logs:
sudo cat /var/log/letsencrypt/letsencrypt.log
-
Test renewal in dry-run mode:
sudo certbot renew --dry-run
-
Manually renew:
sudo certbot renew --force-renewal
sudo systemctl reload nginx
NGINX fails to reload
Issue: NGINX configuration test fails
Solution:
-
Test configuration:
-
Check for syntax errors in nginx.conf:
-
Regenerate configuration:
-
Check NGINX error log:
sudo tail -f /var/log/nginx/error.log
Custom ACME Server
For staging or alternative ACME servers:
sudo bench setup lets-encrypt mysite.com --custom-server https://acme-staging-v02.api.letsencrypt.org/directory
SSL Best Practices
Force HTTPS redirect in site config:
{
"host_name": "https://mysite.com"
}
Keep certificates renewed
Monitor certificate expiry and renewal logs:
sudo tail -f /var/log/letsencrypt/letsencrypt.log
Customize NGINX SSL configuration in config/nginx.conf (advanced):
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
Periodically test SSL configuration:
Monitor certificate expiry
Set up monitoring alerts for certificates expiring soon.
Next Steps