The bench setup lets-encrypt command automatically obtains and configures free SSL certificates from Let’s Encrypt for your Frappe sites.
This command requires sudo privileges and temporarily stops NGINX during certificate generation, causing brief downtime.
Usage
sudo bench setup lets-encrypt [SITE] [OPTIONS]
Arguments
The site name to set up SSL for.Must be an existing site in your bench.
Options
Set up SSL for a specific custom domain instead of the site name.The domain must already be added to the site.
Custom ACME server URL for certificate authority.Useful for testing with Let’s Encrypt staging server.
Run command non-interactively without prompts.Automatically restarts NGINX and runs certbot without interaction.Warning: Only use after first successful setup, as certbot may need manual DNS verification initially.
Prerequisites
DNS Configuration
Your domain must be properly configured in DNS and pointing to your server before running this command.
- Domain DNS A record must point to your server’s IP
- DNS propagation must be complete (check with
nslookup your-domain.com)
- Port 80 must be open and accessible from the internet
Multi-Tenant Mode
SSL setup requires DNS multi-tenancy:
// sites/common_site_config.json
{
"dns_multitenant": true
}
Certbot Installation
Certbot must be installed:
Ubuntu/Debian:
sudo apt-get install certbot
CentOS/RHEL:
Examples
Basic SSL Setup
Set up SSL for your main site:
sudo bench setup lets-encrypt site1.local
You’ll be prompted to:
- Confirm NGINX will be stopped temporarily
- Accept Let’s Encrypt Terms of Service
- Provide an email address for renewal notifications
SSL for Custom Domain
If your site has a custom domain:
# First add the domain
bench setup add-domain example.com --site site1.local
# Then set up SSL for it
sudo bench setup lets-encrypt site1.local --custom-domain example.com
Non-Interactive Mode
For automated scripts or renewals:
sudo bench setup lets-encrypt site1.local --non-interactive
Staging Environment
Test with Let’s Encrypt staging server (doesn’t count against rate limits):
sudo bench setup lets-encrypt site1.local \
--custom-server https://acme-staging-v02.api.letsencrypt.org/directory
What It Does
Verify DNS Multitenant
Checks that dns_multitenant is enabled in bench configuration.
Create Certbot Config
Generates Let’s Encrypt configuration file:/etc/letsencrypt/configs/[domain].cfg
Stop NGINX
Temporarily stops NGINX to free port 80 for certbot’s standalone authenticator.
Obtain Certificate
Runs certbot to obtain SSL certificate from Let’s Encrypt.Certbot uses HTTP challenge to verify domain ownership.
Update Site Config
Adds SSL certificate paths to site configuration:{
"ssl_certificate": "/etc/letsencrypt/live/domain/fullchain.pem",
"ssl_certificate_key": "/etc/letsencrypt/live/domain/privkey.pem"
}
Regenerate NGINX Config
Updates NGINX configuration to include SSL settings.
Start NGINX
Restarts NGINX with new SSL configuration.
Setup Auto-Renewal
Creates a cron job to automatically renew certificates monthly:0 0 */1 * * certbot renew -a nginx --post-hook "systemctl reload nginx"
Certificate Files
Location
Certificates are stored in:
/etc/letsencrypt/live/[domain]/
├── fullchain.pem # Certificate + intermediate chain
├── privkey.pem # Private key
├── cert.pem # Certificate only
└── chain.pem # Intermediate chain only
Permissions
Certificate files are owned by root with restricted permissions:
ls -l /etc/letsencrypt/live/example.com/
# -rw-r--r-- root root fullchain.pem
# -rw-r--r-- root root privkey.pem
Automatic Renewal
Renewal Cron Job
The command sets up automatic renewal at midnight daily:
# View cron job
sudo crontab -l
# Output:
0 0 */1 * * certbot renew -a nginx --post-hook "systemctl reload nginx"
Manual Renewal
Test renewal before expiration:
sudo certbot renew --dry-run
Force renewal (certificates must be within 30 days of expiration):
sudo certbot renew --force-renewal
sudo systemctl reload nginx
Renewal Logs
Check renewal logs:
sudo tail -f /var/log/letsencrypt/letsencrypt.log
Multiple Sites
Set up SSL for multiple sites:
sudo bench setup lets-encrypt site1.local
sudo bench setup lets-encrypt site2.local
sudo bench setup lets-encrypt site3.local
Each site gets its own certificate.
Wildcard SSL
For wildcard certificates (*.example.com):
Note: Wildcard certificates require DNS challenge (not HTTP), so you’ll need to manually add TXT records.
Troubleshooting
Error: “You cannot setup SSL without DNS Multitenancy”
Solution:
# Enable DNS multitenant
bench config dns_multitenant true
# Regenerate NGINX config
bench setup nginx --yes
# Try again
sudo bench setup lets-encrypt site1.local
Domain Not Reachable
Error: “Failed authorization procedure”
Diagnosis:
# Check DNS
nslookup site1.local
# Test port 80 accessibility
curl -I http://site1.local
# Check firewall
sudo ufw status
Solutions:
- Verify DNS A record points to server IP
- Ensure port 80 is open in firewall
- Check that domain is accessible from internet
Rate Limit Exceeded
Let’s Encrypt has rate limits:
- 50 certificates per registered domain per week
- 5 duplicate certificates per week
Solution:
Use staging server for testing:
sudo bench setup lets-encrypt site1.local \
--custom-server https://acme-staging-v02.api.letsencrypt.org/directory
Certificate Already Exists
Error: “SSL for Domain already exists”
Solution:
Certificate is already configured. To renew:
sudo certbot renew --force-renewal
sudo bench setup nginx --yes
sudo systemctl reload nginx
NGINX Won’t Start
After SSL setup, if NGINX fails:
# Test NGINX config
sudo nginx -t
# Check certificate paths
cat sites/site1.local/site_config.json
# Verify certificates exist
sudo ls -l /etc/letsencrypt/live/site1.local/
# Regenerate NGINX config
bench setup nginx --yes
sudo nginx -t
sudo systemctl restart nginx
Security Best Practices
HTTPS Redirect
NGINX automatically redirects HTTP to HTTPS when SSL is configured.
Add HSTS header for enhanced security:
# Add to NGINX config
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Certificate Monitoring
Monitor certificate expiration:
# Check expiration date
sudo certbot certificates
# Output shows:
# Expiry Date: 2024-06-01 12:00:00+00:00 (VALID: 89 days)
Renewal Notifications
Let’s Encrypt sends email reminders before expiration to the email provided during setup.
Source Code
Implementation: bench/config/lets_encrypt.py:18
Command definition: bench/commands/setup.py:158