Search code examples
nixnixos

How to use chown in Nix derivations?


I'm trying to package a script to perform deployments with a git push in a Nix derivation. The goal is having a git repo that on post-receive run some actions.

I want to package it so that I can just keep it alongside my configuration and ship it easily, minimising the amount of manual tasks to do.

I've already setup a git user:

users.users.git = {
    isNormalUser = true;
    shell = "/run/current-system/sw/bin/git-shell";
    home = "/home/git";
    openssh.authorizedKeys.keys = [
      ...
    ];
  };

My derivation looks like this:

with import <nixpkgs> {};
let setupGitRepo = name : (
stdenv.mkDerivation {
  name = "setup-git-repo";
  dontUnpack = true;
  buildInputs = [
    git
  ];
  buildPhase = ''
git init --bare ${name}.git
mkdir -p ${name}.git/hooks
touch ${name}.git/hooks/post-receive
tee ${name}.git/hooks/post-receive <<EOF
GIT="/home/git/${name}.git"
WWW="/var/www/${name}"
TMP="/tmp/${name}"
ENV="/home/git/${name}.env"
rm -rf \$TMP
mkdir -p \$TMP
git --work-tree=\$TMP --git-dir=\$GIT checkout -f
cp -a \$ENV/.* \$TMP
cd \$TMP
# install deps, etc
rm -rf \$WWW/*
mv \$TMP/* \$WWW/*
# restart services here
rm -rf \$TMP
EOF 
  '';
  installPhase = ''
    mkdir -p $out/var/www/${name}
    mkdir -p $out/home/git
    mkdir -p $out/home/git/${name}.env
    chown -R git:users ${name}.git # doesn't work
    chown -R git:users $out/var/www/${name} # doesn't work
    cp -R ${name}.git $out/home/git
  '';
});
in setupGitRepo "test"

My problem is that I can't use chown git:users to set ownership during the build or install phase, I assume because of isolation in the build process.

Is there a way to overcome this? I wonder if the issue I'm getting is a signal I'm missing something obvious or misusing tools. Writing in /home from a package could be another code smell: I'm doing it to have a nicer url to add to git git remote add server git@mydomain:test.git)

Thanks

EDIT: I'll upload my nixos configuration here with the suggestions from David: https://github.com/framp/nixos-configs/blob/master/painpoint


Solution

  • In general, as far as I know, Linux has no way to give ownership of a file to another user, unless you are root.

    Secondly, I question why you would even want files in the output of your derivation to be owned by a different user. As described in the Nix manual, after building a derivation, Nix sets the modes of all files to 0444 or 0555, meaning they will be readable by all users on the system, and some will also be executable by all users on the system. There should be no additional permissions that you need for your users.

    Remember that the output of a Nix derivation is supposed to be an immutable thing that never changes.