Caddy Reverse Proxy
TriviaFlow uses Caddy as its production web server. It acts as a Reverse Proxy that sits in front of the application containers.
We chose Caddy for two specific reasons:
- Automatic HTTPS: It automatically obtains and renews SSL certificates from Let's Encrypt.
- Performance: It serves static files (Images, CSS, JS) directly, relieving the Python application from this task.
Configuration Overview
The configuration is located in the Caddyfile at the root of your project. This file maps your domains to the internal Docker services.
Main Application Block
This block controls the main game interface.
quiz.your-domain.com {
# 1. Static Files (Performance)
# Serves CSS/JS directly from the disk, bypassing Python.
handle_path /static/* {
root * /srv/static
file_server
}
# 2. Media Uploads (Images)
# Serves uploaded quiz images.
handle_path /media/* {
root * /srv/media
file_server
}
# 3. Application Proxy
# Forwards all other requests (WebSockets, HTML) to Django.
reverse_proxy web:8000
}
Database Admin Block (Optional)
If you want to use a graphical interface to manage your database (phpMyAdmin):
# db.your-domain.com {
# reverse_proxy phpmyadmin:80
# }
Security Tip: It is recommended to keep this disabled or protected when not in use.
How It Works
Automatic HTTPS (SSL)
When you start the container, Caddy will attempt to contact Let's Encrypt to generate a certificate for the domains listed in the Caddyfile.
- Requirement: Your DNS records must point to the server before you start Caddy.
- Storage: Certificates are stored in a Docker volume (
caddy_data), so they persist even if you restart the container.
Static File Serving
In a production Django environment, the application server (Daphne/Gunicorn) should not serve static files.
- When you run the container,
python manage.py collectstaticruns automatically. - It copies all CSS/JS files to a shared volume (
static_volume). - Caddy mounts this volume and serves files starting with
/static/directly to the user.
Troubleshooting
If your site is not reachable via HTTPS, check the Caddy logs:
docker compose logs caddy
Common Errors:
- "Challenge failed": Usually means your DNS A-Record is incorrect or hasn't propagated yet.
- "Connection refused": The Python container (
web) might be crashing. Checkdocker compose logs web.