-
-
Save ojensen5115/fbf496f228e0adf63ab0bdeb753db7ac to your computer and use it in GitHub Desktop.
My rebuild script for nixos
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 | |
| set -euo pipefail | |
| # Process options | |
| UPDATE=0 | |
| BOOT=0 | |
| IGNORE_DIFF=0 | |
| ROLLBACK=0 | |
| ALT_HOST=0 | |
| while getopts ":ubirah" opt; do | |
| case "$opt" in | |
| u) UPDATE=1 ;; | |
| b) BOOT=1 ;; | |
| i) IGNORE_DIFF=1 ;; | |
| r) ROLLBACK=1 ;; | |
| a) ALT_HOST=1 ;; | |
| h) echo "Usage: rebuild [-u] [-b] [-i] [-r] [-a] [flake-target] | |
| -u Update this target's nixpkgs input before rebuilding | |
| -b Use 'boot' instead of 'switch' (activate on next boot) | |
| -i Skip diff check | |
| -r Roll back to the previous generation | |
| -a Reach web via its native droplet IP instead of the | |
| reserved IP (workaround for flaky reserved-IP routing) | |
| flake-target Optional nixosConfigurations.<name>; defaults to \$(hostname) | |
| "; exit 0 ;; | |
| \?) echo "Unknown option: -$OPTARG" >&2; exit 2 ;; | |
| esac | |
| done | |
| shift $((OPTIND-1)) | |
| TARGET="${1:-$(hostname)}" | |
| # Per-target config: ssh destination (empty = local) and which flake input | |
| # holds this target's nixpkgs, so hosts can be updated independently. | |
| REMOTE="" | |
| ALT_REMOTE="" | |
| INPUT="nixpkgs" | |
| case "$TARGET" in | |
| web) | |
| REMOTE="root@0x3c.net" | |
| ALT_REMOTE="root@64.227.12.77" # native droplet IP | |
| INPUT="nixpkgs-web" | |
| ;; | |
| esac | |
| if (( ALT_HOST )); then | |
| if [[ -z "$ALT_REMOTE" ]]; then | |
| echo "-a is not valid for target '${TARGET}'" >&2 | |
| exit 2 | |
| fi | |
| echo "Using alternate host ${ALT_REMOTE}" | |
| REMOTE="$ALT_REMOTE" | |
| fi | |
| # Decide which subcommand to use | |
| SUBCOMMAND="switch" | |
| if (( BOOT )); then | |
| SUBCOMMAND="boot" | |
| fi | |
| # Enter the directory | |
| pushd ~/flake >/dev/null | |
| # Rollback short-circuits everything else | |
| if (( ROLLBACK )); then | |
| echo "Rolling back ${TARGET}..." | |
| if [[ -n "$REMOTE" ]]; then | |
| nixos-rebuild switch --rollback --flake ".#${TARGET}" --target-host "$REMOTE" | |
| else | |
| sudo -v | |
| sudo nixos-rebuild switch --rollback --flake ".#${TARGET}" | |
| fi | |
| popd >/dev/null | |
| notify-send "NixOS rolled back (${TARGET})" --icon=software-update-available | |
| exit 0 | |
| fi | |
| # Conditionally update this target's nixpkgs input | |
| if (( UPDATE )); then | |
| echo "Updating flake input ${INPUT}..." | |
| nix flake update "$INPUT" | |
| fi | |
| # Autoformat nix files | |
| alejandra . &>/dev/null || ( alejandra . ; echo "formatting failed!" && exit 1) | |
| # Early return if no changes after update or format. | |
| # Skipped for remote targets: config may be unchanged locally but not yet | |
| # deployed, e.g. redeploying after fixing something on the box by hand. | |
| git add -A | |
| if ! (( IGNORE_DIFF )) && [[ -z "$REMOTE" ]]; then | |
| if git diff --quiet HEAD; then | |
| echo "No changes detected, exiting." | |
| popd >/dev/null | |
| exit 0 | |
| fi | |
| fi | |
| # Shows changes | |
| git diff -U0 HEAD | |
| if [[ -n "$REMOTE" ]]; then | |
| echo "Building locally & deploying to ${REMOTE} (target: ${TARGET})..." | |
| if ! nixos-rebuild "${SUBCOMMAND}" --flake ".#${TARGET}" --target-host "$REMOTE"; then | |
| notify-send -e "NixOS deploy to ${TARGET} failed" | |
| popd >/dev/null | |
| exit 1 | |
| fi | |
| else | |
| # Get sudo permissions | |
| echo "Acquiring sudo..." | |
| sudo -v | |
| echo "Building & activating with nixos-rebuild ${SUBCOMMAND} (target: ${TARGET})..." | |
| if ! sudo nixos-rebuild "${SUBCOMMAND}" --flake ".#${TARGET}"; then | |
| notify-send -e "NixOS build/activation failed" | |
| popd >/dev/null | |
| exit 1 | |
| fi | |
| fi | |
| # Build the commit message. | |
| if [[ -n "$REMOTE" ]]; then | |
| sys_target="$(ssh "$REMOTE" 'readlink /nix/var/nix/profiles/system')" | |
| else | |
| sys_target="$(readlink /nix/var/nix/profiles/system)" | |
| fi | |
| gen_num="${sys_target#system-}" | |
| gen_num="${gen_num%-link}" | |
| timestamp="$(date '+%Y-%m-%d %H:%M:%S')" | |
| message="$TARGET -- Gen $gen_num ($timestamp)" | |
| # Commit all changes with the generation metadata (no-op if nothing changed) | |
| git commit -am "$message" || true | |
| popd >/dev/null | |
| # Tailor the notification to whether we switched or staged for boot | |
| if (( BOOT )); then | |
| notify-send "NixOS Built for Next Boot (${TARGET})" --icon=software-update-available | |
| else | |
| notify-send "NixOS Rebuilt OK! (${TARGET})" --icon=software-update-available | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment