main
  1{
  2  lib,
  3  pkgs,
  4  nix2container,
  5  name,
  6  # NOTE: Skopeo didn't support multi arch image push
  7  tag ? "nixos-${lib.version}-${pkgs.stdenv.system}",
  8}: let
  9  fakeNss = pkgs.dockerTools.fakeNss.override {
 10    extraPasswdLines = [
 11      "podman:x:1000:1000:Podman user:/home/podman:/bin/bash"
 12      "nixbld1:!:999:999:Nix build user 1:/var/empty:/sbin/nologin"
 13      "nixbld2:!:999:999:Nix build user 1:/var/empty:/sbin/nologin"
 14      "nixbld3:!:999:999:Nix build user 1:/var/empty:/sbin/nologin"
 15      "nixbld4:!:999:999:Nix build user 1:/var/empty:/sbin/nologin"
 16      "nixbld5:!:999:999:Nix build user 1:/var/empty:/sbin/nologin"
 17      "nixbld6:!:999:999:Nix build user 1:/var/empty:/sbin/nologin"
 18      "nixbld7:!:999:999:Nix build user 1:/var/empty:/sbin/nologin"
 19      "nixbld8:!:999:999:Nix build user 1:/var/empty:/sbin/nologin"
 20      "nixbld9:!:999:999:Nix build user 1:/var/empty:/sbin/nologin"
 21      "nixbld10:!:999:999:Nix build user 1:/var/empty:/sbin/nologin"
 22    ];
 23    extraGroupLines = [
 24      "podman:x:1000:podman"
 25      "nixbld:x:999:nixbld1,nixbld2,nixbld3,nixbld4,nixbld5,nixbld6,nixbld7,nixbld8,nixbld9,nixbld10"
 26    ];
 27  };
 28
 29  mkNixConf = pkgs.runCommand "nix-act-image-etc" {} ''
 30    mkdir -p $out/etc/nix
 31    echo "experimental-features = nix-command flakes" > $out/etc/nix/nix.conf
 32  '';
 33
 34  mkTmp = pkgs.runCommand "nix-act-image-tmp" {} ''
 35    mkdir -p $out/tmp
 36    mkdir -p $out/var/tmp
 37  '';
 38
 39  mkPodmanConfig = pkgs.runCommand "podman-config" {} ''
 40    mkdir -p $out/etc/containers
 41    mkdir -p $out/home/podman
 42    mkdir -p $out/var/lib/containers
 43    mkdir -p $out/var/lib/shared/overlay-images
 44    mkdir -p $out/var/lib/shared/overlay-layers
 45    mkdir -p $out/var/lib/shared/vfs-images
 46    mkdir -p $out/var/lib/shared/vfs-layers
 47    mkdir -p $out/run
 48
 49    touch $out/var/lib/shared/overlay-images/images.lock
 50    touch $out/var/lib/shared/overlay-layers/layers.lock
 51    touch $out/var/lib/shared/vfs-images/images.lock
 52    touch $out/var/lib/shared/vfs-layers/layers.lock
 53
 54    cat > $out/etc/containers/containers.conf << 'EOF'
 55    [containers]
 56    netns="host"
 57    userns="host"
 58    ipcns="host"
 59    utsns="host"
 60    cgroupns="host"
 61    cgroups="disabled"
 62    log_driver = "k8s-file"
 63    [engine]
 64    cgroup_manager = "cgroupfs"
 65    events_logger="file"
 66    runtime="crun"
 67    EOF
 68
 69    cat > $out/etc/containers/containers.conf.rootless << 'EOF'
 70    [containers]
 71    volumes = [
 72      "/proc:/proc",
 73    ]
 74    default_sysctls = []
 75    EOF
 76
 77    cat > $out/etc/containers/storage.conf << 'EOF'
 78    [storage]
 79    driver = "overlay"
 80    runroot = "/run/containers/storage"
 81    graphroot = "/var/lib/containers/storage"
 82    [storage.options]
 83    mount_program = "${pkgs.fuse-overlayfs}/bin/fuse-overlayfs"
 84    mountopt = "nodev,fsync=0"
 85    additionalimagestores = [
 86      "/var/lib/shared",
 87    ]
 88    [storage.options.overlay]
 89    ignore_chown_errors = "true"
 90    EOF
 91
 92    cat > $out/etc/containers/mounts.conf << 'EOF'
 93    /run/secrets/etc-pki-entitlement:/run/secrets/etc-pki-entitlement
 94    /run/secrets/rhsm:/run/secrets/rhsm
 95    EOF
 96
 97    cat > $out/etc/containers/policy.json << 'EOF'
 98    {"default":[{"type":"insecureAcceptAnything"}]}
 99    EOF
100  '';
101
102  mkSubugid = pkgs.runCommand "subugid" {} ''
103    mkdir -p $out/etc
104    cat > $out/etc/subuid << 'EOF'
105    root:1:999
106    root:1001:64535
107    podman:1:999
108    podman:1001:64535
109    EOF
110    cat > $out/etc/subgid << 'EOF'
111    root:1:999
112    root:1001:64535
113    podman:1:999
114    podman:1001:64535
115    EOF
116  '';
117
118  podmanDockerCompat =
119    pkgs.runCommand "${pkgs.podman.pname}-docker-compat-${pkgs.podman.version}"
120    {
121      nativeBuildInputs = [pkgs.installShellFiles];
122      outputs = [
123        "out"
124        "man"
125      ];
126      inherit (pkgs.podman) meta;
127      preferLocalBuild = true;
128    }
129    (
130      ''
131        mkdir -p $out/bin
132        ln -s ${pkgs.podman}/bin/podman $out/bin/docker
133
134        mkdir -p $man/share/man/man1
135        for f in ${pkgs.podman.man}/share/man/man1/*; do
136          basename=$(basename $f | sed s/podman/docker/g)
137          ln -s $f $man/share/man/man1/$basename
138        done
139      ''
140      + lib.optionalString (pkgs.stdenv.buildPlatform.canExecute pkgs.stdenv.hostPlatform) ''
141        export HOME=$(mktemp -d) # work around `docker <cmd>`
142        installShellCompletion --cmd docker \
143          --bash <($out/bin/docker completion bash) \
144          --zsh <($out/bin/docker completion zsh) \
145          --fish <($out/bin/docker completion fish)
146      ''
147    );
148in
149  nix2container.buildImage {
150    inherit name tag;
151
152    initializeNixDatabase = true;
153    maxLayers = 100;
154
155    copyToRoot = [
156      (pkgs.buildEnv {
157        name = "root";
158        paths = with pkgs; [
159          bash
160          coreutils
161          dockerTools.caCertificates
162          dockerTools.usrBinEnv
163          fakeNss
164          mkNixConf
165          mkTmp
166          nix
167          nodejs_24
168
169          aria2
170          cacert
171          curl
172          dnsutils
173          openssh
174          wget
175
176          gitMinimal
177          git-lfs
178
179          gnutar
180          gzip
181          p7zip
182          unzip
183          xz
184          zip
185          zstd
186
187          autoconf
188          automake
189          gcc
190          gnumake
191          m4
192          patchelf
193
194          binutils
195          file
196          findutils
197          gawk
198          gnugrep
199          gnupg
200          gnused
201          jq
202          parallel
203          python3
204          rsync
205          sqlite
206          sudo
207          tree
208          yq
209
210          fuse-overlayfs
211          mkPodmanConfig
212          podman
213          podmanDockerCompat
214          shadow
215        ];
216      })
217      mkSubugid
218    ];
219    perms = [
220      {
221        path = mkTmp;
222        regex = ".*";
223        mode = "1777";
224      }
225      {
226        path = mkPodmanConfig;
227        regex = "home/podman";
228        mode = "0777";
229      }
230      {
231        path = pkgs.shadow;
232        regex = "bin/new[ug]idmap";
233        mode = "4555";
234      }
235    ];
236    config = {
237      Entrypoint = ["/bin/bash"];
238      Env = [
239        "USER=root"
240        "HOME=/"
241        "PATH=/bin"
242        "NIX_PAGER=cat"
243        "SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
244        "DOCKER_HOST=unix:///run/user/1000/podman/podman.sock"
245        "CONTAINERS_STORAGE=/var/lib/containers/storage"
246        "_CONTAINERS_USERNS_CONFIGURED="
247        "BUILDAH_ISOLATION=chroot"
248      ];
249      Labels = {
250        "org.opencontainers.image.source" = "https://codeberg.org/HPCesia/nix-act-image";
251        "org.opencontainers.image.description" = "A Nix based container for Forgejo Actions";
252        "org.opencontainers.image.licenses" = lib.licenses.mit.spdxId;
253      };
254    };
255  }