Podman Quadlets Arr-Stack And Networking

https://lemmy.dbzer0.com/post/62083240

Podman Quadlets Arr-Stack And Networking - Divisions by zero

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 “—”). I am on Bazzite, which probably makes this even harder. 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. - 2. My setup works but is quite convoluted and probably has many unnecessary lines, so please give me any improvements you see - 3. 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. ::: spoiler spoiler [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 :::

@Excaliburr 3. Are we talking here about rootless podman? If yes, containers are running on the host with the uid of current user, in your example with UID 1000.
Processes IN started containers are often running with UID=0, but this belongs to definition of used container and is only IN container.
PostgreSQL in Debian container is running with UID=999.
To avoid problems with created files in host file system, I'm using `UserNS=keep-id:uid=999,gid=999`, which maps files to the UID on host system.

Yes, rootless podman.

Just to see if I understood correctly: So your container is running as 999, and UserNS=keep-id:uid=999,gid=999 maps 999 (the user used inside the container) to the host (in my case 1000). So any files the container creates have their permission set to 1000 and can be read/modified by both the host user (1000) and the container. UserNS=keep-id:uid=999,gid=999 ONLY maps the UIDs and does not set the UID of the container.

I think I understand now, thanks for the example, that helped.

@Excaliburr Yes, you are right.

Do you have already a single container running with rootless podman?
Your given Arr-Stack seems to me relative complex when you are a beginner with podman.
Probably you could get some experience, when you start with just a single container.

In following posts are my personal quadlet settings for running Portainer, which could be helpful for getting insights of your running containers.

https://docs.portainer.io/start/install-ce/server/podman/linux

Install Portainer CE with Podman on Linux | Portainer Documentation

I’ve been running Docker for various things on Windows before and I’m not a stranger to computers and tech in general, so that’s why I went this deep from the get go. The whole stack works and I’m like 90% sure that it works the way I want it to work, I just want to make it better (and “bullet proof”). I don’t have much experience with networking or Linux, though, so yeah, this was quite the challenge haha. Thanks again for the help, I’ll have a look at your quadlets.