TL;DR: This article describes how to configure custom static networking with Podman Quadlet and Netavark as the network backend.
Preparation phase
First of all, let’s set a proper subnet and disable Podman - NFTables interaction:
# cat /etc/containers/containers.conf
[network]
default_subnet = "100.64.0.0/24"
# cat /etc/containers/netavark/config.json
{
"firewall_driver": "none"
}
The 100.64.0.0/10 prefix is designed for CGNAT and won’t collide with other private networks. See rfc6598.
Deployment
Let’s deploy each service (NextCloud, Immich, Gitea, …) to a separate isolated pod and therefore let’s provide a separate isolated network for each pod.
# cat /etc/containers/system/example.network
[Unit]
Description=Example Network
[Network]
Subnet=100.64.1.0/24
Gateway=100.64.1.1
IPAMDriver=host-local
Label=app=example
InterfaceName=podman-example
NetworkName=example
[Install]
WantedBy=multi-user.target
# cat /etc/containers/system/example.pod
[Unit]
Description=Example Pod
[Pod]
PodName=example
Network=example
IP=100.64.1.2
Label=app=example
[Install]
WantedBy=multi-user.target
# cat /etc/containers/system/example-app.container
[Unit]
Description=Example App Container
[Container]
ContainerName=example-app
Image=registry.opensuse.org/opensuse/nginx:latest
Pod=example.pod
Label=app=example
[Service]
Restart=always
[Install]
WantedBy=multi-user.target
# cat /etc/containers/system/example-db.container
[Unit]
Description=Example DB Container
[Container]
ContainerName=example-db
Image=registry.opensuse.org/opensuse/postgres:latest
Pod=example.pod
Label=app=example
[Service]
Restart=always
[Install]
WantedBy=multi-user.target
Conclusion
Our Example application is reachable via 100.64.1.2 address.
There are of course two important steps missing:
- Firewall of your choice
- HTTP(S) Proxy of your choice