Requirements:
- root directory is a git repository(for
git rev-parse --show-toplevel
) - github.com/nixos/nixpkgs at pkgs/nixpkgs
Tree:
.
├── .git
├── deploy
├── env
├── realise
├── machines
│ └── localhost
│ └── default.nix
└── pkgs
└── nixpkgs
├── ...
└── .git
$ cat deploy
#! /usr/bin/env bash
set -e
root="$(git rev-parse --show-toplevel)"
source "$root"/env
if [ -z "$1" ] || [ -z "$2" ]
then
echo
echo "Usage: $0 <configuration> <machine>"
echo
echo " <configuration> Relative path to machine directory"
echo " or nix configuration which exports system"
echo
echo " <machine> Machine expression which will be passed to SSH"
echo
exit 1
fi
configuration="$1"
shift
machine="$1"
shift
derivation="$($root/realise "$configuration")"
[ ! -z "$derivation" ] || {
echo "No derivation built, aborting"
exit 1
} 1>&2
nix-copy-closure --gzip --to "$machine" "$derivation"
ssh "$machine" '
set -e
sudo nix-env --profile /nix/var/nix/profiles/system --set '"$derivation"'
sudo /nix/var/nix/profiles/system/bin/switch-to-configuration switch
'
$ cat env
#! /usr/bin/env bash
root="${root:-$(git rev-parse --show-toplevel)}"
export NIX_PATH="${root}:nixpkgs=${root}/pkgs/nixpkgs"
export NIX_BUILD_CORES=4
# Docker needs locale
# Otherwise some python apps may break
export LANG=en_US.UTF-8
export LANGUAGE=en_US:en
export LC_ALL=en_US.UTF-8
$ cat realise
#! /usr/bin/env bash
set -e
root="$(git rev-parse --show-toplevel)"
source "$root"/env
[ ! -z "$1" ] || {
echo
echo "Usage: $0 <configuration> [configuration] ..."
echo
echo " <configuration> Relative path to machine directory"
echo " or nix configuration which exports system"
echo
exit 1
}
while [ ! -z "$1" ]
do
configuration="$1"
shift
echo "$configuration" 1>&2
instance=$(nix-instantiate "$configuration")
[ ! -z "$instance" ] || {
echo "Failed to instantiate $configuration"
exit 1
} 1>&2
nix-store --realise $instance
done
$ cat machines/localhost/default.nix
(import <nixpkgs/nixos> {
system = "x86_64-linux";
configuration = { ... }: {
imports = [
./hardware.nix
];
# ... machine configuration ...
};
}).system
$ ./deploy machines/localhost localhost
Bonus: shell in docker container to deploy from machines without nix
installed.
Pay attention that it use nixos/nix:2.0
container
$ cat shell
#! /usr/bin/env bash
set -e
root="$(git rev-parse --show-toplevel)"
source "$root"/env
[ -z "$SSH_AUTH_SOCK" ] || {
docker_run_args+=" -v $SSH_AUTH_SOCK:/ssh-agent -e SSH_AUTH_SOCK=/ssh-agent "
}
[ ! -d "$HOME/.ssh" ] || {
ensure_ssh_script='mkdir -p ~/.ssh && chmod 700 ~/.ssh && cp /root/ssh/* /root/.ssh && chmod 600 /root/.ssh/*;'
}
[ ! -e "$HOME/.ssh/config" ] || {
docker_run_args+=" -v $HOME/.ssh/config:/root/ssh/config:ro "
}
[ ! -e "$HOME/.ssh/known_hosts" ] || {
docker_run_args+=" -v $HOME/.ssh/known_hosts:/root/ssh/known_hosts:ro "
}
[ "$#" -eq 0 ] || {
command="$(printf "%q " "$@")"
}
set -x
sudo docker run --rm -it \
-v nix:/nix:rw \
-v "$root":/deploy \
-e NIX_PATH=/deploy:nixpkgs=/deploy/pkgs/nixpkgs \
-e NIX_BUILD_CORES=$NIX_BUILD_CORES \
-w /deploy \
$docker_run_args nixos/nix:2.0 \
nix-shell --command "$ensure_ssh_script ${command:-exec bash}"
$ cat shell.nix
with import <nixpkgs> {};
stdenv.mkDerivation {
name = "deploy-shell";
buildInputs = [
git
bashInteractive
openssh
nano
mc
jq
glibcLocales
rsync
];
shellHook = ''
source ./env
'';
}