8 Commits
Author SHA1 Message Date
kurogeek 059319237f mob next [ci-skip] [ci skip] [skip ci]
lastFile:routers/default.nix
2026-05-22 16:16:50 +07:00
kurogeek f3a5392841 mob next [ci-skip] [ci skip] [skip ci]
lastFile:routers/default.nix
2026-05-22 14:48:01 +07:00
kurogeek 54b77af40a mob next [ci-skip] [ci skip] [skip ci]
lastFile:flake.nix
2026-05-21 17:15:56 +07:00
kurogeek 2173b4e9c0 mob next [ci-skip] [ci skip] [skip ci]
lastFile:flake.nix
2026-05-21 11:03:52 +07:00
kurogeek 522dbf3456 mob next [ci-skip] [ci skip] [skip ci]
lastFile:flake.nix
2026-05-21 09:30:47 +07:00
kurogeek 6ea98549aa mob next [ci-skip] [ci skip] [skip ci]
lastFile:flake.nix
2026-05-20 17:37:14 +07:00
kurogeek a0aee6cd5a mob next [ci-skip] [ci skip] [skip ci]
lastFile:flake.nix
2026-05-20 16:02:11 +07:00
kurogeek 1fd7995ecf mob next [ci-skip] [ci skip] [skip ci]
lastFile:flake.lock
2026-05-20 14:48:26 +07:00
955 changed files with 7112 additions and 16178 deletions
-1
View File
@@ -3,4 +3,3 @@
result
result-*
run-vm-*
.nixos-test-history
Generated
+84 -202
View File
@@ -53,69 +53,6 @@
"type": "github"
}
},
"clan-community": {
"inputs": {
"clan-core": [
"clan-core"
],
"data-mesher": [
"clan-community",
"clan-core",
"data-mesher"
],
"disko": [
"clan-community",
"clan-core",
"disko"
],
"flake-parts": [
"flake-parts"
],
"nix-darwin": [
"clan-community",
"clan-core",
"nix-darwin"
],
"nix-github-actions": "nix-github-actions",
"nix-select": [
"clan-community",
"clan-core",
"nix-select"
],
"nix-unit": "nix-unit",
"nixpkgs": [
"clan-community",
"clan-core",
"nixpkgs"
],
"sops-nix": [
"clan-community",
"clan-core",
"sops-nix"
],
"systems": [
"clan-community",
"clan-core",
"systems"
],
"treefmt-nix": [
"treefmt-nix"
]
},
"locked": {
"lastModified": 1784417092,
"narHash": "sha256-no5eDYWPUZZu4GtLufnA7b7CiZC4qAhCgf70gFiDLZk=",
"ref": "refs/heads/main",
"rev": "20371843d45f61217019e489d6857842dc8a0203",
"revCount": 73,
"type": "git",
"url": "https://git.clan.lol/clan/clan-community"
},
"original": {
"type": "git",
"url": "https://git.clan.lol/clan/clan-community"
}
},
"clan-core": {
"inputs": {
"data-mesher": "data-mesher",
@@ -135,11 +72,11 @@
]
},
"locked": {
"lastModified": 1781517972,
"narHash": "sha256-G8bIXFqifs/y62GNPwg20Ksf71raYwzmyN99gf1tXak=",
"lastModified": 1772411144,
"narHash": "sha256-WhXudztwPNnKXaqGX4DOqNfHzHdBSiGCvKGHM20pscw=",
"ref": "refs/heads/main",
"rev": "7fc62d0c25c7a97d7027a9c248e21c97c9b3acc1",
"revCount": 14604,
"rev": "92cc85bc24eb31ce5725e1e72753129810ce3fe9",
"revCount": 13201,
"type": "git",
"url": "https://git.clan.lol/clan/clan-core"
},
@@ -164,11 +101,11 @@
]
},
"locked": {
"lastModified": 1778718524,
"narHash": "sha256-pXLoI6Ax0EnUK6r34UM1vibVC7CfTu6j72R2692ZzPs=",
"rev": "12c552ad547d87254f33f33bddd1a2cdbeac754d",
"lastModified": 1772273147,
"narHash": "sha256-Wzhoc6ifjTDZi8aVRH3fuLJPdd4ouNTTwwVhgoMcMek=",
"rev": "d5de7a8d9e5726e678c94e62fe8ac3a809fee5da",
"type": "tarball",
"url": "https://git.clan.lol/api/v1/repos/clan/data-mesher/archive/12c552ad547d87254f33f33bddd1a2cdbeac754d.tar.gz"
"url": "https://git.clan.lol/api/v1/repos/clan/data-mesher/archive/d5de7a8d9e5726e678c94e62fe8ac3a809fee5da.tar.gz"
},
"original": {
"type": "tarball",
@@ -203,11 +140,11 @@
]
},
"locked": {
"lastModified": 1781152676,
"narHash": "sha256-RxWs5ND31KzTG7wvMM+PMfUjyNpmIEr999lqNARaM5o=",
"lastModified": 1771881364,
"narHash": "sha256-A5uE/hMium5of/QGC6JwF5TGoDAfpNtW00T0s9u/PN8=",
"owner": "nix-community",
"repo": "disko",
"rev": "ff8702b4de27f72b4c78573dfb89ec74e36abdf1",
"rev": "a4cb7bf73f264d40560ba527f9280469f1f081c6",
"type": "github"
},
"original": {
@@ -357,11 +294,11 @@
"std": "std"
},
"locked": {
"lastModified": 1782964989,
"narHash": "sha256-pU2Gye+1f+nvFleBTgXdeQfrQnKaJEuO2LT7PnsJ1p0=",
"lastModified": 1779175997,
"narHash": "sha256-Ps/4s3jwaZdLVEpO+1cRs54VbPbgMeXJUqa4CWSPJSY=",
"owner": "kurogeek",
"repo": "frappix",
"rev": "ac5e2814fc1aca188080bf6b50504cd329790e56",
"rev": "0f1b4bcfb8c3b976e808a57e491d10857a1a45ac",
"type": "github"
},
"original": {
@@ -416,11 +353,11 @@
]
},
"locked": {
"lastModified": 1781557312,
"narHash": "sha256-QOIRYSUFSq7L5mY3dZymaVhcnne3tPgoR9riB0WocjA=",
"lastModified": 1768068402,
"narHash": "sha256-bAXnnJZKJiF7Xr6eNW6+PhBf1lg2P1aFUO9+xgWkXfA=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "c03e4752899e55705dfa63979abd885c582a5c48",
"rev": "8bc5473b6bc2b6e1529a9c4040411e1199c43b4c",
"type": "github"
},
"original": {
@@ -547,11 +484,11 @@
]
},
"locked": {
"lastModified": 1781242433,
"narHash": "sha256-bchLZZ3sRn740zyvD2icZSnNoTaanN0nw7l6fjVXO+E=",
"lastModified": 1772379624,
"narHash": "sha256-NG9LLTWlz4YiaTAiRGChbrzbVxBfX+Auq4Ab/SWmk4A=",
"owner": "nix-darwin",
"repo": "nix-darwin",
"rev": "aabb2037edfc0f210723b72cd5f528aab5dd3f0b",
"rev": "52d061516108769656a8bd9c6e811c677ec5b462",
"type": "github"
},
"original": {
@@ -560,49 +497,6 @@
"type": "github"
}
},
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"clan-community",
"nixpkgs"
]
},
"locked": {
"lastModified": 1737420293,
"narHash": "sha256-F1G5ifvqTpJq7fdkT34e/Jy9VCyzd5XfJ9TO8fHhJWE=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "f4158fa080ef4503c8f4c820967d946c2af31ec9",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nix-github-actions_2": {
"inputs": {
"nixpkgs": [
"clan-community",
"nix-unit",
"nixpkgs"
]
},
"locked": {
"lastModified": 1737420293,
"narHash": "sha256-F1G5ifvqTpJq7fdkT34e/Jy9VCyzd5XfJ9TO8fHhJWE=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "f4158fa080ef4503c8f4c820967d946c2af31ec9",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nix-select": {
"locked": {
"lastModified": 1763303120,
@@ -616,32 +510,6 @@
"url": "https://git.clan.lol/clan/nix-select/archive/main.tar.gz"
}
},
"nix-unit": {
"inputs": {
"nix-github-actions": "nix-github-actions_2",
"nixpkgs": [
"clan-community",
"nixpkgs"
],
"treefmt-nix": [
"clan-community",
"treefmt-nix"
]
},
"locked": {
"lastModified": 1779338171,
"narHash": "sha256-affUbv/bwE8SLGhuWKniDr7SVO+Lo1XEPjCZdyU5kgQ=",
"owner": "nix-community",
"repo": "nix-unit",
"rev": "6ab1f232562a01d18b40d5ed6a58718c4f3a74bc",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-unit",
"type": "github"
}
},
"nixago": {
"inputs": {
"flake-utils": "flake-utils_3",
@@ -654,11 +522,11 @@
]
},
"locked": {
"lastModified": 1746801636,
"narHash": "sha256-dlcKfIXp/eqFHzFm+DzseXAWWlpVwyk9cTvCKGtVKkw=",
"lastModified": 1714086354,
"narHash": "sha256-yKVQMxL9p7zCWUhnGhDzRVT8sDgHoI3V595lBK0C2YA=",
"owner": "nix-community",
"repo": "nixago",
"rev": "8cc33f973ab3a891d8a41391e73ef451a783960b",
"rev": "5133633e9fe6b144c8e00e3b212cdbd5a173b63d",
"type": "github"
},
"original": {
@@ -667,29 +535,6 @@
"type": "github"
}
},
"nixos-images": {
"inputs": {
"nixos-stable": [
"nixpkgs"
],
"nixos-unstable": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1784802994,
"narHash": "sha256-4PcD0Ibzdkh85G+70w5dLlR9YgQ2bmNIjiPPMSzO57w=",
"owner": "nix-community",
"repo": "nixos-images",
"rev": "6ece16b0c97986fe085122e796044add4cc3ff64",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixos-images",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1712920918,
@@ -707,11 +552,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1781359544,
"narHash": "sha256-iUuzKQcyXvopYDDzFpMK5eQKP3WIJExYny2kJtbgUcE=",
"lastModified": 1778458615,
"narHash": "sha256-cY07EsdhBJ8tFXPzDYevgqxRev9ZLxFonuq9wmq5kwg=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "9f11f828c213641c2369a9f1fa31fe31557e3156",
"rev": "c6e5ca3c836a5f4dd9af9f2c1fc1c38f0fac988a",
"type": "github"
},
"original": {
@@ -736,6 +581,30 @@
"type": "github"
}
},
"openwrt-imagebuilder": {
"inputs": {
"flake-parts": [
"flake-parts"
],
"nixpkgs": [
"nixpkgs"
],
"systems": "systems_4"
},
"locked": {
"lastModified": 1777544882,
"narHash": "sha256-QqrZLvCSg4w2jmLGXs/4KJVXZeogxIeuX0Hw4o5qWwU=",
"owner": "astro",
"repo": "nix-openwrt-imagebuilder",
"rev": "149d0e41bc9ed257290c87a8fdb18c4071e37e07",
"type": "github"
},
"original": {
"owner": "astro",
"repo": "nix-openwrt-imagebuilder",
"type": "github"
}
},
"paisano": {
"inputs": {
"call-flake": "call-flake",
@@ -808,7 +677,6 @@
},
"root": {
"inputs": {
"clan-community": "clan-community",
"clan-core": "clan-core",
"devshell": "devshell",
"flake-parts": "flake-parts",
@@ -816,8 +684,8 @@
"home-manager": "home-manager",
"import-tree": "import-tree",
"liminix": "liminix",
"nixos-images": "nixos-images",
"nixpkgs": "nixpkgs_2",
"openwrt-imagebuilder": "openwrt-imagebuilder",
"plasma-manager": "plasma-manager",
"treefmt-nix": "treefmt-nix"
}
@@ -830,11 +698,11 @@
]
},
"locked": {
"lastModified": 1780547341,
"narHash": "sha256-Gq8KNx5A7hBB3uGJaj6eQfLDIz5YdLu92gqBcvHvoUo=",
"lastModified": 1772340640,
"narHash": "sha256-1nq7+Kt5IUBD8Hu3nptVPbMf+22rNJoHT0t9L1X+GKA=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "9ed65852b6257fbeae4355bc24ecfea307ca759a",
"rev": "dec4d8eac700dcd2fe3c020857d3ee220ec147f1",
"type": "github"
},
"original": {
@@ -920,22 +788,6 @@
}
},
"systems": {
"locked": {
"lastModified": 1774449309,
"narHash": "sha256-brhZ8DmuGtzkCYHJg4HEd602amKm89Y9ytsFZ5uWD1w=",
"owner": "nix-systems",
"repo": "default",
"rev": "c29398b59d2048c4ab79345812849c9bd15e9150",
"type": "github"
},
"original": {
"owner": "nix-systems",
"ref": "future-26.11",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
@@ -950,6 +802,21 @@
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1680978846,
"narHash": "sha256-Gtqg8b/v49BFDpDetjclCYXm8mAnTrUzR0JnE2nv5aw=",
"owner": "nix-systems",
"repo": "x86_64-linux",
"rev": "2ecfcac5e15790ba6ce360ceccddb15ad16d08a8",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "x86_64-linux",
"type": "github"
}
},
"systems_3": {
"locked": {
"lastModified": 1681028828,
@@ -965,6 +832,21 @@
"type": "github"
}
},
"systems_4": {
"locked": {
"lastModified": 1680978846,
"narHash": "sha256-Gtqg8b/v49BFDpDetjclCYXm8mAnTrUzR0JnE2nv5aw=",
"owner": "nix-systems",
"repo": "x86_64-linux",
"rev": "2ecfcac5e15790ba6ce360ceccddb15ad16d08a8",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "x86_64-linux",
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": [
+7 -26
View File
@@ -7,12 +7,6 @@
inputs.treefmt-nix.follows = "treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
clan-community = {
url = "git+https://git.clan.lol/clan/clan-community";
inputs.clan-core.follows = "clan-core";
inputs.flake-parts.follows = "flake-parts";
inputs.treefmt-nix.follows = "treefmt-nix";
};
devshell = {
url = "github:numtide/devshell";
inputs.nixpkgs.follows = "nixpkgs";
@@ -32,6 +26,11 @@
};
import-tree.url = "github:vic/import-tree";
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
openwrt-imagebuilder = {
inputs.nixpkgs.follows = "nixpkgs";
inputs.flake-parts.follows = "flake-parts";
url = "github:astro/nix-openwrt-imagebuilder";
};
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
@@ -45,12 +44,6 @@
inputs.nixpkgs.follows = "nixpkgs";
inputs.devshell.follows = "devshell";
};
nixos-images = {
url = "github:nix-community/nixos-images";
inputs.nixos-unstable.follows = "nixpkgs";
inputs.nixos-stable.follows = "nixpkgs";
};
};
outputs =
{
@@ -68,6 +61,7 @@
./shell.nix
./overlays
./modules/nixos
./machines
./routers
./inventories
@@ -89,21 +83,8 @@
packages.think = pkgs.think-gtcm;
packages.think-be = pkgs.think-backend-gtcm;
packages.file-uploader = pkgs.gtcm-file-uploader;
packages.installer =
(pkgs.nixos [
inputs.nixos-images.nixosModules.image-installer
{
users.users.root.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAB/raxJR8gASmquP63weHelbi+da2WBJR1DgzHPNz/f"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDuhpzDHBPvn8nv8RH1MRomDOaXyP4GziQm7r3MZ1Syk"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEcZ/p1Ofa9liwIzPWzNtONhJ7+FUWd2lCz33r81t8+w kurogeek@kurogeek"
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIOJDRQfb1+7VK5tOe8W40iryfBWYRO6Uf1r2viDjmsJtAAAABHNzaDo="
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIDgsWq+G/tcr6eUQYT7+sJeBtRmOMabgFiIgIV44XNc6AAAABHNzaDo="
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJMi3TAuwDtIeO4MsORlBZ31HzaV5bji1fFBPcC9/tWuAAAABHNzaDo="
];
}
]).config.system.build.isoImage;
};
}
);
}
+27 -242
View File
@@ -19,11 +19,13 @@
w = [ "sirius" ];
b4l = [
"rigel"
"neptune"
"rana"
"petra"
"alasia"
];
phonebox = [
"neptune"
"rigel"
"almach"
"alpheratz"
@@ -31,166 +33,25 @@
"adhil"
"buna"
];
prometheus = [
"cursa"
"rigel"
"vega"
];
dm-bootstrapper = [
"rigel"
"cursa"
"deneb"
"bosona"
"canopus"
global-network = [
"rana"
"sirius"
"hadar"
"procyon"
"alasia"
];
};
instances = {
borgbackup = {
module = {
name = "borgbackup";
input = "clan-core";
};
roles.client.machines."cursa".settings.destinations = {
alex = {
repo = "ssh://borg@10.0.10.225:2222/backup/cursa/backup";
rsh = "ssh -i /run/secrets/vars/borgbackup/borgbackup.ssh";
};
};
roles.client.machines."hadar".settings.destinations = {
alex = {
repo = "ssh://borg@10.0.10.225:2222/backup/hadar/backup";
rsh = "ssh -i /run/secrets/vars/borgbackup/borgbackup.ssh";
};
};
roles.client.machines."procyon".settings.destinations = {
alex = {
repo = "ssh://borg@10.0.10.225:2222/backup/procyon/backup";
rsh = "ssh -i /run/secrets/vars/borgbackup/borgbackup.ssh";
};
};
roles.client.machines."bosona".settings.destinations = {
alex = {
repo = "ssh://borg@10.0.10.225:2222/backup/bosona/backup";
rsh = "ssh -i /run/secrets/vars/borgbackup/borgbackup.ssh";
};
};
roles.client.machines."canopus".settings.destinations = {
alex = {
repo = "ssh://borg@10.0.10.225:2222/backup/canopus/backup";
rsh = "ssh -i /run/secrets/vars/borgbackup/borgbackup.ssh";
};
};
roles.client.machines."deneb".settings.destinations = {
alex = {
repo = "ssh://borg@10.0.10.225:2222/backup/deneb/backup";
rsh = "ssh -i /run/secrets/vars/borgbackup/borgbackup.ssh";
};
};
roles.client.machines."alasia".settings.destinations = {
alex = {
repo = "ssh://borg@10.0.10.225:2222/backup/alasia/backup";
rsh = "ssh -i /run/secrets/vars/borgbackup/borgbackup.ssh";
};
};
};
data-mesher = {
module = {
name = "data-mesher";
input = "clan-core";
};
roles.bootstrap.tags = [ "dm-bootstrapper" ];
roles.default.tags = [ "all" ];
roles.default.settings.interfaces = [ "ygg" ];
};
auto-pull-update = {
module = {
name = "dm-pull-deploy";
input = "clan-community";
};
roles.push.machines."rigel".settings = {
gitUrl = "https://git.b4l.co.th/newedge/infra.git";
branch = "main";
};
roles.push.extraModules = [
(
{ pkgs, config, ... }:
{
# work around until upstream is fixed
environment.systemPackages = [
(pkgs.writeShellApplication {
name = "custom-dm-send-deploy";
runtimeInputs = [
config.services.data-mesher.package
pkgs.git
pkgs.nix
pkgs.jq
];
text =
let
settings.gitUrl = "https://git.b4l.co.th/newedge/infra.git";
settings.branch = "main";
in
''
if [ $# -gt 1 ]; then
echo "Usage: dm-send-deploy [<flake-ref>]"
echo "Without arguments, sends the latest commit on '${settings.branch}' from ${settings.gitUrl}"
echo "Example: dm-send-deploy git+https://example.com/repo.git?rev=abc123..."
exit 1
fi
KEY="${config.clan.core.vars.generators.dm-pull-deploy-signing-key.files."signing.key".path}"
if [ ! -r "$KEY" ]; then
echo "Error: cannot read signing key at $KEY (are you root?)"
exit 1
fi
if [ $# -eq 1 ]; then
FLAKE_REF="$1"
else
REV=$(git ls-remote "${settings.gitUrl}" "refs/heads/${settings.branch}" | cut -f1)
if [ -z "$REV" ]; then
echo "Error: could not determine latest commit on ${settings.branch} from ${settings.gitUrl}"
exit 1
fi
FLAKE_REF="git+${settings.gitUrl}?rev=$REV"
fi
TMPFILE=$(mktemp)
trap 'rm -f "$TMPFILE"' EXIT
printf '%s' "$FLAKE_REF" > "$TMPFILE"
NETWORK_ID="${config.clan.core.vars.generators.data-mesher-network.files."network.pub".path}"
data-mesher file update "$TMPFILE" \
--url http://localhost:7331 \
--network-id "$NETWORK_ID" \
--key "$KEY" \
--name "dm_pull_deploy/target"
echo "Deployment target pushed: $FLAKE_REF"
'';
})
];
}
)
];
roles.default.tags = [ "all" ];
roles.default.settings.action = "switch";
};
sshd = {
roles.server.tags."all" = { };
roles.server.settings = {
authorizedKeys = {
"berwn" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAB/raxJR8gASmquP63weHelbi+da2WBJR1DgzHPNz/f";
"davhau" = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDuhpzDHBPvn8nv8RH1MRomDOaXyP4GziQm7r3MZ1Syk";
"vi" =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAmgyEGuY/r7SDlJgrzYmQqpcWS5W+fCzRi3OS59ne4W openpgp:0xFF687387";
"kurogeek" =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEcZ/p1Ofa9liwIzPWzNtONhJ7+FUWd2lCz33r81t8+w kurogeek@kurogeek";
"matthewcroughan" =
@@ -241,13 +102,7 @@
name = "zerotier";
input = "clan-core";
};
roles.controller.machines."vega" = {
settings.allowedIds = [
"dbe44c0287" # Alex-gateway
"b0e0b84fd3" # Alex
"2bd36db8cc" # kurogeek-thinkpad
];
};
roles.controller.machines."vega" = { };
roles.peer.tags.glom = { };
};
@@ -256,13 +111,7 @@
name = "zerotier";
input = "clan-core";
};
roles.controller.machines."rigel" = {
settings.allowedIds = [
"dbe44c0287" # Alex-gateway
"b0e0b84fd3" # Alex
"2bd36db8cc" # kurogeek-thinkpad
];
};
roles.controller.machines."rigel" = { };
roles.peer.tags.b4l = { };
};
@@ -280,24 +129,12 @@
roles.peer.tags."poy" = { };
};
internet = {
module.name = "internet";
roles.default.machines = {
ramus.settings.host = "5.223.63.55";
tangra.settings.host = "5.223.65.50";
};
};
yggdrasil-global-network = {
module = {
name = "yggdrasil";
input = "clan-core";
};
roles.default.tags."all" = { };
roles.default.settings.extraYggdrasilIPs = [
# kurogeek's laptop
"200:c8db:ea9b:5bdc:44ed:ad87:462a:6bd0"
];
roles.default.tags."global-network" = { };
roles.default.settings.extraPeers = [
"tls://ygg.jjolly.dev:3443"
"tls://[2602:fc24:18:7a42::1]:993"
@@ -323,6 +160,20 @@
};
};
yggdrasil-phone-network = {
module = {
name = "yggdrasil";
input = "clan-core";
};
roles.default.tags."phonebox" = { };
roles.default.settings.extraPeers = [
"tls://ygg.jjolly.dev:3443"
"tls://[2602:fc24:18:7a42::1]:993"
"tcp://leo.node.3dt.net:9002"
"tcp://ygg-kcmo.incognet.io:8883"
];
};
phonebox = {
module = {
name = "phonebox";
@@ -332,13 +183,6 @@
roles.default.machines."adhil".settings = {
ata-ethernet-iface = "end0";
};
roles.default.machines."rigel".settings = {
extraClientNumbers = [
"01"
"02"
];
extraFixedIPClient = { };
};
};
pulse-stream = {
@@ -433,65 +277,6 @@
dataDir = "/mnt/hdd/samba";
};
};
wordpress = {
module = {
name = "wordpress";
input = "self";
};
roles.server.machines."tangra".settings = {
tenants = [
"poyfestival.com"
];
phpfpmOptions = ''
upload_max_filesize=64M
post_max_size=128M
'';
wpExtraConfig = ''
define('WP_MEMORY_LIMIT', '256M');
define('WP_DEBUG', false);
define('WP_DEBUG_DISPLAY', false);
define('WP_DEBUG_LOG', false);
'';
};
};
prometheus-monitoring = {
module = {
name = "prometheus";
input = "self";
};
roles.server.machines."cursa".settings = {
matrix-alertmanager = {
enable = true;
homeserverUrl = "https://matrix-client.matrix.org";
matrixUser = "@nixapollo:matrix.org";
matrixRooms = [
{
receivers = [
"matrix"
];
roomId = "!rqIrWqPvsXqMgYpcNZ:matrix.org";
}
];
};
};
roles.nodes.machines = {
vega.settings = {
exporters.smartctl = { };
exporters.zfs = { };
};
rigel.settings = {
exporters.smartctl = { };
};
sirius.settings = {
exporters.smartctl = { };
exporters.zfs = { };
};
};
};
};
};
};
-6
View File
@@ -47,12 +47,6 @@
},
"bosona": {
"installedAt": 1779098893
},
"tangra": {
"installedAt": 1779958921
},
"cursa": {
"installedAt": 1782187627
}
}
}
+215 -64
View File
@@ -25,7 +25,10 @@
{
"index": 8,
"attached_to": 0,
"class_list": ["pci", "bridge"],
"class_list": [
"pci",
"bridge"
],
"bus_type": {
"hex": "0004",
"name": "PCI",
@@ -73,7 +76,10 @@
{
"index": 9,
"attached_to": 0,
"class_list": ["pci", "bridge"],
"class_list": [
"pci",
"bridge"
],
"bus_type": {
"hex": "0004",
"name": "PCI",
@@ -125,7 +131,10 @@
{
"index": 10,
"attached_to": 0,
"class_list": ["pci", "bridge"],
"class_list": [
"pci",
"bridge"
],
"bus_type": {
"hex": "0004",
"name": "PCI",
@@ -173,7 +182,10 @@
{
"index": 11,
"attached_to": 0,
"class_list": ["pci", "bridge"],
"class_list": [
"pci",
"bridge"
],
"bus_type": {
"hex": "0004",
"name": "PCI",
@@ -229,7 +241,10 @@
{
"index": 12,
"attached_to": 0,
"class_list": ["pci", "bridge"],
"class_list": [
"pci",
"bridge"
],
"bus_type": {
"hex": "0004",
"name": "PCI",
@@ -282,14 +297,21 @@
},
"driver": "piix4_smbus",
"driver_module": "i2c_piix4",
"drivers": ["piix4_smbus"],
"driver_modules": ["i2c_piix4"],
"drivers": [
"piix4_smbus"
],
"driver_modules": [
"i2c_piix4"
],
"module_alias": "pci:v00008086d00007113sv00001AF4sd00001100bc06sc80i00"
},
{
"index": 17,
"attached_to": 0,
"class_list": ["pci", "bridge"],
"class_list": [
"pci",
"bridge"
],
"bus_type": {
"hex": "0004",
"name": "PCI",
@@ -339,7 +361,11 @@
{
"index": 22,
"attached_to": 15,
"class_list": ["cdrom", "scsi", "block_device"],
"class_list": [
"cdrom",
"scsi",
"block_device"
],
"bus_type": {
"hex": "0084",
"name": "SCSI",
@@ -396,8 +422,14 @@
"unix_device_name2": "/dev/sg1",
"driver": "ata_piix",
"driver_module": "ata_piix",
"drivers": ["ata_piix", "sr"],
"driver_modules": ["ata_piix", "sr_mod"]
"drivers": [
"ata_piix",
"sr"
],
"driver_modules": [
"ata_piix",
"sr_mod"
]
}
],
"cpu": [
@@ -464,7 +496,9 @@
"spectre_v2_user",
"its"
],
"power_management": [""],
"power_management": [
""
],
"bogo": 4224,
"cache": 16384,
"page_size": 4096,
@@ -546,7 +580,9 @@
"spectre_v2_user",
"its"
],
"power_management": [""],
"power_management": [
""
],
"bogo": 4224,
"cache": 16384,
"page_size": 4096,
@@ -570,7 +606,11 @@
{
"index": 23,
"attached_to": 19,
"class_list": ["disk", "scsi", "block_device"],
"class_list": [
"disk",
"scsi",
"block_device"
],
"bus_type": {
"hex": "0084",
"name": "SCSI",
@@ -634,15 +674,24 @@
],
"driver": "virtio_scsi",
"driver_module": "virtio_scsi",
"drivers": ["sd", "virtio_scsi"],
"driver_modules": ["sd_mod", "virtio_scsi"]
"drivers": [
"sd",
"virtio_scsi"
],
"driver_modules": [
"sd_mod",
"virtio_scsi"
]
}
],
"graphics_card": [
{
"index": 16,
"attached_to": 0,
"class_list": ["graphics_card", "pci"],
"class_list": [
"graphics_card",
"pci"
],
"bus_type": {
"hex": "0004",
"name": "PCI",
@@ -699,8 +748,12 @@
},
"driver": "bochs-drm",
"driver_module": "bochs",
"drivers": ["bochs-drm"],
"driver_modules": ["bochs"],
"drivers": [
"bochs-drm"
],
"driver_modules": [
"bochs"
],
"module_alias": "pci:v00001234d00001111sv00001AF4sd00001100bc03sc00i00"
}
],
@@ -708,7 +761,10 @@
{
"index": 24,
"attached_to": 7,
"class_list": ["usb", "hub"],
"class_list": [
"usb",
"hub"
],
"bus_type": {
"hex": "0086",
"name": "USB",
@@ -781,8 +837,12 @@
"hotplug": "usb",
"driver": "hub",
"driver_module": "usbcore",
"drivers": ["hub"],
"driver_modules": ["usbcore"],
"drivers": [
"hub"
],
"driver_modules": [
"usbcore"
],
"module_alias": "usb:v1D6Bp0001d0618dc09dsc00dp00ic09isc00ip00in00"
}
],
@@ -790,7 +850,9 @@
{
"index": 5,
"attached_to": 0,
"class_list": ["memory"],
"class_list": [
"memory"
],
"base_class": {
"hex": "0101",
"name": "Internally Used Class",
@@ -814,7 +876,9 @@
{
"index": 21,
"attached_to": 16,
"class_list": ["monitor"],
"class_list": [
"monitor"
],
"base_class": {
"hex": "0100",
"name": "Monitor",
@@ -960,7 +1024,10 @@
{
"index": 25,
"attached_to": 24,
"class_list": ["mouse", "usb"],
"class_list": [
"mouse",
"usb"
],
"bus_type": {
"hex": "0086",
"name": "USB",
@@ -996,7 +1063,9 @@
"model": "QEMU USB Tablet",
"sysfs_id": "/devices/pci0000:00/0000:00:01.2/usb1/1-1/1-1:1.0",
"sysfs_bus_id": "1-1:1.0",
"unix_device_names": ["/dev/input/mice"],
"unix_device_names": [
"/dev/input/mice"
],
"unix_device_name2": "/dev/input/mouse0",
"resources": [
{
@@ -1037,11 +1106,18 @@
"hotplug": "usb",
"driver": "usbhid",
"driver_module": "usbhid",
"drivers": ["usbhid"],
"driver_modules": ["usbhid"],
"drivers": [
"usbhid"
],
"driver_modules": [
"usbhid"
],
"driver_info": {
"type": "mouse",
"db_entry_0": ["explorerps/2", "exps2"],
"db_entry_0": [
"explorerps/2",
"exps2"
],
"xf86": "explorerps/2",
"gpm": "exps2",
"buttons": -1,
@@ -1054,7 +1130,9 @@
{
"index": 18,
"attached_to": 13,
"class_list": ["network_controller"],
"class_list": [
"network_controller"
],
"bus_type": {
"hex": "008f",
"name": "Virtio",
@@ -1079,7 +1157,9 @@
"model": "Virtio Ethernet Card 0",
"sysfs_id": "/devices/pci0000:00/0000:00:12.0/virtio1",
"sysfs_bus_id": "virtio1",
"unix_device_names": ["ens18"],
"unix_device_names": [
"ens18"
],
"resources": [
{
"type": "hwaddr",
@@ -1092,8 +1172,12 @@
],
"driver": "virtio_net",
"driver_module": "virtio_net",
"drivers": ["virtio_net"],
"driver_modules": ["virtio_net"],
"drivers": [
"virtio_net"
],
"driver_modules": [
"virtio_net"
],
"module_alias": "virtio:d00000001v00001AF4"
}
],
@@ -1101,7 +1185,9 @@
{
"index": 26,
"attached_to": 18,
"class_list": ["network_interface"],
"class_list": [
"network_interface"
],
"base_class": {
"hex": "0107",
"name": "Network Interface",
@@ -1115,7 +1201,9 @@
"model": "Ethernet network interface",
"sysfs_id": "/class/net/ens18",
"sysfs_device_link": "/devices/pci0000:00/0000:00:12.0/virtio1",
"unix_device_names": ["ens18"],
"unix_device_names": [
"ens18"
],
"resources": [
{
"type": "hwaddr",
@@ -1128,13 +1216,19 @@
],
"driver": "virtio_net",
"driver_module": "virtio_net",
"drivers": ["virtio_net"],
"driver_modules": ["virtio_net"]
"drivers": [
"virtio_net"
],
"driver_modules": [
"virtio_net"
]
},
{
"index": 27,
"attached_to": 0,
"class_list": ["network_interface"],
"class_list": [
"network_interface"
],
"base_class": {
"hex": "0107",
"name": "Network Interface",
@@ -1147,14 +1241,19 @@
},
"model": "Loopback network interface",
"sysfs_id": "/class/net/lo",
"unix_device_names": ["lo"]
"unix_device_names": [
"lo"
]
}
],
"pci": [
{
"index": 13,
"attached_to": 0,
"class_list": ["pci", "unknown"],
"class_list": [
"pci",
"unknown"
],
"bus_type": {
"hex": "0004",
"name": "PCI",
@@ -1211,14 +1310,21 @@
},
"driver": "virtio-pci",
"driver_module": "virtio_pci",
"drivers": ["virtio-pci"],
"driver_modules": ["virtio_pci"],
"drivers": [
"virtio-pci"
],
"driver_modules": [
"virtio_pci"
],
"module_alias": "pci:v00001AF4d00001000sv00001AF4sd00000001bc02sc00i00"
},
{
"index": 14,
"attached_to": 0,
"class_list": ["pci", "unknown"],
"class_list": [
"pci",
"unknown"
],
"bus_type": {
"hex": "0004",
"name": "PCI",
@@ -1274,8 +1380,12 @@
},
"driver": "virtio-pci",
"driver_module": "virtio_pci",
"drivers": ["virtio-pci"],
"driver_modules": ["virtio_pci"],
"drivers": [
"virtio-pci"
],
"driver_modules": [
"virtio_pci"
],
"module_alias": "pci:v00001AF4d00001002sv00001AF4sd00000005bc00scFFi00"
}
],
@@ -1283,7 +1393,10 @@
{
"index": 6,
"attached_to": 17,
"class_list": ["storage_controller", "pci"],
"class_list": [
"storage_controller",
"pci"
],
"bus_type": {
"hex": "0004",
"name": "PCI",
@@ -1340,14 +1453,21 @@
},
"driver": "virtio-pci",
"driver_module": "virtio_pci",
"drivers": ["virtio-pci"],
"driver_modules": ["virtio_pci"],
"drivers": [
"virtio-pci"
],
"driver_modules": [
"virtio_pci"
],
"module_alias": "pci:v00001AF4d00001004sv00001AF4sd00000008bc01sc00i00"
},
{
"index": 15,
"attached_to": 0,
"class_list": ["storage_controller", "pci"],
"class_list": [
"storage_controller",
"pci"
],
"bus_type": {
"hex": "0004",
"name": "PCI",
@@ -1437,8 +1557,12 @@
},
"driver": "ata_piix",
"driver_module": "ata_piix",
"drivers": ["ata_piix"],
"driver_modules": ["ata_piix"],
"drivers": [
"ata_piix"
],
"driver_modules": [
"ata_piix"
],
"module_alias": "pci:v00008086d00007010sv00001AF4sd00001100bc01sc01i80"
}
],
@@ -1449,7 +1573,9 @@
{
"index": 19,
"attached_to": 6,
"class_list": ["unknown"],
"class_list": [
"unknown"
],
"base_class": {
"hex": "0000",
"name": "Unclassified device",
@@ -1467,14 +1593,20 @@
"sysfs_bus_id": "virtio2",
"driver": "virtio_scsi",
"driver_module": "virtio_scsi",
"drivers": ["virtio_scsi"],
"driver_modules": ["virtio_scsi"],
"drivers": [
"virtio_scsi"
],
"driver_modules": [
"virtio_scsi"
],
"module_alias": "virtio:d00000008v00001AF4"
},
{
"index": 20,
"attached_to": 14,
"class_list": ["unknown"],
"class_list": [
"unknown"
],
"base_class": {
"hex": "0000",
"name": "Unclassified device",
@@ -1492,8 +1624,12 @@
"sysfs_bus_id": "virtio0",
"driver": "virtio_balloon",
"driver_module": "virtio_balloon",
"drivers": ["virtio_balloon"],
"driver_modules": ["virtio_balloon"],
"drivers": [
"virtio_balloon"
],
"driver_modules": [
"virtio_balloon"
],
"module_alias": "virtio:d00000005v00001AF4"
}
],
@@ -1501,7 +1637,10 @@
{
"index": 7,
"attached_to": 0,
"class_list": ["usb_controller", "pci"],
"class_list": [
"usb_controller",
"pci"
],
"bus_type": {
"hex": "0004",
"name": "PCI",
@@ -1568,15 +1707,25 @@
},
"driver": "uhci_hcd",
"driver_module": "uhci_hcd",
"drivers": ["uhci_hcd"],
"driver_modules": ["uhci_hcd"],
"drivers": [
"uhci_hcd"
],
"driver_modules": [
"uhci_hcd"
],
"driver_info": {
"type": "module",
"db_entry_0": ["uhci-hcd"],
"db_entry_0": [
"uhci-hcd"
],
"active": true,
"modprobe": true,
"names": ["uhci-hcd"],
"module_args": [""],
"names": [
"uhci-hcd"
],
"module_args": [
""
],
"conf": ""
},
"module_alias": "pci:v00008086d00007020sv00001AF4sd00001100bc0Csc03i00"
@@ -1689,7 +1838,9 @@
"name": "RAM",
"value": 7
},
"memory_type_details": ["Other"],
"memory_type_details": [
"Other"
],
"speed": 0
}
],
+1 -1
View File
@@ -50,7 +50,7 @@ in
];
sites = {
"${sitename}" = {
domains = [ sitename ];
domains = [ "localhost" ];
apps = [
"frappe"
"erpnext"
-14
View File
@@ -1,14 +0,0 @@
{
...
}:
{
clan.core.settings.machine.description =
"VM machine for collecting prometheus metrics and fire alerts";
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
system.stateVersion = "25.11";
clan.core.sops.defaultGroups = [ "admins" ];
}
-85
View File
@@ -1,85 +0,0 @@
let
hashDisk = disk: "os-${builtins.substring 0 5 (builtins.hashString "sha256" disk)}";
os = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi0";
in
{
boot.loader = {
systemd-boot = {
enable = true;
};
efi = {
canTouchEfiVariables = true;
};
};
boot.zfs.forceImportRoot = true;
disko.devices = {
disk = {
"os-${hashDisk os}" = {
type = "disk";
device = os;
content = {
type = "gpt";
partitions = {
ESP = {
size = "1G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "nofail" ];
};
};
system = {
size = "100%";
content = {
type = "zfs";
pool = "zroot";
};
};
};
};
};
};
zpool = {
zroot = {
type = "zpool";
rootFsOptions = {
mountpoint = "none";
compression = "lz4";
acltype = "posixacl";
xattr = "sa";
"com.sun:auto-snapshot" = "true";
};
options.ashift = "12";
datasets = {
"root" = {
type = "zfs_fs";
options.mountpoint = "none";
};
"root/nixos" = {
type = "zfs_fs";
options.mountpoint = "/";
mountpoint = "/";
};
"root/home" = {
type = "zfs_fs";
options.mountpoint = "/home";
mountpoint = "/home";
};
"root/tmp" = {
type = "zfs_fs";
mountpoint = "/tmp";
options = {
mountpoint = "/tmp";
sync = "disabled";
};
};
};
};
};
};
}
File diff suppressed because it is too large Load Diff
+1 -9
View File
@@ -9,15 +9,7 @@
];
clan = {
meta.name = "NewEdgeClan";
machines = {
cursa = { ... }: { clan.core.state."vars".folders = [ "/var/lib" ]; };
hadar = { ... }: { clan.core.state."vars".folders = [ "/var/lib" ]; };
procyon = { ... }: { clan.core.state."vars".folders = [ "/var/lib" ]; };
bosona = { ... }: { clan.core.state."vars".folders = [ "/var/lib" ]; };
canopus = { ... }: { clan.core.state."vars".folders = [ "/var/lib" ]; };
deneb = { ... }: { clan.core.state."vars".folders = [ "/var/lib" ]; };
alasia = { ... }: { clan.core.state."vars".folders = [ "/var/lib" ]; };
};
machines = { };
secrets.age.plugins = [
"age-plugin-yubikey"
"age-plugin-fido2-hmac"
-2
View File
@@ -56,7 +56,6 @@ in
pkgs.frappix.erpnext
pkgs.frappix.hrms
pkgs.frappix.crm
pkgs.frappix.posprinter
];
sites = {
"${sitename}" = {
@@ -66,7 +65,6 @@ in
"erpnext"
"hrms"
"crm"
"posprinter"
];
};
};
+17 -3
View File
@@ -9,6 +9,13 @@ let
in
{
clan.core.settings.machine.description = "VM machine that host Inventree system for Poy";
imports = [
inputs.self.nixosModules.inventree
];
nixpkgs.overlays = [
inputs.self.overlays.packagesOverlay
];
nixpkgs.hostPlatform = {
system = "x86_64-linux";
@@ -75,12 +82,19 @@ in
services.inventree = {
enable = true;
inherit domain;
hostName = "${domain}";
config.site_url = "https://${config.services.inventree.hostName}";
secretKeyFile = config.clan.core.vars.generators.inventree.files.secret-key.path;
adminPasswordFile = config.clan.core.vars.generators.inventree.files.admin-password.path;
settings.INVENTREE_SITE_URL = "https://${domain}";
config.oidc_private_key_file = config.clan.core.vars.generators.inventree.files.oidc-key.path;
config.adminPasswordFile = config.clan.core.vars.generators.inventree.files.admin-password.path;
};
# services.nginx.virtualHosts."${domain}" = {
# forceSSL = true;
# sslCertificate = config.clan.core.vars.generators.nginx.files.sslCert.path;
# sslCertificateKey = config.clan.core.vars.generators.nginx.files.sslKey.path;
# };
system.stateVersion = "25.11";
clan.core.sops.defaultGroups = [ "admins" ];
}
+1
View File
@@ -10,6 +10,7 @@
};
system.stateVersion = "25.11";
clan.core.sops.defaultGroups = [ "admins" ];
clan.core.networking.targetHost = "root@[${config.clan.core.vars.generators.zerotier.files.zerotier-ip.value}]";
networking.interfaces.enx00e04c106368.useDHCP = true; # recovery
+17 -3
View File
@@ -9,6 +9,13 @@ let
in
{
clan.core.settings.machine.description = "VM machine that host Inventree system for Glom";
imports = [
inputs.self.nixosModules.inventree
];
nixpkgs.overlays = [
inputs.self.overlays.packagesOverlay
];
nixpkgs.hostPlatform = {
system = "x86_64-linux";
@@ -75,12 +82,19 @@ in
services.inventree = {
enable = true;
inherit domain;
hostName = "${domain}";
config.site_url = "https://${config.services.inventree.hostName}";
secretKeyFile = config.clan.core.vars.generators.inventree.files.secret-key.path;
adminPasswordFile = config.clan.core.vars.generators.inventree.files.admin-password.path;
settings.INVENTREE_SITE_URL = "https://${domain}";
config.oidc_private_key_file = config.clan.core.vars.generators.inventree.files.oidc-key.path;
config.adminPasswordFile = config.clan.core.vars.generators.inventree.files.admin-password.path;
};
# services.nginx.virtualHosts."${domain}" = {
# forceSSL = true;
# sslCertificate = config.clan.core.vars.generators.nginx.files.sslCert.path;
# sslCertificateKey = config.clan.core.vars.generators.nginx.files.sslKey.path;
# };
system.stateVersion = "25.11";
clan.core.sops.defaultGroups = [ "admins" ];
}
+1
View File
@@ -9,6 +9,7 @@
clan.core.settings.machine.description = "A Hetzner VPS machine own by Alex.";
clan.core.sops.defaultGroups = [ "admins" ];
clan.core.networking.targetHost = "root@[${config.clan.core.vars.generators.zerotier.files.zerotier-ip.value}]";
clan.core.vars.generators.acme = {
share = true;
+11
View File
@@ -1,7 +1,18 @@
{ config, ... }:
{
imports = [
(import ../../lib/auto-accept-zerotier-members.nix {
memberIds = [
"dbe44c0287" # Alex-gateway
"b0e0b84fd3" # Alex
"2bd36db8cc" # kurogeek-thinkpad
];
})
];
system.stateVersion = "25.11";
clan.core.sops.defaultGroups = [ "admins" ];
clan.core.networking.targetHost = "root@[${config.clan.core.vars.generators.zerotier.files.zerotier-ip.value}]";
clan.core.settings.machine.description = "Zima board computer for testing in B4L";
}
-32
View File
@@ -1,32 +0,0 @@
{
system.stateVersion = "25.11";
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
clan.core.settings.name = "tangra";
clan.core.settings.machine.description =
"A Hetzner VPS machine own by Alex. This is a machine for poyfestival.com";
clan.core.sops.defaultGroups = [ "admins" ];
clan.core.vars.generators.acme = {
share = true;
files.email.secret = false;
prompts.email = {
type = "line";
description = "Email for ACME registeration";
};
script = ''
cat $prompts/email > $out/email
'';
};
users.users.nginx.extraGroups = [ "acme" ];
security.acme.acceptTerms = true;
imports = [ ];
}
-86
View File
@@ -1,86 +0,0 @@
{ ... }:
let
hashDisk = disk: "os-${builtins.substring 0 5 (builtins.hashString "sha256" disk)}";
os = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_119349241";
in
{
boot.loader = {
systemd-boot = {
enable = true;
};
efi = {
canTouchEfiVariables = true;
};
};
boot.zfs.forceImportRoot = true;
disko.devices = {
disk = {
"os-${hashDisk os}" = {
type = "disk";
device = os;
content = {
type = "gpt";
partitions = {
ESP = {
size = "1G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "nofail" ];
};
};
system = {
size = "100%";
content = {
type = "zfs";
pool = "zroot";
};
};
};
};
};
};
zpool = {
zroot = {
type = "zpool";
rootFsOptions = {
mountpoint = "none";
compression = "lz4";
acltype = "posixacl";
xattr = "sa";
"com.sun:auto-snapshot" = "true";
};
options.ashift = "12";
datasets = {
"root" = {
type = "zfs_fs";
options.mountpoint = "none";
};
"root/nixos" = {
type = "zfs_fs";
options.mountpoint = "/";
mountpoint = "/";
};
"root/home" = {
type = "zfs_fs";
options.mountpoint = "/home";
mountpoint = "/home";
};
"root/tmp" = {
type = "zfs_fs";
mountpoint = "/tmp";
options = {
mountpoint = "/tmp";
sync = "disabled";
};
};
};
};
};
};
}
File diff suppressed because it is too large Load Diff
+8
View File
@@ -10,9 +10,17 @@
(inputs.import-tree ./services)
(import ../../lib/auto-accept-zerotier-members.nix {
memberIds = [
"dbe44c0287" # Alex-gateway
"b0e0b84fd3" # Alex
"2bd36db8cc" # kurogeek-thinkpad
];
})
];
clan.core.sops.defaultGroups = [ "admins" ];
clan.core.networking.targetHost = "root@[${config.clan.core.vars.generators.zerotier.files.zerotier-ip.value}]";
clan.core.settings.machine.description = "Glom NAS";
-4
View File
@@ -1,4 +0,0 @@
# Apple Network
This service allows atalkd instances to connect to each other over vxlan over Yggdrasil. We need to use vxlan due to the support of broadcasting it provides. The service will form a network of star-topology vxlan using the underlying Yggdrasil network. With this vxlan network, we can have a private Apple Talk network over the internet.
-139
View File
@@ -1,139 +0,0 @@
{ clanLib, ... }:
{
_class = "clan.service";
manifest.name = "apple-network";
manifest.description = "This service will create an instance of `atalkd` for each peer to talk to Apple machines over Apple Talk protocol and automatically connect each peer using vxlan over Yggdrasil network to achieve Apple Talk over internet experience";
manifest.readme = builtins.readFile ./README.md;
manifest.categories = [ "Network" ];
roles.peer = {
description = "A gateway machine that allow classic Apple machines to connect to other Apple machines over the internet";
interface =
{ lib, ... }:
{
options = {
zone_name = lib.mkOption {
type = with lib.types; str;
description = "Zone name for Apple Talk protocol";
default = "Default";
};
};
};
perInstance =
{ roles, settings, ... }:
{
nixosModule =
{
lib,
config,
pkgs,
...
}:
let
vxlanPort = 4789;
getYggdrasilIP =
machineName:
if config.clan.core.vars.generators.yggdrasil.files.address ? value then
clanLib.getPublicValue {
flake = config.clan.core.settings.directory;
machine = machineName;
generator = "yggdrasil";
file = "address";
default = null;
}
else
throw "clanService/yggdrasil is required";
noSelfPeers = builtins.filter (peerName: peerName != config.clan.core.settings.machine.name) (
lib.mapAttrsToList (machineName: _: machineName) roles.peer.machines
);
sortedPeers = builtins.sort (x: y: x < y) (
lib.mapAttrsToList (machineName: _: machineName) roles.peer.machines
);
getMachineIndex = machineName: lib.lists.findFirstIndex (x: x == machineName) null sortedPeers;
selfVXAddress = "192.168.254.${
lib.toString ((getMachineIndex config.clan.core.settings.machine.name) + 1)
}/24";
in
{
services.atalkd = {
enable = true;
interfaces = {
vxlan.config = ''
-router -phase 2 -net 1 -zone "${settings.zone_name}"
'';
};
};
networking.useNetworkd = true;
networking.firewall.interfaces."ygg".allowedUDPPorts = [ vxlanPort ];
boot.kernelModules = [ "vxlan" ];
systemd.network.netdevs =
builtins.listToAttrs (
map (
peerName:
(lib.nameValuePair "10-apl-vxlan-${peerName}" {
enable = true;
netdevConfig = {
Name = "vxlan-${peerName}";
Kind = "vxlan";
};
vxlanConfig = {
VNI = (getMachineIndex config.clan.core.settings.machine.name) + (getMachineIndex peerName);
Remote = getYggdrasilIP peerName;
DestinationPort = vxlanPort;
Independent = true;
};
})
) noSelfPeers
)
// {
"10-apl-vxlan" = {
enable = true;
netdevConfig = {
Kind = "bridge";
Name = "vxlan";
};
bridgeConfig = {
STP = true;
};
};
};
systemd.network.networks =
builtins.listToAttrs (
map (
peerName:
(lib.nameValuePair "10-apl-vxlan-${peerName}" {
enable = true;
matchConfig.Name = "vxlan-${peerName}";
networkConfig.Bridge = "vxlan";
})
) noSelfPeers
)
// {
"10-apl-vxlan" = {
enable = true;
matchConfig.Name = "vxlan";
address = [ selfVXAddress ];
};
};
environment.systemPackages = [
pkgs.netatalk
pkgs.bridge-utils
];
};
};
};
}
@@ -1,19 +0,0 @@
{ inputs, self, ... }:
let
module = ./default.nix;
in
{
clan.modules = {
apple-network = module;
};
perSystem =
{ ... }:
{
clan.nixosTests.service-apple-network = {
imports = [ ./tests/vm/default.nix ];
_module.args = { inherit self inputs; };
clan.modules."@clan/apple-network" = module;
};
};
}
@@ -1,76 +0,0 @@
{
self,
lib,
config,
hostPkgs,
...
}:
{
name = "service-apple-network";
result.update-vars =
let
relativeDir = lib.removePrefix "${self}/" (toString config.clan.directory);
in
hostPkgs.writeShellScriptBin "update-vars" ''
set -x
export PRJ_ROOT=$(git rev-parse --show-toplevel)
${
self.inputs.clan-core.packages.${hostPkgs.system}.clan-cli
}/bin/clan-generate-test-vars $PRJ_ROOT/${relativeDir} ${config.name}
'';
clan = {
directory = ./.;
test.useContainers = false;
inventory = {
meta.domain = "test.clan";
machines.peer1 = { };
machines.peer2 = { };
machines.peer3 = { };
instances = {
apple-network = {
module.name = "@clan/apple-network";
module.input = "self";
roles.peer.machines = {
peer1 = { };
peer2 = { };
peer3 = { };
};
};
yggdrasil = {
module.name = "yggdrasil";
roles.default.tags.all = { };
roles.default.settings.extraPeers = [
"tls://ygg.jjolly.dev:3443"
"tls://[2602:fc24:18:7a42::1]:993"
"tcp://leo.node.3dt.net:9002"
"tcp://ygg-kcmo.incognet.io:8883"
];
};
};
};
};
nodes = {
peer1 = { };
peer2 = { };
peer3 = { };
};
testScript = _: ''
# cannot test connectivity due to Yggdrasil's establishment
start_all()
peer1.wait_for_unit("atalkd")
peer1.succeed("systemctl status atalkd")
peer2.wait_for_unit("atalkd")
peer2.succeed("systemctl status atalkd")
peer3.wait_for_unit("atalkd")
peer3.succeed("systemctl status atalkd")
'';
}
@@ -1,6 +0,0 @@
[
{
"publickey": "age1f92zl8y70z5w9gn0l5leg2fhyvxy6m93dfh7n6ltgvuu9nyg6epsrw6t8x",
"type": "age"
}
]
@@ -1,6 +0,0 @@
[
{
"publickey": "age1u36fr87cru90vfznf5szasya9nhvvseh4atk8zsdj0rrsu0nnvwqsyt8g6",
"type": "age"
}
]
@@ -1,6 +0,0 @@
[
{
"publickey": "age1rka3368ltqc787xw99uu762lqfk7qxld9265u2t62fpxnp9xhufsc2q5rw",
"type": "age"
}
]
@@ -1,14 +0,0 @@
{
"data": "ENC[AES256_GCM,data:hC4Lle6mXuTFq//wBHUTyH3X778u/gYJSXJOiQ7xUb+gnC8beH1olxL2ZhtUiMkktzhsPM/j6cxhltPp25UTeJnUOcoYesqZcp8=,iv:WOx2P2Cu4v58xM9ePjAw1gdA0fFnGG2UqEXH2iksGoo=,tag:43n1ibVSy2AeS9f5qQBKNQ==,type:str]",
"sops": {
"age": [
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtT244N1Q3Zk9pRjFFQlUr\ncDExSTBwSWk5UXVyMjhWclQwSFZaYnpTRFY0CnE5YStVdzMrS3BKYzYvc3V3QVFY\nbDVwVytoNERveU1xQllqNUFGV2hYbGMKLS0tIDJSUmkwMUQzL3Y0MU5qZTJ3eFN3\nNGdwamM1UDBPdzhvSWsyZzR6anZ0eFEKKnr1/7rf3fH1i7KUoZdilLDgb44K2qzn\nI9Y+7FbV4gzQUzKWjAQeFN37Z4Qiuy0xJVA0lw8KvM+NCxSZDfh3kw==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
}
],
"lastmodified": "2026-07-03T10:46:56Z",
"mac": "ENC[AES256_GCM,data:hmpbOtra6EyNiPg7EsA3F4elHEO87JPUr4VKVppvzUwLX1HSj67WrU6k3rEoJT+k7Hq1lxnAzDEckSG1fUOap11rk8ksp1IAGR0+yqykC/Qj/Nl8wXqP84gr49bJK6xE/DDdCRCcBff2d6IpnehyEr8fGFEZbWGygblec8U8GPo=,iv:+M1C3rL22foowr0VD80jwrNFb5xz4k5JQ/DJm4ThKHk=,tag:wabFAC5NTCVGfIQQzm0yGg==,type:str]",
"version": "3.13.1"
}
}
@@ -1 +0,0 @@
../../../users/admin
@@ -1,14 +0,0 @@
{
"data": "ENC[AES256_GCM,data:ndWIEOqP2ybCN7Ak5g+8q3YG5rLQ7OuSv/vCbnMA8AK6Lby2JMGRkRGysqJdyEF7eh4w7PpZ/AtKPtPbUucjeTB5+8g76PPJTBE=,iv:EYy0GGqEBmIc5rSWP7Zleb5eQ0JzTz84HqeJPpCSpxk=,tag:iMgTUb9+wxE9S2kKoOEvsQ==,type:str]",
"sops": {
"age": [
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQTEF6OXN4K0dHdXhWWmt2\neG5wdkNIc2F0UnFEeHFLQkdTWkFpUWhTa0NBCmw2N2J1T0FJVE9JR3VBRWV0THh5\nVEZlbVZrcXAwK3BsYXFOZUF6c3lRSkUKLS0tIFRCQzNUaGFHdERWNWR4enVWRGpx\nbDEzRU9jWHgxWHovaENjbkFlZERIbkkKvAW31gTJg9izrWuAMeDHS9SWPQYtxRBY\necDCn8QORFrnDdxEusCnGJrAU4kmS3Y3CwSHCtEijs3JdIgg9wl/MA==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
}
],
"lastmodified": "2026-07-03T10:47:04Z",
"mac": "ENC[AES256_GCM,data:y1U2vsdqR97fPAnp6iZiLY1KbWYmgDqgZ5bwIkWPCr7Gjjrn+qV+sc2T1BTVz3Zo0JOz4ScCc+f6snVsFKdCDU/NmDVFt/sqyH4NHUPRQ3StsQim8C7IkSwUtm3EhrqpLYFD21MEjrYYdHMHbWybxrOI0qI6mDwZymHJFeCLdQA=,iv:lVvPn69eQE/huwDmwePepfpi2l9ZOPQO7W20o4AJBFQ=,tag:7VPfjKZsBVJTZxNwTcI6sg==,type:str]",
"version": "3.13.1"
}
}
@@ -1 +0,0 @@
../../../users/admin
@@ -1,14 +0,0 @@
{
"data": "ENC[AES256_GCM,data:JPdetkhtF9eSmgEfCO2exXlGQ5KWLeIM3mnW5BfyTY8r0PxWSEGAwBskC1SiDdRERWB2VEbPiPgCNXMnGaYlDqSdZN6R9wSFvsQ=,iv:qGveNhUtgxvKnmdsPoPpffKyi5srlq0Pd6aW283B5C0=,tag:TcJsCrBlzfjXvztcRaxYFQ==,type:str]",
"sops": {
"age": [
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvdjNHa1RlcFJHazB5TXFu\nOUQ4REpCZm5Yc3ZhcVhwT1FqRHlvbnoxZWlFCnNrVUEyK2ZYSmlacmJ2b2QrclZl\nSDV1eWxXVmJxZlhMMXgrTWtjcjVhQlkKLS0tIHZPN3pCUVBLQmpRVGx6SDBQNDZo\nSitheGhXNGl5QW9HTGNsTTdTdWVwaE0KfuM5xZOPbR1lxkJPJUOVrtlW5Ujobemp\nid40reDqxKQxP3khJv8lf9ZoN8LAx2Iwh0DeAl+UJpsoVWgS7uI2qQ==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
}
],
"lastmodified": "2026-07-07T04:54:10Z",
"mac": "ENC[AES256_GCM,data:Tt8yqzfAnSDe2n7KDt1Z/D73hkS1w7DsqIh+s5WljLzar9PEt5vUCLb8DIvBwITyzGAoHH1ym3v3NrnJWCdxajKExTMBf4aY3MJCtykeCG37701S/KxumjTW9/fJw74gcET5I6NafTWb6H5XHsrRaQX1Xnspcs8B7uLGZZ28dSM=,iv:Fo5UPVhnjuOx6Cp4grofHOiD2pm0TXuRRuoTwvxKn1s=,tag:VQ/TF1TiyJADj7/3RwPCAg==,type:str]",
"version": "3.13.1"
}
}
@@ -1 +0,0 @@
../../../users/admin
@@ -1,4 +0,0 @@
{
"publickey": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"type": "age"
}
@@ -1 +0,0 @@
200:e6cc:c86:f02d:b0d5:fba9:9b2c:eb77
@@ -1 +0,0 @@
../../../../../../sops/machines/peer1
@@ -1,18 +0,0 @@
{
"data": "ENC[AES256_GCM,data:6YDp5S2TzEnhDgGhcz8cA3uBsfDt0Oc4JpztB1JUcg/+tDBbeaQN4MLxuZKstXn2Hb1mYtBLlX0vHw++T181Js2sIznyfC1lr68GOvQAp4NYgf23dXpdZk/CMPNUMiGOYVwKWQ/Z0/p0azJ6xV29dYQcM4Q9hys=,iv:Ijzz8hm0looCWoSpjg/rYKp9jhvzRuLboKWHrlwVeFA=,tag:kJcH/1Pu+9q9f2J68LETug==,type:str]",
"sops": {
"age": [
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYNDNEL3kvdEpEMjYyOFJG\nMk5adU04M3hxa21jTTZNM2dQREpmUlVES1NvCjh6eDNFZ1hzUVlTY3Nidnp3TkYr\nRVl4TFlrNUE3dVIzZzg2VWMwTFBYUXMKLS0tIFE0dVFQQmxwOFJ6YkdaQlh6dUlW\nTi8rdXdQbGR1eXpLcTdOandqQmxka3cKImbmJQo2YMYMSQD8kNTgol3VJ4YGIaoz\nl3AY4u/fobg5qlzVQwV33G0/Wf72Z2aTjSLnP4thnasQ89PdYvs7hA==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1f92zl8y70z5w9gn0l5leg2fhyvxy6m93dfh7n6ltgvuu9nyg6epsrw6t8x"
},
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiaWw5SU9KWmJnVVVmTVpr\nL1V6RnRYUGg2UnhXR1BnVTh5eFhnNFpidGdjCmdMeU1nZkZmTTVwbkNaVElFa0Z4\nVkdGdjc4c2lPWGNrVGxocE9iQUZ3QTAKLS0tIHIzTzRRbXVkM3I4ZVRxeSs5eHV5\nTUxOaytzb2MxQ2UybkVCYWVWVmVEcUEKPeK+CC7r3CP5BJqg9thWNHWjPBp/ueHU\nRif6T79kqf+c3B34qXwR0zfyM1+a0r9GAVVC2/q+Ha/As5sPJU39ww==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
}
],
"lastmodified": "2026-07-03T10:46:56Z",
"mac": "ENC[AES256_GCM,data:PffiPU1GR9DojTb7TxzBkpivKV2ybmmq9h4pOOyq7p5BAIPF+JSe+BDtbItQ+Gn5LnitQRUVvhat8E2iYfz3JgNxNKcsNFU/mWtCz3PlqyiuRzUBtEL3zYfhdMi8hYYlVdfMumaK3VMk+b4uDGExR+MpURL97TFku47qRbzbILs=,iv:3//fj7WtIX2QNYB9ub1JKAFIn5vJeuZl6rqaEsX0oQc=,tag:njU+WAVq7xBgE0sna2dMKA==,type:str]",
"version": "3.13.1"
}
}
@@ -1 +0,0 @@
../../../../../../sops/users/admin
@@ -1 +0,0 @@
8c99f9bc87e92795022b32698a440d6f9fe01d1110f867de8176bb190b92acab
@@ -1 +0,0 @@
200:eb95:7d1b:3ac3:62e7:24af:2274:3771
@@ -1 +0,0 @@
../../../../../../sops/machines/peer2
@@ -1,18 +0,0 @@
{
"data": "ENC[AES256_GCM,data:vOwMqT12A5ap5hRvCGTjTUX4sXKO3N7KE8eQ+/SCcBWndU9/b2AehiNgplWWMGcYdmeDL9qI8V2pPkgBkQ/tWH6N8DccSM/zQzrBUkXvRApl6hvNZAWuBVf/P4MW4/EbRGtMg2tEXkaPDtRn2TsDK7ygmXmqArI=,iv:FkxFx/ClAftLu85S6Uq3ZOom+YDOpeWGlYLOFBmFfnk=,tag:zprw62qiu+hmLZEZbnqYXA==,type:str]",
"sops": {
"age": [
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0WVB1M2ttd0FocGhTSjNo\nUDFIcmpsL051TndWbkJVakJHbUxjY3Q3NjM0CnkrbFlHS1E4bkZJQTIvMDJ3VDFv\nNW1OdmwvalBEelN2d3YwbHVqTW94OFEKLS0tIGtpOWxCM29xdXhQL2Yzb094OG1n\nT21mc25yU1dJL29vekRHdldzdDR3dEkKoZ1dPRaPg8iVsuec6IhV3cLPchokV2wv\nu6qb92hsLQuyPHDA01Oey0jxmaYMQGtAVjo2zEM+E+zrKY+f2pHIUQ==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
},
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArcmo5d2x6c3J0YTkwMGJE\nanphd2FiUjdGdmdNeW0rL0FpcTVSM3dublZ3CnphajNVV2YrTGl2a3ZqMTJKeU4v\nTzZRS2F5MlA5Ny84cFFoNWZQZnpBZTgKLS0tIHVKQUJWcmlPdy9GNXNBYnpJcEVC\nNmJVMlpvSzZPdk1JY2hIZVEvc3cwV2MKE/cMJU/j5g62njJ49AfnLutmxkpz/gxX\nIqWe1m7Uxl/awVFa7F8N7TUkd0jLbAGXZaonDjiBxOTwg/jr/apnuQ==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1u36fr87cru90vfznf5szasya9nhvvseh4atk8zsdj0rrsu0nnvwqsyt8g6"
}
],
"lastmodified": "2026-07-03T10:47:04Z",
"mac": "ENC[AES256_GCM,data:wiIkwEDwGJZe0u8qLHthPkCXubeIGyHV8yBo8CsSengLVTOtRZ877zTrFvE74ATF1pGE3DFJ5qGRrOGgKJ4VOl043LbEBs0bxZC495pPMPYszimp2UAf/XE3QWlNi9p4Ce/kbvUDd0W3SRt4hIv6HOLWApiRoqfS2qSMUnBQeW0=,iv:Hs7EysUnje/iWZRhJLlqf8wuFJnIMpWfXWHrilfmM5I=,tag:Rgj9x4ZOM2fihKKNQ4ux3g==,type:str]",
"version": "3.13.1"
}
}
@@ -1 +0,0 @@
../../../../../../sops/users/admin
@@ -1 +0,0 @@
8a354172629e4e8c6da86ec5e447411e4238cf7bb439b798fae56509a82d7472
@@ -1 +0,0 @@
200:3dcd:9b0d:103c:f953:1e8:e3a2:ed90
@@ -1 +0,0 @@
../../../../../../sops/machines/peer3
@@ -1,18 +0,0 @@
{
"data": "ENC[AES256_GCM,data:7no9ZnfatNLEykz+JOUExxmaRzBr7B5PEcevETySJWHTCCjSULdRb2KLxbXP5OKWSuJbR8pJ+p+nZuyr7aOTyXrU+fgwf/Pff4KGaZbKf1t3HJun8wJ2q62uaFYu8ACbNFfwIzJ51SPGcO7IHxfjWn5k9zG7av4=,iv:+VNvFKAJ+HDCGZciug8SKHOcM1JZQUAbZpRT5en4xcU=,tag:3kcDHWIs9ITzTKDiyyYhnQ==,type:str]",
"sops": {
"age": [
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvZ0VFcGhPR0NrMGU4dStU\nZGpnMHZmbUF0R0NFNWQzNGVpZXhYQ24xNXk0CnJIYmJYMnBmeURLZytBcXNRNG5u\nZzk4cXdPdnJIU0JVam1NWFA3TkhuWFkKLS0tIDZYUEVGMUtCQWdSM3k4WEZhdUt3\naElkc3o5SXlFYTJLNUpGZ0ptNm96M2MKYKW5emktK2M+IYX0v/swCV1fgrQXQVlb\nmz11rN5fJWV5wvLcTtyU9imgZLB9MfRMyIYlHzD2HPbW+zr8Fe+bBQ==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
},
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZVDVxY3JrWk1TY3ZsazNz\naVl4Vk1vRUdkRTdlaDU1TE15dC96ZHlxQ1ZBCmYvSmh1QlBNRnJyRy9kcDR0cXhY\neDdPUXZ6b2FkWnBXbzA4bzU1aFo3bEUKLS0tIHMrb05Oa3FrRzh5VHN1RWRmUU9W\ndGZUYTVVQkIzM3FRRHp6NXlEdEU0VTgK7ibTaEcvbVTQjcbgeylu2s5tmI5kAadM\nFGiOgJhDFuzbHxXIEQlsCBIaXe6LlGhBo41VZbMxme5py6nJFTBHKg==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1rka3368ltqc787xw99uu762lqfk7qxld9265u2t62fpxnp9xhufsc2q5rw"
}
],
"lastmodified": "2026-07-07T04:54:10Z",
"mac": "ENC[AES256_GCM,data:gonhuGY61G3Gdtj7q23aTNYU95fjLMz2uVTsSX+Hw10LGUTEMM8LF/Phae9kr5BZKD8BYaIgH32As2+n0B9jZ4WV77A5hUe2NJze9d0A40P2MtMh9xFWWh7yEXXnx5dy1UDrthL2LBa7ebPspuaC0mFhRHdoJK3J2W1m41PGjZc=,iv:H4yNuE8i3UxVjAUIpnaFX6i8/DaO4uIlHrEY9VaSiRs=,tag:9lJtixSNv7tpox0V3ZoNnA==,type:str]",
"version": "3.13.1"
}
}
@@ -1 +0,0 @@
../../../../../../sops/users/admin
@@ -1 +0,0 @@
e119327977e183567f0b8e2e8937c9d04708e296beed57792a1b6935eacf69d9
-1
View File
@@ -173,7 +173,6 @@
base_domain = settings.base_domain;
override_local_dns = true;
nameservers.global = settings.nameservers;
magic_dns = false;
};
};
+3 -24
View File
@@ -66,6 +66,8 @@
"AutofillAddressEnabled" = false;
"AutofillCreditCardEnabled" = false;
"TranslateEnabled" = false;
"DnsOverHttpsMode" = "secure";
"DnsOverHttpsTemplates" = "https://dns.adguard-dns.com/dns-query";
};
};
@@ -79,32 +81,14 @@
inputs,
...
}:
let
dictionaries =
with pkgs;
(hunspellWithDicts (
with hunspellDicts;
[
en-us-large
th-th
]
));
in
{
imports = [ inputs.plasma-manager.homeModules.plasma-manager ];
systemd.user.sessionVariables = {
DICPATH = "${dictionaries}/share/hunspell";
};
home = {
homeDirectory = lib.mkForce "/home/${username}";
stateVersion = osConfig.system.stateVersion;
packages = with pkgs; [
libreoffice-qt6
dictionaries
libreoffice-fresh
element-desktop
signal-desktop
brave
@@ -116,11 +100,6 @@
];
};
programs.chromium.package = pkgs.brave;
programs.firefox = {
enable = true;
};
programs.home-manager.enable = true;
services.syncthing.tray.enable = osConfig.services.syncthing.enable;
programs.plasma.enable = true;
@@ -5,4 +5,5 @@
services.displayManager.sddm.enable = lib.mkForce false;
services.displayManager.gdm.enable = true;
services.displayManager.gdm.wayland = true;
}
-79
View File
@@ -24,36 +24,6 @@
description = "";
default = "";
};
options.extraClientNumbers = lib.mkOption {
type = with lib.types; listOf str;
description = "List of client suffix number.";
default = [ ];
};
options.extraFixedIPClient = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule {
options = {
ip = lib.mkOption {
type = lib.types.str;
description = "IP address for this client";
};
name = lib.mkOption {
type = lib.types.str;
description = "Name of the client";
};
};
}
);
description = "Extra client to be added to pjsip config as a fixed IP auth";
example = {
"01" = {
ip = "192.168.1.3";
name = "bob";
};
};
};
};
perInstance =
{
@@ -156,41 +126,6 @@
remove_existing=yes
'';
genLocalSIPEndpointV6 =
{ localNumber }:
''
[${localNumber}](internal_endpoint)
transport=transport-udp6
aors=${localNumber}
auth=${localNumber}
[${localNumber}](userpass_auth)
username=${localNumber}
password=${localNumber}
[${localNumber}](dynamiic_aor)
max_contacts=1
'';
genLocalSIPIPEndpoint = number: ''
[${number}](internal_endpoint)
aors=${number}
auth=${number}
contact_deny=0.0.0.0/0
contact_deny=::/0
contact_permit=${settings.extraFixedIPClient.${number}.ip}/128
[${number}](dynamiic_aor)
max_contacts=1
remove_existing=yes
[${number}](userpass_auth)
username=${number}
password=${number}
'';
genLocalExtenConf =
{ localNumber }:
''
@@ -421,14 +356,6 @@
+ (genLocalExtenConf {
localNumber = config.clan.core.vars.generators.phonebox.files.ata-local-number.value;
})
+ lib.concatStringsSep "\n" (
builtins.map (number: genLocalExtenConf { localNumber = number; }) settings.extraClientNumbers
)
+ lib.concatStringsSep "\n" (
lib.mapAttrsToList (
number: _: genLocalExtenConf { localNumber = number; }
) settings.extraFixedIPClient
)
+ serverConf;
"rtp.conf" = ''
@@ -482,12 +409,6 @@
+ (genLocalSIPEndpoint {
localNumber = config.clan.core.vars.generators.phonebox.files.ata-local-number.value;
})
+ lib.concatStringsSep "\n" (
builtins.map (number: genLocalSIPEndpointV6 { localNumber = number; }) settings.extraClientNumbers
)
+ lib.concatStringsSep "\n" (
lib.mapAttrsToList (number: _: genLocalSIPIPEndpoint number) settings.extraFixedIPClient
)
+ serverConf;
};
};
View File
-308
View File
@@ -1,308 +0,0 @@
{ clanLib, ... }:
{
_class = "clan.service";
manifest.name = "prometheus";
manifest.description = "The Prometheus monitoring system and time series database.";
manifest.readme = builtins.readFile ./README.md;
manifest.categories = [ "System" ];
roles.server = {
description = "Prometheus server that scraps all data from nodes";
interface =
{ lib, ... }:
{
options = {
scrape_interval = lib.mkOption {
type = with lib.types; nullOr str;
default = "1m";
description = "How often to scrape targets. Default is 1 minutes";
};
extra_rules = lib.mkOption {
type = with lib.types; listOf attrs;
default = [ ];
description = "Additional rules for Prometheus";
};
default_receiver = lib.mkOption {
type = with lib.types; attrs;
default = {
name = "default";
};
description = "Definition of a default receiver, default is doing nothing";
};
matrix-alertmanager = {
enable = lib.mkOption {
type = with lib.types; bool;
default = false;
description = "Whether to enable `services.matrix-alertmanager`";
};
homeserverUrl = lib.mkOption {
type = with lib.types; str;
default = "https://matrix-client.matrix.org";
description = "URL of the Matrix homeserver to use";
};
matrixUser = lib.mkOption {
type = with lib.types; str;
description = "Matrix user for the bot";
};
matrixRooms = lib.mkOption {
type = lib.types.listOf (
lib.types.submodule {
options = {
receivers = lib.mkOption {
type = lib.types.listOf lib.types.str;
description = "List of receivers for this room";
};
roomId = lib.mkOption {
type = lib.types.str;
description = "Matrix room ID";
apply =
x:
assert lib.assertMsg (lib.hasPrefix "!" x) "Matrix room ID must start with a '!'. Got: ${x}";
x;
};
};
}
);
description = ''
Combination of Alertmanager receiver(s) and rooms for the bot to join.
Each Alertmanager receiver can be mapped to post to a matrix room.
Note, you must use a room ID and not a room alias/name. Room IDs start
with a "!".
'';
example = [
{
receivers = [
"receiver1"
"receiver2"
];
roomId = "!roomid@example.com";
}
{
receivers = [ "receiver3" ];
roomId = "!differentroomid@example.com";
}
];
};
};
};
};
perInstance =
{
settings,
roles,
...
}:
{
nixosModule =
{
config,
lib,
pkgs,
...
}:
let
getYggdrasilIP =
machineName:
if config.clan.core.vars.generators.yggdrasil.files.address ? value then
clanLib.getPublicValue {
flake = config.clan.core.settings.directory;
machine = machineName;
generator = "yggdrasil";
file = "address";
default = null;
}
else
throw "clanService/yggdrasil is required";
matrixRoomReceivers = lib.unique (
lib.concatMap (entry: entry.receivers) settings.matrix-alertmanager.matrixRooms
);
in
lib.mkMerge [
{
networking.firewall.allowedTCPPorts = [
9090
];
services.prometheus = {
enable = true;
globalConfig = {
scrape_interval = settings.scrape_interval;
};
alertmanagers = [
{
scheme = "http";
path_prefix = "/";
static_configs = [ { targets = [ "localhost:9093" ]; } ];
}
];
alertmanager = {
enable = true;
configuration = {
global = {
resolve_timeout = "5m";
};
route = {
receiver = "default";
routes = map (mReceiver: { receiver = mReceiver; }) matrixRoomReceivers;
};
receivers = [
{ name = "default"; }
]
++ map (mReceiver: {
name = mReceiver;
webhook_configs = [
{
url_file = config.clan.core.vars.generators.prometheus.files.matrix-alertmanager-urlfile.path;
send_resolved = true;
}
];
}) matrixRoomReceivers;
};
};
scrapeConfigs = lib.mapAttrsToList (machineName: machineVal: {
tls_config.insecure_skip_verify = true;
job_name = "${machineName}";
static_configs = lib.mapAttrsToList (
exporterName: exporterVal:
let
targetPort =
if exporterVal ? port then
exporterVal.port
else
config.services.prometheus.exporters."${exporterName}".port;
targetHost = getYggdrasilIP machineName;
in
{
targets = [ "[${targetHost}]:${lib.toString targetPort}" ];
}
) machineVal.settings.exporters;
}) roles.nodes.machines;
rules = [
(builtins.toJSON {
groups = [
{
name = "default";
rules = [
{
alert = "NodesDown";
expr = "count by (job) (up == 0) > 0";
for = "1m";
labels = {
severity = "critical";
};
annotations.summary = "Node **{{ $labels.job }}** has been down for more than 1 minutes.";
}
{
alert = "SmartCtlErrors";
expr = "smartctl_device_error_log_count > 0";
for = "5m";
labels = {
severity = "critical";
};
annotations.summary = ''
Errors occur on **{{ $labels.job }}**
Disk {{ $labels.device }} {{ $value }}
'';
}
{
alert = "ZFSPoolsHealth";
expr = "zfs_pool_health > 0";
for = "5m";
labels = {
severity = "critical";
};
annotations.summary = ''
Unhealthy Pool at **{{ $labels.job }}**
Pool {{ $labels.pool }} value {{ $value }}
'';
}
]
++ settings.extra_rules;
}
];
})
];
};
}
(lib.optionalAttrs settings.matrix-alertmanager.enable {
clan.core.vars.generators.prometheus = {
files.matrix-alertmanager-token.secret = true;
files.matrix-alertmanager-secret.secret = true;
files.matrix-alertmanager-urlfile = {
secret = true;
owner = "alertmanager";
group = "alertmanager";
};
script = ''
echo "" > $out/matrix-alertmanager-token
openssl rand -hex 32 > "$out"/matrix-alertmanager-secret
echo "http://localhost:3000/alerts?secret=$(cat $out/matrix-alertmanager-secret)" > $out/matrix-alertmanager-urlfile
'';
runtimeInputs = [
pkgs.openssl
];
};
services.matrix-alertmanager = lib.mkIf settings.matrix-alertmanager.enable {
enable = true;
tokenFile = config.clan.core.vars.generators.prometheus.files.matrix-alertmanager-token.path;
secretFile = config.clan.core.vars.generators.prometheus.files.matrix-alertmanager-secret.path;
homeserverUrl = settings.matrix-alertmanager.homeserverUrl;
matrixUser = settings.matrix-alertmanager.matrixUser;
matrixRooms = settings.matrix-alertmanager.matrixRooms;
};
})
];
};
};
roles.nodes = {
description = "A node will expose metrics for server to harvest";
interface =
{ lib, ... }:
{
options = {
exporters = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule { });
default = { };
description = "Mirror of services.prometheus.exporters";
};
};
};
perInstance =
{ settings, ... }:
let
enabledExporters = builtins.mapAttrs (
name: value:
value
// {
enable = true;
openFirewall = true;
}
) settings.exporters;
in
{
nixosModule =
{ ... }:
{
services.prometheus.exporters = enabledExporters;
};
};
};
}
-19
View File
@@ -1,19 +0,0 @@
{ self, inputs, ... }:
let
module = ./default.nix;
in
{
clan.modules = {
prometheus = module;
};
perSystem =
{ ... }:
{
clan.nixosTests.service-prometheus = {
imports = [ ./tests/vm/default.nix ];
_module.args = { inherit self inputs; };
clan.modules."@clan/prometheus" = module;
};
};
}
@@ -1,101 +0,0 @@
{
self,
hostPkgs,
config,
lib,
...
}:
{
name = "service-prometheus";
result.update-vars =
let
relativeDir = lib.removePrefix "${self}/" (toString config.clan.directory);
in
hostPkgs.writeShellScriptBin "update-vars" ''
set -x
export PRJ_ROOT=$(git rev-parse --show-toplevel)
${
self.inputs.clan-core.packages.${hostPkgs.system}.clan-cli
}/bin/clan-generate-test-vars $PRJ_ROOT/${relativeDir} ${config.name}
'';
clan = {
test.useContainers = false;
directory = ./.;
inventory = {
machines.server = { };
machines.nodeA = { };
instances = {
yggdrasil = {
module.name = "yggdrasil";
roles.default.machines.server = { };
roles.default.machines.nodeA = { };
};
prometheus = {
module.name = "@clan/prometheus";
module.input = "self";
roles.nodes.machines."nodeA".settings = {
exporters.smartctl = { };
};
roles.server.machines."server".settings = {
extra_rules = [
{
alert = "test";
expr = "zfs_pool_health > 0";
for = "5m";
labels = {
severity = "critical";
};
annotations.summary = ''
Unhealthy Pool at {{ $labels.job }}
Pool {{ $labels.pool }} value {{ $value }}
'';
}
];
matrix-alertmanager = {
enable = true;
matrixUser = "test@matrixtest.org";
matrixRooms = [
{
roomId = "!testroom";
receivers = [ "matrix" ];
}
];
};
};
};
};
};
};
nodes = {
server = { };
nodeA = { };
};
testScript =
{ nodes, ... }:
''
start_all()
server.wait_for_unit("prometheus.service")
nodeA.wait_for_unit("prometheus-smartctl-exporter.service")
nodeA.wait_for_open_port(9633)
nodeA.succeed("systemctl status prometheus-smartctl-exporter.service")
nodeA.succeed("curl http://localhost:9633/metrics")
server_ip = server.succeed("ip -4 addr show eth1 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'").strip()
nodeA_ip = nodeA.succeed("ip -4 addr show eth1 | grep -oP '(?<=inet\s)\d+(\.\d+){3}'").strip()
server.succeed(f"ping -c 3 {nodeA_ip}")
server.succeed(f"curl -v http://{nodeA_ip}:9633/metrics")
'';
}
@@ -1,6 +0,0 @@
[
{
"publickey": "age1kxsp8pa8am6k333nxs4akjqkhht8gspznmlqz4pxn35h5dj4uv5qj6q6fl",
"type": "age"
}
]
@@ -1,6 +0,0 @@
[
{
"publickey": "age1dkrf438z3337d2qnc7ugkggua99xkh55wuf9zgun35fjrxdpnf5qkg4z6j",
"type": "age"
}
]
@@ -1,14 +0,0 @@
{
"data": "ENC[AES256_GCM,data:Z8I3ecNV2N2jed1sPBU+tI5r5qB2nVTO7aNyMxvp0ztujn8kXjw+thSvLGtRygL2V9rSmPJalHQf1IYUriXgCmYtfg5InPDCAqk=,iv:O4rSyg2G6PJWHURZ/BTBKmn1AVekbNBdg5137sOPL/U=,tag:4/CLfO50laZ8ljWkr6o4qA==,type:str]",
"sops": {
"age": [
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTSWxnekYvREdZMTBMVlRq\nRmtCemFYZDhLYU93azc5czdoTVUydFFUL1JzCmo4ZHlrNi8yeW15N2JxTytWeCtk\nbjRwWUVlazUwTlMwc1RZVU8xYlVlckEKLS0tIFVPeU5KMVFwdExFT0wzeXZka2Jo\nSmxEM2RPTWdoZXJxK0dpemUzVkNzdGcKfXdiSeAcNwEZi7kh9c89ss5K+dYG0lhq\nFsf2I0A1csxqqnYJqXPmwlVGMzuWDrWRU0uc+hQLndP3TbadVux64w==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
}
],
"lastmodified": "2026-06-11T07:43:55Z",
"mac": "ENC[AES256_GCM,data:OCPR2tkbN72MdaczO47UNCJBb1KjABHQH9q7dtVEwoAhKg4QWFtsDaMwBTVE9qe48nlaWQbxT1mM7uztm6RXLkc5y2c3danPUYFj/FK/ffqpaxv3oReyxWqMoGayT23kFbB0TWEx1K8Jp3gOkwCPg+ZRClvhV1dXrfnwIwZHrBY=,iv:3puPIWFIxRF1KtrmyG54LqCc7Zg4/AOMD65QjYdN970=,tag:RoIVltMKw7WUvgW6sNk6mA==,type:str]",
"version": "3.13.0"
}
}
@@ -1 +0,0 @@
../../../users/admin
@@ -1,14 +0,0 @@
{
"data": "ENC[AES256_GCM,data:Nuq6ege3HJOxpRgA6fnxdD2Wj+KCw+3PaJCxmZirJl3mkRVLnZgUUhr+gOVEup9Ifjl1ZnP+PqV7b9pPR/WQg0LARYtxIC1QGJ8=,iv:v9p9lsefP5V9McAJCzS7v9sl8XHr9/hAL41XwFbwMOA=,tag:ETK+CFFJAAzGTpowQNAZMQ==,type:str]",
"sops": {
"age": [
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArN0NEWFZoZWlyeUtZc3hi\ndnVNcHl4eVVHckRLeFhPYUt4a3BwMElFMVZZCklkU1NEWVVmSGw1NmJmWWkrVHFH\nVTN5U0x3NXdiQUJCc095TElzMWZCMXMKLS0tIHRXQkJNREFYUFFvMXM1Sk53VW5z\naTRjMXozZXZiNU8zSkF5d2hhdklBY1EKWwsPi6YiHKFfAyqWH2u75hw47gzcQOz/\n95Im0FgadhqGDCeZhTDfEAc4b1VWQULInsjeRapzf5OJOwekbz6guA==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
}
],
"lastmodified": "2026-06-11T07:45:26Z",
"mac": "ENC[AES256_GCM,data:mTKFSBFnUzu3rldQCHPZHoyzDdwPzBWPIAhemC1XyG5PiQ/OczStjYaLzZQGCpPvOjBb5Ntqrc+dnaOedZgKlOdaPjZs1U2ZDWadoeWQ2TAKWYA6+kN7PXomsxtHhntiaujMy3502eh06VyiutpVuCdzK2cfEwuno8nyIcHgtXk=,iv:/5DRvFVDQA+yd8m/+Cyxb+aIsfwoaFcV6KRQ/7ISHnU=,tag:z31P6CL0NNRlQThqwapVNA==,type:str]",
"version": "3.13.0"
}
}
@@ -1 +0,0 @@
../../../users/admin
@@ -1,4 +0,0 @@
{
"publickey": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"type": "age"
}
@@ -1 +0,0 @@
204:b10b:6057:4bbe:2b44:fc58:c6fd:90ad
@@ -1 +0,0 @@
../../../../../../sops/machines/nodeA
@@ -1,18 +0,0 @@
{
"data": "ENC[AES256_GCM,data:JkuciSmL5nmSjcYn22W7iHKzuRxWMJ5dixYllm0aSM7DsyAp9mQzIYJJmalepp7sEhSJ5As3vQW6ZpOQ3G8ZheG06++1GlM8lvVV2FKmYvKHQpI+V7WyUJl7dpfu+5A6BzWES0GbC1g8l/a8sb/+jjEoqUTAj/4=,iv:tehdHsdm2uSRAAzImHhwBSnSBF6lzjLzF9HIPnoi9s0=,tag:dWnQhAiJeCkcssjko+dUpw==,type:str]",
"sops": {
"age": [
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBOVmRSR2xDNmdPYW5MNUVH\nYWVpaTc0TjdOZFBTSEJDL1Z3VG9vVHkrZUFjCklUMUU1bnVmZFJYbzVPd09oZm1U\nNHY0R1hNQnBBc2V4Y2RWQ1ZZRjdOK0kKLS0tIEJkSWFaTDJzMDNJR3QwQzRVdld4\ndDA5ZmZSeTYyVUE5Y1Z1T1l5QmpHRTQKSaN+MIazA8RXhRSyFSkDTyXEp43COpbf\nXOzAhTXja+ut/akUuKadDS4xycZ+ZXAreVmdsF4SWvwZkmPeew+hKQ==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1kxsp8pa8am6k333nxs4akjqkhht8gspznmlqz4pxn35h5dj4uv5qj6q6fl"
},
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMNmZkTHlaRWl1V3UvcGxk\nR0hhL1lNekNzb0REaEc4bitBZkcwYmRDb2hjCnloQTZUL3ZneWZQZk9NTEc1bGNB\nY3ljdFRMMUhLeDdyblhVY3lSOFBXc1UKLS0tIEJUc1ZpQmtuNlRUUEVmajY5TGdP\ncSs2RkZXcnJYRlEvcEtYSWxIWmkrVEkKgQnfxuZuxl1OpZDUPVuqseSN89WnBGFw\nx2PI3cqN67R2tV/FEjOZo+GFgxW93SYdMvxzg2aG2q/7xOQxfj9sjg==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
}
],
"lastmodified": "2026-06-11T07:44:25Z",
"mac": "ENC[AES256_GCM,data:gRk1t7xFxXSTUcZQw0DCH3QtRnQJF4Mc4kZeeckhuQdc/VATj+cq+ugicrcGJWbbXzAscQLG6g72+Qiane5nFfzmjNoO6JMe181wm7pY/5St+2MjXZEzwAaYjn6ZAm+U7aiUVcp8RBjFIL9HCvBF8qFl7rqqTvYHnTOU0V6TIIo=,iv:eUvZFDKl8PX5QaQPmwJXaokawQMNP0TGOklTAMgB/sg=,tag:3cHICox8bKWkPKMUgvLuXA==,type:str]",
"version": "3.13.0"
}
}
@@ -1 +0,0 @@
../../../../../../sops/users/admin
@@ -1 +0,0 @@
0a77a4fd45a20ea5d81d39c8137a97dd4988c692ce4263959559b8c3f966c1de
@@ -1 +0,0 @@
../../../../../../sops/machines/server
@@ -1,18 +0,0 @@
{
"data": "ENC[AES256_GCM,data:VszBHfdaNOOYYa6tNUPq9CsJHp+KMBTnZOdHnJz6v3pZQl1zCeYdW3ExvDfNY85tUAZ3YAHthD9JhuR1D+VVVn8=,iv:zbMmaTDZ5mL9IzRTEzuTSPkfwrwOlOIFJtLQyTzGkPw=,tag:Ez68y6gMIj0e/RYQ/Z+s8Q==,type:str]",
"sops": {
"age": [
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlenlYOCt2RkJOK1hDdUti\ncUpxS1F1RTBnZGo1Njg0Y0EwbzM1dWM5b1hJClFKQ1NDRVVpRXRpOGx3SU52MDZZ\nVVh2NDg5TDgzckFKZ0lNaG1tTEk0MmsKLS0tIHRvR0IzWFZUVkJEM0dwRFZ2SFRz\nNHpCYkI4dUx6YXJSd0xreUN1aUtKNEUK/SJqs5pbFipbp9P7ASUMby7H5ProXknF\nGMvHcIxa6OLLOCRA39YZBVEUlRd03j3rVFILZqVq47CwfaeHj0WBdw==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1dkrf438z3337d2qnc7ugkggua99xkh55wuf9zgun35fjrxdpnf5qkg4z6j"
},
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4cWMzaElhYmZaRGhmMXJQ\nbWk2WVl0UmtidjdzYXM0enB3MGdTMWRMVDBjCmdiNEx2RURGL0ZtWCtkcHlabUs0\nVis2d3JieC8yOXV5OW9sN1l5ZWs5Sk0KLS0tIFNmaVpDQklaUDFQK1JnZWZzMDF6\nY0g1M2NHNTEvSkRsTVJSODcxcVVrV0EK8FLzflXqPcooAPh38L7oVliUY8WbB97W\naQYvGf/yo9Izmm8Pa0/ZUGSRnCVRAXtQ1IeR1uPNyuy47mHXO7n7Bw==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
}
],
"lastmodified": "2026-06-22T07:46:31Z",
"mac": "ENC[AES256_GCM,data:ewR8kGgrAj7i6b5UUwh4Fn4CbtRcsDSHhHzrBwGBi9S0XWaatVTQAAmsAVm7DEiJ+a3SQLIAyx6Ef7uqCsZagmzs7LBq0YXNxWtxv62EWPwx8Vihzz3gscDJo1DM3ictX7yi6EiipQ0aYoPCh1veqw8AspLdwnkBxdUF2C+0muc=,iv:bo7vq8BfL437ZI63Os96pAg8EKi8NnrqhABz4Jft9YI=,tag:8krOKra/Z3MJdlmZFBZ7YQ==,type:str]",
"version": "3.13.1"
}
}
@@ -1 +0,0 @@
../../../../../../sops/users/admin
@@ -1 +0,0 @@
../../../../../../sops/machines/server
@@ -1,18 +0,0 @@
{
"data": "ENC[AES256_GCM,data:Mw==,iv:ylmBzsJVBD2pcQNkLcdthT9FX7YW84yZk0u7SlJUdaY=,tag:O1oT/MVijlrQDQG1ddFKlg==,type:str]",
"sops": {
"age": [
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRd2ZIMElrK2ZacXFTTHFl\nWDkwbGROS1d3WlhzcHhQK21Fc1pmWFZ1VkJRCjlrY1E0cndsZUR1dVQ2L0dud3RQ\nbDlNa3NQZjBPQTAxdUVkUk9lYkgyTGcKLS0tIEUyMVE5Y25BOFJyUWdkdWI1L3VQ\nSE5ubkMvWU9YbE94VTN2VXFUc2F0ajQKKz5VJEtEQcKggoO89ZSfpB3KLBHCnMf+\no8llbCm5bZ39S3qA2Q8spOK4AlkW/NiaCQE4G1LSkvvT6tYEMkwbyQ==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1dkrf438z3337d2qnc7ugkggua99xkh55wuf9zgun35fjrxdpnf5qkg4z6j"
},
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnNHhVMWNhZGR6LzgrcG05\nMmVUYU1zcC93YklZUkVETFhZL1BISU13MEFNCjFSZ25EQUQrZTNIcmliTG5UV2xp\nKzQ3MzhkdzcxeGgyV3oxbXo5Y0ZMcmMKLS0tIDVMZjdYWjRkUE50dmE5dm42alpn\nbk1JN1poZWp2bEZNQ3VIdm9PS3Z1ZlEKYOTa7L9tVKq3gZbAeKmCifIxs/sqaPoj\nqdUlsPkwBPjSvlv1QLdRbjBICPdyfH+GiHCmj78DitzZ+KUnRKYqSQ==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
}
],
"lastmodified": "2026-06-22T07:46:31Z",
"mac": "ENC[AES256_GCM,data:NqKlCAKKPF0OTesGozt0GSSd/HT8+h4meiO57EBzD7vwLc9mobG0rLn5C2i3e7tBM13VYzR66qPzQtaWI/jVA7BpJ0PNa2u9MHA2JV6nshRdhMtYgxVCBy8Had7IixAZEs1lLE2zHcWRvLMJPOvUp7tpghb34RddmF/Po/Mkm2s=,iv:9XCsu+rO/DbtaLt13O0/PUo/yV2eUjNP+GGmkYjOIfY=,tag:7tzJE5XBR5PfOqdIh7IKAQ==,type:str]",
"version": "3.13.1"
}
}
@@ -1 +0,0 @@
../../../../../../sops/users/admin
@@ -1 +0,0 @@
../../../../../../sops/machines/server
@@ -1,18 +0,0 @@
{
"data": "ENC[AES256_GCM,data:LetAgJg1TgcJL+W7dX8k8MlvpS3PPwVGdco3Z6a8fGhGeQARcuHWV57K4lLQzPpJ7Cruxc6XGQn1U/t3cubdp2NPtwQsP9jaIqPnlZblrq6foHaUmBLaRzc4ed7HOo94ErfV5ZY=,iv:jdt3jMNlK3QvJP8i3OlGydkRPRd2rVybnmUxCDCxfz4=,tag:imNVcalMwnpuaLCdaoaegg==,type:str]",
"sops": {
"age": [
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4WU9IT3g4TVpiSWdYMUFo\nZGpSUG5xekZLaGMzNTZlcHFaSm1kbTBxUHhjClRIMzlhWW9ub2JFZHhVY3I3TkF3\nU0t5eHJVeFVHRStoNTFkT0lpYnNoMFkKLS0tIEM3aWdIL2RrSGx0ZkdheVRtYUhm\nUHZxeGZvUlBybWJFTHIrZDNxZVloemMKvpt+hkFaRUEXNp1dcfnIWD1i6fyVkaZm\neTn6RBxl1idVN1XlXAwrHHTekuZIobST5kGTV0uR3nLk5Cmhe2x93g==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1dkrf438z3337d2qnc7ugkggua99xkh55wuf9zgun35fjrxdpnf5qkg4z6j"
},
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjTDlTM0JBaEowaXJOV1hE\nZWZ2UmUzQmlyek5NRWlqWDZiY0FXVHpKL1d3CitreGc3OUFzS0tYYm5UZ0tUb2pX\nb0pZZ3VacVBma09pSDEyalc0VU1HTVUKLS0tIE5YcnY2RnFCVk13dDZJQ3NMZDQ4\nTGgrY3FwMW5ybjM0a0FmNllrRWZYNWMK2BklSFSm1jT1SsdaMtFWZX4uu4JT2kGi\njyD9E/G0yGl5JH8xfKO/x7vIPuow96WW8bx9aqGRnshXqbe6WzvbIQ==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
}
],
"lastmodified": "2026-06-22T07:46:31Z",
"mac": "ENC[AES256_GCM,data:bO9VvnIcjXDSyTdEHm1l5Dqm4umLC7FCEaJIbuC+M776q+GR3crq1FWm7J6tinlHDNFX/WmcS417b5WY5VJlP3jqvCalQdttg0EzlhwT65vATvJHoYEp8uqahyLzA9tj9ncQ9LL2XGFeIsvWnU9OcZ5s/42v2DtVdS1/32PT+7U=,iv:W29qp/zHP367rkwiMmpPQcKS/5g6HR5CZGkGCIacwD4=,tag:3DHc5kdj1Ar+7TcaSOnj+Q==,type:str]",
"version": "3.13.1"
}
}
@@ -1 +0,0 @@
../../../../../../sops/users/admin
@@ -1 +0,0 @@
202:8a70:e215:f822:c67a:f191:b04a:a8f
@@ -1 +0,0 @@
../../../../../../sops/machines/server
@@ -1,18 +0,0 @@
{
"data": "ENC[AES256_GCM,data:JcxiDqZDX3J3ooSeN0pQ28uvI86mtHUf2BEcOQdFIDhJZODGCc+BhZvBQmu2mabV8Jf4skrTWqD+60c1fkRcsM+MMXfoyNsrRyQ2K39mG4kl8jJKVKDs+BqXa+CvZ96kesOMgi9vdc3YUKo5cCLY4bQ9VwymqH8=,iv:W3z8Pbyo2IMzkxI4k14FlirLa28qgZ3rnTAWuusiw/0=,tag:EQc8mo/UvACbt8hQv3zPEw==,type:str]",
"sops": {
"age": [
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkRDNOSU81alN2THNQQ3ZW\nbHVjMmxaYWpzak1NZHplNTVzZzQvMHg4azAwCkExb0VLYlZUd2JjVGNlcXUyR0p1\nWHk5cXpOeGZ0VFRFTGllQWpxRlBTRk0KLS0tIDhKeUc4RHQvb0o0ZXFXZUNCanVY\nYm04TVBoWjlLT0tFOHRnLzd3RHV2ZzAKVpLtENDySGC6UDgAwhDb+7KJiHXOZF6n\nIaeIQWQqiB+45h72NE3yh02boPK8pl6IoJFcK3e4zSO7/G8jGUp0MQ==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1dkrf438z3337d2qnc7ugkggua99xkh55wuf9zgun35fjrxdpnf5qkg4z6j"
},
{
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGSUZXVzJwVHdwZGtxOVRu\nN1hMZkltdVM0cnNRL2tSNENkSGV2VzFIU1VBCmRZWlJTODNPMVRjVWY1V1VZcFln\nTDE3N0xsMXdMWityRUNUYWlQOXBMMTgKLS0tIGViTzBrQk5wQXBYQitIb1ZPUitC\nLysyUER0UjFlZm95c3ZGK3hEMEtrNUEKABpoKBUnvzQKSrgsdnU+uyDyED0Tlr7D\nnSsf12c84cvdt0OeCWwf2WvBANZL26XTcFq1fBYOFTJqNLs1ZfO2kg==\n-----END AGE ENCRYPTED FILE-----\n",
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
}
],
"lastmodified": "2026-06-11T07:45:55Z",
"mac": "ENC[AES256_GCM,data:jjhkZB9NdpvV2R0k9yS/AcUqeMr1RLv1UZwGCemlKSwhBfs8E5NxTXLhtmJeQ+hltOTYpz51BIporVtlaH6ElVnh7khOrG3Lb5cLBrL41QM59y3Tbfu6TjNOE3NyMiWuxZnwuqUGWQjsjrIIhE0ftKnpSpkGHMie+BC3iNSB1tY=,iv:onOVK9eJxWOaIjChQD54tz8lY+r/jpp6AArsBIuoRUM=,tag:2Oas1C5D2kZOe4iiD5huyw==,type:str]",
"version": "3.13.0"
}
}
@@ -1 +0,0 @@
../../../../../../sops/users/admin
@@ -1 +0,0 @@
2eb1e3bd40fba730a1cdc9f6beae1848e4b965e37f18a61593327964108fe6a8
-174
View File
@@ -1,174 +0,0 @@
{ ... }:
{
_class = "clan.service";
manifest.name = "wordpress";
manifest.description = "wordpress with multi-tenant support and state of plugins and themes are allowed";
manifest.readme = "wordpress with multi-tenant support and state of plugins and themes are allowed";
manifest.categories = [ "System" ];
roles.server = {
description = "A default server role";
interface =
{ lib, ... }:
{
options = {
tenants = lib.mkOption {
type = with lib.types; listOf str;
default = [ "localhost" ];
description = "List of tenants website to host on the instance";
example = [ "example.com" ];
};
phpfpmOptions = lib.mkOption {
type = with lib.types; lines;
default = "";
description = "options appended to the PHP configuration file";
};
wpExtraConfig = lib.mkOption {
type = with lib.types; lines;
default = "";
description = "Any additional text to be appended to the wp-config.php";
};
};
};
perInstance =
{ settings, ... }:
{
nixosModule =
{
pkgs,
lib,
config,
...
}:
let
user = "wordpress";
mkSafeDBName = domain: "wp_${builtins.replaceStrings [ "." ] [ "_" ] domain}";
mkWordpressSite = domain: {
database = {
name = mkSafeDBName domain;
user = user;
};
package = wp-pkg domain;
extraConfig = ''
define('FS_METHOD', 'direct');
''
+ settings.wpExtraConfig;
themes = { };
};
stateDir = hostName: "/var/lib/wordpress/${hostName}";
wp-pkg =
hostName:
let
upStreamSrc = pkgs.wordpress;
in
pkgs.stdenv.mkDerivation {
pname = "wordpress-custom";
version = upStreamSrc.version;
src = upStreamSrc;
installPhase = ''
mkdir -p $out
cp -r * $out/
rm -rf $out/share/wordpress/wp-content/plugins
rm -rf $out/share/wordpress/wp-content/themes
# symlink uploads directory
ln -s "${stateDir hostName}"/wp-content/themes $out/share/wordpress/wp-content/themes
ln -s "${stateDir hostName}"/wp-content/plugins $out/share/wordpress/wp-content/plugins
ln -s "${stateDir hostName}"/wp-content/upgrade $out/share/wordpress/wp-content/upgrade
ln -s "${stateDir hostName}"/wp-content/upgrade-temp-backup $out/share/wordpress/wp-content/upgrade-temp-backup
ln -s "${stateDir hostName}"/wp-content/ai1wm-backups $out/share/wordpress/wp-content/ai1wm-backups
'';
};
webserver = config.services.${config.services.wordpress.webserver};
in
{
services.wordpress.webserver = "nginx";
services.wordpress.sites = builtins.listToAttrs (
map (tenant: {
name = tenant;
value = mkWordpressSite tenant;
}) settings.tenants
);
systemd.tmpfiles.rules = lib.flatten (
map (tenant: [
"d '${stateDir tenant}/wp-content' 0750 ${user} ${webserver.group} - -"
"d '${stateDir tenant}/wp-content/themes' 0750 ${user} ${webserver.group} - -"
"Z '${stateDir tenant}/wp-content/themes' 0750 ${user} ${webserver.group} - -"
"d '${stateDir tenant}/wp-content/plugins' 0750 ${user} ${webserver.group} - -"
"Z '${stateDir tenant}/wp-content/plugins' 0750 ${user} ${webserver.group} - -"
"d '${stateDir tenant}/wp-content/upgrade' 0750 ${user} ${webserver.group} - -"
"Z '${stateDir tenant}/wp-content/upgrade' 0750 ${user} ${webserver.group} - -"
"d '${stateDir tenant}/wp-content/upgrade-temp-backup' 0750 ${user} ${webserver.group} - -"
"Z '${stateDir tenant}/wp-content/upgrade-temp-backup' 0750 ${user} ${webserver.group} - -"
"d '${stateDir tenant}/wp-content/ai1wm-backups' 0750 ${user} ${webserver.group} - -"
"Z '${stateDir tenant}/wp-content/ai1wm-backups' 0750 ${user} ${webserver.group} - -"
]) settings.tenants
);
networking.firewall.allowedTCPPorts = [
80
443
];
services.phpfpm.pools = builtins.listToAttrs (
map (
tenant: lib.nameValuePair "wordpress-${tenant}" { phpOptions = settings.phpfpmOptions; }
) settings.tenants
);
security.acme.acceptTerms = true;
users.users.nginx.extraGroups = [ "acme" ];
security.acme.certs = lib.listToAttrs (
map (
tenant:
(lib.nameValuePair tenant {
email = config.clan.core.vars.generators.acme.files.email.value;
webroot = "/var/lib/acme/acme-challenge/${tenant}";
})
) settings.tenants
);
services.nginx.clientMaxBodySize = "128m";
services.nginx.virtualHosts = lib.listToAttrs (
map (
tenant:
(lib.nameValuePair tenant {
forceSSL = true;
useACMEHost = tenant;
acmeRoot = config.security.acme.certs.${tenant}.webroot;
})
) settings.tenants
);
clan.core.vars.generators.acme = {
share = true;
files.email.secret = false;
prompts.email = {
type = "line";
description = "Email for ACME registeration";
};
script = ''
cat $prompts/email > $out/email
'';
};
};
};
};
}
-19
View File
@@ -1,19 +0,0 @@
{ self, inputs, ... }:
let
module = ./default.nix;
in
{
clan.modules = {
wordpress = module;
};
perSystem =
{ ... }:
{
clan.nixosTests.service-wordpress = {
imports = [ ./tests/vm/default.nix ];
_module.args = { inherit self inputs; };
clan.modules."@clan/wordpress" = module;
};
};
}
@@ -1,59 +0,0 @@
{
self,
config,
lib,
hostPkgs,
...
}:
{
name = "service-wordpress";
result.update-vars =
let
relativeDir = lib.removePrefix "${self}/" (toString config.clan.directory);
in
hostPkgs.writeShellScriptBin "update-vars" ''
set -x
export PRJ_ROOT=$(git rev-parse --show-toplevel)
${
self.inputs.clan-core.packages.${hostPkgs.system}.clan-cli
}/bin/clan-generate-test-vars $PRJ_ROOT/${relativeDir} ${config.name}
'';
clan = {
test.useContainers = false;
directory = ./.;
inventory = {
machines.server = { };
instances = {
wordpress-test = {
module.name = "@clan/wordpress";
module.input = "self";
roles.server.machines."server".settings = {
tenants = [
"localhost"
"site2.localhost"
];
};
};
};
};
};
nodes = {
server = { };
};
testScript = ''
start_all()
server.wait_for_unit("phpfpm-wordpress-localhost.service")
server.wait_for_unit("phpfpm-wordpress-site2.localhost.service")
server.succeed("systemctl status phpfpm-wordpress-localhost.service")
server.succeed("systemctl status phpfpm-wordpress-site2.localhost.service")
server.wait_for_open_port(80)
server.succeed("curl -H \"Host: localhost\" http://127.0.0.1:80 ")
server.succeed("curl -H \"Host: site2.localhost\" http://127.0.0.1:80 ")
'';
}
@@ -1,4 +0,0 @@
{
"publickey": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"type": "age"
}
@@ -1 +0,0 @@
fake_line_value
+5
View File
@@ -0,0 +1,5 @@
{
flake.nixosModules = {
inventree = import ../nixos/inventree;
};
}
+334
View File
@@ -0,0 +1,334 @@
{
lib,
config,
pkgs,
...
}:
let
inherit (lib)
mkEnableOption
mkOption
types
mkIf
;
configFormat = pkgs.formats.json { };
cfg = config.services.inventree;
pkg = cfg.package;
configFile = "${cfg.dataDir}/config.json";
env = {
INVENTREE_CONFIG_FILE = configFile;
INVENTREE_SECRET_KEY_FILE = cfg.secretKeyFile;
INVENTREE_AUTO_UPDATE = "1";
INVENTREE_PLUGINS_ENABLED = "1";
INVENTREE_PLUGIN_NOINSTALL = "0";
INVENTREE_STATIC_ROOT = cfg.config.static_root;
INVENTREE_MEDIA_ROOT = cfg.config.media_root;
INVENTREE_BACKUP_DIR = cfg.config.backup_dir;
INVENTREE_OIDC_PRIVATE_KEY_FILE = cfg.config.oidc_private_key_file;
INVENTREE_DB_ENGINE = cfg.config.database.ENGINE;
INVENTREE_DB_NAME = cfg.config.database.NAME;
INVENTREE_DB_HOST = cfg.config.database.HOST;
INVENTREE_DB_USER = "inventree";
INVENTREE_ADMIN_USER = cfg.config.adminUser;
INVENTREE_ADMIN_PASSWORD_FILE = cfg.config.adminPasswordFile;
INVENTREE_USE_X_FORWARDED_HOST = "1";
INVENTREE_CORS_ORIGIN_ALLOW_ALL = "1";
INVENTREE_FRONTEND_SETTINGS = ''{"mobile_mode":"allow-always"}'';
INVENTREE_SITE_URL = cfg.config.site_url;
PYTHONPATH = pkg.pythonPath;
};
inventree-invoke = pkgs.writeShellApplication {
name = "inventree-invoke";
text = ''
export INVENTREE_CONFIG_FILE=${configFile}
export INVENTREE_SECRET_KEY_FILE=${cfg.secretKeyFile}
export PYTHONPATH=${pkg.pythonPath}
exec -a "$0" ${pkgs.python3Packages.invoke}/bin/invoke -r ${cfg.package}/opt/inventree "$@"
'';
};
in
{
options.services.inventree = {
enable = mkEnableOption "InvenTree parts manager";
package = lib.mkOption {
type = types.package;
default = pkgs.inventree;
description = ''
InvenTree package to use
'';
};
hostName = mkOption {
type = types.str;
description = "FQDN for the InvenTree instance.";
};
dataDir = mkOption {
type = types.path;
default = "/var/lib/inventree";
example = "/var/lib/inventree";
description = ''
The default path for all inventree data.
'';
};
secretKeyFile = mkOption {
type = types.path;
default = "${cfg.dataDir}/secret_key.txt";
description = ''
Path to a file containing the secret key
'';
};
config = mkOption {
type = types.submodule ({
freeformType = configFormat.type;
options = {
adminUser = mkOption {
type = types.str;
default = "admin";
};
adminPasswordFile = mkOption {
type = types.path;
description = "Path to password file for user `admin`";
};
site_url = mkOption {
type = types.str;
default = "https://${cfg.hostName}";
};
static_root = mkOption {
type = types.path;
default = "${cfg.dataDir}/static";
description = ''
Static file storage
'';
};
media_root = mkOption {
type = types.path;
default = "${cfg.dataDir}/media_root";
description = "Media root directory";
};
backup_dir = mkOption {
type = types.path;
default = "${cfg.dataDir}/backups";
description = "Backup directory";
};
oidc_private_key_file = mkOption {
type = types.path;
default = "${cfg.dataDir}/oidc.key";
};
};
});
default = { };
description = ''
Config options, see https://docs.inventree.org/en/stable/start/config/
for details
'';
};
serverStartTimeout = mkOption {
type = types.str;
default = "10min";
description = ''
TimeoutStartSec for the server systemd service.
See https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html#TimeoutStartSec=
for more details
'';
};
serverStopTimeout = mkOption {
type = types.str;
default = "5min";
description = ''
TimeoutStopSec for the server systemd service.
See https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html#TimeoutStopSec=
for more details
'';
};
};
config = mkIf cfg.enable {
environment.systemPackages = [ inventree-invoke ];
systemd.tmpfiles.rules = (
map (dir: "d ${dir} 0755 inventree inventree") [
"${cfg.dataDir}"
"${cfg.dataDir}/static"
"${cfg.dataDir}/media_root"
"${cfg.dataDir}/backups"
]
);
services.inventree.config = {
plugins_enabled = false;
plugin_file = "${cfg.dataDir}/plugins.txt";
plugin_dir = "${cfg.dataDir}/plugins";
database = {
ENGINE = "postgresql";
NAME = "inventree";
HOST = "/run/postgresql";
};
};
services.postgresql = {
enable = true;
ensureDatabases = [ "inventree" ];
ensureUsers = [
{
name = "inventree";
ensureDBOwnership = true;
}
];
};
users.users.inventree = {
group = "inventree";
isSystemUser = true;
description = "InvenTree daemon user";
};
users.groups.inventree = { };
services.nginx.enable = true;
services.nginx.virtualHosts.${cfg.hostName} = {
locations =
let
unixPath = config.systemd.sockets.inventree-gunicorn.socketConfig.ListenStream;
in
{
"/" = {
extraConfig = ''
client_max_body_size 100M;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
'';
proxyPass = "http://unix:${unixPath}";
};
"/static/" = {
alias = "${cfg.config.static_root}/";
extraConfig = ''
expires 30d;
'';
};
"/media/" = {
alias = "${cfg.config.media_root}/";
extraConfig = ''
auth_request /auth;
'';
};
"/auth" = {
extraConfig = ''
internal;
'';
proxyPass = "http://unix:${unixPath}:/auth/";
};
};
};
systemd.targets.inventree = {
description = "Target for all InvenTree services";
wantedBy = [ "multi-user.target" ];
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
};
systemd.services.inventree-config = {
description = "Inventree config generation";
wantedBy = [ "inventree.target" ];
partOf = [ "inventree.target" ];
before = [
"inventree-static.service"
"inventree-gunicorn.service"
"inventree-qcluster.service"
];
serviceConfig = {
# User = "root";
# Group = "root";
User = "inventree";
Group = "inventree";
Type = "oneshot";
RemainAfterExit = true;
PrivateTmp = true;
};
environment = env;
script = ''
set -euo pipefail
umask u=rwx,g=,o=
# chown inventree:inventree ${configFile}
${pkg}/opt/inventree/src/backend/InvenTree/manage.py migrate
'';
};
systemd.services.inventree-static = {
description = "InvenTree static migration";
wantedBy = [ "inventree.target" ];
partOf = [ "inventree.target" ];
before = [ "inventree-gunicorn.service" ];
environment = env;
serviceConfig = {
User = "inventree";
Group = "inventree";
StateDirectory = "inventree";
#RuntimeDirectory = "inventree";
PrivateTmp = true;
ExecStart = ''
${pkg}/opt/inventree/src/backend/InvenTree/manage.py collectstatic --no-input
'';
};
};
systemd.services.inventree-gunicorn = {
description = "InvenTree Gunicorn server";
requiredBy = [ "inventree.target" ];
partOf = [ "inventree.target" ];
#wantedBy = [ "inventree.target" ];
environment = env;
serviceConfig = {
User = "inventree";
Group = "inventree";
StateDirectory = "inventree";
#RuntimeDirectory = "inventree";
PrivateTmp = true;
ExecStart = ''
${pkg.gunicorn}/bin/gunicorn InvenTree.wsgi \
--pythonpath ${pkg}/opt/inventree/src/backend/InvenTree
'';
};
};
systemd.sockets.inventree-gunicorn = {
wantedBy = [ "sockets.target" ];
partOf = [ "inventree.target" ];
socketConfig.ListenStream = "/run/inventree/gunicorn.socket";
};
systemd.services.inventree-qcluster = {
description = "InvenTree qcluster server";
requiredBy = [ "inventree.target" ];
wantedBy = [ "inventree.target" ];
partOf = [ "inventree.target" ];
environment = env;
serviceConfig = {
User = "inventree";
Group = "inventree";
StateDirectory = "inventree";
#RuntimeDirectory = "inventree";
PrivateTmp = true;
ExecStart = ''
${pkg}/opt/inventree/src/backend/InvenTree/manage.py qcluster
'';
};
};
};
}
+2 -2
View File
@@ -173,10 +173,10 @@ in
serviceConfig = {
User = cfg.user;
WorkingDirectory = "${file-uploader}";
ExecStart = "${lib.getExe pkgs.nodejs} ${file-uploader}/src/be/index.js";
ExecStart = "${lib.getExe pkgs.nodejs_20} ${file-uploader}/src/be/index.js";
Restart = "on-failure";
};
path = [ pkgs.nodejs ];
path = [ pkgs.nodejs_20 ];
};
environment.systemPackages = [
+1 -1
View File
@@ -17,7 +17,7 @@ buildNpmPackage {
version = "1.0.0";
nativeBuildInputs = with pkgs; [
nodejs
nodejs_20
breakpointHook
];
+161
View File
@@ -0,0 +1,161 @@
{
stdenvNoCC,
python3,
fetchFromGitHub,
fetchYarnDeps,
yarnConfigHook,
nodejs,
}:
let
version = "1.1.0";
src = fetchFromGitHub {
owner = "inventree";
repo = "InvenTree";
tag = "${version}";
hash = "sha256-GAATo5zkkNCes9fCQsYUsZ9auhgYEUnevN4obWj3ZRA=";
};
frontend = stdenvNoCC.mkDerivation {
name = "inventree-frontend";
inherit version src;
yarnOfflineCache = fetchYarnDeps {
yarnLock = "${src}/src/frontend/yarn.lock";
hash = "sha256-Ijbkx+INZgsvMhkzo8h/FUY75W3UHnKAdUjQRD8kJZw=";
};
nativeBuildInputs = [
yarnConfigHook
nodejs
];
patchPhase = ''
runHook prePatch
cd src/frontend
runHook postPatch
'';
buildPhase = ''
echo "Running lingui"
./node_modules/.bin/lingui compile --typescript
echo building lib
./node_modules/.bin/tsc --p ./tsconfig.lib.json
./node_modules/.bin/vite --config vite.lib.config.ts build
echo "Running tsc"
./node_modules/.bin/tsc
echo "Running vite"
./node_modules/.bin/vite build --emptyOutDir --outDir $out
'';
};
in
python3.pkgs.buildPythonApplication rec {
pname = "InvenTree";
inherit version src;
format = "other";
dependencies =
with python3.pkgs;
[
coreapi
cryptography
distutils
dj-rest-auth
django
django-allauth
django-allauth.optional-dependencies.openid
django-allauth.optional-dependencies.mfa
django-allauth.optional-dependencies.socialaccount
django-cleanup
django-cors-headers
django-dbbackup
django-error-report-2
django-filter
django-flags
django-formtools
django-ical
django-js-asset
django-maintenance-mode
django-markdownify
django-money
django-mptt
django-mailbox
django-anymail
django-redis
django-oauth-toolkit
django-otp
django-q-sentry
django-q2
django-redis
django-sesame
django-sql-utils
django-structlog
django-stdimage
django-taggit
django-user-sessions
django-weasyprint
djangorestframework
djangorestframework-simplejwt
djangorestframework-simplejwt.optional-dependencies.crypto
django-xforwardedfor-middleware
django-storages
drf-spectacular
dulwich
feedparser
gunicorn
pdf2image
pillow
pint
pip-licenses
pypdf
python-barcode
python-barcode.optional-dependencies.images
python-dotenv
pyyaml
qrcode
qrcode.optional-dependencies.pil
rapidfuzz
sentry-sdk
tablib
tablib.optional-dependencies.xls
tablib.optional-dependencies.xlsx
tablib.optional-dependencies.yaml
weasyprint
whitenoise
psycopg2
fido2
opentelemetry-api
opentelemetry-sdk
opentelemetry-exporter-otlp
opentelemetry-instrumentation-django
opentelemetry-instrumentation-requests
opentelemetry-instrumentation-redis
opentelemetry-instrumentation-sqlite3
opentelemetry-instrumentation-system-metrics
opentelemetry-instrumentation-wsgi
]
++ django-anymail.optional-dependencies.amazon-ses;
installPhase = ''
substituteInPlace src/backend/InvenTree/InvenTree/settings.py --replace-fail "django_slowtests.testrunner.DiscoverSlowestTestsRunner" "django.test.runner.DiscoverRunner"
mkdir -p $out/opt/inventree
cp -r . $out/opt/inventree
echo "Installing frontend"
mkdir -p $out/opt/inventree/src/backend/InvenTree/web/static/web
cp -r ${frontend}/* $out/opt/inventree/src/backend/InvenTree/web/static/web/
cp -r ${frontend}/.* $out/opt/inventree/src/backend/InvenTree/web/static/web/
'';
passthru = {
pythonPath = python3.pkgs.makePythonPath dependencies;
gunicorn = python3.pkgs.gunicorn;
inherit frontend;
};
}

Some files were not shown because too many files have changed in this diff Show More