2 Commits

Author SHA1 Message Date
123f53cf91 Speed up attic
All checks were successful
Check Flake / check-flake (push) Successful in 2m15s
2026-02-20 23:24:11 -08:00
fb17d81d49 Add Attic binary cache and containerize gitea runner
Replace nix-serve-only setup with Attic for managed binary caching with
upstream filtering and GC. Move gitea actions runner from host into an
isolated NixOS container with private networking. nix-serve kept alongside
Attic during migration.
2026-02-20 22:00:49 -08:00
31 changed files with 157 additions and 555 deletions

View File

@@ -1,29 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
# Configure Attic cache
attic login local "$ATTIC_ENDPOINT" "$ATTIC_TOKEN"
attic use local:nixos
# Check flake
nix flake check --all-systems --print-build-logs --log-format raw --show-trace
# Build all systems
nix eval .#nixosConfigurations --apply 'cs: builtins.attrNames cs' --json \
| jq -r '.[]' \
| xargs -I{} nix build ".#nixosConfigurations.{}.config.system.build.toplevel" \
--no-link --print-build-logs --log-format raw
# Push to cache (only locally-built paths >= 0.5MB)
toplevels=$(nix eval .#nixosConfigurations \
--apply 'cs: map (n: "${cs.${n}.config.system.build.toplevel}") (builtins.attrNames cs)' \
--json | jq -r '.[]')
echo "Found $(echo "$toplevels" | wc -l) system toplevels"
paths=$(echo "$toplevels" \
| xargs nix path-info -r --json \
| jq -r '[to_entries[] | select(
(.value.signatures | all(startswith("cache.nixos.org") | not))
and .value.narSize >= 524288
) | .key] | unique[]')
echo "Pushing $(echo "$paths" | wc -l) unique paths to cache"
echo "$paths" | xargs attic push local:nixos

View File

@@ -1,60 +0,0 @@
name: Auto Update Flake
on:
schedule:
- cron: '0 6 * * *'
workflow_dispatch: {}
env:
DEBIAN_FRONTEND: noninteractive
PATH: /run/current-system/sw/bin/
XDG_CONFIG_HOME: ${{ runner.temp }}/.config
ATTIC_ENDPOINT: ${{ vars.ATTIC_ENDPOINT }}
ATTIC_TOKEN: ${{ secrets.ATTIC_TOKEN }}
jobs:
auto-update:
runs-on: nixos
steps:
- name: Checkout the repository
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: master
token: ${{ secrets.PUSH_TOKEN }}
- name: Configure git identity
run: |
git config user.name "gitea-runner"
git config user.email "gitea-runner@neet.dev"
- name: Update flake inputs
id: update
run: |
nix flake update
if git diff --quiet flake.lock; then
echo "No changes to flake.lock, nothing to do"
echo "changed=false" >> "$GITHUB_OUTPUT"
else
git add flake.lock
git commit -m "flake.lock: update inputs"
echo "changed=true" >> "$GITHUB_OUTPUT"
fi
- name: Build and cache
if: steps.update.outputs.changed == 'true'
run: bash .gitea/scripts/build-and-cache.sh
- name: Push updated lockfile
if: steps.update.outputs.changed == 'true'
run: git push
- name: Notify on failure
if: failure() && steps.update.outputs.changed == 'true'
run: |
curl -s \
-H "Authorization: Bearer ${{ secrets.NTFY_TOKEN }}" \
-H "Title: Flake auto-update failed" \
-H "Priority: high" \
-H "Tags: warning" \
-d "Auto-update workflow failed. Check: ${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_number }}" \
https://ntfy.neet.dev/nix-flake-updates

View File

@@ -6,8 +6,6 @@ env:
DEBIAN_FRONTEND: noninteractive
PATH: /run/current-system/sw/bin/
XDG_CONFIG_HOME: ${{ runner.temp }}/.config
ATTIC_ENDPOINT: ${{ vars.ATTIC_ENDPOINT }}
ATTIC_TOKEN: ${{ secrets.ATTIC_TOKEN }}
jobs:
check-flake:
@@ -18,16 +16,34 @@ jobs:
with:
fetch-depth: 0
- name: Build and cache
run: bash .gitea/scripts/build-and-cache.sh
- name: Notify on failure
if: failure()
- name: Configure Attic cache
run: |
curl -s \
-H "Authorization: Bearer ${{ secrets.NTFY_TOKEN }}" \
-H "Title: Flake check failed" \
-H "Priority: high" \
-H "Tags: warning" \
-d "Check failed for ${{ gitea.ref_name }}. Check: ${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_number }}" \
https://ntfy.neet.dev/nix-flake-updates
attic login local "${{ vars.ATTIC_ENDPOINT }}" "${{ secrets.ATTIC_TOKEN }}"
attic use local:nixos
- name: Check Flake
run: nix flake check --all-systems --print-build-logs --log-format raw --show-trace
- name: Build all systems
run: |
nix eval .#nixosConfigurations --apply 'cs: builtins.attrNames cs' --json \
| jq -r '.[]' \
| xargs -I{} nix build ".#nixosConfigurations.{}.config.system.build.toplevel" --no-link --print-build-logs --log-format raw
- name: Push to cache
run: |
set -euo pipefail
# Get all system toplevel store paths
toplevels=$(nix eval .#nixosConfigurations --apply 'cs: map (n: "${cs.${n}.config.system.build.toplevel}") (builtins.attrNames cs)' --json | jq -r '.[]')
echo "Found $(echo "$toplevels" | wc -l) system toplevels"
# Expand to full closures, deduplicate, and filter out paths that are:
# - already signed by cache.nixos.org (available upstream)
# - smaller than 0.5MB (insignificant build artifacts)
paths=$(echo "$toplevels" \
| xargs nix path-info -r --json \
| jq -r '[to_entries[] | select(
(.value.signatures | all(startswith("cache.nixos.org") | not))
and .value.narSize >= 524288
) | .key] | unique[]')
echo "Pushing $(echo "$paths" | wc -l) unique paths to cache"
echo "$paths" | xargs attic push local:nixos

1
.gitignore vendored
View File

@@ -1,2 +1 @@
result
.claude/worktrees

View File

@@ -67,12 +67,6 @@ IP allocation convention: VMs `.10-.49`, containers `.50-.89`, incus `.90-.129`
`flake.nix` applies patches from `/patches/` to nixpkgs before building (workaround for nix#3920).
### Service Dashboard & Monitoring
When adding or removing a web-facing service, update both:
- **Gatus** (`common/server/gatus.nix`) — add/remove the endpoint monitor
- **Dashy** — add/remove the service entry from the dashboard config
### Key Conventions
- Uses `doas` instead of `sudo` everywhere
@@ -85,9 +79,3 @@ When adding or removing a web-facing service, update both:
- Always use `--no-link` when running `nix build`
- Don't use `nix build --dry-run` unless you only need evaluation — it skips the actual build
- Avoid `2>&1` on nix commands — it can cause error output to be missed
## Git Worktree Requirement
When instructed to work in a git worktree (e.g., via `isolation: "worktree"` or told to use a worktree), you **MUST** do so. If you are unable to create or use a git worktree, you **MUST** stop work immediately and report the failure to the user. Do not fall back to working in the main working tree.
When applying work from a git worktree back to the main branch, commit in the worktree first, then use `git cherry-pick` from the main working tree to bring the commit over. Do not use `git checkout` or `git apply` to copy files directly. Do **not** automatically apply worktree work to the main branch — always ask the user for approval first.

View File

@@ -6,11 +6,11 @@
substituters = [
"https://cache.nixos.org/"
"https://nix-community.cachix.org"
"http://s0.neet.dev:28338/nixos"
"http://s0.koi-bebop.ts.net:28338/nixos"
];
trusted-public-keys = [
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
"nixos:e5AMCUWWEX9MESWAAMjBkZdGUpl588NhgsUO3HsdhFw="
"nixos:SnTTQutdOJbAmxo6AQ3cbRt5w9f4byMXQODCieBH3PQ="
];
# Allow substituters to be offline

View File

@@ -6,8 +6,6 @@
./binary-cache.nix
./flakes.nix
./auto-update.nix
./ntfy-alerts.nix
./zfs-alerts.nix
./shell.nix
./network
./boot
@@ -102,5 +100,5 @@
security.acme.defaults.email = "zuckerberg@neet.dev";
# Enable Desktop Environment if this is a PC (machine role is "personal")
de.enable = lib.mkDefault (config.thisMachine.hasRole."personal" && !config.boot.isContainer);
de.enable = lib.mkDefault (config.thisMachine.hasRole."personal");
}

View File

@@ -4,15 +4,15 @@ let
builderUserName = "nix-builder";
builderRole = "nix-builder";
builders = config.machines.withRole.${builderRole} or [];
thisMachineIsABuilder = config.thisMachine.hasRole.${builderRole} or false;
builders = config.machines.withRole.${builderRole};
thisMachineIsABuilder = config.thisMachine.hasRole.${builderRole};
# builders don't include themselves as a remote builder
otherBuilders = lib.filter (hostname: hostname != config.networking.hostName) builders;
in
lib.mkMerge [
# configure builder
(lib.mkIf (thisMachineIsABuilder && !config.boot.isContainer) {
(lib.mkIf thisMachineIsABuilder {
users.users.${builderUserName} = {
description = "Distributed Nix Build User";
group = builderUserName;

View File

@@ -1,57 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ntfy-alerts;
in
{
options.ntfy-alerts = {
serverUrl = lib.mkOption {
type = lib.types.str;
default = "https://ntfy.neet.dev";
description = "Base URL of the ntfy server.";
};
topic = lib.mkOption {
type = lib.types.str;
default = "service-failures";
description = "ntfy topic to publish alerts to.";
};
};
config = lib.mkIf config.thisMachine.hasRole."ntfy" {
age.secrets.ntfy-token.file = ../secrets/ntfy-token.age;
systemd.services."ntfy-failure@" = {
description = "Send ntfy alert for failed unit %i";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
serviceConfig = {
Type = "oneshot";
EnvironmentFile = "/run/agenix/ntfy-token";
ExecStart = "${pkgs.writeShellScript "ntfy-failure-notify" ''
unit="$1"
${lib.getExe pkgs.curl} \
--fail --silent --show-error \
--max-time 30 --retry 3 \
-H "Authorization: Bearer $NTFY_TOKEN" \
-H "Title: Service failure on ${config.networking.hostName}" \
-H "Priority: high" \
-H "Tags: rotating_light" \
-d "Unit $unit failed at $(date +%c)" \
"${cfg.serverUrl}/${cfg.topic}"
''} %i";
};
};
# Apply OnFailure to all services via a systemd drop-in
systemd.packages = [
(pkgs.runCommand "ntfy-on-failure-dropin" { } ''
mkdir -p $out/lib/systemd/system/service.d
cat > $out/lib/systemd/system/service.d/ntfy-on-failure.conf <<'EOF'
[Unit]
OnFailure=ntfy-failure@%p.service
EOF
'')
];
};
}

View File

@@ -27,7 +27,6 @@ in
../shell.nix
hostConfig.inputs.home-manager.nixosModules.home-manager
hostConfig.inputs.nix-index-database.nixosModules.default
hostConfig.inputs.agenix.nixosModules.default
];
nixpkgs.overlays = [
@@ -117,13 +116,6 @@ in
nix.settings.experimental-features = [ "nix-command" "flakes" ];
nix.settings.trusted-users = [ "googlebot" ];
# Binary cache configuration (inherited from host's common/binary-cache.nix)
nix.settings.substituters = hostConfig.nix.settings.substituters;
nix.settings.trusted-public-keys = hostConfig.nix.settings.trusted-public-keys;
nix.settings.fallback = true;
nix.settings.netrc-file = config.age.secrets.attic-netrc.path;
age.secrets.attic-netrc.file = ../../secrets/attic-netrc.age;
# Make nixpkgs available in NIX_PATH and registry (like the NixOS ISO)
# This allows `nix-shell -p`, `nix repl '<nixpkgs>'`, etc. to work
nix.nixPath = [ "nixpkgs=${hostConfig.inputs.nixpkgs}" ];

View File

@@ -1,7 +1,7 @@
{ config, lib, ... }:
{
config = lib.mkIf (config.thisMachine.hasRole."binary-cache" && !config.boot.isContainer) {
config = lib.mkIf (config.thisMachine.hasRole."binary-cache") {
services.atticd = {
enable = true;
environmentFile = config.age.secrets.atticd-credentials.path;
@@ -49,7 +49,6 @@
systemd.services.atticd = {
after = [ "postgresql.service" ];
requires = [ "postgresql.service" ];
partOf = [ "postgresql.service" ];
serviceConfig = {
DynamicUser = lib.mkForce false;
User = "atticd";

View File

@@ -16,7 +16,5 @@
./librechat.nix
./actualbudget.nix
./unifi.nix
./ntfy.nix
./gatus.nix
];
}

View File

@@ -1,146 +0,0 @@
{ lib, config, ... }:
let
cfg = config.services.gatus;
port = 31103;
in
{
options.services.gatus = {
hostname = lib.mkOption {
type = lib.types.str;
example = "status.example.com";
};
};
config = lib.mkIf cfg.enable {
services.gatus = {
environmentFile = "/run/agenix/ntfy-token";
settings = {
storage = {
type = "sqlite";
path = "/var/lib/gatus/data.db";
};
web = {
address = "127.0.0.1";
port = port;
};
alerting.ntfy = {
url = "https://ntfy.neet.dev";
topic = "service-failures";
priority = 4;
default-alert = {
enabled = true;
failure-threshold = 3;
success-threshold = 2;
send-on-resolved = true;
};
token = "$NTFY_TOKEN";
};
endpoints = [
{
name = "Gitea";
group = "services";
url = "https://git.neet.dev";
interval = "5m";
conditions = [
"[STATUS] == 200"
];
alerts = [{ type = "ntfy"; }];
}
{
name = "The Lounge";
group = "services";
url = "https://irc.neet.dev";
interval = "5m";
conditions = [
"[STATUS] == 200"
];
alerts = [{ type = "ntfy"; }];
}
{
name = "ntfy";
group = "services";
url = "https://ntfy.neet.dev/v1/health";
interval = "5m";
conditions = [
"[STATUS] == 200"
];
alerts = [{ type = "ntfy"; }];
}
{
name = "Librechat";
group = "services";
url = "https://chat.neet.dev";
interval = "5m";
conditions = [
"[STATUS] == 200"
];
alerts = [{ type = "ntfy"; }];
}
{
name = "Owncast";
group = "services";
url = "https://live.neet.dev";
interval = "5m";
conditions = [
"[STATUS] == 200"
];
alerts = [{ type = "ntfy"; }];
}
{
name = "Nextcloud";
group = "services";
url = "https://neet.cloud";
interval = "5m";
conditions = [
"[STATUS] == any(200, 302)"
];
alerts = [{ type = "ntfy"; }];
}
{
name = "Element Web";
group = "services";
url = "https://chat.neet.space";
interval = "5m";
conditions = [
"[STATUS] == 200"
];
alerts = [{ type = "ntfy"; }];
}
{
name = "Mumble";
group = "services";
url = "tcp://voice.neet.space:23563";
interval = "5m";
conditions = [
"[CONNECTED] == true"
];
alerts = [{ type = "ntfy"; }];
}
{
name = "Navidrome";
group = "services";
url = "https://navidrome.neet.cloud";
interval = "5m";
conditions = [
"[STATUS] == 200"
];
alerts = [{ type = "ntfy"; }];
}
];
};
};
services.nginx.enable = true;
services.nginx.virtualHosts.${cfg.hostname} = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString port}";
proxyWebsockets = true;
};
};
};
}

View File

@@ -42,10 +42,6 @@ in
};
# Disable dynamic user so runner state persists via bind mount
assertions = [{
assertion = config.systemd.services.gitea-runner-inst.enable;
message = "Expected systemd service 'gitea-runner-inst' is not enabled the gitea-actions-runner module may have changed its naming scheme.";
}];
systemd.services.gitea-runner-inst.serviceConfig.DynamicUser = lib.mkForce false;
users.users.gitea-runner = {
uid = giteaRunnerUid;
@@ -67,9 +63,6 @@ in
};
};
# Needs to be outside of the container because container uses's the host's nix-daemon
nix.settings.trusted-users = [ "gitea-runner" ];
# Matching user on host — the container's gitea-runner UID must be
# recognized by the host's nix-daemon as trusted (shared UID namespace)
users.users.gitea-runner = {

View File

@@ -1,38 +0,0 @@
{ lib, config, ... }:
let
cfg = config.services.ntfy-sh;
in
{
options.services.ntfy-sh = {
hostname = lib.mkOption {
type = lib.types.str;
example = "ntfy.example.com";
};
};
config = lib.mkIf cfg.enable {
services.ntfy-sh.settings = {
base-url = "https://${cfg.hostname}";
listen-http = "127.0.0.1:2586";
auth-default-access = "deny-all";
behind-proxy = true;
enable-login = true;
};
# backups
backup.group."ntfy".paths = [
"/var/lib/ntfy-sh"
];
services.nginx.enable = true;
services.nginx.virtualHosts.${cfg.hostname} = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:2586";
proxyWebsockets = true;
};
};
};
}

View File

@@ -26,16 +26,6 @@
"printcap name" = "cups";
"hide files" = "/.nobackup/.DS_Store/._.DS_Store/";
# Samba 4.22+ enables SMB3 directory leases by default, allowing clients
# to cache directory listings locally. When files are created locally on
# the server (bypassing Samba), these cached listings go stale because
# kernel oplocks — the mechanism that would break leases on local
# changes — is incompatible with smb2 leases. Enabling kernel oplocks
# would fix this but forces Samba to disable smb2 leases, durable
# handles, and level2 oplocks, losing handle caching performance.
# https://wiki.samba.org/index.php/Editing_files_locally_on_server:_interoperability
"smb3 directory leases" = "no";
};
public = {
path = "/data/samba/Public";

View File

@@ -1,87 +0,0 @@
{ config, lib, pkgs, ... }:
let
cfg = config.ntfy-alerts;
hasZfs = config.boot.supportedFilesystems.zfs or false;
hasNtfy = config.thisMachine.hasRole."ntfy";
checkScript = pkgs.writeShellScript "zfs-health-check" ''
PATH="${lib.makeBinPath [ pkgs.zfs pkgs.coreutils pkgs.gawk pkgs.curl ]}"
unhealthy=""
# Check pool health status
while IFS=$'\t' read -r pool state; do
if [ "$state" != "ONLINE" ]; then
unhealthy="$unhealthy"$'\n'"Pool '$pool' is $state"
fi
done < <(zpool list -H -o name,health)
# Check for errors (read, write, checksum) on any vdev
while IFS=$'\t' read -r pool errors; do
if [ "$errors" != "No known data errors" ] && [ -n "$errors" ]; then
unhealthy="$unhealthy"$'\n'"Pool '$pool' has errors: $errors"
fi
done < <(zpool status -x 2>/dev/null | awk '
/pool:/ { pool=$2 }
/errors:/ { sub(/^[[:space:]]*errors: /, ""); print pool "\t" $0 }
')
# Check for any drives with non-zero error counts
drive_errors=$(zpool status 2>/dev/null | awk '
/DEGRADED|FAULTED|OFFLINE|UNAVAIL|REMOVED/ && !/pool:/ && !/state:/ {
print " " $0
}
/[0-9]+[[:space:]]+[0-9]+[[:space:]]+[0-9]+/ {
if ($3 > 0 || $4 > 0 || $5 > 0) {
print " " $1 " (read:" $3 " write:" $4 " cksum:" $5 ")"
}
}
')
if [ -n "$drive_errors" ]; then
unhealthy="$unhealthy"$'\n'"Device errors:"$'\n'"$drive_errors"
fi
if [ -n "$unhealthy" ]; then
message="ZFS health check failed on ${config.networking.hostName}:$unhealthy"
curl \
--fail --silent --show-error \
--max-time 30 --retry 3 \
-H "Authorization: Bearer $NTFY_TOKEN" \
-H "Title: ZFS issue on ${config.networking.hostName}" \
-H "Priority: urgent" \
-H "Tags: warning" \
-d "$message" \
"${cfg.serverUrl}/${cfg.topic}"
echo "$message" >&2
fi
echo "All ZFS pools healthy"
'';
in
{
config = lib.mkIf (hasZfs && hasNtfy) {
systemd.services.zfs-health-check = {
description = "Check ZFS pool health and alert on issues";
wants = [ "network-online.target" ];
after = [ "network-online.target" "zfs.target" ];
serviceConfig = {
Type = "oneshot";
EnvironmentFile = "/run/agenix/ntfy-token";
ExecStart = checkScript;
};
};
systemd.timers.zfs-health-check = {
description = "Periodic ZFS health check";
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
RandomizedDelaySec = "1h";
};
};
};
}

62
flake.lock generated
View File

@@ -14,11 +14,11 @@
]
},
"locked": {
"lastModified": 1770165109,
"narHash": "sha256-9VnK6Oqai65puVJ4WYtCTvlJeXxMzAp/69HhQuTdl/I=",
"lastModified": 1762618334,
"narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=",
"owner": "ryantm",
"repo": "agenix",
"rev": "b027ee29d959fda4b60b57566d64c98a202e0feb",
"rev": "fcdea223397448d35d9b31f798479227e80183f6",
"type": "github"
},
"original": {
@@ -53,11 +53,11 @@
]
},
"locked": {
"lastModified": 1771632347,
"narHash": "sha256-kNm0YX9RUwf7GZaWQu2F71ccm4OUMz0xFkXn6mGPfps=",
"lastModified": 1770491193,
"narHash": "sha256-zdnWeXmPZT8BpBo52s4oansT1Rq0SNzksXKpEcMc5lE=",
"owner": "sadjow",
"repo": "claude-code-nix",
"rev": "ec90f84b2ea21f6d2272e00d1becbc13030d1895",
"rev": "f68a2683e812d1e4f9a022ff3e0206d46347d019",
"type": "github"
},
"original": {
@@ -124,11 +124,11 @@
]
},
"locked": {
"lastModified": 1770019181,
"narHash": "sha256-hwsYgDnby50JNVpTRYlF3UR/Rrpt01OrxVuryF40CFY=",
"lastModified": 1766051518,
"narHash": "sha256-znKOwPXQnt3o7lDb3hdf19oDo0BLP4MfBOYiWkEHoik=",
"owner": "serokell",
"repo": "deploy-rs",
"rev": "77c906c0ba56aabdbc72041bf9111b565cdd6171",
"rev": "d5eff7f948535b9c723d60cd8239f8f11ddc90fa",
"type": "github"
},
"original": {
@@ -186,11 +186,11 @@
]
},
"locked": {
"lastModified": 1769939035,
"narHash": "sha256-Fok2AmefgVA0+eprw2NDwqKkPGEI5wvR+twiZagBvrg=",
"lastModified": 1763988335,
"narHash": "sha256-QlcnByMc8KBjpU37rbq5iP7Cp97HvjRP0ucfdh+M4Qc=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "a8ca480175326551d6c4121498316261cbb5b260",
"rev": "50b9238891e388c9fdc6a5c49e49c42533a1b5ce",
"type": "github"
},
"original": {
@@ -228,11 +228,11 @@
]
},
"locked": {
"lastModified": 1771756436,
"narHash": "sha256-Tl2I0YXdhSTufGqAaD1ySh8x+cvVsEI1mJyJg12lxhI=",
"lastModified": 1768068402,
"narHash": "sha256-bAXnnJZKJiF7Xr6eNW6+PhBf1lg2P1aFUO9+xgWkXfA=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "5bd3589390b431a63072868a90c0f24771ff4cbb",
"rev": "8bc5473b6bc2b6e1529a9c4040411e1199c43b4c",
"type": "github"
},
"original": {
@@ -250,11 +250,11 @@
"spectrum": "spectrum"
},
"locked": {
"lastModified": 1771802632,
"narHash": "sha256-UAH8YfrHRvXAMeFxUzJ4h4B1loz1K1wiNUNI8KiPqOg=",
"lastModified": 1770310890,
"narHash": "sha256-lyWAs4XKg3kLYaf4gm5qc5WJrDkYy3/qeV5G733fJww=",
"owner": "astro",
"repo": "microvm.nix",
"rev": "b67e3d80df3ec35bdfd3a00ad64ee437ef4fcded",
"rev": "68c9f9c6ca91841f04f726a298c385411b7bfcd5",
"type": "github"
},
"original": {
@@ -270,11 +270,11 @@
]
},
"locked": {
"lastModified": 1771734689,
"narHash": "sha256-/phvMgr1yutyAMjKnZlxkVplzxHiz60i4rc+gKzpwhg=",
"lastModified": 1765267181,
"narHash": "sha256-d3NBA9zEtBu2JFMnTBqWj7Tmi7R5OikoU2ycrdhQEws=",
"owner": "Mic92",
"repo": "nix-index-database",
"rev": "8f590b832326ab9699444f3a48240595954a4b10",
"rev": "82befcf7dc77c909b0f2a09f5da910ec95c5b78f",
"type": "github"
},
"original": {
@@ -285,11 +285,11 @@
},
"nixos-hardware": {
"locked": {
"lastModified": 1771423359,
"narHash": "sha256-yRKJ7gpVmXbX2ZcA8nFi6CMPkJXZGjie2unsiMzj3Ig=",
"lastModified": 1767185284,
"narHash": "sha256-ljDBUDpD1Cg5n3mJI81Hz5qeZAwCGxon4kQW3Ho3+6Q=",
"owner": "NixOS",
"repo": "nixos-hardware",
"rev": "740a22363033e9f1bb6270fbfb5a9574067af15b",
"rev": "40b1a28dce561bea34858287fbb23052c3ee63fe",
"type": "github"
},
"original": {
@@ -301,16 +301,16 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1771369470,
"narHash": "sha256-0NBlEBKkN3lufyvFegY4TYv5mCNHbi5OmBDrzihbBMQ=",
"lastModified": 1768250893,
"narHash": "sha256-fWNJYFx0QvnlGlcw54EoOYs/wv2icINHUz0FVdh9RIo=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "0182a361324364ae3f436a63005877674cf45efb",
"rev": "3971af1a8fc3646b1d554cb1269b26c84539c22e",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"ref": "master",
"repo": "nixpkgs",
"type": "github"
}
@@ -344,11 +344,11 @@
]
},
"locked": {
"lastModified": 1770659507,
"narHash": "sha256-RVZno9CypFN3eHxfULKN1K7mb/Cq0HkznnWqnshxpWY=",
"lastModified": 1766321686,
"narHash": "sha256-icOWbnD977HXhveirqA10zoqvErczVs3NKx8Bj+ikHY=",
"owner": "simple-nixos-mailserver",
"repo": "nixos-mailserver",
"rev": "781e833633ebc0873d251772a74e4400a73f5d78",
"rev": "7d433bf89882f61621f95082e90a4ab91eb0bdd3",
"type": "gitlab"
},
"original": {

View File

@@ -1,7 +1,7 @@
{
inputs = {
# nixpkgs
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs.url = "github:NixOS/nixpkgs/master";
# Common Utils Among flake inputs
systems.url = "github:nix-systems/default";
@@ -175,10 +175,10 @@
kexec = (mkEphemeral "x86_64-linux").config.system.build.images.kexec;
iso = (mkEphemeral "x86_64-linux").config.system.build.images.iso;
};
# "aarch64-linux" = {
# kexec = (mkEphemeral "aarch64-linux").config.system.build.images.kexec;
# iso = (mkEphemeral "aarch64-linux").config.system.build.images.iso;
# };
"aarch64-linux" = {
kexec = (mkEphemeral "aarch64-linux").config.system.build.images.kexec;
iso = (mkEphemeral "aarch64-linux").config.system.build.images.iso;
};
};
overlays.default = import ./overlays { inherit inputs; };

View File

@@ -8,7 +8,6 @@
systemRoles = [
"personal"
"dns-challenge"
"ntfy"
];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID/Df5lG07Il7fizEgZR/T9bMlR0joESRJ7cqM9BkOyP";

View File

@@ -7,7 +7,6 @@
systemRoles = [
"personal"
"ntfy"
];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEQi3q8jU6vRruExAL60J7GFO1gS8HsmXVJuKRT4ljrG";

View File

@@ -0,0 +1,9 @@
{ lib, ... }:
{
imports = [
./hardware-configuration.nix
];
networking.hostName = "phil";
}

View File

@@ -0,0 +1,46 @@
# 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.
{ lib, modulesPath, ... }:
{
imports =
[
(modulesPath + "/profiles/qemu-guest.nix")
];
# because grub just doesn't work for some reason
boot.loader.systemd-boot.enable = true;
remoteLuksUnlock.enable = true;
remoteLuksUnlock.enableTorUnlock = false;
boot.initrd.availableKernelModules = [ "xhci_pci" ];
boot.initrd.kernelModules = [ "dm-snapshot" ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
boot.initrd.luks.devices."enc-pv" = {
device = "/dev/disk/by-uuid/d26c1820-4c39-4615-98c2-51442504e194";
allowDiscards = true;
};
fileSystems."/" =
{
device = "/dev/disk/by-uuid/851bfde6-93cd-439e-9380-de28aa87eda9";
fsType = "btrfs";
};
fileSystems."/boot" =
{
device = "/dev/disk/by-uuid/F185-C4E5";
fsType = "vfat";
};
swapDevices =
[{ device = "/dev/disk/by-uuid/d809e3a1-3915-405a-a200-4429c5efdf87"; }];
networking.interfaces.enp0s6.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
}

View File

@@ -0,0 +1,20 @@
{
hostNames = [
"phil"
"phil.neet.dev"
];
arch = "aarch64-linux";
systemRoles = [
"server"
"nix-builder"
];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBlgRPpuUkZqe8/lHugRPm/m2vcN9psYhh5tENHZt9I2";
remoteUnlock = {
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK0RodotOXLMy/w70aa096gaNqPBnfgiXR5ZAH4+wGzd";
clearnetHost = "unlock.phil.neet.dev";
};
}

View File

@@ -108,12 +108,4 @@
# librechat
services.librechat-container.enable = true;
services.librechat-container.host = "chat.neet.dev";
# push notifications
services.ntfy-sh.enable = true;
services.ntfy-sh.hostname = "ntfy.neet.dev";
# uptime monitoring
services.gatus.enable = true;
services.gatus.hostname = "status.neet.dev";
}

View File

@@ -15,7 +15,6 @@
"dailybot"
"gitea"
"librechat"
"ntfy"
];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMBBlTAIp38RhErU1wNNV5MBeb+WGH0mhF/dxh5RsAXN";

View File

@@ -45,6 +45,12 @@
fsType = "zfs";
options = [ "zfsutil" "X-mount.mkdir" ];
};
fileSystems."/var/lib/atticd" =
{
device = "rpool/nixos/var/lib/atticd";
fsType = "zfs";
options = [ "zfsutil" "X-mount.mkdir" ];
};
fileSystems."/var/log" =
{
device = "rpool/nixos/var/log";

View File

@@ -18,7 +18,6 @@
"linkwarden"
"outline"
"dns-challenge"
"ntfy"
];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwiXcUFtAvZCayhu4+AIcF+Ktrdgv9ee/mXSIhJbp4q";

View File

@@ -8,7 +8,6 @@
systemRoles = [
"personal"
"media-center"
"ntfy"
];
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHvdC1EiLqSNVmk5L1p7cWRIrrlelbK+NMj6tEBrwqIq";

View File

@@ -1,19 +0,0 @@
age-encryption.org/v1
-> ssh-ed25519 qEbiMg 5JtpNApPNiFqAB/gQcAsE1gz0Fg/uHW92f6Kx1J2ggQ
RzC1MQxyDYW1IuMo+OtSgcsND4v7XIRn0rCSkKCFA3A
-> ssh-ed25519 N7drjg mn6LWo+2zWEtUavbFQar966+j+g5su+lcBfWYz1aZDQ
EmKpdfkCSQao1+O/HJdOiam7UvBnDYcEEkgH6KrudQI
-> ssh-ed25519 jQaHAA an3Ukqz3BVoz0FEAA6/Lw1XKOkQWHwmTut+XD4E4vS8
9N2ePtXG2FPJSmOwcAO9p92MJKJJpTlEhKSmgMiinB0
-> ssh-ed25519 ZDy34A v98HzmBgwgOpUk2WrRuFsCdNR+nF2veVLzyT2pU2ZXY
o2pO5JbVEeaOFQ3beBvej6qgDdT9mgPCVHxmw2umhA0
-> ssh-ed25519 w3nu8g Uba2LWQueJ50Ds1/RjvkXI+VH7calMiM7dbL02sRJ3U
mFj5skmDXhJV9lK5iwUpebqxqVPAexdUntrbWJEix+Q
-> ssh-ed25519 evqvfg wLEEdTdmDRiFGYDrYFQjvRzc3zmGXgvztIy3UuFXnWg
CtCV/PpaxBmtDV+6InmcbKxNDmbPUTzyCm8tCf1Qw/4
-> ssh-ed25519 6AT2/g NaA1AhOdb+FGOCoWFEX0QN4cXS1CxlpFwpsH1L6vBA0
Z9aMYAofQ4Ath0zsg0YdZG3GTnCN2uQW7EG02bMZRsc
-> ssh-ed25519 hPp1nw +shAZrydcbjXfYxm1UW1YosKg5ZwBBKO6cct4HdotBo
GxnopKlmZQ/I6kMZPNurLgqwwkFHpUradaNYTPnlMFU
--- W6DrhCmU08IEIyPpHDiRV21xVeALNk1bDHrLYc2YcC4
'+Æ©<C386>CËl”i.Z£t;ýL²1Eãk#5ŸŠÑ£38‰?± šFWhö6?±_Ã=Âæ<C382>ãj/æÌRFÆáãåiÿóãÌZ{

View File

@@ -9,7 +9,7 @@ let
nobody = sshKeys.userKeys;
# For secrets that all machines need to know
everyone = lib.unique (roles.personal ++ roles.server);
everyone = roles.personal ++ roles.server;
in
with roles;
@@ -43,11 +43,8 @@ with roles;
"linkwarden-environment.age".publicKeys = linkwarden;
# backups
"backblaze-s3-backups.age".publicKeys = everyone;
"restic-password.age".publicKeys = everyone;
# ntfy alerts
"ntfy-token.age".publicKeys = everyone;
"backblaze-s3-backups.age".publicKeys = personal ++ server;
"restic-password.age".publicKeys = personal ++ server;
# gitea actions runner
"gitea-actions-runner-token.age".publicKeys = gitea-actions-runner;