I recently made the decision to change from Docker to Podman in my homelab, and in the process, I’ve converted my docker-compose.yaml
files to .container
files (i.e., quadlets).
As a result, I have the following folder structure in ~/.config/containers
:
.
├── containers.conf.d
│ └── engine.conf
├── storage
│ ├── portainer-ce
│ │ ├── bin
│ │ ├── certs
│ │ │ ├── cert.pem
│ │ │ └── key.pem
│ │ ├── chisel
│ │ │ └── private-key.pem
│ │ ├── compose
│ │ ├── docker_config
│ │ │ └── config.json
│ │ ├── portainer.db
│ │ ├── portainer.key
│ │ ├── portainer.pub
│ │ └── tls
│ ├── traefik
│ │ ├── acme.json
│ │ ├── config.yaml
│ │ └── traefik.yaml
│ └── uptime-kuma
│ ├── docker-tls
│ ├── error.log
│ ├── kuma.db
│ ├── kuma.db-shm
│ ├── kuma.db-wal
│ ├── screenshots
│ └── upload
└── systemd
├── chartdb
│ └── chartdb.container
├── glance
│ └── glance.container
├── portainer-ce
│ └── portainer-ce.container
├── traefik
│ ├── traefik.container
│ ├── traefik.env
│ └── traefik.network
└── uptime-kuma
└── uptime-kuma.container
My traefik.container
looks like the following:
[Unit]
Description=Traefik
After=local-fs.target
Wants=network-online.target
After=network-online.target
Requires=podman.socket
After=podman.socket
[Container]
Image=docker.io/traefik:v3.5.1
AutoUpdate=registry
ContainerName=traefik
HostName=traefik
NoNewPrivileges=true
Network=traefik.network
PublishPort=80:80/tcp
PublishPort=443:443/tcp
Environment=CF_API_EMAIL=${CLOUDFLARE_EMAIL}
Environment=CF_DNS_API_TOKEN=${CLOUDFLARE_API_KEY}
Environment=TRAEFIK_DASHBOARD_CREDENTIALS=${TRAEFIK_DASHBOARD_CREDENTIALS}
Label=traefik.enable=true
Label=traefik.http.routers.traefik.entrypoints=http
Label=traefik.http.routers.traefik.rule=Host(`traefik.mydomain.tld`)
Label=traefik.http.middlewares.traefik-auth.basicauth.users=${TRAEFIK_DASHBOARD_CREDENTIALS}
Label=traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https
Label=traefik.http.middlewares.sslheader.headers.customrequestheaders.X-Forwarded-Proto=https
Label=traefik.http.routers.traefik.middlewares=traefik-https-redirect
Label=traefik.http.routers.traefik-secure.entrypoints=https
Label=traefik.http.routers.traefik-secure.rule=Host(`traefik.mydomain.tld`)
Label=traefik.http.routers.traefik-secure.middlewares=traefik-auth
Label=traefik.http.routers.traefik-secure.tls=true
Label=traefik.http.routers.traefik-secure.tls.certresolver=cloudflare
Label=traefik.http.routers.traefik-secure.tls.domains[0].main=mydomain.tld
Label=traefik.http.routers.traefik-secure.tls.domains[0].sans=*.mydomain.tld
Label=traefik.http.routers.traefik-secure.service=api@internal
Label=traefik.http.services.traefik.loadbalancer.server.port=80
Volume=%h/.config/containers/storage/traefik/traefik.yaml:/etc/traefik/traefik.yaml:ro,Z
Volume=%h/.config/containers/storage/traefik/config.yaml:/etc/traefik/config.yaml:ro,Z
Volume=%h/.config/containers/storage/traefik/acme.json:/etc/traefik/acme.json:rw,Z
Volume=/etc/localtime:/etc/localtime:ro
Volume=%t/podman/podman.sock:/var/run/docker.sock:ro
[Service]
Restart=on-failure
TimeoutStartSec=300
EnvironmentFile=%h/.config/containers/systemd/traefik/traefik.env
[Install]
WantedBy=multi-user.target default.target
Similarly, my traefik.yaml
:
global:
checkNewVersion: false
sendAnonymousUsage: false
log:
level: DEBUG
api:
dashboard: true
debug: true
entryPoints:
http:
address: ":80"
http:
redirections:
entryPoint:
to: https
scheme: https
https:
address: ":443"
serversTransport:
insecureSkipVerify: true
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
file:
filename: /etc/traefik/config.yaml
certificatesResolvers:
cloudflare:
acme:
email: REDACTED
storage: /etc/traefik/acme.json
# Production (Default)
caServer: https://acme-v02.api.letsencrypt.org/directory
# Staging
# caServer: https://acme-staging-v02.api.letsencrypt.org/directory
keyType: EC256
dnsChallenge:
provider: cloudflare
resolvers:
- "1.1.1.1:53"
- "1.0.0.1:53"
It should be noted that the traefik.container
and traefik.yaml
are pretty much identical to what I’ve used for Traefik for the past 3 years, with no changes to the labels or the files, etc.
I created uptime-kuma.container
with the following content:
[Unit]
Description=Uptime Kuma
After=local-fs.target
Wants=network-online.target
After=network-online.target
Requires=podman.socket
After=podman.socket
Wants=traefik.service
After=traefik.service
[Container]
Image=docker.io/louislam/uptime-kuma:latest
AutoUpdate=registry
ContainerName=uptime-kuma
HostName=uptime-kuma
Network=traefik
PublishPort=3131:3001/tcp
Label=traefik.enable=true
Label=traefik.http.routers.uptime-kuma.rule=Host(`monitor.mydomain.tld`)
Label=traefik.http.routers.uptime-kuma.entrypoints=https
Label=traefik.http.routers.uptime-kuma.tls=true
Label=traefik.http.services.uptime-kuma.loadbalancer.server.port=3131
Volume=%E/containers/storage/uptime-kuma/:/app/data:rw,Z
Volume=%t/podman/podman.sock:/var/run/docker.sock:ro
[Service]
Restart=on-failure
TimeoutStartSec=300
[Install]
WantedBy=multi-user.target default.
I have all these .containers
running in a VM (podman.mydomain.tld
- 10.10.20.2
), which has CNAME aliases pointing to it for traefik
, monitor
and portainer-ce
(the latter will come in to topic shortly). However, when I navigate to https://monitor.mydomain.tld
, I get the following:
Sep 03 23:33:11 podman traefik[220044]: 2025-09-03T23:33:11+03:00 DBG github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/wrr/wrr.go:175 > Service selected by WRR: http://10.89.0.3:3131
Sep 03 23:33:11 podman traefik[220044]: 2025-09-03T23:33:11+03:00 DBG github.com/traefik/traefik/v3/pkg/proxy/httputil/proxy.go:121 > 502 Bad Gateway error="dial tcp 10.89.0.3:3131: connect: connection refused"
Similary, with portainer-ce
, which consists of the same flags, albeit with portainer
instead of monitor
, and to Port 9443 instead of 3131, throws this error:
Sep 03 23:35:51 podman traefik[220044]: 2025-09-03T23:35:51+03:00 DBG github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/wrr/wrr.go:175 > Service selected by WRR: http://10.89.0.4:9443
Sep 03 23:35:51 podman traefik[220044]: 2025-09-03T23:35:51+03:00 DBG log/log.go:245 > httputil: ReverseProxy read error during body copy: read tcp 10.89.0.2:39532->10.89.0.4:9443: read: connection reset by peer
Sep 03 23:35:51 podman traefik[220044]: 2025-09-03T23:35:51+03:00 DBG github.com/traefik/traefik/v3/pkg/middlewares/recovery/recovery.go:45 > Request has been aborted [10.89.0.2:43954 - /]: net/http: abort Handler middlewareName=traefik-internal-recovery middlewareType=Recovery
I used to have these connections in my config.yaml
, as Portainer and Uptime-Kuma used to be in their own LXC containers, which is no longer the case.
Checking portainer
, I can see that all 3 containers are indeed in the traefik
network, as seen below:
I have Promox and my iLO in config.yaml
, which route perfectly fine, so I know Traefik is working as it should (to a certain extent).
I would really appreciate having some assistance in solving this issue, as I spent a whole week trying to figure it out, but to no avail.
TIA!