Hi,
i having trouble to setup a container with podman rootless and systemd. I’m testing on Nixos unstable.
In root mode, my container is working
virtualisation = {
podman = {
enable = true;
dockerCompat = true;
defaultNetwork.dnsname.enable = true;
};
oci-containers = {
backend = "podman";
containers.pgadmin = {
image = "dpage/pgadmin4";
autoStart = true;
ports = [ "8084:80" ];
environment = {
PGADMIN_DEFAULT_EMAIL = "user@domain.com";
PGADMIN_DEFAULT_PASSWORD = "SuperSecret";
};
};
};
};
But when adding the systemd user config to exec my container with a dedicated user, the service is failing
...
users.users.pgadmin= {
isNormalUser = true;
};
systemd.services.podman-pgadmin.serviceConfig.User = "pgadmin";
...
see the log
Nov 28 02:29:16 sdserver systemd[1]: Starting podman-pgadmin.service...
Nov 28 02:29:16 sdserver podman-pgadmin-pre-start[32056]: time="2022-11-28T02:29:16+01:00" level=warning msg="RunRoot is pointing to a path (/run/user/1003/containers) which i>
Nov 28 02:29:16 sdserver podman-pgadmin-pre-start[32056]: Error: creating tmpdir: mkdir /run/user/1003: permission denied
Nov 28 02:29:16 sdserver podman-pgadmin-pre-start[32069]: rm: cannot remove '/run/podman-pgadmin.ctr-id': Permission denied
Nov 28 02:29:16 sdserver systemd[1]: podman-pgadmin.service: Control process exited, code=exited, status=1/FAILURE
Nov 28 02:29:16 sdserver podman-pgadmin-post-stop[32071]: time="2022-11-28T02:29:16+01:00" level=warning msg="RunRoot is pointing to a path (/run/user/1003/containers) which i>
Nov 28 02:29:16 sdserver podman-pgadmin-post-stop[32071]: Error: creating tmpdir: mkdir /run/user/1003: permission denied
Nov 28 02:29:16 sdserver systemd[1]: podman-pgadmin.service: Control process exited, code=exited, status=125/n/a
Nov 28 02:29:16 sdserver systemd[1]: podman-pgadmin.service: Failed with result 'exit-code'.
Nov 28 02:29:16 sdserver systemd[1]: Failed to start podman-pgadmin.service.
Nov 28 02:29:17 sdserver systemd[1]: podman-pgadmin.service: Scheduled restart job, restart counter is at 5.
Nov 28 02:29:17 sdserver systemd[1]: Stopped podman-pgadmin.service.
Nov 28 02:29:17 sdserver systemd[1]: podman-pgadmin.service: Start request repeated too quickly.
Nov 28 02:29:17 sdserver systemd[1]: podman-pgadmin.service: Failed with result 'exit-code'.
Nov 28 02:29:17 sdserver systemd[1]: Failed to start podman-pgadmin.service.
So /run/user/1003/containers
does not exists. What did i miss in my config ?
Thanks
2 Likes
I face the same problem. The core issue is that Podman services created with virtualisation.oci-containers.containers.<name>
are installed as /etc/systemd/user/podman-<name>.service
.
When you do that (systemd.services.podman-pgadmin.serviceConfig.User = "pgadmin";
), one would expect podman-pgadmin.service
to be run/executed by user pgadmin
. But, for that to happen, the unit file for podman-pgadmin.service
needs to be placed inside /home/pgadmin/.config/systemd/user
(not in /etc/systemd/user/
).
The current workaround is to manually write a systemd service by hand for every container that you want and manage it using home-manager. For containers to be truly rootless (in the same sense as it works on RHEL/Fedora), there should an oci-containers
“module” inside home-manager too.
When you do that (systemd.services.podman-pgadmin.serviceConfig.User = “pgadmin”;), one would expect podman-pgadmin.service to be> run/executed by user pgadmin. But, for that to happen, the unit file for podman-pgadmin.service needs to be placed inside> home/pgadmin.config/systemd/user (not in etc/systemd/user).
That’s not correct.
In the first case it will be run by system systemd instance but running as user pgadmin and started by systemctl start podman-pgadmin
. So run by root as pgadmin
.
If placed inside /etc/systemd/user
or /home/pgadmin/.config/systemd/user
, it will be run by the user systemd instance and started by systemctl --user start podman-pgadmin
when logged in as pgadmin
. So by and as pgadmin
.
1 Like
I misspoke. With systemd.services.<name>.serviceConfig.User
, the unit file will be in /etc/systemd/system/
but the User
field will be occupied with the value mentioned. The behaviour that I mentioned applies to systemd.user.services
. My bad.
Doing a systemctl --user status podman-<name>.service
(as the non-root user) gave me the error that the given service doesn’t exist for this user (Unit podman-<name>.service could not be found.
). I also did a podman ps
with this non-root user; that came up empty.
But then, I logged in as root (didn’t just prefix commands with sudo
; I was logged in as root
, in root
’s shell) and ran systemctl status podman-<name>.service
and got the details I would expect. I also did a podman ps
and found out that the containers are running by the user root
but also as the user root
.
If you define a service through systemd.services.foo
, that will run by the system systemd instance regardless of what you put into serviceConfig.User
. Many system level services do this as you absolutely want to run as few things as possible as root.
1 Like
I found a workaround months ago.
As reminder, i wanted to :
- start podman container at boot.
- rootless container so run by simple user and NOT root
- allow the user start/stop… the container
In the configuration.nix
# create my user
users.users."pgmadin" = {
isNormalUser = true;
uid = 1003;
};
# In order for our user to run containers automatically on boot,
# we need to enable systemd linger support.
# This will ensure that a user manager is run for the user at boot and kept around after logouts.
system.activationScripts = {
enableLingering = ''
# remove all existing lingering users
rm -r /var/lib/systemd/linger
mkdir /var/lib/systemd/linger
# enable for the subset of declared users
touch /var/lib/systemd/linger/pgadmin
'';
};
virtualisation = {
## setup podman
podman = {
enable = true;
dockerCompat = true;
defaultNetwork.settings.dns_enable = true;
};
## declare containers
oci-containers = {
## use podman as default container engine
backend = "podman";
};
};
## pgadmin container
systemd.user.services.pgadmin = {
enable = true;
unitConfig = { ConditionUser = "pgadmin"; };
wantedBy = [ "default.target" ];
after = [ "network.target" ];
description = "pgadmin container";
path = [ "/run/wrappers" ];
serviceConfig =
let
bash = "${pkgs.bash}/bin/bash";
podmancli = "${config.virtualisation.podman.package}/bin/podman";
podname = "pgadmin";
image = "dpage/pgadmin4:6.19";
cid = "%t/podman/%n.cid";
pid = "%t/podman/%n.pid";
startpre = [
"${pkgs.coreutils-full}/bin/rm -f ${cid} ${pid}"
"-${podmancli} stop --ignore ${podname}"
"${podmancli} rm --force --ignore ${podname}"
];
stoppost = [
"${podmancli} stop --ignore ${podname}"
"${podmancli} rm --force --ignore ${podname}"
"${pkgs.coreutils-full}/bin/rm -f ${cid} ${pid}"
];
in
{
ExecStartPre = startpre;
ExecStart = "${podmancli} run " +
"--rm " +
"--replace " +
"--name=${podname} " +
"--conmon-pidfile=${pid} " +
"--cidfile=${cid} " +
"--cgroups=no-conmon " +
"--sdnotify=conmon " +
"--log-driver=journald " +
"--name=${podname} " +
"-p 127.0.0.1:5050:80 " +
"-v pgadmin_data:/var/lib/pgadmin " +
"-e PGADMIN_DEFAULT_EMAIL='admin@localhost.fr' "+
"-e PGADMIN_DEFAULT_PASSWORD='pgadmin' "+
"-d " +
"${image}";
ExecStop = "${podmancli} stop ${podname}";
ExecStopPost = stoppost;
Type = "notify";
NotifyAccess = "all";
Restart = "no";
TimeoutStopSec = 70;
};
};
Then in the pgadmin session
# start user service
systemctl --user start pgadmin
# check status
systemctl --user status pgadmin
# it works so start at boot
systemclt --user enable pgadmin
This way only my user pgadmin can control the service and my podman container is rootless.
2 Likes