How to support both Django's STATIC_URL formats in caddy

I mean:
format 1: /static/
format 2: https://static.example.com/

I did the following which worked, but it means I can only host static files on a subdomain.

CADDY_FQDN=prod.example.com
DJANGO_STATIC_URL=https://static.example.com/
DJANGO_STATIC_ROOT=/app/static-live

STAGING_CADDY_FQDN=staging.example.com
STAGING_DJANGO_STATIC_URL=https://static-staging.example.com/
STAGING_DJANGO_STATIC_ROOT=/app/static-staging-live

# {$CADDY_FQDN} {
#     proxy / django:8000 {
#         transparent
#     }
# }

# {$DJANGO_STATIC_URL} {
#     root {$DJANGO_STATIC_ROOT}
# }



# {$STAGING_CADDY_FQDN} {
#     proxy / staging-django:8000 {
#         transparent
#     }
# }

# {$STAGING_DJANGO_STATIC_URL} {
#     root {$STAGING_DJANGO_STATIC_ROOT}
# }

Client wants urls of format /static/, i.e

CADDY_FQDN=prod.example.com
DJANGO_STATIC_URL=/static/ # i.e. https://prod.example.com/static/
DJANGO_STATIC_ROOT=/app/static-live

STAGING_CADDY_FQDN=staging.example.com
STAGING_DJANGO_STATIC_URL=/static/ # i.e. https://staging.example.com/static/
STAGING_DJANGO_STATIC_ROOT=/app/staging-static-live


I tried a variation of the following conf:

{$CADDY_FQDN} {
    root {$DJANGO_STATIC_ROOT}
    proxy / django:8000 {
        transparent
        except {$DJANGO_STATIC_URL}
    }
}

but I think this is trying to find a file at /app/static-live/static/ instead of /app/static-live/

How can I get it to look in the correct directory? Do I use rewrite to rewrite paths /app/static-live/static/ to /app/static-live/

I just realized that I may be better off moving to a directory structure like DJANGO_STATIC_ROOT=/app/live/static
STAGING_DJANGO_STATIC_ROOT=/app/staging/static

Will try that now.

Changing the directory structure may work.

You can also path-scope your site addresses, e.g.

prod.example.com/static/ {
  root /app/static-live
}

https://caddyserver.com/docs/http-caddyfile#addresses

But to access stuff in that root path, the contained file contents need to match the url.

Is there a way of subtracting a prefix off so that url /static/image.png

Can exist in what is defined at root. E.g /app/static-live/image.png

Instead of having to be located at:

/app/static-live/static/image.png

For the record, I got it working by changing file structure.

I believe that for a path-scoped site prod.example.com/static/ with a root /app/static-live, a request for prod.example.com/static/foo will serve a file off the disk at /app/static-live/foo.

So, the double-up of /static/ won’t happen.

Path-scoped sites automatically strip the base path from the request for the purposes of all matchers (e.g. for rewrites and similar directives where you specify base paths) as well as from the static file server for this very reason (they don’t strip it from placeholders like {uri} and {path} though).

1 Like

This is a nice feature, isn’t it? :slight_smile:

But I know it has caused trouble, too. What do you think we should do regarding this in v2? (Sorry to derail slightly, keep the conversation going as you were!)

I think if you ever have a path-scoped root, the default behaviour should be to strip that base path for the purposes of the path of the file to serve.

Like location /foo with its own root in nginx, or example.com/foo with its own root.

I can’t think of a situation where you’d want to have a subfolder with a separate web root where you didn’t want it stripped - or perhaps more accurately, there’s no situation where having it stripped would be a problem, because you’re already specifying a web root, so you might as well make it intuitive and accurate.

TL;DR: Path matcher + specified web root = strip the matched base path (and probably document this behaviour).

1 Like