Commit 5e2c380e4726
Changed files (9)
imperative
sakhalin
lib
systems
sakhalin
imperative/sakhalin/bootstrap.sh
@@ -0,0 +1,91 @@
+#!/usr/bin/env bash
+
+# Sakhalin (Fedora Workstation) bootstrap script.
+# Installs Determinate Nix, deploys minimal host files, and activates Home Manager.
+
+if [[ "${BASH_SOURCE[0]:-}" == "${0}" ]]; then
+ set -euo pipefail
+fi
+
+readonly GREEN='\033[0;32m'
+readonly YELLOW='\033[0;33m'
+readonly RED='\033[0;31m'
+readonly NC='\033[0m'
+
+REPO_URL="${REPO_URL:-https://git.sbr.pm/home.git}"
+REPO_PATH="${REPO_PATH:-$HOME/src/home}"
+SYSTEM_CONFIG="${SYSTEM_CONFIG:-sakhalin}"
+
+log_info() { echo -e "${GREEN}[INFO]${NC} $*"; }
+log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
+log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
+
+check_root() {
+ if [[ $EUID -eq 0 ]]; then
+ log_error "Run as your regular user, not root (sudo is used when needed)"
+ exit 1
+ fi
+}
+
+source_nix() {
+ if ! command -v nix &>/dev/null && [[ -f /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh ]]; then
+ # shellcheck disable=SC1091
+ . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
+ fi
+}
+
+install_nix() {
+ if command -v nix &>/dev/null; then
+ log_info "Nix already installed: $(nix --version)"
+ return 0
+ fi
+
+ log_info "Installing Nix (Determinate Systems installer)..."
+ curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
+ source_nix
+}
+
+clone_repo() {
+ if [[ -d "$REPO_PATH/.git" ]]; then
+ log_info "Repository exists at $REPO_PATH, pulling..."
+ git -C "$REPO_PATH" pull --ff-only || log_warn "Pull failed, continuing with existing checkout"
+ return 0
+ fi
+
+ log_info "Cloning $REPO_URL → $REPO_PATH"
+ mkdir -p "$(dirname "$REPO_PATH")"
+ git clone "$REPO_URL" "$REPO_PATH"
+}
+
+setup_host_configs() {
+ local config_path
+
+ cd "$REPO_PATH"
+ config_path=$(nix build ".#fedoraConfigs.${SYSTEM_CONFIG}" --no-link --print-out-paths)
+ sudo "${config_path}/deploy"
+}
+
+enable_wireguard() {
+ log_info "Enabling WireGuard for a future boot after private-key restoration..."
+ sudo systemctl enable wg-quick@wg0.service
+}
+
+setup_home_manager() {
+ cd "$REPO_PATH"
+ nix run home-manager -- switch --flake ".#vincent@${SYSTEM_CONFIG}" -b backup
+}
+
+main() {
+ log_info "Bootstrapping Sakhalin..."
+ check_root
+ install_nix
+ clone_repo
+ setup_host_configs
+ enable_wireguard
+ setup_home_manager
+ log_info "Sakhalin bootstrap completed. Restore /etc/wireguard/private.key before starting WireGuard."
+}
+
+if [[ "${BASH_SOURCE[0]:-}" == "${0}" ]]; then
+ main "$@"
+fi
imperative/sakhalin/README.md
@@ -0,0 +1,43 @@
+# Sakhalin — Fedora Workstation + Determinate Nix
+
+Sakhalin is intended to become a Fedora Workstation family machine. Fedora owns
+its packages, desktop, and networking; Determinate Nix provides Nix and
+standalone Home Manager manages the small shared user configuration.
+
+## Bootstrap
+
+After Fedora is installed, run as `vincent`:
+
+```bash
+bash imperative/sakhalin/bootstrap.sh
+```
+
+The script installs Nix when necessary, obtains `~/src/home`, deploys generated
+`/etc/hosts`, `/etc/nix/nix.custom.conf`, and `/etc/wireguard/wg0.conf`, enables
+`wg-quick@wg0`, and activates `vincent@sakhalin` through Home Manager.
+
+WireGuard is enabled but not started by the bootstrap. Restore the preserved
+private key with mode `0600`, then start it:
+
+```bash
+sudo install -m 0600 /path/to/private.key /etc/wireguard/private.key
+sudo systemctl start wg-quick@wg0.service
+```
+
+## Routine updates
+
+```bash
+make host/sakhalin/build
+make host/sakhalin/switch
+```
+
+`host/sakhalin/switch` deploys the generated host files with sudo, then switches
+Home Manager. It does not start WireGuard.
+
+## Managed configuration
+
+- [`systems/sakhalin/gen-configs.nix`](../../systems/sakhalin/gen-configs.nix)
+ generates the small Fedora host-file set.
+- [`systems/sakhalin/home.nix`](../../systems/sakhalin/home.nix) omits the
+ NixOS-only mail services for the standalone profile.
+- WireGuard private-key material remains outside the repository and Nix store.
imperative/sakhalin/test-bootstrap.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+
+set -euo pipefail
+
+repo_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
+bootstrap="$repo_root/imperative/sakhalin/bootstrap.sh"
+generator="$repo_root/systems/sakhalin/gen-configs.nix"
+
+[[ -x "$bootstrap" ]]
+# shellcheck disable=SC2016 # Literal shell fragments are intentional assertions.
+grep -q 'SYSTEM_CONFIG="${SYSTEM_CONFIG:-sakhalin}"' "$bootstrap"
+# shellcheck disable=SC2016 # Literal shell fragments are intentional assertions.
+grep -q 'fedoraConfigs.${SYSTEM_CONFIG}' "$bootstrap"
+# shellcheck disable=SC2016 # Literal shell fragments are intentional assertions.
+grep -q 'home-manager -- switch --flake ".#vincent@${SYSTEM_CONFIG}" -b backup' "$bootstrap"
+grep -q 'systemctl enable wg-quick@wg0.service' "$bootstrap"
+if grep -q 'enable --now wg-quick@wg0' "$bootstrap"; then
+ exit 1
+fi
+
+grep -q '"vincent@sakhalin"' "$repo_root/flake.nix"
+grep -q 'import ./systems/sakhalin/gen-configs.nix' "$repo_root/flake.nix"
+grep -q '# sakhalin = libx.mkHost' "$repo_root/flake.nix"
+if grep -q 'nmDispatcher' "$generator"; then
+ exit 1
+fi
+grep -q 'host/sakhalin/build' "$repo_root/Makefile"
+grep -q 'host/sakhalin/switch' "$repo_root/Makefile"
+
+cd "$repo_root"
+nix eval --raw '.#homeConfigurations."vincent@sakhalin".activationPackage.drvPath' >/dev/null
+nix build .#fedoraConfigs.sakhalin --dry-run >/dev/null
imperative/README.md
@@ -33,7 +33,10 @@ imperative/
├── aomi/ # Fedora CSB laptop — Nix (system-manager + home-manager)
│ ├── README.md
│ └── bootstrap.sh
-└── nagoya/ # Debian server — Determinate Nix + Home Manager
+├── nagoya/ # Debian server — Determinate Nix + Home Manager
+│ ├── README.md
+│ └── bootstrap.sh
+└── sakhalin/ # Fedora family workstation — minimal Nix + Home Manager
├── README.md
└── bootstrap.sh
```
@@ -65,6 +68,17 @@ See [aomi/README.md](aomi/README.md) for details.
See [nagoya/README.md](nagoya/README.md) for details.
+### sakhalin — Fedora Workstation
+
+- **OS:** Fedora Workstation
+- **Type:** Family workstation
+- **Approach:** Determinate Nix with minimal standalone Home Manager and
+ Nix-generated `/etc/hosts`, `/etc/nix/nix.custom.conf`, and WireGuard config
+- **Components:** shared shell baseline and Syncthing; WireGuard is enabled once
+ its externally preserved private key is restored
+
+See [sakhalin/README.md](sakhalin/README.md) for details.
+
## Usage
### Nix-managed hosts
lib/default.nix
@@ -14,6 +14,7 @@
hostname,
username,
desktop ? null,
+ standaloneFedora ? false,
system ? "x86_64-linux",
}:
let
@@ -56,6 +57,7 @@
stateVersion
hostname
desktop
+ standaloneFedora
globals
username
system
systems/sakhalin/gen-configs.nix
@@ -0,0 +1,53 @@
+# Generate the small set of host files Sakhalin needs outside Home Manager.
+# Fedora manages packages, services, and networking.
+{
+ pkgs,
+ globals,
+ libx,
+ ...
+}:
+let
+ machine = globals.machines.sakhalin;
+ hostsEntries = libx.hostConfigs globals.machines;
+ hosts = pkgs.writeText "hosts" ''
+ 127.0.0.1 localhost sakhalin
+ ::1 localhost
+ ${pkgs.lib.concatStringsSep "\n" (
+ pkgs.lib.mapAttrsToList (ip: names: "${ip} ${pkgs.lib.concatStringsSep " " names}") hostsEntries
+ )}
+ '';
+
+ wgConf = pkgs.writeText "wg0.conf" ''
+ [Interface]
+ PostUp = wg set %i private-key /etc/wireguard/private.key
+ Address = ${builtins.head machine.net.vpn.ips}/24
+
+ [Peer]
+ PublicKey = ${globals.machines.carthage.net.vpn.pubkey}
+ AllowedIPs = 10.100.0.0/24
+ Endpoint = ${globals.net.vpn.endpoint}:51820
+ PersistentKeepalive = 25
+ '';
+
+ nixCustomConf = pkgs.writeText "nix.custom.conf" ''
+ trusted-users = root @wheel
+ connect-timeout = 5
+ download-attempts = 2
+ builders-use-substitutes = true
+ '';
+
+ deploy = pkgs.writeShellScript "deploy-sakhalin-configs" ''
+ set -euo pipefail
+ install -m 0644 ${hosts} /etc/hosts
+ install -d -m 0755 /etc/nix /etc/wireguard
+ install -m 0644 ${nixCustomConf} /etc/nix/nix.custom.conf
+ install -m 0600 ${wgConf} /etc/wireguard/wg0.conf
+ '';
+in
+pkgs.runCommand "sakhalin-configs" { } ''
+ mkdir -p "$out/etc/nix" "$out/etc/wireguard"
+ cp ${hosts} "$out/etc/hosts"
+ cp ${nixCustomConf} "$out/etc/nix/nix.custom.conf"
+ cp ${wgConf} "$out/etc/wireguard/wg0.conf"
+ cp ${deploy} "$out/deploy"
+''
systems/sakhalin/home.nix
@@ -1,6 +1,10 @@
-{ ... }:
{
- imports = [
+ lib,
+ standaloneFedora ? false,
+ ...
+}:
+{
+ imports = lib.optionals (!standaloneFedora) [
../../home/common/services/imapfilter.nix
../../home/common/services/imapfilter-rules-updater.nix
../../home/common/services/mail-monitor.nix
flake.nix
@@ -69,6 +69,11 @@
hostname = "nagoya";
system = "aarch64-linux";
};
+ "vincent@sakhalin" = libx.mkHome {
+ username = "vincent";
+ hostname = "sakhalin";
+ standaloneFedora = true;
+ };
# headless machine
"vincent@aion" = libx.mkHome {
username = "vincent";
@@ -88,9 +93,9 @@
desktop = "niri"; # or "sway"
};
# Servers (unstable)
- sakhalin = libx.mkHost {
- hostname = "sakhalin";
- };
+ # sakhalin = libx.mkHost {
+ # hostname = "sakhalin";
+ # };
shikoku = libx.mkHost {
hostname = "shikoku";
pkgsInput = inputs.nixpkgs-26_05;
@@ -168,6 +173,19 @@
{
kyushu = mkFedoraConfigs "kyushu";
aomi = mkFedoraConfigs "aomi";
+ sakhalin =
+ let
+ pkgs = import inputs.nixpkgs { system = "x86_64-linux"; };
+ globals = import ./globals.nix {
+ inherit (inputs.nixpkgs) lib;
+ hostname = "sakhalin";
+ };
+ fedoraLibx = import ./lib/functions.nix { inherit (inputs.nixpkgs) lib; };
+ in
+ import ./systems/sakhalin/gen-configs.nix {
+ inherit pkgs globals;
+ libx = fedoraLibx;
+ };
};
hostConfigs = {
Makefile
@@ -30,6 +30,17 @@ host/%/switch: FORCE ## Deploy to remote host and activate immediately (e.g., ma
nixos-rebuild --target-host root@$*.sbr.pm --flake .#$* switch
# Host-specific overrides (non-standard DNS/network)
+.PHONY: host/sakhalin/build
+host/sakhalin/build: ## Build Home Manager and generated host files for Sakhalin
+ nix build .#homeConfigurations.vincent@sakhalin.activationPackage --no-link
+ nix build .#fedoraConfigs.sakhalin --no-link
+
+.PHONY: host/sakhalin/switch
+host/sakhalin/switch: ## Deploy generated host files and switch Home Manager on Sakhalin
+ nix build .#fedoraConfigs.sakhalin
+ sudo ./result/deploy
+ nix run home-manager -- switch --flake .#vincent@sakhalin -b backup
+
.PHONY: host/nagoya/build
host/nagoya/build: ## Build Home Manager and generated host files for Nagoya
nix build .#homeConfigurations.vincent@nagoya.activationPackage --no-link