Skip to main content

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:

  1. Automatic HTTPS: It automatically obtains and renews SSL certificates from Let's Encrypt.
  2. 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.

  1. When you run the container, python manage.py collectstatic runs automatically.
  2. It copies all CSS/JS files to a shared volume (static_volume).
  3. 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. Check docker compose logs web.