HTTPS Setup Guide
This guide explains how to configure HTTPS for EAS Station using nginx and Let's Encrypt.
Table of Contents
- Overview
- Architecture
- Prerequisites
- Quick Start
- Configuration Options
- Troubleshooting
- Advanced Topics
Overview
EAS Station includes built-in HTTPS support using:
- nginx - Reverse proxy server that handles SSL/TLS termination
- Let's Encrypt - Free, automated SSL certificate authority
- certbot - Automated certificate management and renewal
What This Provides
✅ Automatic HTTPS - Certificates are automatically obtained and renewed ✅ Secure by Default - Modern TLS configuration (TLS 1.2+, strong ciphers) ✅ HTTP → HTTPS Redirect - All HTTP traffic is automatically redirected to HTTPS ✅ Self-Signed Fallback - Generates self-signed certificates for development/testing ✅ Zero Configuration - Works out of the box for localhost testing
Architecture
Internet (HTTPS) → nginx (ports 80/443) → Flask App (internal port 5000)
↑
Let's Encrypt certificates
(auto-renewed by certbot)
How it works:
- nginx listens on ports 80 (HTTP) and 443 (HTTPS)
- Port 80 serves Let's Encrypt ACME challenges and redirects to HTTPS
- Port 443 terminates SSL and proxies requests to Flask on internal port 5000
- certbot runs every 12 hours to check and renew certificates (90-day validity)
- Flask application only needs to handle HTTP internally
Prerequisites
For Production Deployment (Let's Encrypt):
- ✅ Domain name - You must own a domain (e.g.,
eas.example.com) - ✅ DNS configured - Domain must point to your server's public IP address
- ✅ Port 80 accessible - Must be reachable from the internet for ACME validation
- ✅ Port 443 accessible - For HTTPS traffic
- ✅ Valid email - For Let's Encrypt certificate expiration notifications
For Development/Testing:
- ⚠️ Will use self-signed certificates (browser warnings expected)
Quick Start
Option 1: Local Testing (Self-Signed Certificate)
No configuration needed! Just deploy:
# Or using embedded database
Access your application at:
- https://localhost (⚠️ browser will show security warning - this is expected)
- HTTP traffic automatically redirects to HTTPS
Browser Security Warning:
- Click "Advanced" → "Proceed to localhost (unsafe)"
- This is safe for local testing
- Self-signed certificates are not trusted by browsers
Option 2: Production Deployment (Let's Encrypt)
Before deploying, configure your environment variables:
Step 1: Configure Environment Variables
Edit stack.env or .env:
# Your domain name (REQUIRED)
DOMAIN_NAME=eas.example.com
# Email for certificate notifications (REQUIRED)
SSL_EMAIL=admin@example.com
# Use production Let's Encrypt server
CERTBOT_STAGING=0
Step 2: Verify DNS
Ensure your domain points to your server:
# Check DNS resolution
nslookup eas.example.com
# Should return your server's public IP
Step 3: Deploy
Step 4: Verify Certificate
Check the logs:
Look for:
Successfully obtained SSL certificate
Access your application:
- https://eas.example.com (✅ secure, no warnings)
- HTTP automatically redirects to HTTPS
Configuration Options
Environment Variables
| Variable | Description | Default | Required |
|---|---|---|---|
DOMAIN_NAME |
Domain name for SSL certificate | localhost |
Yes (for production) |
SSL_EMAIL |
Email for Let's Encrypt notifications | admin@example.com |
Yes (for production) |
CERTBOT_STAGING |
Use Let's Encrypt staging server | 0 |
No |
Let's Encrypt Staging Mode
When to use staging mode:
CERTBOT_STAGING=1
✅ Use staging when:
- Testing certificate configuration
- Developing SSL features
- Avoiding production rate limits (50 certificates/week per domain)
⚠️ Staging certificates:
- Not trusted by browsers
- Show security warnings
- Good for testing automation
❌ Don't use staging for:
- Production deployments
- Public-facing sites
Rate Limits
Let's Encrypt production limits:
- 50 certificates per registered domain per week
- 5 failed validation attempts per hour
Best practices:
- Test with
CERTBOT_STAGING=1first - Switch to production only when configuration is confirmed working
- Don't delete and recreate certificates unnecessarily
Web UI Certificate Management
NEW in v2.35.0: Full SSL certificate management through the web interface - no CLI required!
Accessing the Certificate Manager
- Log in to EAS Station web interface
- Navigate to Settings → SSL Certificates (or visit
/admin/certbot) - Configure your domain and email in the Configuration tab
Obtaining a Certificate via Web UI
Step 1: Configure Settings
- Enable Certbot
- Enter your domain name (e.g.,
eas.example.com) - Enter your email address
- Choose Production or Staging mode
- Save settings
Step 2: Test Domain
- Click Test Domain to verify DNS and port 80 accessibility
- Ensure both tests pass before obtaining a certificate
Step 3: Obtain Certificate
- Click Obtain Certificate Now
- Choose acquisition method:
- Standalone (Recommended): Temporarily stops nginx, obtains cert, restarts nginx
- Nginx Plugin: No downtime, uses nginx plugin
- Webroot: Uses existing web server
- Click Obtain Certificate and wait for completion
- Real-time output shows certbot progress
Step 4: Verify
- Click Check Certificate Status to view certificate details
- Your site should now be accessible via HTTPS
Managing Certificate Renewal via Web UI
Check Renewal Status:
- Click Manage Certificate Renewal
- Click Check Auto-Renewal Status
- View systemd timer status and next run time
Manual Renewal:
- Click Manage Certificate Renewal
- Choose renewal type:
- Dry Run: Test renewal without making changes (safe)
- Normal Renewal: Only renew if certificate is expiring soon
- Force Renewal: Force renewal immediately (use with caution)
- Click Execute Renewal
- View real-time certbot output
Enable/Disable Auto-Renewal:
- Check auto-renewal status
- Click Enable Auto-Renewal or Disable Auto-Renewal
- Auto-renewal uses systemd timer (certbot.timer)
Benefits of Web UI Management
✅ No CLI Access Required - Everything through the web interface ✅ Real-Time Feedback - See certbot output as it runs ✅ Error Handling - Clear error messages with actionable guidance ✅ One-Click Operations - Obtain, renew, enable auto-renewal with clicks ✅ Safe Testing - Dry run option prevents accidental changes ✅ Status Monitoring - Check certificate validity, auto-renewal timer status
Troubleshooting
Problem: Certificate Not Obtained
Symptom: Self-signed certificate generated instead of Let's Encrypt
Check these:
DNS Resolution
nslookup $DOMAIN_NAMEShould return your server's IP
Port 80 Accessibility
curl http://$DOMAIN_NAME/.well-known/acme-challenge/testShould connect (404 is OK, connection timeout is bad)
Firewall Rules
# Check if port 80 is listening # Test from external host curl -I http://your-ip-addressCheck Logs
Common causes:
- Domain not pointing to server
- Firewall blocking port 80
- Another service using port 80
- Domain validation timeout
Problem: Browser Shows "Not Secure"
Possible causes:
Self-signed certificate (expected for localhost)
- Solution: Use a real domain name with Let's Encrypt
Certificate not installed yet
- Solution: Wait for initialization to complete
Mixed content (HTTPS page loading HTTP resources)
- Check browser console for errors
- Solution: Ensure all resources use HTTPS or relative URLs
Problem: Certificate Renewal Failed
Check:
Common causes:
- Port 80 blocked
- Domain DNS changed
- Disk full (can't write renewed certificate)
Manual renewal test:
# Test renewal (dry run)
# Force renewal
Problem: Port 80 Already in Use
Symptom:
Error: port 80 is already allocated
Find what's using the port:
sudo lsof -i :80
# or
sudo netstat -tlnp | grep :80
Solutions:
Stop conflicting service:
sudo systemctl stop apache2 # or nginx, etc. sudo systemctl disable apache2Use different port mapping:
ports: - "0.0.0.0:8080:80" # Use port 8080 for IPv4 clients - "[::]:8080:80" # Use port 8080 for IPv6 clients - "0.0.0.0:8443:443" # Use port 8443 for IPv4 clients - "[::]:8443:443" # Use port 8443 for IPv6 clients⚠️ Note: Let's Encrypt requires port 80 for validation
Advanced Topics
Custom nginx Configuration
The nginx configuration for bare-metal deployments is located at /etc/nginx/sites-available/eas-station (symlinked from config/nginx-eas-station.conf). To customize:
- Edit the configuration file:
sudo nano /etc/nginx/sites-available/eas-station - Test and reload nginx:
sudo nginx -t && sudo systemctl reload nginx
Common customizations:
Increase Upload Size Limit
# In /etc/nginx/sites-available/eas-station server block
client_max_body_size 500M; # Default is 100M
Add Custom Headers
# In /etc/nginx/sites-available/eas-station server block
add_header X-Custom-Header "value" always;
Adjust Rate Limiting
Rate limiting zones are defined in the main nginx configuration at /etc/nginx/nginx.conf within the http block. To adjust:
sudo nano /etc/nginx/nginx.conf
Find and modify:
# Inside the http block
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s; # More permissive
Then reload nginx:
sudo systemctl reload nginx
Multiple Domains
To serve multiple domains:
Edit the nginx configuration:
sudo nano /etc/nginx/sites-available/eas-stationUpdate the server_name directive:
server { listen 443 ssl http2; server_name eas1.example.com eas2.example.com; # ... rest of config }Obtain certificates for all domains:
sudo certbot --nginx -d eas1.example.com -d eas2.example.com
Using Existing Certificates
If you already have SSL certificates:
Copy your certificates to the system directory:
sudo mkdir -p /etc/letsencrypt/live/yourdomain.com sudo cp fullchain.pem /etc/letsencrypt/live/yourdomain.com/ sudo cp privkey.pem /etc/letsencrypt/live/yourdomain.com/ sudo cp chain.pem /etc/letsencrypt/live/yourdomain.com/ sudo chmod 600 /etc/letsencrypt/live/yourdomain.com/*.pemUpdate nginx configuration to point to your certificates:
sudo nano /etc/nginx/sites-available/eas-stationEnsure the SSL certificate paths are correct:
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;Reload nginx:
sudo systemctl reload nginx
Monitoring Certificate Expiration
Check certificate expiration:
# View certificate details
# Output shows:
# notBefore=...
# notAfter=...
Automatic renewal:
- certbot checks every 12 hours
- Renews certificates 30 days before expiration
- No manual intervention required
HTTPS-Only Mode
To completely disable HTTP (port 80):
Edit the nginx configuration:
sudo nano /etc/nginx/sites-available/eas-stationComment out or remove the HTTP server block (the one listening on port 80)
Reload nginx:
sudo nginx -t && sudo systemctl reload nginx
⚠️ Warning: This breaks Let's Encrypt ACME challenges. Only use if you have other certificate management or already have valid certificates.
SSL/TLS Configuration
Current configuration:
- Protocols: TLS 1.2, TLS 1.3
- Ciphers: Mozilla Intermediate compatibility
- HSTS: Enabled (63072000 seconds = 2 years)
- OCSP Stapling: Enabled
To modify, edit /etc/nginx/sites-available/eas-station:
ssl_protocols TLSv1.3; # TLS 1.3 only (more restrictive)
ssl_ciphers 'HIGH:!aNULL:!MD5'; # Different cipher suite
After changes, test and reload:
sudo nginx -t && sudo systemctl reload nginx
Test your configuration:
Security Best Practices
- Always use production certificates for public deployments
- Keep certbot updated - Done automatically with
certbot/certbot:latest - Monitor expiration - certbot sends emails 30/14/7 days before expiration
- Protect private keys - Never commit certificate files to git
- Use strong ciphers - Default configuration uses Mozilla Intermediate
- Enable HSTS - Already enabled in default config
Related Documentation
- SYSTEM_DEPENDENCIES.md - Infrastructure components
- dependency_attribution.md - nginx and certbot attribution
- PORTAINER_DEPLOYMENT.md - Deployment via Portainer
- SECURITY.md - General security guidelines
Support
Certificate not working?
- Check troubleshooting section above
- Review nginx and certbot logs
- Verify DNS and firewall configuration
Need help?
- Review this documentation
- Check project issues: https://github.com/KR8MER/eas-station/issues
Last Updated: 2025-11-09 Author: KR8MER Amateur Radio Emergency Communications
This document is served from docs/guides/HTTPS_SETUP.md in the EAS Station installation.