1. The problem I’m having:
I am trying to configure Caddy as a simple file server for serving files used in automation, called by wget, Ansible, etc. When viewing the site and attempting to browse files, nothing shows up. It wasn’t until I provided world-executable permissions to directories and files under the root path for the file server that directories and files appeared when browsing. Is this expected behavior?
Additionally, I noticed that even when using the mode
option in the Caddyfile, my log file is being created using the default umask
permissions (0600) instead of the given mode of 0755, and all entries are being logged at the info
level and not debug
as directed.
2. Error messages and/or full log output:
Prior to applying world-executable permissions to all files and folders under the root file server path.
{"level":"info","ts":1750436587.2622643,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"10.20.147.66","remote_port":"52090","proto":"HTTP/1.1","method":"GET","host":"mn4s34385.nmdp.org:8080","uri":"/","headers":{"Accept-Encoding":["gzip, deflate"],"Accept-Language":["en-US,en;q=0.9"],"Upgrade-Insecure-Requests":["1"],"Connection":["keep-alive"],"Dnt":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Cookie":[]}},"user_id":"","duration":0.00345438,"size":14383,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["text/html; charset=utf-8"]}}
{"level":"info","ts":1750436743.5482035,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"10.20.147.66","remote_port":"52090","proto":"HTTP/1.1","method":"GET","host":"mn4s34385.nmdp.org:8080","uri":"/","headers":{"Connection":["keep-alive"],"Cache-Control":["max-age=0"],"Dnt":["1"],"Accept-Encoding":["gzip, deflate"],"Accept-Language":["en-US,en;q=0.9"],"Upgrade-Insecure-Requests":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Cookie":[]}},"user_id":"","duration":0.002090611,"size":14833,"status":200,"resp_headers":{"Content-Type":["text/html; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1750436756.9400399,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"10.20.147.66","remote_port":"52090","proto":"HTTP/1.1","method":"GET","host":"mn4s34385.nmdp.org:8080","uri":"/apictl/","headers":{"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Dnt":["1"],"Upgrade-Insecure-Requests":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"],"Referer":["http://mn4s34385.nmdp.org:8080/"],"Accept-Encoding":["gzip, deflate"],"Accept-Language":["en-US,en;q=0.9"],"Cookie":[],"Connection":["keep-alive"]}},"user_id":"","duration":0.001431602,"size":13292,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["text/html; charset=utf-8"]}}
Directory tree and permissions structure:
ls -laR /var/www/html/pub
/var/www/html/pub:
total 132
drwxrwsrw-. 3 caddy all 72 Jun 20 11:23 .
drwxr-xr-x. 3 root root 33 Jun 19 16:32 ..
drwxrwsrw-. 2 gmichael all 61 Jun 19 16:40 apictl
-rw-------. 1 caddy all 2560 Jun 20 11:25 caddy.log
-rwxrwxrw-. 1 caddy all 124851 Jun 20 11:17 caddy.log.1
-rwxrwxrw-. 1 gmichael all 5 Jun 20 10:19 test.txt
/var/www/html/pub/apictl:
total 12676
drwxrwsrw-. 2 gmichael all 61 Jun 19 16:40 .
drwxrwsrw-. 3 caddy all 72 Jun 20 11:23 ..
-rwxrwsrw-. 1 caddy all 12972351 Jun 19 16:35 apictl-4.4.0-linux-amd64.tar.gz
-rw-rw-r--. 1 gmichael all 5 Jun 20 10:19 test.txt
Viewing the website in my browser, I see the default view of the browse interface, 1 directory, 3 files, the filter box, the Name, Size, and Modified columns, and the apictl directory, caddy.log, caddy.log.1, and test.txt file.
Clicking into the apictl directory, I see no files, only the “Go Up” link to return to the parent directory.
After I apply world-execuable permissions to all files and directories under the root, I now see files under the apictl directory.
Logs after adding world-executable permissions:
{"level":"info","ts":1750436587.2622643,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"10.20.147.66","remote_port":"52090","proto":"HTTP/1.1","method":"GET","host":"mn4s34385.nmdp.org:8080","uri":"/","headers":{"Accept-Encoding":["gzip, deflate"],"Accept-Language":["en-US,en;q=0.9"],"Upgrade-Insecure-Requests":["1"],"Connection":["keep-alive"],"Dnt":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Cookie":[]}},"user_id":"","duration":0.00345438,"size":14383,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["text/html; charset=utf-8"]}}
{"level":"info","ts":1750436743.5482035,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"10.20.147.66","remote_port":"52090","proto":"HTTP/1.1","method":"GET","host":"mn4s34385.nmdp.org:8080","uri":"/","headers":{"Connection":["keep-alive"],"Cache-Control":["max-age=0"],"Dnt":["1"],"Accept-Encoding":["gzip, deflate"],"Accept-Language":["en-US,en;q=0.9"],"Upgrade-Insecure-Requests":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Cookie":[]}},"user_id":"","duration":0.002090611,"size":14833,"status":200,"resp_headers":{"Content-Type":["text/html; charset=utf-8"],"Server":["Caddy"]}}
{"level":"info","ts":1750436756.9400399,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"10.20.147.66","remote_port":"52090","proto":"HTTP/1.1","method":"GET","host":"mn4s34385.nmdp.org:8080","uri":"/apictl/","headers":{"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Dnt":["1"],"Upgrade-Insecure-Requests":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"],"Referer":["http://mn4s34385.nmdp.org:8080/"],"Accept-Encoding":["gzip, deflate"],"Accept-Language":["en-US,en;q=0.9"],"Cookie":[],"Connection":["keep-alive"]}},"user_id":"","duration":0.001431602,"size":13292,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["text/html; charset=utf-8"]}}
{"level":"info","ts":1750437370.7442422,"logger":"http.log.access.log0","msg":"handled request","request":{"remote_ip":"10.20.147.66","remote_port":"52346","proto":"HTTP/1.1","method":"GET","host":"mn4s34385.nmdp.org:8080","uri":"/apictl/","headers":{"Connection":["keep-alive"],"Dnt":["1"],"User-Agent":["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36"],"Accept-Encoding":["gzip, deflate"],"Upgrade-Insecure-Requests":["1"],"Accept":["text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7"],"Accept-Language":["en-US,en;q=0.9"],"Cookie":[]}},"user_id":"","duration":0.004248998,"size":14236,"status":200,"resp_headers":{"Server":["Caddy"],"Content-Type":["text/html; charset=utf-8"]}}
3. Caddy version:
caddy version
v2.6.4
4. How I installed and ran Caddy:
a. System environment:
cat /etc/os-release
NAME="Rocky Linux"
VERSION="9.5 (Blue Onyx)"
ID="rocky"
ID_LIKE="rhel centos fedora"
VERSION_ID="9.5"
PLATFORM_ID="platform:el9"
PRETTY_NAME="Rocky Linux 9.5 (Blue Onyx)"
ANSI_COLOR="0;32"
LOGO="fedora-logo-icon"
CPE_NAME="cpe:/o:rocky:rocky:9::baseos"
HOME_URL="https://rockylinux.org/"
VENDOR_NAME="RESF"
VENDOR_URL="https://resf.org/"
BUG_REPORT_URL="https://bugs.rockylinux.org/"
SUPPORT_END="2032-05-31"
ROCKY_SUPPORT_PRODUCT="Rocky-Linux-9"
ROCKY_SUPPORT_PRODUCT_VERSION="9.5"
REDHAT_SUPPORT_PRODUCT="Rocky Linux"
REDHAT_SUPPORT_PRODUCT_VERSION="9.5"
uname -a
Linux mn4s34385.nmdp.org 5.14.0-503.33.1.el9_5.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Mar 19 16:23:31 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
dnf history info 99
Transaction ID : 99
Begin time : Tue 03 Jun 2025 03:13:32 PM CDT
Begin rpmdb : 75f720491d3c37c4b3236b46603750cb175c04df51bd8a6d78bf12028b36618d
End time : Tue 03 Jun 2025 03:13:41 PM CDT (9 seconds)
End rpmdb : 06392cc2838834306dce61da5712c6fb8ffacd41ee38ff2fddca725820ffc863
User : Kyle Hakala <khakala>
Return-Code : Success
Releasever : 9
Command Line : install caddy
Comment :
Packages Altered:
Install caddy-2.6.4-2.el9.x86_64 @epel
Install rocky-logos-httpd-90.15-2.el9.noarch @rocky-9-appstream
b. Command:
sudo systemctl start caddy
sudo systemctl restart caddy
sudo caddy reload --config /etc/caddy/Caddyfile
sudo caddy validate --config /etc/caddy/Caddyfile
sudo caddy fmt --overwrite /etc/caddy/Caddyfile
c. Service/unit/compose file:
cat /usr/lib/systemd/system/caddy.service
# caddy.service
#
# For using Caddy with a config file.
#
# 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.
[Unit]
Description=Caddy web server
Documentation=https://caddyserver.com/docs/
After=network.target
[Service]
Type=notify
User=caddy
Group=caddy
ExecStartPre=/usr/bin/caddy validate --config /etc/caddy/Caddyfile
ExecStart=/usr/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/bin/caddy reload --config /etc/caddy/Caddyfile
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectHome=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
d. My complete Caddy config:
cat /etc/caddy/Caddyfile
{
debug
admin :2019 {
# origins http://*.nmdp.org http://10.20.0.0/16 http://10.151.0.0/16 http://localhost
# enforce_origin
# ideally I would like to limit sources to IPs and domains within the company
}
grace_period 10s
}
:80 {
# Set this path to your site's directory.
root * /usr/share/caddy/
# Enable the static file server.
file_server
# Another common task is to set up a reverse proxy:
# reverse_proxy localhost:8080
# Or serve a PHP site through php-fpm:
# php_fastcgi localhost:9000
# Refer to the directive documentation for more options.
# https://caddyserver.com/docs/caddyfile/directives
}
:8080 {
root * /var/www/html/pub/
file_server browse
log {
output file /var/www/html/pub/caddy.log {
roll_size 10mb
roll_keep 5
roll_local_time
mode 0755
format {
console
time_local
level debug
}
}
}
}
5. Links to relevant resources:
I have been digging through all the documentation found at the Caddy website: Welcome — Caddy Documentation