Caddyfile for Django API and SPA

1. Caddy version (caddy version):

v2.1.1

2. How I run Caddy:

Caddy is run as a system unit.

a. System environment:

Ubuntu 20.04

b. Command:

./caddy validate Caddyfile
sudo systemctl restart caddy

d. My complete Caddyfile or JSON config:

mydomain.com {
    log {
        output stdout
        level DEBUG
    }
    reverse_proxy /admin* 127.0.0.1:8000
    reverse_proxy /api* 127.0.0.1:8000

    file_server /static/* {
        root /path/to/back
    }

    file_server /media/* {
        root /path/to/back
    }

    try_files {path} /index.html
    file_server /* {
        root /path/to/front/dist
    }
}

3. The problem I’m having:

I’m serving both a Django API and a SPA. I’m trying to use try_files directive (similar to what I used in Nginx) but failing at finding the proper configuracion.

5. What I already tried:

Initially I had this configuration:

...
    file_server /* {
        root /path/to/front/dist
    }

which works ok for mydomain.com but cannot load mydomain.com/team. So I’m trying to change it to serve the SPA correctly.

I’ve tried other modifications (apart from the shown in the d section) in the Caddyfile like:

try_files {path} /index.html
root /* /path/to/front/dist

or

try_files {path} /index.html
root /* /path/to/front/dist
file_server

The configuration seems fine (it validates), but I cannot reach mydomain.com/team which is expected.

Thank you for your help!

Me again! After pairing with a colleague, we found this answer which was helpful. I’ll let here the final configuration that works:

mydomain.com {
    log {
        output stdout
        level DEBUG
    }
    
    root /static/* /path/to/back
    root /media/* /path/to/back
    root * /path/to/front/dist
    
    route {
        reverse_proxy /admin* 127.0.0.1:8000
        reverse_proxy /api* 127.0.0.1:8000
        try_files {path} {path}/ /index.html
        file_server
    }
}
2 Likes

Glad you figured it out!

FYI, it’s very slightly more efficient to use root * /path/to/front/dist rather than /* because /* is a path matcher which will always match, whereas * will just match every request without doing a path comparison.

Thanks for your tip! I’ll add it to the solution, should anyone copy and paste it.

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