Using Caddy to create a secure local network

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

Howdy @amanger, welcome to the Caddy community.

You might have a minor misunderstanding of what HTTPS is and how it works in your browser. HTTPS is designed to achieve two specific goals:

  • Encrypt communication between the client and the server (prevent snooping)
  • Provide a level of guarantee to the client that the server is who it says it is (prevent impostors)

So, when you have this popping up:

What’s happening is that you’ve achieved the first part (encryption) but not the second part (server validation).

This is because .local is not an internet top-level domain - in fact, it’s explicitly reserved to never be used as an internet TLD and is instead used in LAN contexts for mDNS. .home is also not valid as it was never actually approved to become a generic TLD.

That means no PUBLIC trust chain can be established for these TLDs because no publicly trusted certificate authority will issue a HTTPS certificate for these domains that a browser would trust automatically. That means Caddy has to issue its own certificate via its own local, not-publicly-trusted certificate authority.

Since you can’t get publicly valid certificates, you have two options left:

  • Tell your browser to accept an invalid certificate whenever you browse to the site.
  • Install Caddy’s private certificate authority on each computer/browser/client you intend to access your site to establish a private trust chain.

Alternatively, acquire a public domain name and configure Caddy to acquire valid certificates for it via ACME.

As for this:

When you try henry.home, Caddy doesn’t actually know about what I mentioned above (about .home not actually being a real TLD).

This is because we don’t maintain a hard-coded list of what TLDs are public and valid in Caddy itself, because that is a bit fraught with problems. Instead, Caddy knows a specific short list of domains which are always local (like .local, .localhost, etc) and simply assumes that anything else that looks sufficiently like a public domain name must in fact be a public domain name.

As a result, for henry.home, Caddy tries to reach out to an ACME provider and is promptly rebuffed because the ACME provider does know that .home isn’t valid.

If you want Caddy to issue a private certificate for .home you’ll need to specify tls internal on those sites.

2 Likes

@Whitestrake Thank you a hundred times! You are LEGENDARY.

The first part related to the server validation makes complete sense. As long as the connection is encrypted, I’m good!

As for the second part of your reply, I took your advise as well as that of others and switched to using subdomain.home.arpa. I mapped all of my desired subdomains (ex. my.home.arpa) to 192.168.1.9 using Pi-Hole’s Local DNS then added tls internal to each entry in the Caddyfile and now everything works great! Thank you so much!

1 Like

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