This demo shows how to run a socket-activated nginx container with Podman. See also the Podman socket activation tutorial.
Overview of the examples
Example | Type of service | Port | Using quadlet | rootful/rootless podman | Comment |
---|---|---|---|---|---|
Example 1 | systemd user service | 8080 | yes | rootless podman | Only unprivileged port numbers can be used |
Example 2 | systemd system service | 80 | yes | rootful podman | |
Example 3 | systemd system service (with User=test3 ) |
80 | no | rootless podman | Status: experimental |
Example 4 | systemd system service (with User=test4 ) |
80 | no | rootless podman | Similar to Example 3 but configured to run as an HTTP reverse proxy. Status: experimental. |
Example 5 | systemd system service (with User=test5 ) |
80 | no | rootless podman | Similar to Example 4 but the containers use --network=none and communicate over a Unix socket. Status: experimental. |
Example 6 | systemd system service (with User=test6 ) |
80 | no | rootless podman | Similar to Example 5 but the backend web server is started with socket activation in a systemd system service with User=test6 . Status: experimental. |
Note nginx has no official support for systemd socket activation (feature request: https://trac.nginx.org/nginx/ticket/237). These examples makes use of the fact that "nginx includes an undocumented, internal socket-passing mechanism" quote from https://freedesktop.org/wiki/Software/systemd/DaemonSocketActivation/
Communication over the socket-activated socket does not pass through pasta or slirp4netns so it has the same performance characteristics as the normal network on the host.
See the Podman socket activation tutorial.
The option podman run
option --network=none
enhances security.
--- nginx.service 2022-08-27 10:46:14.586561964 +0200
+++ nginx.service.new 2022-08-27 10:50:35.698301637 +0200
@@ -15,6 +15,7 @@
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/%n.ctr-id
ExecStart=/usr/bin/podman run \
+ --network=none \
--cidfile=%t/%n.ctr-id \
--cgroups=no-conmon \
--rm \
See the Podman socket activation tutorial.
See the blog post How to limit container privilege with socket activation
The systemd configuration RestrictAddressFamilies=AF_UNIX AF_NETLINK
enhances security.
To try it out, modify the file ~/.config/systemd/user/nginx.service according to
--- nginx.service 2022-08-27 10:46:14.586561964 +0200
+++ nginx.service.new 2022-08-27 10:58:06.625475911 +0200
@@ -7,14 +7,20 @@
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
+Requires=podman-usernamespace.service
+After=podman-usernamespace.service
RequiresMountsFor=%t/containers
[Service]
+RestrictAddressFamilies=AF_UNIX AF_NETLINK
+NoNewPrivileges=yes
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/%n.ctr-id
ExecStart=/usr/bin/podman run \
+ --network=none \
+ --pull=never \
--cidfile=%t/%n.ctr-id \
--cgroups=no-conmon \
--rm \
and create the file ~/.config/systemd/user/podman-usernamespace.service with this contents
[Unit]
Description=podman-usernamespace.service
[Service]
Type=oneshot
Restart=on-failure
TimeoutStopSec=70
ExecStart=/usr/bin/podman unshare /bin/true
RemainAfterExit=yes
See the blog post How to restrict network access in Podman with systemd
The rootlesskit port forwarding backend for slirp4netns does not preserve source IP. This is not a problem when using socket-activated sockets. See Podman GitHub discussion.
The Podman network tools are not needed when using --network=host or --network=none (see GitHub issue comment). In other words, the total amount of executables and libraries that are needed by Podman is reduced when you run the nginx container with socket activation and --network=none.
Reference 1:
The github project PhracturedBlue/podman-socket-activated-services contains an example of a
customized socket-activated nginx container that watches a directory for Unix sockets that backend applications have created. In case of socket-activated backend application it would have
been systemd that created the Unix sockets. The podman run option --network none
is used.
Reference 2:
The article "How to create multidomain web applications with Podman and Nginx" https://www.redhat.com/sysadmin/podman-nginx-multidomain-applications describes running nginx as a reverse proxy with rootless podman. In the article rootless podman is given the privilege to listen on port 80 with the command
sudo sysctl net.ipv4.ip_unprivileged_port_start=80
Socket activation is not used in the article.