OFFSET偏移
← All articlesOFFSET / FIELD NOTESNO. 125

Managing Podman on NixOS

Declare container runtime environments through system modules, Home Manager, or quadlet-nix.

English translation · Code and commands follow the Chinese original.

IN THESE READING PATHSPodman container workflows ↗
About 4 min readStart reading

This article retains the historical scope of NixOS 25.05 issues and corrects configuration interfaces against current official modules. Before use, check the project’s pinned nixpkgs, Home Manager, and quadlet-nix revisions. No system was evaluated or activated for this article.


Choosing an approach: three paths#

There are three approaches to managing Podman on NixOS, in increasing order of complexity:

graph TD
    A["想在 NixOS 上用 Podman"] --> B{"如何管理容器?"}
    B -->|"临时运行"| C["virtualisation.podman<br/>系统级配置"]
    B -->|"持久服务"| D{"偏好哪种配置方式?"}
    D -->|"Home Manager"| E["services.podman<br/>Home Manager 模块"]
    D -->|"纯 Nix 声明式"| F["quadlet-nix<br/>第三方 Flake"]

Approach 1: system-level Podman (simplest)#

Add this directly to configuration.nix:

{ config, pkgs, ... }:

{
  # 启用容器支持
  virtualisation.containers.enable = true;

  virtualisation.podman = {
    enable = true;
    # Docker CLI 兼容(创建 docker → podman 软链接)
    dockerCompat = true;
    # DNS 解析
    defaultNetwork.settings.dns_enabled = true;
  };

}
# 配置完成后先评估/构建;是否激活由管理员单独决定
nix flake check --no-build
nixos-rebuild dry-build --flake .#workstation
# 激活后的独立检查
podman --version

Enabling Podman through the system module does not force rootful operation: ordinary users can run it rootlessly, and whether sudo is needed depends on the intended workflow. Membership in the podman group is not a prerequisite for rootless operation. When the system Docker-compatible socket is enabled, group access to it may grant root-level management capabilities, so do not add users casually.


Approach 2: rootless Podman with Home Manager (recommended)#

2.1 Enable Podman at the system level first

# configuration.nix
{
  virtualisation.containers.enable = true;
  virtualisation.podman.enable = true;
  virtualisation.podman.dockerCompat = true;
  virtualisation.podman.defaultNetwork.settings.dns_enabled = true;

  # 不全局重写用户PATH;由所用模块/生成unit提供程序及newuidmap等依赖
}

2.2 User setup

# 在 users.users 中
users.users.user = {
  isNormalUser = true;
  linger = true;  # ← 关键!允许用户服务在登录前启动
  # subUidRanges/subGidRanges — 为用户分配 UID 范围(rootless 的前提)
  subUidRanges = [{ startUid = 100000; count = 65536; }];
  subGidRanges = [{ startGid = 100000; count = 65536; }];
};

2.3 Home Manager configuration

# home.nix 或 home-manager 模块
{ pkgs, ... }: {
  services.podman = {
    enable = true;
    # 启用自动更新定时器
    autoUpdate.enable = true;
  };

  # 声明式网络
  services.podman.networks = {
    webnet = {
      driver = "bridge";
      subnet = "192.0.2.0/24"; # 文档示例;实际选不冲突的容器网段
    };
  };
}
# standalone Home Manager先build;NixOS集成模式随系统配置构建
home-manager build
# 经授权激活后另查运行时timer
systemctl --user status podman-auto-update.timer

2.4 Declarative containers

services.podman.containers = {
  myweb = {
    image = "docker.io/library/nginx:alpine";
    autoStart = true;
    autoUpdate = "registry";
    ports = [ "127.0.0.1:8080:80" ];
    volumes = [
      "/path/to/dedicated-data:/usr/share/nginx/html:ro,Z"
    ];
    environment = {
      MYVAR = "hello";
    };
  };
};

Approach 3: quadlet-nix (advanced, native Quadlet)#

quadlet-nix is a Nix Flake that maps Podman’s Quadlet functionality to declarative Nix syntax.

Basic usage

# flake.nix:standalone Home Manager示例;不是nixosSystem构造homeConfigurations
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    home-manager.url = "github:nix-community/home-manager";
    home-manager.inputs.nixpkgs.follows = "nixpkgs";
    quadlet-nix.url = "github:SEIAROTg/quadlet-nix";
  };
  outputs = { nixpkgs, home-manager, quadlet-nix, ... }: {
    homeConfigurations.user = home-manager.lib.homeManagerConfiguration {
      pkgs = import nixpkgs { system = "x86_64-linux"; };
      modules = [
        quadlet-nix.homeManagerModules.quadlet
        ({ config, ... }: {
          home.username = "user";
          home.homeDirectory = "/home/user";
          home.stateVersion = "25.05"; # 使用账户实际首次配置版本,不随升级随意改
          virtualisation.quadlet = {
            containers.echo-server = {
              autoStart = true;
              containerConfig = {
                image = "docker.io/mendhak/http-https-echo:31";
                publishPorts = [ "127.0.0.1:8080:8080" ];
                userns = "keep-id";
                networks = [ config.virtualisation.quadlet.networks.mynet.ref ];
              };
            };
            networks.mynet.networkConfig.driver = "bridge";
            volumes.mydata = { };
          };
        })
      ];
    };
  };
}

Result: quadlet-nix automatically generates the corresponding .container/.network/.volume Quadlet files, which are managed by systemd.


Known issues in NixOS 25.05#

A bug in oci-containers + podman.user

The virtualisation.oci-containers.containers.<name>.podman.user feature in NixOS 25.05 has a known issue (nixpkgs #410857):

  • The systemd service may report Failed with result 'protocol'
  • In some scenarios, the container still runs as root

This issue is a historical record for the 25.05 release and affected scenarios. It does not establish that all current rootless oci-containers setups fail. First compare the implementation in your pinned branch with the issue’s status. If user-level management is needed, assess Home Manager or quadlet-nix while retaining the existing setup and a recovery path.

Volume permission issues

Directory ownership can cause problems when rootless containers mount volumes:

# 先核对容器应用UID映射和宿主目录权限
# 可用Home Manager的systemd.user.tmpfiles.rules管理专用目录,但不替代UID映射核对

Quick comparison#

Need Which approach to use
Run a one-off container quickly podman run (installation is enough)
Development environment Approach 1 + podman-compose
Stable rootless container services Approach 2 (Home Manager services.podman)
Pure declarative Nix + full Quadlet functionality Approach 3 (quadlet-nix)
Already using Docker Compose Keep the compose file and use podman-compose


Enabling the system module, generating Home Manager configuration, building, activating, and observing actual container behavior are separate verification layers. The examples assume that the host already provides the prerequisites for user namespaces/newuidmap; standalone Home Manager cannot replace every system prerequisite. Check subUID/GID ranges for conflicts, and do not simply change ranges when migrating existing storage. Set linger only when services need to run before login. The current Home Manager Podman module can generate Quadlet resources, so do not treat “Home Manager” and “Quadlet” as permanently mutually exclusive architectures. Use the actual generated output to determine service names. Nothing above automatically ran switch or deployed containers.

The current upstream Home Manager autoUpdate service also runs image prune -f after updating. Before enabling it, inspect the ExecStart/ExecStartPost generated by your pinned version, the schedule, and your image-retention requirements.

References & further reading

  1. Official Podman run manual ↗
  2. Official Podman overview and rootless documentation ↗
  3. NixOS 25.05 Podman module ↗
  4. Home Manager Podman module ↗
  5. Official quadlet-nix documentation ↗
  6. Historical NixOS 25.05 issue ↗

Adapted from technical notes. Examples use generic names.

Continue along a reading path

Podman container workflows

  1. 01Podman fundamentals
  2. 02A basic Podman usage guide
  3. 03Rootless containers: whose file permissions count?
  4. 04Rootless configuration: mappings, ICMP, and registries
  5. 05Pods and Kubernetes manifests
  6. 06How does Quadlet turn container declarations into services?
  7. 07Pods and multi-service configuration with Quadlet
  8. 08Compose providers and interoperability with Docker tools
  9. 09Managing Podman on NixOS
  10. 10Advanced Podman operations and tuning
  11. 11Docker and Podman: architecture, compatibility, and coexistence
CONTINUE READING / NEXT ARTICLEAdvanced Podman operations and tuning

Manage resources, health, image toolchains, logs, and storage cleanup.