Compare commits
23 Commits
3d08a3e9bc
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
412dd12b5a | ||
| 684851d641 | |||
| 4cf50b5fb1 | |||
| 288a2841aa | |||
| 0589ca5748 | |||
| a4c5cb589a | |||
| a697ea10ad | |||
| 200d5a5d22 | |||
| 339eac52c6 | |||
| bab4b3ff8e | |||
| 54ab576914 | |||
| c84c0716ce | |||
| a921f40644 | |||
|
|
a6c17164fa | ||
| 9df8390f1f | |||
| 156f0183bd | |||
| 8b92e51ef7 | |||
| 7798872bbf | |||
| cf41285cb8 | |||
| 5a0a525f64 | |||
| 9154595910 | |||
| 1b92363b08 | |||
| 136f024cf0 |
29
.gitea/scripts/build-and-cache.sh
Executable file
29
.gitea/scripts/build-and-cache.sh
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/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
|
||||||
60
.gitea/workflows/auto-update.yaml
Normal file
60
.gitea/workflows/auto-update.yaml
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
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
|
||||||
@@ -5,6 +5,9 @@ on: [push]
|
|||||||
env:
|
env:
|
||||||
DEBIAN_FRONTEND: noninteractive
|
DEBIAN_FRONTEND: noninteractive
|
||||||
PATH: /run/current-system/sw/bin/
|
PATH: /run/current-system/sw/bin/
|
||||||
|
XDG_CONFIG_HOME: ${{ runner.temp }}/.config
|
||||||
|
ATTIC_ENDPOINT: ${{ vars.ATTIC_ENDPOINT }}
|
||||||
|
ATTIC_TOKEN: ${{ secrets.ATTIC_TOKEN }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-flake:
|
check-flake:
|
||||||
@@ -15,5 +18,16 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Check Flake
|
- name: Build and cache
|
||||||
run: nix flake check --all-systems --print-build-logs --log-format raw --show-trace
|
run: bash .gitea/scripts/build-and-cache.sh
|
||||||
|
|
||||||
|
- name: Notify on failure
|
||||||
|
if: failure()
|
||||||
|
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
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
|||||||
result
|
result
|
||||||
|
.claude/worktrees
|
||||||
|
|||||||
12
CLAUDE.md
12
CLAUDE.md
@@ -67,6 +67,12 @@ 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).
|
`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
|
### Key Conventions
|
||||||
|
|
||||||
- Uses `doas` instead of `sudo` everywhere
|
- Uses `doas` instead of `sudo` everywhere
|
||||||
@@ -79,3 +85,9 @@ IP allocation convention: VMs `.10-.49`, containers `.50-.89`, incus `.90-.129`
|
|||||||
- Always use `--no-link` when running `nix build`
|
- 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
|
- 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
|
- 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.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{ ... }:
|
{ config, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
nix = {
|
nix = {
|
||||||
@@ -6,11 +6,11 @@
|
|||||||
substituters = [
|
substituters = [
|
||||||
"https://cache.nixos.org/"
|
"https://cache.nixos.org/"
|
||||||
"https://nix-community.cachix.org"
|
"https://nix-community.cachix.org"
|
||||||
"http://s0.koi-bebop.ts.net:5000"
|
"http://s0.neet.dev:28338/nixos"
|
||||||
];
|
];
|
||||||
trusted-public-keys = [
|
trusted-public-keys = [
|
||||||
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
"nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
|
||||||
"s0.koi-bebop.ts.net:OjbzD86YjyJZpCp9RWaQKANaflcpKhtzBMNP8I2aPUU="
|
"nixos:e5AMCUWWEX9MESWAAMjBkZdGUpl588NhgsUO3HsdhFw="
|
||||||
];
|
];
|
||||||
|
|
||||||
# Allow substituters to be offline
|
# Allow substituters to be offline
|
||||||
@@ -19,6 +19,11 @@
|
|||||||
# and use this flag as intended for deciding if it should build missing
|
# and use this flag as intended for deciding if it should build missing
|
||||||
# derivations locally. See https://github.com/NixOS/nix/issues/6901
|
# derivations locally. See https://github.com/NixOS/nix/issues/6901
|
||||||
fallback = true;
|
fallback = true;
|
||||||
|
|
||||||
|
# Authenticate to private nixos cache
|
||||||
|
netrc-file = config.age.secrets.attic-netrc.path;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
age.secrets.attic-netrc.file = ../secrets/attic-netrc.age;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
./binary-cache.nix
|
./binary-cache.nix
|
||||||
./flakes.nix
|
./flakes.nix
|
||||||
./auto-update.nix
|
./auto-update.nix
|
||||||
|
./ntfy-alerts.nix
|
||||||
|
./zfs-alerts.nix
|
||||||
./shell.nix
|
./shell.nix
|
||||||
./network
|
./network
|
||||||
./boot
|
./boot
|
||||||
@@ -100,5 +102,5 @@
|
|||||||
security.acme.defaults.email = "zuckerberg@neet.dev";
|
security.acme.defaults.email = "zuckerberg@neet.dev";
|
||||||
|
|
||||||
# Enable Desktop Environment if this is a PC (machine role is "personal")
|
# Enable Desktop Environment if this is a PC (machine role is "personal")
|
||||||
de.enable = lib.mkDefault (config.thisMachine.hasRole."personal");
|
de.enable = lib.mkDefault (config.thisMachine.hasRole."personal" && !config.boot.isContainer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ in
|
|||||||
|
|
||||||
config.services.tailscale.enable = mkDefault (!config.boot.isContainer);
|
config.services.tailscale.enable = mkDefault (!config.boot.isContainer);
|
||||||
|
|
||||||
|
# Trust Tailscale interface - access control is handled by Tailscale ACLs.
|
||||||
|
# Required because nftables (used by Incus) breaks Tailscale's automatic iptables rules.
|
||||||
|
config.networking.firewall.trustedInterfaces = mkIf cfg.enable [ "tailscale0" ];
|
||||||
|
|
||||||
# MagicDNS
|
# MagicDNS
|
||||||
config.networking.nameservers = mkIf cfg.enable [ "1.1.1.1" "8.8.8.8" ];
|
config.networking.nameservers = mkIf cfg.enable [ "1.1.1.1" "8.8.8.8" ];
|
||||||
config.networking.search = mkIf cfg.enable [ "koi-bebop.ts.net" ];
|
config.networking.search = mkIf cfg.enable [ "koi-bebop.ts.net" ];
|
||||||
|
|||||||
@@ -4,15 +4,15 @@ let
|
|||||||
builderUserName = "nix-builder";
|
builderUserName = "nix-builder";
|
||||||
|
|
||||||
builderRole = "nix-builder";
|
builderRole = "nix-builder";
|
||||||
builders = config.machines.withRole.${builderRole};
|
builders = config.machines.withRole.${builderRole} or [];
|
||||||
thisMachineIsABuilder = config.thisMachine.hasRole.${builderRole};
|
thisMachineIsABuilder = config.thisMachine.hasRole.${builderRole} or false;
|
||||||
|
|
||||||
# builders don't include themselves as a remote builder
|
# builders don't include themselves as a remote builder
|
||||||
otherBuilders = lib.filter (hostname: hostname != config.networking.hostName) builders;
|
otherBuilders = lib.filter (hostname: hostname != config.networking.hostName) builders;
|
||||||
in
|
in
|
||||||
lib.mkMerge [
|
lib.mkMerge [
|
||||||
# configure builder
|
# configure builder
|
||||||
(lib.mkIf thisMachineIsABuilder {
|
(lib.mkIf (thisMachineIsABuilder && !config.boot.isContainer) {
|
||||||
users.users.${builderUserName} = {
|
users.users.${builderUserName} = {
|
||||||
description = "Distributed Nix Build User";
|
description = "Distributed Nix Build User";
|
||||||
group = builderUserName;
|
group = builderUserName;
|
||||||
|
|||||||
57
common/ntfy-alerts.nix
Normal file
57
common/ntfy-alerts.nix
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
{ 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
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ in
|
|||||||
../shell.nix
|
../shell.nix
|
||||||
hostConfig.inputs.home-manager.nixosModules.home-manager
|
hostConfig.inputs.home-manager.nixosModules.home-manager
|
||||||
hostConfig.inputs.nix-index-database.nixosModules.default
|
hostConfig.inputs.nix-index-database.nixosModules.default
|
||||||
|
hostConfig.inputs.agenix.nixosModules.default
|
||||||
];
|
];
|
||||||
|
|
||||||
nixpkgs.overlays = [
|
nixpkgs.overlays = [
|
||||||
@@ -116,6 +117,13 @@ in
|
|||||||
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
||||||
nix.settings.trusted-users = [ "googlebot" ];
|
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)
|
# Make nixpkgs available in NIX_PATH and registry (like the NixOS ISO)
|
||||||
# This allows `nix-shell -p`, `nix repl '<nixpkgs>'`, etc. to work
|
# This allows `nix-shell -p`, `nix repl '<nixpkgs>'`, etc. to work
|
||||||
nix.nixPath = [ "nixpkgs=${hostConfig.inputs.nixpkgs}" ];
|
nix.nixPath = [ "nixpkgs=${hostConfig.inputs.nixpkgs}" ];
|
||||||
|
|||||||
62
common/server/atticd.nix
Normal file
62
common/server/atticd.nix
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
{ config, lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
config = lib.mkIf (config.thisMachine.hasRole."binary-cache" && !config.boot.isContainer) {
|
||||||
|
services.atticd = {
|
||||||
|
enable = true;
|
||||||
|
environmentFile = config.age.secrets.atticd-credentials.path;
|
||||||
|
settings = {
|
||||||
|
listen = "[::]:28338";
|
||||||
|
database.url = "postgresql:///atticd?host=/run/postgresql";
|
||||||
|
require-proof-of-possession = false;
|
||||||
|
|
||||||
|
# Disable chunking — the dedup savings don't justify the CPU/IO
|
||||||
|
# overhead for local storage, especially on ZFS which already
|
||||||
|
# does block-level compression.
|
||||||
|
chunking = {
|
||||||
|
nar-size-threshold = 0;
|
||||||
|
min-size = 16 * 1024;
|
||||||
|
avg-size = 64 * 1024;
|
||||||
|
max-size = 256 * 1024;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Let ZFS handle compression instead of double-compressing.
|
||||||
|
compression.type = "none";
|
||||||
|
|
||||||
|
garbage-collection.default-retention-period = "6 months";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# PostgreSQL for atticd
|
||||||
|
services.postgresql = {
|
||||||
|
enable = true;
|
||||||
|
ensureDatabases = [ "atticd" ];
|
||||||
|
ensureUsers = [{
|
||||||
|
name = "atticd";
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
}];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Use a static user so the ZFS mountpoint at /var/lib/atticd works
|
||||||
|
# (DynamicUser conflicts with ZFS mountpoints)
|
||||||
|
users.users.atticd = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = "atticd";
|
||||||
|
home = "/var/lib/atticd";
|
||||||
|
};
|
||||||
|
users.groups.atticd = { };
|
||||||
|
|
||||||
|
systemd.services.atticd = {
|
||||||
|
after = [ "postgresql.service" ];
|
||||||
|
requires = [ "postgresql.service" ];
|
||||||
|
partOf = [ "postgresql.service" ];
|
||||||
|
serviceConfig = {
|
||||||
|
DynamicUser = lib.mkForce false;
|
||||||
|
User = "atticd";
|
||||||
|
Group = "atticd";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
age.secrets.atticd-credentials.file = ../../secrets/atticd-credentials.age;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -12,8 +12,11 @@
|
|||||||
./mailserver.nix
|
./mailserver.nix
|
||||||
./nextcloud.nix
|
./nextcloud.nix
|
||||||
./gitea-actions-runner.nix
|
./gitea-actions-runner.nix
|
||||||
|
./atticd.nix
|
||||||
./librechat.nix
|
./librechat.nix
|
||||||
./actualbudget.nix
|
./actualbudget.nix
|
||||||
./unifi.nix
|
./unifi.nix
|
||||||
|
./ntfy.nix
|
||||||
|
./gatus.nix
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
146
common/server/gatus.nix
Normal file
146
common/server/gatus.nix
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
{ 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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,132 +1,85 @@
|
|||||||
{ config, pkgs, lib, ... }:
|
{ config, lib, ... }:
|
||||||
|
|
||||||
# Gitea Actions Runner. Starts 'host' runner that runs directly on the host inside of a nixos container
|
# Gitea Actions Runner inside a NixOS container.
|
||||||
# This is useful for providing a real Nix/OS builder to gitea.
|
# The container shares the host's /nix/store (read-only) and nix-daemon socket,
|
||||||
# Warning, NixOS containers are not secure. For example, the container shares the /nix/store
|
# so builds go through the host daemon and outputs land in the host store.
|
||||||
# Therefore, this should not be used to run untrusted code.
|
# Warning: NixOS containers are not fully secure — do not run untrusted code.
|
||||||
# To enable, assign a machine the 'gitea-actions-runner' system role
|
# To enable, assign a machine the 'gitea-actions-runner' system role.
|
||||||
|
|
||||||
# TODO: skipping running inside of nixos container for now because of issues getting docker/podman running
|
|
||||||
|
|
||||||
let
|
let
|
||||||
thisMachineIsARunner = config.thisMachine.hasRole."gitea-actions-runner";
|
thisMachineIsARunner = config.thisMachine.hasRole."gitea-actions-runner";
|
||||||
containerName = "gitea-runner";
|
containerName = "gitea-runner";
|
||||||
|
giteaRunnerUid = 991;
|
||||||
|
giteaRunnerGid = 989;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
config = lib.mkIf (thisMachineIsARunner && !config.boot.isContainer) {
|
config = lib.mkIf (thisMachineIsARunner && !config.boot.isContainer) {
|
||||||
# containers.${containerName} = {
|
|
||||||
# ephemeral = true;
|
|
||||||
# autoStart = true;
|
|
||||||
|
|
||||||
# # for podman
|
containers.${containerName} = {
|
||||||
# enableTun = true;
|
autoStart = true;
|
||||||
|
ephemeral = true;
|
||||||
|
|
||||||
# # privateNetwork = true;
|
bindMounts = {
|
||||||
# # hostAddress = "172.16.101.1";
|
"/run/agenix/gitea-actions-runner-token" = {
|
||||||
# # localAddress = "172.16.101.2";
|
hostPath = "/run/agenix/gitea-actions-runner-token";
|
||||||
|
isReadOnly = true;
|
||||||
|
};
|
||||||
|
"/var/lib/gitea-runner" = {
|
||||||
|
hostPath = "/var/lib/gitea-runner";
|
||||||
|
isReadOnly = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
# bindMounts =
|
config = { config, lib, pkgs, ... }: {
|
||||||
# {
|
system.stateVersion = "25.11";
|
||||||
# "/run/agenix/gitea-actions-runner-token" = {
|
|
||||||
# hostPath = "/run/agenix/gitea-actions-runner-token";
|
|
||||||
# isReadOnly = true;
|
|
||||||
# };
|
|
||||||
# "/var/lib/gitea-runner" = {
|
|
||||||
# hostPath = "/var/lib/gitea-runner";
|
|
||||||
# isReadOnly = false;
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
|
|
||||||
# extraFlags = [
|
|
||||||
# # Allow podman
|
|
||||||
# ''--system-call-filter=thisystemcalldoesnotexistforsure''
|
|
||||||
# ];
|
|
||||||
|
|
||||||
# additionalCapabilities = [
|
|
||||||
# "CAP_SYS_ADMIN"
|
|
||||||
# ];
|
|
||||||
|
|
||||||
# config = {
|
|
||||||
# imports = allModules;
|
|
||||||
|
|
||||||
# # speeds up evaluation
|
|
||||||
# nixpkgs.pkgs = pkgs;
|
|
||||||
|
|
||||||
# networking.hostName = lib.mkForce containerName;
|
|
||||||
|
|
||||||
# # don't use remote builders
|
|
||||||
# nix.distributedBuilds = lib.mkForce false;
|
|
||||||
|
|
||||||
# environment.systemPackages = with pkgs; [
|
|
||||||
# git
|
|
||||||
# # Gitea Actions rely heavily on node. Include it because it would be installed anyway.
|
|
||||||
# nodejs
|
|
||||||
# ];
|
|
||||||
|
|
||||||
# services.gitea-actions-runner.instances.inst = {
|
|
||||||
# enable = true;
|
|
||||||
# name = config.networking.hostName;
|
|
||||||
# url = "https://git.neet.dev/";
|
|
||||||
# tokenFile = "/run/agenix/gitea-actions-runner-token";
|
|
||||||
# labels = [
|
|
||||||
# "ubuntu-latest:docker://node:18-bullseye"
|
|
||||||
# "nixos:host"
|
|
||||||
# ];
|
|
||||||
# };
|
|
||||||
|
|
||||||
# # To allow building on the host, must override the the service's config so it doesn't use a dynamic user
|
|
||||||
# systemd.services.gitea-runner-inst.serviceConfig.DynamicUser = lib.mkForce false;
|
|
||||||
# users.users.gitea-runner = {
|
|
||||||
# home = "/var/lib/gitea-runner";
|
|
||||||
# group = "gitea-runner";
|
|
||||||
# isSystemUser = true;
|
|
||||||
# createHome = true;
|
|
||||||
# };
|
|
||||||
# users.groups.gitea-runner = { };
|
|
||||||
|
|
||||||
# virtualisation.podman.enable = true;
|
|
||||||
# boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
|
|
||||||
# };
|
|
||||||
# };
|
|
||||||
|
|
||||||
# networking.nat.enable = true;
|
|
||||||
# networking.nat.internalInterfaces = [
|
|
||||||
# "ve-${containerName}"
|
|
||||||
# ];
|
|
||||||
# networking.ip_forward = true;
|
|
||||||
|
|
||||||
# don't use remote builders
|
|
||||||
nix.distributedBuilds = lib.mkForce false;
|
|
||||||
|
|
||||||
services.gitea-actions-runner.instances.inst = {
|
services.gitea-actions-runner.instances.inst = {
|
||||||
enable = true;
|
enable = true;
|
||||||
name = config.networking.hostName;
|
name = containerName;
|
||||||
url = "https://git.neet.dev/";
|
url = "https://git.neet.dev/";
|
||||||
tokenFile = "/run/agenix/gitea-actions-runner-token";
|
tokenFile = "/run/agenix/gitea-actions-runner-token";
|
||||||
labels = [
|
labels = [ "nixos:host" ];
|
||||||
"ubuntu-latest:docker://node:18-bullseye"
|
|
||||||
"nixos:host"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
# Disable dynamic user so runner state persists via bind mount
|
||||||
git
|
assertions = [{
|
||||||
# Gitea Actions rely heavily on node. Include it because it would be installed anyway.
|
assertion = config.systemd.services.gitea-runner-inst.enable;
|
||||||
nodejs
|
message = "Expected systemd service 'gitea-runner-inst' is not enabled — the gitea-actions-runner module may have changed its naming scheme.";
|
||||||
];
|
}];
|
||||||
|
|
||||||
# To allow building on the host, must override the the service's config so it doesn't use a dynamic user
|
|
||||||
systemd.services.gitea-runner-inst.serviceConfig.DynamicUser = lib.mkForce false;
|
systemd.services.gitea-runner-inst.serviceConfig.DynamicUser = lib.mkForce false;
|
||||||
users.users.gitea-runner = {
|
users.users.gitea-runner = {
|
||||||
|
uid = giteaRunnerUid;
|
||||||
home = "/var/lib/gitea-runner";
|
home = "/var/lib/gitea-runner";
|
||||||
group = "gitea-runner";
|
group = "gitea-runner";
|
||||||
isSystemUser = true;
|
isSystemUser = true;
|
||||||
createHome = true;
|
createHome = true;
|
||||||
};
|
};
|
||||||
users.groups.gitea-runner = { };
|
users.groups.gitea-runner.gid = giteaRunnerGid;
|
||||||
|
|
||||||
virtualisation.podman.enable = true;
|
nix.settings.experimental-features = [ "nix-command" "flakes" ];
|
||||||
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
|
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
git
|
||||||
|
nodejs
|
||||||
|
jq
|
||||||
|
attic-client
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# 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 = {
|
||||||
|
uid = giteaRunnerUid;
|
||||||
|
home = "/var/lib/gitea-runner";
|
||||||
|
group = "gitea-runner";
|
||||||
|
isSystemUser = true;
|
||||||
|
createHome = true;
|
||||||
|
};
|
||||||
|
users.groups.gitea-runner.gid = giteaRunnerGid;
|
||||||
|
|
||||||
age.secrets.gitea-actions-runner-token.file = ../../secrets/gitea-actions-runner-token.age;
|
age.secrets.gitea-actions-runner-token.file = ../../secrets/gitea-actions-runner-token.age;
|
||||||
};
|
};
|
||||||
|
|||||||
38
common/server/ntfy.nix
Normal file
38
common/server/ntfy.nix
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{ 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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -26,6 +26,16 @@
|
|||||||
"printcap name" = "cups";
|
"printcap name" = "cups";
|
||||||
|
|
||||||
"hide files" = "/.nobackup/.DS_Store/._.DS_Store/";
|
"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 = {
|
public = {
|
||||||
path = "/data/samba/Public";
|
path = "/data/samba/Public";
|
||||||
|
|||||||
87
common/zfs-alerts.nix
Normal file
87
common/zfs-alerts.nix
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
{ 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
62
flake.lock
generated
@@ -14,11 +14,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1762618334,
|
"lastModified": 1770165109,
|
||||||
"narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=",
|
"narHash": "sha256-9VnK6Oqai65puVJ4WYtCTvlJeXxMzAp/69HhQuTdl/I=",
|
||||||
"owner": "ryantm",
|
"owner": "ryantm",
|
||||||
"repo": "agenix",
|
"repo": "agenix",
|
||||||
"rev": "fcdea223397448d35d9b31f798479227e80183f6",
|
"rev": "b027ee29d959fda4b60b57566d64c98a202e0feb",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -53,11 +53,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1770491193,
|
"lastModified": 1771632347,
|
||||||
"narHash": "sha256-zdnWeXmPZT8BpBo52s4oansT1Rq0SNzksXKpEcMc5lE=",
|
"narHash": "sha256-kNm0YX9RUwf7GZaWQu2F71ccm4OUMz0xFkXn6mGPfps=",
|
||||||
"owner": "sadjow",
|
"owner": "sadjow",
|
||||||
"repo": "claude-code-nix",
|
"repo": "claude-code-nix",
|
||||||
"rev": "f68a2683e812d1e4f9a022ff3e0206d46347d019",
|
"rev": "ec90f84b2ea21f6d2272e00d1becbc13030d1895",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -124,11 +124,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1766051518,
|
"lastModified": 1770019181,
|
||||||
"narHash": "sha256-znKOwPXQnt3o7lDb3hdf19oDo0BLP4MfBOYiWkEHoik=",
|
"narHash": "sha256-hwsYgDnby50JNVpTRYlF3UR/Rrpt01OrxVuryF40CFY=",
|
||||||
"owner": "serokell",
|
"owner": "serokell",
|
||||||
"repo": "deploy-rs",
|
"repo": "deploy-rs",
|
||||||
"rev": "d5eff7f948535b9c723d60cd8239f8f11ddc90fa",
|
"rev": "77c906c0ba56aabdbc72041bf9111b565cdd6171",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -186,11 +186,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1763988335,
|
"lastModified": 1769939035,
|
||||||
"narHash": "sha256-QlcnByMc8KBjpU37rbq5iP7Cp97HvjRP0ucfdh+M4Qc=",
|
"narHash": "sha256-Fok2AmefgVA0+eprw2NDwqKkPGEI5wvR+twiZagBvrg=",
|
||||||
"owner": "cachix",
|
"owner": "cachix",
|
||||||
"repo": "git-hooks.nix",
|
"repo": "git-hooks.nix",
|
||||||
"rev": "50b9238891e388c9fdc6a5c49e49c42533a1b5ce",
|
"rev": "a8ca480175326551d6c4121498316261cbb5b260",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -228,11 +228,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1768068402,
|
"lastModified": 1771756436,
|
||||||
"narHash": "sha256-bAXnnJZKJiF7Xr6eNW6+PhBf1lg2P1aFUO9+xgWkXfA=",
|
"narHash": "sha256-Tl2I0YXdhSTufGqAaD1ySh8x+cvVsEI1mJyJg12lxhI=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "home-manager",
|
"repo": "home-manager",
|
||||||
"rev": "8bc5473b6bc2b6e1529a9c4040411e1199c43b4c",
|
"rev": "5bd3589390b431a63072868a90c0f24771ff4cbb",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -250,11 +250,11 @@
|
|||||||
"spectrum": "spectrum"
|
"spectrum": "spectrum"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1770310890,
|
"lastModified": 1771802632,
|
||||||
"narHash": "sha256-lyWAs4XKg3kLYaf4gm5qc5WJrDkYy3/qeV5G733fJww=",
|
"narHash": "sha256-UAH8YfrHRvXAMeFxUzJ4h4B1loz1K1wiNUNI8KiPqOg=",
|
||||||
"owner": "astro",
|
"owner": "astro",
|
||||||
"repo": "microvm.nix",
|
"repo": "microvm.nix",
|
||||||
"rev": "68c9f9c6ca91841f04f726a298c385411b7bfcd5",
|
"rev": "b67e3d80df3ec35bdfd3a00ad64ee437ef4fcded",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -270,11 +270,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1765267181,
|
"lastModified": 1771734689,
|
||||||
"narHash": "sha256-d3NBA9zEtBu2JFMnTBqWj7Tmi7R5OikoU2ycrdhQEws=",
|
"narHash": "sha256-/phvMgr1yutyAMjKnZlxkVplzxHiz60i4rc+gKzpwhg=",
|
||||||
"owner": "Mic92",
|
"owner": "Mic92",
|
||||||
"repo": "nix-index-database",
|
"repo": "nix-index-database",
|
||||||
"rev": "82befcf7dc77c909b0f2a09f5da910ec95c5b78f",
|
"rev": "8f590b832326ab9699444f3a48240595954a4b10",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -285,11 +285,11 @@
|
|||||||
},
|
},
|
||||||
"nixos-hardware": {
|
"nixos-hardware": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1767185284,
|
"lastModified": 1771423359,
|
||||||
"narHash": "sha256-ljDBUDpD1Cg5n3mJI81Hz5qeZAwCGxon4kQW3Ho3+6Q=",
|
"narHash": "sha256-yRKJ7gpVmXbX2ZcA8nFi6CMPkJXZGjie2unsiMzj3Ig=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixos-hardware",
|
"repo": "nixos-hardware",
|
||||||
"rev": "40b1a28dce561bea34858287fbb23052c3ee63fe",
|
"rev": "740a22363033e9f1bb6270fbfb5a9574067af15b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -301,16 +301,16 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1768250893,
|
"lastModified": 1771369470,
|
||||||
"narHash": "sha256-fWNJYFx0QvnlGlcw54EoOYs/wv2icINHUz0FVdh9RIo=",
|
"narHash": "sha256-0NBlEBKkN3lufyvFegY4TYv5mCNHbi5OmBDrzihbBMQ=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "3971af1a8fc3646b1d554cb1269b26c84539c22e",
|
"rev": "0182a361324364ae3f436a63005877674cf45efb",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"ref": "master",
|
"ref": "nixos-unstable",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
@@ -344,11 +344,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1766321686,
|
"lastModified": 1770659507,
|
||||||
"narHash": "sha256-icOWbnD977HXhveirqA10zoqvErczVs3NKx8Bj+ikHY=",
|
"narHash": "sha256-RVZno9CypFN3eHxfULKN1K7mb/Cq0HkznnWqnshxpWY=",
|
||||||
"owner": "simple-nixos-mailserver",
|
"owner": "simple-nixos-mailserver",
|
||||||
"repo": "nixos-mailserver",
|
"repo": "nixos-mailserver",
|
||||||
"rev": "7d433bf89882f61621f95082e90a4ab91eb0bdd3",
|
"rev": "781e833633ebc0873d251772a74e4400a73f5d78",
|
||||||
"type": "gitlab"
|
"type": "gitlab"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
10
flake.nix
10
flake.nix
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
# nixpkgs
|
# nixpkgs
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/master";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
|
||||||
# Common Utils Among flake inputs
|
# Common Utils Among flake inputs
|
||||||
systems.url = "github:nix-systems/default";
|
systems.url = "github:nix-systems/default";
|
||||||
@@ -175,10 +175,10 @@
|
|||||||
kexec = (mkEphemeral "x86_64-linux").config.system.build.images.kexec;
|
kexec = (mkEphemeral "x86_64-linux").config.system.build.images.kexec;
|
||||||
iso = (mkEphemeral "x86_64-linux").config.system.build.images.iso;
|
iso = (mkEphemeral "x86_64-linux").config.system.build.images.iso;
|
||||||
};
|
};
|
||||||
"aarch64-linux" = {
|
# "aarch64-linux" = {
|
||||||
kexec = (mkEphemeral "aarch64-linux").config.system.build.images.kexec;
|
# kexec = (mkEphemeral "aarch64-linux").config.system.build.images.kexec;
|
||||||
iso = (mkEphemeral "aarch64-linux").config.system.build.images.iso;
|
# iso = (mkEphemeral "aarch64-linux").config.system.build.images.iso;
|
||||||
};
|
# };
|
||||||
};
|
};
|
||||||
|
|
||||||
overlays.default = import ./overlays { inherit inputs; };
|
overlays.default = import ./overlays { inherit inputs; };
|
||||||
|
|||||||
@@ -61,7 +61,8 @@ in
|
|||||||
|
|
||||||
programs.vscode = {
|
programs.vscode = {
|
||||||
enable = thisMachineIsPersonal;
|
enable = thisMachineIsPersonal;
|
||||||
package = pkgs.vscodium;
|
# Must use fhs version for vscode-lldb
|
||||||
|
package = pkgs.vscodium-fhs;
|
||||||
profiles.default = {
|
profiles.default = {
|
||||||
userSettings = {
|
userSettings = {
|
||||||
editor.formatOnSave = true;
|
editor.formatOnSave = true;
|
||||||
@@ -78,6 +79,15 @@ in
|
|||||||
lsp.serverPort = 6005; # port needs to match Godot configuration
|
lsp.serverPort = 6005; # port needs to match Godot configuration
|
||||||
editorPath.godot4 = "godot-mono";
|
editorPath.godot4 = "godot-mono";
|
||||||
};
|
};
|
||||||
|
rust-analyzer = {
|
||||||
|
restartServerOnConfigChange = true;
|
||||||
|
testExplorer = true;
|
||||||
|
server.path = "rust-analyzer"; # Use the rust-analyzer from PATH (which is set by nixEnvSelector from the project's flake)
|
||||||
|
};
|
||||||
|
nixEnvSelector = {
|
||||||
|
useFlakes = true; # This hasn't ever worked for me and I have to use shell.nix... but maybe someday
|
||||||
|
suggestion = false; # Stop really annoy nagging
|
||||||
|
};
|
||||||
};
|
};
|
||||||
extensions = with pkgs.vscode-extensions; [
|
extensions = with pkgs.vscode-extensions; [
|
||||||
bbenoist.nix # nix syntax support
|
bbenoist.nix # nix syntax support
|
||||||
|
|||||||
@@ -13,6 +13,18 @@
|
|||||||
# Upstream interface for sandbox networking (NAT)
|
# Upstream interface for sandbox networking (NAT)
|
||||||
networking.sandbox.upstreamInterface = lib.mkDefault "enp191s0";
|
networking.sandbox.upstreamInterface = lib.mkDefault "enp191s0";
|
||||||
|
|
||||||
|
# Enable sandboxed workspace
|
||||||
|
sandboxed-workspace = {
|
||||||
|
enable = true;
|
||||||
|
workspaces.test-incus = {
|
||||||
|
type = "incus";
|
||||||
|
autoStart = true;
|
||||||
|
config = ./workspaces/test-container.nix;
|
||||||
|
ip = "192.168.83.90";
|
||||||
|
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL0SNSy/MdW38NqKzLr1SG8WKrs8XkrqibacaJtJPzgW";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
environment.systemPackages = with pkgs; [
|
environment.systemPackages = with pkgs; [
|
||||||
system76-keyboard-configurator
|
system76-keyboard-configurator
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
systemRoles = [
|
systemRoles = [
|
||||||
"personal"
|
"personal"
|
||||||
"dns-challenge"
|
"dns-challenge"
|
||||||
|
"ntfy"
|
||||||
];
|
];
|
||||||
|
|
||||||
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID/Df5lG07Il7fizEgZR/T9bMlR0joESRJ7cqM9BkOyP";
|
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID/Df5lG07Il7fizEgZR/T9bMlR0joESRJ7cqM9BkOyP";
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
systemRoles = [
|
systemRoles = [
|
||||||
"personal"
|
"personal"
|
||||||
|
"ntfy"
|
||||||
];
|
];
|
||||||
|
|
||||||
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEQi3q8jU6vRruExAL60J7GFO1gS8HsmXVJuKRT4ljrG";
|
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEQi3q8jU6vRruExAL60J7GFO1gS8HsmXVJuKRT4ljrG";
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
{ lib, ... }:
|
|
||||||
|
|
||||||
{
|
|
||||||
imports = [
|
|
||||||
./hardware-configuration.nix
|
|
||||||
];
|
|
||||||
|
|
||||||
networking.hostName = "phil";
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
# 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";
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
{
|
|
||||||
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";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -108,4 +108,12 @@
|
|||||||
# librechat
|
# librechat
|
||||||
services.librechat-container.enable = true;
|
services.librechat-container.enable = true;
|
||||||
services.librechat-container.host = "chat.neet.dev";
|
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";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"dailybot"
|
"dailybot"
|
||||||
"gitea"
|
"gitea"
|
||||||
"librechat"
|
"librechat"
|
||||||
|
"ntfy"
|
||||||
];
|
];
|
||||||
|
|
||||||
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMBBlTAIp38RhErU1wNNV5MBeb+WGH0mhF/dxh5RsAXN";
|
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMBBlTAIp38RhErU1wNNV5MBeb+WGH0mhF/dxh5RsAXN";
|
||||||
|
|||||||
@@ -72,5 +72,5 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
powerManagement.cpuFreqGovernor = "powersave";
|
powerManagement.cpuFreqGovernor = "schedutil";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
"linkwarden"
|
"linkwarden"
|
||||||
"outline"
|
"outline"
|
||||||
"dns-challenge"
|
"dns-challenge"
|
||||||
|
"ntfy"
|
||||||
];
|
];
|
||||||
|
|
||||||
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwiXcUFtAvZCayhu4+AIcF+Ktrdgv9ee/mXSIhJbp4q";
|
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAwiXcUFtAvZCayhu4+AIcF+Ktrdgv9ee/mXSIhJbp4q";
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
systemRoles = [
|
systemRoles = [
|
||||||
"personal"
|
"personal"
|
||||||
"media-center"
|
"media-center"
|
||||||
|
"ntfy"
|
||||||
];
|
];
|
||||||
|
|
||||||
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHvdC1EiLqSNVmk5L1p7cWRIrrlelbK+NMj6tEBrwqIq";
|
hostKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHvdC1EiLqSNVmk5L1p7cWRIrrlelbK+NMj6tEBrwqIq";
|
||||||
|
|||||||
BIN
secrets/attic-netrc.age
Normal file
BIN
secrets/attic-netrc.age
Normal file
Binary file not shown.
BIN
secrets/atticd-credentials.age
Normal file
BIN
secrets/atticd-credentials.age
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
19
secrets/ntfy-token.age
Normal file
19
secrets/ntfy-token.age
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
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{‘
|
||||||
@@ -7,6 +7,9 @@ let
|
|||||||
|
|
||||||
# nobody is using this secret but I still need to be able to r/w it
|
# nobody is using this secret but I still need to be able to r/w it
|
||||||
nobody = sshKeys.userKeys;
|
nobody = sshKeys.userKeys;
|
||||||
|
|
||||||
|
# For secrets that all machines need to know
|
||||||
|
everyone = lib.unique (roles.personal ++ roles.server);
|
||||||
in
|
in
|
||||||
|
|
||||||
with roles;
|
with roles;
|
||||||
@@ -22,8 +25,10 @@ with roles;
|
|||||||
# nix binary cache
|
# nix binary cache
|
||||||
# public key: s0.koi-bebop.ts.net:OjbzD86YjyJZpCp9RWaQKANaflcpKhtzBMNP8I2aPUU=
|
# public key: s0.koi-bebop.ts.net:OjbzD86YjyJZpCp9RWaQKANaflcpKhtzBMNP8I2aPUU=
|
||||||
"binary-cache-private-key.age".publicKeys = binary-cache;
|
"binary-cache-private-key.age".publicKeys = binary-cache;
|
||||||
# public key: ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINpUZFFL9BpBVqeeU63sFPhR9ewuhEZerTCDIGW1NPSB
|
|
||||||
"binary-cache-push-sshkey.age".publicKeys = nobody; # this value is directly given to gitea
|
# attic binary cache
|
||||||
|
"atticd-credentials.age".publicKeys = binary-cache;
|
||||||
|
"attic-netrc.age".publicKeys = everyone;
|
||||||
|
|
||||||
# vpn
|
# vpn
|
||||||
"pia-login.age".publicKeys = pia;
|
"pia-login.age".publicKeys = pia;
|
||||||
@@ -38,8 +43,11 @@ with roles;
|
|||||||
"linkwarden-environment.age".publicKeys = linkwarden;
|
"linkwarden-environment.age".publicKeys = linkwarden;
|
||||||
|
|
||||||
# backups
|
# backups
|
||||||
"backblaze-s3-backups.age".publicKeys = personal ++ server;
|
"backblaze-s3-backups.age".publicKeys = everyone;
|
||||||
"restic-password.age".publicKeys = personal ++ server;
|
"restic-password.age".publicKeys = everyone;
|
||||||
|
|
||||||
|
# ntfy alerts
|
||||||
|
"ntfy-token.age".publicKeys = everyone;
|
||||||
|
|
||||||
# gitea actions runner
|
# gitea actions runner
|
||||||
"gitea-actions-runner-token.age".publicKeys = gitea-actions-runner;
|
"gitea-actions-runner-token.age".publicKeys = gitea-actions-runner;
|
||||||
|
|||||||
Reference in New Issue
Block a user