Skip to content

LXC Containers

Updated: 2026-07-01

Overview

Proxmox VE currently runs the restored service platform as separate unprivileged LXCs:

  • CT 101 podman-lxc for rootless Podman applications and data services.
  • CT 102 technitium-dns for DNS.
  • CT 103 caddy-ingress for HTTP/HTTPS ingress.
  • CT 104 khysite for a separate site workload that still needs a full service page.
  • CT 105 ts-router for Headscale/Tailscale subnet routing.

Older references to CT 100 proxy and CT 107 dns describe the Docker, Traefik, Pi-hole, and Cloudflared era. Treat them as historical unless a fresh pct list shows them running and a current page explicitly says they are in use.

Verified Running Containers

Read-only Proxmox checks on 2026-06-26, with CT 105 added and verified on 2026-07-01:

CT State CPU Memory Root disk Network Startup Purpose
101 podman-lxc Running 4 cores 8192 MiB 64 GiB local-lvm 192.168.2.20/24, VLAN 2, gateway 192.168.2.1 order=3, onboot=1 Rootless Podman application host
102 technitium-dns Running 2 cores 1024 MiB 8 GiB local-lvm 192.168.2.2/24, VLAN 2, gateway 192.168.2.1 order=2, onboot=1 Technitium DNS
103 caddy-ingress Running 2 cores 1024 MiB 8 GiB local-lvm 192.168.2.3/24, VLAN 2, gateway 192.168.2.1 order=2, onboot=1 Caddy ingress
104 khysite Running 2 cores 512 MiB 8 GiB local-lvm 192.168.2.5/24, VLAN 2, gateway 192.168.2.1 onboot=1 Site workload; document before changing
105 ts-router Running 1 core 512 MiB 8 GiB local-lvm 192.168.2.120/24, VLAN 2, gateway 192.168.2.1 order=2, onboot=1 Dedicated Headscale/Tailscale subnet router

All five running CTs are unprivileged.

CT 101 podman-lxc

CT 101 is the active application container host. It runs rootless Podman as podsvc. Live DHCP on July 1, 2026 placed it at 192.168.2.20/24.

It uses Technitium DNS through a local dhclient override until OPNsense DMZ DHCP option 6 is corrected:

nameserver: 192.168.2.2
DNS override: /etc/dhcp/dhclient.conf supersedes DNS to 192.168.2.2
features: nesting=1,keyctl=1
unprivileged: 1

It also has the narrow /dev/net/tun passthrough required by rootless Podman 5 networking:

lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file

Current rootless services are documented in Podman Ecosystem Standards.

CT 102 technitium-dns

CT 102 is the DNS replacement for the historical Pi-hole/Cloudflared role at the same resolver address, 192.168.2.2.

Verified listeners on 2026-06-26:

Listener Purpose
192.168.2.2:53/tcp and 192.168.2.2:53/udp Client and infrastructure DNS
127.0.0.1:53/tcp and 127.0.0.1:53/udp Local DNS
192.168.2.2:5380/tcp and 127.0.0.1:5380/tcp Technitium web console

Because the web console is listening on the DMZ address, OPNsense rules must limit access to approved admin networks or it must be moved behind Caddy with OIDC. Do not expose the Technitium console publicly.

CT 103 caddy-ingress

CT 103 is the Caddy ingress host. It is separate from CT 101 because ingress holds certificate and authentication material and needs low ports.

Verified on 2026-06-26:

Item Value
Caddy version v2.11.4
Listeners *:80, *:443
Required modules dns.providers.cloudflare v0.2.4, security v1.1.62

Low-port binding is handled by a narrow file capability on the Caddy binary. Do not lower rootless Podman privileged-port limits to solve ingress.

See Caddy and Technitium Migration and Agent Handoff: Caddy, Technitium, and HTTPS.

CT 104 khysite

CT 104 khysite is running at 192.168.2.5. It needs a current service page before any major change, restore, or retirement decision.

Minimum pre-change checks:

ssh pvessh 'pct config 104'
ssh pvessh 'pct exec 104 -- hostname'
ssh pvessh 'pct exec 104 -- systemctl --no-pager --state=running,failed'

Do not assume it is part of the rootless Podman stack.

On July 1, 2026, CTs 101 through 104 were locally mitigated for the DMZ DHCP DNS issue:

/etc/dhcp/dhclient.conf: supersede domain-name-servers 192.168.2.2;
/etc/resolv.conf: nameserver 192.168.2.2

This should become unnecessary after OPNsense Dnsmasq sends option 6 192.168.2.2 on the DMZ interface.

CT 105 ts-router

CT 105 ts-router is the dedicated Headscale/Tailscale subnet router for the DMZ route 192.168.2.0/24. It replaced pve as serving router on 2026-07-01.

Current configuration:

hostname: ts-router
ostype: debian
unprivileged: 1
features: nesting=1,keyctl=1
net0: bridge=vmbr0, tag=2, ip=dhcp, firewall=1
MAC: BC:24:11:F2:77:FD
DMZ lease: 192.168.2.120/24
nameserver: 192.168.2.2

Tailscale requires /dev/net/tun passthrough:

lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file

Inside the CT:

Tailscale version: 1.98.8
Headscale owner: infra
Tailnet IP: 100.64.0.3
Advertised route: 192.168.2.0/24
SNAT: enabled
Forwarding file: /etc/sysctl.d/99-tailscale-subnet-router.conf
DNS override: /etc/dhcp/dhclient.conf supersedes DNS to 192.168.2.2

Historical Containers

The June 2026 baseline docs referenced:

CT Historical role Current handling
100 proxy Docker, Traefik, and app stacks Historical source material; replaced by CT 101 plus Caddy where migrated
107 dns Pi-hole and Cloudflared Historical source material; replaced by CT 102 technitium-dns
101 gam Stopped old identity before rebuild Replaced by CT 101 podman-lxc
105 down Stopped large filesystem Preserve evidence before repair or deletion
106 rdhost RustDesk signal/relay server Preserve identity files if clients are migrated

Operational Procedures

ssh pve 'pct list'
ssh pve 'pct status <CTID>'
ssh pve 'pct config <CTID>'
ssh pve 'pct start <CTID>'
ssh pve 'pct shutdown <CTID>'
ssh pve 'pct enter <CTID>'

For rootless Podman services on CT 101, use Podman Ecosystem Standards.

Troubleshooting

  • DNS failure: check CT 102, then OPNsense DNS enforcement.
  • HTTPS failure with working DNS: check CT 103, then the CT 101 high-port backend.
  • Rootless app failure: check CT 101 user units and Podman containers as podsvc.
  • DMZ reachability failure: check VLAN tag 2, vmbr0, gateway 192.168.2.1, and OPNsense rules.
  • Tailnet route failure: check CT 105, Headscale route state, and whether the client has accepted subnet routes.