1. The problem I’m having:
I want specific subdomains to be either IPv4 or IPv6 only.
My overall goal is that I run a service that relies on the X-Forwarded-For header to show the client’s IP address. My server has both IPv4 and IPv6, but Caddy always forwards the IPv6 address when it’s available. I need to be able to access the client’s IPv4 as well, without disabling IPv6 entirely. So I want to make dedicated v4/v6 subdomains but I don’t know how…
2. Error messages and/or full log output:
I can’t provide logs for it, since I can’t figure out how can I even do this. Currently everything responds to both v4 and v6.
3. Caddy version:
caddy version
v2.10.0 h1:fonubSaQKF1YANl8TXqGcn4IbIRUDdfAkpcsfI/vX5U=
4. How I installed and ran Caddy:
I used xcaddy to build it with caddy-l4 and caddy-dns/cloudflare.
xcaddy build --with github.com/caddy-dns/cloudflare --with github.com/mholt/caddy-l4
a. System environment:
Debian 12 & 6.1.0-37-amd64, with systemd-- no docker.
Domain: (*.)albert.lol
b. Command:
c. Service/unit/compose file:
cat /lib/systemd/system/caddy.service
[Unit]
Description=Caddy
Documentation=https://caddyserver.com/docs/
After=network.target network-online.target
Requires=network-online.target
[Service]
Type=notify
User=caddy
Group=caddy
ExecStart=/usr/local/bin/caddy run --environ --config /etc/caddy/Caddyfile
ExecReload=/usr/local/bin/caddy reload --config /etc/caddy/Caddyfile --force
TimeoutStopSec=5s
LimitNOFILE=1048576
LimitNPROC=512
PrivateTmp=true
ProtectSystem=full
AmbientCapabilities=CAP_NET_BIND_SERVICE
Environment="CLOUDFLARE_API_KEY=REDACTED"
Restart=on-failure
RestartSec=5s
d. My complete Caddy config:
caddy fmt /etc/caddy/Caddyfile
{
layer4 {
udp/:9987 {
route {
proxy udp/192.168.1.103:9987
}
}
:25565 {
route {
proxy {
proxy_protocol v2
upstream 192.168.1.104:25565
}
}
}
:5432 {
route {
proxy 192.168.1.103:5432
}
}
:1022 {
route {
proxy 192.168.1.118:22
}
}
:3022 {
route {
proxy 192.168.1.119:22
}
}
}
}
(common) {
header * {
-Server
-Via
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
X-Frame-Options "SAMEORIGIN"
Referrer-Policy "strict-origin-when-cross-origin"
Permissions-Policy "geolocation=(), microphone=(), camera=(), interest-cohort=()"
}
log {
output file /var/log/caddy/access.log {
roll_size 50MB
roll_keep 5
roll_keep_for 168h
}
format json {
time_format "iso8601"
}
}
encode zstd gzip
}
(insecure) {
transport http {
tls_insecure_skip_verify
}
}
(cf) {
tls {
dns cloudflare {env.CLOUDFLARE_API_KEY}
}
}
:80, http://albert.lol {
redir https://albert.lol{uri} permanent
}
*.demo.albert.lol {
import common
import cf
@btdemo host budgetable.demo.albert.lol
handle @btdemo {
reverse_proxy 192.168.1.103:3006
}
handle {
abort
}
}
albert.lol {
import common
import cf
reverse_proxy 192.168.1.106:3000
}
*.albert.lol {
import common
import cf
import sites/*
handle {
redir https://albert.lol permanent
}
}
Example from my sites/ directory:
cat /etc/caddy/sites/bin.albert.lol
@bin host bin.albert.lol
handle @bin {
reverse_proxy 192.168.1.103:8002
}