Caddy Reverse Proxy Setup w/ Podman

1. The problem I’m having:

Issue

Having an issue getting caddy working as an HTTP/2 reverse proxy for my SentryShot container running on my Debian 12.12 server. Not able to curl into it or access it and I also don’t quite know if anything is set up correctly.

I’m just blindly following a guide (linked below) provided by the SentryShot dev and the caddy docs seem pretty sparse about working with containers.

Pretty new to all this so I don’t really understand a lot of it.

Context

For context, I’m running a sentryshot (linked below) container on baby’s first ever server.

I’m having issues with streams restarting and stopping in every browser I’ve tried across multiple computers. I’ve tried mitigate this by using mediamtx (linked below) proxies via the sentryshot dev’s advice.

This has some positive effect but the issue still persists. So the dev told me to try this https/2 proxy thing and linked that aforementioned guide (linked below).

2. Errors and Logs

Error messages:

user@remote:~/.local/share/containers/storage/volumes/caddy_data/_data$ curl -k localhost:4040
curl: (56) Recv failure: Connection reset by peer
user@remote:~/.local/share/containers/storage/volumes/caddy_data/_data$ curl -k localhost:8080
curl: (56) Recv failure: Connection reset by peer
user@remote:~/.local/share/containers/storage/volumes/caddy_data/_data$ curl -k localhost:8443
curl: (56) Recv failure: Connection reset by peer

3. Caddy version:

“CADDY_VERSION=v2.10.2”

{
    "AppArmorProfile": "",
    "Args": [
        "run",
        "--config",
        "/etc/caddy/Caddyfile",
        "--adapter",
        "caddyfile"
    ],
    "Config": {
        "AttachStderr": false,
        "AttachStdin": false,
        "AttachStdout": false,
        "Cmd": [
            "caddy",
            "run",
            "--config",
            "/etc/caddy/Caddyfile",
            "--adapter",
            "caddyfile"
        ],
        "Domainname": "",
        "Entrypoint": [],
        "Env": [
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
            "TERM=xterm",
            "container=podman",
            "CADDY_VERSION=v2.10.2",
            "XDG_CONFIG_HOME=/config",
            "XDG_DATA_HOME=/data",
            "HOME=/root",
            "HOSTNAME=015e8ff13071"
        ],
        "ExposedPorts": {
            "2019/tcp": {},
            "4040/tcp": {},
            "443/tcp": {},
            "443/udp": {},
            "80/tcp": {},
            "8080/tcp": {},
            "8443/tcp": {}
        },
        "Hostname": "015e8ff13071",
        "Image": "docker.io/library/caddy:latest",
        "Labels": {
            "org.opencontainers.image.description": "a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go",
            "org.opencontainers.image.documentation": "https://caddyserver.com/docs",
            "org.opencontainers.image.licenses": "Apache-2.0",
            "org.opencontainers.image.source": "https://github.com/caddyserver/caddy-docker",
            "org.opencontainers.image.title": "Caddy",
            "org.opencontainers.image.url": "https://caddyserver.com",
            "org.opencontainers.image.vendor": "Light Code Labs",
            "org.opencontainers.image.version": "v2.10.2"
        },
        "OnBuild": null,
        "OpenStdin": true,
        "StdinOnce": false,
        "StopSignal": "15",
        "StopTimeout": 10,
        "Tty": true,
        "User": "",
        "Volumes": null,
        "WorkingDir": "/srv"
    },
    "Created": "2025-10-09T20:33:38.293564421Z",
    "Driver": "vfs",
    "ExecIDs": [],
    "GraphDriver": {
        "Data": null,
        "Name": "vfs"
    },
    "HostConfig": {
        "AutoRemove": false,
        "Binds": [
            "caddy_data:/app/storage:rw,rprivate,nosuid,nodev,rbind"
        ],
        "BlkioDeviceReadBps": null,
        "BlkioDeviceReadIOps": null,
        "BlkioDeviceWriteBps": null,
        "BlkioDeviceWriteIOps": null,
        "BlkioWeight": 0,
        "BlkioWeightDevice": null,
        "CapAdd": [],
        "CapDrop": [
            "AUDIT_WRITE",
            "MKNOD",
            "NET_RAW"
        ],
        "Cgroup": "",
        "CgroupParent": "user.slice",
        "CgroupnsMode": "",
        "ConsoleSize": [
            0,
            0
        ],
        "ContainerIDFile": "",
        "CpuCount": 0,
        "CpuPercent": 0,
        "CpuPeriod": 0,
        "CpuQuota": 0,
        "CpuRealtimePeriod": 0,
        "CpuRealtimeRuntime": 0,
        "CpuShares": 0,
        "CpusetCpus": "",
        "CpusetMems": "",
        "DeviceCgroupRules": null,
        "DeviceRequests": null,
        "Devices": [],
        "Dns": [],
        "DnsOptions": [],
        "DnsSearch": [],
        "ExtraHosts": [],
        "GroupAdd": [],
        "IOMaximumBandwidth": 0,
        "IOMaximumIOps": 0,
        "IpcMode": "shareable",
        "Isolation": "",
        "KernelMemory": 0,
        "KernelMemoryTCP": 0,
        "Links": null,
        "LogConfig": {
            "Config": null,
            "Type": "journald"
        },
        "MaskedPaths": null,
        "Memory": 0,
        "MemoryReservation": 0,
        "MemorySwap": 0,
        "MemorySwappiness": 0,
        "NanoCpus": 0,
        "NetworkMode": "slirp4netns",
        "OomKillDisable": false,
        "OomScoreAdj": 0,
        "PidMode": "private",
        "PidsLimit": 2048,
        "PortBindings": {
            "2019/tcp": [
                {
                    "HostIp": "",
                    "HostPort": "2019"
                }
            ],
            "4040/tcp": [
                {
                    "HostIp": "",
                    "HostPort": "4040"
                }
            ],
            "443/tcp": null,
            "443/udp": null,
            "80/tcp": null,
            "8080/tcp": [
                {
                    "HostIp": "",
                    "HostPort": "8080"
                }
            ],
            "8443/tcp": [
                {
                    "HostIp": "",
                    "HostPort": "8443"
                }
            ]
        },
        "Privileged": false,
        "PublishAllPorts": false,
        "ReadonlyPaths": null,
        "ReadonlyRootfs": false,
        "RestartPolicy": {
            "MaximumRetryCount": 0,
            "Name": ""
        },
        "Runtime": "oci",
        "SecurityOpt": [],
        "ShmSize": 65536000,
        "UTSMode": "private",
        "Ulimits": [],
        "UsernsMode": "",
        "VolumeDriver": "",
        "VolumesFrom": null
    },
    "HostnamePath": "/run/user/1000/containers/vfs-containers/015e8ff130715838145c1066b2760b24a8f7641d8f83e6407b143e951b928c92/userdata/hostname",
    "HostsPath": "/run/user/1000/containers/vfs-containers/015e8ff130715838145c1066b2760b24a8f7641d8f83e6407b143e951b928c92/userdata/hosts",
    "Id": "015e8ff130715838145c1066b2760b24a8f7641d8f83e6407b143e951b928c92",
    "Image": "sha256:e4bd530ab75a01a5c22fbb097938267e4cde118eab50ae68078df59ce83bceb2",
    "LogPath": "",
    "MountLabel": "",
    "Mounts": [
        {
            "Destination": "/app/storage",
            "Driver": "local",
            "Mode": "",
            "Name": "caddy_data",
            "Propagation": "rprivate",
            "RW": true,
            "Source": "/home/fugue/.local/share/containers/storage/volumes/caddy_data/_data",
            "Type": "volume"
        }
    ],
    "Name": "/caddy",
    "NetworkSettings": {
        "Bridge": "",
        "EndpointID": "",
        "Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "HairpinMode": false,
        "IPAddress": "",
        "IPPrefixLen": 0,
        "IPv6Gateway": "",
        "LinkLocalIPv6Address": "",
        "LinkLocalIPv6PrefixLen": 0,
        "MacAddress": "",
        "Networks": {},
        "Ports": {
            "2019/tcp": [
                {
                    "HostIp": "",
                    "HostPort": "2019"
                }
            ],
            "4040/tcp": [
                {
                    "HostIp": "",
                    "HostPort": "4040"
                }
            ],
            "443/tcp": null,
            "443/udp": null,
            "80/tcp": null,
            "8080/tcp": [
                {
                    "HostIp": "",
                    "HostPort": "8080"
                }
            ],
            "8443/tcp": [
                {
                    "HostIp": "",
                    "HostPort": "8443"
                }
            ]
        },
        "SandboxID": "",
        "SandboxKey": "/run/user/1000/netns/netns-98390c4b-cdc4-737e-b4ce-e8608b42c8e5",
        "SecondaryIPAddresses": null,
        "SecondaryIPv6Addresses": null
    },
    "Path": "caddy",
    "Platform": "linux",
    "ProcessLabel": "",
    "ResolvConfPath": "/run/user/1000/containers/vfs-containers/015e8ff130715838145c1066b2760b24a8f7641d8f83e6407b143e951b928c92/userdata/resolv.conf",
    "RestartCount": 0,
    "SizeRootFs": 0,
    "State": {
        "Dead": false,
        "Error": "",
        "ExitCode": 0,
        "FinishedAt": "0001-01-01T00:00:00Z",
        "Health": {
            "FailingStreak": 0,
            "Log": null,
            "Status": ""
        },
        "OOMKilled": false,
        "Paused": false,
        "Pid": 38850,
        "Restarting": false,
        "Running": true,
        "StartedAt": "2025-10-09T20:33:39.078247869Z",
        "Status": "running"
    }
}

4. How I installed and ran Caddy:

a. System environment:

Barest of bones Debian 12.12 netinst,
x86 architecture
I have systemd
podman version 4.3.1

b. Command:

Install script:

podman run -dit \
--name caddy \
-p 2019:2019 \ # default caddy config port per the docs
-p 8080:8080 \ # per techotom Caddyfile
-p 8443:8443 \ # per techotom Caddyfile
-p 4040:4040 \ # port I want to listen on
-v caddy_data:/app/storage \
docker.io/caddy

c. Service/unit/compose file:

I haven’t made any .service files or anything for systemd quite yet. I’m also not using the docker/podman compose feature.

d. My complete Caddy config:

I’m not able to “curl” to get this as it just returns an error.
Caddyfile:

{
  http_port 8080
  https_port 8443
}
:4040 {
  tls ./cert.pem ./key.pem
  reverse_proxy :2020
}

5. Links to relevant resources:

SentryShot

Relevant Issue

MediaMTX

Recommended Guide

Please let me know if there’s any more information I can provide <3

first, where is the caddy logs?

you have not mounted the cert and key files in your container.

caddy docker image stores data by default in /data not in /app/storage.

In your config, if you really want https in port 4040. change https_port 8443 to https_port 4040. change :4040 to https:// in site block address.

{
  http_port 8080
  https_port 4040
}
https:// {
  tls /cert.pem /key.pem
  respond "hello"
}

edit:
i forget, reverse_proxy :2020. i dont see the other service is in the same pod as caddy because you didn’t put a --pod. you have to put other service domain name (container name) in like reverse_proxy sentryshot:2020. podman default doesnt support dns tho. so, you got to use a new one.

3 Likes

thank you so much for your help!

you have not mounted the cert and key files in your container.
caddy docker image stores data by default in /data not in /app/storage.

I forgot to mention that the cert and key files are located in /app/storage:

fugue@hidden-leaf:~/.local/share/containers/storage/volumes/caddy_data/_data$ ls
Caddyfile  cert.pem  key.pem

Is this enough? or did I misunderstand what you said?

first, where is the caddy logs?

Caddy logs from the container (via portainer):

2025/10/09 20:33:39.184	INFO	maxprocs: Leaving GOMAXPROCS=4: CPU quota undefined
2025/10/09 20:33:39.184	INFO	GOMEMLIMIT is updated	{"package": "github.com/KimMachineGun/automemlimit/memlimit", "GOMEMLIMIT": 7376526950, "previous": 9223372036854775807}
2025/10/09 20:33:39.184	INFO	using config from file	{"file": "/etc/caddy/Caddyfile"}
2025/10/09 20:33:39.185	INFO	adapted config to JSON	{"adapter": "caddyfile"}
2025/10/09 20:33:39.186	INFO	admin	admin endpoint started	{"address": "localhost:2019", "enforce_origin": false, "origins": ["//localhost:2019", "//[::1]:2019", "//127.0.0.1:2019"]}
2025/10/09 20:33:39.186	WARN	http.auto_https	server is listening only on the HTTP port, so no automatic HTTPS will be applied to this server	{"server_name": "srv0", "http_port": 80}
2025/10/09 20:33:39.186	WARN	http	HTTP/2 skipped because it requires TLS	{"network": "tcp", "addr": ":80"}
2025/10/09 20:33:39.186	WARN	http	HTTP/3 skipped because it requires TLS	{"network": "tcp", "addr": ":80"}
2025/10/09 20:33:39.186	INFO	http.log	server running	{"name": "srv0", "protocols": ["h1", "h2", "h3"]}
2025/10/09 20:33:39.186	INFO	tls.cache.maintenance	started background certificate maintenance	{"cache": "0xc00027b880"}
2025/10/09 20:33:39.186	INFO	autosaved config (load with --resume flag)	{"file": "/config/caddy/autosave.json"}
2025/10/09 20:33:39.186	INFO	serving initial configuration
2025/10/09 20:33:39.188	INFO	tls	cleaning storage unit	{"storage": "FileStorage:/data/caddy"}
2025/10/09 20:33:39.190	INFO	tls	finished cleaning storage units
2025/10/10 20:33:39.230	INFO	tls	cleaning storage unit	{"storage": "FileStorage:/data/caddy"}
2025/10/10 20:33:39.239	INFO	tls	finished cleaning storage units

i forget, reverse_proxy :2020. i dont see the other service is in the same pod as caddy because you didn’t put a --pod. you have to put other service domain name (container name) in like reverse_proxy sentryshot:2020.

So I need to put --pod <sentryshot-container-id> in my caddy run script?

podman default doesnt support dns tho. so, you got to use a new one.

I have to use a new dns? Something like DuckDNS could work yeah?

Also, forgive me if the reply is slow, it seems the forum wants me to wait 2 hours between each reply

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