Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

nix-oci

nix-oci is a flake-parts module designed to streamline the management of OCI (Open Container Initiative) repositories using the Nix package manager. By leveraging nix2container as its backend, nix-oci facilitates the declarative creation and handling of container images, ensuring reproducibility and efficiency in containerized environments.

Installation

See the readme.

Options

oci.enableDevShell

Whether to enable the flake development shell.

Type: boolean

Default:

false

Declared by:

oci.enableFlakeOutputs

Whether to automatically expose OCI apps, packages, and checks as flake outputs.

Type: boolean

Default:

true

Example:

false

Declared by:

oci.enabled

Whether to enable Enable the OCI module…

Type: boolean

Default:

false

Example:

true

Declared by:

oci.flake.outputs.packages

Expose oci-<name> gated image packages.

Type: boolean

Default:

true

Declared by:

oci.flake.outputs.checks

Expose oci-gate-<name> checks. Disabled by default since the gate is already enforced by packages and apps.

Type: boolean

Default:

false

Declared by:

oci.flake.outputs.loadDocker

Expose oci-load-docker-<name> apps (load into Docker).

Type: boolean

Default:

true

Declared by:

oci.flake.outputs.loadPodman

Expose oci-load-podman-<name> apps (load into Podman).

Type: boolean

Default:

true

Declared by:

oci.flake.outputs.push

Expose oci-push-<name> apps (push to registry).

Type: boolean

Default:

true

Declared by:

oci.flake.outputs.sandbox

Expose oci-sandbox-<name> apps (bubblewrap shell).

Type: boolean

Default:

true

Declared by:

perSystem.oci.packages.amicontained

The package to use for amicontained.

Type: package

Default:

amicontained v0.4.9 static binary

Example:

amicontained v0.4.9 static binary

Declared by:

perSystem.oci.packages.cdk

The package to use for CDK.

Type: package

Default:

cdk v1.5.4 static binary

Example:

cdk v1.5.4 static binary

Declared by:

perSystem.oci.packages.conftest

The package to use for conftest.

Type: package

Default:

pkgs.conftest

Example:

pkgs.conftest

Declared by:

perSystem.oci.packages.containerStructureTest

The package to use for container-structure-test.

Type: package

Default:

pkgs.container-structure-test

Example:

pkgs.container-structure-test

Declared by:

perSystem.oci.packages.cosign

The package to use for cosign.

Type: package

Default:

pkgs.cosign

Example:

pkgs.cosign

Declared by:

perSystem.oci.packages.deepce

The package to use for deepce.

Type: package

Default:

deepce v0.1.0

Example:

deepce v0.1.0

Declared by:

perSystem.oci.packages.dgoss

The package to use for dgoss.

Type: package

Default:

pkgs.dgoss

Example:

pkgs.dgoss

Declared by:

perSystem.oci.packages.dive

The package to use for dive.

Type: package

Default:

pkgs.dive

Example:

pkgs.dive

Declared by:

perSystem.oci.packages.dockle

The package to use for dockle.

Type: package

Default:

pkgs.dockle

Example:

pkgs.dockle

Declared by:

perSystem.oci.packages.grype

The package to use for grype.

Type: package

Default:

pkgs.grype

Example:

pkgs.grype

Declared by:

perSystem.oci.packages.linpeas

The package to use for linpeas.

Type: package

Default:

linpeas 20260604

Example:

linpeas 20260604

Declared by:

perSystem.oci.packages.nix2container

The nix2container package.

Type: attribute set

Default:

inputs.nix2container.packages.${system}.nix2container

Example:

inputs.nix2container.packages.${system}.nix2container

Declared by:

perSystem.oci.packages.podman

The package to use for podman.

Type: package

Default:

pkgs.podman

Example:

pkgs.podman

Declared by:

perSystem.oci.packages.regctl

The package to use for regctl (multi-arch manifest tool).

Type: package

Default:

pkgs.regclient

Example:

pkgs.regclient

Declared by:

perSystem.oci.packages.skaffold

The package to use for skaffold.

Type: package

Default:

pkgs.skaffold

Example:

pkgs.skaffold

Declared by:

perSystem.oci.packages.skopeo

The package to use for skopeo.

Type: package

Default:

inputs.nix2container.packages.${system}.skopeo-nix2container

Example:

inputs.nix2container.packages.${system}.skopeo-nix2container

Declared by:

perSystem.oci.packages.skopeoTurbo

The turbo-patched skopeo package from nix2container-turbo. Null when the input is not available.

Type: null or package

Default:

inputs.nix2container-turbo.packages.${system}.skopeo

Declared by:

perSystem.oci.packages.soci-snapshotter

The package providing soci and soci-snapshotter-grpc binaries.

Type: package

Default:

soci-snapshotter v0.14.1 static binaries

Example:

soci-snapshotter v0.14.1 static binaries

Declared by:

perSystem.oci.packages.syft

The package to use for syft.

Type: package

Default:

pkgs.syft

Example:

pkgs.syft

Declared by:

perSystem.oci.packages.trivy

The package to use for trivy.

Type: package

Default:

pkgs.trivy

Example:

pkgs.trivy

Declared by:

perSystem.oci.packages.vulnix

The package to use for vulnix.

Type: package

Default:

pkgs.vulnix

Example:

pkgs.vulnix

Declared by:

perSystem.oci.containers

Container definitions. Each key is a container name.

Type: attribute set of (submodule)

Default:

{ }

Example:

{
  my-app = {
    package = pkgs.hello;
    dependencies = [ pkgs.bash ];
  };
}

Declared by:

perSystem.oci.containers.<name>.package

The main package for the container.

Type: null or package

Default:

null

Example:

pkgs.hello

Declared by:

perSystem.oci.containers.<name>.autoLabels

Whether to automatically generate OCI image labels from package metadata.

When enabled, the following labels are generated (user labels always override):

  • OCI standard annotations (org.opencontainers.image.*): title, version, description, licenses, base.name
  • Build info (io.github.dauliac.nix-oci.build.*): system, optimized-layers, reproducible
  • Hardening hints (io.github.dauliac.nix-oci.hardening.*): security posture
  • Kubernetes PSS level (io.github.dauliac.nix-oci.kubernetes.pod-security-standard)

Type: boolean

Default:

true

Declared by:

perSystem.oci.containers.<name>.compliance.trivy.enabled

Whether to enable CIS compliance checking with Trivy.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.compliance.trivy.report

Compliance report format: all for detailed results or summary for a condensed overview.

Type: one of “all”, “summary”

Default:

"summary"

Declared by:

perSystem.oci.containers.<name>.compliance.trivy.spec

The compliance spec to check against. See trivy image --help for built-in specs.

Type: string

Default:

"docker-cis-1.6.0"

Example:

"docker-cis-1.6.0"

Declared by:

perSystem.oci.containers.<name>.credentialsLeak.configPath

Path where global credentials leak check configuration files will be stored.

Type: absolute path

Default:

config.rootPath + "/credentials-leak/"

Declared by:

perSystem.oci.containers.<name>.credentialsLeak.trivy.enabled

Whether to enable credentials leak detection with Trivy.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.cve.configPath

Path where CVE scanner configuration files will be stored.

Type: absolute path

Default:

config.rootPath

Declared by:

perSystem.oci.containers.<name>.cve.grype.enabled

Whether to enable CVE scanning with Grype.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.cve.grype.config.enabled

Whether to enable Grype configuration file generation.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.cve.grype.config.rootPath

Path where Grype configuration files will be stored.

Type: absolute path

Default:

config.cve.configPath + "/grype/"

Declared by:

perSystem.oci.containers.<name>.cve.trivy.enabled

Whether to enable CVE scanning with Trivy.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.cve.trivy.ignore.extra

Additional CVE identifiers to ignore globally in Trivy scans.

Type: list of string

Default:

[ ]

Declared by:

perSystem.oci.containers.<name>.cve.trivy.ignore.fileEnabled

Whether to enable Trivy CVE ignore file generation.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.cve.trivy.ignore.rootPath

Path where Trivy CVE ignore files will be stored.

Type: absolute path

Default:

config.cve.configPath

Declared by:

perSystem.oci.containers.<name>.cve.vulnix.enabled

Whether to enable CVE scanning with vulnix.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.cve.vulnix.whitelist.enabled

Whether to enable vulnix whitelist file.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.cve.vulnix.whitelist.rootPath

Path where vulnix whitelist files will be stored.

Type: absolute path

Default:

config.cve.configPath + "/vulnix/"

Declared by:

perSystem.oci.containers.<name>.declaredVolumes

OCI volume mount point declarations baked into the image manifest. These tell the container runtime which paths contain persistent data.

For NixOS containers, auto-derived from systemd service directories:

  • StateDirectory → /var/lib/<dir>
  • RuntimeDirectory → /run/<dir>
  • CacheDirectory → /var/cache/<dir>
  • LogsDirectory → /var/log/<dir>

This is separate from deploy-time volumes (host bind mounts).

Type: list of string

Default: Auto-derived from systemd service directories:

  • StateDirectory/var/lib/<dir>
  • RuntimeDirectory/run/<dir>
  • CacheDirectory/var/cache/<dir>
  • LogsDirectory/var/log/<dir>

Example:

[
  "/var/lib/postgresql"
  "/var/log/nginx"
]

Declared by:

perSystem.oci.containers.<name>.dependencies

Additional dependencies packages to include in the container.

Type: list of package

Default:

[ ]

Example:

[ pkgs.bash pkgs.coreutils ]

Declared by:

perSystem.oci.containers.<name>.entrypoint

OCI entrypoint (command + arguments).

Full container example:

{ pkgs, ... }:
{
  package = pkgs.python3;
  entrypoint = [
    "${pkgs.python3}/bin/python3"
    "-m"
    "http.server"
    "8080"
  ];
}

Type: list of string

Default:

[ ]

Example:

[
  "/bin/hello"
  "--greeting"
  "world"
]

Declared by:

perSystem.oci.containers.<name>.environment

Environment variables baked into the OCI manifest and passed to the runner.

Type: attribute set of string

Default:

{ }

Example:

{
  RUST_LOG = "info";
}

Declared by:

perSystem.oci.containers.<name>.gid

GID for the non-root container user’s primary group.

Only used when isRoot = false. The default (4000) matches the default UID to keep user/group mapping simple.

Type: signed integer

Default:

4000

Example:

1000

Declared by:

perSystem.oci.containers.<name>.gpu.enable

Enable NVIDIA GPU support for this container.

When enabled, sets environment variables that trigger the NVIDIA Container Toolkit runtime injection (NVIDIA_VISIBLE_DEVICES, NVIDIA_DRIVER_CAPABILITIES) and includes CUDA runtime libraries from nixpkgs in the container image.

Compatible with the NVIDIA GPU Operator in Kubernetes – images built with this option work with both legacy (env-var) and CDI (Container Device Interface) injection modes.

Driver libraries (libcuda.so, libnvidia-ml.so, nvidia-smi) are NOT bundled – they are always injected at runtime by the host’s NVIDIA Container Toolkit.

Requires nixpkgs.config.cudaSupport = true and nixpkgs.config.allowUnfree = true in the consuming flake.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.gpu.capabilities

NVIDIA driver capabilities to request at runtime.

Each capability controls which host driver libraries the NVIDIA Container Toolkit bind-mounts into the container:

  • "compute" – CUDA and OpenCL libraries.
  • "utility" – Management tools (nvidia-smi, libnvidia-ml.so).
  • "graphics" – OpenGL, EGL, Vulkan, OptiX libraries.
  • "video" – Hardware video codec libraries (NVENC/NVDEC).
  • "display" – X11 display output libraries.
  • "all" – All capabilities above.

Default: ["compute" "utility"] (CUDA compute + nvidia-smi).

Type: list of (one of “compute”, “utility”, “graphics”, “video”, “display”, “all”)

Default:

[
  "compute"
  "utility"
]

Declared by:

perSystem.oci.containers.<name>.gpu.cudaVersion

Minimum CUDA version constraint.

When set, the NVIDIA_REQUIRE_CUDA environment variable is added to the image config (e.g. cuda>=12.2). The NVIDIA Container Toolkit validates this against the host driver before allowing the container to start.

When null (default), the version is auto-detected from the cudaPackages in nixpkgs.

Type: null or string

Default:

null

Example:

"12.2"

Declared by:

perSystem.oci.containers.<name>.gpu.forwardCompat

Include CUDA forward compatibility libraries in the image.

When enabled, the cuda-compat package is added and LD_LIBRARY_PATH is configured so compat libraries take precedence over the host-injected driver libraries.

This allows the container to use a newer CUDA toolkit than the host driver natively supports. Useful when deploying to clusters where driver upgrades are infrequent.

Not all features are forward-compatible – some require kernel-mode driver support for new hardware capabilities.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.gpu.runtimeLibraries

CUDA toolkit libraries to include in the container image.

  • "cudart" – CUDA runtime (libcudart.so). Almost always needed.
  • "cublas" – cuBLAS linear algebra.
  • "cufft" – cuFFT Fourier transforms.
  • "curand" – cuRAND random number generation.
  • "cusolver" – cuSOLVER dense/sparse solvers.
  • "cusparse" – cuSPARSE sparse matrix operations.
  • "cudnn" – cuDNN deep learning primitives.
  • "tensorrt" – TensorRT inference optimization.
  • "nccl" – NCCL multi-GPU/node communication.
  • "cutlass" – CUTLASS GEMM templates.
  • "nvjpeg" – nvJPEG hardware JPEG decoding.

Only selected libraries are included to minimize image size. Driver libraries (libcuda.so) are never bundled.

Type: list of (one of “cudart”, “cublas”, “cufft”, “curand”, “cusolver”, “cusparse”, “cudnn”, “tensorrt”, “nccl”, “cutlass”, “nvjpeg”)

Default:

[
  "cudart"
]

Example:

[
  "cudart"
  "cublas"
  "cudnn"
]

Declared by:

perSystem.oci.containers.<name>.hardening.enable

Enable container security hardening.

When enabled, applies build-time filesystem restrictions and generates runtime security hints consumed by deploy modules.

Three independent kernel primitives are available:

  • Seccomp – syscall filtering (BPF at the syscall boundary)
  • AppArmor – mandatory access control (LSM pathname-based)
  • Capabilities + flags – privilege restriction at runtime

For containers using nixosConfig, these options are forwarded to the inner NixOS module at oci.container.hardening and can be overridden through NixOS module composition.

Full container example:

{
  package = pkgs.busybox;
  isRoot = true;
  hardening = {
    enable = true;
    disableDns = true;
    noTlsTrustStore = true;
    seccomp = {
      enable = true;
      profile = "strict";
    };
    capabilities = {
      drop = [ "ALL" ];
      add = [ "NET_BIND_SERVICE" ];
    };
    readOnlyRootfs = true;
    noNewPrivileges = true;
  };
}

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.hardening.apparmor

AppArmor MAC profile configuration.

Type: submodule

Default:

{ }

Declared by:

perSystem.oci.containers.<name>.hardening.apparmor.enable

Enable AppArmor profile generation for this container.

When enabled, a tailored AppArmor profile is generated as a build output. The deploy module references it via --security-opt apparmor=<profile>.

Requires the target host to have AppArmor enabled (kernel LSM + apparmor_parser). On NixOS, set security.apparmor.enable = true.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.hardening.apparmor.customProfile

Path to a custom AppArmor profile file. When set, overrides ALL computed profile rules. The profile must be a valid AppArmor profile file.

Note: cross-backend coherence checks cannot verify custom profiles — you take full responsibility for correctness.

Type: null or absolute path

Default:

null

Declared by:

perSystem.oci.containers.<name>.hardening.apparmor.denyMount

Deny mount operations inside the container.

Prevents filesystem remounting, overlay stacking, and bind-mount escape attacks. Enforced via AppArmor deny mount, rule.

Type: boolean

Default:

true

Declared by:

perSystem.oci.containers.<name>.hardening.apparmor.denyPtrace

Deny ptrace of other processes.

Prevents process inspection and memory manipulation attacks. Enforced via AppArmor deny ptrace (read, read, trace, traceby), rule.

Type: boolean

Default:

true

Declared by:

perSystem.oci.containers.<name>.hardening.apparmor.denyUserNamespace

Deny user namespace creation inside the container.

Prevents the class of Local Privilege Escalation (LPE) vulnerabilities where unprivileged processes exploit userns to reach normally-root-only kernel code paths (CVE-2023-2640, CVE-2023-32629, etc.).

Enforced via AppArmor deny userns_create, rule. Complementary to seccomp clone(CLONE_NEWUSER) arg filter and capability drop SYS_ADMIN.

Type: boolean

Default:

true

Declared by:

perSystem.oci.containers.<name>.hardening.apparmor.mode

AppArmor enforcement mode:

  • "enforce" – violations are blocked and logged (default). Use for production.
  • "complain" – violations are logged but NOT blocked. Useful for profile discovery before switching to enforce.

Type: one of “enforce”, “complain”

Default:

"enforce"

Declared by:

perSystem.oci.containers.<name>.hardening.capabilities

Linux capability restrictions applied at runtime by deploy modules.

Type: submodule

Default:

{ }

Declared by:

perSystem.oci.containers.<name>.hardening.capabilities.add

Linux capabilities to add back after dropping. Deploy modules translate to --cap-add.

Type: list of string

Default:

[ ]

Example:

[
  "NET_BIND_SERVICE"
]

Declared by:

perSystem.oci.containers.<name>.hardening.capabilities.drop

Linux capabilities to drop. Defaults to ["ALL"]. Deploy modules translate to --cap-drop.

Type: list of string

Default:

[
  "ALL"
]

Declared by:

perSystem.oci.containers.<name>.hardening.disableDns

Disable DNS resolution inside the container.

Sets /etc/nsswitch.conf hosts line to files only (no dns backend). Applications using IP addresses directly are unaffected.

NOTE: /etc/resolv.conf is NOT written into the image because container runtimes (Docker, Podman) always bind-mount it at startup, masking any baked-in content. To fully enforce DNS restriction at runtime, use --dns=127.0.0.1 or network policies.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.hardening.noNewPrivileges

Set the no_new_privs bit. Prevents privilege escalation via setuid/setgid binaries or file capabilities.

Deploy modules translate to --security-opt=no-new-privileges.

Type: boolean

Default:

true

Declared by:

perSystem.oci.containers.<name>.hardening.noTlsTrustStore

Remove the TLS certificate trust store (/etc/ssl/certs). Prevents all outgoing HTTPS connections.

Only use for containers that never initiate TLS connections. This is a nuclear option – most applications that make any outbound HTTP requests will break.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.hardening.readOnlyRootfs

Mount the container root filesystem as read-only at runtime. Deploy modules translate to --read-only.

Prevents attackers from writing malware or achieving persistence if they gain initial access.

Type: boolean

Default:

true

Declared by:

perSystem.oci.containers.<name>.hardening.seccomp

Seccomp syscall filtering configuration.

Full container example:

{
  package = pkgs.busybox;
  hardening = {
    enable = true;
    seccomp = {
      enable = true;
      profile = "web-server";
      mode = "enforce";
    };
  };
}

Type: submodule

Default:

{ }

Declared by:

perSystem.oci.containers.<name>.hardening.seccomp.enable

Enable a custom seccomp profile for this container.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.hardening.seccomp.customProfileJson

Path to a custom seccomp profile JSON file following the OCI runtime specification format. When set, overrides the profile option.

Type: null or absolute path

Default:

null

Declared by:

perSystem.oci.containers.<name>.hardening.seccomp.mode

Seccomp enforcement mode:

  • "enforce" – block disallowed syscalls with SCMP_ACT_ERRNO (default).
  • "audit" – log disallowed syscalls with SCMP_ACT_LOG but allow them. Useful for profile discovery and testing before switching to enforce.

Type: one of “enforce”, “audit”

Default:

"enforce"

Declared by:

perSystem.oci.containers.<name>.hardening.seccomp.profile

Predefined seccomp profile level:

  • "strict" – allowlist of ~60 syscalls. Suitable for static binaries, Go/Rust services. Blocks mount, ptrace, execve, and most process/namespace ops.

  • "moderate" – blocks ~50 dangerous syscalls including io_uring and memfd_create. All profiles include argument-level filtering for clone (block namespace creation), socket (block AF_NETLINK/AF_PACKET), and ioctl (block TIOCSTI/TIOCLINUX terminal injection).

  • "web-server" – strict base plus networking and threading syscalls. Suitable for HTTP servers.

  • "database" – web-server base plus memory management syscalls (fadvise64, msync, mincore). Suitable for PostgreSQL, Redis, and similar services.

  • "gpu-compute" – web-server base plus CUDA/GPU syscalls (perf_event_open, memfd_create, NUMA memory policy). Relaxes ioctl filtering for GPU command submission. Auto-selected when gpu.enable = true.

In the inner NixOS module, the profile auto-defaults to "gpu-compute" when GPU is enabled, "web-server" when a known web server is detected, and "database" when PostgreSQL or Redis is detected.

Type: one of “strict”, “moderate”, “web-server”, “database”, “gpu-compute”

Default:

"moderate"

Declared by:

perSystem.oci.containers.<name>.healthcheck.command

Health check command (CMD form). When non-empty, baked into the OCI image as Healthcheck.Test.

For NixOS-based containers, service adapters can auto-derive this from the NixOS module configuration (ports, endpoints, etc.).

Example: [ "curl" "-f" "http://localhost:8080/health" ]

Full container example:

{
  package = pkgs.python3;
  dependencies = [ pkgs.curl ];
  entrypoint = [
    "${pkgs.python3}/bin/python3"
    "-m"
    "http.server"
    "8080"
  ];
  ports = [ "8080:8080" ];
  healthcheck = {
    command = [
      "${pkgs.curl}/bin/curl"
      "-f"
      "http://localhost:8080/"
    ];
    interval = 15;
    timeout = 3;
    startPeriod = 5;
    retries = 3;
  };
}

Type: list of string

Default: Auto-derived by service adapters when available:

  • nginx: curl stub_status or /health endpoint
  • caddy: curl admin API (localhost:2019)
  • PostgreSQL: pg_isready
  • Redis: redis-cli ping
  • BIND/dnsmasq: dig DNS query
  • Postfix: postfix status

Example:

[
  "curl"
  "-f"
  "http://localhost:8080/health"
]

Declared by:

perSystem.oci.containers.<name>.healthcheck.interval

Seconds between health checks.

Type: signed integer

Default:

30

Declared by:

perSystem.oci.containers.<name>.healthcheck.retries

Number of consecutive failures before the container is considered unhealthy.

Type: signed integer

Default:

3

Declared by:

perSystem.oci.containers.<name>.healthcheck.startPeriod

Grace period (seconds) before the first health check runs after container start.

Type: signed integer

Default:

5

Declared by:

perSystem.oci.containers.<name>.healthcheck.timeout

Seconds to wait for a single health check to complete.

Type: signed integer

Default:

5

Declared by:

perSystem.oci.containers.<name>.homeManager.flake

The home-manager flake input. When set, enables home-manager integration for this container.

Example:

oci.containers.dev = {
  homeManager.flake = inputs.home-manager;
  homeManager.modules = [{ home.packages = [ pkgs.vim ]; }];
};

Type: null or unspecified value

Default:

null

Example:

"inputs.home-manager"

Declared by:

perSystem.oci.containers.<name>.homeManager.modules

Home-manager modules for the container user’s home directory.

These configure dotfiles, shell, git, editor, etc. Requires homeManager.flake to be set.

Type: list of unspecified value

Default:

[ ]

Declared by:

perSystem.oci.containers.<name>.initializeNixDatabase

Populate the Nix database (/nix/var/nix/db/db.sqlite) with the closure of all store paths shipped in the image.

Enable this when you need to run Nix commands (nix build, nix eval, nix-store -q, …) inside the container. Without it, the Nix store directory contains packages but the database is empty, causing Nix to believe no packages are installed.

Disabled by default because copyToRoot flattens store paths to /, creating phantom database entries for the flattened derivations. This is harmless for in-container Nix usage but may confuse workflows that validate database-vs-disk consistency.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.isRoot

Whether the container process runs as root.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.labels

OCI image labels (metadata key-value pairs).

Full container example:

{
  package = pkgs.hello;
  labels = {
    "org.opencontainers.image.title" = "my-app";
    "org.opencontainers.image.version" = "1.0.0";
    "org.opencontainers.image.description" = "My containerized application";
  };
}

Type: attribute set of string

Default:

{ }

Example:

{
  "org.opencontainers.image.title" = "my-app";
  "org.opencontainers.image.version" = "1.0.0";
}

Declared by:

perSystem.oci.containers.<name>.layerStrategy

Controls how nix2container splits store paths into sub-layers. Only effective when optimizeLayers is true.

  • "minimal": exactly one layer per concern (deps, app). Produces 2 total layers. Most predictable cache behaviour – adding or removing a dependency only invalidates the deps layer. Best for projects with few images where cross-image sharing is not a priority.

  • "fine-grained": each logical layer is further split using nix2container’s store-path popularity algorithm. The deps layer gets up to 80 sub-layers, and buildImage splits remaining paths into up to 40. Foundational packages (glibc, openssl) get their own sub-layers and are shared byte-for-byte across images in the same registry. Best for registries hosting many images with overlapping dependencies.

Type: one of “minimal”, “fine-grained”

Default:

"fine-grained"

Example:

"minimal"

Declared by:

perSystem.oci.containers.<name>.license.conftest.enabled

Whether to enable SBOM license compliance checking with Conftest.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.license.conftest.extraPolicyDirs

Additional directories containing Rego policy files for license checking. These are merged WITH the built-in license policies.

Type: list of absolute path

Default:

[ ]

Example:

[ ./my-license-policies ]

Declared by:

perSystem.oci.containers.<name>.license.conftest.namespaces

Rego namespaces to check. Each namespace maps to a package declaration in the license policy files.

Type: list of string

Default:

[
  "license"
]

Example:

[
  "license"
  "custom_license"
]

Declared by:

perSystem.oci.containers.<name>.license.conftest.policyDir

Path to a directory containing Rego policy files for license checking.

Policies receive a CycloneDX SBOM JSON as input and should define deny or warn rules in the license package. nix-oci ships built-in policies that reject common forbidden licenses (AGPL, SSPL) and warn on copyleft licenses (GPL, LGPL).

Type: absolute path

Default:

built-in nix-oci license policies

Declared by:

perSystem.oci.containers.<name>.lint.dockle.enabled

Whether to enable container image linting with Dockle.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.lint.dockle.exitLevel

Minimum severity level that causes a non-zero exit code.

Type: one of “info”, “warn”, “fatal”

Default:

"info"

Declared by:

perSystem.oci.containers.<name>.lint.dockle.ignore

List of Dockle checkpoint IDs to ignore (e.g. CIS-DI-0001).

Type: list of string

Default:

[
  "CIS-DI-0005"
  "CIS-DI-0006"
]

Example:

[
  "CIS-DI-0001"
  "DKL-DI-0006"
]

Declared by:

perSystem.oci.containers.<name>.mainService

Logical NixOS service name to extract container metadata from.

When set, nix-oci automatically derives:

  • Entrypoint from the systemd ExecStart
  • Stop signal from the systemd KillSignal or service adapter
  • Working directory from WorkingDirectory or service dataDir
  • Health check from the service adapter (curl, pg_isready, etc.)
  • Volumes from StateDirectory, RuntimeDirectory, etc.

For most services, this matches the NixOS option prefix (e.g. "nginx" for services.nginx). For multi-instance services (e.g. Redis), the service adapter resolves the actual systemd unit name automatically.

Requires nixosConfig.modules to include the service configuration.

Type: null or string

Default:

null

Example:

"nginx"

Declared by:

perSystem.oci.containers.<name>.name

OCI image name. Defaults to the container attribute name.

Type: string

Default:

"‹name›"

Example:

"my-custom-image"

Declared by:

perSystem.oci.containers.<name>.optimizeLayers

Split container contents into deduplicated layers for optimal registry caching. Uses a two-level heuristic:

Level 1 – popularity-based splitting. Within each layer, nix2container’s store-path popularity algorithm sorts paths by how many other paths reference them. Foundational packages (glibc, openssl, …) get their own sub-layers; application-specific paths cluster together. Capped by a maxLayers budget per layer.

Level 2 – fold-based cross-layer deduplication. Layers are built in a chain where each layer references all predecessors. nix2container excludes any store path already present in an earlier layer, eliminating duplication across explicit layers.

The resulting layer stack (most stable first):

  • Deps layer (runtime libraries, maxLayers = 80 when fine-grained)
  • App layer (package, shadow, configs)

Use layerStrategy to control sub-splitting granularity: "fine-grained" (default) for maximum cross-image sharing, "minimal" for exactly one layer per concern.

See Nix and layered Docker images for the original algorithm and nix2container for the implementation used here.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.performance.enable

Enable container performance tuning.

When enabled, applies build-time optimizations (allocator injection, glibc tunables, CPU-targeted libraries) and generates runtime hints consumed by deploy modules.

Three independent optimization axes are available:

  • Allocator – replace glibc ptmalloc2 with mimalloc/tcmalloc via LD_PRELOAD
  • glibc tunables – tune malloc arenas, tcache, mmap thresholds
  • hwcaps – ship CPU-optimized library variants (glibc-hwcaps, per-arch)

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.performance.allocator

Alternative memory allocator injected via LD_PRELOAD.

  • "mimalloc" – Microsoft’s general-purpose allocator. Lowest RSS for small allocations, excellent for microservices. Works on musl.

  • "tcmalloc" – Google’s per-CPU-cache allocator. Best throughput for large allocation patterns and high-concurrency servers. Requires glibc (does not work on musl).

  • "jemalloc" – Facebook’s allocator used by Redis and Firefox. Best fragmentation resistance and P99 latency for long-running servers. Requires glibc (segfaults on musl).

    Warning: jemalloc uses MADV_FREE by default, which inflates cgroup RSS accounting. The module automatically sets muzzy_decay_ms:0 unless overridden via allocatorConfig.

  • "snmalloc" – Microsoft Research lock-free allocator. Excellent for high cross-thread deallocation patterns (request/response servers where allocating thread differs from freeing thread).

  • null – use glibc’s default ptmalloc2 (no injection).

The allocator library is added as a container dependency and LD_PRELOAD is set in the OCI manifest Env.

Type: null or one of “mimalloc”, “tcmalloc”, “jemalloc”, “snmalloc”

Default:

null

Example:

"jemalloc"

Declared by:

perSystem.oci.containers.<name>.performance.allocatorConfig

Allocator-specific tuning parameters.

Keys and values depend on the selected performance.allocator:

mimalloc – keys become MIMALLOC_<KEY> environment variables:

  • PURGE_DELAY = "100" – ms before purging unused pages
  • PURGE_DECOMMITS = "1" – use MADV_DONTNEED (cgroup-accurate RSS)
  • ARENA_EAGER_COMMIT = "0" – lazy commit for memory-constrained
  • ALLOW_LARGE_OS_PAGES = "1" – use 2MB huge pages

tcmalloc – keys become TCMALLOC_<KEY> environment variables:

  • AGGRESSIVE_DECOMMIT = "true" – aggressively return memory to OS
  • MAX_TOTAL_THREAD_CACHE_BYTES = "8388608" – 8MB thread cache cap
  • RELEASE_RATE = "10.0" – OS memory return rate

jemalloc – keys are colon-joined into MALLOC_CONF:

  • narenas = "2" – limit arenas (default: 4*ncpus)
  • dirty_decay_ms = "5000" – dirty page purge timing
  • muzzy_decay_ms = "0" – skip MADV_FREE (critical for cgroups)
  • background_thread = "true" – offload purging
  • retain = "false" – actually munmap under cgroup limits
  • metadata_thp = "auto" – THP for jemalloc metadata

snmalloc – no runtime tunables (configured at compile time).

When the selected allocator is null, this option is ignored.

Type: attribute set of string

Default:

{ }

Example:

{
  background_thread = "true";
  dirty_decay_ms = "5000";
  muzzy_decay_ms = "0";
  narenas = "2";
}

Declared by:

perSystem.oci.containers.<name>.performance.compression

Compression algorithm for OCI image layers during transport (skopeo).

  • "gzip" – universal compatibility, slower.
  • "zstd" – 3-5x faster compress/decompress, 12% smaller. Requires OCI 1.1+ registry (Docker Hub, ECR, GCR, GHCR support it). containerd 2.0+ required; containerd 1.7.x does NOT support zstd.
  • "gzip:estargz" – eStargz format for lazy pulling with stargz-snapshotter. Requires performance.turbo.enable = true. Cannot be combined with SOCI (performance.turbo.soci).

Type: one of “gzip”, “zstd”, “gzip:estargz”

Default:

"gzip"

Example:

"zstd"

Declared by:

perSystem.oci.containers.<name>.performance.glibcTunables

glibc tunables set via the GLIBC_TUNABLES environment variable.

Keys are tunable names (e.g. glibc.malloc.arena_max), values are strings. Multiple tunables are colon-joined automatically.

Recommended for containers:

  • glibc.malloc.arena_max = "2" – cap malloc arenas to reduce RSS
  • glibc.malloc.mmap_threshold = "131072" – reduce fragmentation
  • glibc.malloc.tcache_count = "7" – tune per-thread cache

Only effective with glibc-based containers (not musl).

Type: attribute set of string

Default:

{ }

Example:

{
  "glibc.malloc.arena_max" = "2";
}

Declared by:

perSystem.oci.containers.<name>.performance.glibcTunablesPreset

Curated glibc tunables preset for common container workloads.

Presets set glibcTunables values via mkDefault – explicit glibcTunables entries always take precedence.

  • "memory-constrained" – for containers with <512MB memory limit. Aggressively reduces arena count and malloc overhead: arena_max=2, trim_threshold=32768, top_pad=0, mmap_threshold=65536, tcache_count=3

  • "high-throughput" – for CPU-bound servers with ample memory. Maximizes allocation throughput: arena_max=8, tcache_count=15, mxfast=256

  • "balanced" – safe defaults for general-purpose containers. Moderate arena count with sensible thresholds: arena_max=4, trim_threshold=131072, mmap_threshold=131072, tcache_count=7

  • null – no preset (only explicit glibcTunables apply).

Only effective with glibc-based containers (not musl).

Type: null or one of “memory-constrained”, “high-throughput”, “balanced”

Default:

null

Example:

"balanced"

Declared by:

perSystem.oci.containers.<name>.performance.hugePages

Huge page configuration for reduced TLB misses and lower page walk latency.

Type: submodule

Default:

{ }

Declared by:

perSystem.oci.containers.<name>.performance.hugePages.glibcHugetlb

glibc malloc.hugetlb tunable value.

  • 0 – disabled (default).
  • 1 – use MADV_HUGEPAGE after mmap.
  • 2 – use MAP_HUGETLB directly (requires hugetlbfs).

Type: null or one of 0, 1, 2

Default:

null

Example:

1

Declared by:

perSystem.oci.containers.<name>.performance.hugePages.thpMode

Transparent Huge Pages mode hint. Sets glibc.malloc.hugetlb tunable and generates an OCI label for host configuration.

  • "madvise" – recommended for containers.
  • "always" – aggressive, can cause compaction latency spikes.
  • null – no THP hint (host default applies).

Type: null or one of “madvise”, “always”

Default:

null

Example:

"madvise"

Declared by:

perSystem.oci.containers.<name>.performance.hwcaps

glibc-hwcaps: ship CPU-optimized library variants selected at runtime.

Type: submodule

Default:

{ }

Declared by:

perSystem.oci.containers.<name>.performance.hwcaps.enable

Build and ship CPU-optimized library variants via glibc-hwcaps.

The dynamic linker selects the best variant at process startup based on CPUID – zero application changes required.

Only effective on systems with hwcaps support (x86_64-linux). Auto-disabled on unsupported architectures in per-arch config.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.performance.hwcaps.levels

Microarchitecture levels to build optimized libraries for. Valid values depend on the target system:

  • x86_64-linux: "x86-64-v2", "x86-64-v3", "x86-64-v4"

The baseline is always included as fallback (not listed here).

Type: list of string

Default:

[ ]

Example:

[
  "x86-64-v3"
]

Declared by:

perSystem.oci.containers.<name>.performance.hwcaps.libraries

Packages whose shared libraries to rebuild at each hwcaps level. Only .so files are extracted into the hwcaps layer.

Good candidates: crypto (openssl), compression (zlib, zstd), math-heavy libraries, string processing.

Type: list of package

Default:

[ ]

Example:

[ pkgs.openssl pkgs.zlib ]

Declared by:

perSystem.oci.containers.<name>.performance.startup

Container process startup optimization.

Type: submodule

Default:

{ }

Declared by:

perSystem.oci.containers.<name>.performance.startup.ldSoCache

Run ldconfig at image build time to pre-build /etc/ld.so.cache with all library paths.

Eliminates filesystem search at process startup. Beneficial for containers with many shared libraries.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.performance.startup.stackSize

Default thread stack size override. Set via ulimit -s in the container entrypoint.

Reducing from the default 8MB to 512KB-2MB saves significant virtual memory for containers with many threads.

Format: size in KB (e.g. "512" for 512KB, "2048" for 2MB).

Type: null or string

Default:

null

Example:

"512"

Declared by:

perSystem.oci.containers.<name>.performance.turbo.enable

Use nix2container-turbo patched skopeo for image pushes.

Enables cross-machine layer caching via OCI Referrers API: layer mappings (nix store hash → compressed digest) are stored in the registry so any machine can skip re-compressing and re-uploading unchanged layers. Repushes become sub-second regardless of image size.

Requires an OCI registry supporting the Referrers API (ECR, GHCR, Docker Hub, and most modern registries).

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.performance.turbo.layerCache

Enable cross-machine layer caching via OCI Referrers API.

Stores nix store path → compressed layer mappings as referrer manifests in the registry. Subsequent pushes from any machine look up these mappings and skip re-compression and re-upload for unchanged layers.

Achieves sub-second repush times regardless of image size.

Enabled by default when performance.turbo.enable = true. Requires an OCI registry supporting the Referrers API.

Type: boolean

Default:

true

Example:

true

Declared by:

perSystem.oci.containers.<name>.performance.turbo.soci

Generate SOCI v2 indexes during push for lazy pulling.

When enabled, the turbo-patched skopeo generates zTOC (table of contents) for each layer during push and bundles them into a SOCI v2 index manifest alongside the image in an OCI Index.

Reduces cold-start times significantly for large images on AWS ECS/Fargate (~53s → ~20s for a 1GB image).

Requires performance.turbo.enable = true and gzip compression (SOCI does not support zstd). eStargz and SOCI cannot be combined.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.performance.turbo.sociSpanSize

SOCI span size in bytes for zTOC checkpoint granularity.

Controls how often deflate checkpoints are inserted in the compressed layer data. Smaller values allow more precise random-access seeking (faster individual file access) at the cost of a larger zTOC index.

  • 4194304 (4 MiB) – default, good balance for most workloads.
  • 1048576 (1 MiB) – finer granularity, better for many small files.
  • 8388608 (8 MiB) – coarser, smaller index, better for large files.

Only effective when performance.turbo.soci = true.

Type: signed integer

Default:

4194304

Example:

4194304

Declared by:

perSystem.oci.containers.<name>.policy.conftest.enabled

Whether to enable OCI image config policy checking with Conftest.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.policy.conftest.extraPolicyDirs

Additional directories containing Rego policy files. These are merged WITH the built-in policies.

Type: list of absolute path

Default:

[ ]

Example:

[ ./my-policies ./team-policies ]

Declared by:

perSystem.oci.containers.<name>.policy.conftest.namespaces

Rego namespaces to check. Each namespace maps to a package declaration in the policy files.

Type: list of string

Default:

[
  "main"
]

Example:

[
  "main"
  "custom"
]

Declared by:

perSystem.oci.containers.<name>.policy.conftest.policyDir

Path to a directory containing Rego policy files for Conftest.

Policies receive the OCI image config JSON as input and should define deny or warn rules. nix-oci ships built-in policies that check for common security issues (root user, leaked secrets in env vars, missing labels).

Type: absolute path

Default:

built-in nix-oci OCI policies

Declared by:

perSystem.oci.containers.<name>.ports

Port mappings (e.g. ["8080:8080"]). Baked into OCI manifest ExposedPorts and used by the runner service.

Full container example:

{
  package = pkgs.python3;
  entrypoint = [
    "${pkgs.python3}/bin/python3"
    "-m"
    "http.server"
    "8080"
  ];
  ports = [ "8080:8080" ];
}

Type: list of string

Default:

[ ]

Example:

[
  "8080:8080"
  "443:443"
]

Declared by:

perSystem.oci.containers.<name>.registry

The OCI registry to use for pushing and pulling images.

Type: null or string

Default:

null

Declared by:

perSystem.oci.containers.<name>.rootPath

The root path to store the Nix OCI resources.

Type: absolute path

Default:

self + "/oci/"

Declared by:

perSystem.oci.containers.<name>.sbom.path

Path where SBOM files will be stored.

Type: absolute path

Default:

config.rootPath

Declared by:

perSystem.oci.containers.<name>.sbom.syft.enabled

Whether to enable SBOM generation with Syft.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.sbom.syft.config.enabled

Whether to enable Syft configuration file generation.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.sbom.syft.config.rootPath

Path where Syft configuration files will be stored.

Type: absolute path

Default:

config.sbom.path

Declared by:

perSystem.oci.containers.<name>.signing.cosign.enabled

Whether to enable OCI image signing with cosign.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.containers.<name>.signing.cosign.annotations

Key-value annotations to attach to every cosign signature. These appear in cosign verify output and can be used for policy enforcement (e.g. with Kyverno or OPA).

Type: attribute set of string

Default:

{ }

Example:

{
  build-system = "nix";
  repo = "https://github.com/example/repo";
}

Declared by:

perSystem.oci.containers.<name>.signing.cosign.certificateIdentityRegexp

Regular expression to match the certificate identity when verifying keyless signatures. Required for keyless verification. Example: "https://github.com/myorg/.*" or an email pattern.

Type: null or string

Default:

null

Declared by:

perSystem.oci.containers.<name>.signing.cosign.certificateOidcIssuerRegexp

Regular expression to match the OIDC issuer when verifying keyless signatures. Required for keyless verification. Example: "https://token.actions.githubusercontent.com".

Type: null or string

Default:

null

Declared by:

perSystem.oci.containers.<name>.signing.cosign.key

Path or KMS URI for the cosign signing key. Supports local files, environment variables, and KMS URIs:

  • Local file: ./cosign.key
  • Environment variable: env://COSIGN_PRIVATE_KEY
  • AWS KMS: awskms://[ENDPOINT]/[ID/ALIAS/ARN]
  • GCP KMS: gcpkms://projects/[PROJECT]/locations/[LOC]/keyRings/[RING]/cryptoKeys/[KEY]
  • Azure Key Vault: azurekms://[VAULT_NAME][VAULT_URI]/[KEY]
  • HashCorp Vault: hashivault://[KEY] Only used when keyless is false.

Type: null or string

Default:

null

Declared by:

perSystem.oci.containers.<name>.signing.cosign.keyEnvVar

Environment variable consulted at runtime for the cosign key path or URI. When set in the environment, its value is used as --key <value>, overriding the Nix-configured key option.

Set to null to disable runtime override and always use the Nix-configured key value.

Only relevant when keyless is false.

The default "COSIGN_KEY" matches cosign’s own convention. Common patterns:

  • COSIGN_KEY=./cosign.key — local file
  • COSIGN_KEY=env://COSIGN_PRIVATE_KEY — key content in another env var
  • COSIGN_KEY=awskms://... — KMS URI

Type: null or string

Default:

"COSIGN_KEY"

Declared by:

perSystem.oci.containers.<name>.signing.cosign.keyless

Use keyless (OIDC) signing via Sigstore Fulcio. When true, cosign authenticates via an OIDC provider (GitHub Actions, Google, Microsoft) and issues ephemeral certificates. No key management required. When false, key must be set.

Type: boolean

Default:

true

Declared by:

perSystem.oci.containers.<name>.signing.cosign.verify

Whether to verify the signature immediately after signing.

Type: boolean

Default:

true

Declared by:

perSystem.oci.containers.<name>.stopSignal

Signal to send for graceful container shutdown (e.g., “SIGQUIT”, “SIGINT”). When null, auto-derived for NixOS containers from the service adapter or systemd KillSignal. Falls back to the container runtime default (SIGTERM).

Type: null or string

Default: Auto-derived (strongest to weakest):

  1. service adapter signal (e.g. SIGQUIT for nginx, SIGINT for PostgreSQL)
  2. systemd KillSignal
  3. container runtime default (SIGTERM)

Example:

"SIGQUIT"

Declared by:

perSystem.oci.containers.<name>.tag

OCI image tag.

Type: string

Default:

"latest"

Example:

"v1.0.0"

Declared by:

perSystem.oci.containers.<name>.test.amicontained.enabled

Whether to enable amicontained container introspection globally for all containers.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.test.cdk.enabled

Whether to enable CDK container security auditing globally for all containers.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.test.containerStructureTest.enabled

Whether to enable container-structure-test globally for all containers.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.test.deepce.enabled

Whether to enable DEEPCE container escape detection globally for all containers.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.test.dgoss.enabled

Whether to enable dgoss testing globally for all containers.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.test.dgoss.hermetic

Run dgoss as a pure Nix derivation (check) using podman. Requires extra-sandbox-paths = /sys/fs/cgroup in nix.conf.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.test.dive.enabled

Whether to enable Dive analysis globally for all containers.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.test.linpeas.enabled

Whether to enable linPEAS privilege escalation auditing globally for all containers.

Type: boolean

Default:

false

Declared by:

perSystem.oci.containers.<name>.uid

UID for the non-root container user.

Only used when isRoot = false. The default (4000) avoids conflicts with system UIDs (< 1000) and common application UIDs while remaining within the standard UID range.

Type: signed integer

Default:

4000

Example:

1000

Declared by:

perSystem.oci.containers.<name>.user

User to run the container process as.

Full container example:

{ pkgs, ... }:
{
  package = pkgs.hello;
  user = "nobody";
}

Type: string

Default:

"root"

Example:

"nobody"

Declared by:

perSystem.oci.containers.<name>.workingDir

Working directory for the container process. When null, auto-derived for NixOS containers from (strongest to weakest):

  1. systemd WorkingDirectory
  2. service dataDir (e.g., /var/lib/postgresql for PostgreSQL)
  3. user home directory (/root or /home/<user>)

For non-NixOS containers, defaults to the user home directory.

Type: null or string

Default: Auto-derived (strongest to weakest):

  1. systemd WorkingDirectory
  2. service dataDir (e.g. /var/lib/postgresql)
  3. user home directory (/root or /home/<user>)

Example:

"/var/lib/postgresql"

Declared by:

perSystem.oci.flake.packages

OCI container packages that can be exposed as flake outputs.

Type: attribute set of package (read only)

Default:

{ }

Declared by:

perSystem.oci.flake.apps

OCI-related apps that can be exposed as flake outputs.

Type: attribute set of (attribute set) (read only)

Default: Per-container sandbox, push, load-docker, load-podman apps.

Declared by:

perSystem.oci.flake.checks

OCI-related checks that can be exposed as flake outputs.

Type: attribute set of package (read only)

Default:

{ }

Declared by:

perSystem.oci.fromImageManifestDir

Runtime directory for manifest lock files, relative to the flake root. Used by oci-update-manifests to write lock files to the working copy. Each container gets a subdirectory: <dir>/<containerId>/manifest-lock.json.

Type: string

Default:

"./oci"

Declared by:

perSystem.oci.fromImageManifestRootPath

The root path for OCI manifest lock files (Nix path, used at build time). Each container gets a subdirectory.

Type: absolute path

Default:

config.oci.rootPath

Declared by:

perSystem.oci.perArchitecture

Per-architecture module definitions applied to every archConfigs entry.

Parallel to oci.perContainer – a top-level collector for per-architecture options. Contributed modules are evaluated for every target architecture within every container.

Each module receives these special arguments:

  • name : the target system string (e.g. "aarch64-linux")
  • containerConfig : the parent container’s evaluated config
  • containerId : the container’s attribute name
  • system : the host build system
  • pkgs : nixpkgs for the host system

Example:

oci.perArchitecture = [
  ({ name, containerConfig, ... }: {
    options.myArchOption = lib.mkOption { type = lib.types.str; };
  })
];

Type: list of raw value

Default:

[ ]

Declared by:

perSystem.oci.perContainer

Per-container module definition.

Multiple modules can contribute to this option. Each contribution is a module that will be evaluated for every container with container-specific context.

The module receives these special arguments:

  • name: the attribute name of the container (from types.attrsOf)
  • config: the container’s config (for reading within the module)
  • globalConfig: the top-level flake config
  • perSystemConfig: the perSystem config
  • system: the current system
  • pkgs: nixpkgs for current system
  • lib: nixpkgs lib

Type: per-container module

Default:

{ }

Declared by:

perSystem.oci.perContainer.package

The main package for the container.

Type: null or package

Default:

null

Example:

pkgs.hello

Declared by:

perSystem.oci.perContainer.autoLabels

Whether to automatically generate OCI image labels from package metadata.

When enabled, the following labels are generated (user labels always override):

  • OCI standard annotations (org.opencontainers.image.*): title, version, description, licenses, base.name
  • Build info (io.github.dauliac.nix-oci.build.*): system, optimized-layers, reproducible
  • Hardening hints (io.github.dauliac.nix-oci.hardening.*): security posture
  • Kubernetes PSS level (io.github.dauliac.nix-oci.kubernetes.pod-security-standard)

Type: boolean

Default:

true

Declared by:

perSystem.oci.perContainer.compliance.trivy.enabled

Whether to enable CIS compliance checking with Trivy.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.compliance.trivy.report

Compliance report format: all for detailed results or summary for a condensed overview.

Type: one of “all”, “summary”

Default:

"summary"

Declared by:

perSystem.oci.perContainer.compliance.trivy.spec

The compliance spec to check against. See trivy image --help for built-in specs.

Type: string

Default:

"docker-cis-1.6.0"

Example:

"docker-cis-1.6.0"

Declared by:

perSystem.oci.perContainer.credentialsLeak.configPath

Path where global credentials leak check configuration files will be stored.

Type: absolute path

Default:

config.rootPath + "/credentials-leak/"

Declared by:

perSystem.oci.perContainer.credentialsLeak.trivy.enabled

Whether to enable credentials leak detection with Trivy.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.cve.configPath

Path where CVE scanner configuration files will be stored.

Type: absolute path

Default:

config.rootPath

Declared by:

perSystem.oci.perContainer.cve.grype.enabled

Whether to enable CVE scanning with Grype.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.cve.grype.config.enabled

Whether to enable Grype configuration file generation.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.cve.grype.config.rootPath

Path where Grype configuration files will be stored.

Type: absolute path

Default:

config.cve.configPath + "/grype/"

Declared by:

perSystem.oci.perContainer.cve.trivy.enabled

Whether to enable CVE scanning with Trivy.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.cve.trivy.ignore.extra

Additional CVE identifiers to ignore globally in Trivy scans.

Type: list of string

Default:

[ ]

Declared by:

perSystem.oci.perContainer.cve.trivy.ignore.fileEnabled

Whether to enable Trivy CVE ignore file generation.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.cve.trivy.ignore.rootPath

Path where Trivy CVE ignore files will be stored.

Type: absolute path

Default:

config.cve.configPath

Declared by:

perSystem.oci.perContainer.cve.vulnix.enabled

Whether to enable CVE scanning with vulnix.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.cve.vulnix.whitelist.enabled

Whether to enable vulnix whitelist file.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.cve.vulnix.whitelist.rootPath

Path where vulnix whitelist files will be stored.

Type: absolute path

Default:

config.cve.configPath + "/vulnix/"

Declared by:

perSystem.oci.perContainer.declaredVolumes

OCI volume mount point declarations baked into the image manifest. These tell the container runtime which paths contain persistent data.

For NixOS containers, auto-derived from systemd service directories:

  • StateDirectory → /var/lib/<dir>
  • RuntimeDirectory → /run/<dir>
  • CacheDirectory → /var/cache/<dir>
  • LogsDirectory → /var/log/<dir>

This is separate from deploy-time volumes (host bind mounts).

Type: list of string

Default: Auto-derived from systemd service directories:

  • StateDirectory/var/lib/<dir>
  • RuntimeDirectory/run/<dir>
  • CacheDirectory/var/cache/<dir>
  • LogsDirectory/var/log/<dir>

Example:

[
  "/var/lib/postgresql"
  "/var/log/nginx"
]

Declared by:

perSystem.oci.perContainer.dependencies

Additional dependencies packages to include in the container.

Type: list of package

Default:

[ ]

Example:

[ pkgs.bash pkgs.coreutils ]

Declared by:

perSystem.oci.perContainer.entrypoint

OCI entrypoint (command + arguments).

Full container example:

{ pkgs, ... }:
{
  package = pkgs.python3;
  entrypoint = [
    "${pkgs.python3}/bin/python3"
    "-m"
    "http.server"
    "8080"
  ];
}

Type: list of string

Default:

[ ]

Example:

[
  "/bin/hello"
  "--greeting"
  "world"
]

Declared by:

perSystem.oci.perContainer.environment

Environment variables baked into the OCI manifest and passed to the runner.

Type: attribute set of string

Default:

{ }

Example:

{
  RUST_LOG = "info";
}

Declared by:

perSystem.oci.perContainer.gid

GID for the non-root container user’s primary group.

Only used when isRoot = false. The default (4000) matches the default UID to keep user/group mapping simple.

Type: signed integer

Default:

4000

Example:

1000

Declared by:

perSystem.oci.perContainer.gpu.enable

Enable NVIDIA GPU support for this container.

When enabled, sets environment variables that trigger the NVIDIA Container Toolkit runtime injection (NVIDIA_VISIBLE_DEVICES, NVIDIA_DRIVER_CAPABILITIES) and includes CUDA runtime libraries from nixpkgs in the container image.

Compatible with the NVIDIA GPU Operator in Kubernetes – images built with this option work with both legacy (env-var) and CDI (Container Device Interface) injection modes.

Driver libraries (libcuda.so, libnvidia-ml.so, nvidia-smi) are NOT bundled – they are always injected at runtime by the host’s NVIDIA Container Toolkit.

Requires nixpkgs.config.cudaSupport = true and nixpkgs.config.allowUnfree = true in the consuming flake.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.gpu.capabilities

NVIDIA driver capabilities to request at runtime.

Each capability controls which host driver libraries the NVIDIA Container Toolkit bind-mounts into the container:

  • "compute" – CUDA and OpenCL libraries.
  • "utility" – Management tools (nvidia-smi, libnvidia-ml.so).
  • "graphics" – OpenGL, EGL, Vulkan, OptiX libraries.
  • "video" – Hardware video codec libraries (NVENC/NVDEC).
  • "display" – X11 display output libraries.
  • "all" – All capabilities above.

Default: ["compute" "utility"] (CUDA compute + nvidia-smi).

Type: list of (one of “compute”, “utility”, “graphics”, “video”, “display”, “all”)

Default:

[
  "compute"
  "utility"
]

Declared by:

perSystem.oci.perContainer.gpu.cudaVersion

Minimum CUDA version constraint.

When set, the NVIDIA_REQUIRE_CUDA environment variable is added to the image config (e.g. cuda>=12.2). The NVIDIA Container Toolkit validates this against the host driver before allowing the container to start.

When null (default), the version is auto-detected from the cudaPackages in nixpkgs.

Type: null or string

Default:

null

Example:

"12.2"

Declared by:

perSystem.oci.perContainer.gpu.forwardCompat

Include CUDA forward compatibility libraries in the image.

When enabled, the cuda-compat package is added and LD_LIBRARY_PATH is configured so compat libraries take precedence over the host-injected driver libraries.

This allows the container to use a newer CUDA toolkit than the host driver natively supports. Useful when deploying to clusters where driver upgrades are infrequent.

Not all features are forward-compatible – some require kernel-mode driver support for new hardware capabilities.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.gpu.runtimeLibraries

CUDA toolkit libraries to include in the container image.

  • "cudart" – CUDA runtime (libcudart.so). Almost always needed.
  • "cublas" – cuBLAS linear algebra.
  • "cufft" – cuFFT Fourier transforms.
  • "curand" – cuRAND random number generation.
  • "cusolver" – cuSOLVER dense/sparse solvers.
  • "cusparse" – cuSPARSE sparse matrix operations.
  • "cudnn" – cuDNN deep learning primitives.
  • "tensorrt" – TensorRT inference optimization.
  • "nccl" – NCCL multi-GPU/node communication.
  • "cutlass" – CUTLASS GEMM templates.
  • "nvjpeg" – nvJPEG hardware JPEG decoding.

Only selected libraries are included to minimize image size. Driver libraries (libcuda.so) are never bundled.

Type: list of (one of “cudart”, “cublas”, “cufft”, “curand”, “cusolver”, “cusparse”, “cudnn”, “tensorrt”, “nccl”, “cutlass”, “nvjpeg”)

Default:

[
  "cudart"
]

Example:

[
  "cudart"
  "cublas"
  "cudnn"
]

Declared by:

perSystem.oci.perContainer.hardening.enable

Enable container security hardening.

When enabled, applies build-time filesystem restrictions and generates runtime security hints consumed by deploy modules.

Three independent kernel primitives are available:

  • Seccomp – syscall filtering (BPF at the syscall boundary)
  • AppArmor – mandatory access control (LSM pathname-based)
  • Capabilities + flags – privilege restriction at runtime

For containers using nixosConfig, these options are forwarded to the inner NixOS module at oci.container.hardening and can be overridden through NixOS module composition.

Full container example:

{
  package = pkgs.busybox;
  isRoot = true;
  hardening = {
    enable = true;
    disableDns = true;
    noTlsTrustStore = true;
    seccomp = {
      enable = true;
      profile = "strict";
    };
    capabilities = {
      drop = [ "ALL" ];
      add = [ "NET_BIND_SERVICE" ];
    };
    readOnlyRootfs = true;
    noNewPrivileges = true;
  };
}

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.hardening.apparmor

AppArmor MAC profile configuration.

Type: submodule

Default:

{ }

Declared by:

perSystem.oci.perContainer.hardening.apparmor.enable

Enable AppArmor profile generation for this container.

When enabled, a tailored AppArmor profile is generated as a build output. The deploy module references it via --security-opt apparmor=<profile>.

Requires the target host to have AppArmor enabled (kernel LSM + apparmor_parser). On NixOS, set security.apparmor.enable = true.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.hardening.apparmor.customProfile

Path to a custom AppArmor profile file. When set, overrides ALL computed profile rules. The profile must be a valid AppArmor profile file.

Note: cross-backend coherence checks cannot verify custom profiles — you take full responsibility for correctness.

Type: null or absolute path

Default:

null

Declared by:

perSystem.oci.perContainer.hardening.apparmor.denyMount

Deny mount operations inside the container.

Prevents filesystem remounting, overlay stacking, and bind-mount escape attacks. Enforced via AppArmor deny mount, rule.

Type: boolean

Default:

true

Declared by:

perSystem.oci.perContainer.hardening.apparmor.denyPtrace

Deny ptrace of other processes.

Prevents process inspection and memory manipulation attacks. Enforced via AppArmor deny ptrace (read, read, trace, traceby), rule.

Type: boolean

Default:

true

Declared by:

perSystem.oci.perContainer.hardening.apparmor.denyUserNamespace

Deny user namespace creation inside the container.

Prevents the class of Local Privilege Escalation (LPE) vulnerabilities where unprivileged processes exploit userns to reach normally-root-only kernel code paths (CVE-2023-2640, CVE-2023-32629, etc.).

Enforced via AppArmor deny userns_create, rule. Complementary to seccomp clone(CLONE_NEWUSER) arg filter and capability drop SYS_ADMIN.

Type: boolean

Default:

true

Declared by:

perSystem.oci.perContainer.hardening.apparmor.mode

AppArmor enforcement mode:

  • "enforce" – violations are blocked and logged (default). Use for production.
  • "complain" – violations are logged but NOT blocked. Useful for profile discovery before switching to enforce.

Type: one of “enforce”, “complain”

Default:

"enforce"

Declared by:

perSystem.oci.perContainer.hardening.capabilities

Linux capability restrictions applied at runtime by deploy modules.

Type: submodule

Default:

{ }

Declared by:

perSystem.oci.perContainer.hardening.capabilities.add

Linux capabilities to add back after dropping. Deploy modules translate to --cap-add.

Type: list of string

Default:

[ ]

Example:

[
  "NET_BIND_SERVICE"
]

Declared by:

perSystem.oci.perContainer.hardening.capabilities.drop

Linux capabilities to drop. Defaults to ["ALL"]. Deploy modules translate to --cap-drop.

Type: list of string

Default:

[
  "ALL"
]

Declared by:

perSystem.oci.perContainer.hardening.disableDns

Disable DNS resolution inside the container.

Sets /etc/nsswitch.conf hosts line to files only (no dns backend). Applications using IP addresses directly are unaffected.

NOTE: /etc/resolv.conf is NOT written into the image because container runtimes (Docker, Podman) always bind-mount it at startup, masking any baked-in content. To fully enforce DNS restriction at runtime, use --dns=127.0.0.1 or network policies.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.hardening.noNewPrivileges

Set the no_new_privs bit. Prevents privilege escalation via setuid/setgid binaries or file capabilities.

Deploy modules translate to --security-opt=no-new-privileges.

Type: boolean

Default:

true

Declared by:

perSystem.oci.perContainer.hardening.noTlsTrustStore

Remove the TLS certificate trust store (/etc/ssl/certs). Prevents all outgoing HTTPS connections.

Only use for containers that never initiate TLS connections. This is a nuclear option – most applications that make any outbound HTTP requests will break.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.hardening.readOnlyRootfs

Mount the container root filesystem as read-only at runtime. Deploy modules translate to --read-only.

Prevents attackers from writing malware or achieving persistence if they gain initial access.

Type: boolean

Default:

true

Declared by:

perSystem.oci.perContainer.hardening.seccomp

Seccomp syscall filtering configuration.

Full container example:

{
  package = pkgs.busybox;
  hardening = {
    enable = true;
    seccomp = {
      enable = true;
      profile = "web-server";
      mode = "enforce";
    };
  };
}

Type: submodule

Default:

{ }

Declared by:

perSystem.oci.perContainer.hardening.seccomp.enable

Enable a custom seccomp profile for this container.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.hardening.seccomp.customProfileJson

Path to a custom seccomp profile JSON file following the OCI runtime specification format. When set, overrides the profile option.

Type: null or absolute path

Default:

null

Declared by:

perSystem.oci.perContainer.hardening.seccomp.mode

Seccomp enforcement mode:

  • "enforce" – block disallowed syscalls with SCMP_ACT_ERRNO (default).
  • "audit" – log disallowed syscalls with SCMP_ACT_LOG but allow them. Useful for profile discovery and testing before switching to enforce.

Type: one of “enforce”, “audit”

Default:

"enforce"

Declared by:

perSystem.oci.perContainer.hardening.seccomp.profile

Predefined seccomp profile level:

  • "strict" – allowlist of ~60 syscalls. Suitable for static binaries, Go/Rust services. Blocks mount, ptrace, execve, and most process/namespace ops.

  • "moderate" – blocks ~50 dangerous syscalls including io_uring and memfd_create. All profiles include argument-level filtering for clone (block namespace creation), socket (block AF_NETLINK/AF_PACKET), and ioctl (block TIOCSTI/TIOCLINUX terminal injection).

  • "web-server" – strict base plus networking and threading syscalls. Suitable for HTTP servers.

  • "database" – web-server base plus memory management syscalls (fadvise64, msync, mincore). Suitable for PostgreSQL, Redis, and similar services.

  • "gpu-compute" – web-server base plus CUDA/GPU syscalls (perf_event_open, memfd_create, NUMA memory policy). Relaxes ioctl filtering for GPU command submission. Auto-selected when gpu.enable = true.

In the inner NixOS module, the profile auto-defaults to "gpu-compute" when GPU is enabled, "web-server" when a known web server is detected, and "database" when PostgreSQL or Redis is detected.

Type: one of “strict”, “moderate”, “web-server”, “database”, “gpu-compute”

Default:

"moderate"

Declared by:

perSystem.oci.perContainer.healthcheck.command

Health check command (CMD form). When non-empty, baked into the OCI image as Healthcheck.Test.

For NixOS-based containers, service adapters can auto-derive this from the NixOS module configuration (ports, endpoints, etc.).

Example: [ "curl" "-f" "http://localhost:8080/health" ]

Full container example:

{
  package = pkgs.python3;
  dependencies = [ pkgs.curl ];
  entrypoint = [
    "${pkgs.python3}/bin/python3"
    "-m"
    "http.server"
    "8080"
  ];
  ports = [ "8080:8080" ];
  healthcheck = {
    command = [
      "${pkgs.curl}/bin/curl"
      "-f"
      "http://localhost:8080/"
    ];
    interval = 15;
    timeout = 3;
    startPeriod = 5;
    retries = 3;
  };
}

Type: list of string

Default: Auto-derived by service adapters when available:

  • nginx: curl stub_status or /health endpoint
  • caddy: curl admin API (localhost:2019)
  • PostgreSQL: pg_isready
  • Redis: redis-cli ping
  • BIND/dnsmasq: dig DNS query
  • Postfix: postfix status

Example:

[
  "curl"
  "-f"
  "http://localhost:8080/health"
]

Declared by:

perSystem.oci.perContainer.healthcheck.interval

Seconds between health checks.

Type: signed integer

Default:

30

Declared by:

perSystem.oci.perContainer.healthcheck.retries

Number of consecutive failures before the container is considered unhealthy.

Type: signed integer

Default:

3

Declared by:

perSystem.oci.perContainer.healthcheck.startPeriod

Grace period (seconds) before the first health check runs after container start.

Type: signed integer

Default:

5

Declared by:

perSystem.oci.perContainer.healthcheck.timeout

Seconds to wait for a single health check to complete.

Type: signed integer

Default:

5

Declared by:

perSystem.oci.perContainer.homeManager.flake

The home-manager flake input. When set, enables home-manager integration for this container.

Example:

oci.containers.dev = {
  homeManager.flake = inputs.home-manager;
  homeManager.modules = [{ home.packages = [ pkgs.vim ]; }];
};

Type: null or unspecified value

Default:

null

Example:

"inputs.home-manager"

Declared by:

perSystem.oci.perContainer.homeManager.modules

Home-manager modules for the container user’s home directory.

These configure dotfiles, shell, git, editor, etc. Requires homeManager.flake to be set.

Type: list of unspecified value

Default:

[ ]

Declared by:

perSystem.oci.perContainer.initializeNixDatabase

Populate the Nix database (/nix/var/nix/db/db.sqlite) with the closure of all store paths shipped in the image.

Enable this when you need to run Nix commands (nix build, nix eval, nix-store -q, …) inside the container. Without it, the Nix store directory contains packages but the database is empty, causing Nix to believe no packages are installed.

Disabled by default because copyToRoot flattens store paths to /, creating phantom database entries for the flattened derivations. This is harmless for in-container Nix usage but may confuse workflows that validate database-vs-disk consistency.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.isRoot

Whether the container process runs as root.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.labels

OCI image labels (metadata key-value pairs).

Full container example:

{
  package = pkgs.hello;
  labels = {
    "org.opencontainers.image.title" = "my-app";
    "org.opencontainers.image.version" = "1.0.0";
    "org.opencontainers.image.description" = "My containerized application";
  };
}

Type: attribute set of string

Default:

{ }

Example:

{
  "org.opencontainers.image.title" = "my-app";
  "org.opencontainers.image.version" = "1.0.0";
}

Declared by:

perSystem.oci.perContainer.layerStrategy

Controls how nix2container splits store paths into sub-layers. Only effective when optimizeLayers is true.

  • "minimal": exactly one layer per concern (deps, app). Produces 2 total layers. Most predictable cache behaviour – adding or removing a dependency only invalidates the deps layer. Best for projects with few images where cross-image sharing is not a priority.

  • "fine-grained": each logical layer is further split using nix2container’s store-path popularity algorithm. The deps layer gets up to 80 sub-layers, and buildImage splits remaining paths into up to 40. Foundational packages (glibc, openssl) get their own sub-layers and are shared byte-for-byte across images in the same registry. Best for registries hosting many images with overlapping dependencies.

Type: one of “minimal”, “fine-grained”

Default:

"fine-grained"

Example:

"minimal"

Declared by:

perSystem.oci.perContainer.license.conftest.enabled

Whether to enable SBOM license compliance checking with Conftest.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.license.conftest.extraPolicyDirs

Additional directories containing Rego policy files for license checking. These are merged WITH the built-in license policies.

Type: list of absolute path

Default:

[ ]

Example:

[ ./my-license-policies ]

Declared by:

perSystem.oci.perContainer.license.conftest.namespaces

Rego namespaces to check. Each namespace maps to a package declaration in the license policy files.

Type: list of string

Default:

[
  "license"
]

Example:

[
  "license"
  "custom_license"
]

Declared by:

perSystem.oci.perContainer.license.conftest.policyDir

Path to a directory containing Rego policy files for license checking.

Policies receive a CycloneDX SBOM JSON as input and should define deny or warn rules in the license package. nix-oci ships built-in policies that reject common forbidden licenses (AGPL, SSPL) and warn on copyleft licenses (GPL, LGPL).

Type: absolute path

Default:

built-in nix-oci license policies

Declared by:

perSystem.oci.perContainer.lint.dockle.enabled

Whether to enable container image linting with Dockle.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.lint.dockle.exitLevel

Minimum severity level that causes a non-zero exit code.

Type: one of “info”, “warn”, “fatal”

Default:

"info"

Declared by:

perSystem.oci.perContainer.lint.dockle.ignore

List of Dockle checkpoint IDs to ignore (e.g. CIS-DI-0001).

Type: list of string

Default:

[
  "CIS-DI-0005"
  "CIS-DI-0006"
]

Example:

[
  "CIS-DI-0001"
  "DKL-DI-0006"
]

Declared by:

perSystem.oci.perContainer.mainService

Logical NixOS service name to extract container metadata from.

When set, nix-oci automatically derives:

  • Entrypoint from the systemd ExecStart
  • Stop signal from the systemd KillSignal or service adapter
  • Working directory from WorkingDirectory or service dataDir
  • Health check from the service adapter (curl, pg_isready, etc.)
  • Volumes from StateDirectory, RuntimeDirectory, etc.

For most services, this matches the NixOS option prefix (e.g. "nginx" for services.nginx). For multi-instance services (e.g. Redis), the service adapter resolves the actual systemd unit name automatically.

Requires nixosConfig.modules to include the service configuration.

Type: null or string

Default:

null

Example:

"nginx"

Declared by:

perSystem.oci.perContainer.name

OCI image name. Defaults to the container attribute name.

Type: string

Default:

"‹name›"

Example:

"my-custom-image"

Declared by:

perSystem.oci.perContainer.optimizeLayers

Split container contents into deduplicated layers for optimal registry caching. Uses a two-level heuristic:

Level 1 – popularity-based splitting. Within each layer, nix2container’s store-path popularity algorithm sorts paths by how many other paths reference them. Foundational packages (glibc, openssl, …) get their own sub-layers; application-specific paths cluster together. Capped by a maxLayers budget per layer.

Level 2 – fold-based cross-layer deduplication. Layers are built in a chain where each layer references all predecessors. nix2container excludes any store path already present in an earlier layer, eliminating duplication across explicit layers.

The resulting layer stack (most stable first):

  • Deps layer (runtime libraries, maxLayers = 80 when fine-grained)
  • App layer (package, shadow, configs)

Use layerStrategy to control sub-splitting granularity: "fine-grained" (default) for maximum cross-image sharing, "minimal" for exactly one layer per concern.

See Nix and layered Docker images for the original algorithm and nix2container for the implementation used here.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.performance.enable

Enable container performance tuning.

When enabled, applies build-time optimizations (allocator injection, glibc tunables, CPU-targeted libraries) and generates runtime hints consumed by deploy modules.

Three independent optimization axes are available:

  • Allocator – replace glibc ptmalloc2 with mimalloc/tcmalloc via LD_PRELOAD
  • glibc tunables – tune malloc arenas, tcache, mmap thresholds
  • hwcaps – ship CPU-optimized library variants (glibc-hwcaps, per-arch)

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.performance.allocator

Alternative memory allocator injected via LD_PRELOAD.

  • "mimalloc" – Microsoft’s general-purpose allocator. Lowest RSS for small allocations, excellent for microservices. Works on musl.

  • "tcmalloc" – Google’s per-CPU-cache allocator. Best throughput for large allocation patterns and high-concurrency servers. Requires glibc (does not work on musl).

  • "jemalloc" – Facebook’s allocator used by Redis and Firefox. Best fragmentation resistance and P99 latency for long-running servers. Requires glibc (segfaults on musl).

    Warning: jemalloc uses MADV_FREE by default, which inflates cgroup RSS accounting. The module automatically sets muzzy_decay_ms:0 unless overridden via allocatorConfig.

  • "snmalloc" – Microsoft Research lock-free allocator. Excellent for high cross-thread deallocation patterns (request/response servers where allocating thread differs from freeing thread).

  • null – use glibc’s default ptmalloc2 (no injection).

The allocator library is added as a container dependency and LD_PRELOAD is set in the OCI manifest Env.

Type: null or one of “mimalloc”, “tcmalloc”, “jemalloc”, “snmalloc”

Default:

null

Example:

"jemalloc"

Declared by:

perSystem.oci.perContainer.performance.allocatorConfig

Allocator-specific tuning parameters.

Keys and values depend on the selected performance.allocator:

mimalloc – keys become MIMALLOC_<KEY> environment variables:

  • PURGE_DELAY = "100" – ms before purging unused pages
  • PURGE_DECOMMITS = "1" – use MADV_DONTNEED (cgroup-accurate RSS)
  • ARENA_EAGER_COMMIT = "0" – lazy commit for memory-constrained
  • ALLOW_LARGE_OS_PAGES = "1" – use 2MB huge pages

tcmalloc – keys become TCMALLOC_<KEY> environment variables:

  • AGGRESSIVE_DECOMMIT = "true" – aggressively return memory to OS
  • MAX_TOTAL_THREAD_CACHE_BYTES = "8388608" – 8MB thread cache cap
  • RELEASE_RATE = "10.0" – OS memory return rate

jemalloc – keys are colon-joined into MALLOC_CONF:

  • narenas = "2" – limit arenas (default: 4*ncpus)
  • dirty_decay_ms = "5000" – dirty page purge timing
  • muzzy_decay_ms = "0" – skip MADV_FREE (critical for cgroups)
  • background_thread = "true" – offload purging
  • retain = "false" – actually munmap under cgroup limits
  • metadata_thp = "auto" – THP for jemalloc metadata

snmalloc – no runtime tunables (configured at compile time).

When the selected allocator is null, this option is ignored.

Type: attribute set of string

Default:

{ }

Example:

{
  background_thread = "true";
  dirty_decay_ms = "5000";
  muzzy_decay_ms = "0";
  narenas = "2";
}

Declared by:

perSystem.oci.perContainer.performance.compression

Compression algorithm for OCI image layers during transport (skopeo).

  • "gzip" – universal compatibility, slower.
  • "zstd" – 3-5x faster compress/decompress, 12% smaller. Requires OCI 1.1+ registry (Docker Hub, ECR, GCR, GHCR support it). containerd 2.0+ required; containerd 1.7.x does NOT support zstd.
  • "gzip:estargz" – eStargz format for lazy pulling with stargz-snapshotter. Requires performance.turbo.enable = true. Cannot be combined with SOCI (performance.turbo.soci).

Type: one of “gzip”, “zstd”, “gzip:estargz”

Default:

"gzip"

Example:

"zstd"

Declared by:

perSystem.oci.perContainer.performance.glibcTunables

glibc tunables set via the GLIBC_TUNABLES environment variable.

Keys are tunable names (e.g. glibc.malloc.arena_max), values are strings. Multiple tunables are colon-joined automatically.

Recommended for containers:

  • glibc.malloc.arena_max = "2" – cap malloc arenas to reduce RSS
  • glibc.malloc.mmap_threshold = "131072" – reduce fragmentation
  • glibc.malloc.tcache_count = "7" – tune per-thread cache

Only effective with glibc-based containers (not musl).

Type: attribute set of string

Default:

{ }

Example:

{
  "glibc.malloc.arena_max" = "2";
}

Declared by:

perSystem.oci.perContainer.performance.glibcTunablesPreset

Curated glibc tunables preset for common container workloads.

Presets set glibcTunables values via mkDefault – explicit glibcTunables entries always take precedence.

  • "memory-constrained" – for containers with <512MB memory limit. Aggressively reduces arena count and malloc overhead: arena_max=2, trim_threshold=32768, top_pad=0, mmap_threshold=65536, tcache_count=3

  • "high-throughput" – for CPU-bound servers with ample memory. Maximizes allocation throughput: arena_max=8, tcache_count=15, mxfast=256

  • "balanced" – safe defaults for general-purpose containers. Moderate arena count with sensible thresholds: arena_max=4, trim_threshold=131072, mmap_threshold=131072, tcache_count=7

  • null – no preset (only explicit glibcTunables apply).

Only effective with glibc-based containers (not musl).

Type: null or one of “memory-constrained”, “high-throughput”, “balanced”

Default:

null

Example:

"balanced"

Declared by:

perSystem.oci.perContainer.performance.hugePages

Huge page configuration for reduced TLB misses and lower page walk latency.

Type: submodule

Default:

{ }

Declared by:

perSystem.oci.perContainer.performance.hugePages.glibcHugetlb

glibc malloc.hugetlb tunable value.

  • 0 – disabled (default).
  • 1 – use MADV_HUGEPAGE after mmap.
  • 2 – use MAP_HUGETLB directly (requires hugetlbfs).

Type: null or one of 0, 1, 2

Default:

null

Example:

1

Declared by:

perSystem.oci.perContainer.performance.hugePages.thpMode

Transparent Huge Pages mode hint. Sets glibc.malloc.hugetlb tunable and generates an OCI label for host configuration.

  • "madvise" – recommended for containers.
  • "always" – aggressive, can cause compaction latency spikes.
  • null – no THP hint (host default applies).

Type: null or one of “madvise”, “always”

Default:

null

Example:

"madvise"

Declared by:

perSystem.oci.perContainer.performance.hwcaps

glibc-hwcaps: ship CPU-optimized library variants selected at runtime.

Type: submodule

Default:

{ }

Declared by:

perSystem.oci.perContainer.performance.hwcaps.enable

Build and ship CPU-optimized library variants via glibc-hwcaps.

The dynamic linker selects the best variant at process startup based on CPUID – zero application changes required.

Only effective on systems with hwcaps support (x86_64-linux). Auto-disabled on unsupported architectures in per-arch config.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.performance.hwcaps.levels

Microarchitecture levels to build optimized libraries for. Valid values depend on the target system:

  • x86_64-linux: "x86-64-v2", "x86-64-v3", "x86-64-v4"

The baseline is always included as fallback (not listed here).

Type: list of string

Default:

[ ]

Example:

[
  "x86-64-v3"
]

Declared by:

perSystem.oci.perContainer.performance.hwcaps.libraries

Packages whose shared libraries to rebuild at each hwcaps level. Only .so files are extracted into the hwcaps layer.

Good candidates: crypto (openssl), compression (zlib, zstd), math-heavy libraries, string processing.

Type: list of package

Default:

[ ]

Example:

[ pkgs.openssl pkgs.zlib ]

Declared by:

perSystem.oci.perContainer.performance.startup

Container process startup optimization.

Type: submodule

Default:

{ }

Declared by:

perSystem.oci.perContainer.performance.startup.ldSoCache

Run ldconfig at image build time to pre-build /etc/ld.so.cache with all library paths.

Eliminates filesystem search at process startup. Beneficial for containers with many shared libraries.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.performance.startup.stackSize

Default thread stack size override. Set via ulimit -s in the container entrypoint.

Reducing from the default 8MB to 512KB-2MB saves significant virtual memory for containers with many threads.

Format: size in KB (e.g. "512" for 512KB, "2048" for 2MB).

Type: null or string

Default:

null

Example:

"512"

Declared by:

perSystem.oci.perContainer.performance.turbo.enable

Use nix2container-turbo patched skopeo for image pushes.

Enables cross-machine layer caching via OCI Referrers API: layer mappings (nix store hash → compressed digest) are stored in the registry so any machine can skip re-compressing and re-uploading unchanged layers. Repushes become sub-second regardless of image size.

Requires an OCI registry supporting the Referrers API (ECR, GHCR, Docker Hub, and most modern registries).

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.performance.turbo.layerCache

Enable cross-machine layer caching via OCI Referrers API.

Stores nix store path → compressed layer mappings as referrer manifests in the registry. Subsequent pushes from any machine look up these mappings and skip re-compression and re-upload for unchanged layers.

Achieves sub-second repush times regardless of image size.

Enabled by default when performance.turbo.enable = true. Requires an OCI registry supporting the Referrers API.

Type: boolean

Default:

true

Example:

true

Declared by:

perSystem.oci.perContainer.performance.turbo.soci

Generate SOCI v2 indexes during push for lazy pulling.

When enabled, the turbo-patched skopeo generates zTOC (table of contents) for each layer during push and bundles them into a SOCI v2 index manifest alongside the image in an OCI Index.

Reduces cold-start times significantly for large images on AWS ECS/Fargate (~53s → ~20s for a 1GB image).

Requires performance.turbo.enable = true and gzip compression (SOCI does not support zstd). eStargz and SOCI cannot be combined.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.performance.turbo.sociSpanSize

SOCI span size in bytes for zTOC checkpoint granularity.

Controls how often deflate checkpoints are inserted in the compressed layer data. Smaller values allow more precise random-access seeking (faster individual file access) at the cost of a larger zTOC index.

  • 4194304 (4 MiB) – default, good balance for most workloads.
  • 1048576 (1 MiB) – finer granularity, better for many small files.
  • 8388608 (8 MiB) – coarser, smaller index, better for large files.

Only effective when performance.turbo.soci = true.

Type: signed integer

Default:

4194304

Example:

4194304

Declared by:

perSystem.oci.perContainer.policy.conftest.enabled

Whether to enable OCI image config policy checking with Conftest.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.policy.conftest.extraPolicyDirs

Additional directories containing Rego policy files. These are merged WITH the built-in policies.

Type: list of absolute path

Default:

[ ]

Example:

[ ./my-policies ./team-policies ]

Declared by:

perSystem.oci.perContainer.policy.conftest.namespaces

Rego namespaces to check. Each namespace maps to a package declaration in the policy files.

Type: list of string

Default:

[
  "main"
]

Example:

[
  "main"
  "custom"
]

Declared by:

perSystem.oci.perContainer.policy.conftest.policyDir

Path to a directory containing Rego policy files for Conftest.

Policies receive the OCI image config JSON as input and should define deny or warn rules. nix-oci ships built-in policies that check for common security issues (root user, leaked secrets in env vars, missing labels).

Type: absolute path

Default:

built-in nix-oci OCI policies

Declared by:

perSystem.oci.perContainer.ports

Port mappings (e.g. ["8080:8080"]). Baked into OCI manifest ExposedPorts and used by the runner service.

Full container example:

{
  package = pkgs.python3;
  entrypoint = [
    "${pkgs.python3}/bin/python3"
    "-m"
    "http.server"
    "8080"
  ];
  ports = [ "8080:8080" ];
}

Type: list of string

Default:

[ ]

Example:

[
  "8080:8080"
  "443:443"
]

Declared by:

perSystem.oci.perContainer.registry

The OCI registry to use for pushing and pulling images.

Type: null or string

Default:

null

Declared by:

perSystem.oci.perContainer.rootPath

The root path to store the Nix OCI resources.

Type: absolute path

Default:

self + "/oci/"

Declared by:

perSystem.oci.perContainer.sbom.path

Path where SBOM files will be stored.

Type: absolute path

Default:

config.rootPath

Declared by:

perSystem.oci.perContainer.sbom.syft.enabled

Whether to enable SBOM generation with Syft.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.sbom.syft.config.enabled

Whether to enable Syft configuration file generation.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.sbom.syft.config.rootPath

Path where Syft configuration files will be stored.

Type: absolute path

Default:

config.sbom.path

Declared by:

perSystem.oci.perContainer.signing.cosign.enabled

Whether to enable OCI image signing with cosign.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.perContainer.signing.cosign.annotations

Key-value annotations to attach to every cosign signature. These appear in cosign verify output and can be used for policy enforcement (e.g. with Kyverno or OPA).

Type: attribute set of string

Default:

{ }

Example:

{
  build-system = "nix";
  repo = "https://github.com/example/repo";
}

Declared by:

perSystem.oci.perContainer.signing.cosign.certificateIdentityRegexp

Regular expression to match the certificate identity when verifying keyless signatures. Required for keyless verification. Example: "https://github.com/myorg/.*" or an email pattern.

Type: null or string

Default:

null

Declared by:

perSystem.oci.perContainer.signing.cosign.certificateOidcIssuerRegexp

Regular expression to match the OIDC issuer when verifying keyless signatures. Required for keyless verification. Example: "https://token.actions.githubusercontent.com".

Type: null or string

Default:

null

Declared by:

perSystem.oci.perContainer.signing.cosign.key

Path or KMS URI for the cosign signing key. Supports local files, environment variables, and KMS URIs:

  • Local file: ./cosign.key
  • Environment variable: env://COSIGN_PRIVATE_KEY
  • AWS KMS: awskms://[ENDPOINT]/[ID/ALIAS/ARN]
  • GCP KMS: gcpkms://projects/[PROJECT]/locations/[LOC]/keyRings/[RING]/cryptoKeys/[KEY]
  • Azure Key Vault: azurekms://[VAULT_NAME][VAULT_URI]/[KEY]
  • HashCorp Vault: hashivault://[KEY] Only used when keyless is false.

Type: null or string

Default:

null

Declared by:

perSystem.oci.perContainer.signing.cosign.keyEnvVar

Environment variable consulted at runtime for the cosign key path or URI. When set in the environment, its value is used as --key <value>, overriding the Nix-configured key option.

Set to null to disable runtime override and always use the Nix-configured key value.

Only relevant when keyless is false.

The default "COSIGN_KEY" matches cosign’s own convention. Common patterns:

  • COSIGN_KEY=./cosign.key — local file
  • COSIGN_KEY=env://COSIGN_PRIVATE_KEY — key content in another env var
  • COSIGN_KEY=awskms://... — KMS URI

Type: null or string

Default:

"COSIGN_KEY"

Declared by:

perSystem.oci.perContainer.signing.cosign.keyless

Use keyless (OIDC) signing via Sigstore Fulcio. When true, cosign authenticates via an OIDC provider (GitHub Actions, Google, Microsoft) and issues ephemeral certificates. No key management required. When false, key must be set.

Type: boolean

Default:

true

Declared by:

perSystem.oci.perContainer.signing.cosign.verify

Whether to verify the signature immediately after signing.

Type: boolean

Default:

true

Declared by:

perSystem.oci.perContainer.stopSignal

Signal to send for graceful container shutdown (e.g., “SIGQUIT”, “SIGINT”). When null, auto-derived for NixOS containers from the service adapter or systemd KillSignal. Falls back to the container runtime default (SIGTERM).

Type: null or string

Default: Auto-derived (strongest to weakest):

  1. service adapter signal (e.g. SIGQUIT for nginx, SIGINT for PostgreSQL)
  2. systemd KillSignal
  3. container runtime default (SIGTERM)

Example:

"SIGQUIT"

Declared by:

perSystem.oci.perContainer.tag

OCI image tag.

Type: string

Default:

"latest"

Example:

"v1.0.0"

Declared by:

perSystem.oci.perContainer.test.amicontained.enabled

Whether to enable amicontained container introspection globally for all containers.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.test.cdk.enabled

Whether to enable CDK container security auditing globally for all containers.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.test.containerStructureTest.enabled

Whether to enable container-structure-test globally for all containers.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.test.deepce.enabled

Whether to enable DEEPCE container escape detection globally for all containers.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.test.dgoss.enabled

Whether to enable dgoss testing globally for all containers.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.test.dgoss.hermetic

Run dgoss as a pure Nix derivation (check) using podman. Requires extra-sandbox-paths = /sys/fs/cgroup in nix.conf.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.test.dive.enabled

Whether to enable Dive analysis globally for all containers.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.test.linpeas.enabled

Whether to enable linPEAS privilege escalation auditing globally for all containers.

Type: boolean

Default:

false

Declared by:

perSystem.oci.perContainer.uid

UID for the non-root container user.

Only used when isRoot = false. The default (4000) avoids conflicts with system UIDs (< 1000) and common application UIDs while remaining within the standard UID range.

Type: signed integer

Default:

4000

Example:

1000

Declared by:

perSystem.oci.perContainer.user

User to run the container process as.

Full container example:

{ pkgs, ... }:
{
  package = pkgs.hello;
  user = "nobody";
}

Type: string

Default:

"root"

Example:

"nobody"

Declared by:

perSystem.oci.perContainer.workingDir

Working directory for the container process. When null, auto-derived for NixOS containers from (strongest to weakest):

  1. systemd WorkingDirectory
  2. service dataDir (e.g., /var/lib/postgresql for PostgreSQL)
  3. user home directory (/root or /home/<user>)

For non-NixOS containers, defaults to the user home directory.

Type: null or string

Default: Auto-derived (strongest to weakest):

  1. systemd WorkingDirectory
  2. service dataDir (e.g. /var/lib/postgresql)
  3. user home directory (/root or /home/<user>)

Example:

"/var/lib/postgresql"

Declared by:

perSystem.oci.pipeline.defaultBackend

Default backend for probe-phase steps:

  • "vm" — probes run as NixOS VM derivations (build-time gate).
  • "daemon" — probes run as scripts in the Taskfile (runtime).

Individual steps can override via oci.pipeline.steps.<name>.backend.

Type: one of “vm”, “daemon”

Default:

"vm"

Declared by:

perSystem.oci.pipeline.envVars.pushedTag

Stdout marker for pushed tag output.

Type: string

Default:

"NIX_OCI_PUSHED_TAG"

Declared by:

perSystem.oci.pipeline.envVars.registry

Env var name for the target registry.

Type: string

Default:

"NIX_OCI_REGISTRY"

Declared by:

perSystem.oci.pipeline.envVars.registryFallback

Fallback env var for registry (GitLab compat).

Type: string

Default:

"CI_REGISTRY_IMAGE"

Declared by:

perSystem.oci.pipeline.envVars.reportDir

Env var name for the report output directory.

Type: string

Default:

"NIX_OCI_REPORT_DIR"

Declared by:

perSystem.oci.pipeline.steps

Registry of pipeline steps contributed by tool lib.nix files.

Each step has: phase, category, backend, deps, isEnabled, mkStamp (for build-time gate), mkScript (for Taskfile).

Adding a new tool = one registration. The pipeline composer picks it up automatically.

Type: attribute set of (submodule)

Default:

{ }

Declared by:

perSystem.oci.pipeline.steps.<name>.backend

Execution backend override. When null, inferred from phase:

  • build-check → pure
  • probe → global oci.pipeline.defaultBackend
  • pre-push/post-push → daemon

Type: null or one of “pure”, “vm”, “daemon”

Default:

null

Declared by:

perSystem.oci.pipeline.steps.<name>.category

Tool category for documentation and grouping.

Type: one of “policy”, “cve”, “lint”, “compliance”, “sbom”, “signing”, “structure”, “probe”, “license”, “push”, “credentials”

Declared by:

perSystem.oci.pipeline.steps.<name>.deps

Step names this step depends on (DAG ordering for Taskfile).

Type: list of string

Default:

[ ]

Declared by:

perSystem.oci.pipeline.steps.<name>.isEnabled

Function containerConfig → bool that determines whether this step is active for a given container.

Type: function that evaluates to a(n) boolean

Declared by:

perSystem.oci.pipeline.steps.<name>.label

Custom output prefix for Taskfile (e.g. probe:cdk instead of probe-cdk).

Type: null or string

Default:

null

Declared by:

perSystem.oci.pipeline.steps.<name>.mkScript

For daemon backend: function { containerId, perSystemConfig } → package. The package is a writeShellApplication added to the Taskfile.

Type: null or (function that evaluates to a(n) package)

Default:

null

Declared by:

perSystem.oci.pipeline.steps.<name>.mkStamp

For pure/vm backend: function { containerId, perSystemConfig } → derivation. The derivation is a stamp (touch $out on success). Added to the gate’s nativeBuildInputs.

Type: null or (function that evaluates to a(n) package)

Default:

null

Declared by:

perSystem.oci.pipeline.steps.<name>.parallel

Whether this step can run concurrently with siblings in the same phase.

Type: boolean

Default:

true

Declared by:

perSystem.oci.pipeline.steps.<name>.phase

Pipeline phase:

  • "build-check" — pure Nix derivation, no runtime needed (conftest, dockle, dive, sbom).
  • "probe" — container introspection (amicontained, cdk, deepce, linpeas, cst, dgoss).
  • "pre-push" — runs before push (load-image).
  • "post-push" — runs after push (signing, compliance scans).

Type: one of “build-check”, “probe”, “pre-push”, “post-push”

Declared by:

perSystem.oci.pipeline.steps.<name>.timeout

Timeout in seconds for this step (Taskfile timeout field).

Type: signed integer

Default:

120

Declared by:

perSystem.oci.rootPath

The root path to store the Nix OCI resources.

Type: absolute path

Default:

self + "/oci/"

Declared by:

perSystem.oci.turbo.enable

Use nix2container-turbo patched skopeo for all container pushes.

Enables cross-machine layer caching via OCI Referrers API by default. Per-container overrides: oci.containers.<name>.performance.turbo.enable.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.turbo.layerCache

Enable cross-machine layer caching via OCI Referrers API for all containers.

Per-container overrides: oci.containers.<name>.performance.turbo.layerCache.

Type: boolean

Default:

true

Example:

true

Declared by:

perSystem.oci.turbo.soci

Generate SOCI v2 indexes during push for all containers.

Enables lazy pulling on AWS ECS/Fargate and containerd with soci-snapshotter. Per-container overrides: oci.containers.<name>.performance.turbo.soci.

Type: boolean

Default:

false

Example:

true

Declared by:

perSystem.oci.turbo.sociSpanSize

Default SOCI span size in bytes for all containers.

Per-container overrides: oci.containers.<name>.performance.turbo.sociSpanSize.

Type: signed integer

Default:

4194304

Example:

4194304

Declared by:

perSystem.test.oci.perContainer

BDD test specs contributed by .test.nix files.

Outer key = option group (e.g. “hardening-seccomp”). Inner key = scenario name (e.g. “blocks-dangerous-syscalls”). Value = test spec with BDD metadata + assertions.

Type: attribute set of attribute set of (submodule)

Default:

{ }

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions

Assertions to verify after building/running the container.

Type: submodule

Default:

{ }

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.containerInspect

Expected podman inspect fields (dot-path notation).

Example: { "HostConfig.LogConfig.Type" = "passthrough"; }

Type: attribute set of raw value

Default:

{ }

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.fails

Commands that must fail (exit != 0) when run via podman run --rm --entrypoint <command> <image>. Used for testing seccomp blocks, capability drops, etc. Optionally assert a specific exit code.

Type: list of (submodule)

Default:

[ ]

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.fails.*.args

Arguments passed to the command.

Type: string

Default:

""

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.fails.*.command

Binary to run as entrypoint.

Type: string

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.fails.*.exitCode

If set, assert this specific exit code. Otherwise any non-zero.

Type: null or signed integer

Default:

null

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.fileContains

Files in the image that must contain a string. Uses podman create + cp to read from image layers directly (bypasses runtime bind-mounts like resolv.conf).

Example: { "/etc/nsswitch.conf" = "files"; }

Type: attribute set of string

Default:

{ }

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.fileNotContains

Files in the image that must NOT contain a string.

Example: { "/etc/ssl/certs/ca-bundle.crt" = "BEGIN CERTIFICATE"; }

Type: attribute set of string

Default:

{ }

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.httpResponds

HTTP endpoint check with built-in wait/retry. Uses wait_for_open_port + wait_until_succeeds + curl.

Type: null or (submodule)

Default:

null

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.httpResponds.contains

If set, assert response body contains this string.

Type: string

Default:

""

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.httpResponds.path

HTTP path to request.

Type: string

Default:

"/"

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.httpResponds.port

Port to check.

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.imageConfig

Expected OCI image Config fields. Checked via podman image inspect → .Config.<key>.

Example: { User = "nobody"; ExposedPorts."8080/tcp" = {}; }

Type: attribute set of raw value

Default:

{ }

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.labels

Expected OCI labels. Checked via podman image inspect → .Labels.<key>.

Example: { "org.opencontainers.image.title" = "my-app"; }

Type: attribute set of string

Default:

{ }

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.processEnv

Expected process environment variables. Read from /proc/1/environ inside the running container (captures OCI-configured env vars that env may not show).

Example: { LD_PRELOAD = "jemalloc"; }

Type: attribute set of string

Default:

{ }

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.runtime

Raw Python test script (escape hatch). In the pytest context, this becomes a standalone test function body with client (docker SDK) available.

Type: strings concatenated with “\n”

Default:

""

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.succeeds

Commands that must succeed (exit 0) when run via podman run --rm --entrypoint <command> <image>. Optionally check stdout contains a string.

Type: list of (submodule)

Default:

[ ]

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.succeeds.*.args

Arguments passed to the command.

Type: string

Default:

""

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.succeeds.*.command

Binary to run as entrypoint.

Type: string

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.succeeds.*.stdout

If set, assert stdout contains this string.

Type: null or string

Default:

null

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.assertions.systemdProps

Expected systemd service properties. Checked via systemctl show <service> --property=<keys>.

Example: { Type = "notify"; NotifyAccess = "all"; }

Type: attribute set of string

Default:

{ }

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.container

Container config for this BDD test scenario. Used by the new .test.nix BDD system.

Type: raw value

Default:

{ }

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.default

Container config using only defaults. Tests that the option’s default value produces a valid container. (Legacy _tests system — use container for new BDD specs.)

Type: raw value

Default:

{ }

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.exampleFile

Link to an examples/ file for documentation cross-reference.

Type: null or absolute path

Default:

null

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.given

BDD precondition / context (rendered in test coverage docs).

Type: string

Default:

""

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.level

Test depth — determines what kind of check is generated:

  • "eval" — container config evaluates without error (cheapest).
  • "build" — OCI image builds successfully.
  • "inspect" — image metadata / file contents (VM, no container run).
  • "runtime" — oneshot podman run --rm, check output / exit code.
  • "deploy" — long-running daemon via systemd, check HTTP / env / lifecycle.

Type: one of “eval”, “build”, “inspect”, “runtime”, “deploy”

Default:

"eval"

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.mode

Container run mode (only relevant for runtime/deploy levels):

  • "oneshot"podman run --rm, runs command and exits.
  • "daemon" — deployed via systemd, stays running for interaction.

Type: one of “oneshot”, “daemon”

Default:

"oneshot"

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.override

Container config with the example value applied. Tests that overriding the option with its documented example works. (Legacy _tests system — use container for new BDD specs.)

Type: raw value

Default:

{ }

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.target

Which test harness to use:

  • "oci" — flake-parts container (podman run).
  • "nixos-oci" — NixOS container eval + systemd.
  • "home-manager-oci" — home-manager activation.
  • "deploy-nixos" — full NixOS deployment.
  • "deploy-home-manager" — home-manager deployment.

Type: one of “oci”, “nixos-oci”, “home-manager-oci”, “deploy-nixos”, “deploy-home-manager”

Default:

"oci"

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.testDependencies

Extra packages injected into the test container for testing purposes. These are NOT part of the option being tested — they are test harness dependencies (e.g., a C binary that probes io_uring for seccomp tests).

Type: list of package

Default:

[ ]

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.“then”

BDD expected outcome (rendered in test coverage docs).

Type: string

Default:

""

Declared by:

perSystem.test.oci.perContainer.<name>.<name>.when

BDD action or trigger (rendered in test coverage docs).

Type: string

Default:

""

Declared by: