Forbidden with `file_server` despite correct permissions

1. Caddy version (caddy version):


2. How I run Caddy:

a. System environment:

Debian with systemd.

b. Command:

I do not use any command.

c. Service/unit/compose file:

# caddy.service
# For using Caddy with a config file.
# Make sure the ExecStart and ExecReload commands are correct
# for your installation.
# See for instructions.
# WARNING: This service does not use the --resume flag, so if you
# use the API to make changes, they will be overwritten by the
# Caddyfile next time the service is restarted. If you intend to
# use Caddy's API to configure it, add the --resume flag to the
# `caddy run` command or use the caddy-api.service file instead.


ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile


d. My complete Caddyfile or JSON config: {
    encode zstd gzip

    handle /download/* {
        uri strip_prefix /download
        root * /var/lib/transmission-daemon/downloads
        file_server browse

    basicauth {
        # credentials

3. The problem I’m having:

When browsing /download/ page, I can see the Transmission downloads. However, when I click on a downloaded file, I have a 403 error.

4. Error messages and/or full log output:

I do not see any log in journalctl.

5. What I already tried:

Transmission is configured so that downloaded torrents are readable by debian-transmission group and caddy user is in debian-transmission group.

I have check the torrents have correct permissions:

ls -l /var/lib/transmission-daemon/downloads
-rw-r----- 1 debian-transmission debian-transmission         7 20 mai   03:05 mytorrent

I have checked that caddy can access the file:

sudo -u caddy cat /var/lib/transmission-daemon/downloads/mytorrent

Making the torrents world readable fixes the issue but I don’t want to have my torrents world readable.

6. Links to relevant resources:

You can shorten this to just handle_path /download/* { btw. The handle_path directive has built-in strip_prefix logic, so it saved you a line.

Add this at the top of your Caddyfile to see additional information about potential issues in your logs:


Did you try adding the caddy user to the debian-transmission group?

1 Like

Thank you for the handle_path directive, I was not aware of it, it will save one line… but in a lot of files!

With debug enabled, I have those lines:

{"level":"debug","ts":1621520919.3390122,"logger":"http.handlers.rewrite","msg":"rewrote request","request":{"remote_addr":"","proto":"HTTP/1.1","method":"GET","host":"","uri":"/download/","headers":{"User-Agent":["MyUserAgent"],"Accept-Encoding":["gzip, deflate, br"],"Authorization":["***CREDENTIALS***"],"Upgrade-Insecure-Requests":["1"],"X-Forwarded-Proto":["https"],"Accept":["text/html"],"Accept-Language":["fr"],"Te":["trailers"],"X-Forwarded-For":[""]}},"method":"GET","uri":"/"}
{"level":"debug","ts":1621520919.3391666,"logger":"http.handlers.file_server","msg":"sanitized path join","site_root":"/var/lib/transmission-daemon/downloads","request_path":"/","result":"/var/lib/transmission-daemon/downloads"}
{"level":"debug","ts":1621520919.3393222,"logger":"http.handlers.file_server","msg":"no index file in directory","path":"/var/lib/transmission-daemon/downloads","index_filenames":["index.html","index.txt"]}
{"level":"debug","ts":1621520919.3393741,"logger":"http.handlers.file_server","msg":"browse enabled; listing directory contents","path":"/var/lib/transmission-daemon/downloads","root":"/var/lib/transmission-daemon/downloads"}
{"level":"debug","ts":1621520922.3969133,"logger":"http.handlers.rewrite","msg":"rewrote request","request":{"remote_addr":"","proto":"HTTP/1.1","method":"GET","host":"","uri":"/download/mytorrent","headers":{"Accept":["text/html"],"Accept-Language":["fr"],"Authorization":["***CREDENTIALS***"],"Te":["trailers"],"Upgrade-Insecure-Requests":["1"],"X-Forwarded-For":[""],"X-Forwarded-Proto":["https"],"User-Agent":["MyUserAgent"],"Accept-Encoding":["gzip, deflate, br"]}},"method":"GET","uri":"/mytorrent"}
{"level":"debug","ts":1621520922.3970568,"logger":"http.handlers.file_server","msg":"sanitized path join","site_root":"/var/lib/transmission-daemon/downloads","request_path":"/mytorrent","result":"/var/lib/transmission-daemon/downloads/mytorrent"}
{"level":"debug","ts":1621520922.3971844,"logger":"http.handlers.file_server","msg":"opening file","filename":"/var/lib/transmission-daemon/downloads/mytorrent"}
{"level":"debug","ts":1621520922.3972888,"logger":"http.handlers.file_server","msg":"permission denied","filename":"/var/lib/transmission-daemon/downloads/mytorrent","error":"open /var/lib/transmission-daemon/downloads/mytorrent: permission denied"}

Yes caddy is already in debian-transmission group (which is why sudo -u caddy cat /var/lib/transmission-daemon/downloads/mytorrent works).

There might be some SELinux policies at play or something like that. I couldn’t really say with certainty. But this seems more like a Linux problem than a Caddy problem :thinking:

OK thank you for your help.
I checked and SELinux is not installed on the server. Do you know any similar tool so that I can search for it?

I believe you need to set the execute permission on the /var/lib/transmission-daemon/downloads/mytorrent directory. Basically you have to do chmod g+x /var/lib/transmission-daemon/downloads/mytorrent.

@Mohammed90 execute permission is not required because adding only read permission for everyone is enough.

I have actually found the issue just now: the problem was that I did not restarted the Caddy service after adding caddy to debian-transmission group. As such, the caddy user running caddy was not in the debian-transmission group when the service was started and then does not have access to the debian-transmission group. Restarting the caddy service after modifying the groups of the caddy user is mandatory for the changes to be effective.

Thank you all for your help

1 Like

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