Archived
Compare commits
334
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71d052e737 | ||
|
|
e76486efbe | ||
|
|
302c3b671f | ||
|
|
0900ff25ae | ||
|
|
79d2ed0314 | ||
|
|
8932e52d72 | ||
|
|
4822f0b290 | ||
|
|
f8de4c8abc | ||
|
|
ca18a9d29d | ||
|
|
7d113e302f | ||
|
|
bc68d8cf17 | ||
|
|
4728982c05 | ||
|
|
8734b23746 | ||
|
|
5f52cb0cd7 | ||
|
|
f4139eec13 | ||
|
|
afc57e3755 | ||
|
|
d7cad12720 | ||
|
|
bab83d1aad | ||
|
|
da0cd225be | ||
|
|
de4b4302c9 | ||
|
|
45fe770569 | ||
|
|
3797c8885e | ||
|
|
2fb6b1de00 | ||
|
|
a2f817b098 | ||
|
|
d9015e87d3 | ||
|
|
5dc41e2866 | ||
|
|
0aae9c3bcf | ||
|
|
2a426615cb | ||
|
|
7be80e7ab6 | ||
|
|
d8d2718289 | ||
|
|
e577fda538 | ||
|
|
ffd2705ee3 | ||
|
|
54e11853b5 | ||
|
|
5fcaa6ae87 | ||
|
|
a5ef1aa519 | ||
|
|
a919252a47 | ||
|
|
3fda26e46c | ||
|
|
d48e4d4f10 | ||
|
|
d5c13bc2d2 | ||
|
|
fe83640776 | ||
|
|
03066d716d | ||
|
|
bcf57246e0 | ||
|
|
9fb6d9da13 | ||
|
|
24dd5adfed | ||
|
|
489ed11406 | ||
|
|
f77a26402f | ||
|
|
9eb219360e | ||
|
|
a3fe69a89c | ||
|
|
aa7a98f884 | ||
|
|
af48b1aef6 | ||
|
|
33522a4613 | ||
|
|
217564ffc4 | ||
|
|
8e571c7592 | ||
|
|
7ea203e22d | ||
|
|
567e2536b1 | ||
|
|
f3c6f13e89 | ||
|
|
b9b3d06810 | ||
|
|
efa0ee26fe | ||
|
|
0c68f54e1f | ||
|
|
c9b449d60e | ||
|
|
a495de3f83 | ||
|
|
6cc79e0c36 | ||
|
|
4078230052 | ||
|
|
06dc25c983 | ||
|
|
aa2af2d169 | ||
|
|
1788faf093 | ||
|
|
33584d9a02 | ||
|
|
b25d9db82b | ||
|
|
94df02515d | ||
|
|
8b49deb1d7 | ||
|
|
fac343fa76 | ||
|
|
9f59ed4426 | ||
|
|
1f2dc03486 | ||
|
|
da75a23700 | ||
|
|
3d42dee0bf | ||
|
|
9fef163850 | ||
|
|
c64e4ad7d5 | ||
|
|
aeaa1f6479 | ||
|
|
bca8c2f9df | ||
|
|
153b2f0cfa | ||
|
|
c1ba633bff | ||
|
|
62edbd203d | ||
|
|
fa3d91303c | ||
|
|
59a01b35bf | ||
|
|
cf78588f00 | ||
|
|
7156c343bb | ||
|
|
32b65b0894 | ||
|
|
5046cae7b1 | ||
|
|
0286bb4dfa | ||
|
|
cf9bb14d4b | ||
|
|
6d53a62f85 | ||
|
|
4bf1ec450a | ||
|
|
8bafae6eb2 | ||
|
|
32323aee06 | ||
|
|
bd117a8dd5 | ||
|
|
12f6703e0f | ||
|
|
56bf912c4d | ||
|
|
0649c48b96 | ||
|
|
d871f2a45d | ||
|
|
74bdbd8c9a | ||
|
|
258d471b21 | ||
|
|
a86300f094 | ||
|
|
f8886b2215 | ||
|
|
e538222c24 | ||
|
|
004529aa88 | ||
|
|
35352cc9b2 | ||
|
|
70d459de15 | ||
|
|
60886c6a64 | ||
|
|
564f8548ec | ||
|
|
36c3c48474 | ||
|
|
c29d8f9df7 | ||
|
|
b82c868b7a | ||
|
|
6f6e9a5a11 | ||
|
|
1b588d0ea0 | ||
|
|
3212d80b63 | ||
|
|
e28d953b8d | ||
|
|
566135bbbb | ||
|
|
8af805241e | ||
|
|
d3c26d7e9e | ||
|
|
63f5acb18f | ||
|
|
074ed2cbe1 | ||
|
|
1cb6bdae2f | ||
|
|
bf74783623 | ||
|
|
c31606922e | ||
|
|
a2f2af77b6 | ||
|
|
7aa4c56660 | ||
|
|
100923e1a9 | ||
|
|
0e105923da | ||
|
|
2d1cd0674c | ||
|
|
abd0b83cb2 | ||
|
|
6ad9b5ffa4 | ||
|
|
88a9d4dd78 | ||
|
|
472c18922c | ||
|
|
33cd951205 | ||
|
|
903e5243a7 | ||
|
|
3c5081506b | ||
|
|
edb898d27b | ||
|
|
c32341b2d5 | ||
|
|
745bbe0732 | ||
|
|
48c5e5c094 | ||
|
|
287f42cd81 | ||
|
|
8434e90aec | ||
|
|
5141123b34 | ||
|
|
84488de426 | ||
|
|
ed2d86bead | ||
|
|
1b6ffd9117 | ||
|
|
bd9aef4624 | ||
|
|
16d345262d | ||
|
|
ee30e40ce4 | ||
|
|
79d24c7497 | ||
|
|
dcf1c8e780 | ||
|
|
27470bd854 | ||
|
|
72b58093b1 | ||
|
|
688904321a | ||
|
|
2fb0928ff5 | ||
|
|
d424a70110 | ||
|
|
60faf681b3 | ||
|
|
4fb1a6a204 | ||
|
|
a61f88d4a3 | ||
|
|
923ac6c178 | ||
|
|
cc986d1ab7 | ||
|
|
1fd0adee54 | ||
|
|
b0d480adb8 | ||
|
|
e78dd516a6 | ||
|
|
4e30618954 | ||
|
|
3259391451 | ||
|
|
31b57930c6 | ||
|
|
0e29abd0ac | ||
|
|
038103391d | ||
|
|
7f719eb6a9 | ||
|
|
47fdce6193 | ||
|
|
e68b4f8d14 | ||
|
|
c47052fc21 | ||
|
|
59a2e65bf5 | ||
|
|
4a928707f6 | ||
|
|
5be2bdb170 | ||
|
|
4abe01c0cb | ||
|
|
d838784dd5 | ||
|
|
e95a4b5f4d | ||
|
|
247d8fc96b | ||
|
|
5f63a48731 | ||
|
|
8d26f62b57 | ||
|
|
089190ef23 | ||
|
|
d36380b79a | ||
|
|
8dd20f6ced | ||
|
|
926df3d334 | ||
|
|
26eec71b8c | ||
|
|
554f484593 | ||
|
|
7de7c76597 | ||
|
|
a36805d8dd | ||
|
|
0e244b2bc7 | ||
|
|
61f8ffb35e | ||
|
|
b5c8e43688 | ||
|
|
bd674bc5d9 | ||
|
|
97fceee985 | ||
|
|
0fe04bd956 | ||
|
|
6862fb6455 | ||
|
|
4632c14191 | ||
|
|
54b795aba8 | ||
|
|
a0cc52c3cc | ||
|
|
0cdeba3b7a | ||
|
|
4bf0e14663 | ||
|
|
4444f4e70d | ||
|
|
4b4b7834d6 | ||
|
|
4ddef559a4 | ||
|
|
33b596d254 | ||
|
|
105d20b94c | ||
|
|
7d88bb7332 | ||
|
|
0711d0aae6 | ||
|
|
d08f55af3a | ||
|
|
03cd8e5755 | ||
|
|
3b15296cf0 | ||
|
|
aba8f7605d | ||
|
|
7880f54068 | ||
|
|
d4e67d5785 | ||
|
|
a73061909e | ||
|
|
d07236986c | ||
|
|
667348bc98 | ||
|
|
c5509c420b | ||
|
|
f1dcabd579 | ||
|
|
ca5914062e | ||
|
|
025937ec6d | ||
|
|
4594242d1d | ||
|
|
832e2bb39d | ||
|
|
b7f5ae83cb | ||
|
|
2dc246b4ec | ||
|
|
9deddd14e6 | ||
|
|
10ca67ac23 | ||
|
|
e4f726839f | ||
|
|
fb9f6185ec | ||
|
|
a4e303fa34 | ||
|
|
c3259ad3a2 | ||
|
|
fd2d9d8aeb | ||
|
|
bbaf012329 | ||
|
|
e18b3bb76e | ||
|
|
df6515ad6a | ||
|
|
c731705075 | ||
|
|
aa376a2448 | ||
|
|
141491233c | ||
|
|
3d6b55df79 | ||
|
|
84cd3a1a83 | ||
|
|
60f17723ba | ||
|
|
da267255b0 | ||
|
|
17b45fd23e | ||
|
|
9cb5f9627c | ||
|
|
25b4c6cdd2 | ||
|
|
9575986b93 | ||
|
|
15f90bc2f2 | ||
|
|
119be5aca0 | ||
|
|
84a9a12f4d | ||
|
|
f979f61be1 | ||
|
|
b455028547 | ||
|
|
c424cb1cb0 | ||
|
|
9d0b736a51 | ||
|
|
7a590a2d99 | ||
|
|
513c286a4a | ||
|
|
5e778c9045 | ||
|
|
274544a212 | ||
|
|
859f30a56c | ||
|
|
0b91b68333 | ||
|
|
27122baec0 | ||
|
|
0a8af8d8e4 | ||
|
|
2ca2f74bbc | ||
|
|
fa9c3f5572 | ||
|
|
be8fefd9f8 | ||
|
|
79fb3799a9 | ||
|
|
bb1a4d8a3e | ||
|
|
f5dcb13b86 | ||
|
|
41a6800c58 | ||
|
|
f9a6ada47b | ||
|
|
941aff5048 | ||
|
|
ccf11fa673 | ||
|
|
d42336b288 | ||
|
|
66453b3396 | ||
|
|
a4fc3d9b3b | ||
|
|
66d8680b26 | ||
|
|
ac21c48b52 | ||
|
|
d4d1fc795b | ||
|
|
a4566a6f80 | ||
|
|
551cf90cdd | ||
|
|
8e896e9067 | ||
|
|
b3bc217586 | ||
|
|
59f75cd31c | ||
|
|
cdfe2943ed | ||
|
|
c3ed7ccf46 | ||
|
|
61bd88fd15 | ||
|
|
b7d572c40e | ||
|
|
431f769af8 | ||
|
|
1f8dfe54da | ||
|
|
66ab3a3977 | ||
|
|
264dae9a92 | ||
|
|
da55436abb | ||
|
|
fbd36b28ea | ||
|
|
a93fe3cc3c | ||
|
|
ad82ffcfc1 | ||
|
|
4f4699d334 | ||
|
|
8667552141 | ||
|
|
059dd4c333 | ||
|
|
3c3d6ccfa7 | ||
|
|
075d1f77b7 | ||
|
|
1241a8e9ae | ||
|
|
ddfcaa0c68 | ||
|
|
49f0a156c3 | ||
|
|
f6a1bdb0cf | ||
|
|
d5d83c78e1 | ||
|
|
f385a420db | ||
|
|
b3eed0d061 | ||
|
|
7cb3429139 | ||
|
|
b3c2033fb2 | ||
|
|
ad4f69c05e | ||
|
|
bc29cfc5ef | ||
|
|
d9f520c959 | ||
|
|
7d155d6413 | ||
|
|
1a742a35c6 | ||
|
|
5ef1bef1c0 | ||
|
|
7f5d03c06c | ||
|
|
0e650af351 | ||
|
|
b4cdf89e71 | ||
|
|
9a65f15b58 | ||
|
|
1da2471a4a | ||
|
|
e171715448 | ||
|
|
3c8c57d2f9 | ||
|
|
175ea8c7c9 | ||
|
|
54dbee8543 | ||
|
|
29a5c6c4e8 | ||
|
|
9b9ec47150 | ||
|
|
8e08a5adef | ||
|
|
3eff3b000b | ||
|
|
ac40a14d79 | ||
|
|
f81abfb31d | ||
|
|
28db091ea0 | ||
|
|
8e9ba91536 | ||
|
|
fee0f1ef14 | ||
|
|
b80550d91b |
@@ -0,0 +1,29 @@
|
||||
name: Check NixOS configurations
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
eval-hosts:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@v19
|
||||
|
||||
- name: Evaluate all NixOS hosts
|
||||
run: |
|
||||
set -euo pipefail
|
||||
hosts="$(nix --extra-experimental-features 'nix-command flakes' eval --json \
|
||||
.#nixosConfigurations --apply builtins.attrNames | jq -r '.[]')"
|
||||
for host in $hosts; do
|
||||
echo "Evaluating ${host}"
|
||||
nix --extra-experimental-features 'nix-command flakes' eval \
|
||||
".#nixosConfigurations.${host}.config.system.build.toplevel.drvPath" --raw
|
||||
done
|
||||
@@ -0,0 +1,32 @@
|
||||
name: Update flake.lock
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 6 * * 1"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update-flake-lock:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@v19
|
||||
|
||||
- name: Update and commit flake.lock
|
||||
run: |
|
||||
set -euo pipefail
|
||||
nix --extra-experimental-features 'nix-command flakes' flake update
|
||||
|
||||
if git diff --quiet -- flake.lock; then
|
||||
echo "No flake.lock changes detected"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
git config user.name "gitea-actions"
|
||||
git config user.email "gitea-actions@nix-cache.local"
|
||||
git add flake.lock
|
||||
git commit -m "chore: update flake.lock"
|
||||
git push
|
||||
Executable
+11
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
# Blocks commits containing secrets. Installed via:
|
||||
# git config core.hooksPath .githooks
|
||||
# (scripts/codex-setup.sh does this automatically in Codex sessions.)
|
||||
set -euo pipefail
|
||||
|
||||
if command -v gitleaks >/dev/null 2>&1; then
|
||||
gitleaks protect --staged -v
|
||||
else
|
||||
nix-shell -p gitleaks --run "gitleaks protect --staged -v"
|
||||
fi
|
||||
@@ -0,0 +1,29 @@
|
||||
name: Check NixOS configurations
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
eval-hosts:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@v19
|
||||
|
||||
- name: Evaluate all NixOS hosts
|
||||
run: |
|
||||
set -euo pipefail
|
||||
hosts="$(nix --extra-experimental-features 'nix-command flakes' eval --json \
|
||||
.#nixosConfigurations --apply builtins.attrNames | jq -r '.[]')"
|
||||
for host in $hosts; do
|
||||
echo "Evaluating ${host}"
|
||||
nix --extra-experimental-features 'nix-command flakes' eval \
|
||||
".#nixosConfigurations.${host}.config.system.build.toplevel.drvPath" --raw
|
||||
done
|
||||
@@ -0,0 +1,37 @@
|
||||
name: Update flake.lock
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "0 6 * * 1"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update-flake-lock:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Nix
|
||||
uses: DeterminateSystems/nix-installer-action@v19
|
||||
|
||||
- name: Update flake.lock
|
||||
run: |
|
||||
nix --extra-experimental-features 'nix-command flakes' flake update
|
||||
|
||||
- name: Create pull request
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
add-paths: flake.lock
|
||||
branch: chore/update-flake-lock
|
||||
title: "chore: update flake.lock"
|
||||
commit-message: "chore: update flake.lock"
|
||||
body: |
|
||||
This is an automated update of `flake.lock` generated by the scheduled workflow.
|
||||
|
||||
It updates pinned flake inputs so dependency updates can be reviewed and merged via PR.
|
||||
@@ -6,3 +6,10 @@ result-*
|
||||
# Ignore automatically generated direnv output
|
||||
.direnv
|
||||
|
||||
auto-installer/flake.lock
|
||||
auto-installer/result
|
||||
auto-installer/nixos-auto.iso
|
||||
|
||||
# Temporary Milestone 1 audit checklist (remove-sensetive-info-refactor.md)
|
||||
# - working notes only, never committed, deleted once every row is rotated.
|
||||
secrets-inventory.md
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
keys:
|
||||
- &admin age10nd382a9klsn2mrs60emdtsxe43pht3a0m9p29phfrhy0wfyt3vsq9r667
|
||||
- &docker age19gfn2yedg76dmztm4hncr7vf3r3c9j0qpt4rap7y7gersjk4m3ks2lhd0e
|
||||
- &server age1ll6hj5ggruetgjwjfnplpn5xtq35uhlcdflksx3xmnjm6s3uad9sz70jkf
|
||||
- &nix-cache age120le4a5l8dh3lyfgvmj3d9ksmej6ajs5mer5y7r0vfg3x9fn69dqf8xgzu
|
||||
|
||||
creation_rules:
|
||||
# Shared across every currently-deployed host: root/nixos password hash,
|
||||
# GitHub access token. Same value on every host today, so every live host's
|
||||
# key can decrypt it (matches current risk profile — narrow further in
|
||||
# Milestone 4 if hosts should diverge).
|
||||
- path_regex: secrets/common\.yaml$
|
||||
key_groups:
|
||||
- age:
|
||||
- *admin
|
||||
- *docker
|
||||
- *server
|
||||
- *nix-cache
|
||||
|
||||
- path_regex: secrets/nix-cache\.yaml$
|
||||
key_groups:
|
||||
- age:
|
||||
- *admin
|
||||
- *nix-cache
|
||||
|
||||
- path_regex: secrets/server\.yaml$
|
||||
key_groups:
|
||||
- age:
|
||||
- *admin
|
||||
- *server
|
||||
|
||||
- path_regex: secrets/docker\.yaml$
|
||||
key_groups:
|
||||
- age:
|
||||
- *admin
|
||||
- *docker
|
||||
@@ -0,0 +1,45 @@
|
||||
# AGENTS.md
|
||||
|
||||
## Repo purpose
|
||||
|
||||
This repository contains flake-based NixOS configurations for Wayne's LAN
|
||||
servers and workstation.
|
||||
|
||||
The flake exposes NixOS configurations named `<platform>-<buildtype>`
|
||||
(platforms: `linode`, `proxmox`, `lxc`; build types: `minimal`, `nix-cache`,
|
||||
`server`, `docker`, `gui`, `pxe-boot`), generated from `modules/platforms/*`
|
||||
and `modules/build-types/*` by the `mkTarget` function in `flake.nix`. Not
|
||||
every combination is built — `pxe-boot` has no `linode` variant. See
|
||||
`README.md` for the full current target list; treat `flake.nix` as the
|
||||
source of truth since this list can drift.
|
||||
|
||||
Do not deploy, switch, reboot, repartition, format disks, or run destructive
|
||||
install commands from this repository unless explicitly asked.
|
||||
|
||||
## Safety rules
|
||||
|
||||
- Never run `nixos-rebuild switch`, `boot`, `test`, `nixos-install`, `parted`,
|
||||
`mkfs`, `mkswap`, `swapon`, `mount`, or destructive disk commands in Codex.
|
||||
- Validation work should be limited to evaluation, linting, formatting checks,
|
||||
and `nix build --dry-run --no-link`.
|
||||
- Do not add secrets, tokens, private keys, password hashes, or live credentials
|
||||
to the repo.
|
||||
- Treat `flake.nix`, Home Manager config, and Nix config files as public.
|
||||
- If you find committed tokens or hashes, flag them immediately and recommend
|
||||
rotation/removal.
|
||||
|
||||
## Expected commands
|
||||
|
||||
Use these commands when validating changes:
|
||||
|
||||
```bash
|
||||
bash scripts/codex-setup.sh
|
||||
bash scripts/codex-maintenance.sh
|
||||
bash scripts/codex-maintenance.sh dry-run
|
||||
```
|
||||
|
||||
Host evaluation is safe when limited to drvPath checks:
|
||||
|
||||
```bash
|
||||
nix eval .#nixosConfigurations.<host>.config.system.build.toplevel.drvPath --raw
|
||||
```
|
||||
@@ -0,0 +1,114 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Repo purpose
|
||||
|
||||
Flake-based NixOS configuration for Wayne's LAN servers and workstation. There is
|
||||
no application code here — changes are Nix module edits that affect real
|
||||
machines when deployed.
|
||||
|
||||
## Safety rules (read before touching anything)
|
||||
|
||||
- **Never** run `nixos-rebuild switch|boot|test`, `nixos-install`, `parted`,
|
||||
`mkfs`, `mkswap`, `swapon`, `mount`, or any other destructive disk/deploy
|
||||
command from an agent session, even if asked indirectly. Deployment is done
|
||||
manually by the operator on the target host.
|
||||
- Validation is limited to evaluation, linting, formatting checks, and
|
||||
`nix build --dry-run --no-link`.
|
||||
- Do not add secrets, tokens, private keys, or new password hashes to the repo.
|
||||
- This repo currently contains **committed password hashes** (e.g.
|
||||
`prepare.sh`, `hosts/nixos/configuration.nix`) and SSH public keys (e.g.
|
||||
`modules/nix-cache/server.nix`). The hashes are known tech debt — do not use
|
||||
them as a template for new hosts, and flag any *new* secret-like string you
|
||||
encounter instead of committing it.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
# One-time environment bootstrap (installs Nix if missing, prints hosts)
|
||||
bash scripts/codex-setup.sh
|
||||
|
||||
# Full validation: secret grep, nixpkgs-fmt --check, statix lint, eval all hosts
|
||||
bash scripts/codex-maintenance.sh
|
||||
|
||||
# Same, plus a dry-run build (no result symlink) of every host's toplevel
|
||||
bash scripts/codex-maintenance.sh dry-run
|
||||
|
||||
# List the hosts the flake currently exposes
|
||||
nix eval --json .#nixosConfigurations --apply builtins.attrNames | jq -r '.[]'
|
||||
|
||||
# Evaluate a single host without building (fast sanity check)
|
||||
nix eval .#nixosConfigurations.<host>.config.system.build.toplevel.drvPath --raw
|
||||
|
||||
# Dry-run build a single host
|
||||
nix build --dry-run --no-link .#nixosConfigurations.<host>.config.system.build.toplevel
|
||||
```
|
||||
|
||||
Formatting/lint tools (`nixpkgs-fmt`, `statix`) are not installed locally; the
|
||||
maintenance script pulls them via `nix run github:NixOS/nixpkgs/nixos-25.11#<tool>`.
|
||||
There is no test suite — "correctness" here means the flake evaluates and
|
||||
`nixpkgs-fmt`/`statix` are clean.
|
||||
|
||||
## Architecture
|
||||
|
||||
`flake.nix` is the single entry point. It defines one `nixosConfigurations.<host>`
|
||||
attribute per machine, each built the same way:
|
||||
|
||||
```
|
||||
nixosSystem {
|
||||
modules = [
|
||||
disko.nixosModules.disko
|
||||
./hosts/<host>/configuration.nix # host-specific config
|
||||
./modules/hardware-configuration/vm/<proxmox|linode>.nix
|
||||
home-manager.nixosModules.home-manager { ... }
|
||||
];
|
||||
}
|
||||
```
|
||||
|
||||
Hosts currently defined in `flake.nix`: `nixos`, `docker`, `server`,
|
||||
`nix-cache`, `nix-minimal`, `pxe-boot`, `linode-minimal`. Treat `flake.nix` as
|
||||
the source of truth for which hosts exist — `README.md`, `AGENTS.md`,
|
||||
`docs/flake-lock-automation.md`, and the CI eval workflows
|
||||
(`.github/workflows/check-nixos.yml`, `.gitea/workflows/check-nixos.yml`) list
|
||||
hosts by hand and can drift from it, so re-check them against `flake.nix` when
|
||||
adding or removing a host.
|
||||
|
||||
### Composition pattern
|
||||
|
||||
Every host's real configuration lives in `hosts/<host>/configuration.nix`,
|
||||
which is a thin list of `imports` pulling in reusable pieces from `modules/`:
|
||||
|
||||
- `modules/common/configuration.nix` — base NixOS config imported by (almost)
|
||||
every host: locale, users, nix settings, git. Nearly always the first import.
|
||||
- `modules/common/home.nix` / `hosts/<host>/home.nix` — Home Manager config for
|
||||
the `nixos` user; the `nixos` workstation has its own, other hosts share
|
||||
`modules/common/home.nix`.
|
||||
- `modules/disko/proxmox.nix` — declarative disk layout (GPT: ESP + swap +
|
||||
ext4 root) via disko, used by all Proxmox-VM hosts.
|
||||
- `modules/boot/efi.nix` — systemd-boot + EFI vars, paired with the disko module.
|
||||
- `modules/hardware-configuration/vm/{proxmox,linode}.nix` — hypervisor-specific
|
||||
hardware config, wired in from `flake.nix` (not from the host file).
|
||||
- `modules/nix-cache/{client,server}.nix` + `modules/remote-builder-client.nix` —
|
||||
binary cache substituter + SSH remote-builder wiring; see `docs/nix-cache.md`
|
||||
for the full design (per-host local stores, no shared `/nix/store`, and how
|
||||
the `nixremote` signing/SSH keys fit together).
|
||||
- `modules/tailscale/`, `modules/docker/`, `modules/beszel/`,
|
||||
`modules/services/*` — single-purpose, single-host feature modules (e.g.
|
||||
`docker/enable-service.nix`, `services/zfs/enable-service.nix`,
|
||||
`beszel/enable-agent.nix` for monitoring). Grep `hosts/*/configuration.nix`
|
||||
for the `imports` list to see which modules apply to a given host.
|
||||
|
||||
New host = new `hosts/<name>/configuration.nix` + a matching block added to
|
||||
`flake.nix`'s `nixosConfigurations`, composed from existing `modules/*` pieces
|
||||
rather than duplicating config.
|
||||
|
||||
### Other docs worth reading before touching these areas
|
||||
|
||||
- `docs/nix-cache.md` — nix-cache binary cache/remote-builder design and key
|
||||
handling.
|
||||
- `docs/pxe-boot.md` — the `pxe-boot` host's iPXE/TFTP/HTTP boot chain and
|
||||
directory layout under `/srv/pxe`.
|
||||
- `docs/flake-lock-automation.md` — how `flake.lock` updates flow through CI
|
||||
(scheduled `nix flake update` PR + host-eval-on-PR workflow) and why hosts
|
||||
should track the committed lock file rather than `nixos-rebuild --upgrade-all`.
|
||||
@@ -1,2 +1,110 @@
|
||||
# nixos
|
||||
# NixOS LAN Configurations
|
||||
|
||||
Flake-based NixOS configuration repository for Wayne's LAN servers and
|
||||
workstation.
|
||||
|
||||
## Hosts
|
||||
|
||||
Targets are named `<platform>-<buildtype>`, generated from two orthogonal
|
||||
pieces composed in `flake.nix`:
|
||||
|
||||
- **Platforms** (what it runs on): `linode`, `proxmox`, `lxc`
|
||||
- **Build types** (what it's for): `minimal`, `nix-cache`, `server`, `docker`,
|
||||
`gui`, `pxe-boot`
|
||||
|
||||
Not every combination exists — `pxe-boot` has no `linode` variant, since
|
||||
PXE/DHCP/TFTP need LAN L2 adjacency that a Linode VPS doesn't have. The full
|
||||
list:
|
||||
|
||||
| Target | Purpose |
|
||||
| --- | --- |
|
||||
| `linode-minimal` | Minimal NixOS host profile on a Linode VPS (real, deployed) |
|
||||
| `proxmox-minimal` | Minimal NixOS host profile on Proxmox (real, deployed — previously the flat `nix-minimal` target) |
|
||||
| `lxc-minimal` | Minimal NixOS host profile in a Proxmox LXC container |
|
||||
| `linode-nix-cache` / `proxmox-nix-cache` / `lxc-nix-cache` | Local Nix binary cache and remote builder (`proxmox-nix-cache` is the real, deployed one — previously the flat `nix-cache` target) |
|
||||
| `linode-server` / `proxmox-server` / `lxc-server` | Storage, NFS, backup, and monitoring exporter host (`proxmox-server` is the real, deployed one — previously the flat `server` target) |
|
||||
| `linode-docker` / `proxmox-docker` / `lxc-docker` | Docker host for the main container stack (`proxmox-docker` is the real, deployed one — previously the flat `docker` target) |
|
||||
| `linode-gui` / `proxmox-gui` / `lxc-gui` | Cinnamon desktop workstation (`proxmox-gui` is the real, deployed one — previously the flat `nixos` target) |
|
||||
| `proxmox-pxe-boot` / `lxc-pxe-boot` | HTTP/iPXE boot asset host (`proxmox-pxe-boot` is the real, deployed one — previously the flat `pxe-boot` target) |
|
||||
|
||||
Each buildtype's `hosts/<name>/host.nix` carries the per-machine identity
|
||||
(hostname, hostId, per-machine secrets, `system.stateVersion`) that must stay
|
||||
fixed regardless of which platform it's built for — see
|
||||
`flake-target-refactor-spec.md` for the full rationale. Every deployed host
|
||||
stamps its own active target name into `/etc/flake-target` at build time, so
|
||||
`nixos-rebuild switch --flake .#$(cat /etc/flake-target)` always picks up the
|
||||
right one even after a platform migration changes the flake attribute name.
|
||||
|
||||
List hosts with:
|
||||
|
||||
```bash
|
||||
nix eval --json .#nixosConfigurations --apply builtins.attrNames | jq -r '.[]'
|
||||
```
|
||||
|
||||
## Layout
|
||||
|
||||
| Path | Purpose |
|
||||
| --- | --- |
|
||||
| `flake.nix` | Flake inputs, the `mkTarget` platform × build-type generator, and `nixosConfigurations` outputs |
|
||||
| `hosts/<name>/host.nix` | Per-machine identity: hostname, hostId, per-machine secrets, `system.stateVersion` |
|
||||
| `hosts/nixos/home.nix` | Workstation-specific Home Manager config (used by the `gui` build type) |
|
||||
| `modules/platforms/` | Platform-specific config: virtualisation guest tools, boot method, hardware config (`linode.nix`, `proxmox.nix`, `lxc.nix`) |
|
||||
| `modules/build-types/` | Build-type-specific config: what makes a system minimal/server/docker/gui/pxe-boot/nix-cache |
|
||||
| `modules/common/` | Shared NixOS config, Home Manager, aliases imported by every host |
|
||||
| `modules/nix-cache/` | Binary cache and remote builder client/server modules |
|
||||
| `docs/` | Operational notes for cache, builders, lock updates, and boot services |
|
||||
| `scripts/` | Codex setup and validation helpers |
|
||||
|
||||
## Validation
|
||||
|
||||
Safe validation commands for Codex and local review:
|
||||
|
||||
```bash
|
||||
bash scripts/codex-setup.sh
|
||||
bash scripts/codex-maintenance.sh dry-run
|
||||
bash scripts/codex-maintenance.sh
|
||||
```
|
||||
|
||||
For individual host evaluation:
|
||||
|
||||
```bash
|
||||
nix eval .#nixosConfigurations.<host>.config.system.build.toplevel.drvPath --raw
|
||||
```
|
||||
|
||||
Use `nix build --dry-run --no-link` when build planning is needed. Do not run
|
||||
deployment, install, disk formatting, mount, or reboot commands from automated
|
||||
review sessions.
|
||||
|
||||
## Operations
|
||||
|
||||
- Host rebuilds should consume the committed `flake.lock`.
|
||||
- Routine dependency updates should happen through the flake lock automation
|
||||
described in `docs/flake-lock-automation.md`.
|
||||
- `nix-cache` serves substitutes over HTTP and can act as a remote builder for
|
||||
client hosts.
|
||||
- `pxe-boot` serves iPXE boot files over HTTP from `/srv/pxe`.
|
||||
|
||||
## Security Notes
|
||||
|
||||
Do not commit tokens, private keys, live credentials, or new password hashes
|
||||
as plaintext. Secrets are managed with [sops-nix](https://github.com/Mic92/sops-nix):
|
||||
encrypted files live under `secrets/`, recipients (per-host age keys derived
|
||||
from each host's existing SSH host key, plus an admin key) are declared in
|
||||
`.sops.yaml`. To add or edit a secret:
|
||||
|
||||
```bash
|
||||
nix-shell -p sops --run "sops secrets/<file>.yaml"
|
||||
```
|
||||
|
||||
then reference it from a module via `config.sops.secrets."<name>".path`
|
||||
(or `sops.templates` for values that need to be embedded in a rendered
|
||||
config file, e.g. `nix.conf`'s `access-tokens`). Never write a secret value
|
||||
directly into a tracked `.nix` file. A pre-commit hook (`.githooks/`,
|
||||
enabled via `git config core.hooksPath .githooks`, done automatically by
|
||||
`scripts/codex-setup.sh`) runs `gitleaks protect --staged` to catch mistakes
|
||||
before they're committed.
|
||||
|
||||
This repository's git *history* still contains secrets committed before this
|
||||
migration (see `remove-sensetive-info-refactor.md`) — those are being
|
||||
scrubbed and rotated separately; don't treat the repo as safe to make public
|
||||
until that's finished.
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ # Include the results of the hardware scan.
|
||||
./hardware-configuration.nix
|
||||
|
||||
];
|
||||
# Use the GRUB 2 boot loader.
|
||||
boot.loader.grub.enable = true;
|
||||
boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only
|
||||
|
||||
networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
|
||||
|
||||
# Set your time zone.
|
||||
time.timeZone = "Australia/Brisbane";
|
||||
|
||||
# Enable QEMU agent
|
||||
services.qemuGuest.enable = true;
|
||||
|
||||
# Enable docker-compose
|
||||
environment.systemPackages = with pkgs; [
|
||||
vim
|
||||
btop
|
||||
git
|
||||
gcr
|
||||
];
|
||||
#Set root password
|
||||
users.users.root = {
|
||||
hashedPassword = "$6$Kwv9KAyvcurAViQF$H4.u3feqGE7lVoNgkFXhE3n2Pmo//9JYDTCz8ifrVHBxPjwa1xMby7tEZ8Bpt5MXs9Rkx6/YbZWxs5CpH0s/70";
|
||||
};
|
||||
|
||||
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||
users.users.nixos = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
|
||||
packages = with pkgs; [
|
||||
tree
|
||||
];
|
||||
hashedPassword = "$6$Kwv9KAyvcurAViQF$H4.u3feqGE7lVoNgkFXhE3n2Pmo//9JYDTCz8ifrVHBxPjwa1xMby7tEZ8Bpt5MXs9Rkx6/YbZWxs5CpH0s/70";
|
||||
openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCq/Q5LvIXlZwO2kdeAN5nLGZ59nZB7JHYMEszHxmNtGMzv1lM31jiPNsr0z2EKVZhE7OOfa2IF9rhWYD7JUA9G0yzdZ4WTXFNGVVOJoOVH6vAF3XCxoVilOEwTc7h2Wiy+rzd0B28/3spffzQQWJhY6GRQVa8j+6xAGF60Fcvl1vLosYT9Bn2ZbK4TCWOwAn2jqXIieGpZdn/UNZbGOeKRiCvhktDfMAzuQzN/9jMu/oF4pkPn2X1UrsQdNlvp0Ci8md612MozIpncQJyAF1ADhunr3sMx0isUXiqD29R5DS4TftpekqLNLak+zcxFa8N7DcRNp3DcKfJvyTkwQrR4r+b7lFLYOLHLagSso9CzeW/paAS2q9I5SBm/2DtE1diLLg2jZikYcstsu/G5RgvbzbKqjiaMwTdXC3AMvDxQrs7U5pDRZFzoofG3cpODbTm+uy3m0kP70z0M1K45UbDG0p+itnTu9x40JbQEgefbx38AItNvAIx1A8HO4I1VX28= wayne@stream"
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
# Enable the OpenSSH daemon.
|
||||
services.openssh.enable = true;
|
||||
|
||||
#Enable flakes
|
||||
|
||||
nix.settings.experimental-features = "nix-command flakes";
|
||||
|
||||
nix.settings = {
|
||||
substituters = [
|
||||
"http://nix-cache"
|
||||
"https://cache.nixos.org/"
|
||||
];
|
||||
trusted-public-keys = [
|
||||
"nix-ccache-1:<base32‑pubkey‑hash‑from‑cache-pub.pem>"
|
||||
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
programs.git = {
|
||||
enable = true;
|
||||
package = pkgs.git;
|
||||
config = {
|
||||
credential.helper = "store";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
mySwitchCmd = ''
|
||||
sudo nixos-rebuild switch \
|
||||
--no-write-lock-file \
|
||||
--refresh \
|
||||
--flake git+https://gitea.lan.ddnsgeek.com/beatzaplenty/nixos.git#$(hostname)
|
||||
'';
|
||||
myTestCmd = ''
|
||||
sudo nixos-rebuild switch \
|
||||
--no-write-lock-file \
|
||||
--refresh \
|
||||
--flake git+https://gitea.lan.ddnsgeek.com/beatzaplenty/nixos.git#$(hostname)
|
||||
'';
|
||||
in {
|
||||
home.username = "nixos"; # your actual username
|
||||
home.homeDirectory = "/home/nixos";
|
||||
home.stateVersion = "25.05"; # match your NixOS stateVersion
|
||||
|
||||
programs.home-manager.enable = true; # mandatory to activate HM
|
||||
|
||||
programs.bash = {
|
||||
enable = true;
|
||||
shellAliases = {
|
||||
"Switch-nix" = mySwitchCmd;
|
||||
"Test-nix" = mySwitchCmd;
|
||||
};
|
||||
initExtra = ''
|
||||
# ensure loading of aliases/session variables
|
||||
[[ -f ~/.profile ]] && . ~/.profile
|
||||
'';
|
||||
};
|
||||
|
||||
# Optional: packages
|
||||
home.packages = with pkgs; [
|
||||
git
|
||||
vim
|
||||
tmux
|
||||
];
|
||||
|
||||
# Optional: set environment vars
|
||||
home.sessionVariables = {
|
||||
EDITOR = "vim";
|
||||
};
|
||||
|
||||
# Optional: enable bash (or zsh, fish...)
|
||||
# programs.bash.enable = true;
|
||||
|
||||
# Optional: manage dotfiles via symlinks
|
||||
# home.file = {
|
||||
# ".tmux.conf".source = ./dotfiles/tmux.conf;
|
||||
# ".config/nvim/init.vim".source = ./dotfiles/init.vim;
|
||||
# };
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
# flake.lock automation
|
||||
|
||||
This repository uses CI workflows to keep `flake.lock` up to date on a schedule
|
||||
and to verify that declared NixOS hosts still evaluate after dependency updates.
|
||||
|
||||
## What this automation does
|
||||
|
||||
- A scheduled workflow runs `nix flake update` once per week.
|
||||
- On GitHub, any resulting `flake.lock` change is proposed through a pull request.
|
||||
- On Gitea, the workflow can commit and push `flake.lock` directly when PR automation is not configured.
|
||||
- A separate CI workflow evaluates every configured host before merge, listed
|
||||
dynamically via `nix eval --json .#nixosConfigurations --apply builtins.attrNames`
|
||||
rather than hand-enumerated, so it can't drift as `<platform>-<buildtype>`
|
||||
targets are added or removed. See `README.md` for the current target list.
|
||||
|
||||
## Why hosts should stop using `--upgrade-all`
|
||||
|
||||
`flake.lock` is the source of truth for pinned dependency versions in a flake-based workflow. Normal host rebuilds should consume the committed lock file instead of upgrading dependencies ad-hoc on each machine.
|
||||
|
||||
Recommended rebuild command:
|
||||
|
||||
```bash
|
||||
sudo nixos-rebuild switch --flake git+https://gitea.lan.ddnsgeek.com/beatzaplenty/nixos.git#$(cat /etc/flake-target)
|
||||
```
|
||||
|
||||
Flake attribute names are `<platform>-<buildtype>` (e.g. `proxmox-docker`)
|
||||
and no longer match `hostname`, since a host's hostname stays fixed while
|
||||
the platform backing it can change. Each `nixosConfiguration` stamps its own
|
||||
active target name into `/etc/flake-target` at build time, which is what the
|
||||
command above reads.
|
||||
|
||||
Using the committed lock file keeps all hosts aligned and makes updates auditable through CI and code review.
|
||||
|
||||
Codex and automated review sessions must not run rebuilds. Limit checks to
|
||||
evaluation, linting, formatting, and dry-run builds.
|
||||
|
||||
## Command differences
|
||||
|
||||
- `nix flake update`
|
||||
- Updates flake input pins in `flake.lock`.
|
||||
- Should be run in CI or in a dedicated update PR workflow.
|
||||
- `nixos-rebuild --upgrade`
|
||||
- Primarily for channel-based workflows; not the normal path for flake-pinned deployments.
|
||||
- `nixos-rebuild --upgrade-all`
|
||||
- Aggressively updates package sources and bypasses coordinated lock-file updates.
|
||||
- Avoid for routine flake-based host rebuilds.
|
||||
|
||||
## nix-cache and remote builder fit
|
||||
|
||||
With `nix-cache` acting as a binary cache and remote builder, lock-file updates become safer and more reproducible:
|
||||
|
||||
- CI verifies host evaluations against the updated lock file.
|
||||
- Builds can be performed once on the remote builder.
|
||||
- Built artifacts can be served via `nix-cache` to other hosts, reducing rebuild time and drift.
|
||||
|
||||
## Token and secret handling
|
||||
|
||||
Do **not** commit access tokens into `flake.nix`, `flake.lock`, or any other tracked file.
|
||||
|
||||
If private source access is needed:
|
||||
|
||||
- configure tokens locally in `~/.config/nix/nix.conf` or equivalent machine-local config, or
|
||||
- provide tokens through CI secrets/environment variables.
|
||||
|
||||
## GitHub Actions setup notes
|
||||
|
||||
- Ensure `GITHUB_TOKEN` has permission to create branches and pull requests (workflow sets `contents: write` and `pull-requests: write`).
|
||||
- The update workflow uses `peter-evans/create-pull-request` with branch `chore/update-flake-lock`.
|
||||
- The evaluation workflow runs on pull requests, pushes to `main`, and manual dispatch.
|
||||
|
||||
## Gitea Actions runner setup notes
|
||||
|
||||
- Ensure the runner image includes Git and can execute the Nix installer action.
|
||||
- For direct push mode, grant workflow push permission to the repository.
|
||||
- The workflow sets commit identity to:
|
||||
- `user.name = gitea-actions`
|
||||
- `user.email = gitea-actions@nix-cache.local`
|
||||
- Commits are only created when `flake.lock` actually changes.
|
||||
@@ -0,0 +1,55 @@
|
||||
# nix-cache architecture
|
||||
|
||||
This repository configures `nix-cache` as a **binary cache server** and a **remote builder** for other hosts.
|
||||
|
||||
## Important design notes
|
||||
|
||||
- This is **not** a shared `/nix/store` setup.
|
||||
- Every machine still keeps and uses its own local `/nix/store`.
|
||||
- Clients prefer `http://nix-cache` for substitutes and keep `https://cache.nixos.org/` as fallback.
|
||||
- Clients can offload builds to `nix-cache` through SSH (`nix.distributedBuilds`).
|
||||
- Client hosts import `modules/nix/cache-client.nix` and, when remote building is enabled, `modules/nix/remote-builder-client.nix`.
|
||||
- The `nix-cache` host imports `modules/nix/cache-server.nix`.
|
||||
|
||||
## Binary cache signing keys (on nix-cache)
|
||||
|
||||
```bash
|
||||
sudo install -d -m 0700 /etc/nix
|
||||
sudo nix-store --generate-binary-cache-key nix-cache-1 /etc/nix/cache-priv.pem /etc/nix/cache-pub.pem
|
||||
sudo chmod 0600 /etc/nix/cache-priv.pem
|
||||
sudo chmod 0644 /etc/nix/cache-pub.pem
|
||||
cat /etc/nix/cache-pub.pem
|
||||
```
|
||||
|
||||
Do not commit private keys.
|
||||
Do not commit new password hashes or live credentials. Existing committed hashes
|
||||
should be rotated and moved to host-local secret management.
|
||||
|
||||
## Remote builder SSH keys
|
||||
|
||||
On each client, install the private key used to authenticate as `nixremote`:
|
||||
|
||||
```bash
|
||||
sudo install -d -m 0700 /root/.ssh
|
||||
sudo install -m 0600 ./nixremote /root/.ssh/nixremote
|
||||
sudo ssh -i /root/.ssh/nixremote nixremote@nix-cache nix-store --version
|
||||
```
|
||||
|
||||
On `nix-cache`, install the matching public key used by `nixremote` authorized keys.
|
||||
|
||||
The committed `nixremote` authorized keys are public SSH keys only. Keep the
|
||||
matching private keys on client hosts and out of the repository.
|
||||
|
||||
## Manual verification
|
||||
|
||||
After deployment:
|
||||
|
||||
```bash
|
||||
curl http://nix-cache/nix-cache-info
|
||||
nix store ping --store http://nix-cache
|
||||
nix show-config | grep -E 'substituters|trusted-public-keys|builders-use-substitutes'
|
||||
sudo ssh -i /root/.ssh/nixremote nixremote@nix-cache nix-store --version
|
||||
nix build nixpkgs#hello --builders 'ssh://nixremote@nix-cache x86_64-linux /root/.ssh/nixremote 4 2 big-parallel,kvm,nixos-test,benchmark' -L
|
||||
nix path-info -r nixpkgs#hello
|
||||
curl -I "http://nix-cache/$(basename "$(nix path-info nixpkgs#hello)").narinfo"
|
||||
```
|
||||
@@ -0,0 +1,95 @@
|
||||
# pxe-boot
|
||||
|
||||
The `pxe-boot` host serves HTTP boot assets for iPXE clients.
|
||||
|
||||
## Host Role
|
||||
|
||||
- Hostname: `pxe-boot`
|
||||
- Web service: nginx on TCP port 80
|
||||
- PXE root: `/srv/pxe`
|
||||
- HTTP root for scripts and images: `/srv/pxe/http`
|
||||
- TFTP root for first-stage bootloaders: `/srv/pxe/tftp`
|
||||
- iPXE entry script: `/srv/pxe/http/boot.ipxe`
|
||||
- Generated iPXE menu: `/srv/pxe/http/menu.ipxe`
|
||||
- SystemRescue iPXE script: `/srv/pxe/http/systemrescue.ipxe`
|
||||
- TFTP fallback script: `/srv/pxe/tftp/autoexec.ipxe`
|
||||
- Boot binaries copied from the Nix `ipxe` package:
|
||||
- `/srv/pxe/tftp/ipxe.efi`
|
||||
- `/srv/pxe/tftp/undionly.kpxe`
|
||||
|
||||
## Directory Layout
|
||||
|
||||
The host creates these directories with systemd tmpfiles:
|
||||
|
||||
```text
|
||||
/srv/pxe
|
||||
/srv/pxe/http
|
||||
/srv/pxe/http/images
|
||||
/srv/pxe/http/nixos
|
||||
/srv/pxe/http/systemrescue
|
||||
/srv/pxe/http/ubuntu
|
||||
/srv/pxe/http/rescue
|
||||
/srv/pxe/tftp
|
||||
```
|
||||
|
||||
Mount shared image storage under `/srv/pxe/http`, preferably
|
||||
`/srv/pxe/http/images` unless a menu entry expects files in a specific
|
||||
directory such as `/srv/pxe/http/nixos`.
|
||||
|
||||
The HTTP iPXE chain is:
|
||||
|
||||
```text
|
||||
undionly.kpxe or ipxe.efi
|
||||
-> autoexec.ipxe from the TFTP root, when iPXE requests it
|
||||
-> http://192.168.2.247/boot.ipxe
|
||||
-> http://192.168.2.247/menu.ipxe
|
||||
```
|
||||
|
||||
The generated menu currently exposes entries for:
|
||||
|
||||
- NixOS installer
|
||||
- SystemRescue environment
|
||||
- iPXE shell
|
||||
- Reboot
|
||||
|
||||
Kernel and initrd artifacts for the NixOS installer entry must be placed under
|
||||
`/srv/pxe/http/nixos` by an operator or a separate build process.
|
||||
|
||||
The SystemRescue entry expects the source ISO at:
|
||||
|
||||
```text
|
||||
/srv/pxe/http/images/systemrescue.iso
|
||||
```
|
||||
|
||||
The `stage-systemrescue.service` oneshot extracts that ISO into:
|
||||
|
||||
```text
|
||||
/srv/pxe/http/systemrescue
|
||||
```
|
||||
|
||||
The rescue menu entry then chains `http://192.168.2.247/systemrescue.ipxe`,
|
||||
which loads the SystemRescue kernel and initramfs from the extracted tree and
|
||||
uses `archiso_http_srv` to fetch the squashfs payload over HTTP.
|
||||
|
||||
## Validation
|
||||
|
||||
Safe evaluation check:
|
||||
|
||||
```bash
|
||||
nix eval .#nixosConfigurations.pxe-boot.config.system.build.toplevel.drvPath --raw
|
||||
```
|
||||
|
||||
After deployment by an operator, basic service checks are:
|
||||
|
||||
```bash
|
||||
curl http://pxe-boot/boot.ipxe
|
||||
curl http://pxe-boot/menu.ipxe
|
||||
curl http://pxe-boot/systemrescue.ipxe
|
||||
curl -I http://pxe-boot/systemrescue/sysresccd/boot/x86_64/vmlinuz
|
||||
curl -I http://pxe-boot/systemrescue/sysresccd/boot/x86_64/sysresccd.img
|
||||
```
|
||||
|
||||
During a successful BIOS chainload, TFTP should deliver `undionly.kpxe` once,
|
||||
then nginx should log requests for `/boot.ipxe` and `/menu.ipxe`. Repeated TFTP
|
||||
downloads of `undionly.kpxe` indicate the iPXE stage is still not reaching the
|
||||
HTTP chain.
|
||||
Executable
+143
@@ -0,0 +1,143 @@
|
||||
# Spec: Refactor Flake Targets into Platform × Build-Type Matrix
|
||||
|
||||
## Context
|
||||
|
||||
The flake at `~/nixos` currently defines these output targets (flat, ad-hoc naming):
|
||||
|
||||
- `docker`
|
||||
- `linode-minimal`
|
||||
- `nix-cache`
|
||||
- `nix-minimal`
|
||||
- `nixos`
|
||||
- `server`
|
||||
- `pxe-boot`
|
||||
|
||||
Some already follow a `platform-buildtype` convention (`linode-minimal`), most don't.
|
||||
`~/nix-auto-installer` is a related repo and should be checked for any coupling to
|
||||
these target names (scripts, docs, CI, or install automation that reference them by
|
||||
name) before renaming anything.
|
||||
|
||||
## Goal
|
||||
|
||||
Restructure the flake so targets are generated from two orthogonal concepts:
|
||||
|
||||
**Build types** (what the system is for):
|
||||
- `minimal`
|
||||
- `nix-cache`
|
||||
- `server`
|
||||
- `docker`
|
||||
- `pxe-boot`
|
||||
- `gui`
|
||||
|
||||
**Platforms** (what it's deployed on):
|
||||
- `linode` (Linode VM)
|
||||
- `proxmox` (Proxmox VM)
|
||||
- `lxc` (Proxmox LXC container)
|
||||
|
||||
Final targets should be named consistently as `<platform>-<buildtype>`, e.g.:
|
||||
|
||||
```
|
||||
linode-minimal proxmox-minimal lxc-minimal
|
||||
linode-nix-cache proxmox-nix-cache lxc-nix-cache
|
||||
linode-server proxmox-server lxc-server
|
||||
linode-docker proxmox-docker lxc-docker
|
||||
linode-pxe-boot proxmox-pxe-boot lxc-pxe-boot
|
||||
linode-gui proxmox-gui lxc-gui
|
||||
```
|
||||
|
||||
That's the full matrix (18 targets) if every build type applies to every platform.
|
||||
See **Open Questions** below — some combinations may not make sense and should be
|
||||
confirmed with me before being built out, not silently included or dropped.
|
||||
|
||||
## Migration mapping (old → new)
|
||||
|
||||
| Old target | New target | Notes |
|
||||
|--------------------|------------------------------------------------------|-------|
|
||||
| `linode-minimal` | `linode-minimal` | Already correct, keep as-is |
|
||||
| `nix-minimal` | likely `proxmox-minimal` or a platform-less base module | Ambiguous — see Open Questions |
|
||||
| `nix-cache` | base module consumed by `linode-nix-cache`, `proxmox-nix-cache`, `lxc-nix-cache` | Currently platform-less; needs to become a build-type module, not a standalone target |
|
||||
| `server` | base module consumed by `linode-server`, `proxmox-server`, `lxc-server` | Same as above |
|
||||
| `docker` | base module consumed by `linode-docker`, `proxmox-docker`, `lxc-docker` | Confirm docker actually makes sense as an LXC/VM guest build vs. a standalone container image — see Open Questions |
|
||||
| `pxe-boot` | TBD — may stay a single target rather than a per-platform one | See Open Questions |
|
||||
| `nixos` | TBD — unclear what this maps to in the new scheme | See Open Questions |
|
||||
|
||||
## Open Questions (Claude Code: raise these with me before implementing, don't guess)
|
||||
|
||||
1. **`nixos` target** — what is this currently used for (bare metal install, dev
|
||||
shell, template)? It doesn't obviously map to any of the six build types.
|
||||
2. **`nix-minimal` vs `linode-minimal`** — are these two different things, or is
|
||||
`nix-minimal` a leftover/duplicate?
|
||||
3. **`pxe-boot` and `gui` across all three platforms** — does PXE boot make sense
|
||||
for an LXC container or a cloud VM (Linode), or is it inherently bare-metal/
|
||||
network-boot only and should remain a single non-platform target? Does `gui`
|
||||
make sense inside an LXC container?
|
||||
4. **`docker` as a build type** — is this "a NixOS host configured to run Docker"
|
||||
(which would sensibly have linode/proxmox/lxc variants), or "a Docker container
|
||||
image built by the flake" (which wouldn't take a platform prefix at all, since
|
||||
it doesn't run on Linode/Proxmox/LXC as a guest OS)? These are structurally
|
||||
different and change how it should be wired in.
|
||||
5. Confirm whether all 18 combinations should actually exist, or whether this is
|
||||
meant to produce only the combinations that are genuinely useful (e.g. maybe no
|
||||
one needs `lxc-pxe-boot`).
|
||||
|
||||
## Implementation approach
|
||||
|
||||
1. **Inventory first.** Read the current `flake.nix` and any `nixosConfigurations`/
|
||||
`modules` structure. Map every existing target to what module(s) it actually
|
||||
pulls in. Don't assume — confirm against the real file contents.
|
||||
2. **Separate build-type and platform into their own module directories**, e.g.:
|
||||
```
|
||||
modules/build-types/minimal.nix
|
||||
modules/build-types/nix-cache.nix
|
||||
modules/build-types/server.nix
|
||||
modules/build-types/docker.nix
|
||||
modules/build-types/pxe-boot.nix
|
||||
modules/build-types/gui.nix
|
||||
|
||||
modules/platforms/linode.nix
|
||||
modules/platforms/proxmox.nix
|
||||
modules/platforms/lxc.nix
|
||||
```
|
||||
Build-type modules should contain only what makes a system "minimal" vs
|
||||
"server" vs "gui", etc. Platform modules should contain only what's specific
|
||||
to running as a Linode VM vs Proxmox VM vs LXC container (virtualisation
|
||||
guest tools, boot method, filesystem/image format, LXC-specific constraints
|
||||
like no kernel modules, etc).
|
||||
3. **Generate the target matrix programmatically** in `flake.nix` rather than
|
||||
hand-writing 18 near-identical `nixosConfigurations` entries — e.g. a small
|
||||
function that takes a platform name and build-type name, composes the two
|
||||
modules plus any shared base module, and produces the named output. This
|
||||
keeps future build types/platforms a one-line addition rather than a copy-paste
|
||||
job.
|
||||
4. **Only build combinations we've confirmed make sense** (see Open Questions) —
|
||||
don't emit all 18 by default if some are structurally invalid.
|
||||
5. **Preserve existing working configs during the transition.** Don't delete the
|
||||
old target names until their replacements build successfully — rename/alias
|
||||
at the end, not the start, so there's no window where the flake is broken.
|
||||
|
||||
## Verification
|
||||
|
||||
For every new target produced:
|
||||
```bash
|
||||
nix flake check
|
||||
nix build .#nixosConfigurations.<target>.config.system.build.toplevel
|
||||
```
|
||||
Confirm each builds without evaluation errors before considering it done. If a
|
||||
target fails to build, report which one and why rather than silently skipping it.
|
||||
|
||||
## Deliverables
|
||||
|
||||
- Refactored `flake.nix` using the composed module + generated-matrix approach.
|
||||
- New `modules/build-types/*.nix` and `modules/platforms/*.nix` files.
|
||||
- Old flat target names removed only after their replacements are verified.
|
||||
- A short `README.md` (or section in existing docs) listing the final target
|
||||
names and what each one is for.
|
||||
- A summary at the end of what changed, what was removed, and any of the Open
|
||||
Questions above that got resolved differently than expected.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Don't touch `~/nix-auto-installer` contents beyond checking it for references
|
||||
to the old target names — if changes there are needed, flag them, don't make
|
||||
them without confirming.
|
||||
- Don't add new build types or platforms beyond the ones listed here.
|
||||
Generated
+234
@@ -0,0 +1,234 @@
|
||||
{
|
||||
"nodes": {
|
||||
"disko": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1781152676,
|
||||
"narHash": "sha256-RxWs5ND31KzTG7wvMM+PMfUjyNpmIEr999lqNARaM5o=",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"rev": "ff8702b4de27f72b4c78573dfb89ec74e36abdf1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"locked": {
|
||||
"lastModified": 1767039857,
|
||||
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat_2": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1650374568,
|
||||
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1694529238,
|
||||
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils-plus": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1715533576,
|
||||
"narHash": "sha256-fT4ppWeCJ0uR300EH3i7kmgRZnAVxrH+XtK09jQWihk=",
|
||||
"owner": "gytis-ivaskevicius",
|
||||
"repo": "flake-utils-plus",
|
||||
"rev": "3542fe9126dc492e53ddd252bb0260fe035f2c0f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "gytis-ivaskevicius",
|
||||
"repo": "flake-utils-plus",
|
||||
"rev": "3542fe9126dc492e53ddd252bb0260fe035f2c0f",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"home-manager": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1783740085,
|
||||
"narHash": "sha256-qajyHfZY29G2oEQk+uHxmsJcRoBUBXP9maTpFlwP/dI=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "3cd22efe6471dc7365c822bd9ad73a21e55f38fb",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"ref": "release-26.05",
|
||||
"repo": "home-manager",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixos-conf-editor": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"snowfall-lib": "snowfall-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1771149335,
|
||||
"narHash": "sha256-YPUIwyumbQOE2DUY8NIsHIUTGUQnDVhnTVUZMZDRwi4=",
|
||||
"owner": "snowfallorg",
|
||||
"repo": "nixos-conf-editor",
|
||||
"rev": "9f8b4519a2e0e8919b69b7572bc26dab54274a6f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "snowfallorg",
|
||||
"repo": "nixos-conf-editor",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1771008912,
|
||||
"narHash": "sha256-gf2AmWVTs8lEq7z/3ZAsgnZDhWIckkb+ZnAo5RzSxJg=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "a82ccc39b39b621151d6732718e3e250109076fa",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1784011430,
|
||||
"narHash": "sha256-lDebytrYdd47IBLwvNOD+6AGeoqZ78CIKlp70hzW280=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "8eeec934ae0dbeca3d7868c059568a65c08b2fc3",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-26.05",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"disko": "disko",
|
||||
"home-manager": "home-manager",
|
||||
"nixos-conf-editor": "nixos-conf-editor",
|
||||
"nixpkgs": "nixpkgs_2",
|
||||
"sops-nix": "sops-nix"
|
||||
}
|
||||
},
|
||||
"snowfall-lib": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_2",
|
||||
"flake-utils-plus": "flake-utils-plus",
|
||||
"nixpkgs": [
|
||||
"nixos-conf-editor",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1765361626,
|
||||
"narHash": "sha256-kX0Dp/kYSRbQ+yd9e3lmmUWdNbipufvKfL2IzbrSpnY=",
|
||||
"owner": "snowfallorg",
|
||||
"repo": "lib",
|
||||
"rev": "c566ad8b7352c30ec3763435de7c8f1c46ebb357",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "snowfallorg",
|
||||
"repo": "lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"sops-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1783174389,
|
||||
"narHash": "sha256-aCWC8ngycU7OdJrU2+Je3qf+1a2ykuBvpPhZT/9tXMc=",
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"rev": "f1406619a3884cd5c47992a70b8b35c9c0fcb4c9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Mic92",
|
||||
"repo": "sops-nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
@@ -2,69 +2,91 @@
|
||||
description = "LAN NixOS configs";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-26.05";
|
||||
nixos-conf-editor.url = "github:snowfallorg/nixos-conf-editor";
|
||||
home-manager = {
|
||||
url = "github:nix-community/home-manager";
|
||||
url = "github:nix-community/home-manager/release-26.05";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
disko = {
|
||||
url = "github:nix-community/disko";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
sops-nix = {
|
||||
url = "github:Mic92/sops-nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, nixos-conf-editor, home-manager, ... } @ inputs:
|
||||
let system = "x86_64-linux"; in {
|
||||
nixosConfigurations = {
|
||||
# automatically use each host folder by name
|
||||
nixos = nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
modules = [
|
||||
./hosts/nixos/configuration.nix
|
||||
./common/hardware-configuration.nix
|
||||
home-manager.nixosModules.home-manager {
|
||||
home-manager.useGlobalPkgs = true;
|
||||
home-manager.useUserPackages = true;
|
||||
home-manager.users.nixos = import ./hosts/nixos/home.nix;
|
||||
outputs = { self, nixpkgs, nixos-conf-editor, home-manager, sops-nix, ... } @ inputs:
|
||||
|
||||
}
|
||||
];
|
||||
specialArgs = { inherit inputs; };
|
||||
};
|
||||
docker = nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
modules = [
|
||||
./hosts/docker/configuration.nix
|
||||
./common/hardware-configuration.nix
|
||||
home-manager.nixosModules.home-manager {
|
||||
home-manager.useGlobalPkgs = true;
|
||||
home-manager.useUserPackages = true;
|
||||
home-manager.users.nixos = import ./common/home.nix;
|
||||
}
|
||||
];
|
||||
};
|
||||
server = nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
modules = [
|
||||
./hosts/server/configuration.nix
|
||||
./common/hardware-configuration.nix
|
||||
home-manager.nixosModules.home-manager {
|
||||
home-manager.useGlobalPkgs = true;
|
||||
home-manager.useUserPackages = true;
|
||||
home-manager.users.nixos = import ./common/home.nix;
|
||||
}
|
||||
];
|
||||
};
|
||||
nix-cache = nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
modules = [
|
||||
./hosts/nix-cache/configuration.nix
|
||||
./common/hardware-configuration.nix
|
||||
home-manager.nixosModules.home-manager {
|
||||
home-manager.useGlobalPkgs = true;
|
||||
home-manager.useUserPackages = true;
|
||||
home-manager.users.nixos = import ./common/home.nix;
|
||||
}
|
||||
];
|
||||
};
|
||||
let
|
||||
system = "x86_64-linux";
|
||||
inherit (nixpkgs) lib;
|
||||
|
||||
# Generates a nixosConfiguration from a platform (what it runs on) and
|
||||
# a build type (what it's for), plus the per-identity host.nix that
|
||||
# carries the bits that must stay fixed regardless of platform
|
||||
# (hostName, hostId, per-machine secrets). Every build type except
|
||||
# nix-cache itself consumes the nix-cache substituter and remote
|
||||
# builder.
|
||||
mkTarget = { platform, buildType, hostPath, homeFile ? ./modules/common/home.nix }:
|
||||
nixpkgs.lib.nixosSystem {
|
||||
inherit system;
|
||||
modules = [
|
||||
inputs.disko.nixosModules.disko
|
||||
sops-nix.nixosModules.sops
|
||||
./modules/common/configuration.nix
|
||||
./modules/platforms/${platform}.nix
|
||||
./modules/build-types/${buildType}.nix
|
||||
hostPath
|
||||
{ environment.etc."flake-target".text = "${platform}-${buildType}"; }
|
||||
home-manager.nixosModules.home-manager
|
||||
{
|
||||
home-manager = {
|
||||
useGlobalPkgs = true;
|
||||
useUserPackages = true;
|
||||
users.nixos = import homeFile;
|
||||
};
|
||||
}
|
||||
] ++ lib.optionals (buildType != "nix-cache") [
|
||||
./modules/nix-cache/client.nix
|
||||
./modules/remote-builder-client.nix
|
||||
];
|
||||
specialArgs = { inherit inputs; };
|
||||
};
|
||||
|
||||
# Generated platform x build-type matrix. pxe-boot has no linode
|
||||
# variant (PXE/DHCP/TFTP need LAN L2 adjacency, which a Linode VPS
|
||||
# doesn't have).
|
||||
generatedTargets = {
|
||||
linode-minimal = mkTarget { platform = "linode"; buildType = "minimal"; hostPath = ./hosts/linode-minimal/host.nix; };
|
||||
proxmox-minimal = mkTarget { platform = "proxmox"; buildType = "minimal"; hostPath = ./hosts/proxmox-minimal/host.nix; };
|
||||
lxc-minimal = mkTarget { platform = "lxc"; buildType = "minimal"; hostPath = ./hosts/lxc-minimal/host.nix; };
|
||||
|
||||
linode-nix-cache = mkTarget { platform = "linode"; buildType = "nix-cache"; hostPath = ./hosts/nix-cache/host.nix; };
|
||||
proxmox-nix-cache = mkTarget { platform = "proxmox"; buildType = "nix-cache"; hostPath = ./hosts/nix-cache/host.nix; };
|
||||
lxc-nix-cache = mkTarget { platform = "lxc"; buildType = "nix-cache"; hostPath = ./hosts/nix-cache/host.nix; };
|
||||
|
||||
linode-server = mkTarget { platform = "linode"; buildType = "server"; hostPath = ./hosts/server/host.nix; };
|
||||
proxmox-server = mkTarget { platform = "proxmox"; buildType = "server"; hostPath = ./hosts/server/host.nix; };
|
||||
lxc-server = mkTarget { platform = "lxc"; buildType = "server"; hostPath = ./hosts/server/host.nix; };
|
||||
|
||||
linode-docker = mkTarget { platform = "linode"; buildType = "docker"; hostPath = ./hosts/docker/host.nix; };
|
||||
proxmox-docker = mkTarget { platform = "proxmox"; buildType = "docker"; hostPath = ./hosts/docker/host.nix; };
|
||||
lxc-docker = mkTarget { platform = "lxc"; buildType = "docker"; hostPath = ./hosts/docker/host.nix; };
|
||||
|
||||
linode-gui = mkTarget { platform = "linode"; buildType = "gui"; hostPath = ./hosts/nixos/host.nix; homeFile = ./hosts/nixos/home.nix; };
|
||||
proxmox-gui = mkTarget { platform = "proxmox"; buildType = "gui"; hostPath = ./hosts/nixos/host.nix; homeFile = ./hosts/nixos/home.nix; };
|
||||
lxc-gui = mkTarget { platform = "lxc"; buildType = "gui"; hostPath = ./hosts/nixos/host.nix; homeFile = ./hosts/nixos/home.nix; };
|
||||
|
||||
proxmox-pxe-boot = mkTarget { platform = "proxmox"; buildType = "pxe-boot"; hostPath = ./hosts/pxe-boot/host.nix; };
|
||||
lxc-pxe-boot = mkTarget { platform = "lxc"; buildType = "pxe-boot"; hostPath = ./hosts/pxe-boot/host.nix; };
|
||||
};
|
||||
|
||||
in
|
||||
{
|
||||
|
||||
nixosConfigurations = generatedTargets;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
# Edit this configuration file to define what should be installed on
|
||||
# your system. Help is available in the configuration.nix(5) man page, on
|
||||
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
|
||||
|
||||
{ config, lib, pkgs, inputs, ... }:
|
||||
|
||||
let
|
||||
pythonEnv = pkgs.python3.withPackages (ps: with ps; [
|
||||
docker
|
||||
pytz
|
||||
]);
|
||||
in
|
||||
|
||||
{
|
||||
imports =
|
||||
[ # Include the results of the hardware scan.
|
||||
../../common/configuration.nix
|
||||
];
|
||||
|
||||
networking.hostName = "docker"; # Define your hostname.
|
||||
virtualisation.docker.enable = true;
|
||||
|
||||
# Enable docker-compose
|
||||
environment.systemPackages = with pkgs; [
|
||||
docker-compose
|
||||
];
|
||||
|
||||
# Mount docker persistent data
|
||||
fileSystems."/mnt/docker-persistent-data" = {
|
||||
device = "/dev/disk/by-label/docker-data";
|
||||
fsType = "ext4";
|
||||
options = [ "defaults" "nofail" "noatime" ];
|
||||
};
|
||||
|
||||
# Create nextcloud cron scheduled task
|
||||
systemd.services.nextcloud = {
|
||||
description = "Nextcloud scheduled task";
|
||||
script = ''docker-compose -f ~/docker/nextcloud/docker-compose.yml exec -u 33 webapp php ./cron.php'';
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "nixos";
|
||||
};
|
||||
path = with pkgs; [ docker docker-compose ];
|
||||
};
|
||||
|
||||
systemd.timers.nextcloud = {
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = "*:0/5";
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
|
||||
# create update task
|
||||
|
||||
systemd.services.update-containers = {
|
||||
description = "Update Docker Compose Containers";
|
||||
after = [ "docker.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "nixos";
|
||||
WorkingDirectory = "/home/nixos/docker";
|
||||
ExecStart = "${pythonEnv}/bin/python3 /home/nixos/docker/update-containers.py";
|
||||
StandardOutput = "journal";
|
||||
StandardError = "journal";
|
||||
};
|
||||
|
||||
path = [ pkgs.docker pkgs.docker-compose ]; # Ensures docker CLI is available in $PATH
|
||||
};
|
||||
|
||||
|
||||
systemd.timers.update-containers = {
|
||||
description = "Weekly + Reboot container update";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnBootSec = "5min"; # Run 5 minutes after boot
|
||||
OnUnitActiveSec = "1w"; # Run every week after last run
|
||||
Persistent = true; # Catch up if system was off
|
||||
};
|
||||
};
|
||||
|
||||
#Add sym links to data on users home folder
|
||||
system.userActivationScripts.createDockerSymlink.text = ''
|
||||
ln -sf /mnt/docker-persistent-data/docker /home/nixos/docker
|
||||
'';
|
||||
system.userActivationScripts.createSetupSymlink.text = ''
|
||||
ln -sf /mnt/docker-persistent-data/setup /home/nixos/setup
|
||||
'';
|
||||
|
||||
users.users.nixos.extraGroups = [ "docker" ];
|
||||
services.openssh.settings.PermitRootLogin = "yes";
|
||||
|
||||
# Open ports in the firewall.
|
||||
networking.firewall.allowedTCPPorts = [ 80 8080 443 ];
|
||||
# networking.firewall.allowedUDPPorts = [ ... ];
|
||||
# Or disable the firewall altogether.
|
||||
# networking.firewall.enable = false;
|
||||
|
||||
# Copy the NixOS configuration file and link it from the resulting system
|
||||
# (/run/current-system/configuration.nix). This is useful in case you
|
||||
# accidentally delete configuration.nix.
|
||||
# system.copySystemConfiguration = true;
|
||||
|
||||
# This option defines the first version of NixOS you have installed on this particular machine,
|
||||
# and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
|
||||
#
|
||||
# Most users should NEVER change this value after the initial install, for any reason,
|
||||
# even if you've upgraded your system to a new NixOS release.
|
||||
#
|
||||
# This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
|
||||
# so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
|
||||
# to actually do that.
|
||||
#
|
||||
# This value being lower than the current NixOS release does NOT mean your system is
|
||||
# out of date, out of support, or vulnerable.
|
||||
#
|
||||
# Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
|
||||
# and migrated your data accordingly.
|
||||
#
|
||||
# For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.sta>
|
||||
system.stateVersion = "25.05"; # Did you read the comment?
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
networking.hostName = "docker";
|
||||
networking.hostId = "007f0200";
|
||||
boot.zfs.forceImportRoot = false;
|
||||
|
||||
# Preserved from the pre-refactor `docker` target — stateVersion must never
|
||||
# be bumped on an already-installed machine.
|
||||
system.stateVersion = "25.05";
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
networking.hostName = "linode-minimal";
|
||||
|
||||
# Preserved from the pre-refactor `linode-minimal` target — stateVersion
|
||||
# must never be bumped on an already-installed machine.
|
||||
system.stateVersion = "26.05";
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
networking.hostName = "lxc-minimal";
|
||||
|
||||
# No pre-existing deployed machine to preserve — pin explicitly to the
|
||||
# current release rather than let it silently default.
|
||||
system.stateVersion = "26.05";
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
# Edit this configuration file to define what should be installed on
|
||||
# your system. Help is available in the configuration.nix(5) man page, on
|
||||
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
|
||||
|
||||
{ config, lib, pkgs, inputs, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ # Include the results of the hardware scan.
|
||||
../../common/configuration.nix
|
||||
];
|
||||
|
||||
networking.hostName = "nix-cache"; # Define your hostname.
|
||||
|
||||
services.nix-serve.enable = true;
|
||||
services.nix-serve.secretKeyFile = "/etc/nix/cache-priv.pem";
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedProxySettings = true;
|
||||
virtualHosts."cache.local" = {
|
||||
locations."/".proxyPass = "http://${config.services.nix-serve.bindAddress}:${toString config.services.nix-serve.port}";
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ config.services.nginx.defaultHTTPListenPort ];
|
||||
# Open ports in the firewall.
|
||||
# networking.firewall.allowedTCPPorts = [ 80 8080 443 ];
|
||||
# networking.firewall.allowedUDPPorts = [ ... ];
|
||||
# Or disable the firewall altogether.
|
||||
# networking.firewall.enable = false;
|
||||
|
||||
# Copy the NixOS configuration file and link it from the resulting system
|
||||
# (/run/current-system/configuration.nix). This is useful in case you
|
||||
# accidentally delete configuration.nix.
|
||||
# system.copySystemConfiguration = true;
|
||||
|
||||
# This option defines the first version of NixOS you have installed on this particular machine,
|
||||
# and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
|
||||
#
|
||||
# Most users should NEVER change this value after the initial install, for any reason,
|
||||
# even if you've upgraded your system to a new NixOS release.
|
||||
#
|
||||
# This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
|
||||
# so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
|
||||
# to actually do that.
|
||||
#
|
||||
# This value being lower than the current NixOS release does NOT mean your system is
|
||||
# out of date, out of support, or vulnerable.
|
||||
#
|
||||
# Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
|
||||
# and migrated your data accordingly.
|
||||
#
|
||||
# For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.sta>
|
||||
system.stateVersion = "25.05"; # Did you read the comment?
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
{ config, ... }:
|
||||
|
||||
{
|
||||
networking.hostName = "nix-cache";
|
||||
|
||||
sops.secrets."beszel-token".sopsFile = ../../secrets/nix-cache.yaml;
|
||||
sops.templates."nix-cache-beszel.env".content = ''
|
||||
TOKEN=${config.sops.placeholder."beszel-token"}
|
||||
'';
|
||||
|
||||
services.beszel.agent.environment = {
|
||||
#DOCKER_HOST = "tcp://docker-socket-proxy:2375";
|
||||
#HUB_URL = "http://docker.sweet.home:8090";
|
||||
KEY = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFPR9kwtC4TAeTRu46A7+opZsYpxqkRJ+x/ZyB2GWCeG";
|
||||
};
|
||||
services.beszel.agent.environmentFile = config.sops.templates."nix-cache-beszel.env".path;
|
||||
|
||||
# Preserved from the pre-refactor `nix-cache` target — stateVersion must
|
||||
# never be bumped on an already-installed machine.
|
||||
system.stateVersion = "25.05";
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
# Edit this configuration file to define what should be installed on
|
||||
# your system. Help is available in the configuration.nix(5) man page
|
||||
# and in the NixOS manual (accessible by running ‘nixos-help’).
|
||||
|
||||
{ config, pkgs, lib, inputs,... }:
|
||||
let
|
||||
nixosConfEditor = builtins.getFlake "github:snowfallorg/nixos-conf-editor";
|
||||
in {
|
||||
#{
|
||||
environment.systemPackages = with pkgs; [
|
||||
inputs.nixos-conf-editor.packages.${pkgs.system}.nixos-conf-editor
|
||||
nodejs
|
||||
appimage-run
|
||||
seahorse
|
||||
|
||||
];
|
||||
|
||||
|
||||
|
||||
imports =
|
||||
[ # Include the results of the hardware scan.
|
||||
../../common/configuration.nix
|
||||
];
|
||||
|
||||
# Bootloader.
|
||||
boot.loader.grub.useOSProber = true;
|
||||
|
||||
networking.hostName = "nixos"; # Define your hostname.
|
||||
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
|
||||
|
||||
# Select internationalisation properties.
|
||||
i18n.defaultLocale = "en_AU.UTF-8";
|
||||
|
||||
i18n.extraLocaleSettings = {
|
||||
LC_ADDRESS = "en_AU.UTF-8";
|
||||
LC_IDENTIFICATION = "en_AU.UTF-8";
|
||||
LC_MEASUREMENT = "en_AU.UTF-8";
|
||||
LC_MONETARY = "en_AU.UTF-8";
|
||||
LC_NAME = "en_AU.UTF-8";
|
||||
LC_NUMERIC = "en_AU.UTF-8";
|
||||
LC_PAPER = "en_AU.UTF-8";
|
||||
LC_TELEPHONE = "en_AU.UTF-8";
|
||||
LC_TIME = "en_AU.UTF-8";
|
||||
};
|
||||
|
||||
# Enable the X11 windowing system.
|
||||
services.xserver.enable = true;
|
||||
|
||||
# Enable the Cinnamon Desktop Environment.
|
||||
services.xserver.displayManager.lightdm.enable = true;
|
||||
services.xserver.desktopManager.cinnamon.enable = true;
|
||||
# services.xserver.desktopManager.xfce.enable = true;
|
||||
|
||||
# Configure keymap in X11
|
||||
services.xserver.xkb = {
|
||||
layout = "au";
|
||||
variant = "";
|
||||
};
|
||||
|
||||
# Enable CUPS to print documents.
|
||||
services.printing.enable = true;
|
||||
|
||||
# Enable sound with pipewire.
|
||||
# services.pulseaudio.enable = false;
|
||||
security.rtkit.enable = true;
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
alsa.support32Bit = true;
|
||||
pulse.enable = true;
|
||||
# If you want to use JACK applications, uncomment this
|
||||
#jack.enable = true;
|
||||
|
||||
# use the example session manager (no others are packaged yet so this is enabled by default,
|
||||
# no need to redefine it in your config for now)
|
||||
#media-session.enable = true;
|
||||
};
|
||||
|
||||
# Enable touchpad support (enabled default in most desktopManager).
|
||||
# services.xserver.libinput.enable = true;
|
||||
|
||||
users.users.nixos.extraGroups = [ "networkmanager" ]; # Enable ‘sudo’ for the user.
|
||||
|
||||
# Install firefox.
|
||||
programs.firefox.enable = true;
|
||||
|
||||
system.stateVersion = "25.05"; # Did you read the comment?
|
||||
|
||||
|
||||
nix.settings.experimental-features = "nix-command flakes";
|
||||
services.xrdp.enable = true;
|
||||
services.xrdp.defaultWindowManager = "cinnamon-session";
|
||||
services.xrdp.openFirewall = true;
|
||||
|
||||
# systemd.services.nextcloud-appimage = {
|
||||
# enable = true;
|
||||
# Unit = {
|
||||
# Description = "Nextcloud AppImage client";
|
||||
# After = [ "graphical-session.target" ];
|
||||
# Wants = [ "graphical-session.target" ]; # optional but helpful
|
||||
# };
|
||||
# Service = {
|
||||
# ExecStart = "/run/current-system/sw/bin/appimage-run /home/nixos/Applications/Nextcloud.AppImage --background";
|
||||
# Restart = "on-failure";
|
||||
# # You can add RestartSec = "5s"; if you like
|
||||
# };
|
||||
# Install = {
|
||||
# WantedBy = [ "default.target" ];
|
||||
# };
|
||||
# };
|
||||
|
||||
}
|
||||
@@ -1,6 +1,11 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
|
||||
imports = [
|
||||
../../modules/common/aliases.nix
|
||||
];
|
||||
|
||||
home.username = "nixos"; # your actual username
|
||||
home.homeDirectory = "/home/nixos";
|
||||
home.stateVersion = "25.05"; # match your NixOS stateVersion
|
||||
@@ -13,6 +18,8 @@
|
||||
vim
|
||||
tmux
|
||||
nextcloud-client
|
||||
# vscode
|
||||
chromium
|
||||
];
|
||||
|
||||
# Optional: set environment vars
|
||||
@@ -27,5 +34,46 @@
|
||||
# Optionally start in background directly
|
||||
startInBackground = true;
|
||||
};
|
||||
home.file = {
|
||||
".local/share/applications/proxmox-chromium-app.desktop".text = ''
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Proxmox (Chromium)
|
||||
Exec=chromium --app=https://pve.sweet.home:8006 --window-size=1920,1080 --window-position=0,0
|
||||
Icon=/home/nixos/.local/share/icons/proxmox.png
|
||||
Terminal=false
|
||||
Categories=Hypervisor;
|
||||
StartupWMClass=PVE
|
||||
'';
|
||||
".local/share/applications/pbs-chromium-app.desktop".text = ''
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Proxmox Backup Server (Chromium)
|
||||
Exec=chromium --app=https://192.168.2.108:8007 --window-size=1920,1080 --window-position=0,0
|
||||
Icon=/home/nixos/.local/share/icons/proxmox.png
|
||||
Terminal=false
|
||||
Categories=backup;
|
||||
|
||||
'';
|
||||
".local/share/applications/proxmox-firefox-app.desktop".text = ''
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Proxmox (Firefox)
|
||||
Exec=firefox --new-instance https://pve.sweet.home:8006 --profile ProxmoxWebApp --window-size=1920,1080 --class ProxmoxWebApp
|
||||
Icon=/home/nixos/.local/share/icons/proxmox.png
|
||||
Terminal=false
|
||||
Categories=Hypervisor;
|
||||
StartupWMClass=PVE
|
||||
'';
|
||||
".local/share/applications/pbs-firefox-app.desktop".text = ''
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Proxmox Backup Server (Firefox)
|
||||
Exec=firefox --new-window https://192.168.2.108:8007 --profile PbsWebApp --window-size=1920,1080 --class PbsWebApp
|
||||
Icon=/home/nixos/.local/share/icons/proxmox.png
|
||||
Terminal=false
|
||||
Categories=backup;
|
||||
StartupWMClass=PBS
|
||||
'';
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
networking.hostName = "nixos";
|
||||
|
||||
# Preserved from the pre-refactor `nixos` target — stateVersion must never
|
||||
# be bumped on an already-installed machine.
|
||||
system.stateVersion = "25.05";
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
# Preserves the hostname of the existing, already-deployed machine
|
||||
# (previously the flat `nix-minimal` target) — the flake attribute name
|
||||
# changed, the real machine's hostname did not.
|
||||
networking.hostName = "nix-minimal";
|
||||
|
||||
# Preserved from the pre-refactor `nix-minimal` target — stateVersion must
|
||||
# never be bumped on an already-installed machine.
|
||||
system.stateVersion = "25.05";
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
networking.hostName = "pxe-boot";
|
||||
|
||||
# Preserved from the pre-refactor `pxe-boot` target — stateVersion must
|
||||
# never be bumped on an already-installed machine.
|
||||
system.stateVersion = "25.05";
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
# Edit this configuration file to define what should be installed on
|
||||
# your system. Help is available in the configuration.nix(5) man page, on
|
||||
# https://search.nixos.org/options and in the NixOS manual (`nixos-help`).
|
||||
|
||||
{ config, lib, pkgs, inputs,... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ # Include the results of the hardware scan.
|
||||
../../common/configuration.nix
|
||||
];
|
||||
|
||||
networking.hostName = "server"; # Define your hostname.
|
||||
# Pick only one of the below networking options.
|
||||
# networking.wireless.enable = true; # Enables wireless support via wpa_supplicant.
|
||||
|
||||
# Mount server data
|
||||
fileSystems."/srv" = {
|
||||
device = "/dev/disk/by-label/server-data";
|
||||
fsType = "ext4";
|
||||
options = [ "defaults" ];
|
||||
};
|
||||
|
||||
fileSystems."/backup" = {
|
||||
device = "/dev/disk/by-label/backup-data";
|
||||
fsType = "ext4";
|
||||
options = [ "defaults" ];
|
||||
};
|
||||
|
||||
#Add sym links to data on users home folder
|
||||
system.userActivationScripts.createDockerSymlink.text = ''
|
||||
ln -sf /srv/scripts /home/nixos/scripts
|
||||
'';
|
||||
#system.userActivationScripts.createSetupSymlink.text = ''
|
||||
# ln -sf /mnt/docker-persistent-data/setup /home/nixos/setup
|
||||
#'';
|
||||
|
||||
services.nfs.server = {
|
||||
enable = true;
|
||||
exports = ''
|
||||
/srv/ 192.168.2.0/24(rw,sync,no_subtree_check)
|
||||
/backup 192.168.2.0/24(rw,sync,no_subtree_check)
|
||||
'';
|
||||
};
|
||||
|
||||
security.sudo = {
|
||||
enable = true;
|
||||
extraRules = [
|
||||
{
|
||||
users = [ "nixos" ];
|
||||
commands = [
|
||||
{
|
||||
command = "/run/current-system/sw/bin/rsync";
|
||||
options = [ "NOPASSWD" ];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
systemd.services.backup = {
|
||||
description = "Backup data";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "root";
|
||||
# WorkingDirectory = "/home/nixos/scripts";
|
||||
ExecStart = "${pkgs.bash}/bin/bash -e /srv/scripts/rsync.sh";
|
||||
StandardOutput = "journal";
|
||||
StandardError = "journal";
|
||||
};
|
||||
path = with pkgs; [ bash rsync openssh coreutils ];
|
||||
};
|
||||
|
||||
|
||||
systemd.timers.backup = {
|
||||
description = "Daily backup";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnUnitActiveSec = "1d"; # Run every day after last run
|
||||
Persistent = true; # Catch up if system was off
|
||||
};
|
||||
};
|
||||
|
||||
services.openssh.settings.PermitRootLogin = "yes";
|
||||
# Open ports in the firewall.
|
||||
networking.firewall.allowedTCPPorts = [ 2049 ];
|
||||
# networking.firewall.allowedUDPPorts = [ 111 2049 20048 ];
|
||||
# Or disable the firewall altogether.
|
||||
# networking.firewall.enable = false;
|
||||
|
||||
# Copy the NixOS configuration file and link it from the resulting system
|
||||
# (/run/current-system/configuration.nix). This is useful in case you
|
||||
# accidentally delete configuration.nix.
|
||||
# system.copySystemConfiguration = true;
|
||||
|
||||
# This option defines the first version of NixOS you have installed on this particular machine,
|
||||
# and is used to maintain compatibility with application data (e.g. databases) created on older NixOS versions.
|
||||
#
|
||||
# Most users should NEVER change this value after the initial install, for any reason,
|
||||
# even if you've upgraded your system to a new NixOS release.
|
||||
#
|
||||
# This value does NOT affect the Nixpkgs version your packages and OS are pulled from,
|
||||
# so changing it will NOT upgrade your system - see https://nixos.org/manual/nixos/stable/#sec-upgrading for how
|
||||
# to actually do that.
|
||||
#
|
||||
# This value being lower than the current NixOS release does NOT mean your system is
|
||||
# out of date, out of support, or vulnerable.
|
||||
#
|
||||
# Do NOT change this value unless you have manually inspected all the changes it would make to your configuration,
|
||||
# and migrated your data accordingly.
|
||||
#
|
||||
# For more information, see `man configuration.nix` or https://nixos.org/manual/nixos/stable/options#opt-system.sta>
|
||||
system.stateVersion = "25.05"; # Did you read the comment?
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
{ config, ... }:
|
||||
|
||||
{
|
||||
networking.hostName = "server";
|
||||
networking.hostId = "6689f93e";
|
||||
|
||||
sops.secrets."beszel-token".sopsFile = ../../secrets/server.yaml;
|
||||
sops.templates."server-beszel.env".content = ''
|
||||
TOKEN=${config.sops.placeholder."beszel-token"}
|
||||
'';
|
||||
|
||||
services.beszel.agent.environment = {
|
||||
#DOCKER_HOST = "tcp://docker-socket-proxy:2375";
|
||||
#HUB_URL = "http://docker.sweet.home:8090";
|
||||
KEY = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFPR9kwtC4TAeTRu46A7+opZsYpxqkRJ+x/ZyB2GWCeG";
|
||||
EXTRA_FILESYSTEMS = "/tank/docker/volumes";
|
||||
LOG_LEVEL = "debug";
|
||||
};
|
||||
services.beszel.agent.environmentFile = config.sops.templates."server-beszel.env".path;
|
||||
|
||||
# Preserved from the pre-refactor `server` target — stateVersion must never
|
||||
# be bumped on an already-installed machine.
|
||||
system.stateVersion = "25.05";
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
services.beszel.agent.enable = true;
|
||||
services.beszel.agent.environment = {
|
||||
#DOCKER_HOST = "tcp://docker-socket-proxy:2375";
|
||||
HUB_URL = "http://docker.sweet.home:8090";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
boot.loader.efi.canTouchEfiVariables = true;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
# Pins the Docker Engine version, carried forward from the pre-refactor
|
||||
# `docker` target's inline pkgs overlay.
|
||||
nixpkgs.overlays = [
|
||||
(final: prev: {
|
||||
docker = prev.docker_29;
|
||||
docker_cli = prev.docker_29;
|
||||
})
|
||||
];
|
||||
|
||||
imports = [
|
||||
../docker/mount-data.nix
|
||||
../docker/enable-service.nix
|
||||
../tailscale/enable-service.nix
|
||||
../rotate-traefik-logs.nix
|
||||
../raspi/mount-data.nix
|
||||
../services/nextcloud-cron-job.nix
|
||||
../services/docker-health-to-gotify.nix
|
||||
../services/enable-rpcbind.nix
|
||||
];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
nfs-utils
|
||||
];
|
||||
|
||||
boot.supportedFilesystems = [ "nfs" ];
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"L+ /home/nixos/docker - - - - /mnt/docker/config"
|
||||
"d /mnt/docker 0755 nixos users -"
|
||||
"d /mnt/raspi-backup 0755 nixos users -"
|
||||
];
|
||||
|
||||
users.users.nixos.extraGroups = [ "docker" ];
|
||||
services.openssh.settings.PermitRootLogin = "yes";
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 8080 443 8090 ];
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
{ config, pkgs, lib, inputs, ... }:
|
||||
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
inputs.nixos-conf-editor.packages.${pkgs.system}.nixos-conf-editor
|
||||
nodejs
|
||||
appimage-run
|
||||
seahorse
|
||||
vscode
|
||||
p7zip
|
||||
popsicle # balena-etcher
|
||||
shotcut
|
||||
gimp
|
||||
pdfarranger
|
||||
terminator
|
||||
libreoffice-qt
|
||||
transmission_4-qt
|
||||
];
|
||||
|
||||
boot.loader.grub.useOSProber = true;
|
||||
|
||||
services.xserver.enable = true;
|
||||
services.xserver.displayManager.lightdm.enable = true;
|
||||
services.xserver.desktopManager.cinnamon.enable = true;
|
||||
|
||||
services.xserver.xkb = {
|
||||
layout = "au";
|
||||
variant = "";
|
||||
};
|
||||
|
||||
services.printing.enable = true;
|
||||
|
||||
security.rtkit.enable = true;
|
||||
services.pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
alsa.support32Bit = true;
|
||||
pulse.enable = true;
|
||||
};
|
||||
|
||||
users.users.nixos.extraGroups = [ "networkmanager" ];
|
||||
|
||||
programs.firefox.enable = true;
|
||||
|
||||
services.xrdp.enable = true;
|
||||
services.xrdp.defaultWindowManager = "cinnamon-session";
|
||||
services.xrdp.openFirewall = true;
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
|
||||
services.gnome.gnome-keyring.enable = true;
|
||||
security.pam.services.login.enableGnomeKeyring = true;
|
||||
|
||||
services.xserver.displayManager.sessionCommands = ''
|
||||
eval $(gnome-keyring-daemon --start --components=secrets,ssh)
|
||||
export SSH_AUTH_SOCK
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
networking.networkmanager.enable = true;
|
||||
|
||||
users.users.nixos.extraGroups = [ "networkmanager" ];
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
inetutils
|
||||
mtr
|
||||
sysstat
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
../nix-cache/server.nix
|
||||
../beszel/enable-agent.nix
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
{ config, lib, pkgs, inputs, ... }:
|
||||
|
||||
let
|
||||
pxeRoot = "/srv/pxe";
|
||||
httpRoot = "${pxeRoot}/http";
|
||||
tftpRoot = "${pxeRoot}/tftp";
|
||||
pxeBaseUrl = "http://192.168.2.247";
|
||||
|
||||
bootIpxe = pkgs.writeText "boot.ipxe" ''
|
||||
#!ipxe
|
||||
|
||||
dhcp
|
||||
echo Booting from PXE server...
|
||||
chain ${pxeBaseUrl}/menu.ipxe
|
||||
'';
|
||||
|
||||
autoexecIpxe = pkgs.writeText "autoexec.ipxe" ''
|
||||
#!ipxe
|
||||
|
||||
dhcp
|
||||
chain ${pxeBaseUrl}/boot.ipxe
|
||||
'';
|
||||
|
||||
systemRescueIpxe = pkgs.writeText "systemrescue.ipxe" ''
|
||||
#!ipxe
|
||||
|
||||
set base ${pxeBaseUrl}
|
||||
|
||||
kernel ''${base}/systemrescue/sysresccd/boot/x86_64/vmlinuz initrd=sysresccd.img archisobasedir=sysresccd archiso_http_srv=''${base}/systemrescue/ ip=dhcp checksum
|
||||
initrd ''${base}/systemrescue/sysresccd/boot/x86_64/sysresccd.img sysresccd.img
|
||||
boot
|
||||
'';
|
||||
|
||||
stageSystemRescue = pkgs.writeShellScript "stage-systemrescue" ''
|
||||
set -eu
|
||||
|
||||
iso="${httpRoot}/images/systemrescue.iso"
|
||||
staged="${httpRoot}/systemrescue"
|
||||
tmp="${httpRoot}/.systemrescue.tmp"
|
||||
previous="${httpRoot}/.systemrescue.previous"
|
||||
|
||||
if [ ! -e "$iso" ]; then
|
||||
echo "SystemRescue ISO not found at $iso; skipping staging."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
rm -rf "$tmp"
|
||||
mkdir -p "$tmp"
|
||||
|
||||
${pkgs.libarchive}/bin/bsdtar -C "$tmp" -xf "$iso"
|
||||
|
||||
test -f "$tmp/sysresccd/boot/x86_64/vmlinuz"
|
||||
test -f "$tmp/sysresccd/boot/x86_64/sysresccd.img"
|
||||
chmod -R a+rX "$tmp"
|
||||
|
||||
rm -rf "$previous"
|
||||
if [ -e "$staged" ]; then
|
||||
mv "$staged" "$previous"
|
||||
fi
|
||||
|
||||
mv "$tmp" "$staged"
|
||||
rm -rf "$previous"
|
||||
'';
|
||||
|
||||
menuIpxe = pkgs.writeText "menu.ipxe" ''
|
||||
#!ipxe
|
||||
|
||||
set base ${pxeBaseUrl}
|
||||
|
||||
menu PXE Boot Menu
|
||||
item nixos NixOS Installer
|
||||
item rescue Rescue Environment
|
||||
item shell iPXE Shell
|
||||
item reboot Reboot
|
||||
|
||||
choose target && goto ''${target}
|
||||
|
||||
:nixos
|
||||
kernel ''${base}/nixos/bzImage ip=dhcp
|
||||
initrd ''${base}/nixos/initrd
|
||||
boot
|
||||
|
||||
:rescue
|
||||
chain ''${base}/systemrescue.ipxe
|
||||
|
||||
:shell
|
||||
shell
|
||||
|
||||
:reboot
|
||||
reboot
|
||||
'';
|
||||
in
|
||||
{
|
||||
environment.systemPackages = with pkgs; [
|
||||
ipxe
|
||||
];
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
|
||||
virtualHosts."pxe-boot" = {
|
||||
default = true;
|
||||
root = httpRoot;
|
||||
locations."/" = {
|
||||
extraConfig = ''
|
||||
autoindex on;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# TFTP is only used to deliver the initial iPXE bootloader. After iPXE
|
||||
# starts, all further assets are fetched via nginx over HTTP.
|
||||
services.atftpd = {
|
||||
enable = true;
|
||||
root = tftpRoot;
|
||||
extraOptions = [
|
||||
"--verbose=5"
|
||||
];
|
||||
};
|
||||
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${pxeRoot} 0755 root root -"
|
||||
"d ${httpRoot} 0755 root root -"
|
||||
"d ${httpRoot}/images 0755 root root -"
|
||||
"d ${httpRoot}/nixos 0755 root root -"
|
||||
"d ${httpRoot}/systemrescue 0755 root root -"
|
||||
"d ${httpRoot}/ubuntu 0755 root root -"
|
||||
"d ${httpRoot}/rescue 0755 root root -"
|
||||
"d ${tftpRoot} 0755 root root -"
|
||||
"C+ ${httpRoot}/boot.ipxe 0644 root root - ${bootIpxe}"
|
||||
"C+ ${httpRoot}/menu.ipxe 0644 root root - ${menuIpxe}"
|
||||
"C+ ${httpRoot}/systemrescue.ipxe 0644 root root - ${systemRescueIpxe}"
|
||||
"C+ ${tftpRoot}/autoexec.ipxe 0644 root root - ${autoexecIpxe}"
|
||||
"C+ ${tftpRoot}/ipxe.efi 0644 root root - ${pkgs.ipxe}/ipxe.efi"
|
||||
"C+ ${tftpRoot}/undionly.kpxe 0644 root root - ${pkgs.ipxe}/undionly.kpxe"
|
||||
];
|
||||
|
||||
systemd.services.stage-systemrescue = {
|
||||
description = "Stage SystemRescue ISO contents for HTTP PXE boot";
|
||||
after = [
|
||||
"local-fs.target"
|
||||
"systemd-tmpfiles-setup.service"
|
||||
];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = stageSystemRescue;
|
||||
};
|
||||
};
|
||||
|
||||
services.openssh.settings.PermitRootLogin = "yes";
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
networking.firewall.allowedUDPPorts = [ 69 ];
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
../beszel/enable-agent.nix
|
||||
../services/zfs/enable-service.nix
|
||||
];
|
||||
|
||||
boot.zfs.extraPools = [ "tank" ];
|
||||
|
||||
systemd.services.nfs-server = {
|
||||
after = [ "zfs-mount.service" ];
|
||||
requires = [ "zfs-mount.service" ];
|
||||
};
|
||||
|
||||
services.nfs.server = {
|
||||
enable = true;
|
||||
exports = ''
|
||||
/tank/docker/config 192.168.2.0/24(rw,sync,no_subtree_check,no_root_squash)
|
||||
/tank/docker/volumes 192.168.2.0/24(rw,sync,no_subtree_check,no_root_squash)
|
||||
/tank/docker/databases 192.168.2.0/24(rw,sync,no_subtree_check,no_root_squash)
|
||||
/tank/docker/nextcloud-data 192.168.2.0/24(rw,sync,no_subtree_check,no_root_squash)
|
||||
/tank/raspi/volumes 192.168.2.0/24(rw,sync,no_subtree_check,no_root_squash)
|
||||
'';
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 111 2049 ];
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
# Flake attribute names are now <platform>-<buildtype> (e.g. proxmox-docker)
|
||||
# and no longer match networking.hostName, since a host's hostname stays
|
||||
# fixed while the platform backing it can change. Each nixosConfiguration
|
||||
# stamps its own active target name into /etc/flake-target at build time.
|
||||
mySwitchCmd = ''
|
||||
sudo nixos-rebuild switch \
|
||||
--no-write-lock-file \
|
||||
--refresh \
|
||||
--flake git+https://gitea.lan.ddnsgeek.com/beatzaplenty/nixos.git#$(cat /etc/flake-target)
|
||||
'';
|
||||
myTestCmd = ''
|
||||
sudo nixos-rebuild test \
|
||||
--no-write-lock-file \
|
||||
--refresh \
|
||||
--flake git+https://gitea.lan.ddnsgeek.com/beatzaplenty/nixos.git#$(cat /etc/flake-target)
|
||||
'';
|
||||
in
|
||||
{
|
||||
programs.bash = {
|
||||
enable = true;
|
||||
shellAliases = {
|
||||
"Switch-nix" = mySwitchCmd;
|
||||
"Test-nix" = myTestCmd;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ # Include the results of the hardware scan.
|
||||
# ./hardware-configuration.nix
|
||||
../set-locale.nix
|
||||
];
|
||||
# Use the GRUB 2 boot loader.
|
||||
# boot.loader.grub.enable = true;
|
||||
#boot.loader.grub.device = "/dev/sda"; # or "nodev" for efi only
|
||||
|
||||
networking.networkmanager.enable = true; # Easiest to use and most distros use this by default.
|
||||
|
||||
# Set your time zone.
|
||||
time.timeZone = "Australia/Brisbane";
|
||||
|
||||
# Enable QEMU agent
|
||||
services.qemuGuest.enable = true;
|
||||
|
||||
# Enable docker-compose
|
||||
environment.systemPackages = with pkgs; [
|
||||
vim
|
||||
btop
|
||||
git
|
||||
gcr
|
||||
];
|
||||
|
||||
# Secrets shared by every host, decrypted at activation via each host's
|
||||
# existing SSH host key (sops-nix derives the age key from
|
||||
# /etc/ssh/ssh_host_ed25519_key automatically — see modules/common/README
|
||||
# or docs/ for the sops workflow). hashedPassword/hashedPasswordFile need
|
||||
# neededForUsers so they're available before the normal secret-activation
|
||||
# step, since user creation happens very early in boot.
|
||||
sops.defaultSopsFile = ../../secrets/common.yaml;
|
||||
sops.secrets."root-hashedPassword".neededForUsers = true;
|
||||
sops.secrets."nixos-hashedPassword".neededForUsers = true;
|
||||
sops.secrets."nix-github-token" = { };
|
||||
|
||||
# nix.conf doesn't support a *File-style option for access-tokens, so the
|
||||
# token is rendered into a runtime-only file (never touches the Nix store)
|
||||
# and pulled in via nix.conf's native !include directive.
|
||||
sops.templates."nix-github-token.conf".content = ''
|
||||
access-tokens = github.com=${config.sops.placeholder."nix-github-token"}
|
||||
'';
|
||||
nix.extraOptions = ''
|
||||
!include ${config.sops.templates."nix-github-token.conf".path}
|
||||
'';
|
||||
|
||||
#Set root password
|
||||
users.users.root = {
|
||||
hashedPasswordFile = config.sops.secrets."root-hashedPassword".path;
|
||||
};
|
||||
|
||||
# Define a user account. Don't forget to set a password with ‘passwd’.
|
||||
users.users.nixos = {
|
||||
isNormalUser = true;
|
||||
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
|
||||
packages = with pkgs; [
|
||||
tree
|
||||
];
|
||||
hashedPasswordFile = config.sops.secrets."nixos-hashedPassword".path;
|
||||
openssh.authorizedKeys.keys = [
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCq/Q5LvIXlZwO2kdeAN5nLGZ59nZB7JHYMEszHxmNtGMzv1lM31jiPNsr0z2EKVZhE7OOfa2IF9rhWYD7JUA9G0yzdZ4WTXFNGVVOJoOVH6vAF3XCxoVilOEwTc7h2Wiy+rzd0B28/3spffzQQWJhY6GRQVa8j+6xAGF60Fcvl1vLosYT9Bn2ZbK4TCWOwAn2jqXIieGpZdn/UNZbGOeKRiCvhktDfMAzuQzN/9jMu/oF4pkPn2X1UrsQdNlvp0Ci8md612MozIpncQJyAF1ADhunr3sMx0isUXiqD29R5DS4TftpekqLNLak+zcxFa8N7DcRNp3DcKfJvyTkwQrR4r+b7lFLYOLHLagSso9CzeW/paAS2q9I5SBm/2DtE1diLLg2jZikYcstsu/G5RgvbzbKqjiaMwTdXC3AMvDxQrs7U5pDRZFzoofG3cpODbTm+uy3m0kP70z0M1K45UbDG0p+itnTu9x40JbQEgefbx38AItNvAIx1A8HO4I1VX28= wayne@stream"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICMJhrfFayLBG+gWtO6oAvgambw5nWWgztiTFEaaaVRH debian@surface"
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
# Enable the OpenSSH daemon.
|
||||
services.openssh.enable = true;
|
||||
|
||||
#Enable flakes
|
||||
|
||||
nix.settings = {
|
||||
experimental-features = [ "nix-command" "flakes" ];
|
||||
auto-optimise-store = true;
|
||||
};
|
||||
|
||||
|
||||
programs.git = {
|
||||
enable = true;
|
||||
package = pkgs.git;
|
||||
config = {
|
||||
credential.helper = "store";
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
{ config, pkgs, lib, ... }:
|
||||
|
||||
let
|
||||
remote = "root@proxmox-ip:/var/lib/vz/template/iso";
|
||||
localMount = "${config.home.homeDirectory}/proxmox-iso";
|
||||
in {
|
||||
|
||||
imports = [
|
||||
./aliases.nix
|
||||
];
|
||||
|
||||
home.username = "nixos"; # your actual username
|
||||
home.homeDirectory = "/home/nixos";
|
||||
home.stateVersion = "25.11"; # match your NixOS stateVersion
|
||||
|
||||
programs.home-manager.enable = true; # mandatory to activate HM
|
||||
|
||||
programs.bash.enable = true;
|
||||
|
||||
# GitHub access-tokens setting used to live here in plaintext; it's now
|
||||
# rendered system-wide from a sops-nix secret via nix.extraOptions in
|
||||
# modules/common/configuration.nix instead (covers the daemon for every
|
||||
# user, not just this one).
|
||||
|
||||
# Optional: packages
|
||||
home.packages = with pkgs; [
|
||||
git
|
||||
vim
|
||||
tmux
|
||||
nano
|
||||
sshfs
|
||||
];
|
||||
|
||||
# Optional: set environment vars
|
||||
home.sessionVariables = {
|
||||
EDITOR = "nano";
|
||||
};
|
||||
# systemd.user.services.mount-proxmox-iso = {
|
||||
# Unit = {
|
||||
# Description = "Mount Proxmox ISO dir via SSHFS";
|
||||
# After = [ "network-online.target" ];
|
||||
# Wants = [ "network-online.target" ];
|
||||
# };
|
||||
|
||||
# Service = {
|
||||
# Type = "simple";
|
||||
# ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p ${localMount}";
|
||||
# ExecStart = "${pkgs.sshfs}/bin/sshfs -o IdentityFile=${config.home.homeDirectory}/.ssh/id_ed25519,allow_other,reconnect,ServerAliveInterval=15,ServerAliveCountMax=3 root@proxmox-ip:/var/lib/vz/template/iso ${localMount}";
|
||||
# ExecStop = "${pkgs.fuse3}/bin/fusermount3 -u ${localMount}";
|
||||
# Restart = "on-failure";
|
||||
# };
|
||||
|
||||
# Install = {
|
||||
# WantedBy = [ "default.target" ];
|
||||
# };
|
||||
# };
|
||||
# Optional: enable bash (or zsh, fish...)
|
||||
# programs.bash.enable = true;
|
||||
|
||||
# Optional: manage dotfiles via symlinks
|
||||
# home.file = {
|
||||
# ".tmux.conf".source = ./dotfiles/tmux.conf;
|
||||
# ".config/nvim/init.vim".source = ./dotfiles/init.vim;
|
||||
# };
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
disko.devices = {
|
||||
disk.main = {
|
||||
type = "disk";
|
||||
device = "/dev/sda";
|
||||
|
||||
content = {
|
||||
type = "gpt";
|
||||
|
||||
partitions = {
|
||||
esp = {
|
||||
priority = 1;
|
||||
name = "ESP";
|
||||
size = "512M";
|
||||
type = "EF00";
|
||||
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
mountOptions = [ "umask=0077" ];
|
||||
extraArgs = [
|
||||
"-F"
|
||||
"32"
|
||||
"-n"
|
||||
"boot"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
swap = {
|
||||
size = "8G";
|
||||
|
||||
content = {
|
||||
type = "swap";
|
||||
randomEncryption = false;
|
||||
# label = "swap";
|
||||
};
|
||||
};
|
||||
|
||||
root = {
|
||||
size = "100%";
|
||||
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "ext4";
|
||||
mountpoint = "/";
|
||||
extraArgs = [
|
||||
"-L"
|
||||
"nixos"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
# virtualisation.docker.enable = true;
|
||||
virtualisation.docker = {
|
||||
enable = true;
|
||||
package = pkgs.docker;
|
||||
# listenOptions = [
|
||||
# "unix:///var/run/docker.sock"
|
||||
# "tcp://0.0.0.0:2375"
|
||||
#];
|
||||
|
||||
# daemon.settings = {
|
||||
# metrics-addr = "0.0.0.0:9323";
|
||||
# experimental = true;
|
||||
# };
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
docker-compose
|
||||
docker-buildx
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
fileSystems."/mnt/docker/config" = {
|
||||
device = "server:/tank/docker/config";
|
||||
fsType = "nfs";
|
||||
|
||||
options = [
|
||||
"nfsvers=4.2"
|
||||
"_netdev"
|
||||
"x-systemd.automount"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
|
||||
fileSystems."/mnt/docker/databases" = {
|
||||
device = "server:/tank/docker/databases";
|
||||
fsType = "nfs";
|
||||
|
||||
options = [
|
||||
"nfsvers=4.2"
|
||||
"_netdev"
|
||||
"x-systemd.automount"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
|
||||
fileSystems."/mnt/docker/volumes" = {
|
||||
device = "server:/tank/docker/volumes";
|
||||
fsType = "nfs";
|
||||
|
||||
options = [
|
||||
"nfsvers=4.2"
|
||||
"_netdev"
|
||||
"x-systemd.automount"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
|
||||
fileSystems."/mnt/nextcloud-data" = {
|
||||
device = "server:/tank/docker/nextcloud-data";
|
||||
fsType = "nfs";
|
||||
|
||||
options = [
|
||||
"nfsvers=4.2"
|
||||
"_netdev"
|
||||
"x-systemd.automount"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
|
||||
fileSystems."/mnt/raspi-backup" = {
|
||||
device = "server:/tank/raspi/volumes";
|
||||
fsType = "nfs";
|
||||
|
||||
options = [
|
||||
"nfsvers=4.2"
|
||||
"_netdev"
|
||||
"x-systemd.automount"
|
||||
"noatime"
|
||||
];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{ config, lib, ... }:
|
||||
|
||||
{
|
||||
options.myNetworking.ipForwarding.enable = lib.mkEnableOption "Enable IPv4 and IPv6 forwarding";
|
||||
|
||||
config = lib.mkIf config.myNetworking.ipForwarding.enable {
|
||||
boot.kernel.sysctl = {
|
||||
"net.ipv4.ip_forward" = 1;
|
||||
"net.ipv6.conf.all.forwarding" = 1;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[ (modulesPath + "/profiles/qemu-guest.nix")
|
||||
];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "virtio_pci" "virtio_scsi" "ahci" "sd_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ ];
|
||||
boot.extraModulePackages = [ ];
|
||||
boot.loader.grub.device = "/dev/sda";
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/sda";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
swapDevices =
|
||||
[ { device = "/dev/sdb"; }
|
||||
];
|
||||
|
||||
# Enable LISH
|
||||
boot.kernelParams = [ "console=ttyS0,19200n8" ];
|
||||
boot.loader.grub.extraConfig = ''
|
||||
serial --speed=19200 --unit=0 --word=8 --parity=no --stop=1;
|
||||
terminal_input serial;
|
||||
terminal_output serial;
|
||||
'';
|
||||
|
||||
boot.loader.grub.forceInstall = true;
|
||||
# boot.loader.grub.device = "nodev";
|
||||
boot.loader.timeout = 10;
|
||||
|
||||
|
||||
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
|
||||
}
|
||||
@@ -10,17 +10,18 @@
|
||||
|
||||
boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ];
|
||||
boot.initrd.kernelModules = [ ];
|
||||
boot.kernelModules = [ ];
|
||||
boot.kernelModules = [ "kvm-amd" ];
|
||||
boot.extraModulePackages = [ ];
|
||||
# boot.loader.grub.device = "/dev/sda2"; # or "nodev" for efi only
|
||||
|
||||
fileSystems."/" =
|
||||
{ device = "/dev/disk/by-label/nixos";
|
||||
fsType = "ext4";
|
||||
};
|
||||
# fileSystems."/" =
|
||||
# { device = "/dev/disk/by-label/nixos";
|
||||
# fsType = "ext4";
|
||||
# };
|
||||
|
||||
swapDevices =
|
||||
[ { device = "/dev/disk/by-label/swap"; }
|
||||
];
|
||||
# swapDevices =
|
||||
# [ { device = "/dev/disk/by-label/swap"; }
|
||||
# ];
|
||||
|
||||
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
||||
# (the default) this is the recommended approach. When using systemd-networkd it's
|
||||
@@ -0,0 +1,15 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
nix.settings = {
|
||||
substituters = [
|
||||
"http://nix-cache"
|
||||
"https://cache.nixos.org/"
|
||||
];
|
||||
trusted-public-keys = [
|
||||
"cache.local-1:usoWYanY3Kpq2+kDIS2nhWoLZiRxanmdysdzqCFBHW4="
|
||||
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||
];
|
||||
auto-optimise-store = true;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
{ config, pkgs, ... }:
|
||||
|
||||
{
|
||||
# Generate the binary cache key pair on the nix-cache host:
|
||||
# sudo install -d -m 0700 /etc/nix
|
||||
# sudo nix-store --generate-binary-cache-key nix-cache-1 \
|
||||
# /etc/nix/cache-priv.pem \
|
||||
# /etc/nix/cache-pub.pem
|
||||
# sudo chmod 0600 /etc/nix/cache-priv.pem
|
||||
# sudo chmod 0644 /etc/nix/cache-pub.pem
|
||||
# cat /etc/nix/cache-pub.pem
|
||||
services.nix-serve = {
|
||||
enable = true;
|
||||
secretKeyFile = "/etc/nix/cache-priv.pem";
|
||||
};
|
||||
|
||||
services.nginx = {
|
||||
enable = true;
|
||||
recommendedProxySettings = true;
|
||||
virtualHosts."nix-cache" = {
|
||||
locations."/" = {
|
||||
proxyPass = "http://${config.services.nix-serve.bindAddress}:${toString config.services.nix-serve.port}";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.allowedTCPPorts = [ 80 ];
|
||||
|
||||
users.groups.nixremote = {};
|
||||
|
||||
users.users.nixremote = {
|
||||
isSystemUser = true;
|
||||
group = "nixremote";
|
||||
createHome = true;
|
||||
home = "/var/lib/nixremote";
|
||||
shell = pkgs.bashInteractive;
|
||||
# Provide remote builder public keys here (safe to commit public keys only):
|
||||
# openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAA... client@host" ];
|
||||
#
|
||||
# Avoid absolute keyFiles paths here because they break pure flake evaluation.
|
||||
openssh.authorizedKeys.keys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFDEA1S2ikpObREgbP5uVBWMxIOGbY8B+Wx7VTZK1m6t root@server"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPAYIT9ormlmxZ0SziyDQaUntnKI8HK9/s3Qac1ZKjP2 root@docker"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKKKzoEPl/ZW9KBRHBcp6/ThOngGpwMv5EhkTlgC4aDf root@nixos"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIGtOWOCS+ImHc7NehguoyD7PbonGosKMZqc9+QR3v/h root@nixos"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHxXTQxFnArK5HXG7czeoybZebCGfxpUdusJkPn+BCSp root@server"];
|
||||
};
|
||||
|
||||
services.openssh.enable = true;
|
||||
|
||||
nix.settings = {
|
||||
trusted-users = [ "root" "nixremote" ];
|
||||
experimental-features = [ "nix-command" "flakes" ];
|
||||
auto-optimise-store = true;
|
||||
builders-use-substitutes = true;
|
||||
};
|
||||
|
||||
nix.gc = {
|
||||
automatic = true;
|
||||
dates = "weekly";
|
||||
options = "--delete-older-than 30d";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
../hardware-configuration/vm/linode.nix
|
||||
];
|
||||
|
||||
networking = {
|
||||
usePredictableInterfaceNames = false;
|
||||
useDHCP = false;
|
||||
interfaces.eth0.useDHCP = true;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
boot.isContainer = true;
|
||||
|
||||
boot.loader.grub.enable = false;
|
||||
boot.loader.systemd-boot.enable = false;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
imports = [
|
||||
../hardware-configuration/vm/proxmox.nix
|
||||
../boot/efi.nix
|
||||
../disko/proxmox.nix
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
fileSystems."/mnt/raspi" = {
|
||||
device = "raspberrypi.tail13f623.ts.net:/home/raspi/raspi";
|
||||
fsType = "nfs4";
|
||||
options = [
|
||||
"nofail"
|
||||
"_netdev"
|
||||
"noatime"
|
||||
|
||||
# Don't mount until first access
|
||||
"x-systemd.automount"
|
||||
|
||||
# Unmount after 10 min idle
|
||||
"x-systemd.idle-timeout=600"
|
||||
|
||||
# Give the Pi/Tailscale a little time to appear
|
||||
"x-systemd.device-timeout=10s"
|
||||
|
||||
# Explicitly use NFSv4.2 if supported
|
||||
"nfsvers=4.2"
|
||||
];
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
# Install the remote builder key on each client host (do not commit private keys):
|
||||
# sudo install -d -m 0700 /root/.ssh
|
||||
# sudo install -m 0600 ./nixremote /root/.ssh/nixremote
|
||||
# sudo ssh -i /root/.ssh/nixremote nixremote@nix-cache nix-store --version
|
||||
nix.distributedBuilds = true;
|
||||
|
||||
nix.buildMachines = [
|
||||
{
|
||||
hostName = "nix-cache";
|
||||
sshUser = "nixremote";
|
||||
sshKey = "/root/.ssh/nixremote";
|
||||
system = pkgs.stdenv.hostPlatform.system;
|
||||
maxJobs = 4;
|
||||
speedFactor = 2;
|
||||
supportedFeatures = [ "nixos-test" "benchmark" "big-parallel" "kvm" ];
|
||||
}
|
||||
];
|
||||
|
||||
nix.settings = {
|
||||
builders-use-substitutes = true;
|
||||
max-jobs = "auto";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
services.logrotate = {
|
||||
enable = true;
|
||||
|
||||
settings = {
|
||||
"/mnt/docker/volumes/traefik-data/logs/*.log" = {
|
||||
daily = true;
|
||||
size = "100M";
|
||||
rotate = 20;
|
||||
compress = true;
|
||||
missingok = true;
|
||||
notifempty = true;
|
||||
copytruncate = true;
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
systemd.services.docker-health-to-gotify = {
|
||||
description = "Alert Gotify when Docker containers become unhealthy";
|
||||
after = [ "docker.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
# Run as root so it can read /etc/secrets and access docker socket
|
||||
# User = "root";
|
||||
#EnvironmentFile = "-/etc/secrets/docker-health-alert.env";
|
||||
ExecStart = "${pkgs.bash}/bin/bash /home/nixos/docker/monitoring/gotify/docker-health-to-gotify.sh";
|
||||
StandardOutput = "journal";
|
||||
StandardError = "journal";
|
||||
};
|
||||
path = with pkgs; [ docker curl coreutils gnused ];
|
||||
};
|
||||
|
||||
systemd.timers.docker-health-to-gotify = {
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnBootSec = "2min";
|
||||
OnUnitActiveSec = "1min";
|
||||
AccuracySec = "15s";
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
services.rpcbind.enable = true;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
# Create nextcloud cron scheduled task
|
||||
systemd.services.nextcloud = {
|
||||
description = "Nextcloud scheduled task";
|
||||
script = ''${pkgs.bash}/bin/bash ~/docker/services-up.sh --profile nextcloud exec -u 33 nextcloud-webapp php ./cron.php'';
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "nixos";
|
||||
};
|
||||
path = with pkgs; [ docker docker-compose ];
|
||||
};
|
||||
|
||||
systemd.timers.nextcloud = {
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = "*:0/5";
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{ pkgs, boot, ... }:
|
||||
|
||||
{
|
||||
boot.postBootCommands = ''
|
||||
echo "=== STARTING ZPOOL IMPORT ==="
|
||||
${pkgs.zfs_unstable}/bin/zpool import -a -N -d /dev/disk/by-path
|
||||
${pkgs.zfs_unstable}/bin/zpool status
|
||||
${pkgs.zfs_unstable}/bin/zfs mount -a
|
||||
${pkgs.zfs_unstable}/bin/zfs list
|
||||
echo "=== ZPOOL IMPORT COMPLETE ==="
|
||||
'';
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
boot.supportedFilesystems = [ "zfs" ];
|
||||
boot.zfs.forceImportRoot = false;
|
||||
boot.zfs.package = pkgs.zfs_unstable;
|
||||
services.zfs = {
|
||||
autoScrub.enable = true;
|
||||
autoSnapshot.enable = true;
|
||||
trim.enable = true;
|
||||
};
|
||||
|
||||
#systemd.services.zfs-import-cache.enable = true;
|
||||
systemd.services.zfs-mount.enable = true;
|
||||
boot.zfs.devNodes = "/dev/disk/by-id";
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
i18n.defaultLocale = "en_AU.UTF-8";
|
||||
|
||||
i18n.extraLocaleSettings = {
|
||||
LC_ADDRESS = "en_AU.UTF-8";
|
||||
LC_IDENTIFICATION = "en_AU.UTF-8";
|
||||
LC_MEASUREMENT = "en_AU.UTF-8";
|
||||
LC_MONETARY = "en_AU.UTF-8";
|
||||
LC_NAME = "en_AU.UTF-8";
|
||||
LC_NUMERIC = "en_AU.UTF-8";
|
||||
LC_PAPER = "en_AU.UTF-8";
|
||||
LC_TELEPHONE = "en_AU.UTF-8";
|
||||
LC_TIME = "en_AU.UTF-8";
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
services.tailscale.enable = true;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{ ... }:
|
||||
|
||||
{
|
||||
services.tailscale = {
|
||||
enable = true;
|
||||
|
||||
extraUpFlags = [
|
||||
"--advertise-exit-node"
|
||||
"--advertise-routes=192.168.2.0/24"
|
||||
];
|
||||
};
|
||||
}
|
||||
+6
-5
@@ -17,13 +17,14 @@ swapon /dev/sda2
|
||||
|
||||
#mount nixos partition
|
||||
mount /dev/disk/by-label/nixos /mnt
|
||||
|
||||
export TMPDIR=/mnt/install-tmp
|
||||
mkdir -p /mnt/install-tmp
|
||||
#Generate config
|
||||
nixos-generate-config --root /mnt/
|
||||
#nixos-generate-config --root /mnt/
|
||||
|
||||
#copy customised configuration over
|
||||
cp configuration.nix /mnt/etc/nixos/configuration.nix
|
||||
#cp configuration.nix /mnt/etc/nixos/configuration.nix
|
||||
|
||||
nixos-install --no-root-passwd
|
||||
#nixos-install --no-root-passwd
|
||||
|
||||
reboot
|
||||
#reboot
|
||||
@@ -0,0 +1,134 @@
|
||||
# Spec: Remove Sensitive Information from NixOS Flake
|
||||
|
||||
## Goal
|
||||
|
||||
Every secret currently readable in plaintext anywhere in this repo (working tree *and* git history) gets removed, replaced with `sops-nix`-managed encrypted references, and rotated. When this is done, the repo should be safe to make public without exposing anything about the systems it configures.
|
||||
|
||||
Treat this as three sequential milestones. Do not start git history rewriting (Milestone 3) until Milestones 1 and 2 are fully verified and the flake still builds. This should be its own branch (`refactor/secrets`) until fully verified, then merged.
|
||||
|
||||
---
|
||||
|
||||
## Milestone 1 — Audit
|
||||
|
||||
Before touching anything, produce a complete inventory. Do not guess at scope — grep the whole tree and the whole history.
|
||||
|
||||
1. Run a secret scanner across the working tree and full history. Use both, since they catch different things:
|
||||
- `gitleaks detect --source . -v --log-opts="--all"` (scans history too)
|
||||
- `trufflehog git file://. --since-commit=$(git rev-list --max-parents=0 HEAD) --only-verified=false`
|
||||
If neither is installed, add them via a temporary `nix-shell -p gitleaks trufflehog` — don't install anything globally on the host.
|
||||
|
||||
2. Manually grep for the categories below, since scanners miss config-specific patterns:
|
||||
- `hashedPassword`, `password`, `initialPassword`, `initialHashedPassword` in any `users.users.*` block
|
||||
- `age.secrets`, `sops.secrets` (if any partial secrets work already exists — check for it)
|
||||
- PSK / `preSharedKey`, `privateKeyFile` inline values (vs. file references) for WireGuard
|
||||
- `authKey`, `apiToken`, `api_key`, `token =`, `secret =` in service modules (Tailscale, Cloudflare, backup tools, etc.)
|
||||
- SSH private key material: search for `BEGIN OPENSSH PRIVATE KEY` / `BEGIN RSA PRIVATE KEY` literals
|
||||
- TLS cert/key pairs committed under e.g. `secrets/`, `certs/`, `pki/`
|
||||
- Real name, personal email, home address, or anything in comments/hostnames that maps a machine to your physical identity or network layout (e.g. hostnames like `wayne-desktop`, static LAN IPs, ISP-identifying info)
|
||||
- `.env` files, `secrets.nix`, `secrets.yaml`, or any file that looks like it was meant to be gitignored but wasn't
|
||||
|
||||
3. Produce `secrets-inventory.md` (temporary, delete before finishing) listing: file path, line, secret type, and which host/service it belongs to. This becomes the checklist for Milestone 2 — every row must be either migrated to sops or deleted, with nothing left unaccounted for.
|
||||
|
||||
---
|
||||
|
||||
## Milestone 2 — Migrate to sops-nix
|
||||
|
||||
### 2.1 Set up sops-nix
|
||||
|
||||
1. Add the flake input:
|
||||
```nix
|
||||
sops-nix.url = "github:Mic92/sops-nix";
|
||||
sops-nix.inputs.nixpkgs.follows = "nixpkgs";
|
||||
```
|
||||
2. Import `sops-nix.nixosModules.sops` into each host's module list (or into a shared `common.nix` if all hosts use it).
|
||||
3. Generate an age keypair **per host** (not one shared key for everything — a compromised host shouldn't decrypt every other host's secrets):
|
||||
```
|
||||
nix-shell -p age --run "age-keygen -o /var/lib/sops-nix/key.txt"
|
||||
```
|
||||
Print the public key (`age-keygen -y`) for each host — you'll need it for `.sops.yaml`.
|
||||
4. Also generate one age key for yourself (your admin workstation) so you can edit secrets without needing to SSH into a host: store it at `~/.config/sops/age/keys.txt`, back it up somewhere outside this repo (password manager, offline). **If this key is lost, every secret encrypted with it is unrecoverable — losing the age key is equivalent to losing the secrets.**
|
||||
5. Create `.sops.yaml` at the repo root defining creation rules: which age public keys can decrypt which secrets files, keyed by path regex, so e.g. `secrets/hostA.yaml` is decryptable by your admin key + hostA's key, `secrets/hostB.yaml` by your admin key + hostB's key.
|
||||
|
||||
### 2.2 Migrate each secret category from the inventory
|
||||
|
||||
For each row in `secrets-inventory.md`:
|
||||
|
||||
- **Password hashes**: generate hash with `mkpasswd -m sha-512` (or `bcrypt` if your setup wants that), store under `sops.secrets."<name>/hashedPassword"`, reference via `users.users.<name>.hashedPasswordFile = config.sops.secrets."<name>/hashedPassword".path;`. Do not put the *plaintext* password anywhere, only the hash, and only the hash goes into the encrypted sops file.
|
||||
- **API tokens / auth keys**: move the raw value into the per-host sops YAML, reference in the module via `config.sops.secrets."<service>/token".path` — most NixOS service modules that take a token also accept a `*File` variant (e.g. `environmentFile`, `tokenFile`); use that instead of passing the value directly.
|
||||
- **Private keys / certs**: move the PEM/key content wholesale into a sops secret, output as a file with appropriate `sops.secrets.<name>.path`, `owner`, `mode`, `restartUnits` so the depending service (sshd, wireguard, nginx) reloads when the secret changes.
|
||||
- **Personal/identifying info**: this doesn't belong in sops (it's not "secret," it's just information you don't want public). Replace real names/emails with placeholders or move to a small untracked `local.nix` that's `.gitignore`'d and imported conditionally, with a documented template (`local.nix.example`) committed instead.
|
||||
|
||||
### 2.3 Verify before moving on
|
||||
|
||||
- `nixos-rebuild dry-build --flake .#<host>` succeeds for every host.
|
||||
- `sudo nixos-rebuild switch --flake .#<host>` on at least one real machine (or a VM) confirms secrets decrypt and services start.
|
||||
- Confirm decrypted secrets land under `/run/secrets/` (not the Nix store — anything placed in `/nix/store` is world-readable by design, so sops-nix's runtime-only placement is the whole point; double check no module accidentally pulls a secret path into a store-built config file).
|
||||
- Re-run the grep/scanner sweep from Milestone 1 against the *working tree only* (not history yet) — it should now come back clean.
|
||||
|
||||
---
|
||||
|
||||
## Milestone 3 — Scrub git history
|
||||
|
||||
Do this only after Milestone 2 is merged to your main branch and confirmed working, since it rewrites every commit SHA from the point of the earliest offending commit onward.
|
||||
|
||||
**This is destructive and irreversible on your local clone. Back up first:**
|
||||
```
|
||||
cp -r /path/to/nixos-repo /path/to/nixos-repo-backup-$(date +%F)
|
||||
```
|
||||
|
||||
1. Install `git-filter-repo` (not the older `git filter-branch` / BFG — filter-repo is the currently maintained, faster, safer tool):
|
||||
```
|
||||
nix-shell -p git-filter-repo
|
||||
```
|
||||
2. Use the `secrets-inventory.md` list to build a list of literal strings/paths to strip. Two approaches, use both:
|
||||
- Path-based: if whole files were secret (e.g. `secrets.nix`, a `.env`, a private key file), remove them entirely from history:
|
||||
```
|
||||
git filter-repo --path secrets.nix --path .env --invert-paths
|
||||
```
|
||||
- Value-based: for secrets embedded inline in files you're keeping (not deleting the whole file), use `--replace-text` with a file listing each literal secret string to replace with `***REMOVED***`:
|
||||
```
|
||||
git filter-repo --replace-text expressions.txt
|
||||
```
|
||||
3. After filtering, verify: run the Milestone 1 scanners again against full history (`--log-opts="--all"`). They must come back clean.
|
||||
4. Force-push the rewritten history:
|
||||
```
|
||||
git push origin --force --all
|
||||
git push origin --force --tags
|
||||
```
|
||||
5. **Every other clone of this repo (other machines, WSL instances, CI) must be deleted and re-cloned fresh** — a `git pull` against rewritten history will not work cleanly and risks resurrecting the old commits. Don't try to reconcile old clones; throw them away and re-clone.
|
||||
6. If this repo has ever been pushed to a public host (GitHub, etc.) or a fork/mirror exists, treat every secret that was ever in history as **permanently compromised regardless of the rewrite** — caches, forks, and Wayback-style archives can retain old commits indefinitely. History scrubbing prevents *future* exposure via `git clone`; it does not undo past exposure.
|
||||
|
||||
---
|
||||
|
||||
## Milestone 4 — Rotate everything
|
||||
|
||||
Because the secrets were exposed in history (even briefly, even in a private repo), the migration is not complete until every credential in the inventory has been **rotated**, not just re-encrypted. Re-encrypting an already-leaked value protects it going forward but doesn't undo the leak.
|
||||
|
||||
For each row in the original inventory:
|
||||
- Password hashes → change the actual account password, regenerate the hash, update the sops file.
|
||||
- API tokens/auth keys → revoke the old token in the issuing service's dashboard (Cloudflare, Tailscale, backup provider, etc.) and generate a new one.
|
||||
- SSH/WireGuard private keys → generate new keypairs, update the corresponding public key wherever it's trusted (authorized_keys, peer configs, etc.), retire the old ones.
|
||||
- TLS certs → reissue if the private key was exposed.
|
||||
|
||||
Keep `secrets-inventory.md` open during this step and check off each row as rotated. Delete the file only once every row is checked off — it should not be committed.
|
||||
|
||||
---
|
||||
|
||||
## Ongoing prevention
|
||||
|
||||
Add a pre-commit hook (or a `nix flake check` step) running `gitleaks protect --staged` so a secret can't be committed again by accident. Document in the repo README (briefly) that new secrets go through `sops <file>` to edit, never as plaintext in a tracked file.
|
||||
|
||||
---
|
||||
|
||||
## Definition of done
|
||||
|
||||
- [ ] Milestone 1 inventory complete and reviewed
|
||||
- [ ] All hosts have per-host age keys; admin key backed up outside the repo
|
||||
- [ ] Every inventoried secret migrated to sops-nix, referenced via `*File`/`sops.secrets.*.path`, nothing plaintext in the working tree
|
||||
- [ ] `nixos-rebuild dry-build` and at least one real `switch` verified per host
|
||||
- [ ] Working-tree scanner sweep clean
|
||||
- [ ] History rewritten with `git-filter-repo`, force-pushed, full-history scanner sweep clean
|
||||
- [ ] All other clones deleted and re-cloned from the rewritten history
|
||||
- [ ] Every credential in the original inventory rotated (not just re-encrypted)
|
||||
- [ ] Pre-commit secret scanning hook added
|
||||
- [ ] `secrets-inventory.md` deleted from the working directory (never committed)
|
||||
Executable
+70
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
export NIX_CONFIG="${NIX_CONFIG:-}
|
||||
experimental-features = nix-command flakes
|
||||
accept-flake-config = false
|
||||
warn-dirty = false
|
||||
"
|
||||
|
||||
MODE="${1:-validate}"
|
||||
|
||||
ensure_nix_profile() {
|
||||
if [ -f /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh ]; then
|
||||
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
elif [ -f "$HOME/.nix-profile/etc/profile.d/nix.sh" ]; then
|
||||
. "$HOME/.nix-profile/etc/profile.d/nix.sh"
|
||||
fi
|
||||
}
|
||||
|
||||
ensure_nix_profile
|
||||
|
||||
if ! command -v nix >/dev/null 2>&1; then
|
||||
echo "ERROR: nix is not available in PATH. Run bash scripts/codex-setup.sh first." >&2
|
||||
exit 127
|
||||
fi
|
||||
|
||||
hosts_json="$(nix eval --json --no-use-registries --no-accept-flake-config .#nixosConfigurations --apply builtins.attrNames)"
|
||||
hosts="$(echo "$hosts_json" | jq -r '.[]')"
|
||||
|
||||
echo "Hosts:"
|
||||
echo "$hosts"
|
||||
|
||||
echo
|
||||
echo "Checking for obvious committed secrets..."
|
||||
if grep -RInE 'github_pat_|ghp_|access-tokens|hashedPassword[[:space:]]*=' \
|
||||
--exclude-dir=.git \
|
||||
--exclude=flake.lock \
|
||||
.; then
|
||||
echo
|
||||
echo "WARNING: Potential secrets or password hashes found. Review before committing."
|
||||
else
|
||||
echo "No obvious token patterns found."
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Checking Nix formatting with nixpkgs-fmt..."
|
||||
nix run --no-use-registries --no-accept-flake-config github:NixOS/nixpkgs/nixos-25.11#nixpkgs-fmt -- --check .
|
||||
|
||||
echo
|
||||
echo "Running statix lint..."
|
||||
nix run --no-use-registries --no-accept-flake-config github:NixOS/nixpkgs/nixos-25.11#statix -- check .
|
||||
|
||||
echo
|
||||
echo "Evaluating host toplevel derivations..."
|
||||
for host in $hosts; do
|
||||
echo "==> $host"
|
||||
nix eval --raw --no-use-registries --no-accept-flake-config ".#nixosConfigurations.${host}.config.system.build.toplevel.drvPath"
|
||||
done
|
||||
|
||||
if [[ "$MODE" == "dry-run" ]]; then
|
||||
echo
|
||||
echo "Running dry-run builds for all hosts. This will not create result symlinks."
|
||||
for host in $hosts; do
|
||||
echo "==> Dry-run build: $host"
|
||||
nix build --dry-run --no-link --no-use-registries --no-accept-flake-config ".#nixosConfigurations.${host}.config.system.build.toplevel"
|
||||
done
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Maintenance checks complete."
|
||||
Executable
+91
@@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
export NIX_CONFIG="${NIX_CONFIG:-}
|
||||
experimental-features = nix-command flakes
|
||||
accept-flake-config = false
|
||||
warn-dirty = false
|
||||
"
|
||||
|
||||
ensure_nix_profile() {
|
||||
if [ -f /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh ]; then
|
||||
. /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh
|
||||
elif [ -f "$HOME/.nix-profile/etc/profile.d/nix.sh" ]; then
|
||||
. "$HOME/.nix-profile/etc/profile.d/nix.sh"
|
||||
fi
|
||||
}
|
||||
|
||||
install_nix_if_missing() {
|
||||
if command -v nix >/dev/null 2>&1; then
|
||||
return
|
||||
fi
|
||||
|
||||
echo "Nix not found. Installing Nix..."
|
||||
|
||||
if [ "$(id -u)" -eq 0 ]; then
|
||||
echo "Running as root; preparing nixbld users for container/Codex environment..."
|
||||
|
||||
if ! getent group nixbld >/dev/null; then
|
||||
groupadd -r nixbld
|
||||
fi
|
||||
|
||||
for i in $(seq 1 10); do
|
||||
if ! id "nixbld$i" >/dev/null 2>&1; then
|
||||
useradd \
|
||||
-r \
|
||||
-g nixbld \
|
||||
-G nixbld \
|
||||
-d /var/empty \
|
||||
-s /usr/sbin/nologin \
|
||||
"nixbld$i" || true
|
||||
fi
|
||||
done
|
||||
|
||||
mkdir -p /etc/nix
|
||||
cat > /etc/nix/nix.conf <<'EOF'
|
||||
experimental-features = nix-command flakes
|
||||
accept-flake-config = false
|
||||
warn-dirty = false
|
||||
build-users-group = nixbld
|
||||
EOF
|
||||
|
||||
sh <(curl -L https://nixos.org/nix/install) --no-daemon
|
||||
else
|
||||
sh <(curl -L https://nixos.org/nix/install) --no-daemon
|
||||
fi
|
||||
|
||||
ensure_nix_profile
|
||||
}
|
||||
|
||||
install_nix_if_missing
|
||||
ensure_nix_profile
|
||||
|
||||
mkdir -p "$HOME/.config/nix"
|
||||
cat > "$HOME/.config/nix/nix.conf" <<'EOF'
|
||||
experimental-features = nix-command flakes
|
||||
accept-flake-config = false
|
||||
warn-dirty = false
|
||||
EOF
|
||||
|
||||
echo "Nix version:"
|
||||
nix --version
|
||||
|
||||
echo "Enabling tracked git hooks (pre-commit secret scan)..."
|
||||
git config core.hooksPath .githooks
|
||||
|
||||
echo "Installing jq if unavailable..."
|
||||
if ! command -v jq >/dev/null 2>&1; then
|
||||
nix profile install nixpkgs#jq
|
||||
fi
|
||||
|
||||
echo "Available NixOS hosts:"
|
||||
hosts="$(nix eval --json --no-use-registries --no-accept-flake-config .#nixosConfigurations --apply builtins.attrNames | jq -r '.[]')"
|
||||
echo "$hosts"
|
||||
|
||||
echo "Evaluating all host toplevel derivations..."
|
||||
for host in $hosts; do
|
||||
echo "==> Evaluating $host"
|
||||
nix eval --raw --no-use-registries --no-accept-flake-config ".#nixosConfigurations.${host}.config.system.build.toplevel.drvPath"
|
||||
done
|
||||
|
||||
echo "Codex setup complete."
|
||||
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
#boot to rescue mode
|
||||
# set root password
|
||||
scp $RESULT_ISO root@$LINODE_IP:/tmp/nixos-auto.iso
|
||||
|
||||
#in LISH or ssh to rescue mode
|
||||
dd if=/tmp/nixos.iso of=/dev/sda bs=4M status=progress conv=fsync
|
||||
@@ -0,0 +1,45 @@
|
||||
root-hashedPassword: ENC[AES256_GCM,data:Kp0nOZI7vDoLhJHiOJBwJn0rQZ5yhnwapGnAcA+qh8vlDETtFs/iQdetF/2ZxmANf62SviTNd+Ag0q5JIF1996x7onZGXqxgSMCuVzZLBdUlsO5IR0BslWWz47khYGTe4WkUg4NB1itBfQ==,iv:5Sra5vJ79V8hxQT3g9qJ+dOj2W2sumIhqpitqnHjJdk=,tag:3Igu0+8GeUZHqS3fKUVwog==,type:str]
|
||||
nixos-hashedPassword: ENC[AES256_GCM,data:pT7tVRN6X4a+DNUgB7fIUUE3CbnetkjxmoSL1PxSU+ktsFU+fB0mEvJjA1uujsGH5Rcztg7YM815+M0Z67ILmHaXbza5DtFacrqhi4/b277xly0SHRX4yOvBwQh6mJG1jn/0O/wvUUIYdw==,iv:bp2nfhC8nFbk6o5iWDAugvbzu7J/a1xayFnBEtkhNpE=,tag:HqWgkIpSrSM/K9OK2WO+VQ==,type:str]
|
||||
nix-github-token: ENC[AES256_GCM,data:OfNRGJg16Ede6EilWUetCs9za+xk5/Lsa3SpVajsqz8PMdA1xQNeCWdX7ZAMdijHClpBhU6ETFGsXvt41O9aORS951uijeGSW7/NH35/bnPISrKdYeBx/+xEiqwH,iv:QGU3v7xOy89uzRTCb1U9ICyJ8XYIpXrUsDt12aL3g2Y=,tag:Bde2wcWNv8H4WLxSEUAodg==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6NkpZRzJuMFNuV09WamR0
|
||||
SERDN0VSUlNQbkhSem1EeFlxdlhmdUx0S21JCnY1VkRBQTBqcW9JRHpJWEtJSitN
|
||||
dHkyR0I4ckNkWkpGWHAzZGRaZkhJalEKLS0tIHRrU3RhU3UxN3B4NHdLeStuSXQ4
|
||||
anFkRlpMTHowZzJNdnY0MExQcXd4OUEKgbT7uOSFkfEs6t3X6jmGOiC28lDJWF33
|
||||
50f2fZ771ylhHa6WJMetGZ5cwl9r1RCaDiWyJEaqNGe7NqARlhr3EQ==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age10nd382a9klsn2mrs60emdtsxe43pht3a0m9p29phfrhy0wfyt3vsq9r667
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBDamw2ekY0dFZyOGNJelVa
|
||||
ZGlNK2VNOWtWNTRzU3o2aVJvRi9CME5yS1JFCndlamdFMzVRTnoyVE1ZWXZkTjRR
|
||||
eWdSZzZERHE5VElrOGZvcE4vK0g2d0EKLS0tIG15QlVyalZTK2NpVDdWWU4yUU4r
|
||||
SkFncC9rZkNKUS9MSmF6WGQwOENwZTQKs5kLNLdQJoZtcsw3zlUWUUtJs0MJnuvw
|
||||
o5vziOswRnuXENw//xN01nMDC6Ckzvb+q9GFIyxHLE4j3fT5XdZakg==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age19gfn2yedg76dmztm4hncr7vf3r3c9j0qpt4rap7y7gersjk4m3ks2lhd0e
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAyaWpWTGd4TEVoaHg4b3hm
|
||||
S1o3VXdkYkZCS0QxcW5hUWxyVjFneE5aSmp3ClNsdEZoMHpPUzI4K3B0ZnBYMlEw
|
||||
MkJyd2NPcGJDZzgvc1EyWFBhNVlGUVEKLS0tIEptYXI2bnJHZVZGR3hSSm1sMlN5
|
||||
ay8wdUh6TEowL0ZiUWtqbXl3NzhYOVEKW9l4mr+MLhuXA8sgQndaU8NiFeCMcxhG
|
||||
qjKFn+mu2GFbwfZWAy6y/KUd9Ug4H6y3pNHlJMHupTu8v2wZ+3S4EA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age1ll6hj5ggruetgjwjfnplpn5xtq35uhlcdflksx3xmnjm6s3uad9sz70jkf
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxVG13RVVweGpRM04vMWxG
|
||||
V2hMMnp2Qk5Ub1BZQWNKNXVya3J4NGpreDJrCktqajVPRXdEL1BMU1dMbDhmU01L
|
||||
UlQvRVQvcEFUZVZ5Umc3Y0hMUWNLVFEKLS0tIFgzRnF1RHdQdktDVjROSURYYTdx
|
||||
NjAydjVuV1VCOGZoVFdTZmw1YmJ0eEEKN9KRGegafu1sjHlhyn4KCMPPAKxsSZLc
|
||||
QJkei1ZQ0AVgC2QfCVEXonMOrs45nCIplG+uyER9khZyyjKObWk1pA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age120le4a5l8dh3lyfgvmj3d9ksmej6ajs5mer5y7r0vfg3x9fn69dqf8xgzu
|
||||
lastmodified: "2026-07-19T02:30:40Z"
|
||||
mac: ENC[AES256_GCM,data:UiL3VMDF6rq4Nr87KspcDx434q3tfNXeb5pwH2O+4ssNQ6xzcYDdzXBnhAY3zLBsqPMKrvHBd4Ot/gEMcq3FMIVe7Q6p9yWKpep66KZ/yWEhAlwIVhD79Oj8VS+1CHKjf25zpRdhZorp04oeFQQd9VfjJB4EE/Q1aVbwTGlpIic=,iv:i/0conaFgFia+wzNTdUL6tlSTw35HTK3Ap1Sr5RGHf8=,tag:ULbz5FllShA/JjlSRdxA0g==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.13.1
|
||||
@@ -0,0 +1,25 @@
|
||||
beszel-token: ENC[AES256_GCM,data:meuzUP/6wCssJDVTgbC0XwiLZPMGyDl55HEIiON9xOXCD9k6,iv:TDqWcp+8Mxd8wN09r5otQRQXq3XTeQphaTWxvvuLTAs=,tag:cRPZQGlwB/dTguBAheWPQg==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkb29VM3haQ0c0WDY0STVn
|
||||
L1ZyOUROSnR6ZjZZZWc1VGFFNVp6bWxCV3hZCnlGTC9CbEtIM3MvSGJQaStEbzJ0
|
||||
eWVhY2l6UHNDRTYxdEpkd003WXFia2MKLS0tIHcxU3FPYTVuZ0RqZTZTT1RvZnN0
|
||||
OGlQM3B2R0l4MHhWNXBBWmpiOEVxK1EK8kxh3ikKL6Fw2am3r7lPGpB0fCqzEukO
|
||||
NU10Cbf38Bd+fybRbBnvRuu9To1FOf+KU3iKbsuWmZn4KJn4Ajcbhw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age10nd382a9klsn2mrs60emdtsxe43pht3a0m9p29phfrhy0wfyt3vsq9r667
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCNWRhK2QrV1ZibllqY25Y
|
||||
ZVRPLzZ0TE82TWZ4L0w5ZmFPTDBtT0poODBnCkE5TWhJcXJjNkdva1hYZ3loeVdq
|
||||
UlBXWHZpRUpMSGhPU0FIRi9JMEtTdGMKLS0tIE9yUk5Ebjk2MEFtNEkyR3RDcU51
|
||||
ZVMwNnNRMlBMVVFlamU1U3JQSy9UT00KJZdEpRHuj4Dp1dGwP1z4xi9oddQOrQj2
|
||||
qheEN/IlifVdZDpvlLUc8jgLzd/TO5EeEhVqfbdrlua8FHly29oTNw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age120le4a5l8dh3lyfgvmj3d9ksmej6ajs5mer5y7r0vfg3x9fn69dqf8xgzu
|
||||
lastmodified: "2026-07-19T02:30:40Z"
|
||||
mac: ENC[AES256_GCM,data:7+FeT6aeCGn+JFBXbPO0qP4BJ1nHPSennewv1kWkG+hOTIqs1ymuswUK1Hyfi6Z9h2umFX9HvK+o3qtmYvk6k7BUNe6w6QUHTNwm6lmNqrb7sgAE3iFVI2p9m14NGhgoTfnXx1M4JIZ1iuNYhCukpENI4+svIe+r7x5YeE5Evac=,iv:4AKAPI6upyAvHBr8BLWX7R/NupmJdcXdqiN8e0ZQ3ls=,tag:TkpfpCaLhn+Mx5cQZZuMdA==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.13.1
|
||||
@@ -0,0 +1,25 @@
|
||||
beszel-token: ENC[AES256_GCM,data:cbQOXhLzNk4g9d6hvm2DH7Q5ApTPCTzsW2txflDT2dD/UPIE,iv:V19MI1GEo5/0205Hrt7JImfkjduFiZ7f9aIkDVaI8mU=,tag:WCArgdrnIOudVe/Tw+oxRw==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxaFZURjAxMGRJZEJ5MW1x
|
||||
ZjVwWEQrQlkwNmRibVNiL2RpTTFLeUVDQ3hRCkVIamVnZkM1MnlueloxMHVFQnBF
|
||||
RjV2bnUrZUo4WGZJTmR4Y0xITkxRUkUKLS0tIGlJdVQ5MFBubVhxRUVMWW0wSGpP
|
||||
UGdKNUNPYW9nek1UZ0tWbXd3QVNUNDgKIHOiKelITQdH5R4Nc3WF7mzz15D1f9on
|
||||
VaTdr5qkf8LNNvPI0fxsXA9is5cqeg+KbDRHtUumEhNp6Zrf8zWBkw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age10nd382a9klsn2mrs60emdtsxe43pht3a0m9p29phfrhy0wfyt3vsq9r667
|
||||
- enc: |
|
||||
-----BEGIN AGE ENCRYPTED FILE-----
|
||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3N0hvV01naytDSWVwK1B1
|
||||
MXM1ZkdpaVc2Q3FPV2VBcC83WmcvSjdGUGgwClJGSXZ6YW5JeFlValNJbjVhK29u
|
||||
bUFqN2dRQTI4ZkwyeXNWYk5JeWVJRXcKLS0tIDlMMkNBUnNUSTJwVVFmc2dlcEZS
|
||||
VGQ1VHR2dXB0M3RsalppVWxiUUROM0UKZM/4QDTam3LDTzjnDs41Ije50R7Q7GC4
|
||||
IZbUZjs72rBzY8IkJDbN9JidadEc4NAtMOJwXiJbpZGiCBNfc8+SXw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
recipient: age1ll6hj5ggruetgjwjfnplpn5xtq35uhlcdflksx3xmnjm6s3uad9sz70jkf
|
||||
lastmodified: "2026-07-19T02:30:40Z"
|
||||
mac: ENC[AES256_GCM,data:rKHZjU/MH08ASTlu32HZO9uWmsBYuMCEC6M8gwVhzuWvmablnP05tS2z13XfaWaCEUXk6kmGJKuU0zu5+IKVZgamCF6DAMtxQb6bVCaLsoAm/GSqWQ5VI9eHqgnSSdN/o3ul/33Rf8iBQo4aw8FFAmDVuNz8bfAn0QefFTj0ByI=,iv:JD2gtqRinOY77etg6PUmZNovkYl1Q3F6ZvRi4x7RznQ=,tag:/5IMpWKRVt+l1luCTQE0BA==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.13.1
|
||||
Reference in New Issue
Block a user