I need some help if anyone could take the time and has the knowledge:

I’m basically new to podman and namespaces, relatively new to linux and a noob at networking. So figuring this out and getting it to work took many more hours than I would like to admit, but I still have a few problems. I have all my current Quadlets below in the spoiler (seperated by “—”, assume user123 = UID 1000). I am on Bazzite, rootless Podman, which probably makes this even harder.

Spoiler with the Quadlets
[Unit]
Description=Arr-stack pod

[Pod]
PodName=arr-stack
# Network
# Network=vpn-only

# User mapping / I don't fully understand this yet, but the pod does not work without this (maps user id to specified ID inside the containers? So the containers have UID:GID 1000:1000?)
UserNS=keep-id:uid=1000,gid=1000
#
# Homepage Port Mapping
PublishPort=3000:3000
# Jellyfin Port Mapping
PublishPort=8096:8096/tcp
# qBittorrent Port Mapping
PublishPort=8080:8080
#PublishPort=6881:6881
#PublishPort=6881:6881/udp
# Prowlarr Port Mapping
PublishPort=9696:9696
# Flaresolverr Port Mapping
PublishPort=8191:8191
# Radarr Port Mapping
PublishPort=7878:7878
# Sonarr Port Mapping
PublishPort=8989:8989

# Jellyseerr Port Mapping
#PublishPort=8055:5055

#[Install]
# WantedBy=default.target

---

[Unit]
Description=Gluetun Container
# Dependencies
# pod
Wants=arr-stack-pod.service
After=arr-stack-pod.service
Requires=arr-stack-pod.service
PartOf=arr-stack-pod.service
# .pod is probably not quite what I want, but it works and I might as well keep it, in case they change the syntax
Wants=arr-stack.pod
After=arr-stack.pod
Requires=arr-stack.pod
PartOf=arr-stack.pod


[Container]
ContainerName=gluetun
Pod=arr-stack.pod
Image=docker.io/qmcgaw/gluetun:v3
AutoUpdate=registry
# Network
# Network=vpn-only

# UID/GID permissions / root + privileged for networking?
PodmanArgs=--privileged
User=0
Group=0
# Equivalent to cap_add: - NET_ADMIN # one wrong?
AddCapability=NET_ADMIN
AddCapability=CAP_NET_ADMIN
# Required for Gluetun to delete the bridge's default route, but does not work
AddCapability=NET_RAW
AddCapability=CAP_NET_RAW
# Equivalent to "devices: - /dev/net/tun:/dev/net/tun"
AddDevice=/dev/net/tun:/dev/net/tun

# EnvironmentFile=global.env
Timezone=UTC
Environment=TZ=Etc/UTC

# EnvironmentFile=gluetun.env
# Environment=FIREWALL_OUTBOUND_SUBNETS=10.90.0.0/24 / test from a specific podman network
Environment=FIREWALL_INPUT_PORTS=8080
#
Environment=VPN_SERVICE_PROVIDER= <123>
Environment=VPN_TYPE=wireguard
Environment=WIREGUARD_PRIVATE_KEY= <key>
Environment=SERVER_COUNTRIES= <country>
# for now:
Environment=VPN_PORT_FORWARDING=off
#Secret=openvpn_user,type=env,target=OPENVPN_USER
#Secret=openvpn_password,type=env,target=OPENVPN_PASSWORD

#Volume
Volume=/var/home/user123/.config/arr-configs/gluetun:/gluetun:Z
# SecurityLabel=disable

[Service]
Restart=always

#[Install]
#WantedBy=default.target

---

[Unit]
Description=qBittorrent Container
# Dependencies
# pod
Wants=arr-stack-pod.service
After=arr-stack-pod.service
Requires=arr-stack-pod.service
PartOf=arr-stack-pod.service
# .pod is probably not quite what I want, but it works and I might as well keep it, in case they change the syntax
Wants=arr-stack.pod
After=arr-stack.pod
Requires=arr-stack.pod
PartOf=arr-stack.pod
# gluetun
Wants=gluetun.service
After=gluetun.service
Requires=gluetun.service
BindsTo=gluetun.service
# .container is probably not quite what I want, but it works and I might as well keep it, in case they change the syntax
Wants=gluetun.container
After=gluetun.container
Requires=gluetun.container
BindsTo=gluetun.container


[Container]
ContainerName=qbittorrent
Pod=arr-stack.pod
Image=lscr.io/linuxserver/qbittorrent:latest
AutoUpdate=registry
# Network
Network=container:gluetun

# UID/GID permissions / linuxserver images require UID:GID 0:0 at the start; they won't start without it
User=0
Group=0
Environment=PUID=1000
Environment=PGID=1000

# EnvironmentFile=global.env
Timezone=UTC
Environment=TZ=Etc/UTC

# EnvironmentFile=qbittorrent.env
Environment=WEBUI_PORT=8080
# Environtment=TORRENTING_PORT=6881

# Volume :Z (> :z) probably works as well and is saver for configs?
Volume=/var/home/user123/.config/arr-configs/qbittorrent:/config:z
Volume=/var/home/user123/Videos/Downloads:/downloads:z
# Volume=/var/home/user123/Videos/Downloads/completed:/downloads:z,U
# Volume=/var/home/user123/Videos/Downloads/incomplete:/incomplete:z,U
# Volume=/var/home/user123/Videos/Downloads/torrents:/torrents:z,U

[Service]
Restart=always

#[Install]
#WantedBy=default.target

---

[Unit]
Description=Prowlarr Container
# Dependencies
# pod
Wants=arr-stack-pod.service
After=arr-stack-pod.service
Requires=arr-stack-pod.service
PartOf=arr-stack-pod.service
# .pod is probably not quite what I want, but it works and I might as well keep it, in case they change the syntax
Wants=arr-stack.pod
After=arr-stack.pod
Requires=arr-stack.pod
PartOf=arr-stack.pod
# gluetun
Wants=gluetun.service
After=gluetun.service
Requires=gluetun.service
BindsTo=gluetun.service
# .container is probably not quite what I want, but it works and I might as well keep it, in case they change the syntax
Wants=gluetun.container
After=gluetun.container
Requires=gluetun.container
BindsTo=gluetun.container


[Container]
ContainerName=prowlarr
Pod=arr-stack.pod
Image=lscr.io/linuxserver/prowlarr:latest
AutoUpdate=registry
# Network
Network=container:gluetun

# UID/GID permissions / linuxserver images require UID:GID 0:0 at the start; they won't start without it
User=0
Group=0
Environment=PUID=1000
Environment=PGID=1000

# EnvironmentFile=global.env
Timezone=UTC
Environment=TZ=Etc/UTC

# EnvironmentFile=prowlarr.env
Environment=WEBUI_PORT=9696

# Volume
Volume=/var/home/user123/.config/arr-configs/prowlarr:/config:z,U

[Service]
Restart=always

#[Install]
#WantedBy=default.target

---

[Unit]
Description=Sonarr Container
# Dependencies
# pod
Wants=arr-stack-pod.service
After=arr-stack-pod.service
Requires=arr-stack-pod.service
PartOf=arr-stack-pod.service
# .pod is probably not quite what I want, but it works and I might as well keep it, in case they change the syntax
Wants=arr-stack.pod
After=arr-stack.pod
Requires=arr-stack.pod
PartOf=arr-stack.pod
# gluetun
Wants=gluetun.service
After=gluetun.service
Requires=gluetun.service
BindsTo=gluetun.service
# .container is probably not quite what I want, but it works and I might as well keep it, in case they change the syntax
Wants=gluetun.container
After=gluetun.container
Requires=gluetun.container
BindsTo=gluetun.container


[Container]
ContainerName=sonarr
Pod=arr-stack.pod
Image=lscr.io/linuxserver/sonarr:latest
AutoUpdate=registry
# Network
Network=container:gluetun

# UID/GID permissions / linuxserver images require UID:GID 0:0 at the start; they won't start without it
User=0
Group=0
Environment=PUID=1000
Environment=PGID=1000

# EnvironmentFile=global.env
Timezone=UTC
Environment=TZ=Etc/UTC

# EnvironmentFile=sonarr.env
Environment=WEBUI_PORT=8989

# Volume / Disable SecurityLabels due to SMB share, need to look this up
SecurityLabelDisable=true
Volume=/var/home/user123/.config/arr-configs/sonarr:/config:z
Volume=/var/home/user123/Videos/Shows:/tv:z
Volume=/var/home/user123/Videos/Downloads:/downloads:z

[Service]
Restart=always

#[Install]
#WantedBy=default.target

---

[Unit]
Description=Radarr Container
# Dependencies
# pod
Wants=arr-stack-pod.service
After=arr-stack-pod.service
Requires=arr-stack-pod.service
PartOf=arr-stack-pod.service
# .pod is probably not quite what I want, but it works and I might as well keep it, in case they change the syntax
Wants=arr-stack.pod
After=arr-stack.pod
Requires=arr-stack.pod
PartOf=arr-stack.pod
# gluetun
Wants=gluetun.service
After=gluetun.service
Requires=gluetun.service
BindsTo=gluetun.service
# .container is probably not quite what I want, but it works and I might as well keep it, in case they change the syntax
Wants=gluetun.container
After=gluetun.container
Requires=gluetun.container
BindsTo=gluetun.container


[Container]
ContainerName=radarr
Pod=arr-stack.pod
Image=lscr.io/linuxserver/radarr:latest
AutoUpdate=registry
# Network
Network=container:gluetun

# UID/GID permissions / linuxserver images require UID:GID 0:0 at the start; they won't start without it
User=0
Group=0
Environment=PUID=1000
Environment=PGID=1000

# EnvironmentFile=global.env
Timezone=UTC
Environment=TZ=Etc/UTC

# EnvironmentFile=radarr.env
Environment=WEBUI_PORT=7878

# Volume / Disable SecurityLabels due to SMB share
SecurityLabelDisable=true
Volume=/var/home/user123/.config/arr-configs/radarr:/config:z
Volume=/var/home/user123/Videos/Movies:/movies:z
Volume=/var/home/user123/Videos/Downloads:/downloads:z

[Service]
Restart=always

#[Install]
#WantedBy=default.target

---

[Unit]
Description=Flaresolverr Container
# Dependencies
# pod
Wants=arr-stack-pod.service
After=arr-stack-pod.service
Requires=arr-stack-pod.service
PartOf=arr-stack-pod.service
# .pod is probably not quite what I want, but it works and I might as well keep it, in case they change the syntax
Wants=arr-stack.pod
After=arr-stack.pod
Requires=arr-stack.pod
PartOf=arr-stack.pod
# gluetun
Wants=gluetun.service
After=gluetun.service
Requires=gluetun.service
BindsTo=gluetun.service
# .container is probably not quite what I want, but it works and I might as well keep it, in case they change the syntax
Wants=gluetun.container
After=gluetun.container
Requires=gluetun.container
BindsTo=gluetun.container


[Container]
ContainerName=flaresolverr
Pod=arr-stack.pod
Image=ghcr.io/flaresolverr/flaresolverr:latest
AutoUpdate=registry
# Network
Network=container:gluetun

# UID/GID permissions
User=0
Group=0
Environment=PUID=1000
Environment=PGID=1000

# EnvironmentFile=global.env
Timezone=UTC
Environment=TZ=Etc/UTC

# EnvironmentFile=flaresolverr.env
Environment=WEBUI_PORT=8191
Environment=LOG_LEVEL=info
Environment=LOG_HTML=false
Environment=CAPTCHA_SOLVER=none

# Volume=flaresolverr:/app/

[Service]
Restart=always

#[Install]
#WantedBy=default.target

---

[Unit]
Description=Podman - Jellyfin
# Dependencies
# pod
Wants=arr-stack-pod.service
After=arr-stack-pod.service
Requires=arr-stack-pod.service
PartOf=arr-stack-pod.service
# .pod is probably not quite what I want, but it works and I might as well keep it, in case they change the syntax
Wants=arr-stack.pod
After=arr-stack.pod
Requires=arr-stack.pod
PartOf=arr-stack.pod
# gluetun
Wants=gluetun.service
After=gluetun.service
Requires=gluetun.service
BindsTo=gluetun.service
# .container is probably not quite what I want, but it works and I might as well keep it, in case they change the syntax
Wants=gluetun.container
After=gluetun.container
Requires=gluetun.container
BindsTo=gluetun.container


[Container]
ContainerName=jellyfin
Pod=arr-stack.pod
Image=ghcr.io/jellyfin/jellyfin
AutoUpdate=registry
# Network
Network=container:gluetun

# UID/GID permissions / 1000:1000 might work?
User=0
Group=0
Environment=PUID=1000
Environment=PGID=1000

# EnvironmentFile=global.env
Timezone=UTC
Environment=TZ=Etc/UTC

# EnvironmentFile=jellyfin.env
Environment=WEBUI_PORT=8096:8096/tcp
#PublishPort=8096:8096/tcp
#PublishPort=8920:8920
#PublishPort=7359:7359/udp
#PublishPort=1900:1900/udp

# Volume
Volume=/var/home/user123/.config/arr-configs/jellyfin:/config:z
Volume=/var/home/user123/Videos/jellyfin-cache:/cache:z
Volume=/var/home/user123/Videos/Movies:/data/movies:z
Volume=/var/home/user123/Videos/Shows:/data/shows:z

[Service]
# Inform systemd of additional exit status
# SuccessExitStatus=0 143a
Restart=always
TimeoutStartSec=900

#[Install]
# Start by default on boot
#WantedBy=default.target


---

[Unit]
Description=Homepage Dashboard
# Dependencies
# pod
Wants=arr-stack-pod.service
After=arr-stack-pod.service
Requires=arr-stack-pod.service
PartOf=arr-stack-pod.service
# .pod is probably not quite what I want, but it works and I might as well keep it, in case they change the syntax
Wants=arr-stack.pod
After=arr-stack.pod
Requires=arr-stack.pod
PartOf=arr-stack.pod
# gluetun
Wants=gluetun.service
After=gluetun.service
Requires=gluetun.service
BindsTo=gluetun.service
# .container is probably not quite what I want, but it works and I might as well keep it, in case they change the syntax
Wants=gluetun.container
After=gluetun.container
Requires=gluetun.container
BindsTo=gluetun.container
# idk about this?:
After=network-online.target
Wants=network-online.target
# Socket
Wants=podman.socket
After=podman.socket
Requires=podman.socket


[Container]
ContainerName=homepage
Pod=arr-stack.pod
Image=ghcr.io/gethomepage/homepage:latest
AutoUpdate=registry
# Network
Network=container:gluetun

# UID/GID permissions
User=1000
Group=1000
Environment=PUID=1000
Environment=PGID=1000

# EnvironmentFile=global.env
Timezone=UTC
Environment=TZ=Etc/UTC

# EnvirontmentFile=homepage.env
#Environment=LOG_LEVEL=debug
Environment=HOMEPAGE_ALLOWED_HOSTS=gethomepage.dev
#PublishPort=3000:3000

# Podman socket (recommended on Bazzite)
Volume=%t/podman/podman.sock:/var/run/docker.sock:ro
#Volume=/var/run/docker.sock:/run/user/1000/podman/podman.sock:ro
#Volume=/%t/podman/podman.sock:/run/user/1000/podman/podman.sock:ro

# Volume / Config directory
SecurityLabelDisable=true
Volume=%h/apps/homepage:/app/config:Z
Volume=%h/apps/homepage/icons:/app/public/icons:Z

[Service]
Restart=on-failure
TimeoutStartSec=300

#[Install]
#WantedBy=default.target

Questions:

    1. If I use “podman exec <container> ip route” (on e.g. qbittorrent) the default route goes through my actual network interface (actual ip adress) which I very much do not want (or through my killswitch dummy network from my VPN if on, which is better but still not ideal). Is there a way to completely remove my actual network from a container’s eyes? “podman exec <container> ip addr” shows 1 lo (local), 2 my actual network, 4 tun0 from gluetun. The traffic does go through gluetun correctly, but I don’t trust it 100%. Having the containers separated and NOT inside a pod gives the same result, since the containers share the network namespaces from the gluetun container when I do “Network=container:gluetun” (same as just having them in a pod as far as I understand). I tried to also create a podman network without a default gateway, but then gluetun cannot connect to the VPN in the first place.
    1. My setup works but is quite convoluted and probably has many unnecessary lines, so please give me any improvements you see
    1. Is User=1000, Group=1000, even sensible? For example in the homepage container those lines result in the container showing User “1000:1000” (from podman inspect). Would User=0, Group=0 (or no lines since I use UserNS=keep-id in the pod?), which shows as User=root (podman inspect) mean that it has actual root access or just that it is root INSIDE the container?

Thank you in advance for the answers, in case I don’t reply to your comment specifically.

  • just_another_person@lemmy.world
    link
    fedilink
    English
    arrow-up
    7
    ·
    10 hours ago
    1. No, you can’t “remove” your local networking interfaces from a container and expect it to use networking, anymore than you can remove the engine from a car, and expect it to drive. Set the default route of that container to some VPN tunnel interface, and you should be fine.
    2. I’m not seeing a link to any config
    3. 1000:1000 is usually the default user that is created for you when you setup a Linux system, so yes it’s reasonable for them to run as your user. It is NOT reasonable to run them as root, which is 0:0. Don’t do that.
    • Excaliburr@lemmy.dbzer0.comOP
      link
      fedilink
      English
      arrow-up
      3
      ·
      edit-2
      10 hours ago

      Thanks for the answer.

      To

      1. Maybe I worded that poorly, I do understand that I can’t take out the engine haha (good analogy). I thought gluetun was supposed to set the default route (but it seems it either doesn’t or can’t), I’ll dig deeper into manually setting a default route for containers. My goal was to only have gluetun see my computer’s network and have the containers only see local network and gluetun’s tun0 network (with default routing through tun0). AFAIK pods share network namespaces, though, so that might not be possible? (even without pods?)

      2. The quadlets are in the spoiler at the bottom of the post. I’ll move the spoiler up a bit

      3. So they would be rootless containers, but have root access as 0:0, if I understand that correctly? linuxserver images require 0:0 or they won’t start, do you happen to know a workaround?

      • just_another_person@lemmy.world
        link
        fedilink
        English
        arrow-up
        3
        ·
        10 hours ago

        If they require root at start, it’s more than likely they need to access devices or sockets on the host on startup. If it’s then transitioning to another uid/gid for the actual runtime in the container - which looks to be happening - its not quite rootLESS because it obviously requires root.

        I’m unfamiliar with the linuxserver images, so don’t understand the need for root here.