Rootless podman-compose configuration

I’m new to NixOS (and not a programmer) and I’m struggling to set up rootless podman-compose on my home server. I’m having 2 main issues with my current configuration:

  1. Overlay error. My root directory is btrfs and podman is using the overlay graph driver (i.e., podman info | grep graphDriverName returns graphDriverName: overlay). This regularly creates a large amount of btrfs subvolumes and results in the overlay error:

ERRO[0000] User-selected graph driver “overlay” overwritten by graph driver “btrfs” from database - delete libpod local files (“/var/lib/containers/storage”) to resolve. May prevent use of images created by other tools

  1. No auto-start on boot. Containers don’t automatically start on boot. This can be manually fixed by logging in and running podman restart -a after a reboot, but it seems like this can be automatically fixed the “Nix way”. I found a guide that proposes a solution, but it involves a new systemd service for every container. I tried enabling the podman-restart service (i.e., systemd.user.services.podman-restart = { enable = true; wantedBy = [ "multi-user.target" ]; };) but that didn’t work/fix it.

Has anyone fixed these issues for setting up a rootless podman? Any advice on what to try to fix these issues?

My podman.nix

{config, pkgs, lib, ...}:
{
  # Enable container support
  virtualisation = {
    podman = {
      enable = true; # Needed to populate /run/user/1000/podman/podman.sock
    };
  };
  # add podman and podman-compose to the system (https://discourse.nixos.org/t/podman-rootless-networking-not-working/40585)
  environment.systemPackages = with pkgs; [ podman podman-compose runc conmon skopeo slirp4netns fuse-overlayfs ];

  # Allow non-root containers to access lower port numbers
  boot.kernel.sysctl."net.ipv4.ip_unprivileged_port_start" = 80;

  # Enable lingering so containers persist after ssh exit
  systemd.tmpfiles.rules = [
    "f /var/lib/systemd/linger/<user-name>"
  ];
}

For fellow noobs like me, to add a second file to your configuration.nix, add ./podman.nix to your imports.

  imports =
    [ # Include the results of the hardware scan.
      ./hardware-configuration.nix
      ./podman.nix
    ];
  1. For the first issue, I think the solution is below.
  # Set graphDriverName to btrfs
  virtualisation.containers.storage.settings = {
    storage = {
      driver = "btrfs";
      graphroot = "/var/lib/containers/storage";
      runroot = "/run/containers/storage";
    };
  };

If it still has the error after switching to this, stop all containers (e.g., reboot since issue 2 isn’t working) and run podman system reset

I’m still looking into auto-starting containers.

To auto-start containers, it’s a bit crude but I am running a command on each boot:

  # Automatically start containers on boot
  systemd.services.podman-autostart = {
    enable = true;
    after = [ "podman.service" ];
    wantedBy = [ "multi-user.target" ];
    description = "Automatically start containers with --restart=always tag";
    serviceConfig = {
      Type = "idle";
      User = "<user-name>";
      ExecStart = ''/run/current-system/sw/bin/podman start --all --filter restart-policy=always'';
    };
  };

I’m not sure if there is a better or more elegant way to do this. For containers I want to auto-start, I tag as “always” and for containers I don’t want to auto-start I tag as “unless-stopped”. I changed the type to idle to make sure the boot process is reasonably far along before running it. I’m sure there is a better way of waiting “long enough”.

My updated podman.nix is below.

{config, pkgs, lib, ...}:
{
  # Enable container support
  virtualisation = {
    podman = {
      enable = true; # Needed to populate /run/user/1000/podman/podman.sock
    };
  };

  # Set graphDriverName to btrfs
  virtualisation.containers.storage.settings = {
    storage = {
      driver = "btrfs";
      graphroot = "/var/lib/containers/storage";
      runroot = "/run/containers/storage";
    };
  };
  # add podman and podman-compose
  environment.systemPackages = with pkgs; [ podman-compose slirp4netns fuse-overlayfs ];

  # Allow non-root containers to access lower port numbers
  boot.kernel.sysctl."net.ipv4.ip_unprivileged_port_start" = 80;

  # Enable lingering so containers persist after ssh exit
  users.users.<user-name>.linger = true;

  # Automatically start containers on boot
  systemd.services.podman-autostart = {
    enable = true;
    after = [ "podman.service" ];
    wantedBy = [ "multi-user.target" ];
    description = "Automatically start containers with --restart=always tag";
    serviceConfig = {
      Type = "idle";
      User = "<user-name>";
      ExecStartPre = ''${pkgs.coreutils}/bin/sleep 1'';
      ExecStart = ''/run/current-system/sw/bin/podman start --all --filter restart-policy=always'';
    };
  };
}