NixOS / NixOS/nixpkgs

nixos/nixos-containers: bindMounts fails with paths containing spaces

Open
#482,452 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

0.kind: bug 2.status: stale 6.topic: nixos
Dominant language
Nix
Stars
26.2k
Forks
20.1k
PR merge metrics
PR metrics pending

Description

Nixpkgs version
  • Stable (25.11)
Describe the bug

The NixOS containers module doesn’t properly handle bind mount paths containing spaces. When bindMounts includes a hostPath or a target path with spaces, the generated container fails to start with "No such file or directory" because the path is split on the space character.

The container start script in /nix/store/*/container_*-start seems to expand ${EXTRA_NSPAWN_FLAGS-} without quotes, causing bash to perform word-splitting on the bind mount arguments.

Steps to reproduce

Create a container that binds a directory with spaces in the hostPath:

{ ... }:

{ 
  # Create test directories with spaces
  systemd.tmpfiles.rules = [
    "f \"/tmp/test-bind-mounts1/path with spaces/test.txt\" 0644 root root - test content"
  ];

  containers.spaces-host-path = {
    ephemeral = true;
    
    bindMounts = {
      "/mnt/target/test spaces" = {
        hostPath = "/tmp/test-bind-mounts";
      };
    };
    
    config = { ... }: {
      system.stateVersion = "25.11";
    };
  };
}

Create a container that binds a directory with spaces in the target path:

{ ... }:

{
  # Create test directories with spaces
  systemd.tmpfiles.rules = [
    "f \"/tmp/test-bind-mounts2/path with spaces/test.txt\" 0644 root root - test content"
  ];

  containers.spaces-target-path = {
    ephemeral = true;
    
    bindMounts = {
      "/mnt/target" = {
        hostPath = "/tmp/test-bind-mounts/path with spaces";
        isReadOnly = true;
      };
    };
    
    config = { ... }: {
      system.stateVersion = "25.11";
    };
  };
}

Both cases fail.

The same configuration without spaces works fine:

…

    bindMounts = {
      "/mnt/without_space" = {
        hostPath = "/tmp/test-bind-mounts";
        isReadOnly = true;
      };
    };
…
Expected behaviour

I expect paths with spaces to be handled correctly.

Screenshots

No response

Relevant log output
[root@hypervisor-test:/home/aaron]# systemctl start container@spaces-host-path.service
Job for container@spaces-host-path.service failed because the control process exited with error code.
See "systemctl status container@spaces-host-path.service" and "journalctl -xeu container@spaces-host-path.service" for details.

[root@hypervisor-test:/home/aaron]# journalctl -u container@spaces-host-path.service
Jan 21 23:22:56 hypervisor-test systemd[1]: Starting Container 'spaces-host-path'...
Jan 21 23:22:56 hypervisor-test systemd-nspawn[95452]: ░ Spawning container spaces-host-path on /run/nixos-containers/.#machine.spaces-host-pathd8e3ed6bd826890f.
Jan 21 23:22:56 hypervisor-test container spaces-host-path[95452]: execv(spaces) failed: No such file or directory
Jan 21 23:22:56 hypervisor-test systemd-nspawn[95452]: Container spaces-host-path failed with error code 1.
Jan 21 23:22:56 hypervisor-test systemd[1]: container@spaces-host-path.service: Main process exited, code=exited, status=1/FAILURE
Jan 21 23:22:56 hypervisor-test systemd[1]: container@spaces-host-path.service: Failed with result 'exit-code'.
Jan 21 23:22:56 hypervisor-test systemd[1]: Failed to start Container 'spaces-host-path'.

[root@hypervisor-test:/home/aaron]# systemctl start container@spaces-target-path.service
Job for container@spaces-target-path.service failed because the control process exited with error code.
See "systemctl status container@spaces-target-path.service" and "journalctl -xeu container@spaces-target-path.service" for details.

[root@hypervisor-test:/home/aaron]# journalctl -u container@spaces-target-path.service -f
Jan 21 23:23:43 hypervisor-test systemd[1]: Starting Container 'spaces-target-path'...
Jan 21 23:23:43 hypervisor-test systemd-nspawn[95673]: ░ Spawning container spaces-target-path on /run/nixos-containers/.#machine.spaces-target-path547a15f2988402ee.
Jan 21 23:23:43 hypervisor-test systemd-nspawn[95685]: Failed to clone /tmp/test-bind-mounts/path: No such file or directory
Jan 21 23:23:43 hypervisor-test systemd[1]: container@spaces-target-path.service: Main process exited, code=exited, status=1/FAILURE
Jan 21 23:23:43 hypervisor-test systemd[1]: container@spaces-target-path.service: Failed with result 'exit-code'.
Jan 21 23:23:43 hypervisor-test systemd[1]: Failed to start Container 'spaces-target-path'.

[root@hypervisor-test:/home/aaron]# cat /etc/nixos-containers/spaces-*
SYSTEM_PATH=/nix/store/6nzvgssqlqs76cdmis4xvgvvrgkyvhyc-nixos-system-spaces-host-path-25.11pre-git




PRIVATE_USERS=no
INTERFACES=""
MACVLANS=""

EXTRA_NSPAWN_FLAGS=" --bind-ro=/tmp/test-bind-mounts:/mnt/target/test spaces"
SYSTEM_PATH=/nix/store/85144rm2kk36zdv0z04sdjib483nfayf-nixos-system-spaces-target-path-25.11pre-git




PRIVATE_USERS=no
INTERFACES=""
MACVLANS=""

EXTRA_NSPAWN_FLAGS=" --bind-ro=/tmp/test-bind-mounts/path with spaces:/mnt/target"

[root@hypervisor-test:/home/aaron]# cat /nix/store/11pjr1wd0nd5axjv22x2hldjprcj8zb1-unit-script-container_spaces-host-path-start/bin/container_spaces-host-path-start
#!/nix/store/j8645yndikbrvn292zgvyv64xrrmwdcb-bash-5.3p3/bin/bash
set -o errexit
set -o nounset
set -o pipefail

…
(truncated)
…

export SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=1

# Run systemd-nspawn without startup notification (we'll
# wait for the container systemd to signal readiness)
# Kill signal handling means systemd-nspawn will pass a system-halt signal
# to the container systemd when it receives SIGTERM for container shutdown;
# containerInit and stage2 have to handle this as well.
# TODO: fix shellcheck issue properly
# shellcheck disable=SC2086
exec /nix/store/yxk9smkrispxlz2ka3gxigvmzhf0fn65-systemd-258.2/bin/systemd-nspawn \
  --keep-unit \
  -M "$INSTANCE" -D "$root" "${extraFlags[@]}" \
  --notify-ready=yes \
  --kill-signal=SIGRTMIN+3 \
  --bind-ro=/nix/store:/nix/store$NIX_BIND_OPT \
  --bind-ro=/nix/var/nix/db:/nix/var/nix/db$NIX_BIND_OPT \
  --bind-ro=/nix/var/nix/daemon-socket:/nix/var/nix/daemon-socket$NIX_BIND_OPT \
  --bind="/nix/var/nix/profiles/per-container/$INSTANCE:/nix/var/nix/profiles$NIX_BIND_OPT" \
  --bind="/nix/var/nix/gcroots/per-container/$INSTANCE:/nix/var/nix/gcroots$NIX_BIND_OPT" \
   \
  --setenv PRIVATE_NETWORK="${PRIVATE_NETWORK-}" \
  --setenv PRIVATE_USERS="${PRIVATE_USERS-}" \
  --setenv HOST_BRIDGE="${HOST_BRIDGE-}" \
  --setenv HOST_ADDRESS="${HOST_ADDRESS-}" \
  --setenv LOCAL_ADDRESS="${LOCAL_ADDRESS-}" \
  --setenv HOST_ADDRESS6="${HOST_ADDRESS6-}" \
  --setenv LOCAL_ADDRESS6="${LOCAL_ADDRESS6-}" \
  --setenv HOST_PORT="${HOST_PORT-}" \
  --setenv PATH="$PATH" \
  --ephemeral \
   \
   \
  ${EXTRA_NSPAWN_FLAGS-} \
  /nix/store/pbbhp8a3lg7dlxcd9gw7km25p6bx53n3-container-init "${SYSTEM_PATH:-/nix/var/nix/profiles/system}/init"
Additional context

No response

System metadata
  • system: "x86_64-linux"
  • host os: Linux 6.12.65, NixOS, 25.11 (Xantusia), 25.11.20260117.72ac591
  • multi-user?: yes
  • sandbox: yes
  • version: nix-env (Nix) 2.31.2
  • nixpkgs: /nix/store/j0svprv1655d13l3vbd3bnimq7wzk0s4-source
Notify maintainers

@trueNAHO


Note for maintainers: Please tag this issue in your pull request description. (i.e. Resolves #ISSUE.)

I assert that this issue is relevant for Nixpkgs
Is this issue important to you?

Add a 👍 reaction to issues you find important.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing both configurations and inspect the generated /etc/nixos-containers files and container_*-start script shown in the report. Trace how bindMounts becomes EXTRA_NSPAWN_FLAGS and how the shell expands those flags. Done means containers start successfully when either hostPath or target paths contain spaces, while paths without spaces continue to work.

Written by the indexing model from the issue text.

Assessment

Tech stack
bash, linux
Domain
operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.