Nginx location proxy_pass conversion

1. Caddy version (caddy version):


2. How I run Caddy:


a. System environment:

Docker Compose with a .env file, which provides {$MY_DOMAIN}

b. Command:

docker-compose up -d

c. Service/unit/compose file:

    image: caddy
    container_name: caddy
    restart: unless-stopped
      - "80:80"
      - "443:443"
      - MY_DOMAIN
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
      - caddy_config:/config
      - caddy_logs:/var/log/caddy
      - "commstack"

d. My complete Caddyfile or JSON config:

bookwyrm.{$MY_DOMAIN} {
	import logging
	import hsts
	handle / {
		reverse_proxy bookwyrm_web_1:8000
	handle /images/* {
		reverse_proxy bookwyrm_nginx_1:8001
	handle /static/* {
		reverse_proxy bookwyrm_nginx_1:8001

3. The problem I’m having:

Really i’m just looking for help converting this nginx block into Caddy:

server {
    listen [::]:443 ssl http2;
    listen 443 ssl http2;

    server_name your.domain;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    location / {
        proxy_pass http://localhost:8000;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;

    location /images/ {
        proxy_pass http://localhost:8001;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;

    location /static/ {
        proxy_pass http://localhost:8001;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;

Trying to run a docker-compose stack which has two web servers - nginx and gunicorn. Everything proxies through the domain name and the root is served by the nginx container, but certain paths ($DOMAIN/images/* and $DOMAIN/static/*) go through the gunicorn container.

I can get content served through the main, nginx, container, but can’t get the /images/ and /static/ to serve, through the gunicorn server.

The Caddy container and the bookwyrm stack are in two different compose files, but in the same network.

4. Error messages and/or full log output:

No error messages

5. What I already tried:

Multiple variations of the above caddyfile, i.e. breaking the two docker containers into their own caddy sections, path vs. path_handle, &c.

6. Links to relevant resources:

the Reverse Proxy section of the docker stack i’m trying to serve - Using a Reverse-Proxy - BookWyrm Documentation

In Caddy, request matching is exact, so / will only match exactly / and nothing else. Omit the matcher (or use *, which omitting is the same as) to match all requests. Only the first matching handle block will be executed (due to handle's mutual-exclusivity property).

You might need to try handle_path for these instead of handle. I think Nginx strips the path from the request with location blocks, and Caddy’s handle does not. But handle_path does have path prefix stripping behaviour.

Are you sure? If there’s a problem, Caddy’s logs would say so. Check the container’s logs with docker-compose logs caddy.

Make sure to enable the debug global option to get more detailed information.


Thanks for the help, Francis!
After enabling debug and digging through the logs some more, i realized that everything was routing more or less as i had told it to, hence the lack of errors, but none of that was the correct routing path. I had wildly misunderstood what the dev was doing with the gunicorn/nginx combo and the example config in the docs, and with a slightly more critical look at the two, realized that i don’t actually need to approach the gunicorn server at all. It’s just a straightforward reverse_proxy into the nginx container.

Thanks again for your time!

1 Like

This topic was automatically closed after 30 days. New replies are no longer allowed.