1. The problem I’m having:
Prefacing with the fact I use rootless Podman and utilize the Quadlet format.
I honestly think this is more of a networking question, but I can’t really come up with a viable solution. I will eventually use VLAN, but at the moment it is not possible.
I have linuxserver.io/docker-wireguard in a Podman container, and it is using Pihole as the DNS server with Unbound as the upstream DNS. Caddy is also in a container. All four of these are on the same dns.network
. Only my WireGuard instance is publicly accessible, everything else is only accessible locally.
Is it possible to have Caddy successfully reverse_proxy
requests from WireGuard’s container AND from the host machine? I scoured the documents and maybe have thought about it too hard and as a result have dug my brain into a hole, but I can’t seem to come up with a good solution.
2. Error messages and/or full log output:
Not applicable.
3. Caddy version:
v2.9.1 h1:OEYiZ7DbCzAWVb6TNEkjRcSCRGHVoZsJinoDR/n9oaY=
4. How I installed and ran Caddy:
Podman using docker.io/library/caddy
image, then using systemd --user start caddy
, although it is listening on caddy.socket
.
a. System environment:
Arch Linux using linux-hardened
kernel, x86_64
Rootless Podman
b. Command:
systemd --user enable caddy.socket
systemd --user start caddy.socket
systemd --user start caddy
c. Service/unit/compose file:
---caddy.service---
[Unit]
Wants=podman-user-wait-network-online.service
After=podman-user-wait-network-online.service
AssertPathExists=%h/.config/containers/storage/caddy/Caddyfile
SourcePath=/home/riley/.config/containers/systemd/caddy.container
RequiresMountsFor=%t/containers
Requires=dns-network.service
After=dns-network.service
Requires=vaultwarden-network.service
After=vaultwarden-network.service
Requires=ts-net-network.service
After=ts-net-network.service
Requires=immich-network.service
After=immich-network.service
Requires=radicale-network.service
After=radicale-network.service
Requires=crowdsec-network.service
After=crowdsec-network.service
RequiresMountsFor=/srv/www
[X-Container]
ContainerName=caddy
Image=docker.io/library/caddy
Exec=/usr/bin/caddy run --config /etc/caddy/Caddyfile
Environment=EMAIL=REDACTED
Environment=LOG_FILE=/data/access.log
Secret=NAMECHEAP_API_KEY,type=env,target=NAMECHEAP_API_KEY
Secret=NAMECHEAP_API_USER,type=env,target=NAMECHEAP_API_USER
Secret=CROWDSEC_API_KEY,type=env,target=CROWDSEC_API_KEY
Volume=%h/.config/containers/storage/caddy/caddy:/usr/bin/caddy
Volume=%h/.config/containers/storage/caddy/Caddyfile:/etc/caddy/Caddyfile
Volume=%h/.config/containers/storage/caddy/caddy-config:/config
Volume=%h/.config/containers/storage/caddy/caddy-data:/data
Volume=%h/.config/containers/storage/caddy/log.d:/data/log.d
Volume=/srv/www:/srv/www:ro
Notify=true
Network=dns.network
AddHost=pihole:172.17.0.5
AddHost=unbound:172.17.0.10
Network=vaultwarden.network
AddHost=vaultwarden:172.19.0.5
Network=ts-net.network
AddHost=ts3-server:172.20.0.10
Network=immich.network
AddHost=immich-infra:10.89.1.21
Network=radicale.network
AddHost=radicale:10.89.2.3
Network=crowdsec.network
[Install]
WantedBy=default.target
[Service]
Restart=always
ExecReload=/usr/bin/podman exec caddy /usr/bin/caddy reload --config /etc/caddy/Caddyfile --force
Environment=PODMAN_SYSTEMD_UNIT=%n
KillMode=mixed
ExecStop=/usr/bin/podman rm -v -f -i --cidfile=%t/%N.cid
ExecStopPost=-/usr/bin/podman rm -v -f -i --cidfile=%t/%N.cid
Delegate=yes
Type=notify
NotifyAccess=all
SyslogIdentifier=%N
ExecStart=/usr/bin/podman run --name caddy --cidfile=%t/%N.cid --replace --rm --cgroups=split --add-host pihole:172.17.0.5 --add-host unbound:
172.17.0.10 --add-host vaultwarden:172.19.0.5 --add-host ts3-server:172.20.0.10 --add-host immich-infra:10.89.1.21 --add-host radicale:10.89.2
.3 --network dns --network vaultwarden --network ts-net --network immich --network radicale --network crowdsec --sdnotify=container -d -v %h/.
config/containers/storage/caddy/caddy:/usr/bin/caddy -v %h/.config/containers/storage/caddy/Caddyfile:/etc/caddy/Caddyfile -v %h/.config/conta
iners/storage/caddy/caddy-config:/config -v %h/.config/containers/storage/caddy/caddy-data:/data -v %h/.config/containers/storage/caddy/log.d:
/data/log.d -v /srv/www:/srv/www:ro --env EMAIL=REDACTED --env LOG_FILE=/data/access.log --secret NAMECHEAP_API_KEY,type=env
,target=NAMECHEAP_API_KEY --secret NAMECHEAP_API_USER,type=env,target=NAMECHEAP_API_USER --secret CROWDSEC_API_KEY,type=env,target=CROWDSEC_AP
I_KEY docker.io/library/caddy /usr/bin/caddy run --config /etc/caddy/Caddyfile
---dns-network.service---
[X-Network]
NetworkName=dns
Subnet=172.17.0.0/16
[Install]
WantedBy=default.target
[Unit]
Wants=podman-user-wait-network-online.service
After=podman-user-wait-network-online.service
SourcePath=/home/riley/.config/containers/systemd/dns.network
RequiresMountsFor=%t/containers
[Service]
ExecStart=/usr/bin/podman network create --ignore --subnet 172.17.0.0/16 dns
SyslogIdentifier=%N
Type=oneshot
RemainAfterExit=yes
---wireguard.service---
[X-Container]
ContainerName=wireguard
AddCapability=NET_ADMIN NET_RAW SYS_MODULE
Image=lscr.io/linuxserver/wireguard:latest
Sysctl=net.ipv4.conf.all.src_valid_mark=1 net.ipv4.ip_forward=1
PublishPort=51820:51820/udp
Environment=TZ=America/Boise
Environment=SERVERURL=wireguard.famdam.top
Environment=SERVERPORT=51820
Environment=PEERS=kodiephone,rileyphone
Environment=PEERDNS=172.17.0.5
Environment=INTERNAL_SUBNET=172.18.0.0/24
Environment=ALLOWEDIPS=0.0.0.0/0
Environment=PERSISTENTKEEPALIVE_PEERS=all
Environment=UMASK=022
#Environment=LOG_CONFS=true
Volume=%h/.config/containers/storage/wireguard:/config
Volume=/lib/modules:/lib/modules
Network=dns.network
IP=172.17.0.15
[Install]
WantedBy=default.target
[Unit]
Wants=podman-user-wait-network-online.service
After=podman-user-wait-network-online.service
SourcePath=/home/riley/.config/containers/systemd/wireguard.container
RequiresMountsFor=%t/containers
Requires=dns-network.service
After=dns-network.service
RequiresMountsFor=/lib/modules
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
KillMode=mixed
ExecStop=/usr/bin/podman rm -v -f -i --cidfile=%t/%N.cid
ExecStopPost=-/usr/bin/podman rm -v -f -i --cidfile=%t/%N.cid
Delegate=yes
Type=notify
NotifyAccess=all
SyslogIdentifier=%N
ExecStart=/usr/bin/podman run --name wireguard --cidfile=%t/%N.cid --replace --rm --cgroups=split --ip 172.17.0.15 --network dns --sdnotify=conmon -d --cap-add net_admin --cap-add net_raw --cap-add sys_module --sysctl net.ipv4.conf.all.sr
c_valid_mark=1 --sysctl net.ipv4.ip_forward=1 -v %h/.config/containers/storage/wireguard:/config -v /lib/modules:/lib/modules --publish 51820:
51820/udp --env ALLOWEDIPS=0.0.0.0/0 --env INTERNAL_SUBNET=172.18.0.0/24 --env PEERDNS=172.17.0.5 --env PEERS=kodiephone,rileyphone --env PERS
ISTENTKEEPALIVE_PEERS=all --env SERVERPORT=51820 --env SERVERURL=wireguard.famdam.top --env TZ=America/Boise --env UMASK=022 lscr.io/linuxserv
er/wireguard:latest
---pihole.service---
[X-Container]
ContainerName=pihole
Image=pihole/pihole:latest
Environment=FTLCONF_dns_listeningMode=all
Environment=TZ=America/Boise
Environment=WEBTHEME=default-dark
Environment=FTLCONF_dns_upstreams="172.17.0.10#5335"
Secret=pihole-pass,type=env,target=FTLCONF_webserver_api_password
PublishPort=53:53/tcp
PublishPort=53:53/udp
Network=dns.network
AddHost=unbound:172.17.0.10
IP=172.17.0.5
Volume=%h/.config/containers/storage/pihole/etc-pihole:/etc/pihole
[Install]
WantedBy=default.target
[Service]
Restart=always
Environment=PODMAN_SYSTEMD_UNIT=%n
KillMode=mixed
ExecStop=/usr/bin/podman rm -v -f -i --cidfile=%t/%N.cid
ExecStopPost=-/usr/bin/podman rm -v -f -i --cidfile=%t/%N.cid
Delegate=yes
Type=notify
NotifyAccess=all
SyslogIdentifier=%N
ExecStart=/usr/bin/podman run --name pihole --cidfile=%t/%N.cid --replace --rm --cgroups=split --ip 172.17.0.5 --add-host unbound:172.17.0.10
--network dns --sdnotify=conmon -d -v %h/.config/containers/storage/pihole/etc-pihole:/etc/pihole --publish 53:53/tcp --publish 53:53/udp --en
v FTLCONF_dns_listeningMode=all --env FTLCONF_dns_upstreams=172.17.0.10#5335 --env TZ=America/Boise --env WEBTHEME=default-dark --secret pihol
e-pass,type=env,target=FTLCONF_webserver_api_password pihole/pihole:latest
[Unit]
Wants=podman-user-wait-network-online.service
After=podman-user-wait-network-online.service
SourcePath=/home/riley/.config/containers/systemd/pihole.container
RequiresMountsFor=%t/containers
Requires=dns-network.service
After=dns-network.service
d. My complete Caddy config:
I did redact anything entirely not relevant to said services.
Caddyfile
{
debug
crowdsec {
api_url http://crowdsec:8080
api_key {env.CROWDSEC_API_KEY}
}
dynamic_dns {
provider namecheap {
api_key {env.NAMECHEAP_API_KEY}
user {env.NAMECHEAP_API_USER}
}
domains {
famdam.top @
}
versions ipv4
}
acme_dns namecheap {
api_key {env.NAMECHEAP_API_KEY}
user {env.NAMECHEAP_API_USER}
api_endpoint https://api.namecheap.com/xml.response
}
}
pihole.famdam.top {
bind fd/3 {
protocols h1
}
bind fd/4 {
protocols h1 h2
}
bind fdgram/5 {
protocols h3
}
log {
output file /data/log.d/pihole.log {
roll_local_time
mode 644
roll_keep_for 48h
}
}
reverse_proxy pihole:80
encode zstd gzip
}