1. The problem I’m having:
I am trying to create a home server with HTTPS enabled. I want to keep it local for now and ensure security is tight before exposing outside my LAN. I am currently using my router’s VPN to access my home network when necessary and plan to continue doing so for now.
I am running several docker containers that I want to be able to access via domain names instead of IP:PORT. Some examples include Homepage (my landing page), Filebrowser, Photoprism, and Actual Budget, as well as some native apps such as OctoPrint and Pi-Hole.
My server running on 192.168.1.9
( henry.local
). I want to access Homepage through my.home
and other containers/services through <service>.home
(for example filebrowser.home
) and all .home
sites should be HTTPS.
2. Error messages and/or full log output:
Here is my terminal output from the caddy container on dockge.
caddy_proxy | {"level":"info","ts":1726131556.945289,"logger":"http.auto_https","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443}
caddy_proxy | {"level":"info","ts":1726131556.945377,"logger":"http.auto_https","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
caddy_proxy | {"level":"info","ts":1726131556.945469,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0x2eca720"}
caddy_proxy | {"level":"info","ts":1726131556.9465542,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
caddy_proxy | {"level":"info","ts":1726131556.9472482,"msg":"failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 7168 kiB, got: 416 kiB). See https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes for details."}
caddy_proxy | {"level":"info","ts":1726131556.9477122,"logger":"http.log","msg":"server running","name":"srv0","protocols":["h1","h2","h3"]}
caddy_proxy | {"level":"info","ts":1726131556.9482114,"logger":"http.log","msg":"server running","name":"remaining_auto_https_redirects","protocols":["h1","h2","h3"]}
caddy_proxy | {"level":"info","ts":1726131556.9482703,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["my.home"]}
caddy_proxy | {"level":"info","ts":1726131556.948969,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
caddy_proxy | {"level":"info","ts":1726131556.9490278,"msg":"serving initial configuration"}
caddy_proxy | {"level":"info","ts":1726131556.949571,"logger":"tls.obtain","msg":"acquiring lock","identifier":"my.home"}
caddy_proxy | {"level":"info","ts":1726131556.9580927,"logger":"tls","msg":"storage cleaning happened too recently; skipping for now","storage":"FileStorage:/data/caddy","instance":"9248ff52-c2e7-4321-91c6-2d4544aeaf26","try_again":1726217956.9580803,"try_again_in":86399.999994296}
caddy_proxy | {"level":"info","ts":1726131556.9607337,"logger":"tls","msg":"finished cleaning storage units"}
caddy_proxy | {"level":"info","ts":1726131556.9626958,"logger":"tls.obtain","msg":"lock acquired","identifier":"my.home"}
caddy_proxy | {"level":"info","ts":1726131556.963397,"logger":"tls.obtain","msg":"obtaining certificate","identifier":"my.home"}
caddy_proxy | {"level":"info","ts":1726131556.9832873,"logger":"http","msg":"waiting on internal rate limiter","identifiers":["my.home"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":""}
caddy_proxy | {"level":"info","ts":1726131556.9835448,"logger":"http","msg":"done waiting on internal rate limiter","identifiers":["my.home"],"ca":"https://acme-v02.api.letsencrypt.org/directory","account":""}
caddy_proxy | {"level":"info","ts":1726131556.9838157,"logger":"http","msg":"using ACME account","account_id":"https://acme-v02.api.letsencrypt.org/acme/acct/1942416656","account_contact":[]}
caddy_proxy | {"level":"error","ts":1726131557.445534,"logger":"tls.obtain","msg":"could not get certificate from issuer","identifier":"my.home","issuer":"acme-v02.api.letsencrypt.org-directory","error":"HTTP 400 urn:ietf:params:acme:error:rejectedIdentifier - Invalid identifiers requested :: Cannot issue for \"my.home\": Domain name does not end with a valid public suffix (TLD)"}
caddy_proxy | {"level":"error","ts":1726131557.4457622,"logger":"tls.obtain","msg":"will retry","error":"[my.home] Obtain: [my.home] creating new order: attempt 1: https://acme-v02.api.letsencrypt.org/acme/new-order: HTTP 400 urn:ietf:params:acme:error:rejectedIdentifier - Invalid identifiers requested :: Cannot issue for \"my.home\": Domain name does not end with a valid public suffix (TLD) (ca=https://acme-v02.api.letsencrypt.org/directory)","attempt":1,"retrying_in":60,"elapsed":0.482825481,"max_duration":2592000}
caddy_proxy | {"level":"info","ts":1726131589.1122136,"msg":"shutting down apps, then terminating","signal":"SIGTERM"}
caddy_proxy | {"level":"warn","ts":1726131589.1123636,"msg":"exiting; byeee!! 👋","signal":"SIGTERM"}
caddy_proxy | {"level":"info","ts":1726131589.11242,"logger":"http","msg":"servers shutting down with eternal grace period"}
caddy_proxy | {"level":"info","ts":1726131589.113248,"logger":"tls.obtain","msg":"releasing lock","identifier":"my.home"}
caddy_proxy | {"level":"error","ts":1726131589.1134021,"logger":"tls.obtain","msg":"unable to unlock","identifier":"my.home","lock_key":"issue_cert_my.home","error":"remove /data/caddy/locks/issue_cert_my.home.lock: no such file or directory"}
caddy_proxy | {"level":"info","ts":1726131589.1134157,"logger":"admin","msg":"stopped previous server","address":"localhost:2019"}
caddy_proxy | {"level":"error","ts":1726131589.1134598,"logger":"tls","msg":"job failed","error":"my.home: obtaining certificate: context canceled"}
caddy_proxy | {"level":"info","ts":1726131589.1134803,"msg":"shutdown complete","signal":"SIGTERM","exit_code":0}
caddy_proxy | {"level":"info","ts":1726131590.5606048,"msg":"using config from file","file":"/etc/caddy/Caddyfile"}
caddy_proxy | {"level":"info","ts":1726131590.566899,"msg":"adapted config to JSON","adapter":"caddyfile"}
caddy_proxy | {"level":"warn","ts":1726131590.5670006,"msg":"Caddyfile input is not formatted; run 'caddy fmt --overwrite' to fix inconsistencies","adapter":"caddyfile","file":"/etc/caddy/Caddyfile","line":2}
caddy_proxy | {"level":"info","ts":1726131590.5704422,"logger":"admin","msg":"admin endpoint started","address":"localhost:2019","enforce_origin":false,"origins":["//localhost:2019","//[::1]:2019","//127.0.0.1:2019"]}
caddy_proxy | {"level":"info","ts":1726131590.572865,"logger":"http.auto_https","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443}
caddy_proxy | {"level":"info","ts":1726131590.5729387,"logger":"http.auto_https","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
caddy_proxy | {"level":"info","ts":1726131590.572917,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0x3a92f00"}
caddy_proxy | {"level":"info","ts":1726131590.5933208,"logger":"pki.ca.local","msg":"root certificate is already trusted by system","path":"storage:pki/authorities/local/root.crt"}
caddy_proxy | {"level":"info","ts":1726131590.5939918,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
caddy_proxy | {"level":"info","ts":1726131590.5946074,"msg":"failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 7168 kiB, got: 416 kiB). See https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes for details."}
caddy_proxy | {"level":"info","ts":1726131590.5953197,"logger":"http.log","msg":"server running","name":"srv0","protocols":["h1","h2","h3"]}
caddy_proxy | {"level":"info","ts":1726131590.5957036,"logger":"http.log","msg":"server running","name":"remaining_auto_https_redirects","protocols":["h1","h2","h3"]}
caddy_proxy | {"level":"info","ts":1726131590.5959334,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["henry.local"]}
caddy_proxy | {"level":"info","ts":1726131590.6039937,"logger":"tls","msg":"storage cleaning happened too recently; skipping for now","storage":"FileStorage:/data/caddy","instance":"9248ff52-c2e7-4321-91c6-2d4544aeaf26","try_again":1726217990.6039813,"try_again_in":86399.999995149}
caddy_proxy | {"level":"info","ts":1726131590.604572,"logger":"tls","msg":"finished cleaning storage units"}
caddy_proxy | {"level":"warn","ts":1726131590.6066906,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [henry.local]: no OCSP server specified in certificate","identifiers":["henry.local"]}
caddy_proxy | {"level":"info","ts":1726131590.6075563,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
caddy_proxy | {"level":"info","ts":1726131590.607607,"msg":"serving initial configuration"}
caddy_proxy | {"level":"info","ts":1726146590.5732336,"logger":"tls","msg":"certificate is in configured renewal window based on expiration date","subjects":["henry.local"],"expiration":1726160527,"ari_cert_id":"","next_ari_update":null,"renew_check_interval":600,"window_start":-6795364578.8713455,"window_end":-6795364578.8713455,"remaining":13936.426775922}
caddy_proxy | {"level":"info","ts":1726146590.5766523,"logger":"tls.cache.maintenance","msg":"certificate expires soon; queuing for renewal","identifiers":["henry.local"],"remaining":13936.423354988}
caddy_proxy | {"level":"info","ts":1726146590.576777,"logger":"tls.cache.maintenance","msg":"attempting certificate renewal","identifiers":["henry.local"],"remaining":13936.423229618}
caddy_proxy | {"level":"info","ts":1726146590.5781784,"logger":"tls.renew","msg":"acquiring lock","identifier":"henry.local"}
caddy_proxy | {"level":"info","ts":1726146590.5872672,"logger":"tls.renew","msg":"lock acquired","identifier":"henry.local"}
caddy_proxy | {"level":"info","ts":1726146590.5880504,"logger":"tls.renew","msg":"renewing certificate","identifier":"henry.local","remaining":13936.411975131}
caddy_proxy | {"level":"info","ts":1726146590.6089625,"logger":"tls.renew","msg":"certificate renewed successfully","identifier":"henry.local","issuer":"local"}
caddy_proxy | {"level":"info","ts":1726146590.6092935,"logger":"tls.renew","msg":"releasing lock","identifier":"henry.local"}
caddy_proxy | {"level":"info","ts":1726146590.6095135,"logger":"tls","msg":"reloading managed certificate","identifiers":["henry.local"]}
caddy_proxy | {"level":"warn","ts":1726146590.6116433,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [henry.local]: no OCSP server specified in certificate","identifiers":["henry.local"]}
caddy_proxy | {"level":"info","ts":1726146590.6117406,"logger":"tls.cache","msg":"replaced certificate in cache","subjects":["henry.local"],"new_expiration":1726189791}
caddy_proxy | {"level":"info","ts":1726158352.7093725,"msg":"shutting down apps, then terminating","signal":"SIGTERM"}
caddy_proxy | {"level":"warn","ts":1726158352.7113082,"msg":"exiting; byeee!! 👋","signal":"SIGTERM"}
caddy_proxy | {"level":"info","ts":1726158352.7114534,"logger":"http","msg":"servers shutting down with eternal grace period"}
caddy_proxy | {"level":"info","ts":1726158352.7803278,"logger":"admin","msg":"stopped previous server","address":"localhost:2019"}
caddy_proxy | {"level":"info","ts":1726158352.780431,"msg":"shutdown complete","signal":"SIGTERM","exit_code":0}
caddy_proxy | {"level":"info","ts":1726158354.5038822,"msg":"using config from file","file":"/etc/caddy/Caddyfile"}
caddy_proxy | {"level":"info","ts":1726158354.507288,"msg":"adapted config to JSON","adapter":"caddyfile"}
caddy_proxy | {"level":"warn","ts":1726158354.507352,"msg":"Caddyfile input is not formatted; run 'caddy fmt --overwrite' to fix inconsistencies","adapter":"caddyfile","file":"/etc/caddy/Caddyfile","line":2}
caddy_proxy | {"level":"info","ts":1726158354.5110712,"logger":"admin","msg":"admin endpoint started","address":"localhost:2019","enforce_origin":false,"origins":["//localhost:2019","//[::1]:2019","//127.0.0.1:2019"]}
caddy_proxy | {"level":"info","ts":1726158354.5122871,"logger":"http.auto_https","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443}
caddy_proxy | {"level":"info","ts":1726158354.5124414,"logger":"http.auto_https","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
caddy_proxy | {"level":"info","ts":1726158354.5126884,"logger":"http.auto_https","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv1"}
caddy_proxy | {"level":"info","ts":1726158354.514575,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0x33fe000"}
caddy_proxy | {"level":"info","ts":1726158354.5336854,"logger":"pki.ca.local","msg":"root certificate is already trusted by system","path":"storage:pki/authorities/local/root.crt"}
caddy_proxy | {"level":"info","ts":1726158354.5342655,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
caddy_proxy | {"level":"info","ts":1726158354.5347676,"msg":"failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 7168 kiB, got: 416 kiB). See https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes for details."}
caddy_proxy | {"level":"info","ts":1726158354.5352943,"logger":"http.log","msg":"server running","name":"srv0","protocols":["h1","h2","h3"]}
caddy_proxy | {"level":"info","ts":1726158354.5357924,"logger":"http","msg":"enabling HTTP/3 listener","addr":":8095"}
caddy_proxy | {"level":"info","ts":1726158354.5363197,"logger":"http.log","msg":"server running","name":"srv1","protocols":["h1","h2","h3"]}
caddy_proxy | {"level":"info","ts":1726158354.5367815,"logger":"http.log","msg":"server running","name":"remaining_auto_https_redirects","protocols":["h1","h2","h3"]}
caddy_proxy | {"level":"info","ts":1726158354.5368202,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["henry.local","192.168.1.9"]}
caddy_proxy | {"level":"warn","ts":1726158354.546527,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [henry.local]: no OCSP server specified in certificate","identifiers":["henry.local"]}
caddy_proxy | {"level":"info","ts":1726158354.5480087,"logger":"tls","msg":"storage cleaning happened too recently; skipping for now","storage":"FileStorage:/data/caddy","instance":"9248ff52-c2e7-4321-91c6-2d4544aeaf26","try_again":1726244754.5479994,"try_again_in":86399.999996575}
caddy_proxy | {"level":"info","ts":1726158354.54854,"logger":"tls","msg":"finished cleaning storage units"}
caddy_proxy | {"level":"info","ts":1726158354.54895,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
caddy_proxy | {"level":"info","ts":1726158354.549099,"msg":"serving initial configuration"}
caddy_proxy | {"level":"info","ts":1726158354.5498524,"logger":"tls.obtain","msg":"acquiring lock","identifier":"192.168.1.9"}
caddy_proxy | {"level":"info","ts":1726158354.5565486,"logger":"tls.obtain","msg":"lock acquired","identifier":"192.168.1.9"}
caddy_proxy | {"level":"info","ts":1726158354.5572119,"logger":"tls.obtain","msg":"obtaining certificate","identifier":"192.168.1.9"}
caddy_proxy | {"level":"info","ts":1726158354.5775676,"logger":"tls.obtain","msg":"certificate obtained successfully","identifier":"192.168.1.9","issuer":"local"}
caddy_proxy | {"level":"info","ts":1726158354.5781374,"logger":"tls.obtain","msg":"releasing lock","identifier":"192.168.1.9"}
caddy_proxy | {"level":"warn","ts":1726158354.5804136,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [192.168.1.9]: no OCSP server specified in certificate","identifiers":["192.168.1.9"]}
caddy_proxy | {"level":"info","ts":1726175754.5148356,"logger":"tls","msg":"certificate is in configured renewal window based on expiration date","subjects":["henry.local"],"expiration":1726189791,"ari_cert_id":"","next_ari_update":null,"renew_check_interval":600,"window_start":-6795364578.8713455,"window_end":-6795364578.8713455,"remaining":14036.485171135}
caddy_proxy | {"level":"info","ts":1726175754.5183706,"logger":"tls.cache.maintenance","msg":"certificate expires soon; queuing for renewal","identifiers":["henry.local"],"remaining":14036.481635506}
caddy_proxy | {"level":"info","ts":1726175754.518478,"logger":"tls.cache.maintenance","msg":"attempting certificate renewal","identifiers":["henry.local"],"remaining":14036.481528635}
caddy_proxy | {"level":"info","ts":1726175754.5297801,"logger":"tls.renew","msg":"acquiring lock","identifier":"henry.local"}
caddy_proxy | {"level":"info","ts":1726175754.5385678,"logger":"tls.renew","msg":"lock acquired","identifier":"henry.local"}
caddy_proxy | {"level":"info","ts":1726175754.5394893,"logger":"tls.renew","msg":"renewing certificate","identifier":"henry.local","remaining":14036.460535677}
caddy_proxy | {"level":"info","ts":1726175754.5601113,"logger":"tls.renew","msg":"certificate renewed successfully","identifier":"henry.local","issuer":"local"}
caddy_proxy | {"level":"info","ts":1726175754.5606391,"logger":"tls.renew","msg":"releasing lock","identifier":"henry.local"}
caddy_proxy | {"level":"info","ts":1726175754.5609908,"logger":"tls","msg":"reloading managed certificate","identifiers":["henry.local"]}
caddy_proxy | {"level":"warn","ts":1726175754.5634556,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [henry.local]: no OCSP server specified in certificate","identifiers":["henry.local"]}
caddy_proxy | {"level":"info","ts":1726175754.5635567,"logger":"tls.cache","msg":"replaced certificate in cache","subjects":["henry.local"],"new_expiration":1726218955}
3. Caddy version:
v2.8.4
4. How I installed and ran Caddy:
a. System environment:
Operating System: Raspbian GNU/Linux 11 (bullseye)
Kernel: Linux 6.1.21-v8+
Architecture: arm64
Docker Version: 26.1.1
Systemd Version: 247 (247.3-7+rpi1+deb11u2)
Pi-hole version is v5.18.3 (Latest: v5.18.3)
web version is v5.21 (Latest: v5.21)
FTL version is v5.25.2 (Latest: v5.25.2)
Octoprint Version 1.10.2
Docker Containers
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b25bcd5069d7 filebrowser/filebrowser:latest "/filebrowser" 6 hours ago Up 6 hours (healthy) 0.0.0.0:8095->80/tcp, :::8095->80/tcp filebrowser
df167647a5b1 actualbudget/actual-server:latest-alpine "/sbin/tini -g -- no…" 14 hours ago Up 14 hours 0.0.0.0:5006->5006/tcp, :::5006->5006/tcp actual-actual-1
a0bbc7621597 ghcr.io/gethomepage/homepage:latest "docker-entrypoint.s…" 15 hours ago Up 15 hours (healthy) 0.0.0.0:3000->3000/tcp, :::3000->3000/tcp homepage
5f03f2febc18 caddy:latest "caddy run --config …" 16 hours ago Up 6 hours 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp, 0.0.0.0:443->443/udp, :::443->443/udp, 2019/tcp caddy_proxy
fb112898be87 aanousakis/no-ip:latest "/scripts/start_comm…" 18 hours ago Up 18 hours no-ip-no-ip-1
cdba9c678736 photoprism/photoprism:arm64 "/scripts/entrypoint…" 20 hours ago Up 17 hours 0.0.0.0:2342->2342/tcp, :::2342->2342/tcp, 2442-2443/tcp photoprism-photoprism-1
5a4a5c654c0a containrrr/watchtower "/watchtower" 20 hours ago Up 17 hours (healthy) 8080/tcp photoprism-watchtower-1
803394bb3180 arm64v8/mariadb:11 "docker-entrypoint.s…" 20 hours ago Up 17 hours 3306/tcp photoprism-mariadb-1
829539eb70f3 louislam/dockge:latest "/usr/bin/dumb-init …" 20 hours ago Up 20 hours (healthy) 0.0.0.0:5001->5001/tcp, :::5001->5001/tcp dockge-dockge-1
b. Command:
docker compose up -d
c. Service/unit/compose file:
services:
caddy:
# Use the caddy:latest image from Docker Hub
image: caddy:latest
# Restart policy: restart the container unless explicitly stopped
restart: unless-stopped
container_name: caddy_proxy
# ports for Caddy
ports:
- 80:80
- 443:443
- 443:443/udp
volumes:
# Mount the host Caddyfile
- ./Caddyfile:/etc/caddy/Caddyfile
- ./site:/srv
- caddy_data:/data
- caddy_config:/config
# Connect the Caddy container caddy_net
networks:
- caddy_net
volumes:
# persist data caddy_data
caddy_data: null # caddy_config Docker volume
caddy_config: null
networks:
# Docker network for Caddy
caddy_net:
external: true
d. My complete Caddy config:
This is my working file that enables HTTPS for my Homepage; however, I am still getting warned by my browser that the HTTPS is not secure. When I try changing the domain or anything that is not henry.local
, it doesn’t work.
henry.local {
reverse_proxy homepage:3000
}
This is what I want to be, the desired outcome that each of these domains is HTTPS and points to the correct container.
my.home {
reverse_proxy homepage:3000
}
budget.home {
reverse_proxy actual:5006
}
photos.home {
reverse_proxy photoprism:2343
}
pihole.home {
reverse_proxy http://henry.local:8090/admin
}
henry.home {
reverse_proxy http://henry.local:8010
}
files.home {
reverse_proxy filebrowser:80
}
docker.home {
reverse_proxy dockge:5001
}
5. Links to relevant resources:
Links provided in a code block since I hit the limit (4 links for a new user).
Homepage: https://gethomepage.dev/latest/
Filebrowser: https://filebrowser.org
Photoprism: https://www.photoprism.app
Actual Budget: https://actualbudget.org
OctoPrint: https://octoprint.org
Pi-Hole: https://pi-hole.net
Dockge: https://github.com/louislam/dockge
6. Additional information
Posting here is a lot resort. I did a LOT of trial and error to get to this point and haven’t figured it out yet. Thank you so much in advance for being a part of this community! Please pardon my ignorance as I’m learning so much. I’m happy to provide additional dialogue, files, or information.
Here is my Homepage compose.yaml file as an example of how my containers are setup.
services:
homepage:
image: ghcr.io/gethomepage/homepage:latest
container_name: homepage
restart: unless-stopped
ports:
- 3000:3000
volumes:
- /home/henry/dockge/stacks/homepage:/app/config # Make sure your local config directory exists
- /data/ssd1:/app/media
- /home/henry/dockge/stacks/homepage/images:/app/public/images
- /var/run/docker.sock:/var/run/docker.sock # (optional) For docker integrations
networks:
- caddy_net
networks:
caddy_net:
external: true