nixos/nixos-containers: bindMounts fails with paths containing spaces
Nobody has claimed this yet.
- 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
- I assert that this is a bug and not a support request.
- I assert that this is not a duplicate of an existing issue.
- I assert that I have read the NixOS Code of Conduct and agree to abide by it.
Is this issue important to you?
Add a 👍 reaction to issues you find important.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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