# BookWyrm + Caddy: Static Files Fix **Caddy is proxying directly to Gunicorn**, which doesn't serve static files. It returns HTML for every `/static/` request, and the browser blocks it due to MIME type mismatch. The fix is to add a small nginx container between Caddy and Gunicorn. nginx serves `/static/` and `/images/` straight from the Docker volumes, and passes everything else to Gunicorn. ## 1. Add the nginx config Create nginx-books/nginx.conf next to your docker-compose.yml]: ```nginx upstream bookwyrm { server bookwyrm-web:8000; } server { listen 80; client_max_body_size 10M; location /static/ { alias /app/static/; } location /images/ { alias /app/images/; } location / { proxy_pass http://bookwyrm; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_set_header X-Forwarded-Proto https; proxy_redirect off; } } ``` ## 2. Add the nginx service to docker-compose.yml ```yaml bookwyrm-nginx: image: nginx:alpine restart: unless-stopped depends_on: - bookwyrm-web volumes: - ./nginx-books/nginx.conf:/etc/nginx/conf.d/default.conf:ro - bookwyrm_static:/app/static:ro - bookwyrm_media:/app/images:ro ``` Make sure it's on the same Docker network as your other BookWyrm containers. ## 3. Update Caddy to point at nginx, not Gunicorn ``` books.yourdomain.com { reverse_proxy bookwyrm-nginx:80 } ``` Instead of `bookwyrm-web:8000`. ## 4. Restart everything ```bash docker compose up -d ``` If Caddy seems to be ignoring the new config, `caddy reload` doesn't always apply changes. Do a full restart instead: ```bash docker compose up -d --force-recreate caddy ``` ## One gotcha: celery-beat needs EMAIL_HOST BookWyrm's settings require `EMAIL_HOST` even for containers that never send email (like `celery-beat`). Pass the full email env block to all BookWyrm containers or beat will crash on startup.