-
-
Save cstrahan/84b2b70d6724f7383513 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /usr/bin/env bash | |
# WARNING NB This script wipes out the targeted host's root filesystem when it | |
# runs to completion. Any errors halt execution. set -x is used to help debug, | |
# as often a failed run leaves the system in an inconsistent state, requiring a | |
# rebuild (in DigitalOcean panel: Droplet Settings -> "Destroy" -> "Rebuild | |
# from original"). | |
# | |
# TO USE: | |
# - Add any custom config you want (see notes below) | |
# - Deploy a Debian 8.3 x64 droplet (enable ipv6; add your ssh key) | |
# - cat customConfig.optional nixos-infect | ssh root@targethost bash | |
# | |
# This was last tested with the DigitalOcean Debian 8.3 x64 and Ubuntu 15.10 | |
# x64 images. Different versions and archs (namely i386) should work as well, | |
# but then, there's not much point in selecting something different if you | |
# intend to wipe out the fs, as this script does. You may need to make minor | |
# modifications to use in other templates, but basically all that will ever | |
# need tweaking are already inlined in this file: | |
# /etc/nixos/{,hardware-}configuration.nix : rudimentary mostly static config | |
# /etc/nixos/networking.nix, networking settings determined at runtime | |
# tweak if no ipv6, different number of adapters, etc. | |
# | |
# Motivation for this script: nixos-assimilate should supplant this script | |
# entirely, if it's ever completed. nixos-in-place was quite broken when I | |
# tried it, and also took a pretty janky approach that was substantially more | |
# complex than this (although it supported more platforms): it didn't install | |
# to root (/nixos instead), left dregs of the old filesystem (almost always | |
# unnecessary since starting from a fresh deployment), and most importantly, | |
# simply didn't work for me! (old system was being because grub wasnt properly | |
# reinstalled) | |
set -ex | |
makeConf() { | |
# NB remember to escape / $ ` in heredocs! | |
# TODO use appended archive or some curl-able tarball? | |
mkdir -p /etc/nixos | |
IFS=$'\n'; keys=($(cat /root/.ssh/authorized_keys)) | |
cat > /etc/nixos/networking.nix << EOF | |
# This file will be populated at runtime with the | |
# networking details gathered from the active system. | |
{...}:{} | |
EOF | |
cat > /etc/nixos/configuration.nix << EOF | |
{ ... }: { | |
imports = [ | |
./hardware-configuration.nix | |
./networking.nix # generated at runtime by nixos-infect | |
]; | |
boot.cleanTmpDir = true; | |
networking.hostName = "$(hostname)"; | |
networking.firewall.allowPing = true; | |
services.openssh.enable = true; | |
users.users.root.openssh.authorizedKeys.keys = [$(for key in ${keys[@]}; do echo -n " | |
\"$key\""; done) | |
]; | |
} | |
EOF | |
# (nixos-generate-config will add qemu-user and bind-mounts, so avoid) | |
cat > /etc/nixos/hardware-configuration.nix << EOF | |
{ ... }: { | |
imports = [ <nixpkgs/nixos/modules/profiles/qemu-guest.nix> ]; | |
boot.loader.grub.devices = [ "/dev/vda" ]; | |
fileSystems."/" = { device = "/dev/vda1"; fsType = "ext4"; }; | |
} | |
EOF | |
#! /usr/bin/env bash | |
# NB put your semi-sensitive (not posted to github) configuration in a separate | |
# file and include it via this customConfig() function. e.g.: | |
# customConfig() { | |
# cat > /etc/nixos/custom.nix << EOF | |
# { config, lib, pkgs, ... }: { | |
# } | |
# EOF | |
# } | |
# | |
# then you can add the files in configuration.nix's imports above and run something like: | |
# cat customConfig nixos-infect | root@targethost bash | |
if [[ `type -t customConfig` == "function" ]]; then customConfig; fi | |
} | |
makeSwap() { | |
if [[ ! -e /swap ]]; then | |
dd if=/dev/zero of=/swap bs=1M count=$((1024*2)) | |
chmod 0600 /swap | |
mkswap /swap | |
swapon /swap | |
fi | |
} | |
makeConf | |
makeSwap # smallest (512MB) droplet needs extra memory! | |
apt-get install -y curl sudo rsync | |
groupadd -r nixbld | |
seq 1 10 | xargs -I{} useradd -c "Nix build user {}" -d /var/empty -g nixbld -G nixbld -M -N -r -s `which nologin` nixbld{} | |
curl https://nixos.org/nix/install | sh | |
source ~/.nix-profile/etc/profile.d/nix.sh | |
nix-channel --add https://nixos.org/channels/nixos-unstable nixos | |
nix-channel --update | |
newRootImg=`mktemp` | |
newRootMount=`mktemp -d` | |
oldRootMount=`mktemp -d` | |
export NIXOS_CONFIG=/etc/nixos/configuration.nix | |
nix-env -i -f /nix/var/nix/profiles/per-user/root/channels/nixpkgs/nixos \ | |
-A config.system.build.nixos-install \ | |
-A config.system.build.nixos-option \ | |
-A config.system.build.nixos-generate-config | |
# XXX GOTCHA NB bindmount causes /bin/bash permission BUG on many | |
# versions (nix 1.10-1.11, nixpkgs 15-16), so we must use loopback image instead. | |
dd if=/dev/zero of=$newRootImg bs=1M count=$((1024*2)) | |
mkfs.ext4 $newRootImg | |
mount $newRootImg $newRootMount | |
rsync -aR /./etc/nixos $newRootMount | |
nixos-install --root $newRootMount | |
swapoff /swap | |
mount -B / $oldRootMount | |
rsync -a --delete --exclude=$(dirname $newRootMount) $newRootMount/ $oldRootMount | |
# restore access to commands | |
/nix/var/nix/profiles/system/activate | |
source /nix/var/nix/profiles/system/etc/profile | |
# XXX temporary fix for name resolution | |
echo nameserver 8.8.4.4 > /etc/resolv.conf | |
IFS=$'\n' | |
ip4s=($(ip address show dev eth0 | grep 'inet ' | sed -r 's|.*inet ([0-9.]+)/([0-9]+).*|{ address="\1"; prefixLength=\2; }|')) | |
ip6s=($(ip address show dev eth0 | grep 'inet6 .*global' | sed -r 's|.*inet6 ([0-9a-f:]+)/([0-9]+).*|{ address="\1"; prefixLength=\2; }|')) | |
gateway=($(ip route show dev eth0 | grep default | sed -r 's|default via ([0-9.]+).*|\1|')) | |
gateway6=($(ip -6 route show dev eth0 | grep default | sed -r 's|default via ([0-9a-f:]+).*|\1|')) | |
ether0=($(ip address show dev eth0 | grep link/ether | sed -r 's|.*link/ether ([0-9a-f:]+) .*|\1|')) | |
ether1=($(ip address show dev eth1 | grep link/ether | sed -r 's|.*link/ether ([0-9a-f:]+) .*|\1|')) | |
cat > /etc/nixos/networking.nix << EOF | |
{ ... }: { | |
networking = { | |
nameservers = [ "8.8.4.4" ]; | |
defaultGateway = "${gateway}"; | |
defaultGateway6 = "${gateway6}"; | |
interfaces = { | |
eth0 = { | |
ip4 = [$(for a in ${ip4s[@]}; do echo -n " | |
$a"; done) | |
]; | |
ip6 = [$(for a in ${ip6s[@]}; do echo -n " | |
$a"; done) | |
]; | |
}; | |
# eth1 is for private networking or something? | |
eth1.useDHCP = false; | |
}; | |
}; | |
services.udev.extraRules = '' | |
KERNEL=="eth*", ATTR{address}=="${ether0}", NAME="eth0" | |
KERNEL=="eth*", ATTR{address}=="${ether1}", NAME="eth1" | |
''; | |
} | |
EOF | |
# grub/initrd was probably installed incorrectly (using false root device), so we need a final rebuild | |
nixos-rebuild boot --install-grub | |
sync | |
echo "You may now Ctrl-C or otherwise terminate this process." | |
reboot -f |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment