Files
merchbay_admin/TRAEFIK-SSL-CONFIG.md
Frank John Begornia 63c5c50578
Some checks failed
Deploy Development / deploy (push) Failing after 1m18s
Update domain and application URL to dev-admin.merchbay.app across deployment configurations
2025-12-16 13:33:09 +08:00

315 lines
7.5 KiB
Markdown

# Traefik SSL Configuration for MerchBay Admin
This document explains how to configure paid SSL certificates for production and automatic Let's Encrypt for development.
## Network Configuration
All deployments use the external network: `traefik-public`
```bash
# Ensure the network exists
docker network inspect traefik-public >/dev/null 2>&1 || docker network create traefik-public
```
## Development (dev-admin.merchbay.app) - Automatic SSL
Development uses Let's Encrypt for automatic SSL certificate generation.
### Traefik Configuration
Ensure your Traefik has Let's Encrypt configured:
```yaml
# traefik.yml or dynamic config
certificatesResolvers:
letsencrypt:
acme:
email: admin@merchbay.app
storage: /letsencrypt/acme.json
httpChallenge:
entryPoint: web
```
### Application Labels (Already configured in docker-compose)
```yaml
labels:
- "traefik.http.routers.merchbay-admin-dev.tls.certresolver=letsencrypt"
```
## Production (merchbay.app) - Paid SSL Certificate
Production uses a paid SSL certificate (e.g., from GoDaddy, Namecheap, Cloudflare).
### Step 1: Prepare SSL Certificate Files
You should have these files from your SSL provider:
- `merchbay.app.crt` - Certificate file
- `merchbay.app.key` - Private key file
- `ca-bundle.crt` - CA bundle (optional, for chain)
Create a combined certificate file:
```bash
# Your SSL certificates are in /srv/certs
# Verify files exist
ls -la /srv/certs/
# If you have a CA bundle, create a full chain
cd /srv/certs
cat merchbay.app.crt ca-bundle.crt > merchbay.app-fullchain.crt
# Set proper permissions
sudo chmod 600 /srv/certs/*.key
sudo chmod 644 /srv/certs/*.crt
```
### Step 2: Configure Traefik File Provider
Create a dynamic configuration file for Traefik:
```bash
sudo nano /opt/traefik/dynamic/certs.yml
```
Add:
```yaml
# /opt/traefik/dynamic/certs.yml or your Traefik dynamic config location
tls:
certificates:
- certFile: /srv/certs/merchbay.app-fullchain.crt
keyFile: /srv/certs/merchbay.app.key
stores:
- default
stores:
default:
defaultCertificate:
certFile: /srv/certs/merchbay.app-fullchain.crt
keyFile: /srv/certs/merchbay.app.key
```
### Step 3: Update Traefik docker-compose.yml
Ensure Traefik has file provider enabled and certificates mounted:
```yaml
services:
traefik:
image: traefik:v2.10
command:
- "--providers.docker=true"
- "--providers.docker.network=traefik-public"
- "--providers.file.directory=/etc/traefik/dynamic"
- "--providers.file.watch=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
# Let's Encrypt for dev
- "--certificatesresolvers.letsencrypt.acme.email=admin@merchbay.app"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /srv/certs:/srv/certs:ro
- /opt/traefik/dynamic:/etc/traefik/dynamic:ro
- traefik-letsencrypt:/letsencrypt
networks:
- traefik-public
```
### Step 4: Restart Traefik
```bash
cd /path/to/traefik
docker compose restart traefik
# Verify certificates are loaded
docker compose logs traefik | grep -i cert
```
## Application Configuration
### Development Branch (dev)
File: `docker-compose.portainer.dev.yml`
- Domain: `dev-admin.merchbay.app`
- SSL: Let's Encrypt (automatic)
- Certificate Resolver: `letsencrypt`
```yaml
labels:
- "traefik.http.routers.merchbay-admin-dev.rule=Host(`dev-admin.merchbay.app`)"
- "traefik.http.routers.merchbay-admin-dev.tls.certresolver=letsencrypt"
```
### Production Branch (main)
File: `docker-compose.portainer.yml`
- Domain: `merchbay.app`
- SSL: Paid certificate (via Traefik file provider)
- No certresolver label (uses default store)
```yaml
labels:
- "traefik.http.routers.merchbay-admin.rule=Host(`merchbay.app`)"
- "traefik.http.routers.merchbay-admin.tls=true"
# No certresolver - uses file provider certificate
```
## Gitea Secrets Configuration
### Development Secrets
```
DEV_DB_HOST=dev-mysql-host
DEV_DB_PORT=3306
DEV_DB_DATABASE=merchbay_admin_dev
DEV_DB_USERNAME=dev_user
DEV_DB_PASSWORD=dev_password
```
### Production Secrets
```
PROD_DEPLOY_HOST=prod-server-ip
PROD_DEPLOY_USER=deploy
PROD_DEPLOY_SSH_KEY=-----BEGIN RSA PRIVATE KEY-----...
PROD_DEPLOY_PORT=22
PROD_DB_HOST=prod-mysql-host
PROD_DB_PORT=3306
PROD_DB_DATABASE=merchbay_admin
PROD_DB_USERNAME=prod_user
PROD_DB_PASSWORD=prod_password
```
### Shared Secrets (if using same server)
```
DEPLOY_HOST=your-server-ip
DEPLOY_USER=deploy
DEPLOY_SSH_KEY=-----BEGIN RSA PRIVATE KEY-----...
DEPLOY_PORT=22
```
## Verification
### Check Development SSL
```bash
# Check certificate issuer (should be Let's Encrypt)
echo | openssl s_client -servername dev-admin.merchbay.app -connect dev-admin.merchbay.app:443 2>/dev/null | openssl x509 -noout -issuer
# Should show: issuer=C = US, O = Let's Encrypt, CN = R3
```
### Check Production SSL
```bash
# Check certificate issuer (should be your SSL provider)
echo | openssl s_client -servername merchbay.app -connect merchbay.app:443 2>/dev/null | openssl x509 -noout -issuer
# Should show your paid SSL provider
# Check certificate validity
echo | openssl s_client -servername merchbay.app -connect merchbay.app:443 2>/dev/null | openssl x509 -noout -dates
```
### Verify in Browser
1. Visit https://dev-admin.merchbay.app
- Certificate should be issued by "Let's Encrypt Authority X3"
2. Visit https://merchbay.com
- Certificate should be issued by your paid SSL provider
## Troubleshooting
### Development SSL Not Working
```bash
# Check Let's Encrypt logs
docker logs traefik | grep letsencrypt
# Verify acme.json permissions
ls -l /path/to/letsencrypt/acme.json
# Should be: -rw------- (600)
# Check DNS
dig dev-admin.merchbay.app +short
# Should return your server IP
```
### Production SSL Not Working
```bash
# Verify Traefik can read certificates
docker exec traefik ls -l /srv/certs/
# Check dynamic configuration is loaded
docker exec traefik cat /etc/traefik/dynamic/certs.yml
# Verify certificate format
openssl x509 -in /srv/certs/merchbay.app-fullchain.crt -text -noout
# Check private key
openssl rsa -in /srv/certs/merchbay.app.key -check
```
### Certificate Mismatch
```bash
# Verify certificate and key match
openssl x509 -noout -modulus -in /srv/certs/merchbay.app.crt | openssl md5
openssl rsa -noout -modulus -in /srv/certs/merchbay.app.key | openssl md5
# Both should output the same hash
```
## Renewing Certificates
### Development (Let's Encrypt)
Automatic renewal every 60 days. No action needed.
### Production (Paid SSL)
Before certificate expiration:
1. Download new certificate from your SSL provider
2. Update files in `/srv/certs/`
3. Restart Traefik: `docker compose restart traefik`
4. Verify: `curl -vI https://merchbay.app`
## DNS Configuration
### Development
```
Type: A
Name: dev-admin.merchbay.app
Value: YOUR_SERVER_IP
TTL: 3600
```
### Production
```
Type: A
Name: merchbay.app (or @)
Value: YOUR_SERVER_IP
TTL: 3600
Type: A
Name: www.merchbay.app
Value: YOUR_SERVER_IP
TTL: 3600
```
## Security Best Practices
1. **Keep certificates private**: Never commit SSL keys to git
2. **Use strong permissions**: 600 for private keys, 644 for certificates
3. **Monitor expiration**: Set reminders 30 days before expiration
4. **Use HSTS**: Add header after SSL is working correctly
5. **Enable OCSP stapling**: Improves SSL performance
6. **Regular updates**: Keep Traefik updated for security patches