diff --git a/nixos/modules/virtualisation/podman.nix b/nixos/modules/virtualisation/podman.nix index e879b5ad8f9f..edf4bbe079a3 100644 --- a/nixos/modules/virtualisation/podman.nix +++ b/nixos/modules/virtualisation/podman.nix @@ -46,6 +46,20 @@ in ''; }; + dockerSocket.enable = mkOption { + type = types.bool; + default = false; + description = '' + Make the Podman socket available in place of the Docker socket, so + Docker tools can find the Podman socket. + + Podman implements the Docker API. + + Users must be in the podman group in order to connect. As + with Docker, members of this group can gain root access. + ''; + }; + dockerCompat = mkOption { type = types.bool; default = false; @@ -123,6 +137,11 @@ in >$out/lib/tmpfiles.d/podman.conf '') ]; + systemd.tmpfiles.rules = + lib.optionals cfg.dockerSocket.enable [ + "L! /run/docker.sock - - - - /run/podman/podman.sock" + ]; + users.groups.podman = {}; assertions = [ @@ -130,6 +149,12 @@ in assertion = cfg.dockerCompat -> !config.virtualisation.docker.enable; message = "Option dockerCompat conflicts with docker"; } + { + assertion = cfg.dockerSocket.enable -> !config.virtualisation.docker.enable; + message = '' + The options virtualisation.podman.dockerSocket.enable and virtualisation.docker.enable conflict, because only one can serve the socket. + ''; + } ]; } ]); diff --git a/nixos/tests/podman.nix b/nixos/tests/podman.nix index 6078a936edea..343ecbe14b2d 100644 --- a/nixos/tests/podman.nix +++ b/nixos/tests/podman.nix @@ -13,10 +13,23 @@ import ./make-test-python.nix ( { virtualisation.podman.enable = true; + # To test docker socket support + virtualisation.podman.dockerSocket.enable = true; + environment.systemPackages = [ + pkgs.docker-client + ]; + users.users.alice = { isNormalUser = true; home = "/home/alice"; description = "Alice Foobar"; + extraGroups = [ "podman" ]; + }; + + users.users.mallory = { + isNormalUser = true; + home = "/home/mallory"; + description = "Mallory Foobar"; }; }; @@ -26,9 +39,9 @@ import ./make-test-python.nix ( import shlex - def su_cmd(cmd): + def su_cmd(cmd, user = "alice"): cmd = shlex.quote(cmd) - return f"su alice -l -c {cmd}" + return f"su {user} -l -c {cmd}" podman.wait_for_unit("sockets.target") @@ -105,6 +118,26 @@ import ./make-test-python.nix ( assert pid == "1" pid = podman.succeed("podman run --rm --init busybox readlink /proc/self").strip() assert pid == "2" + + with subtest("A podman member can use the docker cli"): + podman.succeed(su_cmd("docker version")) + + with subtest("Run container via docker cli"): + podman.succeed("docker network create default") + podman.succeed("tar cv --files-from /dev/null | podman import - scratchimg") + podman.succeed( + "docker run -d --name=sleeping -v /nix/store:/nix/store -v /run/current-system/sw/bin:/bin scratchimg /bin/sleep 10" + ) + podman.succeed("docker ps | grep sleeping") + podman.succeed("podman ps | grep sleeping") + podman.succeed("docker stop sleeping") + podman.succeed("docker rm sleeping") + + with subtest("A podman non-member can not use the docker cli"): + podman.fail(su_cmd("docker version", user="mallory")) + + # TODO: add docker-compose test + ''; } )