1. Caddy version (caddy version
):
Latest Docker 2-alpine
container (v2.3.0
)
2. How I run Caddy:
a. System environment:
Docker (2-alpine
)
b. Command:
Default container startup command which appears to be:
'caddy' 'run' '--config' '/etc/caddy/Caddyfile' '--adapter' 'caddyfile'
c. Service/unit/compose file:
N/A - Nextcloud and Caddy containers are managed via Portainer so no docker-compose files.
d. My complete Caddyfile or JSON config:
My initial attempt at translating the config, which is incomplete and doesn’t work (white page on request to /):
cloud.example.com {
header * {
# Remove actual server header for privacy
Server "CERN HTTPd/0.1"
# Enable cross-site filter (XSS) and tell browser to block detected attacks
X-XSS-Protection "1; mode=block"
# Disallow the site to be rendered within a frame (clickjacking protection) unless from same origin
X-Frame-Options "SAMEORIGIN"
# Prevent search engines from indexing
X-Robots-Tag "none"
# Strict transport security / force SSL
Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;"
# Remove the referrer when linking to external pages
Referrer-Policy "no-referrer"
# Other recommended headers
X-Content-Type-Options "nosniff"
X-Download-Options "noopen"
X-Permitted-Cross-Domain-Policies "none"
}
# Compression
encode zstd gzip
# Redirect well-known requests
redir /.well-known/carddav /remote.php/dav 301
redir /.well-known/caldav /remote.php/dav 301
# ?
rewrite / /index.php
# Send to FastCGI
php_fastcgi * nextcloud:9000 {
env PATH /bin
#env PATH_INFO {path}
env SCRIPT_FILENAME /var/www/html/{file}
env HTTPS on
env modHeadersAvailable true
env front_controller_active true
dial_timeout 60s
read_timeout 3600s
write_timeout 300s
}
}
3. The problem I’m having:
Nextcloud has 2 different docker containers, one of which contains Apache HTTPd to allow simply proxying HTTP requests while the other just runs FPM. Of course, the latter is lighter, and as such preferable, because I’m running on an ARM SBC. However, I’ve had some trouble getting this version to work. I read in many examples that it is necessary to make the static files visible to Caddy so that it can serve them, but I did not need to do this with NGINX, and I believe this is because Nextcloud supports serving them from the PHP script? Maybe? Anyway, I have been looking around for configuration that would work with my setup since yesterday, but to no avail (many were for Caddy v1 for example), and so, I decided it would be better to just translate my working NGINX config. Still, I have had trouble doing that also, and so decided to seek help here.
My current NGINX configuration is as follows (but I understand that some of these directives are unnecessary, such as those to do with SSL:
server {
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/letsencrypt/live/cloud.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cloud.example.com/privkey.pem;
include /etc/nginx/snippets/options-ssl-nginx.conf;
# This folder is actually blank, so this is probably unnecessary
root /usr/share/nginx/html/cloud/;
server_name cloud.example.com;
access_log /var/log/nginx/host.access.log main;
# Add headers to serve security related headers
# Before enabling Strict-Transport-Security headers please read into this
# topic first.
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
#
# WARNING: Only add the preload option once you read about
# the consequences in https://hstspreload.org/. This option
# will add the domain to a hardcoded list that is shipped
# in all major browsers and getting removed from this list
# could take several months.
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "none" always;
add_header X-XSS-Protection "1; mode=block" always;
index index.php index.html index.htm;
# Remove X-Powered-By, which is an information leak
fastcgi_hide_header X-Powered-By;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
# The following 2 rules are only needed for the user_webfinger app.
# Uncomment it if you're planning to use this app.
#rewrite ^/.well-known/host-meta /public.php?service=host-meta last;
#rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
# The following rule is only needed for the Social app.
# Uncomment it if you're planning to use this app.
#rewrite ^/.well-known/webfinger /public.php?service=webfinger last;
location = /.well-known/carddav {
return 301 $scheme://$host:$server_port/remote.php/dav;
}
location = /.well-known/caldav {
return 301 $scheme://$host:$server_port/remote.php/dav;
}
# Set max upload size
client_max_body_size 10G;
fastcgi_buffers 64 4K;
# Prevent 504 timeouts
fastcgi_send_timeout 600;
fastcgi_read_timeout 600;
# Enable gzip but do not remove ETag headers
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
# Uncomment if your server is build with the ngx_pagespeed module
# This module is currently not supported.
#pagespeed off;
location / {
rewrite ^ /index.php;
}
location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
deny all;
}
location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
deny all;
}
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) {
fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
set $path_info $fastcgi_path_info;
try_files $fastcgi_script_name =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info;
fastcgi_param HTTPS on;
# Avoid sending the security headers twice
fastcgi_param modHeadersAvailable true;
# Enable pretty urls
fastcgi_param front_controller_active true;
fastcgi_pass nextcloud:9000;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
}
location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) {
try_files $uri/ =404;
index index.php;
}
# Adding the cache control header for js, css and map files
# Make sure it is BELOW the PHP block
location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
try_files $uri /index.php$request_uri;
add_header Cache-Control "public, max-age=15778463";
# Add headers to serve security related headers (It is intended to
# have those duplicated to the ones above)
# Before enabling Strict-Transport-Security headers please read into
# this topic first.
#add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;
#
# WARNING: Only add the preload option once you read about
# the consequences in https://hstspreload.org/. This option
# will add the domain to a hardcoded list that is shipped
# in all major browsers and getting removed from this list
# could take several months.
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "none" always;
add_header X-XSS-Protection "1; mode=block" always;
# Optional: Don't log access to assets
access_log off;
}
location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap|mp4|webm)$ {
try_files $uri /index.php$request_uri;
# Optional: Don't log access to other assets
access_log off;
}
}
4. Error messages and/or full log output:
N/A
5. What I already tried:
See My Complete Caddyfile section