Skip to content

deploy-rs fails on any boot.initrd.extraFiles shell script with nix flake check #335

@mariaa144

Description

@mariaa144

🐛 Issue

deployChecks fails on shell scripts in boot.initrd.extraFiles with valid sh syntax (=, >, 2>, |) or even echo.


Overview

When using deploy-rs v1.0 with nix 2.28.3, deployChecks fails if a shell script in boot.initrd.extraFiles includes common valid shell syntax like:

  • =
  • >
  • 2>
  • |
  • echo

Even though nixos-rebuild succeeds and the system works correctly at runtime.


Minimal Reproduction

Directory structure:

.
├── flake.nix
├── flake.lock
└── unlock.sh


flake.nix:

{
  description = "Deploy bug with shell script in extraFiles";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
    deploy-rs.url = "github:serokell/deploy-rs";
  };

  outputs = { self, nixpkgs, deploy-rs, ... }:
    let
      system = "x86_64-linux";
    in {
      nixosConfigurations.test = nixpkgs.lib.nixosSystem {
        inherit system;
        modules = [{
          system.stateVersion = "25.05";
          boot.initrd.extraFiles."/unlock.sh" = ./unlock.sh;

          # Required dummy options
          fileSystems."/".device = "/dev/null";

          # Disable bootloader entirely for evaluation
          boot.loader.grub.enable = false;
          boot.loader.systemd-boot.enable = false;
          boot.loader.generic-extlinux-compatible.enable = false;
        }];
      };

      checks = builtins.mapAttrs
        (system: deployLib: deployLib.deployChecks self.deploy)
        deploy-rs.lib;

      deploy.test = {
        hostname = "my-host";
        sshUser = "root";
        profiles.system.path = self.nixosConfigurations.test.config.system.build.toplevel;
      };
    };
}

unlock.sh:

#!/bin/sh
echo "Remote unlock initrd shell"

Each of these causes failure independently:

  • foo=bar
  • echo hi > /tmp/file
  • somecmd 2> /dev/null
  • cmd1 | cmd2

Steps to Reproduce

nix flake check

Fails with:

       error: undefined variable 'echo'
       at /nix/store/vi24zyx5bvl9baxac3x5z2b7273hxdqi-source/unlock.sh:2:1:
            1| #!/bin/sh
            2| echo "example script here"
             | ^
            3|

Environment

  • deploy-rs: 1.0
  • nix: 2.28.3
  • nixos: 25.04 / 25.05
  • system: x86_64-linux

Why This Matters

Shell scripts in boot.initrd.extraFiles are copied verbatim to the initrd and should never be parsed as Nix. This bug blocks valid remote-unlock workflows (e.g. over SSH).

✅ Suggested Fix

  • Treat extraFiles contents as opaque
  • Don’t evaluate or parse their syntax
  • Optionally allow opt-out from parsing via __noDeployCheck = true or similar
🤖 ChatGPT assistance note

I worked with ChatGPT to debug this issue. It helped me:

  • Identify that deployChecks was failing due to boot.initrd.extraFiles including valid shell syntax like =, >, 2>, and |
  • Confirm that the files were being misinterpreted by the Nix expression parser even though they were valid for the initrd
  • Reproduce the issue using a minimal flake.nix and unlock.sh example
  • Suggest a possible PR direction: skip or bypass parsing for boot.initrd.extraFiles during schema checks
  • Draft the issue template and Markdown body for submission

This saved time narrowing down and presenting the issue clearly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions