My nix-darwin and NixOS config
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

darwin: remove automated Time Machine setup; document manual tmutil flow

- Drop activation script for tmutil setdestination (requires root + Full Disk Access)
- Document one-time manual Time Machine registration in docs/time-machine.md
- Clarify that destination persists and cannot be automated without MDM
- Rename AltServer launch agent label and make it explicit one-shot (KeepAlive = false)

+28 -71
+21 -19
docs/time-machine.md
··· 1 1 # Time Machine Setup 2 2 3 3 Backups go to a dedicated APFS volume on the external CT2000X9SSD9 (USB, `disk4`/`disk5`). 4 - The `nrs` activation script handles registration and mounting automatically on every rebuild — 5 - this doc covers the one-time volume creation only. 4 + 5 + ## Why this isn't automated 6 + 7 + `tmutil setdestination` requires root **and** Full Disk Access (TCC). macOS does not allow 8 + FDA to be granted to scripts or launchd daemons without MDM — so it fundamentally cannot 9 + be run from a `nrs` activation script. The destination only needs to be set **once manually**; 10 + it then persists across reboots and `nrs` runs indefinitely. 6 11 7 12 ## First-time setup 8 13 9 - ### 1. Create the Time Machine APFS volume 14 + ### 1. Create the Time Machine APFS volume (if not already done) 10 15 11 16 ```bash 12 17 sudo diskutil apfs addVolume disk5 APFS "Time Machine" 13 18 ``` 14 19 15 - > `disk5` is the APFS container that lives on `disk4s2`. Run `diskutil list` to confirm 16 - > it's still the right identifier before running this. 20 + > `disk5` is the APFS container on `disk4s2`. Run `diskutil list` to confirm the right 21 + > identifier before running this. 17 22 18 23 ### 2. Get the volume UUID 19 24 ··· 29 34 myConfig.darwin.externalDisk.timeMachineVolumeUUID = "<uuid from step 2>"; 30 35 ``` 31 36 32 - ### 4. Rebuild 37 + This is used only for documentation/reference — `nrs` no longer runs any TM automation. 38 + 39 + ### 4. Register the destination (once, manually) 33 40 34 41 ```bash 35 - nrs 42 + sudo tmutil setdestination "/Volumes/Time Machine" 36 43 ``` 37 44 38 - The activation script will mount the volume if needed and register it as a Time Machine 39 - destination. Backups run on a weekly interval (configured via `tmutil setbackupinterval`). 40 - 41 - ## How it works 45 + This requires your terminal to have Full Disk Access granted in 46 + **System Settings → Privacy & Security → Full Disk Access**. 42 47 43 - `modules/darwin/system.nix` runs a `system.activationScripts.timeMachineDestination` on 44 - every `nrs`. It: 48 + ### 5. Verify 45 49 46 - 1. Looks up the volume by UUID via `diskutil info` 47 - 2. Mounts it if it exists but isn't mounted 48 - 3. Registers it with `tmutil setdestination -a` if not already registered 49 - 4. Skips silently if the disk isn't plugged in 50 + ```bash 51 + tmutil destinationinfo 52 + ``` 50 53 51 - Setting `myConfig.darwin.externalDisk.timeMachineVolumeUUID = null` disables the script 52 - entirely. 54 + You should see the volume listed. Time Machine will now back up to it automatically. 53 55 54 56 ## Server Time Machine (not configured) 55 57
+2 -2
hosts/macmini/default.nix
··· 32 32 # AltServer is a menu bar app (LSUIElement = true) so macOS intentionally 33 33 # hides it from Spotlight — this is by design and cannot be changed. 34 34 # Launch it automatically at login via a launchd user agent instead. 35 - launchd.user.agents.AltServer = { 35 + launchd.user.agents."com.rileytestut.AltServer-launcher" = { 36 36 serviceConfig = { 37 - Label = "com.rileytestut.AltServer"; 38 37 ProgramArguments = [ "/usr/bin/open" "-a" "/Applications/AltServer.app" ]; 39 38 RunAtLoad = true; 39 + KeepAlive = false; # one-shot: open the app then exit 40 40 }; 41 41 }; 42 42
+5 -50
modules/darwin/system.nix
··· 1 1 { 2 2 config, 3 - lib, 4 3 ... 5 4 }: 6 5 let ··· 24 23 security.pam.services.sudo_local.touchIdAuth = cfg.darwin.security.touchIdForSudo; 25 24 26 25 # ── Time Machine destination ────────────────────────────────────────────── 27 - # No native nix-darwin option exists for tmutil setdestination, so we use an 28 - # activation script. Skipped entirely if timeMachineVolumeUUID is null. 26 + # tmutil setdestination requires root + Full Disk Access (TCC). macOS does 27 + # not allow FDA to be granted to activation scripts or launchd daemons 28 + # without MDM, so this cannot be automated via nrs. 29 29 # 30 - # The volume is auto-mounted if it exists but isn't mounted yet. 31 - # Idempotent: skipped if the destination is already registered. 32 - # 33 - # NOTE: activation scripts must never call `exit` — that would abort the 34 - # entire nix-darwin activation. Early returns are handled via a wrapper 35 - # function so we can use `return` safely. 36 - system.activationScripts.timeMachineDestination = lib.mkIf 37 - (cfg.darwin.externalDisk.timeMachineVolumeUUID != null) 38 - { 39 - text = 40 - let 41 - uuid = cfg.darwin.externalDisk.timeMachineVolumeUUID; 42 - in 43 - '' 44 - _setup_time_machine() { 45 - echo "Checking local Time Machine volume (UUID=${uuid})..." 46 - _info=$(/usr/sbin/diskutil info "${uuid}" 2>/dev/null) || { 47 - echo " Disk not found — skipping Time Machine setup." 48 - return 0 49 - } 50 - 51 - _mount=$(echo "$_info" | /usr/bin/awk '/Mount Point/ { for(i=3;i<=NF;i++) printf "%s ", $i; print "" }' | /usr/bin/sed 's/ *$//') 52 - if [ -z "$_mount" ] || [ "$_mount" = "Not applicable (no file system)" ]; then 53 - echo " Volume not mounted — mounting..." 54 - /usr/sbin/diskutil mount "${uuid}" 2>&1 || true 55 - _mount=$(/usr/sbin/diskutil info "${uuid}" 2>/dev/null | /usr/bin/awk '/Mount Point/ { for(i=3;i<=NF;i++) printf "%s ", $i; print "" }' | /usr/bin/sed 's/ *$//') 56 - fi 57 - 58 - if [ -z "$_mount" ] || [ "$_mount" = "Not applicable (no file system)" ]; then 59 - echo " Could not mount volume — skipping Time Machine setup." 60 - return 0 61 - fi 62 - 63 - if /usr/bin/tmutil destinationinfo 2>/dev/null | /usr/bin/grep -qF "$_mount"; then 64 - echo " Already registered as Time Machine destination, skipping." 65 - else 66 - echo " Registering $_mount as Time Machine destination..." 67 - /usr/bin/tmutil setdestination -a "$_mount" 2>&1 || \ 68 - echo " WARNING: tmutil setdestination failed." 69 - fi 70 - 71 - # Weekly backup interval (604800 seconds = 7 days) 72 - /usr/bin/tmutil setbackupinterval 604800 73 - } 74 - _setup_time_machine 75 - ''; 76 - }; 30 + # The destination only needs to be set once manually (see docs/time-machine.md). 31 + # It persists across reboots and nrs runs, so no automation is needed. 77 32 }