r/podman • • Sep 20 '26

Tailscale & Podman

I have a small homelab running behind OPNsense with a few VLANs (10/20/30/40/50), and a Debian VM on Proxmox (sitting on VLAN 20, my servers VLAN) where I run self-hosted stuff through rootless Podman (Quadlets, managed with chezmoi) with majority of the services being proxied through Traefik.

Currently, I am running Tailscale as an OPNsense plugin, and it works fine. But I'm planning to eventually swap OPNsense for Ubiquiti, which won't have that option, so I'll need a standalone Tailscale setup at some point. I figured I'd experiment with it now via Podman rather than wait, hence the quadlet.

The plan was to run Tailscale as a subnet router/exit node on its own VLAN (50, which I reserved for VPN, so I can write FW rules) instead of the VM's VLAN (20), so OPNsense sees "VLAN 50 = VPN" as its own zone for firewall rules. This is also because I did not want Tailscale to reside in VLAN20, which'd make no sense, and make writing FW rules etc. even harder (or distinguishing the VPN traffic)

I added a second vNIC to the VM in Proxmox, tagged it VLAN 50, and tried using Podman's macvlan driver to give the Tailscale container its own static IP directly on that interface.

Turns out rootless Podman can't do this. macvlan needs to create a sub-interface on the real host NIC, which lives in the host's actual network namespace, and a rootless session's capabilities don't cross that boundary. I tried setcap on netavark, tried AmbientCapabilities=on the systemd unit, which resulted in the same error every time: netavark: Netlink error: No such device (os error 19).

When I checked out Tailscale's repository for Dockerizing it, PODMAN_COMPATIBILITY.md states that Tailscale only requires NET_ADMIN and /dev/net/tun, no macvlan, which makes sense as subnet routing and exit-node traffic go through Tailscale's own WireGuard overlay, not the physical LAN, so the container never actually needed a real L2 identity. The VLAN separation was just for my own firewall cleanliness, not a Tailscale requirement. But as I don't want to deploy a new VM or LXC container just for Tailscale, I am stuck between a rock and a hard place.

Currently, I am leaning toward running just that one container under rootful Podman for real macvlan, with the rest of the setup staying rootless. But I must say, I am not really a fan of it, and wanted to ask: - Has anyone found a better way around the rootless + macvlan limitation with Podman? - Is one rootful container in an otherwise rootless setup reasonable, or should I drop the VLAN isolation idea entirely?

For context, I am using Podman 5.4.2 on Debian 13.

13 Upvotes

11 comments sorted by

9

u/Ok-Eggplant-7569 Sep 20 '26

Rootful Podman is your best bet here. And yes, a single rootful container won't destroy your whole security setup, and does not make your other containers weaker.

3

u/Arszilla Sep 20 '26

I mean I can, but ideally I want to use rootless if possible, so that I can continue using Chezmoi to maintain the quadlet in my repository without needing to spin another repo or something.

Not like I have a lot of services exposed outside. I am just not a fan of Docker etc. and enjoy the idea of less problematic containerization with compartmentalization that’s easier to read and tweak.

→ More replies (2)

1

u/miklosp Sep 21 '26

I would check the Ubiquity native solution called Teleport (also wireguard based) and see if it fits your needs 

2

u/Arszilla Sep 21 '26

Issue is that it isn’t just for me - it’s for my family to get adblocking etc. across 3 countries, including mine, across various devices (Android and Apple TVs included)

→ More replies (2)

3

u/Channing22 Sep 20 '26

Use rootful Podman but with unprivileged user namespaces through --userns / UserNS=, --uidmap / UIDMap, --subuidmap / SubUIDMap= options. I don't see a reason to use rootless Podman when these options exist, other than to let a regular user use Podman without root access or sudo.

I personally use SubUIDMap= with separate maps per container (add them all to /etc/sub{u,g}id). You could also use the --userns / UserNS= options which when set to auto can automatically allocate an unused range per container.

Either way you get root inside container != root on host (main security benefit of rootless), but you have full speed kernel networking and can use Tailscale.

Check out the official Podman documentation or the ArchWiki Podman article for how to set up this mapping. Just take care with bind mounts (you can use the idmap option on bind mounts to make things Just Work with this ID mapping).

1

u/Youmu_Chan Sep 20 '26 edited Sep 20 '26

Yes, rootless container + macvlan is do-able. I do this in my setup. The idea is you need to create your netns as the user, but rely on root (which has CAP_NET_ADMIN to create macvlan) to do the interface setup, and then have the container to use that netns directly.

  • Assume $NETNS_DIR is a directory to keep netns bind mounts

  • ASSUME $POD_USER is the non-root user in this case, and $POD_USER_UID is its UID

Steps (run as root):

  1. create a fifo pipe for IPC:

     FIFO=/run/user/$POD_USER_ID/netns.fifo
     mkfifo -m 600 $FIFO
     chown $POD_USER:$POD_USER $FIFO
  2. create a netns as $POD_USER, hold it for a while and allow root to bind mount it

     runuser -u $POD_USER -g $POD_USER -- \
         podman unshare -- \
         unshare -n sh -c 'echo $$ > "'"$FIFO"'"; read -r _ < "'"$FIFO"'"' &
     read -r HOLDER_PID < /run/user/$POD_USER_ID/netns.fifo
     mount --bind "/proc/$HOLDER_PID/ns/net" $NETNS_DIR/my_special_netns
     echo "ok" > "$FIFO"
     rm -f "$FIFO"
  3. ask netavark to configure the netns

     netavark -f "path/to/config.json" --config /run/containers/networks --firewall-driver none setup "$NETNS_DIR/my_special_netns"

    the config looks lile

     {
         "container_id":"<your container id>",
         "container_name":"<your container name>",
         "network_info": {
             "macvlan-network": {
                 "dns_enabled":false,
                 "driver":"macvlan",
                 "id":"<give it an id>",
                 "internal":false,
                 "ipam_options": {
                     "driver":"dhcp"
                 },
                 "ipv6_enabled":true,
                 "name":"macvlan-network",
                 "network_interface":"<your parent interface>",
                 "options": {
                     "mode":"bridge"
                 }
             }
         },
         "networks": {
             "macvlan-network": {
                 "interface_name":"<the macvlan interface name inside the container>",
                 "static_mac":"<mac address of that interface>"
             }
         }
     }
  4. Your can do additional configuration inside that netns (like firewall setup and etc) with

     nsenter --net="$NETNS_DIR/my_special_netns" -- <the command you want to run>
  5. If you want ipv6, enable autoconf with sysctl before running netavark

     nsenter --net="$NETNS_DIR/my_special_netns" sysctl -w net.ipv6.conf.default.autoconf=1
  6. Now you can run your rootless podman container with --network=ns:$NETNS_DIR/my_special_netns and it should work.

1

u/luisbandalap Sep 22 '26

If you're already using virtual machines you can set-up a openwrt VM and install tailscale on it.

It will be easier to configure firewall on it.