83 Commits

Author SHA1 Message Date
UGA Innovation Factory
c4a44cbddb use checksum for usda-dash src copy
All checks were successful
CI / Format Check (push) Successful in 1s
CI / Flake Check (push) Successful in 1m17s
CI / Evaluate Key Configurations (nix-builder) (push) Successful in 10s
CI / Evaluate Key Configurations (nix-desktop1) (push) Successful in 11s
CI / Evaluate Key Configurations (nix-laptop1) (push) Successful in 8s
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Successful in 16s
CI / Evaluate Artifacts (lxc-nix-builder) (push) Successful in 10s
2025-12-19 23:55:17 +00:00
UGA Innovation Factory
27281f223f use checksum for usda-dash src copy 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
9c4aa59868 update 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
07d32eb459 round bottom border on password 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
3edadbf546 round bottom border on password 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
1bcb354b0c fix for password too on usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
b960ba8ff2 actually fix text color for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
135a126b91 apply text color to body for usda-vision 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
2e9c888f06 respect font import better with safari for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
8e801474cf updated dark color scheme to show text on login for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
532a57ab3d usda dashboard external url in allowed hosts 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
b2ba4f59dc update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
e02c904d16 update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
6bf8e7fdb6 update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
309efa9e16 update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
b758bb2c71 update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
4f5ad03bc9 update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
79a0c3e75e update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
29571e842a update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
cf65a2a968 update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
315b248f14 update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
01c0dbc4ae update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
6bcc562697 update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
b9ea8d8a8e update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
5f53d6c839 update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
af22dbe03e update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
8776f19562 update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
89011003b5 update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
b83c8709fc update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
a6e9b2665d update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
cb7df047a8 update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
23af6a3050 update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
f037ad8f49 update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
958a815489 update external config for usda-dash 2025-12-19 23:55:17 +00:00
UGA Innovation Factory
0c81e2218f improve reference updater tool
All checks were successful
CI / Format Check (push) Successful in 2s
CI / Flake Check (push) Successful in 1m15s
CI / Evaluate Key Configurations (nix-builder) (push) Successful in 10s
CI / Evaluate Key Configurations (nix-desktop1) (push) Successful in 11s
CI / Evaluate Key Configurations (nix-laptop1) (push) Successful in 8s
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Successful in 19s
CI / Evaluate Artifacts (lxc-nix-builder) (push) Successful in 10s
2025-12-19 15:52:39 -05:00
UGA Innovation Factory
cce1ee4a2c improve reference updater tool
All checks were successful
CI / Format Check (push) Successful in 2s
CI / Flake Check (push) Successful in 1m16s
CI / Evaluate Key Configurations (nix-builder) (push) Successful in 10s
CI / Evaluate Key Configurations (nix-desktop1) (push) Successful in 11s
CI / Evaluate Key Configurations (nix-laptop1) (push) Successful in 8s
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Successful in 16s
CI / Evaluate Artifacts (lxc-nix-builder) (push) Successful in 9s
2025-12-19 15:25:20 -05:00
UGA Innovation Factory
35223b6435 add a reference updater tool
Some checks failed
CI / Format Check (push) Failing after 2s
CI / Flake Check (push) Has been skipped
CI / Evaluate Key Configurations (nix-builder) (push) Has been skipped
CI / Evaluate Key Configurations (nix-desktop1) (push) Has been skipped
CI / Evaluate Key Configurations (nix-laptop1) (push) Has been skipped
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Has been skipped
CI / Evaluate Artifacts (lxc-nix-builder) (push) Has been skipped
2025-12-19 13:08:59 -05:00
UGA Innovation Factory
cb9bff5d74 updater to not require sudo prefix for flags
All checks were successful
CI / Format Check (push) Successful in 1s
CI / Flake Check (push) Successful in 1m20s
CI / Evaluate Key Configurations (nix-builder) (push) Successful in 10s
CI / Evaluate Key Configurations (nix-desktop1) (push) Successful in 11s
CI / Evaluate Key Configurations (nix-laptop1) (push) Successful in 7s
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Successful in 16s
CI / Evaluate Artifacts (lxc-nix-builder) (push) Successful in 10s
2025-12-19 16:00:33 +00:00
UGA Innovation Factory
aa233dbbc8 update the updater to support flags for privileged users
All checks were successful
CI / Format Check (push) Successful in 1s
CI / Flake Check (push) Successful in 1m16s
CI / Evaluate Key Configurations (nix-builder) (push) Successful in 11s
CI / Evaluate Key Configurations (nix-desktop1) (push) Successful in 12s
CI / Evaluate Key Configurations (nix-laptop1) (push) Successful in 8s
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Successful in 16s
CI / Evaluate Artifacts (lxc-nix-builder) (push) Successful in 9s
2025-12-19 15:41:14 +00:00
hdh20267
b81500bd7b Merge pull request 'update external config for usda-dash' (#17) from usda-docker into main
All checks were successful
CI / Format Check (push) Successful in 2s
CI / Flake Check (push) Successful in 1m17s
CI / Evaluate Key Configurations (nix-builder) (push) Successful in 10s
CI / Evaluate Key Configurations (nix-desktop1) (push) Successful in 13s
CI / Evaluate Key Configurations (nix-laptop1) (push) Successful in 9s
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Successful in 18s
CI / Evaluate Artifacts (lxc-nix-builder) (push) Successful in 12s
Reviewed-on: http://git.factory.uga.edu/UGA-Innovation-Factory/athenix/pulls/17
2025-12-18 23:38:37 +00:00
UGA Innovation Factory
4af1549b41 update external config for usda-dash 2025-12-18 18:38:14 -05:00
hdh20267
08802d3147 Merge pull request 'add keys to allow builder to work with ssh git refs' (#16) from builder-ci into main
All checks were successful
CI / Format Check (push) Successful in 2s
CI / Flake Check (push) Successful in 1m27s
CI / Evaluate Key Configurations (nix-builder) (push) Successful in 11s
CI / Evaluate Key Configurations (nix-desktop1) (push) Successful in 12s
CI / Evaluate Key Configurations (nix-laptop1) (push) Successful in 9s
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Successful in 17s
CI / Evaluate Artifacts (lxc-nix-builder) (push) Successful in 12s
Reviewed-on: http://git.factory.uga.edu/UGA-Innovation-Factory/athenix/pulls/16
2025-12-18 23:16:54 +00:00
UGA Innovation Factory
319111b469 add keys to allow builder to work with ssh git refs 2025-12-18 18:16:35 -05:00
hdh20267
44e8a897ca Merge pull request 'update external config for usda-dash' (#15) from usda-docker into main
All checks were successful
CI / Format Check (push) Successful in 7s
CI / Flake Check (push) Successful in 1m16s
CI / Evaluate Key Configurations (nix-builder) (push) Successful in 10s
CI / Evaluate Key Configurations (nix-desktop1) (push) Successful in 12s
CI / Evaluate Key Configurations (nix-laptop1) (push) Successful in 9s
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Successful in 17s
CI / Evaluate Artifacts (lxc-nix-builder) (push) Successful in 11s
Reviewed-on: http://git.factory.uga.edu/UGA-Innovation-Factory/athenix/pulls/15
2025-12-18 21:56:38 +00:00
UGA Innovation Factory
6e755a1db0 update external config for usda-dash 2025-12-18 16:56:06 -05:00
hdh20267
1d70023307 Merge pull request 'update external config for usda-dash' (#14) from usda-docker into main
Some checks failed
CI / Format Check (push) Successful in 2s
CI / Evaluate Key Configurations (nix-builder) (push) Has been cancelled
CI / Evaluate Key Configurations (nix-desktop1) (push) Has been cancelled
CI / Evaluate Key Configurations (nix-laptop1) (push) Has been cancelled
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Has been cancelled
CI / Evaluate Artifacts (lxc-nix-builder) (push) Has been cancelled
CI / Flake Check (push) Has been cancelled
Reviewed-on: http://git.factory.uga.edu/UGA-Innovation-Factory/athenix/pulls/14
2025-12-18 21:45:12 +00:00
UGA Innovation Factory
4819082ed3 update external config for usda-dash 2025-12-18 16:44:48 -05:00
hdh20267
22564e96d4 Merge pull request 'update external config for usda-dash' (#13) from usda-docker into main
Some checks failed
CI / Format Check (push) Successful in 1s
CI / Evaluate Key Configurations (nix-builder) (push) Has been cancelled
CI / Evaluate Key Configurations (nix-desktop1) (push) Has been cancelled
CI / Evaluate Key Configurations (nix-laptop1) (push) Has been cancelled
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Has been cancelled
CI / Evaluate Artifacts (lxc-nix-builder) (push) Has been cancelled
CI / Flake Check (push) Has been cancelled
Reviewed-on: http://git.factory.uga.edu/UGA-Innovation-Factory/athenix/pulls/13
2025-12-18 21:40:55 +00:00
UGA Innovation Factory
ee03958c1e update external config for usda-dash 2025-12-18 16:40:19 -05:00
hdh20267
d4079dae32 Merge pull request 'update external config for usda-dash' (#8) from usda-docker into main
Some checks failed
CI / Format Check (push) Successful in 2s
CI / Evaluate Key Configurations (nix-builder) (push) Has been cancelled
CI / Evaluate Key Configurations (nix-desktop1) (push) Has been cancelled
CI / Evaluate Key Configurations (nix-laptop1) (push) Has been cancelled
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Has been cancelled
CI / Evaluate Artifacts (lxc-nix-builder) (push) Has been cancelled
CI / Flake Check (push) Has been cancelled
Reviewed-on: http://git.factory.uga.edu/UGA-Innovation-Factory/athenix/pulls/8
2025-12-18 21:15:22 +00:00
UGA Innovation Factory
c3211f7446 update external config for usda-dash 2025-12-18 16:15:07 -05:00
hdh20267
65e0840c31 Merge pull request 'update external docker module' (#7) from usda-docker into main
Some checks failed
CI / Format Check (push) Successful in 2s
CI / Evaluate Key Configurations (nix-builder) (push) Has been cancelled
CI / Evaluate Key Configurations (nix-desktop1) (push) Has been cancelled
CI / Evaluate Key Configurations (nix-laptop1) (push) Has been cancelled
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Has been cancelled
CI / Evaluate Artifacts (lxc-nix-builder) (push) Has been cancelled
CI / Flake Check (push) Has been cancelled
Reviewed-on: http://git.factory.uga.edu/UGA-Innovation-Factory/athenix/pulls/7
2025-12-18 21:09:00 +00:00
UGA Innovation Factory
1f55099138 update external docker module 2025-12-18 16:08:45 -05:00
hdh20267
1dc81173e5 Merge pull request 'update external usda-dash-config repo' (#6) from usda-docker into main
Some checks failed
CI / Format Check (push) Successful in 2s
CI / Evaluate Key Configurations (nix-builder) (push) Has been cancelled
CI / Evaluate Key Configurations (nix-desktop1) (push) Has been cancelled
CI / Evaluate Key Configurations (nix-laptop1) (push) Has been cancelled
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Has been cancelled
CI / Evaluate Artifacts (lxc-nix-builder) (push) Has been cancelled
CI / Flake Check (push) Has been cancelled
Reviewed-on: http://git.factory.uga.edu/UGA-Innovation-Factory/athenix/pulls/6
2025-12-18 20:59:28 +00:00
UGA Innovation Factory
0e898c316d update external usda-dash-config repo 2025-12-18 15:58:59 -05:00
hdh20267
6b6f449d9f Merge pull request 'use submodules for usda-dash' (#5) from usda-docker into main
Some checks failed
CI / Format Check (push) Successful in 2s
CI / Evaluate Key Configurations (nix-builder) (push) Has been cancelled
CI / Evaluate Key Configurations (nix-desktop1) (push) Has been cancelled
CI / Evaluate Key Configurations (nix-laptop1) (push) Has been cancelled
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Has been cancelled
CI / Evaluate Artifacts (lxc-nix-builder) (push) Has been cancelled
CI / Flake Check (push) Has been cancelled
Reviewed-on: http://git.factory.uga.edu/UGA-Innovation-Factory/athenix/pulls/5
2025-12-18 20:47:18 +00:00
UGA Innovation Factory
71ea6258e9 use submodules for usda-dash 2025-12-18 15:46:48 -05:00
hdh20267
fd7a4b1156 Merge pull request 'use ssh for usda-dash git fetch' (#4) from usda-docker into main
Some checks failed
CI / Format Check (push) Successful in 1s
CI / Evaluate Key Configurations (nix-desktop1) (push) Has been cancelled
CI / Evaluate Key Configurations (nix-laptop1) (push) Has been cancelled
CI / Evaluate Key Configurations (nix-builder) (push) Has been cancelled
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Has been cancelled
CI / Evaluate Artifacts (lxc-nix-builder) (push) Has been cancelled
CI / Flake Check (push) Has been cancelled
Reviewed-on: http://git.factory.uga.edu/UGA-Innovation-Factory/athenix/pulls/4
2025-12-18 20:38:33 +00:00
UGA Innovation Factory
ac4192f764 use ssh for usda-dash git fetch 2025-12-18 15:37:45 -05:00
hdh20267
795d179788 Merge pull request 'docker compose runner for usda-dash' (#3) from usda-docker into main
All checks were successful
CI / Format Check (push) Successful in 1s
CI / Flake Check (push) Successful in 1m16s
CI / Evaluate Key Configurations (nix-builder) (push) Successful in 10s
CI / Evaluate Key Configurations (nix-desktop1) (push) Successful in 12s
CI / Evaluate Key Configurations (nix-laptop1) (push) Successful in 8s
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Successful in 16s
CI / Evaluate Artifacts (lxc-nix-builder) (push) Successful in 9s
Reviewed-on: http://git.factory.uga.edu/UGA-Innovation-Factory/athenix/pulls/3
2025-12-18 20:23:37 +00:00
UGA Innovation Factory
2acb63e220 docker compose runner for usda-dash 2025-12-18 15:22:32 -05:00
hdh20267
2b7fcf5f21 Merge pull request 'run on pr review, not pr' (#2) from ci-update into main
All checks were successful
CI / Format Check (push) Successful in 2s
CI / Flake Check (push) Successful in 1m17s
CI / Evaluate Key Configurations (nix-builder) (push) Successful in 12s
CI / Evaluate Key Configurations (nix-desktop1) (push) Successful in 11s
CI / Evaluate Key Configurations (nix-laptop1) (push) Successful in 8s
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Successful in 17s
CI / Evaluate Artifacts (lxc-nix-builder) (push) Successful in 10s
Reviewed-on: #2
2025-12-18 19:19:46 +00:00
UGA Innovation Factory
7b8dcc7621 run on pr review, not pr 2025-12-18 19:17:11 +00:00
hdh20267
7941135cb3 Merge pull request 'ci-update' (#1) from ci-update into main
All checks were successful
CI / Format Check (push) Successful in 2s
CI / Flake Check (push) Successful in 1m15s
CI / Evaluate Key Configurations (nix-builder) (push) Successful in 10s
CI / Evaluate Key Configurations (nix-desktop1) (push) Successful in 12s
CI / Evaluate Key Configurations (nix-laptop1) (push) Successful in 8s
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Successful in 16s
CI / Evaluate Artifacts (lxc-nix-builder) (push) Successful in 10s
Reviewed-on: #1
2025-12-18 19:10:31 +00:00
UGA Innovation Factory
5eeaa48f09 Revert "change requirements"
All checks were successful
CI / Format Check (pull_request) Successful in 2s
CI / Evaluate Key Configurations (nix-desktop1) (pull_request) Has been skipped
CI / Evaluate Key Configurations (nix-laptop1) (pull_request) Has been skipped
CI / Evaluate Artifacts (lxc-nix-builder) (pull_request) Has been skipped
CI / Flake Check (pull_request) Has been skipped
CI / Evaluate Key Configurations (nix-builder) (pull_request) Has been skipped
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (pull_request) Has been skipped
This reverts commit 75359032b1.
2025-12-18 13:57:40 -05:00
UGA Innovation Factory
75359032b1 change requirements
All checks were successful
CI / Format Check (pull_request) Has been skipped
CI / Flake Check (pull_request) Has been skipped
CI / Evaluate Key Configurations (nix-builder) (pull_request) Has been skipped
CI / Evaluate Key Configurations (nix-desktop1) (pull_request) Has been skipped
CI / Evaluate Key Configurations (nix-laptop1) (pull_request) Has been skipped
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (pull_request) Has been skipped
CI / Evaluate Artifacts (lxc-nix-builder) (pull_request) Has been skipped
2025-12-18 13:54:23 -05:00
UGA Innovation Factory
af81786d52 don't auto-check for all prs 2025-12-18 13:52:43 -05:00
UGA Innovation Factory
90688ec5f1 just evaluate instead of building artificats for CI
All checks were successful
CI / Flake Check (push) Successful in 1m15s
CI / Format Check (push) Successful in 1s
CI / Evaluate Key Configurations (nix-builder) (push) Successful in 9s
CI / Evaluate Key Configurations (nix-desktop1) (push) Successful in 11s
CI / Evaluate Key Configurations (nix-laptop1) (push) Successful in 8s
CI / Evaluate Artifacts (installer-iso-nix-laptop1) (push) Successful in 16s
CI / Evaluate Artifacts (lxc-nix-builder) (push) Successful in 11s
2025-12-18 12:55:27 -05:00
UGA Innovation Factory
0ba0e854cf migrate CI to gitea
All checks were successful
CI / Flake Check (push) Successful in 1m33s
CI / Format Check (push) Successful in 2s
CI / Evaluate Key Configurations (nix-builder) (push) Successful in 10s
CI / Evaluate Key Configurations (nix-desktop1) (push) Successful in 11s
CI / Evaluate Key Configurations (nix-laptop1) (push) Successful in 8s
CI / Build Artifacts (installer-iso-nix-laptop1) (push) Successful in 3m33s
CI / Build Artifacts (lxc-nix-builder) (push) Successful in 57s
2025-12-18 12:35:35 -05:00
UGA Innovation Factory
811eb1bd4b finish rename 2025-12-18 12:24:26 -05:00
UGA Innovation Factory
6ab5f20946 Rename project to 'Athenix' 2025-12-18 12:07:25 -05:00
Hunter Halloran
85ffa56d12 nix flake update 2025-12-17 20:26:03 -05:00
Hunter
6ee51cd747 Merge pull request #10 from UGA-Innovation-Factory/documentation-patch
documentation update
2025-12-17 19:41:44 -05:00
Hunter Halloran
ab3b4a017d documentation update 2025-12-17 19:39:02 -05:00
Hunter
fb6ac75f3c Merge pull request #7 from UGA-Innovation-Factory/user-module-redesign
overhaul external user modules
2025-12-17 16:42:41 -05:00
Hunter
89865a0a06 Merge pull request #9 from UGA-Innovation-Factory/copilot/sub-pr-7-again
Fix user attribute merging to preserve all fields from users.nix
2025-12-17 16:39:09 -05:00
Hunter Halloran
59937416c1 nix fmt 2025-12-17 16:32:12 -05:00
Hunter Halloran
a4600fa66a Merge branch 'copilot/sub-pr-7-again' of github.com:UGA-Innovation-Factory/nixos-systems into copilot/sub-pr-7-again 2025-12-17 16:28:22 -05:00
copilot-swe-agent[bot]
f51ef4ce01 Fix user merging logic to preserve all fields from users.nix
Co-authored-by: Jyumpp <11142390+Jyumpp@users.noreply.github.com>
2025-12-17 16:27:18 -05:00
copilot-swe-agent[bot]
fdda1795db Initial plan 2025-12-17 16:27:18 -05:00
Hunter Halloran
99ed790ea5 fix merge conflict 2025-12-17 16:24:31 -05:00
copilot-swe-agent[bot]
5084ece692 Fix user merging logic to preserve all fields from users.nix
Co-authored-by: Jyumpp <11142390+Jyumpp@users.noreply.github.com>
2025-12-17 21:23:19 +00:00
copilot-swe-agent[bot]
316c642dc7 Initial plan 2025-12-17 21:20:41 +00:00
45 changed files with 1386 additions and 673 deletions

81
.gitea/workflows/ci.yml Normal file
View File

@@ -0,0 +1,81 @@
name: CI
on:
push:
branches:
- main
pull_request_review:
workflow_dispatch:
permissions:
contents: read
jobs:
flake-check:
name: Flake Check
runs-on: [self-hosted, nix-builder]
needs: [format-check]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Check flake
run: nix flake check --show-trace --print-build-logs
format-check:
name: Format Check
runs-on: [self-hosted, nix-builder]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Check formatting
run: |
nix fmt **/*.nix
if ! git diff --quiet; then
echo "::error::Code is not formatted. Please run 'nix fmt **/*.nix' locally."
git diff
exit 1
fi
eval-configs:
name: Evaluate Key Configurations
runs-on: [self-hosted, nix-builder]
needs: [flake-check, format-check]
strategy:
matrix:
config:
- nix-builder
- nix-laptop1
- nix-desktop1
fail-fast: false
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Evaluate configuration
run: |
echo "Evaluating configuration for ${{ matrix.config }}"
nix eval .#nixosConfigurations.${{ matrix.config }}.config.system.build.toplevel.drvPath \
--show-trace
eval-artifacts:
name: Evaluate Artifacts
runs-on: [self-hosted, nix-builder]
needs: [flake-check, format-check]
strategy:
matrix:
artifact:
- lxc-nix-builder
- installer-iso-nix-laptop1
fail-fast: false
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Evaluate artifact
run: |
echo "Evaluating artifact ${{ matrix.artifact }}"
nix eval .#${{ matrix.artifact }}.drvPath \
--show-trace

View File

@@ -1,12 +1,14 @@
# GitHub Copilot Instructions for nixos-systems # GitHub Copilot Instructions for Athenix
This repository manages NixOS configurations for the UGA Innovation Factory's fleet of devices using Nix flakes and a custom configuration system. This repository manages NixOS configurations for the UGA Innovation Factory's fleet of devices using Nix flakes and a custom configuration system.
**Repository:** https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git
## Repository Overview ## Repository Overview
This is a **NixOS system configuration repository** that uses: This is a **NixOS system configuration repository** that uses:
- **Nix flakes** for dependency management and reproducible builds - **Nix flakes** for dependency management and reproducible builds
- **Custom namespace** (`ugaif.*`) for all Innovation Factory-specific options - **Custom namespace** (`athenix.*`) for all Innovation Factory-specific options
- **Inventory-based** host generation from `inventory.nix` - **Inventory-based** host generation from `inventory.nix`
- **External module support** for user and system configurations - **External module support** for user and system configurations
- **Multiple hardware types**: desktops, laptops, Surface tablets, LXC containers, WSL - **Multiple hardware types**: desktops, laptops, Surface tablets, LXC containers, WSL
@@ -30,18 +32,18 @@ This is a **NixOS system configuration repository** that uses:
- **`templates/`**: Templates for external configurations - **`templates/`**: Templates for external configurations
### Naming Conventions ### Naming Conventions
- Module options: Use `ugaif.*` namespace for all custom options - Module options: Use `athenix.*` namespace for all custom options
- Hostnames: `{type}{number}` or `{type}-{name}` (e.g., `nix-laptop1`, `nix-surface-alpha`) - Hostnames: `{type}{number}` or `{type}-{name}` (e.g., `nix-laptop1`, `nix-surface-alpha`)
- Hardware types: Prefix with `nix-` (e.g., `nix-desktop`, `nix-laptop`) - Hardware types: Prefix with `nix-` (e.g., `nix-desktop`, `nix-laptop`)
- Software types: Use descriptive names (`desktop`, `tablet-kiosk`, `headless`) - Software types: Use descriptive names (`desktop`, `tablet-kiosk`, `headless`)
## Custom Namespace (`ugaif`) ## Custom Namespace (`athenix`)
All Innovation Factory-specific options MUST use the `ugaif` namespace: All Innovation Factory-specific options MUST use the `athenix` namespace:
### Host Options (`ugaif.host.*`) ### Host Options (`athenix.host.*`)
```nix ```nix
ugaif.host = { athenix.host = {
filesystem.device = "/dev/sda"; # Boot disk filesystem.device = "/dev/sda"; # Boot disk
filesystem.swapSize = "32G"; # Swap size filesystem.swapSize = "32G"; # Swap size
buildMethods = [ "iso" ]; # Artifact types buildMethods = [ "iso" ]; # Artifact types
@@ -50,9 +52,9 @@ ugaif.host = {
}; };
``` ```
### Software Options (`ugaif.sw.*`) ### Software Options (`athenix.sw.*`)
```nix ```nix
ugaif.sw = { athenix.sw = {
type = "desktop"; # System type type = "desktop"; # System type
kioskUrl = "https://..."; # Kiosk browser URL kioskUrl = "https://..."; # Kiosk browser URL
python.enable = true; # Python tools (pixi, uv) python.enable = true; # Python tools (pixi, uv)
@@ -64,13 +66,13 @@ ugaif.sw = {
}; };
``` ```
### User Options (`ugaif.users.*`) ### User Options (`athenix.users.*`)
```nix ```nix
ugaif.users = { athenix.users = {
accounts = { ... }; # User definitions accounts = { ... }; # User definitions
enabledUsers = [ "root" "engr-ugaif" ]; # Enabled users enabledUsers = [ "root" "engr-ugaif" ]; # Enabled users
}; };
ugaif.forUser = "username"; # Convenience: enable user + set WSL user athenix.forUser = "username"; # Convenience: enable user + set WSL user
``` ```
## Development Workflow ## Development Workflow
@@ -90,8 +92,8 @@ ugaif.forUser = "username"; # Convenience: enable user + set WSL user
### Common Tasks ### Common Tasks
#### Adding a New User #### Adding a New User
1. Edit `users.nix` to add user definition under `ugaif.users.accounts` 1. Edit `users.nix` to add user definition under `athenix.users.accounts`
2. Enable user in `inventory.nix` via `ugaif.users.username.enable = true` or use `ugaif.forUser = "username"` 2. Enable user in `inventory.nix` via `athenix.users.username.enable = true` or use `athenix.forUser = "username"`
3. Test: `nix flake check` 3. Test: `nix flake check`
#### Adding a New Host #### Adding a New Host
@@ -102,19 +104,19 @@ ugaif.forUser = "username"; # Convenience: enable user + set WSL user
#### Modifying Software Configuration #### Modifying Software Configuration
1. Edit appropriate file in `sw/` directory based on system type 1. Edit appropriate file in `sw/` directory based on system type
2. For system-wide changes: modify `sw/{type}/programs.nix` 2. For system-wide changes: modify `sw/{type}/programs.nix`
3. For specific hosts: use `ugaif.sw.extraPackages` in `inventory.nix` 3. For specific hosts: use `athenix.sw.extraPackages` in `inventory.nix`
4. Test: `nix flake check` 4. Test: `nix flake check`
#### Creating External Modules #### Creating External Modules
1. Use templates: `nix flake init -t github:UGA-Innovation-Factory/nixos-systems#{user|system}` 1. Use templates: `nix flake init -t git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#{user|system}`
2. User modules: Provide `home.nix` (required) and `nixos.nix` (optional) 2. User modules: Provide `user.nix` (required) and `nixos.nix` (optional)
3. System modules: Provide `default.nix` that accepts `{ inputs, ... }` 3. System modules: Provide `default.nix` that accepts `{ inputs, ... }`
4. Reference in `inventory.nix` or `users.nix` using `builtins.fetchGit` 4. Reference in `inventory.nix` or `users.nix` using `builtins.fetchGit`
## Important Constraints ## Important Constraints
### What NOT to Do ### What NOT to Do
- **Never** use options outside the `ugaif` namespace for Innovation Factory-specific functionality - **Never** use options outside the `athenix` namespace for Innovation Factory-specific functionality
- **Never** remove or modify working host configurations unless explicitly requested - **Never** remove or modify working host configurations unless explicitly requested
- **Never** break existing functionality when adding new features - **Never** break existing functionality when adding new features
- **Never** hardcode values that should be configurable - **Never** hardcode values that should be configurable
@@ -122,7 +124,7 @@ ugaif.forUser = "username"; # Convenience: enable user + set WSL user
### What to ALWAYS Do ### What to ALWAYS Do
- **Always** run `nix flake check` before finalizing changes - **Always** run `nix flake check` before finalizing changes
- **Always** use the `ugaif.*` namespace for custom options - **Always** use the `athenix.*` namespace for custom options
- **Always** preserve existing comment styles and documentation - **Always** preserve existing comment styles and documentation
- **Always** test that configurations build successfully - **Always** test that configurations build successfully
- **Always** consider impact on existing hosts when making changes - **Always** consider impact on existing hosts when making changes
@@ -135,13 +137,12 @@ This repository supports external configurations via Git repositories:
### User Configurations (Dotfiles) ### User Configurations (Dotfiles)
```nix ```nix
# In users.nix # In users.nix
myuser = { myuser.external = builtins.fetchGit {
description = "My Name";
home = builtins.fetchGit {
url = "https://github.com/username/dotfiles"; url = "https://github.com/username/dotfiles";
rev = "abc123..."; # Pin to specific commit rev = "abc123..."; # Pin to specific commit
}; };
}; # The external user.nix file contains BOTH user account options
# (athenix.users.myuser) AND home-manager configuration
``` ```
### System Configurations ### System Configurations
@@ -157,7 +158,7 @@ nix-lxc = {
**Key Points:** **Key Points:**
- External modules receive `{ inputs }` parameter with flake inputs - External modules receive `{ inputs }` parameter with flake inputs
- User modules must provide `home.nix` (home-manager config) - User modules must provide `user.nix` (user options AND home-manager config)
- System modules must provide `default.nix` (NixOS module) - System modules must provide `default.nix` (NixOS module)
- Always pin to specific commit hash (`rev`) for reproducibility - Always pin to specific commit hash (`rev`) for reproducibility
@@ -185,7 +186,7 @@ nix flake show
``` ```
### Artifact Types ### Artifact Types
Set via `ugaif.host.buildMethods`: Set via `athenix.host.buildMethods`:
- `"iso"` - Installer ISO with auto-install - `"iso"` - Installer ISO with auto-install
- `"live-iso"` - Live boot ISO without installer - `"live-iso"` - Live boot ISO without installer
- `"lxc"` - LXC container tarball - `"lxc"` - LXC container tarball
@@ -232,7 +233,7 @@ Set via `ugaif.host.buildMethods`:
## Code Review Checklist ## Code Review Checklist
When reviewing or generating code: When reviewing or generating code:
- [ ] Uses `ugaif.*` namespace for custom options - [ ] Uses `athenix.*` namespace for custom options
- [ ] Runs `nix flake check` successfully - [ ] Runs `nix flake check` successfully
- [ ] Follows existing code style and formatting - [ ] Follows existing code style and formatting
- [ ] Preserves existing functionality - [ ] Preserves existing functionality

View File

@@ -1,6 +1,6 @@
# UGA Innovation Factory - NixOS Systems # UGA Innovation Factory - Athenix
[![CI](https://github.com/UGA-Innovation-Factory/nixos-systems/actions/workflows/ci.yml/badge.svg)](https://github.com/UGA-Innovation-Factory/nixos-systems/actions/workflows/ci.yml) [![CI](https://git.factory.uga.edu/UGA-Innovation-Factory/athenix/actions/workflows/ci.yml/badge.svg)](https://git.factory.uga.edu/UGA-Innovation-Factory/athenix/actions)
This repository contains the NixOS configuration for the Innovation Factory's fleet of laptops, desktops, Surface tablets, and containers. It provides a declarative, reproducible system configuration using Nix flakes. This repository contains the NixOS configuration for the Innovation Factory's fleet of laptops, desktops, Surface tablets, and containers. It provides a declarative, reproducible system configuration using Nix flakes.
@@ -8,7 +8,7 @@ This repository contains the NixOS configuration for the Innovation Factory's fl
- **[Quick Start](#quick-start)** - Get started in 5 minutes - **[Quick Start](#quick-start)** - Get started in 5 minutes
- **[docs/INVENTORY.md](docs/INVENTORY.md)** - Configure hosts and fleet inventory - **[docs/INVENTORY.md](docs/INVENTORY.md)** - Configure hosts and fleet inventory
- **[docs/NAMESPACE.md](docs/NAMESPACE.md)** - Configuration options reference (`ugaif.*`) - **[docs/NAMESPACE.md](docs/NAMESPACE.md)** - Configuration options reference (`athenix.*`)
- **[docs/USER_CONFIGURATION.md](docs/USER_CONFIGURATION.md)** - User account management - **[docs/USER_CONFIGURATION.md](docs/USER_CONFIGURATION.md)** - User account management
- **[docs/EXTERNAL_MODULES.md](docs/EXTERNAL_MODULES.md)** - External configuration modules - **[docs/EXTERNAL_MODULES.md](docs/EXTERNAL_MODULES.md)** - External configuration modules
- **[docs/BUILDING.md](docs/BUILDING.md)** - Build ISOs and container images - **[docs/BUILDING.md](docs/BUILDING.md)** - Build ISOs and container images
@@ -28,7 +28,7 @@ This command automatically fetches the latest configuration, rebuilds your syste
**Note:** If you use external user configurations (personal dotfiles), run: **Note:** If you use external user configurations (personal dotfiles), run:
```bash ```bash
sudo nixos-rebuild switch --flake github:UGA-Innovation-Factory/nixos-systems --impure sudo nixos-rebuild switch --flake git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git --impure
``` ```
### For Administrators ### For Administrators
@@ -83,22 +83,22 @@ nixos-systems/
## Configuration Overview ## Configuration Overview
All Innovation Factory options use the `ugaif.*` namespace. See **[docs/NAMESPACE.md](docs/NAMESPACE.md)** for complete reference. All Innovation Factory options use the `athenix.*` namespace. See **[docs/NAMESPACE.md](docs/NAMESPACE.md)** for complete reference.
**Quick examples:** **Quick examples:**
```nix ```nix
# Host configuration # Host configuration
ugaif.host.filesystem.device = "/dev/nvme0n1"; athenix.host.filesystem.device = "/dev/nvme0n1";
ugaif.host.filesystem.swapSize = "64G"; athenix.host.filesystem.swapSize = "64G";
# Software configuration # Software configuration
ugaif.sw.type = "desktop"; # or "headless", "tablet-kiosk" athenix.sw.type = "desktop"; # or "headless", "tablet-kiosk"
ugaif.sw.extraPackages = with pkgs; [ vim docker ]; athenix.sw.extraPackages = with pkgs; [ vim docker ];
# User management # User management
ugaif.users.myuser.enable = true; athenix.users.myuser.enable = true;
ugaif.forUser = "myuser"; # Convenience shortcut athenix.forUser = "myuser"; # Convenience shortcut
``` ```
## Prerequisites ## Prerequisites
@@ -134,7 +134,7 @@ myuser = {
```nix ```nix
nix-laptop = { nix-laptop = {
devices = 2; devices = 2;
overrides.ugaif.users.myuser.enable = true; overrides.athenix.users.myuser.enable = true;
}; };
``` ```
@@ -153,8 +153,8 @@ nix-laptop = {
# With configuration # With configuration
nix-surface = { nix-surface = {
devices = { devices = {
"1".ugaif.sw.kioskUrl = "https://dashboard1.example.com"; "1".athenix.sw.kioskUrl = "https://dashboard1.example.com";
"2".ugaif.sw.kioskUrl = "https://dashboard2.example.com"; "2".athenix.sw.kioskUrl = "https://dashboard2.example.com";
}; };
}; };
@@ -162,8 +162,8 @@ nix-surface = {
nix-desktop = { nix-desktop = {
devices = 3; devices = 3;
overrides = { overrides = {
ugaif.users.student.enable = true; athenix.users.student.enable = true;
ugaif.sw.extraPackages = with pkgs; [ vim ]; athenix.sw.extraPackages = with pkgs; [ vim ];
}; };
}; };
``` ```
@@ -175,19 +175,18 @@ nix-desktop = {
Users and systems can reference external Git repositories for configuration: Users and systems can reference external Git repositories for configuration:
```nix ```nix
# In users.nix - External dotfiles # In users.nix - External dotfiles with user configuration
myuser = { myuser.external = builtins.fetchGit {
description = "My Name"; url = "https://git.factory.uga.edu/username/dotfiles";
home = builtins.fetchGit {
url = "https://github.com/username/dotfiles";
rev = "abc123..."; rev = "abc123...";
}; };
}; # The external user.nix file contains both athenix.users.myuser options
# AND home-manager configuration
# In inventory.nix - External system config # In inventory.nix - External system config
nix-lxc = { nix-lxc = {
devices."server" = builtins.fetchGit { devices."server" = builtins.fetchGit {
url = "https://github.com/org/server-config"; url = "https://git.factory.uga.edu/org/server-config";
rev = "abc123..."; rev = "abc123...";
}; };
}; };
@@ -196,10 +195,10 @@ nix-lxc = {
**Create templates:** **Create templates:**
```bash ```bash
# User configuration (dotfiles) # User configuration (dotfiles)
nix flake init -t github:UGA-Innovation-Factory/nixos-systems#user nix flake init -t git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#user
# System configuration # System configuration
nix flake init -t github:UGA-Innovation-Factory/nixos-systems#system nix flake init -t git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#system
``` ```
**See [docs/EXTERNAL_MODULES.md](docs/EXTERNAL_MODULES.md) for complete guide.** **See [docs/EXTERNAL_MODULES.md](docs/EXTERNAL_MODULES.md) for complete guide.**
@@ -208,13 +207,13 @@ nix flake init -t github:UGA-Innovation-Factory/nixos-systems#system
```bash ```bash
# Build installer ISO # Build installer ISO
nix build github:UGA-Innovation-Factory/nixos-systems#installer-iso-nix-laptop1 nix build git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#installer-iso-nix-laptop1
# Build LXC container # Build LXC container
nix build .#lxc-nix-builder nix build .#lxc-nix-builder
# List all available artifacts # List all available artifacts
nix flake show github:UGA-Innovation-Factory/nixos-systems nix flake show git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git
``` ```
**See [docs/BUILDING.md](docs/BUILDING.md) for complete guide on building ISOs, containers, and using remote builders.** **See [docs/BUILDING.md](docs/BUILDING.md) for complete guide on building ISOs, containers, and using remote builders.**
@@ -226,7 +225,7 @@ nix flake show github:UGA-Innovation-Factory/nixos-systems
- **`stateless-kiosk`** - Diskless PXE boot kiosks - **`stateless-kiosk`** - Diskless PXE boot kiosks
- **`headless`** - Servers and containers (no GUI) - **`headless`** - Servers and containers (no GUI)
Set via `ugaif.sw.type` option. See [docs/NAMESPACE.md](docs/NAMESPACE.md) for all options. Set via `athenix.sw.type` option. See [docs/NAMESPACE.md](docs/NAMESPACE.md) for all options.
## Development ## Development

View File

@@ -16,7 +16,7 @@ This guide covers building installer ISOs, live images, and container artifacts
```bash ```bash
# Build an installer ISO for a specific host # Build an installer ISO for a specific host
nix build github:UGA-Innovation-Factory/nixos-systems#installer-iso-nix-laptop1 nix build git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#installer-iso-nix-laptop1
# Result will be in result/iso/ # Result will be in result/iso/
ls -lh result/iso/ ls -lh result/iso/
@@ -27,7 +27,7 @@ ls -lh result/iso/
List all available build outputs: List all available build outputs:
```bash ```bash
nix flake show github:UGA-Innovation-Factory/nixos-systems nix flake show git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git
``` ```
Common artifact types: Common artifact types:
@@ -57,10 +57,10 @@ ls -lh result/iso/nixos-*.iso
sudo dd if=result/iso/nixos-*.iso of=/dev/sdX bs=4M status=progress sudo dd if=result/iso/nixos-*.iso of=/dev/sdX bs=4M status=progress
``` ```
### Building from GitHub ### Building from Gitea
```bash ```bash
nix build github:UGA-Innovation-Factory/nixos-systems#installer-iso-nix-laptop1 nix build git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#installer-iso-nix-laptop1
``` ```
### Using the Installer ### Using the Installer
@@ -70,7 +70,7 @@ nix build github:UGA-Innovation-Factory/nixos-systems#installer-iso-nix-laptop1
3. After installation completes, remove the USB drive and reboot 3. After installation completes, remove the USB drive and reboot
4. Log in with the configured user credentials 4. Log in with the configured user credentials
**Note:** The installer will **erase all data** on the target disk specified in `ugaif.host.filesystem.device`. **Note:** The installer will **erase all data** on the target disk specified in `athenix.host.filesystem.device`.
## Live ISOs ## Live ISOs
@@ -224,7 +224,7 @@ ssh engr-ugaif@nix-builder df -h
In `inventory.nix`: In `inventory.nix`:
```nix ```nix
ugaif.sw.remoteBuild.enable = false; athenix.sw.remoteBuild.enable = false;
``` ```
### Out of Disk Space ### Out of Disk Space

View File

@@ -66,7 +66,7 @@ sudo nixos-rebuild build --flake .
## Continuous Integration ## Continuous Integration
The repository uses GitHub Actions for automated testing and validation. CI jobs run on the self-hosted `nix-builder` machine via SSH. The repository uses Gitea Actions for automated testing and validation. CI jobs run on the self-hosted `nix-builder` machine.
### CI Workflow ### CI Workflow
@@ -94,7 +94,7 @@ Check the CI status badge at the top of the README or view detailed logs:
```bash ```bash
# View workflow status # View workflow status
https://github.com/UGA-Innovation-Factory/nixos-systems/actions https://git.factory.uga.edu/UGA-Innovation-Factory/athenix/actions
``` ```
### Running CI Checks Locally ### Running CI Checks Locally
@@ -118,49 +118,49 @@ nix build .#lxc-nix-builder
### Self-Hosted Runner ### Self-Hosted Runner
CI jobs run on the `nix-builder` host as a self-hosted GitHub Actions runner. This provides: CI jobs run on the `nix-builder` host as a self-hosted Gitea Actions runner. This provides:
- Native Nix environment without installation overhead - Native Nix environment without installation overhead
- Access to local Nix store for faster builds - Access to local Nix store for faster builds
- Consistent build environment matching deployment targets - Consistent build environment matching deployment targets
- Direct access to build caching infrastructure - Direct access to build caching infrastructure
#### Setting Up the GitHub Actions Runner #### Setting Up the Gitea Actions Runner
The nix-builder host is configured with a GitHub Actions self-hosted runner in `inventory.nix`. To complete the setup: The nix-builder host is configured with a Gitea Actions self-hosted runner in `inventory.nix`. To complete the setup:
1. **Generate a GitHub Personal Access Token (PAT)**: 1. **Generate a Gitea Runner Token**:
- Go to https://github.com/settings/tokens - Go to https://git.factory.uga.edu/UGA-Innovation-Factory/athenix/settings/actions/runners
- Create a new token with `repo` scope - Click "Create new Runner"
- Copy the token value - Copy the registration token
2. **Create the token file on nix-builder**: 2. **Create the token file on nix-builder**:
```bash ```bash
ssh engr-ugaif@nix-builder ssh engr-ugaif@nix-builder
echo "YOUR_TOKEN_HERE" | sudo tee /var/lib/github-runner-token > /dev/null echo "YOUR_TOKEN_HERE" | sudo tee /var/lib/gitea-runner-token > /dev/null
sudo chmod 600 /var/lib/github-runner-token sudo chmod 600 /var/lib/gitea-runner-token
``` ```
3. **Rebuild the system** to start the runner: 3. **Rebuild the system** to start the runner:
```bash ```bash
sudo nixos-rebuild switch --flake github:UGA-Innovation-Factory/nixos-systems#nix-builder sudo nixos-rebuild switch --flake git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#nix-builder
``` ```
4. **Verify the runner is registered**: 4. **Verify the runner is registered**:
- Check https://github.com/UGA-Innovation-Factory/nixos-systems/settings/actions/runners - Check https://git.factory.uga.edu/UGA-Innovation-Factory/athenix/settings/actions/runners
- The runner should appear with the `nix-builder` label - The runner should appear with the `nix-builder` label
The runner service is configured in the nix-builder device configuration and will automatically: The runner service is configured in the nix-builder device configuration and will automatically:
- Register with the repository on first start - Register with the repository on first start
- Use the `nix-builder` label for workflow targeting - Use the `nix-builder` label for workflow targeting
- Run as the `engr-ugaif` user - Run as the `engr-ugaif` user
- Store work in `/var/lib/github-runner` - Store work in `/var/lib/gitea-runner`
### Troubleshooting CI Failures ### Troubleshooting CI Failures
If CI fails: If CI fails:
1. **Check the error logs** in the GitHub Actions tab 1. **Check the error logs** in the Gitea Actions tab
2. **Run the same command locally** to reproduce the issue 2. **Run the same command locally** to reproduce the issue
3. **Use `--show-trace`** for detailed error information 3. **Use `--show-trace`** for detailed error information
4. **Verify formatting** with `nix fmt` if format check fails 4. **Verify formatting** with `nix fmt` if format check fails
@@ -195,13 +195,13 @@ sudo nixos-rebuild build --flake .
```bash ```bash
# Rebuild from GitHub main branch # Rebuild from GitHub main branch
sudo nixos-rebuild switch --flake github:UGA-Innovation-Factory/nixos-systems sudo nixos-rebuild switch --flake git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git
# Use --impure for external user configurations with fetchGit # Use --impure for external user configurations with fetchGit
sudo nixos-rebuild switch --flake github:UGA-Innovation-Factory/nixos-systems --impure sudo nixos-rebuild switch --flake git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git --impure
# Rebuild specific host from GitHub # Rebuild specific host from GitHub
sudo nixos-rebuild switch --flake github:UGA-Innovation-Factory/nixos-systems#nix-laptop1 sudo nixos-rebuild switch --flake git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#nix-laptop1
``` ```
### Boot into Previous Generation ### Boot into Previous Generation
@@ -288,13 +288,13 @@ vim sw/headless/programs.nix
### Packages for Specific Hosts ### Packages for Specific Hosts
Add to `ugaif.sw.extraPackages` in `inventory.nix`: Add to `athenix.sw.extraPackages` in `inventory.nix`:
```nix ```nix
nix-laptop = { nix-laptop = {
devices = 2; devices = 2;
overrides = { overrides = {
ugaif.sw.extraPackages = with pkgs; [ athenix.sw.extraPackages = with pkgs; [
vim vim
docker docker
kubernetes-helm kubernetes-helm
@@ -305,16 +305,15 @@ nix-laptop = {
### User-Specific Packages ### User-Specific Packages
Add to user's home-manager configuration in `users.nix` or external dotfiles: Add to user's home-manager configuration in their external `user.nix`:
```nix ```nix
myuser = { # In external user.nix
homePackages = with pkgs; [ home.packages = with pkgs; [
ripgrep ripgrep
fd fd
bat bat
]; ];
};
``` ```
### Search for Packages ### Search for Packages
@@ -379,7 +378,7 @@ uv pip install -r requirements.txt
Python development tools are configured in `sw/python.nix` and can be controlled via: Python development tools are configured in `sw/python.nix` and can be controlled via:
```nix ```nix
ugaif.sw.python.enable = true; # Default: enabled athenix.sw.python.enable = true; # Default: enabled
``` ```
## Contributing ## Contributing
@@ -389,7 +388,7 @@ ugaif.sw.python.enable = true; # Default: enabled
- Run formatter before committing: `nix fmt` - Run formatter before committing: `nix fmt`
- Follow existing code structure and conventions - Follow existing code structure and conventions
- Add comments for complex logic - Add comments for complex logic
- Use the `ugaif.*` namespace for all custom options - Use the `athenix.*` namespace for all custom options
### Testing Workflow ### Testing Workflow

View File

@@ -32,13 +32,13 @@ nix-lxc = {
devices = { devices = {
# Traditional inline configuration # Traditional inline configuration
"local-server" = { "local-server" = {
ugaif.users.admin.enable = true; athenix.users.admin.enable = true;
services.nginx.enable = true; services.nginx.enable = true;
}; };
# External module from Git # External module from Git
"remote-server" = builtins.fetchGit { "remote-server" = builtins.fetchGit {
url = "https://github.com/org/server-config"; url = "https://git.factory.uga.edu/org/server-config";
rev = "abc123..."; # Pin to specific commit rev = "abc123..."; # Pin to specific commit
}; };
}; };
@@ -66,9 +66,9 @@ server-config/
}; };
}; };
# Use ugaif namespace options # Use athenix namespace options
ugaif.users.admin.enable = true; athenix.users.admin.enable = true;
ugaif.sw.type = "headless"; athenix.sw.type = "headless";
} }
``` ```
@@ -96,7 +96,7 @@ Later modules can override earlier ones using standard NixOS module precedence.
Create a new system module: Create a new system module:
```bash ```bash
nix flake init -t github:UGA-Innovation-Factory/nixos-systems#system nix flake init -t git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#system
``` ```
See [templates/system/](../templates/system/) for the complete template. See [templates/system/](../templates/system/) for the complete template.
@@ -108,17 +108,19 @@ External user modules provide home-manager configurations (dotfiles, packages, p
### Usage in users.nix ### Usage in users.nix
```nix ```nix
ugaif.users = { athenix.users = {
myuser = { # External user module (dotfiles, home-manager, and user options)
description = "My Name"; myuser = builtins.fetchGit {
extraGroups = [ "wheel" "networkmanager" ]; url = "https://git.factory.uga.edu/username/dotfiles";
hashedPassword = "$6$...";
# External home-manager configuration
home = builtins.fetchGit {
url = "https://github.com/username/dotfiles";
rev = "abc123..."; rev = "abc123...";
}; };
# Inline user definition
inlineuser = {
description = "Inline User";
extraGroups = [ "wheel" ];
shell = pkgs.zsh;
hashedPassword = "$6$...";
}; };
}; };
``` ```
@@ -127,20 +129,35 @@ ugaif.users = {
``` ```
dotfiles/ dotfiles/
├── home.nix # Required: Home-manager config ├── user.nix # Required: User options AND home-manager config
├── nixos.nix # Optional: System-level config ├── nixos.nix # Optional: System-level config
└── dotfiles/ # Optional: Actual dotfiles └── config/ # Optional: Actual dotfiles
├── bashrc ├── bashrc
└── vimrc └── vimrc
``` ```
**home.nix (required):** **user.nix (required):**
```nix ```nix
{ inputs, ... }: { inputs, ... }:
{ config, lib, pkgs, osConfig, ... }: { config, lib, pkgs, osConfig ? null, ... }:
{ {
# Home-manager configuration # ========== User Account Configuration ==========
home.packages = with pkgs; [ vim git htop ]; athenix.users.myusername = {
description = "Your Full Name";
shell = pkgs.zsh;
hashedPassword = "!";
opensshKeys = [ "ssh-ed25519 AAAA..." ];
useZshTheme = true;
useNvimPlugins = true;
};
# ========== Home Manager Configuration ==========
# Packages
home.packages = with pkgs; [
vim
git
htop
] ++ lib.optional (osConfig.athenix.sw.type or null == "desktop") firefox;
programs.git = { programs.git = {
enable = true; enable = true;
@@ -166,7 +183,7 @@ dotfiles/
### What User Modules Receive ### What User Modules Receive
**In home.nix:** **In user.nix:**
- **`inputs`** - Flake inputs (nixpkgs, home-manager, etc.) - **`inputs`** - Flake inputs (nixpkgs, home-manager, etc.)
- **`config`** - Home-manager configuration - **`config`** - Home-manager configuration
- **`lib`** - Nixpkgs library functions - **`lib`** - Nixpkgs library functions
@@ -187,8 +204,7 @@ username = {
description = "Full Name"; description = "Full Name";
# External configuration # External configuration
home = builtins.fetchGit { ... }; external = builtins.fetchGit { ... };
# System settings # System settings
extraGroups = [ "wheel" "networkmanager" ]; extraGroups = [ "wheel" "networkmanager" ];
hashedPassword = "$6$..."; hashedPassword = "$6$...";
@@ -200,7 +216,7 @@ username = {
useNvimPlugins = true; # Apply system nvim config (default: true) useNvimPlugins = true; # Apply system nvim config (default: true)
# Enable on specific systems (see docs/INVENTORY.md) # Enable on specific systems (see docs/INVENTORY.md)
enable = false; # Set in inventory.nix via ugaif.users.username.enable enable = false; # Set in inventory.nix via athenix.users.username.enable
}; };
``` ```
@@ -209,7 +225,7 @@ username = {
Create a new user module: Create a new user module:
```bash ```bash
nix flake init -t github:UGA-Innovation-Factory/nixos-systems#user nix flake init -t git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#user
``` ```
See [templates/user/](../templates/user/) for the complete template. See [templates/user/](../templates/user/) for the complete template.
@@ -287,7 +303,7 @@ Use local directories during development:
# Initialize in new directory # Initialize in new directory
mkdir my-server-config mkdir my-server-config
cd my-server-config cd my-server-config
nix flake init -t github:UGA-Innovation-Factory/nixos-systems#system nix flake init -t git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#system
``` ```
See [templates/system/README.md](../templates/system/README.md) for detailed usage. See [templates/system/README.md](../templates/system/README.md) for detailed usage.
@@ -298,7 +314,7 @@ See [templates/system/README.md](../templates/system/README.md) for detailed usa
# Initialize in new directory # Initialize in new directory
mkdir my-dotfiles mkdir my-dotfiles
cd my-dotfiles cd my-dotfiles
nix flake init -t github:UGA-Innovation-Factory/nixos-systems#user nix flake init -t git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#user
``` ```
See [templates/user/README.md](../templates/user/README.md) for detailed usage. See [templates/user/README.md](../templates/user/README.md) for detailed usage.
@@ -321,20 +337,28 @@ External system modules are imported and merged into the NixOS configuration:
import externalModulePath { inherit inputs; } import externalModulePath { inherit inputs; }
``` ```
They can use all standard NixOS options plus `ugaif.*` namespace options. They can use all standard NixOS options plus `athenix.*` namespace options.
### User Module Integration ### User Module Integration
External user modules are loaded separately for home-manager (`home.nix`) and NixOS (`nixos.nix` if it exists): External user modules are loaded in two contexts:
**Home-manager:** **User options (NixOS module context):**
```nix ```nix
import (externalHomePath + "/home.nix") { inherit inputs; } import (externalPath + "/user.nix") { inherit inputs; }
# Evaluated as NixOS module to extract athenix.users.<username> options
``` ```
**NixOS (optional):** **Home-manager configuration:**
```nix ```nix
import (externalHomePath + "/nixos.nix") { inherit inputs; } import (externalPath + "/user.nix") { inherit inputs; }
# Imported into home-manager for home.*, programs.*, services.* options
```
**System-level config (optional):**
```nix
import (externalPath + "/nixos.nix") { inherit inputs; }
# If present, imported as NixOS module for system-level configuration
``` ```
### Combining External and Local Config ### Combining External and Local Config
@@ -345,39 +369,33 @@ You can mix external modules with local overrides:
nix-lxc = { nix-lxc = {
devices = { devices = {
"server" = builtins.fetchGit { "server" = builtins.fetchGit {
url = "https://github.com/org/base-config"; url = "https://git.factory.uga.edu/org/base-config";
rev = "abc123..."; rev = "abc123...";
}; };
}; };
overrides = { overrides = {
# Apply to all devices, including external ones # Apply to all devices, including external ones
ugaif.users.admin.enable = true; athenix.users.admin.enable = true;
networking.firewall.allowedTCPPorts = [ 80 443 ]; networking.firewall.allowedTCPPorts = [ 80 443 ];
}; };
}; };
``` ```
## Examples
### Minimal System Module
**default.nix:**
```nix
{ inputs, ... }:
{ config, lib, pkgs, ... }:
{
ugaif.sw.type = "headless";
services.nginx.enable = true;
}
```
### Minimal User Module ### Minimal User Module
**home.nix:** **user.nix:**
```nix ```nix
{ inputs, ... }: { inputs, ... }:
{ config, lib, pkgs, ... }: { config, lib, pkgs, osConfig ? null, ... }:
{ {
# User account options
athenix.users.myusername = {
description = "My Name";
shell = pkgs.zsh;
hashedPassword = "!";
};
# Home-manager config
home.packages = with pkgs; [ vim git ]; home.packages = with pkgs; [ vim git ];
} }
``` ```
@@ -386,7 +404,7 @@ nix-lxc = {
``` ```
dotfiles/ dotfiles/
├── home.nix ├── user.nix
├── nixos.nix ├── nixos.nix
└── config/ └── config/
├── bashrc ├── bashrc
@@ -394,12 +412,35 @@ dotfiles/
└── gitconfig └── gitconfig
``` ```
**home.nix:** **user.nix:**
```nix ```nix
{ inputs, ... }: { inputs, ... }:
{ config, lib, pkgs, ... }: { config, lib, pkgs, osConfig ? null, ... }:
{ {
home.packages = with pkgs; [ ripgrep fd bat ]; # User account configuration
athenix.users.myusername = {
description = "My Full Name";
shell = pkgs.zsh;
extraGroups = [ "wheel" "networkmanager" ];
hashedPassword = "!";
opensshKeys = [ "ssh-ed25519 AAAA..." ];
useZshTheme = true;
useNvimPlugins = true;
};
# Home-manager configuration
home.packages = with pkgs; [
ripgrep
fd
bat
] ++ lib.optional (osConfig.athenix.sw.type or null == "desktop") firefox;
programs.git = {
enable = true;
userName = "My Full Name";
userEmail = "me@example.com";
extraConfig.init.defaultBranch = "main";
};
home.file = { home.file = {
".bashrc".source = ./config/bashrc; ".bashrc".source = ./config/bashrc;
@@ -411,8 +452,9 @@ dotfiles/
## See Also ## See Also
- [docs/INVENTORY.md](INVENTORY.md) - Host configuration guide - [INVENTORY.md](INVENTORY.md) - Host configuration guide
- [docs/NAMESPACE.md](NAMESPACE.md) - Configuration options reference - [USER_CONFIGURATION.md](USER_CONFIGURATION.md) - User management guide
- [NAMESPACE.md](NAMESPACE.md) - Configuration options reference
- [templates/system/](../templates/system/) - System module template - [templates/system/](../templates/system/) - System module template
- [templates/user/](../templates/user/) - User module template - [templates/user/](../templates/user/) - User module template
- [README.md](../README.md) - Main documentation - [README.md](../README.md) - Main documentation

View File

@@ -18,7 +18,7 @@ The `inventory.nix` file defines all hosts in the fleet using a flexible system.
- **Numeric suffixes**: no dash (e.g., `nix-laptop1`, `nix-laptop2`) - **Numeric suffixes**: no dash (e.g., `nix-laptop1`, `nix-laptop2`)
- **Non-numeric suffixes**: with dash (e.g., `nix-laptop-alpha`, `nix-laptop-beta`) - **Non-numeric suffixes**: with dash (e.g., `nix-laptop-alpha`, `nix-laptop-beta`)
- **Custom hostnames**: Set `ugaif.host.useHostPrefix = false` to use suffix as full hostname - **Custom hostnames**: Set `athenix.host.useHostPrefix = false` to use suffix as full hostname
## Adding Hosts ## Adding Hosts
@@ -37,8 +37,8 @@ nix-laptop = {
devices = 5; devices = 5;
overrides = { overrides = {
# Applied to ALL nix-laptop hosts # Applied to ALL nix-laptop hosts
ugaif.users.student.enable = true; athenix.users.student.enable = true;
ugaif.sw.extraPackages = with pkgs; [ vim git ]; athenix.sw.extraPackages = with pkgs; [ vim git ];
}; };
}; };
``` ```
@@ -48,9 +48,9 @@ nix-laptop = {
```nix ```nix
nix-surface = { nix-surface = {
devices = { devices = {
"1".ugaif.sw.kioskUrl = "https://dashboard1.example.com"; "1".athenix.sw.kioskUrl = "https://dashboard1.example.com";
"2".ugaif.sw.kioskUrl = "https://dashboard2.example.com"; "2".athenix.sw.kioskUrl = "https://dashboard2.example.com";
"3".ugaif.sw.kioskUrl = "https://dashboard3.example.com"; "3".athenix.sw.kioskUrl = "https://dashboard3.example.com";
}; };
}; };
``` ```
@@ -62,12 +62,12 @@ nix-surface = {
defaultCount = 2; # Creates nix-surface1, nix-surface2 defaultCount = 2; # Creates nix-surface1, nix-surface2
devices = { devices = {
"special" = { # Creates nix-surface-special "special" = { # Creates nix-surface-special
ugaif.sw.kioskUrl = "https://special-dashboard.example.com"; athenix.sw.kioskUrl = "https://special-dashboard.example.com";
}; };
}; };
overrides = { overrides = {
# Applied to all devices (including "special") # Applied to all devices (including "special")
ugaif.sw.kioskUrl = "https://default-dashboard.example.com"; athenix.sw.kioskUrl = "https://default-dashboard.example.com";
}; };
}; };
``` ```
@@ -76,15 +76,15 @@ nix-surface = {
### Direct Configuration (Recommended) ### Direct Configuration (Recommended)
Use any NixOS or `ugaif.*` option: Use any NixOS or `athenix.*` option:
```nix ```nix
"1" = { "1" = {
# UGAIF options # Athenix options
ugaif.users.myuser.enable = true; athenix.users.myuser.enable = true;
ugaif.host.filesystem.swapSize = "64G"; athenix.host.filesystem.swapSize = "64G";
ugaif.sw.extraPackages = with pkgs; [ docker ]; athenix.sw.extraPackages = with pkgs; [ docker ];
ugaif.sw.kioskUrl = "https://example.com"; athenix.sw.kioskUrl = "https://example.com";
# Standard NixOS options # Standard NixOS options
networking.firewall.enable = false; networking.firewall.enable = false;
@@ -93,14 +93,14 @@ Use any NixOS or `ugaif.*` option:
}; };
``` ```
### Convenience: `ugaif.forUser` ### Convenience: `athenix.forUser`
Quick setup for single-user systems (especially WSL): Quick setup for single-user systems (especially WSL):
```nix ```nix
nix-wsl = { nix-wsl = {
devices = { devices = {
"alice".ugaif.forUser = "alice-username"; "alice".athenix.forUser = "alice-username";
}; };
}; };
``` ```
@@ -115,7 +115,7 @@ For complex configurations, use external modules (see [EXTERNAL_MODULES.md](../E
nix-lxc = { nix-lxc = {
devices = { devices = {
"special-server" = builtins.fetchGit { "special-server" = builtins.fetchGit {
url = "https://github.com/org/server-config"; url = "https://git.factory.uga.edu/org/server-config";
rev = "abc123..."; rev = "abc123...";
}; };
}; };
@@ -130,7 +130,7 @@ nix-lxc = {
nix-laptop = { nix-laptop = {
devices = 10; # Creates nix-laptop1 through nix-laptop10 devices = 10; # Creates nix-laptop1 through nix-laptop10
overrides = { overrides = {
ugaif.users.student.enable = true; athenix.users.student.enable = true;
}; };
}; };
``` ```
@@ -142,13 +142,13 @@ nix-surface = {
defaultCount = 5; # nix-surface1 through nix-surface5 (default config) defaultCount = 5; # nix-surface1 through nix-surface5 (default config)
devices = { devices = {
"admin" = { # nix-surface-admin (special config) "admin" = { # nix-surface-admin (special config)
ugaif.sw.type = "desktop"; # Full desktop instead of kiosk athenix.sw.type = "desktop"; # Full desktop instead of kiosk
ugaif.users.admin.enable = true; athenix.users.admin.enable = true;
}; };
}; };
overrides = { overrides = {
ugaif.sw.type = "tablet-kiosk"; athenix.sw.type = "tablet-kiosk";
ugaif.sw.kioskUrl = "https://dashboard.factory.uga.edu"; athenix.sw.kioskUrl = "https://dashboard.factory.uga.edu";
}; };
}; };
``` ```
@@ -159,15 +159,15 @@ nix-surface = {
nix-lxc = { nix-lxc = {
devices = { devices = {
"nix-builder" = { "nix-builder" = {
ugaif.sw.type = "headless"; athenix.sw.type = "headless";
}; };
"webserver" = { "webserver" = {
ugaif.sw.type = "headless"; athenix.sw.type = "headless";
services.nginx.enable = true; services.nginx.enable = true;
}; };
}; };
overrides = { overrides = {
ugaif.host.useHostPrefix = false; # Use exact device key as hostname athenix.host.useHostPrefix = false; # Use exact device key as hostname
}; };
}; };
``` ```
@@ -177,8 +177,8 @@ nix-lxc = {
```nix ```nix
nix-wsl = { nix-wsl = {
devices = { devices = {
"alice".ugaif.forUser = "alice-uga"; "alice".athenix.forUser = "alice-uga";
"bob".ugaif.forUser = "bob-uga"; "bob".athenix.forUser = "bob-uga";
}; };
}; };
``` ```
@@ -187,4 +187,4 @@ nix-wsl = {
- [USER_CONFIGURATION.md](USER_CONFIGURATION.md) - User account management - [USER_CONFIGURATION.md](USER_CONFIGURATION.md) - User account management
- [EXTERNAL_MODULES.md](EXTERNAL_MODULES.md) - External configuration modules - [EXTERNAL_MODULES.md](EXTERNAL_MODULES.md) - External configuration modules
- [Configuration Namespace Reference](NAMESPACE.md) - All `ugaif.*` options - [Configuration Namespace Reference](NAMESPACE.md) - All `athenix.*` options

View File

@@ -1,36 +1,36 @@
# Configuration Namespace Reference # Configuration Namespace Reference
All UGA Innovation Factory-specific options are under the `ugaif` namespace to avoid conflicts with standard NixOS options. All UGA Innovation Factory-specific options are under the `athenix` namespace to avoid conflicts with standard NixOS options.
## Table of Contents ## Table of Contents
- [Host Configuration (`ugaif.host`)](#host-configuration-ugaifhost) - [Host Configuration (`athenix.host`)](#host-configuration-athenixhost)
- [Software Configuration (`ugaif.sw`)](#software-configuration-ugaifsw) - [Software Configuration (`athenix.sw`)](#software-configuration-athenixsw)
- [User Management (`ugaif.users`)](#user-management-ugaifusers) - [User Management (`athenix.users`)](#user-management-athenixusers)
- [System Configuration (`ugaif.system`)](#system-configuration-ugaifsystem) - [System Configuration (`athenix.system`)](#system-configuration-athenixsystem)
- [Convenience Options](#convenience-options) - [Convenience Options](#convenience-options)
## Host Configuration (`ugaif.host`) ## Host Configuration (`athenix.host`)
Hardware and host-specific settings. Hardware and host-specific settings.
### `ugaif.host.filesystem` ### `athenix.host.filesystem`
Disk and storage configuration. Disk and storage configuration.
**Options:** **Options:**
- `ugaif.host.filesystem.device` - Boot disk device (default: `/dev/sda`) - `athenix.host.filesystem.device` - Boot disk device (default: `/dev/sda`)
- `ugaif.host.filesystem.swapSize` - Swap file size (default: `"32G"`) - `athenix.host.filesystem.swapSize` - Swap file size (default: `"32G"`)
**Example:** **Example:**
```nix ```nix
ugaif.host.filesystem = { athenix.host.filesystem = {
device = "/dev/nvme0n1"; device = "/dev/nvme0n1";
swapSize = "64G"; swapSize = "64G";
}; };
``` ```
### `ugaif.host.buildMethods` ### `athenix.host.buildMethods`
List of supported build artifact types for this host. List of supported build artifact types for this host.
@@ -42,10 +42,10 @@ List of supported build artifact types for this host.
**Example:** **Example:**
```nix ```nix
ugaif.host.buildMethods = [ "lxc" "proxmox" ]; athenix.host.buildMethods = [ "lxc" "proxmox" ];
``` ```
### `ugaif.host.useHostPrefix` ### `athenix.host.useHostPrefix`
Whether to prepend the host type prefix to the hostname (used in inventory generation). Whether to prepend the host type prefix to the hostname (used in inventory generation).
@@ -55,26 +55,26 @@ Whether to prepend the host type prefix to the hostname (used in inventory gener
**Example:** **Example:**
```nix ```nix
ugaif.host.useHostPrefix = false; # "builder" instead of "nix-lxc-builder" athenix.host.useHostPrefix = false; # "builder" instead of "nix-lxc-builder"
``` ```
### `ugaif.host.wsl` ### `athenix.host.wsl`
WSL-specific configuration options. WSL-specific configuration options.
**Options:** **Options:**
- `ugaif.host.wsl.user` - Default WSL user for this instance - `athenix.host.wsl.user` - Default WSL user for this instance
**Example:** **Example:**
```nix ```nix
ugaif.host.wsl.user = "myusername"; athenix.host.wsl.user = "myusername";
``` ```
## Software Configuration (`ugaif.sw`) ## Software Configuration (`athenix.sw`)
System software and application configuration. System software and application configuration.
### `ugaif.sw.enable` ### `athenix.sw.enable`
Enable the software configuration module. Enable the software configuration module.
@@ -82,7 +82,7 @@ Enable the software configuration module.
**Default:** `true` **Default:** `true`
### `ugaif.sw.type` ### `athenix.sw.type`
System type that determines the software profile. System type that determines the software profile.
@@ -98,10 +98,10 @@ System type that determines the software profile.
**Example:** **Example:**
```nix ```nix
ugaif.sw.type = "headless"; athenix.sw.type = "headless";
``` ```
### `ugaif.sw.kioskUrl` ### `athenix.sw.kioskUrl`
URL to display in kiosk mode browsers (for `tablet-kiosk` and `stateless-kiosk` types). URL to display in kiosk mode browsers (for `tablet-kiosk` and `stateless-kiosk` types).
@@ -111,38 +111,38 @@ URL to display in kiosk mode browsers (for `tablet-kiosk` and `stateless-kiosk`
**Example:** **Example:**
```nix ```nix
ugaif.sw.kioskUrl = "https://dashboard.example.com"; athenix.sw.kioskUrl = "https://dashboard.example.com";
``` ```
### `ugaif.sw.python` ### `athenix.sw.python`
Python development tools configuration. Python development tools configuration.
**Options:** **Options:**
- `ugaif.sw.python.enable` - Enable Python tools (pixi, uv) (default: `true`) - `athenix.sw.python.enable` - Enable Python tools (pixi, uv) (default: `true`)
**Example:** **Example:**
```nix ```nix
ugaif.sw.python.enable = true; athenix.sw.python.enable = true;
``` ```
### `ugaif.sw.remoteBuild` ### `athenix.sw.remoteBuild`
Remote build server configuration for offloading builds. Remote build server configuration for offloading builds.
**Options:** **Options:**
- `ugaif.sw.remoteBuild.enable` - Use remote builders (default: enabled on tablets) - `athenix.sw.remoteBuild.enable` - Use remote builders (default: enabled on tablets)
- `ugaif.sw.remoteBuild.hosts` - List of build server hostnames - `athenix.sw.remoteBuild.hosts` - List of build server hostnames
**Example:** **Example:**
```nix ```nix
ugaif.sw.remoteBuild = { athenix.sw.remoteBuild = {
enable = true; enable = true;
hosts = [ "nix-builder" "nix-builder2" ]; hosts = [ "nix-builder" "nix-builder2" ];
}; };
``` ```
### `ugaif.sw.extraPackages` ### `athenix.sw.extraPackages`
Additional system packages to install beyond the type defaults. Additional system packages to install beyond the type defaults.
@@ -152,14 +152,14 @@ Additional system packages to install beyond the type defaults.
**Example:** **Example:**
```nix ```nix
ugaif.sw.extraPackages = with pkgs; [ athenix.sw.extraPackages = with pkgs; [
vim vim
htop htop
docker docker
]; ];
``` ```
### `ugaif.sw.excludePackages` ### `athenix.sw.excludePackages`
Packages to exclude from the default list for this system type. Packages to exclude from the default list for this system type.
@@ -169,16 +169,16 @@ Packages to exclude from the default list for this system type.
**Example:** **Example:**
```nix ```nix
ugaif.sw.excludePackages = with pkgs; [ athenix.sw.excludePackages = with pkgs; [
firefox # Remove Firefox from default desktop packages firefox # Remove Firefox from default desktop packages
]; ];
``` ```
## User Management (`ugaif.users`) ## User Management (`athenix.users`)
User account configuration and management. User account configuration and management.
### `ugaif.users.<username>.enable` ### `athenix.users.<username>.enable`
Enable a specific user account on this system. Enable a specific user account on this system.
@@ -188,7 +188,7 @@ Enable a specific user account on this system.
**Example:** **Example:**
```nix ```nix
ugaif.users = { athenix.users = {
myuser.enable = true; myuser.enable = true;
student.enable = true; student.enable = true;
}; };
@@ -199,44 +199,45 @@ ugaif.users = {
Each user in `users.nix` can be configured with: Each user in `users.nix` can be configured with:
```nix ```nix
ugaif.users.myuser = { # Option 1: Define inline in users.nix
athenix.users.myuser = {
description = "Full Name"; description = "Full Name";
isNormalUser = true; # Default: true isNormalUser = true; # Default: true
extraGroups = [ "wheel" "docker" ]; # Additional groups extraGroups = [ "wheel" "docker" ]; # Additional groups
shell = pkgs.zsh; # Login shell shell = pkgs.zsh; # Login shell
hashedPassword = "$6$..."; # Hashed password hashedPassword = "$6$..."; # Hashed password
opensshKeys = [ "ssh-ed25519 ..." ]; # SSH public keys opensshKeys = [ "ssh-ed25519 ..." ]; # SSH public keys
homePackages = with pkgs; [ ... ]; # User packages
useZshTheme = true; # Use system Zsh theme useZshTheme = true; # Use system Zsh theme
useNvimPlugins = true; # Use system Neovim config useNvimPlugins = true; # Use system Neovim config
# External home-manager configuration (optional) enable = false; # Enable per-system in inventory.nix
home = builtins.fetchGit {
url = "https://github.com/username/dotfiles";
rev = "abc123...";
}; };
enable = false; # Enable per-system in inventory.nix # Option 2: Use external configuration (recommended)
# The external user.nix can set athenix.users.myuser options directly
athenix.users.anotheruser.external = builtins.fetchGit {
url = "https://git.factory.uga.edu/username/dotfiles";
rev = "abc123...";
}; };
``` ```
## System Configuration (`ugaif.system`) ## System Configuration (`athenix.system`)
System-wide settings and services. System-wide settings and services.
### `ugaif.system.gc` ### `athenix.system.gc`
Automatic garbage collection configuration. Automatic garbage collection configuration.
**Options:** **Options:**
- `ugaif.system.gc.enable` - Enable automatic garbage collection (default: `true`) - `athenix.system.gc.enable` - Enable automatic garbage collection (default: `true`)
- `ugaif.system.gc.frequency` - How often to run (default: `"weekly"`) - `athenix.system.gc.frequency` - How often to run (default: `"weekly"`)
- `ugaif.system.gc.retentionDays` - Days to keep old generations (default: `30`) - `athenix.system.gc.retentionDays` - Days to keep old generations (default: `30`)
- `ugaif.system.gc.optimise` - Optimize Nix store automatically (default: `true`) - `athenix.system.gc.optimise` - Optimize Nix store automatically (default: `true`)
**Example:** **Example:**
```nix ```nix
ugaif.system.gc = { athenix.system.gc = {
enable = true; enable = true;
frequency = "daily"; frequency = "daily";
retentionDays = 14; retentionDays = 14;
@@ -246,7 +247,7 @@ ugaif.system.gc = {
## Convenience Options ## Convenience Options
### `ugaif.forUser` ### `athenix.forUser`
Quick setup option that enables a user account in one line. Quick setup option that enables a user account in one line.
@@ -256,14 +257,14 @@ Quick setup option that enables a user account in one line.
**Example:** **Example:**
```nix ```nix
ugaif.forUser = "myusername"; # Equivalent to ugaif.users.myusername.enable = true athenix.forUser = "myusername"; # Equivalent to athenix.users.myusername.enable = true
``` ```
**Usage in inventory.nix:** **Usage in inventory.nix:**
```nix ```nix
nix-wsl = { nix-wsl = {
devices = { devices = {
"alice".ugaif.forUser = "alice-uga"; "alice".athenix.forUser = "alice-uga";
}; };
}; };
``` ```
@@ -271,5 +272,6 @@ nix-wsl = {
## See Also ## See Also
- [INVENTORY.md](INVENTORY.md) - Host inventory configuration guide - [INVENTORY.md](INVENTORY.md) - Host inventory configuration guide
- [USER_CONFIGURATION.md](../USER_CONFIGURATION.md) - User management guide - [USER_CONFIGURATION.md](USER_CONFIGURATION.md) - User management guide
- [EXTERNAL_MODULES.md](EXTERNAL_MODULES.md) - External configuration modules
- [README.md](../README.md) - Main documentation - [README.md](../README.md) - Main documentation

View File

@@ -26,7 +26,8 @@ Users are defined in `users.nix` but are **not enabled by default** on all syste
### 1. Define User in users.nix ### 1. Define User in users.nix
```nix ```nix
ugaif.users = { athenix.users = {
# Option 1: Inline definition
myuser = { myuser = {
description = "My Full Name"; description = "My Full Name";
extraGroups = [ "wheel" "networkmanager" ]; extraGroups = [ "wheel" "networkmanager" ];
@@ -36,6 +37,12 @@ ugaif.users = {
"ssh-ed25519 AAAA... user@machine" "ssh-ed25519 AAAA... user@machine"
]; ];
}; };
# Option 2: External configuration (recommended for personalization)
myuser.external = builtins.fetchGit {
url = "https://git.factory.uga.edu/username/dotfiles";
rev = "abc123..."; # Pin to specific commit
};
}; };
``` ```
@@ -46,20 +53,20 @@ In `inventory.nix`:
```nix ```nix
nix-laptop = { nix-laptop = {
devices = 2; devices = 2;
overrides.ugaif.users.myuser.enable = true; # Enables on all nix-laptop hosts overrides.athenix.users.myuser.enable = true; # Enables on all nix-laptop hosts
}; };
# Or for specific devices # Or for specific devices
nix-desktop = { nix-desktop = {
devices = { devices = {
"1".ugaif.users.myuser.enable = true; "1".athenix.users.myuser.enable = true;
"2".ugaif.users.otheruser.enable = true; "2".athenix.users.otheruser.enable = true;
}; };
}; };
# Or use convenience option # Or use convenience option
nix-wsl = { nix-wsl = {
devices."alice".ugaif.forUser = "alice-user"; # Automatically enables user devices."alice".athenix.forUser = "alice-user"; # Automatically enables user
}; };
``` ```
@@ -93,14 +100,6 @@ username = {
# === External Configuration === # === External Configuration ===
external = builtins.fetchGit { ... }; # External user module (see below) external = builtins.fetchGit { ... }; # External user module (see below)
# OR (if not using external config):
homePackages = with pkgs; [ # User packages
ripgrep
fd
bat
];
extraImports = [ ./my-module.nix ]; # Additional home-manager modules
# === Theme Integration === # === Theme Integration ===
useZshTheme = true; # Apply system Zsh theme (default: true) useZshTheme = true; # Apply system Zsh theme (default: true)
useNvimPlugins = true; # Apply system Neovim config (default: true) useNvimPlugins = true; # Apply system Neovim config (default: true)
@@ -127,7 +126,7 @@ myuser = {
# Point to external configuration repository # Point to external configuration repository
external = builtins.fetchGit { external = builtins.fetchGit {
url = "https://github.com/username/dotfiles"; url = "https://git.factory.uga.edu/username/dotfiles";
rev = "abc123..."; # Pin to specific commit rev = "abc123..."; # Pin to specific commit
}; };
}; };
@@ -137,7 +136,7 @@ myuser = {
``` ```
dotfiles/ dotfiles/
├── user.nix # Optional: User options AND home-manager config ├── user.nix # Required: User options AND home-manager config
├── nixos.nix # Optional: System-level configuration ├── nixos.nix # Optional: System-level configuration
└── config/ # Optional: Your dotfiles └── config/ # Optional: Your dotfiles
├── bashrc ├── bashrc
@@ -145,32 +144,42 @@ dotfiles/
└── ... └── ...
``` ```
**Both `.nix` files are optional, but at least one should be present.** **At least `user.nix` should be present for a functional user module.**
**user.nix (optional):** **user.nix (required):**
```nix ```nix
{ inputs, ... }: { inputs, ... }:
{ config, lib, pkgs, ... }: { config, lib, pkgs, osConfig ? null, ... }:
{ {
# User account options (imported as NixOS module) # ========== User Account Configuration ==========
ugaif.users.myuser = { # These options define the user account itself
athenix.users.myuser = {
description = "My Full Name"; description = "My Full Name";
extraGroups = [ "wheel" "docker" ]; extraGroups = [ "wheel" "docker" ];
shell = pkgs.zsh; shell = pkgs.zsh;
hashedPassword = "!";
opensshKeys = [
"ssh-ed25519 AAAA... user@host"
];
useZshTheme = true; useZshTheme = true;
useNvimPlugins = true;
}; };
# Home-manager configuration (imported into home-manager) # ========== Home Manager Configuration ==========
# User environment, packages, and dotfiles
home.packages = with pkgs; [ home.packages = with pkgs; [
vim vim
ripgrep ripgrep
]; ] ++ lib.optional (osConfig.athenix.sw.type or null == "desktop") firefox;
programs.git = { programs.git = {
enable = true; enable = true;
userName = "My Name"; userName = "My Name";
userEmail = "me@example.com"; userEmail = "me@example.com";
extraConfig = {
init.defaultBranch = "main";
};
}; };
home.file.".bashrc".source = ./config/bashrc; home.file.".bashrc".source = ./config/bashrc;
@@ -199,13 +208,15 @@ dotfiles/
### How External Modules Are Loaded ### How External Modules Are Loaded
The `user.nix` module is used in two ways: The `user.nix` module serves a dual purpose and is imported in **two contexts**:
1. **User Options (Data Extraction)**: The `ugaif.users.<username>` options are extracted and loaded as **data**. The module is evaluated with minimal arguments to extract just the ugaif.users options, which override any defaults set in `users.nix` (which uses `lib.mkDefault`). 1. **NixOS Module Context (User Options)**: The module is imported as a NixOS module where `athenix.users.<username>` options are read to define the user account (description, shell, groups, SSH keys, etc.). These options override any defaults set in `users.nix`.
2. **Home-Manager Configuration**: The entire module (including `home.*`, `programs.*`, `services.*` options) is imported into home-manager as a configuration module. 2. **Home-Manager Context**: The same module is imported into home-manager where `home.*`, `programs.*`, and `services.*` options configure the user's environment, packages, and dotfiles.
This means you can define both user account settings AND home-manager configuration in a single file. **Key insight:** A single `user.nix` file contains both account configuration AND home environment configuration. The system automatically imports it in the appropriate contexts.
**Example:** The user account options (like `shell`, `extraGroups`) are read during NixOS evaluation, while home-manager options (like `home.packages`, `programs.git`) are used when building the user's home environment.
**In nixos.nix:** **In nixos.nix:**
- `inputs` - Flake inputs - `inputs` - Flake inputs
@@ -220,22 +231,12 @@ This means you can define both user account settings AND home-manager configurat
external = /home/username/dev/dotfiles; external = /home/username/dev/dotfiles;
``` ```
**Note:** User options can be set in users.nix OR in the external module's user.nix file. **Note:** User options can be set in users.nix OR in the external module's user.nix file. For custom packages and environment configuration without external modules, create a local module and reference it with `extraImports`.
**No external config:**
```nix
# Configure everything directly in users.nix
myuser = {
description = "My Name";
homePackages = with pkgs; [ vim git ];
# external is null by default
};
```
### Create User Template ### Create User Template
```bash ```bash
nix flake init -t github:UGA-Innovation-Factory/nixos-systems#user nix flake init -t git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix.git#user
``` ```
See [templates/user/README.md](../templates/user/README.md) for complete template. See [templates/user/README.md](../templates/user/README.md) for complete template.
@@ -250,7 +251,7 @@ Users must be explicitly enabled on each host in `inventory.nix`.
nix-laptop = { nix-laptop = {
devices = 5; devices = 5;
overrides = { overrides = {
ugaif.users.student.enable = true; # All 5 laptops get this user athenix.users.student.enable = true; # All 5 laptops get this user
}; };
}; };
``` ```
@@ -260,30 +261,30 @@ nix-laptop = {
```nix ```nix
nix-desktop = { nix-desktop = {
devices = { devices = {
"1".ugaif.users.alice.enable = true; "1".athenix.users.alice.enable = true;
"2".ugaif.users.bob.enable = true; "2".athenix.users.bob.enable = true;
"3" = { "3" = {
ugaif.users.alice.enable = true; athenix.users.alice.enable = true;
ugaif.users.bob.enable = true; athenix.users.bob.enable = true;
}; };
}; };
}; };
``` ```
### Method 3: Convenience Option (ugaif.forUser) ### Method 3: Convenience Option (athenix.forUser)
Quick setup for single-user systems: Quick setup for single-user systems:
```nix ```nix
nix-wsl = { nix-wsl = {
devices = { devices = {
"alice".ugaif.forUser = "alice-user"; # Automatically enables alice-user "alice".athenix.forUser = "alice-user"; # Automatically enables alice-user
"bob".ugaif.forUser = "bob-user"; "bob".athenix.forUser = "bob-user";
}; };
}; };
``` ```
This is equivalent to `ugaif.users.alice-user.enable = true`. This is equivalent to `athenix.users.alice-user.enable = true`.
## Password Management ## Password Management
@@ -380,7 +381,7 @@ admin = {
}; };
``` ```
### User with External Dotfiles ### User with External Configuration
```nix ```nix
developer = { developer = {
@@ -388,8 +389,8 @@ developer = {
extraGroups = [ "wheel" "docker" ]; extraGroups = [ "wheel" "docker" ];
shell = pkgs.zsh; shell = pkgs.zsh;
hashedPassword = "$6$..."; hashedPassword = "$6$...";
home = builtins.fetchGit { external = builtins.fetchGit {
url = "https://github.com/username/dotfiles"; url = "https://git.factory.uga.edu/username/dotfiles";
rev = "abc123def456..."; rev = "abc123def456...";
}; };
}; };
@@ -403,8 +404,8 @@ wsl-user = {
extraGroups = [ "wheel" ]; extraGroups = [ "wheel" ];
shell = pkgs.zsh; shell = pkgs.zsh;
hashedPassword = "$6$..."; hashedPassword = "$6$...";
home = builtins.fetchGit { external = builtins.fetchGit {
url = "https://github.com/username/dotfiles"; url = "https://git.factory.uga.edu/username/dotfiles";
rev = "abc123..."; rev = "abc123...";
}; };
}; };
@@ -413,7 +414,7 @@ wsl-user = {
Enable in inventory.nix: Enable in inventory.nix:
```nix ```nix
nix-wsl = { nix-wsl = {
devices."my-wsl".ugaif.forUser = "wsl-user"; devices."my-wsl".athenix.forUser = "wsl-user";
}; };
``` ```
@@ -429,7 +430,7 @@ poweruser = {
hashedPassword = "$6$..."; hashedPassword = "$6$...";
useZshTheme = false; # Don't apply system theme useZshTheme = false; # Don't apply system theme
useNvimPlugins = false; # Don't apply system nvim config useNvimPlugins = false; # Don't apply system nvim config
home = builtins.fetchGit { external = builtins.fetchGit {
url = "https://github.com/username/custom-dotfiles"; url = "https://github.com/username/custom-dotfiles";
rev = "abc123..."; rev = "abc123...";
}; };
@@ -463,7 +464,7 @@ Disable if you want to configure Neovim yourself.
**Check if enabled on host:** **Check if enabled on host:**
```bash ```bash
nix eval .#nixosConfigurations.nix-laptop1.config.ugaif.users.myuser.enable nix eval .#nixosConfigurations.nix-laptop1.config.athenix.users.myuser.enable
``` ```
**Check if user exists:** **Check if user exists:**
@@ -488,23 +489,23 @@ nix eval .#nixosConfigurations.nix-laptop1.config.users.users.myuser.openssh.aut
**Check repository access:** **Check repository access:**
```bash ```bash
git ls-remote https://github.com/username/dotfiles git ls-remote https://git.factory.uga.edu/username/dotfiles
``` ```
**Verify structure:** **Verify structure:**
- Must have `home.nix` at repository root - Must have `user.nix` at repository root
- `nixos.nix` is optional - `nixos.nix` is optional
- Check file permissions - Check file permissions
**Test with local path first:** **Test with local path first:**
```nix ```nix
home = /path/to/local/dotfiles; external = /path/to/local/dotfiles;
``` ```
## See Also ## See Also
- [docs/EXTERNAL_MODULES.md](EXTERNAL_MODULES.md) - External module guide - [EXTERNAL_MODULES.md](EXTERNAL_MODULES.md) - External module guide
- [docs/INVENTORY.md](INVENTORY.md) - Host configuration - [INVENTORY.md](INVENTORY.md) - Host configuration guide
- [docs/NAMESPACE.md](NAMESPACE.md) - Configuration options - [NAMESPACE.md](NAMESPACE.md) - Configuration options reference
- [templates/user/](../templates/user/) - User module template - [templates/user/](../templates/user/) - User module template
- [README.md](../README.md) - Main documentation - [README.md](../README.md) - Main documentation

30
flake.lock generated
View File

@@ -115,11 +115,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1765326679, "lastModified": 1765794845,
"narHash": "sha256-fTLX9kDwLr9Y0rH/nG+h1XG5UU+jBcy0PFYn5eneRX8=", "narHash": "sha256-YD5QWlGnusNbZCqR3pxG8tRxx9yUXayLZfAJRWspq2s=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "d64e5cdca35b5fad7c504f615357a7afe6d9c49e", "rev": "7194cfe5b7a3660726b0fe7296070eaef601cae9",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -318,11 +318,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1765384171, "lastModified": 1765979862,
"narHash": "sha256-FuFtkJrW1Z7u+3lhzPRau69E0CNjADku1mLQQflUORo=", "narHash": "sha256-/r9/1KamvbHJx6I40H4HsSXnEcBAkj46ZwibhBx9kg0=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "44777152652bc9eacf8876976fa72cc77ca8b9d8", "rev": "d3135ab747fd9dac250ffb90b4a7e80634eacbe9",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -486,11 +486,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1765483419, "lastModified": 1765841014,
"narHash": "sha256-w6wznH1lBzlSH3+pWDkE+L6xA0F02drFAzu2E7PD/Jo=", "narHash": "sha256-55V0AJ36V5Egh4kMhWtDh117eE3GOjwq5LhwxDn9eHg=",
"owner": "nix-community", "owner": "nix-community",
"repo": "NixOS-WSL", "repo": "NixOS-WSL",
"rev": "0c040f28b44b18e0d4240e027096078e34dbb029", "rev": "be4af8042e7a61fa12fda58fe9a3b3babdefe17b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -518,11 +518,11 @@
}, },
"nixpkgs-old-kernel": { "nixpkgs-old-kernel": {
"locked": { "locked": {
"lastModified": 1764939437, "lastModified": 1765687488,
"narHash": "sha256-4TLFHUwXraw9Df5mXC/vCrJgb50CRr3CzUzF0Mn3CII=", "narHash": "sha256-7YAJ6xgBAQ/Nr+7MI13Tui1ULflgAdKh63m1tfYV7+M=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "00d2457e2f608b4be6fe8b470b0a36816324b0ae", "rev": "d02bcc33948ca19b0aaa0213fe987ceec1f4ebe1",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -534,11 +534,11 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1765311797, "lastModified": 1765838191,
"narHash": "sha256-mSD5Ob7a+T2RNjvPvOA1dkJHGVrNVl8ZOrAwBjKBDQo=", "narHash": "sha256-m5KWt1nOm76ILk/JSCxBM4MfK3rYY7Wq9/TZIIeGnT8=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "09eb77e94fa25202af8f3e81ddc7353d9970ac1b", "rev": "c6f52ebd45e5925c188d1a20119978aa4ffd5ef6",
"type": "github" "type": "github"
}, },
"original": { "original": {

View File

@@ -3,7 +3,7 @@
# Flake Entry Point # Flake Entry Point
# ============================================================================ # ============================================================================
# This file defines the inputs (dependencies) and outputs (configurations) # This file defines the inputs (dependencies) and outputs (configurations)
# for the NixOS systems. It ties together the hardware, software, and user # for Athenix. It ties together the hardware, software, and user
# configurations into deployable systems. # configurations into deployable systems.
inputs = { inputs = {

View File

@@ -12,14 +12,14 @@
{ config, lib, ... }: { config, lib, ... }:
{ {
options.ugaif = { options.athenix = {
forUser = lib.mkOption { forUser = lib.mkOption {
type = lib.types.nullOr lib.types.str; type = lib.types.nullOr lib.types.str;
default = null; default = null;
description = '' description = ''
Convenience option to configure a host for a specific user. Convenience option to configure a host for a specific user.
Automatically enables the user (sets ugaif.users.username.enable = true). Automatically enables the user (sets athenix.users.username.enable = true).
Value should be a username from ugaif.users.accounts. Value should be a username from athenix.users.accounts.
''; '';
}; };
@@ -80,8 +80,8 @@
config = lib.mkMerge [ config = lib.mkMerge [
# Enable forUser if specified # Enable forUser if specified
(lib.mkIf (config.ugaif.forUser != null) { (lib.mkIf (config.athenix.forUser != null) {
ugaif.users.${config.ugaif.forUser}.enable = true; athenix.users.${config.athenix.forUser}.enable = true;
}) })
# Main configuration # Main configuration
@@ -92,7 +92,7 @@
disko.devices = { disko.devices = {
disk.main = { disk.main = {
type = "disk"; type = "disk";
device = config.ugaif.host.filesystem.device; device = config.athenix.host.filesystem.device;
content = { content = {
type = "gpt"; type = "gpt";
partitions = { partitions = {
@@ -118,7 +118,7 @@
swap = { swap = {
name = "swap"; name = "swap";
label = "swap"; label = "swap";
size = config.ugaif.host.filesystem.swapSize; size = config.athenix.host.filesystem.swapSize;
content = { content = {
type = "swap"; type = "swap";
}; };

View File

@@ -36,12 +36,12 @@
]; ];
# Automatic Garbage Collection # Automatic Garbage Collection
nix.gc = lib.mkIf config.ugaif.system.gc.enable { nix.gc = lib.mkIf config.athenix.system.gc.enable {
automatic = true; automatic = true;
dates = config.ugaif.system.gc.frequency; dates = config.athenix.system.gc.frequency;
options = "--delete-older-than ${toString config.ugaif.system.gc.retentionDays}d"; options = "--delete-older-than ${toString config.athenix.system.gc.retentionDays}d";
}; };
# Optimize storage # Optimize storage
nix.optimise.automatic = config.ugaif.system.gc.optimise; nix.optimise.automatic = config.athenix.system.gc.optimise;
} }

View File

@@ -16,7 +16,7 @@
# "my-hostname" = { # "my-hostname" = {
# type = "nix-desktop"; # Host type module to use # type = "nix-desktop"; # Host type module to use
# system = "x86_64-linux"; # Optional # system = "x86_64-linux"; # Optional
# # ... any ugaif.* options or device-specific config # # ... any athenix.* options or device-specific config
# }; # };
# #
# "lab-prefix" = { # "lab-prefix" = {
@@ -44,7 +44,7 @@ let
# Load users.nix to find external user modules # Load users.nix to find external user modules
pkgs = nixpkgs.legacyPackages.${system}; pkgs = nixpkgs.legacyPackages.${system};
usersData = import ../users.nix { inherit pkgs; }; usersData = import ../users.nix { inherit pkgs; };
accounts = usersData.ugaif.users or { }; accounts = usersData.athenix.users or { };
# Build a map of user names to their nixos module paths (if they exist) # Build a map of user names to their nixos module paths (if they exist)
# We'll use this to conditionally import modules based on user.enable # We'll use this to conditionally import modules based on user.enable
@@ -90,7 +90,7 @@ let
if lib.isFunction importedModuleFunc then importedModuleFunc args else importedModuleFunc; if lib.isFunction importedModuleFunc then importedModuleFunc args else importedModuleFunc;
in in
{ {
config = lib.mkIf (config.ugaif.users.${name}.enable or false) importedModule; config = lib.mkIf (config.athenix.users.${name}.enable or false) importedModule;
} }
) userNixosModulePaths; ) userNixosModulePaths;
@@ -106,7 +106,7 @@ let
externalPathModule = externalPathModule =
if externalModulePath != null then import externalModulePath { inherit inputs; } else { }; if externalModulePath != null then import externalModulePath { inherit inputs; } else { };
# Config override module - translate special keys to ugaif options # Config override module - translate special keys to athenix options
overrideModule = overrideModule =
{ ... }: { ... }:
let let
@@ -119,7 +119,7 @@ let
"buildMethods" "buildMethods"
]; ];
specialConfig = lib.optionalAttrs (configOverrides ? buildMethods) { specialConfig = lib.optionalAttrs (configOverrides ? buildMethods) {
ugaif.host.buildMethods = configOverrides.buildMethods; athenix.host.buildMethods = configOverrides.buildMethods;
}; };
in in
{ {
@@ -220,7 +220,7 @@ let
lib.recursiveUpdate (lib.recursiveUpdate baseConfig overrides) deviceConfig; lib.recursiveUpdate (lib.recursiveUpdate baseConfig overrides) deviceConfig;
# Check useHostPrefix from the merged config # Check useHostPrefix from the merged config
usePrefix = mergedConfig.ugaif.host.useHostPrefix or true; usePrefix = mergedConfig.athenix.host.useHostPrefix or true;
hostName = mkHostName prefix deviceKey usePrefix; hostName = mkHostName prefix deviceKey usePrefix;
# If external module, also add a default.nix path for import # If external module, also add a default.nix path for import

View File

@@ -38,15 +38,15 @@
]; ];
# ========== Filesystem Configuration ========== # ========== Filesystem Configuration ==========
ugaif.host.filesystem.swapSize = lib.mkDefault "16G"; athenix.host.filesystem.swapSize = lib.mkDefault "16G";
ugaif.host.filesystem.device = lib.mkDefault "/dev/nvme0n1"; athenix.host.filesystem.device = lib.mkDefault "/dev/nvme0n1";
ugaif.host.buildMethods = lib.mkDefault [ "installer-iso" ]; athenix.host.buildMethods = lib.mkDefault [ "installer-iso" ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
# ========== Hardware Configuration ========== # ========== Hardware Configuration ==========
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
# ========== Software Profile ========== # ========== Software Profile ==========
ugaif.sw.enable = lib.mkDefault true; athenix.sw.enable = lib.mkDefault true;
ugaif.sw.type = lib.mkDefault "desktop"; athenix.sw.type = lib.mkDefault "desktop";
} }

View File

@@ -39,9 +39,9 @@
# ========== Ephemeral Configuration ========== # ========== Ephemeral Configuration ==========
# No persistent storage - everything runs from RAM # No persistent storage - everything runs from RAM
ugaif.host.filesystem.swapSize = lib.mkForce "0G"; athenix.host.filesystem.swapSize = lib.mkForce "0G";
ugaif.host.filesystem.device = lib.mkForce "/dev/null"; # Dummy device athenix.host.filesystem.device = lib.mkForce "/dev/null"; # Dummy device
ugaif.host.buildMethods = lib.mkDefault [ athenix.host.buildMethods = lib.mkDefault [
"iso" # Live ISO image "iso" # Live ISO image
"ipxe" # Network boot "ipxe" # Network boot
]; ];
@@ -63,6 +63,6 @@
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
ugaif.sw.enable = lib.mkDefault true; athenix.sw.enable = lib.mkDefault true;
ugaif.sw.type = lib.mkDefault "stateless-kiosk"; athenix.sw.type = lib.mkDefault "stateless-kiosk";
} }

View File

@@ -46,9 +46,9 @@
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
# ========== Filesystem Configuration ========== # ========== Filesystem Configuration ==========
ugaif.host.filesystem.device = lib.mkDefault "/dev/nvme0n1"; athenix.host.filesystem.device = lib.mkDefault "/dev/nvme0n1";
ugaif.host.filesystem.swapSize = lib.mkDefault "34G"; # Larger swap for hibernation athenix.host.filesystem.swapSize = lib.mkDefault "34G"; # Larger swap for hibernation
ugaif.host.buildMethods = lib.mkDefault [ "installer-iso" ]; athenix.host.buildMethods = lib.mkDefault [ "installer-iso" ];
# ========== Power Management ========== # ========== Power Management ==========
services.upower.enable = lib.mkDefault true; services.upower.enable = lib.mkDefault true;
@@ -60,6 +60,6 @@
}; };
}; };
ugaif.sw.enable = lib.mkDefault true; athenix.sw.enable = lib.mkDefault true;
ugaif.sw.type = lib.mkDefault "desktop"; athenix.sw.type = lib.mkDefault "desktop";
} }

View File

@@ -52,11 +52,11 @@
# ========== System Configuration ========== # ========== System Configuration ==========
system.stateVersion = "25.11"; system.stateVersion = "25.11";
ugaif.host.buildMethods = lib.mkDefault [ athenix.host.buildMethods = lib.mkDefault [
"lxc" # LXC container tarball "lxc" # LXC container tarball
"proxmox" # Proxmox VMA archive "proxmox" # Proxmox VMA archive
]; ];
ugaif.sw.enable = lib.mkDefault true; athenix.sw.enable = lib.mkDefault true;
ugaif.sw.type = lib.mkDefault "headless"; athenix.sw.type = lib.mkDefault "headless";
} }

View File

@@ -56,15 +56,15 @@ in
boot.kernelPackages = lib.mkForce refKernelPackages; boot.kernelPackages = lib.mkForce refKernelPackages;
# ========== Filesystem Configuration ========== # ========== Filesystem Configuration ==========
ugaif.host.filesystem.swapSize = lib.mkDefault "8G"; athenix.host.filesystem.swapSize = lib.mkDefault "8G";
ugaif.host.filesystem.device = lib.mkDefault "/dev/mmcblk0"; # eMMC storage # eMMC storage athenix.host.filesystem.device = lib.mkDefault "/dev/mmcblk0"; # eMMC storage # eMMC storage
ugaif.host.buildMethods = lib.mkDefault [ "installer-iso" ]; athenix.host.buildMethods = lib.mkDefault [ "installer-iso" ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
# ========== Hardware Configuration ========== # ========== Hardware Configuration ==========
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
# ========== Software Profile ========== # ========== Software Profile ==========
ugaif.sw.enable = lib.mkDefault true; athenix.sw.enable = lib.mkDefault true;
ugaif.sw.type = lib.mkDefault "tablet-kiosk"; # Touch-optimized kiosk mode athenix.sw.type = lib.mkDefault "tablet-kiosk"; # Touch-optimized kiosk mode
} }

View File

@@ -18,7 +18,7 @@
]; ];
# ========== Options ========== # ========== Options ==========
options.ugaif.host.wsl.user = lib.mkOption { options.athenix.host.wsl.user = lib.mkOption {
type = lib.types.str; type = lib.types.str;
default = "engr-ugaif"; default = "engr-ugaif";
description = "The default user to log in as in WSL."; description = "The default user to log in as in WSL.";
@@ -29,11 +29,11 @@
wsl.enable = true; wsl.enable = true;
# Use forUser if set, otherwise fall back to wsl.user option # Use forUser if set, otherwise fall back to wsl.user option
wsl.defaultUser = wsl.defaultUser =
if config.ugaif.forUser != null then config.ugaif.forUser else config.ugaif.host.wsl.user; if config.athenix.forUser != null then config.athenix.forUser else config.athenix.host.wsl.user;
# ========== Software Profile ========== # ========== Software Profile ==========
ugaif.sw.enable = lib.mkDefault true; athenix.sw.enable = lib.mkDefault true;
ugaif.sw.type = lib.mkDefault "headless"; athenix.sw.type = lib.mkDefault "headless";
# ========== Remote Development ========== # ========== Remote Development ==========
services.vscode-server.enable = true; services.vscode-server.enable = true;
@@ -48,7 +48,7 @@
systemd.network.enable = lib.mkForce false; systemd.network.enable = lib.mkForce false;
# Provide dummy values for required options from boot.nix # Provide dummy values for required options from boot.nix
ugaif.host.filesystem.device = "/dev/null"; athenix.host.filesystem.device = "/dev/null";
ugaif.host.filesystem.swapSize = "0G"; athenix.host.filesystem.swapSize = "0G";
}; };
} }

View File

@@ -16,7 +16,7 @@
let let
# Load users.nix to get account definitions # Load users.nix to get account definitions
usersData = import ../users.nix { inherit pkgs; }; usersData = import ../users.nix { inherit pkgs; };
accounts = usersData.ugaif.users or { }; accounts = usersData.athenix.users or { };
# Helper: Resolve external module path from fetchGit/fetchTarball/path # Helper: Resolve external module path from fetchGit/fetchTarball/path
resolveExternalPath = resolveExternalPath =
@@ -35,7 +35,7 @@ let
&& (builtins.isPath path || (builtins.isString path && lib.hasPrefix "/" path)) && (builtins.isPath path || (builtins.isString path && lib.hasPrefix "/" path))
&& builtins.pathExists path; && builtins.pathExists path;
# Extract ugaif.users options from external user.nix modules # Extract athenix.users options from external user.nix modules
# First, build a cache of options per user from their external user.nix (if any). # First, build a cache of options per user from their external user.nix (if any).
externalUserModuleOptions = lib.genAttrs (lib.attrNames accounts) ( externalUserModuleOptions = lib.genAttrs (lib.attrNames accounts) (
name: name:
@@ -53,20 +53,20 @@ let
inherit lib pkgs; inherit lib pkgs;
osConfig = null; osConfig = null;
}; };
# Extract just the ugaif.users.<name> options # Extract just the athenix.users.<name> options
ugaifUsers = evaluatedModule.ugaif.users or { }; athenixUsers = evaluatedModule.athenix.users or { };
in in
ugaifUsers.${name} or { } athenixUsers.${name} or { }
else else
{ } { }
); );
# externalUserOptions only contains users that actually have options defined # externalUserOptions only contains users that actually have options defined
externalUserOptions = lib.filterAttrs (_: moduleOptions: moduleOptions != { }) externalUserModuleOptions; externalUserOptions = lib.filterAttrs (
_: moduleOptions: moduleOptions != { }
) externalUserModuleOptions;
# Submodule defining the structure of a user account # Submodule defining the structure of a user account
userSubmodule = lib.types.submodule {
options = {
userSubmodule = lib.types.submodule { userSubmodule = lib.types.submodule {
options = { options = {
isNormalUser = lib.mkOption { isNormalUser = lib.mkOption {
@@ -116,7 +116,7 @@ let
- A fetchGit/fetchTarball result pointing to a repository - A fetchGit/fetchTarball result pointing to a repository
The external module can contain: The external module can contain:
- user.nix (optional): Sets ugaif.users.<name> options AND home-manager config - user.nix (optional): Sets athenix.users.<name> options AND home-manager config
- nixos.nix (optional): System-level NixOS configuration - nixos.nix (optional): System-level NixOS configuration
Example: builtins.fetchGit { url = "https://github.com/user/dotfiles"; rev = "..."; } Example: builtins.fetchGit { url = "https://github.com/user/dotfiles"; rev = "..."; }
@@ -154,11 +154,10 @@ let
}; };
}; };
}; };
in in
{ {
options.ugaif.users = lib.mkOption { options.athenix.users = lib.mkOption {
type = lib.types.attrsOf userSubmodule; type = lib.types.attrsOf userSubmodule;
default = { }; default = { };
description = "User accounts configuration. Set enable=true for users that should exist on this system."; description = "User accounts configuration. Set enable=true for users that should exist on this system.";
@@ -167,13 +166,13 @@ in
config = { config = {
# Merge user definitions from users.nix with options from external user.nix modules # Merge user definitions from users.nix with options from external user.nix modules
# External options take precedence over users.nix (which uses lib.mkDefault) # External options take precedence over users.nix (which uses lib.mkDefault)
ugaif.users = lib.mapAttrs ( athenix.users = lib.mapAttrs (
name: user: name: user:
{ user
// {
description = lib.mkDefault (user.description or null); description = lib.mkDefault (user.description or null);
shell = lib.mkDefault (user.shell or null); shell = lib.mkDefault (user.shell or null);
extraGroups = lib.mkDefault (user.extraGroups or [ ]); extraGroups = lib.mkDefault (user.extraGroups or [ ]);
external = user.external or null;
} }
// (externalUserOptions.${name} or { }) // (externalUserOptions.${name} or { })
) accounts; ) accounts;
@@ -181,7 +180,7 @@ in
# Generate NixOS users # Generate NixOS users
users.users = users.users =
let let
enabledAccounts = lib.filterAttrs (_: user: user.enable) config.ugaif.users; enabledAccounts = lib.filterAttrs (_: user: user.enable) config.athenix.users;
in in
lib.mapAttrs ( lib.mapAttrs (
name: user: name: user:
@@ -210,7 +209,7 @@ in
users = users =
let let
enabledAccounts = lib.filterAttrs (_: user: user.enable) config.ugaif.users; enabledAccounts = lib.filterAttrs (_: user: user.enable) config.athenix.users;
in in
lib.mapAttrs ( lib.mapAttrs (
name: user: name: user:
@@ -221,13 +220,13 @@ in
userNixPath = if externalPath != null then externalPath + "/user.nix" else null; userNixPath = if externalPath != null then externalPath + "/user.nix" else null;
hasExternalUser = isValidPath userNixPath; hasExternalUser = isValidPath userNixPath;
# Import external user.nix for home-manager (filter out ugaif.* options) # Import external user.nix for home-manager (filter out athenix.* options)
externalUserModule = externalUserModule =
if hasExternalUser then if hasExternalUser then
let let
fullModule = import userNixPath { inherit inputs; }; fullModule = import userNixPath { inherit inputs; };
in in
# Only pass through non-ugaif options to home-manager # Only pass through non-athenix options to home-manager
{ {
config, config,
lib, lib,
@@ -245,7 +244,7 @@ in
; ;
}; };
in in
lib.filterAttrs (attrName: _: attrName != "ugaif") evaluated lib.filterAttrs (attrName: _: attrName != "athenix") evaluated
else else
{ }; { };

View File

@@ -39,8 +39,8 @@ Add the host to `inventory.nix` with the `nix-lxc` type or ensure it has the app
"my-container" = { }; "my-container" = { };
}; };
overrides = { overrides = {
ugaif.host.useHostPrefix = false; athenix.host.useHostPrefix = false;
ugaif.host.buildMethods = [ "lxc" ]; athenix.host.buildMethods = [ "lxc" ];
}; };
}; };
} }
@@ -291,7 +291,7 @@ nix eval .#nixosConfigurations.nix-builder.config.boot.isContainer
# Should output: true # Should output: true
# Check build methods # Check build methods
nix eval .#nixosConfigurations.nix-builder.config.ugaif.host.buildMethods nix eval .#nixosConfigurations.nix-builder.config.athenix.host.buildMethods
# Should include: "lxc" # Should include: "lxc"
``` ```
@@ -386,7 +386,7 @@ Inside the container:
The script works with any host in your `nixosConfigurations` that: The script works with any host in your `nixosConfigurations` that:
1. Has `boot.isContainer = true` 1. Has `boot.isContainer = true`
2. Has `"lxc"` in `ugaif.host.buildMethods` 2. Has `"lxc"` in `athenix.host.buildMethods`
3. Imports the Proxmox LXC module 3. Imports the Proxmox LXC module
Your `artifacts.nix` automatically exposes these as `lxc-<hostname>` packages. Your `artifacts.nix` automatically exposes these as `lxc-<hostname>` packages.

View File

@@ -79,7 +79,7 @@ let
let let
cfg = hosts.nixosConfigurations.${name}; cfg = hosts.nixosConfigurations.${name};
in in
if lib.elem "installer-iso" cfg.config.ugaif.host.buildMethods then if lib.elem "installer-iso" cfg.config.athenix.host.buildMethods then
[ [
{ {
name = "installer-iso-${name}"; name = "installer-iso-${name}";
@@ -98,7 +98,7 @@ let
let let
cfg = hosts.nixosConfigurations.${name}; cfg = hosts.nixosConfigurations.${name};
in in
if lib.elem "iso" cfg.config.ugaif.host.buildMethods then if lib.elem "iso" cfg.config.athenix.host.buildMethods then
[ [
{ {
name = "iso-${name}"; name = "iso-${name}";
@@ -117,7 +117,7 @@ let
let let
cfg = hosts.nixosConfigurations.${name}; cfg = hosts.nixosConfigurations.${name};
in in
if lib.elem "ipxe" cfg.config.ugaif.host.buildMethods then if lib.elem "ipxe" cfg.config.athenix.host.buildMethods then
[ [
{ {
name = "ipxe-${name}"; name = "ipxe-${name}";
@@ -147,7 +147,7 @@ let
let let
cfg = hosts.nixosConfigurations.${name}; cfg = hosts.nixosConfigurations.${name};
in in
if lib.elem "lxc" cfg.config.ugaif.host.buildMethods then if lib.elem "lxc" cfg.config.athenix.host.buildMethods then
[ [
{ {
name = "lxc-${name}"; name = "lxc-${name}";
@@ -166,7 +166,7 @@ let
let let
cfg = hosts.nixosConfigurations.${name}; cfg = hosts.nixosConfigurations.${name};
in in
if lib.elem "proxmox" cfg.config.ugaif.host.buildMethods then if lib.elem "proxmox" cfg.config.athenix.host.buildMethods then
[ [
{ {
name = "proxmox-${name}"; name = "proxmox-${name}";

View File

@@ -21,7 +21,7 @@
# # Neovim module (requires user parameter): # # Neovim module (requires user parameter):
# home-manager.users.myuser.imports = [ # home-manager.users.myuser.imports = [
# (inputs.nixos-systems.homeManagerModules.nvim { # (inputs.nixos-systems.homeManagerModules.nvim {
# user = config.ugaif.users.accounts.myuser; # user = config.athenix.users.accounts.myuser;
# }) # })
# ]; # ];
@@ -37,9 +37,9 @@
nix-ephemeral = import ../hosts/types/nix-ephemeral.nix { inherit inputs; }; # Diskless/RAM-only nix-ephemeral = import ../hosts/types/nix-ephemeral.nix { inherit inputs; }; # Diskless/RAM-only
# ========== Software Configuration Module ========== # ========== Software Configuration Module ==========
# Main software module with all ugaif.sw options # Main software module with all athenix.sw options
# Use ugaif.sw.type to select profile: "desktop", "tablet-kiosk", "headless", "stateless-kiosk" # Use athenix.sw.type to select profile: "desktop", "tablet-kiosk", "headless", "stateless-kiosk"
# Use ugaif.sw.extraPackages to add additional packages # Use athenix.sw.extraPackages to add additional packages
# Use ugaif.sw.kioskUrl to set kiosk mode URL # Use athenix.sw.kioskUrl to set kiosk mode URL
sw = { inputs, ... }@args: (import ../sw/default.nix (args // { inherit inputs; })); sw = { inputs, ... }@args: (import ../sw/default.nix (args // { inherit inputs; }));
} }

View File

@@ -8,7 +8,7 @@
# Hostname generation rules: # Hostname generation rules:
# - Numeric suffixes: no dash (e.g., "nix-surface1", "nix-surface2") # - Numeric suffixes: no dash (e.g., "nix-surface1", "nix-surface2")
# - Non-numeric suffixes: add dash (e.g., "nix-surface-alpha", "nix-surface-beta") # - Non-numeric suffixes: add dash (e.g., "nix-surface-alpha", "nix-surface-beta")
# - Set ugaif.host.useHostPrefix = false to use suffix as full hostname # - Set athenix.host.useHostPrefix = false to use suffix as full hostname
# #
# Format: # Format:
# "prefix" = { # "prefix" = {
@@ -29,19 +29,19 @@
# "1" = { ... }; # Creates: prefix1 # "1" = { ... }; # Creates: prefix1
# "alpha" = { ... }; # Creates: prefix-alpha # "alpha" = { ... }; # Creates: prefix-alpha
# "custom" = { # Creates: custom (no prefix) # "custom" = { # Creates: custom (no prefix)
# ugaif.host.useHostPrefix = false; # athenix.host.useHostPrefix = false;
# }; # };
# }; # };
# #
# # Common config for all devices in this group # # Common config for all devices in this group
# overrides = { # overrides = {
# ugaif.users.user1.enable = true; # Applied to all devices in this group # athenix.users.user1.enable = true; # Applied to all devices in this group
# # ... any other config # # ... any other config
# }; # };
# }; # };
# #
# Convenience options: # Convenience options:
# ugaif.forUser = "username"; # Automatically enables user (sets ugaif.users.username.enable = true) # athenix.forUser = "username"; # Automatically enables user (sets athenix.users.username.enable = true)
# #
# External modules (instead of config): # External modules (instead of config):
# Device values can be either a config attrset OR a fetchGit/fetchurl call # Device values can be either a config attrset OR a fetchGit/fetchurl call
@@ -56,22 +56,22 @@
# }; # };
# "laptop" = { # "laptop" = {
# devices = 5; # devices = 5;
# overrides.ugaif.users.student.enable = true; # All 5 laptops get this user # overrides.athenix.users.student.enable = true; # All 5 laptops get this user
# }; # };
# "wsl" = { # "wsl" = {
# devices."alice".ugaif.forUser = "alice123"; # Sets up for user alice123 # devices."alice".athenix.forUser = "alice123"; # Sets up for user alice123
# }; # };
# "external" = { # "external" = {
# devices."remote" = builtins.fetchGit { # External module via Git # devices."remote" = builtins.fetchGit { # External module via Git
# url = "https://github.com/example/config"; # url = "https://github.com/example/config";
# rev = "abc123..."; # rev = "e1ccd7cc3e709afe4f50b0627e1c4bde49165014";
# }; # };
# }; # ========== Lab Laptops ========== # }; # ========== Lab Laptops ==========
# Creates: nix-laptop1, nix-laptop2 # Creates: nix-laptop1, nix-laptop2
# Both get hdh20267 user via overrides # Both get hdh20267 user via overrides
nix-laptop = { nix-laptop = {
devices = 2; devices = 2;
overrides.ugaif.users.hdh20267.enable = true; overrides.athenix.users.hdh20267.enable = true;
}; };
# ========== Desktop ========== # ========== Desktop ==========
@@ -85,10 +85,10 @@
nix-surface = { nix-surface = {
defaultCount = 3; defaultCount = 3;
devices = { devices = {
"1".ugaif.sw.kioskUrl = "https://google.com"; "1".athenix.sw.kioskUrl = "https://google.com";
}; };
overrides = { overrides = {
ugaif.sw.kioskUrl = "https://yahoo.com"; athenix.sw.kioskUrl = "https://yahoo.com";
}; };
}; };
@@ -97,37 +97,37 @@
nix-lxc = { nix-lxc = {
devices = { devices = {
"nix-builder" = { "nix-builder" = {
# GitHub Actions self-hosted runner configuration # Gitea Actions self-hosted runner configuration
ugaif.sw = { athenix.sw = {
type = [ type = [
"headless" "headless"
"builders" "builders"
]; ];
builders.githubRunner = { builders.giteaRunner = {
enable = true; enable = true;
url = "https://github.com/UGA-Innovation-Factory/nixos-systems"; url = "https://git.factory.uga.edu";
# Token file must be created manually at this path with a GitHub PAT # Token file must be created manually at this path with a Gitea runner token
# that has repo access. Generate at: https://github.com/settings/tokens # Generate in repository settings: Settings > Actions > Runners > Create new Runner
# echo "YOUR_TOKEN_HERE" | sudo tee /var/lib/github-runner-token > /dev/null # echo "TOKEN=YOUR_TOKEN_HERE" | sudo tee /var/lib/gitea-runner-token > /dev/null
tokenFile = "/var/lib/github-runner-token"; tokenFile = "/var/lib/gitea-runner-token";
# Labels to identify this runner in workflows # Labels to identify this runner in workflows
extraLabels = [ "nix-builder" ]; extraLabels = [
# User to run the runner as "self-hosted"
user = "engr-ugaif"; "nix-builder"
# Working directory for runner ];
workDir = "/var/lib/github-runner";
# Runner service name # Runner service name
name = "nixos-systems"; name = "athenix";
}; };
}; };
}; };
"usda-dash" = builtins.fetchGit { "usda-dash" = builtins.fetchGit {
url = "https://git.factory.uga.edu/MODEL/usda-dash-config.git"; url = "git@factory.uga.edu:MODEL/usda-dash-config.git";
rev = "c47ab8fe295ba38cf3baa8670812b23a09fb4d53"; rev = "49cded91cff4a956d4e01ac6b8fe4efa86f82182";
submodules = true;
}; };
}; };
overrides = { overrides = {
ugaif.host.useHostPrefix = false; athenix.host.useHostPrefix = false;
}; };
}; };
@@ -135,7 +135,7 @@
# Creates: nix-wsl-alireza # Creates: nix-wsl-alireza
nix-wsl = { nix-wsl = {
devices = { devices = {
"alireza".ugaif.forUser = "sv22900"; "alireza".athenix.forUser = "sv22900";
}; };
}; };
@@ -151,7 +151,7 @@
# # Option 1: fetchGit with specific revision (recommended for reproducibility) # # Option 1: fetchGit with specific revision (recommended for reproducibility)
# "prod-server" = builtins.fetchGit { # "prod-server" = builtins.fetchGit {
# url = "https://github.com/example/server-config"; # url = "https://github.com/example/server-config";
# rev = "abc123def456..."; # Full commit hash # rev = "e1ccd7cc3e709afe4f50b0627e1c4bde49165014"; # Full commit hash
# ref = "main"; # Optional: branch/tag name # ref = "main"; # Optional: branch/tag name
# }; # };
# #

View File

@@ -1,7 +1,7 @@
# ============================================================================ # ============================================================================
# Builders Software Configuration # Builders Software Configuration
# ============================================================================ # ============================================================================
# Imports builder-specific programs and services (GitHub Actions runners, etc.) # Imports builder-specific programs and services (Gitea Actions runners, etc.)
{ {
config, config,

View File

@@ -9,11 +9,24 @@
with lib; with lib;
let let
cfg = config.ugaif.sw; cfg = config.athenix.sw;
basePackages = with pkgs; [ basePackages = with pkgs; [
# Build-related packages can be added here if needed # Build-related packages can be added here if needed
]; ];
in in
{ {
environment.systemPackages = subtractLists cfg.excludePackages (basePackages ++ cfg.extraPackages); environment.systemPackages = subtractLists cfg.excludePackages (basePackages ++ cfg.extraPackages);
programs.ssh.knownHosts."factory.uga.edu" = {
hostNames = [ "factory.uga.edu" ];
publicKey = ''
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGcrA7pAz+JGn7/7PqPR4aCZJB5c3aVMTvGXWjg/BqST
'';
};
programs.ssh.knownHosts."github.com" = {
hostNames = [ "github.com" ];
publicKey = ''
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
'';
};
} }

View File

@@ -8,122 +8,66 @@
with lib; with lib;
let let
cfg = config.ugaif.sw; cfg = config.athenix.sw;
builderCfg = cfg.builders; builderCfg = cfg.builders;
in in
mkIf builderCfg.githubRunner.enable { mkIf builderCfg.giteaRunner.enable {
services.github-runners.${builderCfg.githubRunner.name} = { services.gitea-actions-runner.instances.${builderCfg.giteaRunner.name} = {
enable = true; enable = true;
url = builderCfg.githubRunner.url; url = builderCfg.giteaRunner.url;
tokenFile = builderCfg.githubRunner.tokenFile; tokenFile = builderCfg.giteaRunner.tokenFile;
extraLabels = builderCfg.githubRunner.extraLabels; labels = builderCfg.giteaRunner.extraLabels;
user = builderCfg.githubRunner.user; name = builderCfg.giteaRunner.name;
workDir = builderCfg.githubRunner.workDir;
replace = builderCfg.githubRunner.replace; # Run as engr-ugaif user to access SSH keys
settings = {
runner = {
user = "engr-ugaif";
};
};
}; };
# Configure the systemd service for better handling of cleanup and restarts # Configure the systemd service for better handling in LXC containers
systemd.services."github-runner-${builderCfg.githubRunner.name}" = { systemd.services."gitea-runner-${builderCfg.giteaRunner.name}" = {
unitConfig = { unitConfig = {
# Only start the service if token file exists # Only start the service if token file exists
# This allows graceful deployment before the token is manually installed # This allows graceful deployment before the token is manually installed
ConditionPathExists = builderCfg.githubRunner.tokenFile; ConditionPathExists = builderCfg.giteaRunner.tokenFile;
}; };
serviceConfig = { serviceConfig = {
# Run as engr-ugaif user
User = mkForce "engr-ugaif";
Group = mkForce "users";
# Give the service more time to stop cleanly # Give the service more time to stop cleanly
TimeoutStopSec = 60; TimeoutStopSec = mkForce 60;
# Restart on failure, but not immediately
RestartSec = 10; # Add Node.js and other tools to PATH for GitHub Actions compatibility
Environment = [
"PATH=${pkgs.nodejs}/bin:${pkgs.bash}/bin:${pkgs.coreutils}/bin:${pkgs.git}/bin:${pkgs.nix}/bin:/run/current-system/sw/bin"
"HOME=/home/engr-ugaif"
];
# Disable all namespace isolation features that don't work in LXC containers # Disable all namespace isolation features that don't work in LXC containers
# Remove systemd security features that conflict with home directory access
DynamicUser = mkForce false;
PrivateMounts = mkForce false; PrivateMounts = mkForce false;
MountAPIVFS = mkForce false; MountAPIVFS = mkForce false;
BindPaths = mkForce [ ]; BindPaths = mkForce [ ];
BindReadOnlyPaths = mkForce [ ]; BindReadOnlyPaths = mkForce [ ];
ReadWritePaths = mkForce [ ];
ReadOnlyPaths = mkForce [ ];
InaccessiblePaths = mkForce [ ];
PrivateTmp = mkForce false; PrivateTmp = mkForce false;
PrivateDevices = mkForce false; PrivateDevices = mkForce false;
ProtectSystem = mkForce false; ProtectSystem = mkForce false;
ProtectHome = mkForce false; ProtectHome = mkForce false;
ReadOnlyPaths = mkForce [ ];
InaccessiblePaths = mkForce [ ];
PrivateUsers = mkForce false; PrivateUsers = mkForce false;
ProtectKernelTunables = mkForce false; ProtectKernelTunables = mkForce false;
ProtectKernelModules = mkForce false; ProtectKernelModules = mkForce false;
ProtectControlGroups = mkForce false; ProtectControlGroups = mkForce false;
RestrictAddressFamilies = mkForce [ ];
# Use LoadCredential to securely pass the token file to the service SystemCallFilter = mkForce [ ];
# This allows the service to read the token even when running as non-root
LoadCredential = "token:${builderCfg.githubRunner.tokenFile}";
# Don't override ExecStartPre - let the default module handle configuration
# Just make the cleanup more tolerant by wrapping the original script
ExecStartPre = mkForce (
let
# Get the runner package and scripts
runnerPkg = pkgs.github-runner;
# Create wrapper scripts that are failure-tolerant
unconfigureWrapper = pkgs.writeShellScript "github-runner-unconfigure-wrapper.sh" ''
set +e # Don't fail on errors
runnerDir="$1"
stateDir="$2"
logDir="$3"
# If directory is busy, just skip cleanup with a warning
if [ -d "$runnerDir" ]; then
echo "Attempting cleanup of $runnerDir..."
find "$runnerDir" -mindepth 1 -maxdepth 1 -delete 2>/dev/null || {
echo "Warning: Cleanup had issues (directory may be in use), continuing anyway..."
}
fi
exit 0
'';
configureScript = pkgs.writeShellScript "github-runner-configure.sh" ''
set -e
runnerDir="${builderCfg.githubRunner.workDir}/${builderCfg.githubRunner.name}"
# Read token from systemd credential (passed via LoadCredential)
if [ -n "''${CREDENTIALS_DIRECTORY:-}" ] && [ -f "''${CREDENTIALS_DIRECTORY}/token" ]; then
token=$(cat "''${CREDENTIALS_DIRECTORY}/token")
else
echo "Error: Token credential not available"
exit 1
fi
cd "$runnerDir"
# Configure the runner, optionally replacing existing registration
if [ ! -f ".runner" ] || [ "${
if builderCfg.githubRunner.replace then "true" else "false"
}" = "true" ]; then
echo "Configuring GitHub Actions runner..."
${runnerPkg}/bin/Runner.Listener configure \
--unattended \
--url "${builderCfg.githubRunner.url}" \
--token "$token" \
--name "$(hostname)" \
--labels "${lib.concatStringsSep "," builderCfg.githubRunner.extraLabels}" \
--work "_work" \
${if builderCfg.githubRunner.replace then "--replace" else ""}
else
echo "Runner already configured, skipping configuration."
fi
'';
in
[
"-${unconfigureWrapper} ${builderCfg.githubRunner.workDir}/${builderCfg.githubRunner.name} ${builderCfg.githubRunner.workDir} /var/log/github-runner/${builderCfg.githubRunner.name}"
"${configureScript}"
]
);
}; };
}; };
# Ensure the work directory exists with proper ownership
systemd.tmpfiles.rules = [
"d ${builderCfg.githubRunner.workDir} 0755 ${builderCfg.githubRunner.user} ${builderCfg.githubRunner.user} -"
];
} }

View File

@@ -16,7 +16,7 @@
with lib; with lib;
let let
cfg = config.ugaif.sw; cfg = config.athenix.sw;
# Normalize type to always be a list # Normalize type to always be a list
swTypes = if isList cfg.type then cfg.type else [ cfg.type ]; swTypes = if isList cfg.type then cfg.type else [ cfg.type ];
@@ -29,9 +29,10 @@ in
./python.nix ./python.nix
./ghostty.nix ./ghostty.nix
./updater.nix ./updater.nix
./update-ref.nix
]; ];
options.ugaif.sw = { options.athenix.sw = {
enable = mkEnableOption "Standard Workstation Configuration"; enable = mkEnableOption "Standard Workstation Configuration";
type = mkOption { type = mkOption {
@@ -79,21 +80,21 @@ in
builders = mkOption { builders = mkOption {
type = types.submodule { type = types.submodule {
options = { options = {
githubRunner = { giteaRunner = {
enable = mkEnableOption "GitHub Actions self-hosted runner"; enable = mkEnableOption "Gitea Actions self-hosted runner";
url = mkOption { url = mkOption {
type = types.str; type = types.str;
description = "GitHub repository URL for the runner"; description = "Gitea instance URL for the runner";
}; };
tokenFile = mkOption { tokenFile = mkOption {
type = types.path; type = types.path;
default = "/var/lib/github-runner-token"; default = "/var/lib/gitea-runner-token";
description = '' description = ''
Path to file containing GitHub PAT token. Path to file containing Gitea runner token.
Generate at: https://github.com/settings/tokens Generate in Gitea repository settings under Actions > Runners.
The token must have repo access. The token must have runner registration access.
''; '';
}; };
@@ -103,28 +104,10 @@ in
description = "Extra labels to identify this runner in workflows"; description = "Extra labels to identify this runner in workflows";
}; };
user = mkOption {
type = types.str;
default = "engr-ugaif";
description = "User to run the runner as";
};
workDir = mkOption {
type = types.str;
default = "/var/lib/github-runner";
description = "Working directory for runner";
};
name = mkOption { name = mkOption {
type = types.str; type = types.str;
default = "nixos-systems"; default = "athenix";
description = "Name of the GitHub runner service"; description = "Name of the Gitea runner service";
};
replace = mkOption {
type = types.bool;
default = false;
description = "Replace existing runner registration on start";
}; };
}; };
}; };

View File

@@ -9,7 +9,7 @@
with lib; with lib;
let let
cfg = config.ugaif.sw; cfg = config.athenix.sw;
basePackages = with pkgs; [ basePackages = with pkgs; [
tmux tmux
man man

View File

@@ -6,7 +6,7 @@
}: }:
{ {
ugaif.sw.python.enable = lib.mkDefault true; athenix.sw.python.enable = lib.mkDefault true;
services.displayManager.sddm.enable = true; services.displayManager.sddm.enable = true;
services.desktopManager.plasma6.enable = true; services.desktopManager.plasma6.enable = true;

View File

@@ -9,7 +9,7 @@
with lib; with lib;
let let
cfg = config.ugaif.sw; cfg = config.athenix.sw;
basePackages = with pkgs; [ basePackages = with pkgs; [
tmux tmux
man man

View File

@@ -15,10 +15,10 @@
with lib; with lib;
let let
cfg = config.ugaif.sw.python; cfg = config.athenix.sw.python;
in in
{ {
options.ugaif.sw.python = { options.athenix.sw.python = {
enable = mkEnableOption "Python development tools (pixi, uv)" // { enable = mkEnableOption "Python development tools (pixi, uv)" // {
default = true; default = true;
}; };

View File

@@ -6,7 +6,7 @@
}: }:
let let
cfg = config.ugaif.sw; cfg = config.athenix.sw;
in in
{ {
programs.dconf = { programs.dconf = {

View File

@@ -9,7 +9,7 @@
with lib; with lib;
let let
cfg = config.ugaif.sw; cfg = config.athenix.sw;
basePackages = with pkgs; [ basePackages = with pkgs; [
libcamera libcamera
chromium chromium

View File

@@ -155,7 +155,7 @@
--noerrdialogs \ --noerrdialogs \
--disable-session-crashed-bubble \ --disable-session-crashed-bubble \
--disable-infobars \ --disable-infobars \
${config.ugaif.sw.kioskUrl} ${config.athenix.sw.kioskUrl}
''; '';
}; };
}; };

487
sw/update-ref.nix Normal file
View File

@@ -0,0 +1,487 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
python3
git
(pkgs.writeShellScriptBin "update-ref" ''
set -euo pipefail
RED='\033[31m'; YEL='\033[33m'; NC='\033[0m'
die() { printf "''${RED}error:''${NC} %s\n" "$*" >&2; exit 2; }
warn() { printf "''${YEL}warning:''${NC} %s\n" "$*" >&2; }
usage() {
cat >&2 <<'EOF'
usage:
update-ref [-R PATH|--athenix-repo=PATH] [-b BRANCH|--athenix-branch=BRANCH]
[-m "msg"|--message "msg"]
[-p[=false] [remote[=URL]]|--push[=false] [remote[=URL]]]
[--make-local|-l] [--make-remote|-r]
user=<username> | system=<device-type>:<hostkey>
EOF
exit 2
}
# --- must be in a git repo (current dir) ---
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || die "This directory is not a git project"
CUR_REPO_ROOT="$(git rev-parse --show-toplevel)"
CUR_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
# --- athenix checkout (working tree) ---
ATHENIX_DIR="$HOME/athenix"
ATHENIX_BRANCH=""
# --- current repo automation ---
COMMIT_MSG=""
PUSH_SPEC=""
# --- push / url mode ---
PUSH_SET=0
DO_PUSH=0
MODE_FORCE="" # "", local, remote
TARGET=""
is_remote_url() {
# https://, http://, ssh://, or scp-style git@host:org/repo
printf "%s" "$1" | grep -qE '^(https?|ssh)://|^[^/@:]+@[^/:]+:'
}
derive_full_hostname() {
devtype="$1"; hostkey="$2"
if printf "%s" "$hostkey" | grep -q '-' || printf "%s" "$hostkey" | grep -q "^$devtype"; then
printf "%s" "$hostkey"
elif printf "%s" "$hostkey" | grep -qE '^[0-9]+$'; then
printf "%s" "$devtype$hostkey"
else
printf "%s" "$devtype-$hostkey"
fi
}
extract_existing_fetch_url() {
# args: mode file username key
python3 - "$1" "$2" "$3" "$4" <<'PY'
import sys, re, pathlib
mode, file, username, key = sys.argv[1:5]
t = pathlib.Path(file).read_text()
def url_from_block(block: str) -> str:
if not block:
return ""
m = re.search(r'url\s*=\s*"([^"]+)"\s*;', block)
return m.group(1) if m else ""
if mode == "user":
m = re.search(r'(?s)\n\s*' + re.escape(username) + r'\.external\s*=\s*builtins\.fetchGit\s*\{(.*?)\n\s*\};', t)
block = m.group(1) if m else ""
print(url_from_block(block))
else:
m = re.search(r'(?s)\n\s*"' + re.escape(key) + r'"\s*=\s*builtins\.fetchGit\s*\{(.*?)\n\s*\};', t)
block = m.group(1) if m else ""
print(url_from_block(block))
PY
}
# --- parse args ---
while [ "$#" -gt 0 ]; do
case "$1" in
user=*|system=*)
[ -z "$TARGET" ] || die "Only one subcommand allowed (user=... or system=...)"
TARGET="$1"; shift
;;
--athenix-repo=*)
ATHENIX_DIR="''${1#*=}"; shift
;;
-R)
[ "$#" -ge 2 ] || usage
ATHENIX_DIR="$2"; shift 2
;;
--athenix-branch=*)
ATHENIX_BRANCH="''${1#*=}"; shift
;;
-b)
[ "$#" -ge 2 ] || usage
ATHENIX_BRANCH="$2"; shift 2
;;
-m|--message)
[ "$#" -ge 2 ] || usage
COMMIT_MSG="$2"; shift 2
;;
-p|--push)
PUSH_SET=1
DO_PUSH=1
PUSH_SPEC=""
# If there is a next token, only consume it if it is a remote spec
# and not another flag or the subcommand.
if [ "$#" -ge 2 ]; then
nxt="$2"
if printf "%s" "$nxt" | grep -qE '^(user=|system=)'; then
# next token is the subcommand; don't consume it
shift
elif printf "%s" "$nxt" | grep -qE '^-'; then
# next token is another flag; don't consume it
shift
elif printf "%s" "$nxt" | grep -qE '^[A-Za-z0-9._-]+$'; then
# remote name
PUSH_SPEC="$nxt"
shift 2
elif printf "%s" "$nxt" | grep -qE '^[A-Za-z0-9._-]+=.+$'; then
# remote=URL
PUSH_SPEC="$nxt"
shift 2
else
# unknown token; treat as not-a-push-spec and don't consume it
shift
fi
else
shift
fi
;;
-p=*|--push=*)
PUSH_SET=1
val="''${1#*=}"
case "$val" in
false|0|no|off) DO_PUSH=0 ;;
true|1|yes|on|"") DO_PUSH=1 ;;
*) die "Invalid value for --push: $val (use true/false)" ;;
esac
shift
;;
--make-local|-l) MODE_FORCE="local"; shift ;;
--make-remote|-r) MODE_FORCE="remote"; shift ;;
-h|--help) usage ;;
*) die "Unknown argument: $1" ;;
esac
done
[ -n "$TARGET" ] || die "Missing required subcommand: user=<username> or system=<device-type>:<hostkey>"
# --- validate athenix working tree path ---
[ -d "$ATHENIX_DIR" ] || die "$ATHENIX_DIR does not exist"
git -C "$ATHENIX_DIR" rev-parse --is-inside-work-tree >/dev/null 2>&1 || die "$ATHENIX_DIR is not a git project (athenix checkout)"
# --- -b behavior: fork/switch athenix working tree into branch ---
if [ -n "$ATHENIX_BRANCH" ]; then
ATH_CUR_BRANCH="$(git -C "$ATHENIX_DIR" rev-parse --abbrev-ref HEAD)"
if [ "$ATH_CUR_BRANCH" != "$ATHENIX_BRANCH" ]; then
if git -C "$ATHENIX_DIR" show-ref --verify --quiet "refs/heads/$ATHENIX_BRANCH"; then
warn "Branch '$ATHENIX_BRANCH' already exists in $ATHENIX_DIR."
warn "Delete and recreate it from current branch '$ATH_CUR_BRANCH' state? [y/N] "
read -r ans || true
case "''${ans:-N}" in
y|Y|yes|YES)
git -C "$ATHENIX_DIR" branch -D "$ATHENIX_BRANCH"
git -C "$ATHENIX_DIR" switch -c "$ATHENIX_BRANCH"
;;
*)
git -C "$ATHENIX_DIR" switch "$ATHENIX_BRANCH"
;;
esac
else
git -C "$ATHENIX_DIR" switch -c "$ATHENIX_BRANCH"
fi
fi
fi
# --- target file + identifiers ---
MODE=""; FILE=""; USERNAME=""; DEVTYPE=""; HOSTKEY=""
case "$TARGET" in
user=*)
MODE="user"
USERNAME="''${TARGET#user=}"
[ -n "$USERNAME" ] || die "user=<username>: username missing"
FILE="$ATHENIX_DIR/users.nix"
;;
system=*)
MODE="system"
RHS="''${TARGET#system=}"
printf "%s" "$RHS" | grep -q ':' || die "system=... must be system=<device-type>:<hostkey>"
DEVTYPE="''${RHS%%:*}"
HOSTKEY="''${RHS#*:}"
[ -n "$DEVTYPE" ] || die "system=<device-type>:<hostkey>: device-type missing"
[ -n "$HOSTKEY" ] || die "system=<device-type>:<hostkey>: hostkey missing"
FILE="$ATHENIX_DIR/inventory.nix"
;;
esac
[ -f "$FILE" ] || die "File not found: $FILE"
# --- push default based on existing entry url in the target file ---
EXISTING_URL=""
ENTRY_EXISTS=0
if [ "$MODE" = "user" ]; then
EXISTING_URL="$(extract_existing_fetch_url user "$FILE" "$USERNAME" "")"
[ -n "$EXISTING_URL" ] && ENTRY_EXISTS=1 || true
else
FULL="$(derive_full_hostname "$DEVTYPE" "$HOSTKEY")"
EXISTING_URL="$(extract_existing_fetch_url system "$FILE" "" "$HOSTKEY")"
if [ -n "$EXISTING_URL" ]; then
ENTRY_EXISTS=1
elif [ "$FULL" != "$HOSTKEY" ]; then
EXISTING_URL="$(extract_existing_fetch_url system "$FILE" "" "$FULL")"
[ -n "$EXISTING_URL" ] && ENTRY_EXISTS=1 || true
fi
fi
if [ "$PUSH_SET" -eq 0 ]; then
if [ "$ENTRY_EXISTS" -eq 1 ] && is_remote_url "$EXISTING_URL"; then
DO_PUSH=1
else
DO_PUSH=0
[ "$MODE_FORCE" = "remote" ] && DO_PUSH=1 || true
fi
fi
if [ "$MODE_FORCE" = "local" ] && [ "$PUSH_SET" -eq 0 ]; then
DO_PUSH=0
fi
# --- if current repo dirty, prompt ---
if [ -n "$(git status --porcelain)" ]; then
warn "This branch has untracked or uncommitted changes. Would you like to add, commit''${DO_PUSH:+, and push}? [y/N] "
read -r ans || true
case "''${ans:-N}" in
y|Y|yes|YES)
git add -A
if ! git diff --cached --quiet; then
if [ -n "$COMMIT_MSG" ]; then git commit -m "$COMMIT_MSG"; else git commit; fi
else
warn "No staged changes to commit."
fi
;;
*) warn "Proceeding without committing. (rev will be last committed HEAD.)" ;;
esac
fi
# --- push current repo if requested ---
PUSH_REMOTE_URL=""
if [ "$DO_PUSH" -eq 1 ]; then
if [ -n "$PUSH_SPEC" ]; then
if printf "%s" "$PUSH_SPEC" | grep -q '='; then
REM_NAME="''${PUSH_SPEC%%=*}"
REM_URL="''${PUSH_SPEC#*=}"
[ -n "$REM_NAME" ] || die "--push remote-name=URL: remote-name missing"
[ -n "$REM_URL" ] || die "--push remote-name=URL: URL missing"
if git remote get-url "$REM_NAME" >/dev/null 2>&1; then
git remote set-url "$REM_NAME" "$REM_URL"
else
git remote add "$REM_NAME" "$REM_URL"
fi
git push -u "$REM_NAME" "$CUR_BRANCH"
PUSH_REMOTE_URL="$REM_URL"
else
REM_NAME="$PUSH_SPEC"
git push -u "$REM_NAME" "$CUR_BRANCH"
PUSH_REMOTE_URL="$(git remote get-url "$REM_NAME")"
fi
else
if ! git rev-parse --abbrev-ref --symbolic-full-name @{u} >/dev/null 2>&1; then
die "No upstream is set. Set a default upstream with \"git branch -u <remote>/<remote_branch_name>\""
fi
git push
UPSTREAM_REMOTE="$(git rev-parse --abbrev-ref --symbolic-full-name @{u} | cut -d/ -f1)"
PUSH_REMOTE_URL="$(git remote get-url "$UPSTREAM_REMOTE")"
fi
fi
CUR_REV="$(git -C "$CUR_REPO_ROOT" rev-parse HEAD)"
# --- choose URL to write into fetchGit ---
if [ "$MODE_FORCE" = "local" ]; then
FETCH_URL="file://$CUR_REPO_ROOT"
elif [ "$MODE_FORCE" = "remote" ]; then
if [ "$DO_PUSH" -eq 1 ]; then
FETCH_URL="$PUSH_REMOTE_URL"
elif [ "$ENTRY_EXISTS" -eq 1 ] && [ -n "$EXISTING_URL" ] && is_remote_url "$EXISTING_URL"; then
FETCH_URL="$EXISTING_URL"
else
CUR_ORIGIN="$(git remote get-url origin 2>/dev/null || true)"
[ -n "$CUR_ORIGIN" ] && is_remote_url "$CUR_ORIGIN" || die "--make-remote requires a remote url (set origin or use -p remote=URL)"
FETCH_URL="$CUR_ORIGIN"
fi
else
if [ "$DO_PUSH" -eq 1 ]; then FETCH_URL="$PUSH_REMOTE_URL"; else FETCH_URL="file://$CUR_REPO_ROOT"; fi
fi
# --- rewrite users.nix or inventory.nix ---
python3 - "$MODE" "$FILE" "$FETCH_URL" "$CUR_REV" "$USERNAME" "$DEVTYPE" "$HOSTKEY" <<'PY'
import sys, re, pathlib
mode = sys.argv[1]
path = pathlib.Path(sys.argv[2])
fetch_url = sys.argv[3]
rev = sys.argv[4]
username = sys.argv[5]
devtype = sys.argv[6]
hostkey = sys.argv[7]
text = path.read_text()
def find_matching_brace(s: str, start: int) -> int:
depth = 0
i = start
in_str = False
while i < len(s):
ch = s[i]
if in_str:
if ch == '\\':
i += 2
continue
if ch == '"':
in_str = False
i += 1
continue
if ch == '"':
in_str = True
i += 1
continue
if ch == '{':
depth += 1
elif ch == '}':
depth -= 1
if depth == 0:
return i
i += 1
raise ValueError("Could not find matching '}'")
def mk_fetch(entry_indent: str) -> str:
# entry_indent is indentation for the whole `"key" = <here>;` line.
# The attrset contents should be indented one level deeper.
inner = entry_indent + " "
return (
'builtins.fetchGit {\n'
f'{inner}url = "{fetch_url}";\n'
f'{inner}rev = "{rev}";\n'
f'{inner}submodules = true;\n'
f'{entry_indent}}}'
)
def full_hostname(devtype: str, hostkey: str) -> str:
if hostkey.startswith(devtype) or "-" in hostkey:
return hostkey
if hostkey.isdigit():
return f"{devtype}{hostkey}"
return f"{devtype}-{hostkey}"
def update_user(t: str) -> str:
mblock = re.search(r"(?s)athenix\.users\s*=\s*\{(.*?)\n\s*\};", t)
if not mblock:
raise SystemExit("error: could not locate `athenix.users = { ... };` block")
# locate the full span of the users block to edit inside it
# (re-find with groups for reconstruction)
m2 = re.search(r"(?s)(athenix\.users\s*=\s*\{)(.*?)(\n\s*\};)", t)
head, body, tail = m2.group(1), m2.group(2), m2.group(3)
entry_re = re.search(
r"(?s)(\n[ \t]*" + re.escape(username) + r"\.external\s*=\s*)builtins\.fetchGit\s*\{",
body
)
if entry_re:
brace = body.rfind("{", 0, entry_re.end())
end = find_matching_brace(body, brace)
semi = re.match(r"\s*;", body[end+1:])
if not semi:
raise SystemExit("error: expected ';' after fetchGit attrset")
semi_end = end + 1 + semi.end()
line_start = body.rfind("\n", 0, entry_re.start()) + 1
indent = re.match(r"[ \t]*", body[line_start:entry_re.start()]).group(0)
new_body = body[:entry_re.start()] + entry_re.group(1) + mk_fetch(indent) + ";" + body[semi_end:]
else:
indent = " "
new_body = body + f"\n{indent}{username}.external = {mk_fetch(indent)};\n"
return t[:m2.start()] + head + new_body + tail + t[m2.end():]
def update_system(t: str) -> str:
# Find devtype block robustly: start-of-file or newline.
m = re.search(r"(?s)(^|\n)[ \t]*" + re.escape(devtype) + r"\s*=\s*\{", t)
if not m:
raise SystemExit(f"error: could not locate `{devtype} = {{ ... }};` block")
dev_open = t.find("{", m.end() - 1)
dev_close = find_matching_brace(t, dev_open)
dev = t[dev_open:dev_close+1]
# Find devices attrset inside dev
dm = re.search(r"(?s)(^|\n)[ \t]*devices\s*=\s*\{", dev)
if not dm:
raise SystemExit(f"error: could not locate `devices = {{ ... }};` inside `{devtype}`")
devices_open = dev.find("{", dm.end() - 1)
devices_close = find_matching_brace(dev, devices_open)
devices = dev[devices_open:devices_close+1]
# indentation for entries in devices
# find indent of the 'devices' line, then add 2 spaces
candidates = [hostkey, full_hostname(devtype, hostkey)]
seen = set()
candidates = [c for c in candidates if not (c in seen or seen.add(c))]
for key in candidates:
entry = re.search(
r'(?s)\n([ ]*)"' + re.escape(key) + r'"\s*=\s*builtins\.fetchGit\s*\{',
devices
)
if entry:
entry_indent = entry.group(1)
# find the '{' we matched
brace = devices.find("{", entry.end() - 1)
end = find_matching_brace(devices, brace)
semi = re.match(r"\s*;", devices[end+1:])
if not semi:
raise SystemExit("error: expected ';' after fetchGit attrset in devices")
semi_end = end + 1 + semi.end()
# Reconstruct the prefix: newline + indent + "key" =
prefix = f'\n{entry_indent}"{key}" = '
new_devices = (
devices[:entry.start()]
+ prefix
+ mk_fetch(entry_indent)
+ ";"
+ devices[semi_end:]
)
new_dev = dev[:devices_open] + new_devices + dev[devices_close+1:]
return t[:dev_open] + new_dev + t[dev_close+1:]
# Not found: append into devices (exact hostkey)
# Indent for new entries: take indent of the closing '}' of devices, add 2 spaces.
close_line_start = devices.rfind("\n", 0, len(devices)-1) + 1
close_indent = re.match(r"[ ]*", devices[close_line_start:]).group(0)
entry_indent = close_indent + " "
insertion = f'\n{entry_indent}"{hostkey}" = {mk_fetch(entry_indent)};\n'
new_devices = devices[:-1].rstrip() + insertion + close_indent + "}"
new_dev = dev[:devices_open] + new_devices + dev[devices_close+1:]
return t[:dev_open] + new_dev + t[dev_close+1:]
if mode == "user":
out = update_user(text)
elif mode == "system":
out = update_system(text)
else:
raise SystemExit("error: unknown mode")
path.write_text(out)
PY
cd $ATHENIX_DIR
nix fmt **/*.nix
cd $CUR_REPO_ROOT
printf "updated %s\n" "$FILE" >&2
printf " url = %s\n" "$FETCH_URL" >&2
printf " rev = %s\n" "$CUR_REV" >&2
'')
];
}

View File

@@ -8,7 +8,7 @@
with lib; with lib;
{ {
options.ugaif.sw.remoteBuild = lib.mkOption { options.athenix.sw.remoteBuild = lib.mkOption {
type = types.submodule { type = types.submodule {
options = { options = {
hosts = mkOption { hosts = mkOption {
@@ -29,19 +29,54 @@ with lib;
}; };
config = { config = {
ugaif.sw.remoteBuild.enable = lib.mkDefault (config.ugaif.sw.type == "tablet-kiosk"); athenix.sw.remoteBuild.enable = lib.mkDefault (config.athenix.sw.type == "tablet-kiosk");
environment.systemPackages = [ environment.systemPackages = [
(pkgs.writeShellScriptBin "update-system" '' (pkgs.writeShellScriptBin "update-system" ''
set -euo pipefail set -euo pipefail
RED='\033[31m'; NC='\033[0m'
is_root() { [ "''${EUID:-$(id -u)}" -eq 0 ]; }
in_wheel() { id -nG 2>/dev/null | tr ' ' '\n' | grep -qx wheel; }
# Service path for unprivileged (no flags)
UNIT="update-system.service" UNIT="update-system.service"
# Start following logs in the background # Figure out the "real" invoking user, even under sudo.
INVOKER_USER="''${SUDO_USER:-$(id -un)}"
INVOKER_HOME="$(getent passwd "$INVOKER_USER" | cut -d: -f6)"
if [ -z "$INVOKER_HOME" ]; then
# fallback if getent is weird in some containers
INVOKER_HOME="''${HOME:-/home/$INVOKER_USER}"
fi
# Defaults for flagged mode
DEFAULT_REMOTE_URL="https://git.factory.uga.edu/UGA-Innovation-Factory/athenix"
REPO_MODE="default" # default | local | remote
LOCAL_PATH=""
REMOTE_URL=""
BRANCH=""
IMPURE=0
usage() {
cat >&2 <<'EOF'
usage:
update-system
update-system [--local-repo[=PATH]] [--remote-repo=URL] [--branch=BRANCH] [--impure]
notes:
- No flags: runs the systemd service (works for unprivileged users via polkit).
- Any flags: only allowed for root or wheel (runs nixos-rebuild directly).
EOF
exit 2
}
# No flags -> polkit-friendly systemd service route
if [ "$#" -eq 0 ]; then
journalctl -fu "$UNIT" -n 0 --output=cat & journalctl -fu "$UNIT" -n 0 --output=cat &
JPID=$! JPID=$!
# Start the service and wait for it to finish
if systemctl start --wait --no-ask-password "$UNIT"; then if systemctl start --wait --no-ask-password "$UNIT"; then
STATUS=$? STATUS=$?
else else
@@ -49,11 +84,115 @@ with lib;
fi fi
sleep 2 sleep 2
# Kill the log follower
kill "$JPID" 2>/dev/null || true kill "$JPID" 2>/dev/null || true
exit "$STATUS" exit "$STATUS"
fi
# Flags -> require root or wheel
if ! is_root && ! in_wheel; then
printf "''${RED}error:''${NC} flags are only allowed for root or wheel. Run without flags (service path), or use sudo / add yourself to wheel.\n" >&2
exit 2
fi
# Parse flags
while [ "$#" -gt 0 ]; do
case "$1" in
--local-repo)
REPO_MODE="local"
LOCAL_PATH="$INVOKER_HOME/athenix"
shift
;;
--local-repo=*)
REPO_MODE="local"
LOCAL_PATH="''${1#*=}"
shift
;;
--remote-repo=*)
REPO_MODE="remote"
REMOTE_URL="''${1#*=}"
shift
;;
--branch)
[ "$#" -ge 2 ] || usage
BRANCH="$2"
shift 2
;;
--branch=*)
BRANCH="''${1#*=}"
shift
;;
--impure)
IMPURE=1
shift
;;
-h|--help) usage ;;
*)
printf "''${RED}error:''${NC} unknown argument: %s\n" "$1" >&2
usage
;;
esac
done
if [ "$REPO_MODE" = "local" ] && [ -n "$REMOTE_URL" ]; then
printf "''${RED}error:''${NC} can't use --local-repo and --remote-repo together.\n" >&2
exit 2
fi
host="''${HOSTNAME:-$(hostname)}"
# Build flake ref
if [ "$REPO_MODE" = "local" ]; then
[ -n "$LOCAL_PATH" ] || LOCAL_PATH="$INVOKER_HOME/athenix"
# Clone default repo if missing
if [ ! -d "$LOCAL_PATH" ]; then
printf "local repo not found at %s, cloning %s...\n" "$LOCAL_PATH" "$DEFAULT_REMOTE_URL" >&2
if [ -n "$BRANCH" ]; then
git clone --branch "$BRANCH" "$DEFAULT_REMOTE_URL" "$LOCAL_PATH"
else
git clone "$DEFAULT_REMOTE_URL" "$LOCAL_PATH"
fi
fi
flakeRef="''${LOCAL_PATH}#''${host}"
else
url="''${REMOTE_URL:-$DEFAULT_REMOTE_URL}"
if echo "$url" | grep -qE '^(https?|ssh)://'; then
base="git+''${url}"
elif echo "$url" | grep -qE '^[^/@:]+@[^/:]+:'; then
# scp-style: git@host:owner/repo(.git)
userhost="''${url%%:*}"
path="''${url#*:}"
base="git+ssh://''${userhost}/''${path}"
else
base="''${url}"
fi
if [ -n "$BRANCH" ]; then
if echo "$base" | grep -q '?'; then
base="''${base}&ref=''${BRANCH}"
else
base="''${base}?ref=''${BRANCH}"
fi
fi
flakeRef="''${base}#''${host}"
fi
impureFlag=""
if [ "$IMPURE" -eq 1 ]; then
impureFlag="--impure"
fi
# If not root, re-exec via sudo to do the actual switch.
# Preserve our computed invoker context so sudo doesn't "helpfully" change it.
if ! is_root; then
exec sudo --preserve-env=HOME,USER,LOGNAME \
nixos-rebuild switch --refresh --print-build-logs $impureFlag --flake "$flakeRef"
else
exec nixos-rebuild switch --refresh --print-build-logs $impureFlag --flake "$flakeRef"
fi
'') '')
]; ];
@@ -69,11 +208,12 @@ with lib;
Type = "oneshot"; Type = "oneshot";
ExecStart = ExecStart =
let let
hosts = config.ugaif.sw.remoteBuild.hosts; hosts = config.athenix.sw.remoteBuild.hosts;
builders = lib.strings.concatMapStringsSep ";" (x: x) hosts; builders = lib.strings.concatMapStringsSep ";" (x: x) hosts;
rebuildCmd = "${pkgs.nixos-rebuild}/bin/nixos-rebuild switch --refresh"; rebuildCmd = "${pkgs.nixos-rebuild}/bin/nixos-rebuild switch --refresh";
source = "--flake github:UGA-Innovation-Factory/nixos-systems"; source = "--flake git+https://git.factory.uga.edu/UGA-Innovation-Factory/athenix";
remoteBuildFlags = if config.ugaif.sw.remoteBuild.enable then ''--builders "${builders}"'' else ""; remoteBuildFlags =
if config.athenix.sw.remoteBuild.enable then ''--builders "${builders}"'' else "";
in in
"${rebuildCmd} ${remoteBuildFlags} --print-build-logs ${source}#${config.networking.hostName}"; "${rebuildCmd} ${remoteBuildFlags} --print-build-logs ${source}#${config.networking.hostName}";
User = "root"; User = "root";

View File

@@ -20,7 +20,7 @@
user = { user = {
path = ./user; path = ./user;
description = "External user home-manager configuration"; description = "External user configuration module";
welcomeText = '' welcomeText = ''
# User Configuration Template # User Configuration Template
@@ -29,10 +29,10 @@
## Quick Start ## Quick Start
1. Edit `home.nix` with your home-manager configuration 1. Edit `user.nix` with user account options and home-manager configuration
2. (Optional) Edit `nixos.nix` for system-level configuration 2. (Optional) Edit `nixos.nix` for system-level configuration
3. Commit to a Git repository 3. Commit to a Git repository
4. Reference in users.nix using the `flakeUrl` field 4. Reference in users.nix using external = builtins.fetchGit { ... }
See README.md for detailed documentation. See README.md for detailed documentation.
''; '';

View File

@@ -94,6 +94,6 @@ Your `default.nix` must:
External modules are automatically integrated into the nixos-systems build: External modules are automatically integrated into the nixos-systems build:
- They receive the same flake inputs (nixpkgs, home-manager, etc.) - They receive the same flake inputs (nixpkgs, home-manager, etc.)
- They can use ugaif.* options if defined in the host type - They can use athenix.* options if defined in the host type
- They are merged with local overrides and base configuration - They are merged with local overrides and base configuration
- They work with all build methods (ISO, LXC, Proxmox, etc.) - They work with all build methods (ISO, LXC, Proxmox, etc.)

View File

@@ -50,7 +50,7 @@
# Example: Configure services # Example: Configure services
# services.openssh.enable = true; # services.openssh.enable = true;
# Example: Use ugaif options if available from nixos-systems # Example: Use athenix options if available from nixos-systems
# ugaif.users.myuser.enable = true; # athenix.users.myuser.enable = true;
}; };
} }

View File

@@ -10,46 +10,47 @@ External user modules allow users to maintain their personal configurations (dot
``` ```
user-dotfiles-repo/ user-dotfiles-repo/
├── user.nix # Optional: User options AND home-manager configuration ├── user.nix # Required: User options AND home-manager configuration
├── nixos.nix # Optional: System-level NixOS configuration ├── nixos.nix # Optional: System-level NixOS configuration
├── README.md # Documentation ├── README.md # Documentation
└── dotfiles/ # Optional: Dotfiles to symlink └── config/ # Optional: Dotfiles to symlink
├── bashrc
└── vimrc
``` ```
**Note:** Both `.nix` files are optional, but at least one should be present for the module to be useful. **Note:** The `user.nix` file is required for a functional user module. It should contain both `athenix.users.<username>` options and home-manager configuration.
## Usage ## Usage
### 1. Create Your User Configuration Repository ### 1. Create Your User Configuration Repository
Copy the templates from this directory to your own Git repository: Copy the templates from this directory to your own Git repository:
- `home.nix` - Required for home-manager configuration - `user.nix` - Required: Contains both user account options and home-manager configuration
- `nixos.nix` - Optional for system-level configuration - `nixos.nix` - Optional: System-level NixOS configuration (e.g., system services, extra groups)
### 2. Reference It in users.nix ### 2. Reference It in users.nix
```nix ```nix
{ {
ugaif.users = { athenix.users = {
myusername = { # Option 1: Define inline (without external module)
# Option 1: Set user options in users.nix inlineuser = {
description = "My Name"; description = "My Name";
extraGroups = [ "wheel" "networkmanager" ]; extraGroups = [ "wheel" "networkmanager" ];
shell = pkgs.zsh; shell = pkgs.zsh;
hashedPassword = "$6$...";
};
# Option 2: Or let the external module's user.nix set these options # Option 2: Use external module (recommended for personal configs)
# The external user.nix will set athenix.users.myusername options
# Reference external dotfiles module myusername.external = builtins.fetchGit {
external = builtins.fetchGit {
url = "https://github.com/username/dotfiles"; url = "https://github.com/username/dotfiles";
rev = "abc123def456..."; # Full commit hash for reproducibility rev = "abc123def456..."; # Full commit hash for reproducibility
ref = "main"; # Optional: branch/tag name ref = "main"; # Optional: branch/tag name
}; };
# Or use local path for testing # Or use local path for testing
# external = /path/to/local/dotfiles; # myusername.external = /path/to/local/dotfiles;
# };
};
}; };
} }
``` ```
@@ -63,7 +64,7 @@ Enable the user in `inventory.nix`:
"my-system" = { "my-system" = {
devices = { devices = {
"hostname" = { "hostname" = {
ugaif.users.myusername.enable = true; athenix.users.myusername.enable = true;
}; };
}; };
}; };
@@ -72,30 +73,26 @@ Enable the user in `inventory.nix`:
## File Descriptions ## File Descriptions
### user.nix (Optional) ### user.nix (Required)
This file serves dual purpose: This file serves a dual purpose and is imported in **two contexts**:
1. Sets `ugaif.users.<username>` options (description, shell, extraGroups, etc.)
2. Provides home-manager configuration (programs.*, home.*, services.*) 1. **NixOS Module Context**: Imported to read `athenix.users.<username>` options that define the user account (description, shell, groups, SSH keys, etc.)
2. **Home-Manager Context**: Imported to configure the user environment with `home.*`, `programs.*`, and `services.*` options
**How it works:** **How it works:**
- The `ugaif.users.<username>` options are extracted and loaded as **data** during module evaluation - The same file is evaluated twice in different contexts
- These options override any defaults set in `users.nix` (which uses `lib.mkDefault`) - User account options (`athenix.users.<username>`) are read during NixOS evaluation
- The home-manager options (`home.*`, `programs.*`, etc.) are imported as a module for home-manager - Home-manager options are used when building the user's environment
- External module options take precedence over `users.nix` base configuration - External module options override any defaults set in `users.nix`
- You can conditionally include packages/config based on system type using `osConfig`
The same file is imported in two contexts:
- As a NixOS module to read ugaif.users options
- As a home-manager module for home.*, programs.*, services.*, etc.
Simply include both types of options in the same file.
**Receives:** **Receives:**
- `inputs` - Flake inputs (nixpkgs, home-manager, etc.) - `inputs` - Flake inputs (nixpkgs, home-manager, etc.)
- `config` - Config (NixOS or home-manager depending on context) - `config` - Configuration (NixOS or home-manager depending on context)
- `lib` - Nixpkgs library - `lib` - Nixpkgs library functions
- `pkgs` - Nixpkgs package set - `pkgs` - Nixpkgs package set
- `osConfig` - (home-manager context only) OS-level configuration - `osConfig` - (home-manager context only) Read-only access to OS configuration
**Example:** See `user.nix` template **Example:** See `user.nix` template
@@ -118,17 +115,20 @@ This file contains system-level NixOS configuration. Only needed for:
```nix ```nix
{ inputs, ... }: { inputs, ... }:
{ config, lib, pkgs, ... }: { config, lib, pkgs, osConfig ? null, ... }:
{ {
# User account options (imported as NixOS module) # User account options
ugaif.users.myuser = { athenix.users.myuser = {
description = "My Name"; description = "My Name";
shell = pkgs.zsh; shell = pkgs.zsh;
hashedPassword = "!";
extraGroups = [ "wheel" "networkmanager" ]; extraGroups = [ "wheel" "networkmanager" ];
opensshKeys = [ "ssh-ed25519 AAAA... user@host" ];
useZshTheme = true;
useNvimPlugins = true;
}; };
# Home-manager configuration (imported into home-manager) # Home-manager configuration
home.packages = with pkgs; [ home.packages = with pkgs; [
vim vim
git git
@@ -139,6 +139,7 @@ This file contains system-level NixOS configuration. Only needed for:
enable = true; enable = true;
userName = "My Name"; userName = "My Name";
userEmail = "me@example.com"; userEmail = "me@example.com";
extraConfig.init.defaultBranch = "main";
}; };
} }
``` ```
@@ -147,24 +148,31 @@ This file contains system-level NixOS configuration. Only needed for:
```nix ```nix
{ inputs, ... }: { inputs, ... }:
{ config, lib, pkgs, ... }: { config, lib, pkgs, osConfig ? null, ... }:
{ {
ugaif.users.myuser = { athenix.users.myuser = {
description = "My Name"; description = "My Name";
shell = pkgs.zsh; shell = pkgs.zsh;
hashedPassword = "!";
extraGroups = [ "wheel" ];
opensshKeys = [ "ssh-ed25519 AAAA..." ];
}; };
home.packages = with pkgs; [ ripgrep fd bat ]; home.packages = with pkgs; [
ripgrep
fd
bat
] ++ lib.optional (osConfig.athenix.sw.type or null == "desktop") firefox;
# Symlink dotfiles # Symlink dotfiles
home.file.".bashrc".source = ./dotfiles/bashrc; home.file.".bashrc".source = ./config/bashrc;
home.file.".vimrc".source = ./dotfiles/vimrc; home.file.".vimrc".source = ./config/vimrc;
programs.git = { programs.git = {
enable = true; enable = true;
userName = "My Name"; userName = "My Name";
userEmail = "me@example.com"; userEmail = "me@example.com";
extraConfig.init.defaultBranch = "main";
}; };
} }
``` ```
@@ -189,11 +197,13 @@ This file contains system-level NixOS configuration. Only needed for:
External user modules: External user modules:
- Receive the same flake inputs as nixos-systems - Receive the same flake inputs as nixos-systems
- Can set user options via user.nix (description, shell, home-manager, etc.) - Define both user account options AND home-manager config in user.nix
- Single file is imported in two contexts (NixOS module + home-manager module)
- Can access OS configuration via `osConfig` parameter in home-manager context
- Optionally provide system-level configuration (nixos.nix) - Optionally provide system-level configuration (nixos.nix)
- System zsh theme applied if `useZshTheme = true` (default) - System zsh theme applied if `useZshTheme = true` (default)
- System nvim config applied if `useNvimPlugins = true` (default) - System nvim config applied if `useNvimPlugins = true` (default)
- Settings from user.nix override base users.nix definitions - Settings from external user.nix override base users.nix definitions
## Development Workflow ## Development Workflow

View File

@@ -4,16 +4,15 @@
# User NixOS System Configuration (Optional) # User NixOS System Configuration (Optional)
# ============================================================================ # ============================================================================
# This file provides system-level NixOS configuration for a user. # This file provides system-level NixOS configuration for a user.
# It's optional - most user configuration should go in home.nix. # It's optional - most user configuration should go in user.nix.
# #
# Use this for: # Use this for:
# - System-level services that depend on the user (e.g., user systemd services) # - System-level services that depend on the user (e.g., user systemd services)
# - Special system permissions or configurations # - Special system permissions or configurations
# - Installing system packages that require root # - Installing system packages that require root
# #
# Note: User options (description, shell, extraGroups, etc.) should be set # Note: User options (description, shell, extraGroups, etc.) AND home-manager
# in your external module's user.nix or in the main users.nix file, not in # configuration should be set in user.nix, not in this nixos.nix.
# this nixos.nix.
# #
# This module receives the same `inputs` flake inputs as the main # This module receives the same `inputs` flake inputs as the main
# nixos-systems configuration. # nixos-systems configuration.
@@ -47,5 +46,5 @@
# Example: Add user to additional groups # Example: Add user to additional groups
# users.users.myusername.extraGroups = [ "docker" ]; # users.users.myusername.extraGroups = [ "docker" ];
# Most configuration should be in home.nix instead of here # Most configuration should be in user.nix instead of here
} }

View File

@@ -1,16 +1,15 @@
{ inputs, ... }: { inputs, ... }:
# ============================================================================ # ============================================================================
# User Configuration (Optional) # User Configuration
# ============================================================================ # ============================================================================
# This file can configure BOTH: # This file configures BOTH:
# 1. User account options (ugaif.users.<username>) when imported as NixOS module # 1. User account options (athenix.users.<username>)
# 2. Home-manager configuration (home.*, programs.*, services.*) when imported # 2. Home-manager configuration (home.*, programs.*, services.*)
# into home-manager
# #
# This file is optional - if not present, the system will use the defaults # The same file is imported in two contexts:
# from the main users.nix file. Use this file to override or extend those # - As a NixOS module to read athenix.users.<username> options
# default user and home-manager options for this user. # - As a home-manager module for user environment configuration
# #
# This module receives the same `inputs` flake inputs as the main # This module receives the same `inputs` flake inputs as the main
# nixos-systems configuration (nixpkgs, home-manager, etc.). # nixos-systems configuration (nixpkgs, home-manager, etc.).
@@ -25,11 +24,12 @@
{ {
# ========== User Account Configuration ========== # ========== User Account Configuration ==========
# These are imported as a NixOS module to set ugaif.users options
# Replace "myusername" with your actual username # Replace "myusername" with your actual username
ugaif.users.myusername = { athenix.users.myusername = {
description = "Your Full Name"; description = "Your Full Name";
shell = pkgs.zsh;
hashedPassword = "!"; # Locked password - use SSH keys only
extraGroups = [ extraGroups = [
"wheel" # Sudo access "wheel" # Sudo access
@@ -37,33 +37,31 @@
# "docker" # Docker access (if needed) # "docker" # Docker access (if needed)
]; ];
shell = pkgs.zsh; opensshKeys = [
# Add your SSH public keys here
# "ssh-ed25519 AAAA... user@machine"
];
# Optional: Override editor useZshTheme = true; # Apply system Zsh theme
# editor = pkgs.helix; useNvimPlugins = true; # Apply system Neovim plugins
# Optional: Disable system theme/nvim plugins
# useZshTheme = false;
# useNvimPlugins = false;
# Optional: Add system-level packages
# extraPackages = with pkgs; [ docker ];
}; };
# Note: You don't need to set 'enable = true' - that's controlled # Note: You don't need to set 'enable = true' - that's controlled
# per-host in inventory.nix # per-host in inventory.nix via athenix.users.myusername.enable
# ========== Home Manager Configuration ========== # ========== Home Manager Configuration ==========
# These are imported into home-manager for user environment
# System theme (zsh) and nvim config are applied automatically based on flags above
# Packages # Packages
home.packages = with pkgs; [ home.packages =
# Add your preferred packages here with pkgs;
# ripgrep [
# fd htop
# bat ripgrep
]; fd
bat
]
++ lib.optional (osConfig.athenix.sw.type or null == "desktop") firefox;
# Conditionally add packages based on system type
# ========== Programs ========== # ========== Programs ==========
@@ -77,18 +75,28 @@
}; };
}; };
# Zsh configuration
programs.zsh = {
enable = true;
# System theme is applied automatically if useZshTheme = true
};
# ========== Shell Environment ========== # ========== Shell Environment ==========
home.sessionVariables = { home.sessionVariables = {
# EDITOR is set automatically based on ugaif.users.*.editor EDITOR = "nvim";
# Add your custom environment variables here # Add your custom environment variables here
}; };
# ========== XDG Configuration ==========
xdg.enable = true;
# ========== Dotfiles ========== # ========== Dotfiles ==========
# You can manage dotfiles with home.file # You can manage dotfiles with home.file
# home.file.".bashrc".source = ./dotfiles/bashrc; # home.file.".bashrc".source = ./config/bashrc;
# home.file.".vimrc".source = ./dotfiles/vimrc; # home.file.".vimrc".source = ./config/vimrc;
# Or use programs.* options for better integration # Or use programs.* options for better integration (recommended)
} }

View File

@@ -5,7 +5,7 @@
# ============================================================================ # ============================================================================
# This file defines the available user accounts. These accounts are NOT # This file defines the available user accounts. These accounts are NOT
# enabled by default on all systems. They must be enabled via the # enabled by default on all systems. They must be enabled via the
# 'ugaif.users.enabledUsers' option in inventory.nix or system flakes. # 'athenix.users.enabledUsers' option in inventory.nix or system flakes.
# Define the users here using the new option # Define the users here using the new option
# To generate a password hash, run: mkpasswd -m sha-512 # To generate a password hash, run: mkpasswd -m sha-512
@@ -16,12 +16,17 @@
# external = builtins.fetchGit { url = "..."; rev = "..."; }; # external = builtins.fetchGit { url = "..."; rev = "..."; };
# external = /path/to/local/config; # external = /path/to/local/config;
# #
# External repositories can contain: # External repositories should contain:
# - user.nix (optional): Sets ugaif.users.<name> options AND home-manager config # - user.nix (required): Defines athenix.users.<name> options AND home-manager config
# - nixos.nix (optional): System-level NixOS configuration # - nixos.nix (optional): System-level NixOS configuration
# #
# User options can be set either in users.nix OR in the external module's user.nix. # The user.nix file is imported in TWO contexts:
ugaif.users = { # 1. As a NixOS module to read athenix.users.<name> options (account settings)
# 2. As a home-manager module for home.*, programs.*, services.* (user environment)
#
# User options can be set in users.nix OR in the external module's user.nix.
# External module options take precedence over users.nix defaults.
athenix.users = {
root = { root = {
isNormalUser = false; isNormalUser = false;
hashedPassword = "!"; hashedPassword = "!";
@@ -44,7 +49,7 @@
hdh20267 = { hdh20267 = {
external = builtins.fetchGit { external = builtins.fetchGit {
url = "https://git.factory.uga.edu/hdh20267/hdh20267-nix"; url = "https://git.factory.uga.edu/hdh20267/hdh20267-nix";
rev = "db96137bb4cb16acefcf59d58c9f848924f2ad43"; rev = "c538e0c0510045b58264627bb897fc499dc7c490";
}; };
}; };
sv22900 = { sv22900 = {