Compare commits

..
Author SHA1 Message Date
kurogeek 9ddef2b268 mob next [ci-skip] [ci skip] [skip ci]
lastFile:machines/vega/services/ups.nix
2025-09-25 17:28:59 +07:00
kurogeek c102be10c6 Update vars via generator ups for machine vega 2025-09-25 17:18:52 +07:00
1812 changed files with 1473 additions and 74283 deletions

No files matched your search

+1 -2
View File
@@ -2,5 +2,4 @@
# Ignore build outputs from performing a nix-build or `nix build` command
result
result-*
run-vm-*
.nixos-test-history
Generated
+35 -977
View File
File diff suppressed because it is too large. Load diff
+1 -81
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";
@@ -21,53 +15,12 @@
inputs.nixpkgs-lib.follows = "nixpkgs";
url = "github:hercules-ci/flake-parts";
};
home-manager = {
inputs.nixpkgs.follows = "nixpkgs";
url = "github:nix-community/home-manager";
};
plasma-manager = {
url = "github:nix-community/plasma-manager";
inputs.nixpkgs.follows = "nixpkgs";
inputs.home-manager.follows = "home-manager";
};
import-tree.url = "github:vic/import-tree";
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
liminix = {
url = "git+https://gti.telent.net/dan/liminix";
flake = false;
};
frappix = {
url = "github:kurogeek/frappix";
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";
};
matthew-hardware = {
url = "git+https://codeberg.org/matthewcroughan/matthew-hardware?ref=mc/wip";
inputs.flake-parts.follows = "flake-parts";
inputs.nixpkgs.follows = "nixpkgs";
inputs.disko.follows = "clan-core/disko";
};
# `router` clan service (site gateway: PPPoE, VLAN bridge, Kea/Blocky,
# nftables). Consumed via `module.input = "cnx-network"` in inventories/router.nix.
cnx-network = {
url = "git+https://git.b4l.co.th/B4L/cnx-network-clan";
inputs.clan-core.follows = "clan-core";
inputs.nixpkgs.follows = "nixpkgs";
inputs.flake-parts.follows = "flake-parts";
inputs.treefmt-nix.follows = "treefmt-nix";
};
};
outputs =
{
@@ -84,43 +37,10 @@
./fmt.nix
./shell.nix
./overlays
./machines
./routers
./inventories
./overlays
./tests
./modules/clan/flake-module.nix
./modules/nixos/flake-module.nix
];
perSystem =
{ pkgs, system, ... }:
{
_module.args.pkgs = import inputs.nixpkgs {
inherit system;
overlays = [
inputs.self.overlays.packagesOverlay
];
config = { };
};
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;
};
}
);
}
+62 -503
View File
@@ -1,264 +1,53 @@
{
imports = [
./personal-computer.nix
./emmie.nix
./router.nix
];
inputs,
self,
lib,
pkgs,
...
}:
{
clan = {
inventory = {
machines = {
rigel.deploy.targetHost = "root@rigel.local";
vega.deploy.targetHost = "root@vega.local";
};
tags = {
glom = [
"vega"
"ramus"
"canopus"
];
poy = [
"deneb"
"bosona"
];
w = [
"sirius"
"stellio"
];
b4l = [
"rigel"
"rana"
"petra"
"alasia"
];
phonebox = [
"rigel"
"almach"
"alpheratz"
"mirach"
"adhil"
"buna"
];
prometheus = [
"cursa"
"rigel"
"vega"
"buna"
];
dm-bootstrapper = [
"rigel"
"cursa"
"deneb"
"bosona"
"canopus"
];
dm-pull-deploy = [
"rana"
"rigel"
"vega"
];
glom = [ "vega" ];
b4l = [ "rigel" ];
};
instances = {
borgbackup = {
admin = {
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/per-machine/cursa/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/per-machine/hadar/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/per-machine/procyon/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/per-machine/bosona/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/per-machine/canopus/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/per-machine/deneb/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/per-machine/alasia/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 = [ "dm-pull-deploy" ];
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";
"kurogeek" =
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEcZ/p1Ofa9liwIzPWzNtONhJ7+FUWd2lCz33r81t8+w kurogeek@kurogeek";
"matthewcroughan" =
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIOJDRQfb1+7VK5tOe8W40iryfBWYRO6Uf1r2viDjmsJtAAAABHNzaDo=";
"matthewcroughan-1" =
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIDgsWq+G/tcr6eUQYT7+sJeBtRmOMabgFiIgIV44XNc6AAAABHNzaDo=";
"matthewcroughan-2" =
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJMi3TAuwDtIeO4MsORlBZ31HzaV5bji1fFBPcC9/tWuAAAABHNzaDo=";
};
};
};
root-password = {
module = {
name = "users";
name = "admin";
input = "clan-core";
};
roles.default.tags."all" = { };
roles.default.settings = {
user = "root";
roles.default.settings.allowedKeys = {
"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" =
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIOJDRQfb1+7VK5tOe8W40iryfBWYRO6Uf1r2viDjmsJtAAAABHNzaDo=";
"matthewcroughan-1" =
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIDgsWq+G/tcr6eUQYT7+sJeBtRmOMabgFiIgIV44XNc6AAAABHNzaDo=";
"matthewcroughan-2" =
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJMi3TAuwDtIeO4MsORlBZ31HzaV5bji1fFBPcC9/tWuAAAABHNzaDo=";
};
};
tor = {
module = {
name = "tor";
input = "clan-core";
};
roles.server.tags."nixos" = { };
};
w-network = {
module = {
name = "zerotier";
input = "clan-core";
};
roles.controller.machines."sirius" = {
settings.allowedIps = [
#kurogeek
"fdfe:7bf:a795:4524:4c99:932b:d36d:b8cc"
];
};
roles.peer.tags.w = { };
};
glom-network = {
module = {
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 = { };
};
@@ -267,304 +56,74 @@
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 = { };
};
poy-network = {
pocket-id = {
module = {
name = "zerotier";
input = "clan-core";
};
roles.controller.machines."deneb" = {
settings.allowedIps = [
#kurogeek
"fdfe:7bf:a795:4524:4c99:932b:d36d:b8cc"
];
};
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.settings.extraPeers = [
"tls://133.18.201.69:54232"
"tls://153.120.42.137:54232"
"tcp://yg-sin.magicum.net:23901"
"tls://asia.deinfra.org:15015"
"tls://ygg5.mk16.de:1338?key=0000009611ae5391dc0aceea9f3fa6a0dc1279f4306059339e84bfb8b74d2f9b"
"tcp://leo.node.3dt.net:9002"
"tcp://ygg-kcmo.incognet.io:8883"
"tls://23.184.48.86:1443"
"tls://192.3.13.16:8118"
"tls://ygg-pa.incognet.io:8884"
"tls://mo.us.ygg.triplebit.org:993"
];
};
newedge-headscale = {
module = {
name = "headscale";
name = "pocket-id";
input = "self";
};
roles.server.machines."alasia".settings = {
public_url = "tailvpn.public.newedge.house";
advertise_routes = [ "10.0.10.0/24" ];
dns = {
magic_dns = true;
base_domain = "tailvpn.newedge.house";
nameservers = [
"10.0.10.82"
"1.1.1.1"
"8.8.8.8"
];
extra_records = [
{
name = "poyerp.newedge.house";
type = "A";
value = "10.0.10.1";
}
{
name = "glomerp.newedge.house";
type = "A";
value = "10.0.10.1";
}
];
};
};
roles.default.machines.b4l = { };
};
phonebox = {
nextcloud = {
module = {
name = "phonebox";
name = "nextcloud";
input = "self";
};
roles.default.tags."phonebox" = { };
roles.default.machines."adhil".settings = {
ata-ethernet-iface = "end0";
};
roles.default.machines."rigel".settings = {
extraClientNumbers = [
"01"
"02"
];
extraFixedIPClient = { };
};
roles.default.machines.b4l = { };
roles.default.machines.vega = { };
};
pulse-stream = {
stirling-pdf = {
module = {
name = "pulse-stream";
name = "stirling-pdf";
input = "self";
};
roles.default.machines.neptune = {
settings.client-ip-ranges = [
"10.0.0.0/24"
];
};
roles.default.machines.b4l = { };
};
jukebox = {
actual-budget = {
module = {
name = "jukebox";
name = "actual-budget";
input = "self";
};
roles.default.machines.neptune = {
settings = {
binds = [ "wlp1s0" ];
disks.m3 = {
uuid = "105D-319E";
mountOptions = [ "utf8" ];
};
};
};
roles.default.machines.b4l = { };
};
git-daemon = {
victoriametrics = {
module = {
name = "git-daemon";
name = "victoriametrics";
input = "self";
};
roles.default.machines.neptune = {
settings.repositories =
let
defaults = rec {
write-access = [
"10.0.0.0/24"
"200:d7b1:c5d5:ea7:27ad:6837:40f6:404d/128"
];
read-access = write-access;
};
PUBLIC = {
read-access = [
"10.0.0.0/24"
"0200::/7"
];
};
in
builtins.mapAttrs (_: override: defaults // override) {
"9e" = PUBLIC;
archive-dl = { };
barrytown = { };
cleanroom = PUBLIC;
community-memory = { };
eris = { };
ftdi-sd-spi = { };
go-go-gadget = { };
hacking-the-kindle = { };
islands = PUBLIC;
kt = { };
legba = { };
llb = PUBLIC;
llc = PUBLIC;
lora = { };
mute = { };
navi = { };
notmuch-memoryhole = PUBLIC;
pms5003 = { };
thinc = PUBLIC;
toad = { };
yggdrasil-erlang = { };
};
};
roles.default.machines.b4l = { };
};
samba = {
vikunja = {
module = {
name = "samba";
name = "vikunja";
input = "self";
};
roles.server.machines."sirius".settings = {
globalUsers = {
w.writePerm = true;
};
sharedFolders = {
WHITEHOUSE = {
allowedGuest = true;
};
};
dataDir = "/mnt/hdd/samba";
};
roles.default.machines.b4l = { };
};
wordpress = {
grafana = {
module = {
name = "wordpress";
name = "grafana";
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);
'';
};
roles.default.machines.b4l = { };
};
prometheus-monitoring = {
pingvin = {
module = {
name = "prometheus";
name = "pingvin";
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 = { };
};
buna.settings = {
exporters.smartctl = { };
};
mirach.settings = {
exporters.smartctl = { };
};
almach.settings = {
exporters.smartctl = { };
};
stellio.settings.exporters.smartctl = { };
};
roles.default.machines.b4l = { };
};
wifi =
let
networks = {
home = { };
glom = { };
};
in
{
module.name = "wifi";
module.input = "clan-community";
roles.default = {
machines."buna".settings = { inherit networks; };
extraModules = [
(
{ lib, ... }:
{
# profile names match the network attr names above;
# 0 = retry forever for both (defaults: 4 autoconnect attempts, 3 auth attempts)
networking.networkmanager.ensureProfiles.profiles = lib.mapAttrs (_: _: {
connection.autoconnect-retries = 0;
connection.auth-retries = 0;
}) networks;
}
)
];
};
paperless = {
module = {
name = "paperless";
input = "self";
};
roles.default.machines.b4l = { };
};
};
};
};
-43
View File
@@ -1,43 +0,0 @@
{ config, ... }:
let
username = "emmie";
userhome = "/home/${username}";
in
{
clan.inventory = {
tags = {
emmie = [ "rana" ];
};
instances = {
emmie-syncthing = {
module = {
name = "syncthing";
input = "clan-core";
};
roles.peer.tags.emmie = { };
roles.peer.settings = {
folders = {
Syncthing.path = "${userhome}/Share/Syncthing";
Desktop.path = "${userhome}/Desktop";
};
extraDevices = {
pixel7a = {
id = "CEUJMEG-SOHXIJF-G2FT5QB-6MZW3EN-PONI3QN-HPEIOSU-IMSLGW7-XUU6BQK";
name = "eris";
addresses = [ "dynamic" ];
};
};
};
roles.peer.extraModules = [
{
config.services.syncthing = {
user = username;
dataDir = "${userhome}/Share";
};
}
];
};
};
};
}
-50
View File
@@ -1,50 +0,0 @@
{
clan.inventory = {
tags = {
kde-desktop = [
"rana"
"petra"
];
personal-computer = [
"rana"
"petra"
];
};
instances = {
emmie-home = {
module = {
name = "emmie-home";
input = "self";
};
roles.default.machines."rana" = { };
};
chocolate-home = {
module = {
name = "home-user";
input = "self";
};
roles.default.settings = {
username = "chocolate";
kbLayout = "us,th";
kbOptions = "grp:win_space_toggle,grp:alt_shift_toggle";
};
roles.default.machines."petra" = { };
};
personal-computer = {
module = {
name = "personal-computer";
input = "self";
};
roles.default.tags."personal-computer" = { };
};
kde = {
module = {
name = "kde";
input = "clan-core";
};
roles.default.tags."kde-desktop" = { };
};
};
};
}
-91
View File
@@ -1,91 +0,0 @@
# Site gateways: the `router` clan service from cnx-network-clan (see
# flake.nix input `cnx-network`, and that repo's modules/clan/router/README.md).
# One instance for the fleet; each site adds its gateway machine with the
# site's port / VLAN layout. `clan vars generate <gw>` then prompts for the
# PPPoE username/password.
{ lib, ... }:
let
# Admin mesh = the site's ZeroTier network. The service only opens SSH,
# metrics and iperf3 to this prefix, so the gateway must also be a peer of
# the same network (tag membership in default.nix). Prefix derivation as in
# cnx-network's modules/mesh-hosts.nix: fd + 8-byte network id + 0x9993,
# /88 covers every peer.
meshSubnet =
instance:
let
networkId = lib.fileContents ../vars/shared/zerotier-network-${instance}/network-id/value;
full = "fd" + networkId + "9993";
hextet = i: builtins.substring (i * 4) 4 full;
in
"${hextet 0}:${hextet 1}:${hextet 2}:${hextet 3}:${hextet 4}:${builtins.substring 20 2 full}00::/88";
in
{
clan.inventory.instances.router = {
module = {
name = "router";
input = "cnx-network";
};
roles.default.settings.mesh.subnet = meshSubnet "w-network";
# stellio: GL.iNet Flint 2 (GL-MT6000, MT7986a). Ports as named by the
# device tree in matthew-hardware: eth1 = the 2.5G "WAN" port, lan1 = the
# 2.5G LAN port, lan2-lan5 = the 1G LAN ports (DSA on the MT7531 switch).
roles.default.machines.stellio.settings = {
site = "white-house";
siteId = 8;
# PPPoE on the ISP's VLAN 10, as on the liminix router it replaces
# (routers/white-house); set to null if the ISP runs PPPoE untagged.
wan.interface = "end1";
wan.vlanId = 10;
# lan1 (2.5G): untagged mgmt port for on-site recovery. lan2-lan4 (1G):
# untagged client ports on lan. lan5 is the pre-cutover staging uplink:
# DHCP client into the old LAN (routers/white-house), SSH only, no VLAN
# membership; set stagingPort = null at cutover.
accessPorts = {
lan1 = "mgmt";
lan2 = "lan";
lan3 = "lan";
lan4 = "lan";
};
stagingPort = "lan5";
# Both MT7976 radios serve lan as an untagged access port, one SSID per
# band named like the GL-AR750 it stands in for ("GL-AR750" on 2.4 GHz,
# "GL-AR750-5" on 5 GHz) so clients roam over unchanged. Passphrases
# are the `wifi-GL-AR750-passphrase` / `wifi-GL-AR750-5-passphrase`
# vars prompts. Channels as on the old router. Check the band mapping
# with `iw phy` (mt7986: phy0/wlan0 = 2.4 GHz, phy1/wlan1 = 5 GHz).
wifi = {
enable = true;
countryCode = "TH";
networks = {
"GL-AR750".vlan = "lan";
"GL-AR750-5".vlan = "lan";
};
radios = {
wlan0 = {
band = "2g";
channel = 2;
wifi6 = true;
networks = [ "GL-AR750" ];
};
wlan1 = {
band = "5g";
channel = 36;
wifi6 = true;
networks = [ "GL-AR750-5" ];
};
};
};
# 10.1.<id>.0/24, router .1, DHCP pool .100-.199.
vlans = {
mgmt.id = 10;
lan.id = 20;
};
};
};
}
+1 -58
View File
@@ -1,58 +1 @@
{
"machines": {
"ramus": {
"installedAt": 1764139649
},
"alpheratz": {
"installedAt": 1764741499
},
"mirach": {
"installedAt": 1764744666
},
"almach": {
"installedAt": 1764745787
},
"neptune": {
"installedAt": 1762147067
},
"adhil": {
"installedAt": 1765277591
},
"buna": {
"installedAt": 1787123510
},
"rana": {
"installedAt": 1773134236
},
"petra": {
"installedAt": 1769064458
},
"sirius": {
"installedAt": 1770974584
},
"deneb": {
"installedAt": 1775718970
},
"canopus": {
"installedAt": 1775793532
},
"hadar": {
"installedAt": 1774427255
},
"procyon": {
"installedAt": 1775458442
},
"alasia": {
"installedAt": 1793077313
},
"bosona": {
"installedAt": 1779098893
},
"tangra": {
"installedAt": 1779958921
},
"cursa": {
"installedAt": 1782187627
}
}
}
{}
-14
View File
@@ -1,14 +0,0 @@
{ ... }:
{
nixpkgs.hostPlatform = {
system = "aarch64-linux";
};
system.stateVersion = "25.11";
clan.core.sops.defaultGroups = [ "admins" ];
# clan.core.networking.targetHost = "root@";
clan.core.settings.name = "adhil";
clan.core.settings.machine.description =
"Raspberry Pi 4 SBC board for one of w phone network. (With w office)";
}
-56
View File
@@ -1,56 +0,0 @@
{ ... }:
let
hashDisk = disk: "os-${builtins.substring 0 5 (builtins.hashString "sha256" disk)}";
os = "/dev/disk/by-id/mmc-SD64G_0xfb330ff6";
in
{
boot.loader = {
systemd-boot = {
enable = true;
};
efi = {
canTouchEfiVariables = true;
};
};
disko.devices = {
disk = {
"os-${hashDisk os}" = {
type = "disk";
device = os;
content = {
type = "gpt";
partitions = {
ESP = {
end = "500M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
root = {
name = "root";
end = "-0";
content = {
type = "filesystem";
format = "f2fs";
mountpoint = "/";
extraArgs = [
"-O"
"extra_attr,inode_checksum,sb_checksum,compression"
];
mountOptions = [
"compress_algorithm=zstd:6,compress_chksum,atgc,gc_merge,lazytime,nodiscard"
];
};
};
};
};
};
};
};
}
File diff suppressed because it is too large. Load diff
-15
View File
@@ -1,15 +0,0 @@
{
clan.core.settings.machine.description = "VM machine to host headplane instance";
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
networking.firewall.allowedTCPPorts = [
80
443
];
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 = false;
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
-13
View File
@@ -1,13 +0,0 @@
{ config, ... }:
{
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
system.stateVersion = "25.11";
clan.core.sops.defaultGroups = [ "admins" ];
# clan.core.networking.targetHost = "root@";
clan.core.settings.name = "almach";
clan.core.settings.machine.description = "Radxa X4 SBC board for one of w phone network.";
}
-92
View File
@@ -1,92 +0,0 @@
{ ... }:
let
hashDisk = disk: "os-${builtins.substring 0 5 (builtins.hashString "sha256" disk)}";
os = "/dev/disk/by-id/mmc-CUTB42_0x95d64f17";
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";
};
};
swap = {
size = "4G";
content = {
type = "swap";
};
};
};
};
};
};
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
-13
View File
@@ -1,13 +0,0 @@
{ config, ... }:
{
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
system.stateVersion = "25.11";
clan.core.sops.defaultGroups = [ "admins" ];
# clan.core.networking.targetHost = "root@";
clan.core.settings.name = "alpheratz";
clan.core.settings.machine.description = "Radxa X4 SBC board for one of w phone network.";
}
-92
View File
@@ -1,92 +0,0 @@
{ ... }:
let
hashDisk = disk: "os-${builtins.substring 0 5 (builtins.hashString "sha256" disk)}";
os = "/dev/disk/by-id/mmc-CUTB42_0xaedcfa8b";
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";
};
};
swap = {
size = "4G";
content = {
type = "swap";
};
};
};
};
};
};
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
+22
View File
@@ -0,0 +1,22 @@
{ inputs, config, ... }:
{
imports = [
(inputs.import-tree ./services)
];
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
boot.loader.grub.devices = [ "/dev/disk/by-id/FIXME" ];
fileSystems = {
"/".device = "/dev/FIXME";
};
networking.fqdn = "b4l.co.th";
system.stateVersion = "25.11";
clan.core.sops.defaultGroups = [ "admins" ];
security.acme.defaults.email = "admin@b4l.co.th";
security.acme.acceptTerms = true;
services.nginx.virtualHosts."${config.networking.fqdn}" = {
enableACME = true;
};
}
+36
View File
@@ -0,0 +1,36 @@
{ config, ... }:
let
abDomain = "${config.clan.core.vars.generators.b4l-actual-budget.files.subdomain.value}.${config.networking.fqdn}";
in
{
clan.core.vars.generators.b4l-actual-budget = {
files.subdomain.secret = false;
prompts = {
subdomain = {
persist = true;
type = "line";
description = "Sub-domain for Actual Budget app. Default:(budget)";
};
};
script = ''cat $prompts/subdomain || echo -n "budget" > $out/subdomain'';
};
services.actual = {
settings = {
allowedLoginMethods = [
"password"
"openid"
];
trustedProxies = [ "127.0.0.1" ];
};
};
services.nginx.virtualHosts."${abDomain}" = {
useACMEHost = "${config.networking.fqdn}";
forceSSL = true;
locations."/" = {
proxyPass = "http://localhost:${builtins.toString config.services.actual.settings.port}";
};
};
}
+79
View File
@@ -0,0 +1,79 @@
{
pkgs,
config,
lib,
...
}:
with lib;
let
serviceName = "${config.networking.hostName}-grafana";
gfDomain = "${
config.clan.core.vars.generators."${serviceName}".files.subdomain.value
}.${config.networking.fqdn}";
settingsFormatIni = pkgs.formats.ini {
listToValue = concatMapStringsSep " " (generators.mkValueStringDefault { });
mkKeyValue = generators.mkKeyValueDefault {
mkValueString = v: if v == null then "" else generators.mkValueStringDefault { } v;
} "=";
};
configFile = settingsFormatIni.generate "config.ini" config.services.grafana.settings;
in
{
clan.core.vars.generators."${serviceName}" = {
files = {
adminpassword.secret = true;
subdomain.secret = false;
};
prompts = {
subdomain = {
persist = true;
type = "line";
description = "Sub-domain for Grafana. Default:(grafana)";
};
adminpassword = {
persist = true;
type = "hidden";
description = "Password for the admin user. Leave empty to auto-generate.";
};
};
runtimeInputs = [
pkgs.xkcdpass
pkgs.coreutils
];
script = ''
prompt_domain=$(cat "$prompts"/subdomain)
if [[ -n "''${prompt_domain-}" ]]; then
echo $prompt_domain | tr -d "\n" > "$out"/subdomain
else
echo -n "grafana" > "$out"/subdomain
fi
prompt_password=$(cat "$prompts"/adminpassword)
if [[ -n "''${prompt_password-}" ]]; then
echo "$prompt_password" | tr -d "\n" > "$out"/adminpassword
else
xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/adminpassword
fi
'';
};
systemd.services.grafana.serviceConfig.ExecStartPre = [
"+${pkgs.writeShellScript "grafana-set-password" ''
${pkgs.grafana}/bin/grafana cli --homepath ${config.services.grafana.dataDir} --config ${configFile} admin reset-admin-password $(cat ${
config.clan.core.vars.generators."${serviceName}".files.adminpassword.path
})
''}"
];
services.nginx.virtualHosts."${gfDomain}" = {
forceSSL = true;
useACMEHost = "${config.networking.fqdn}";
locations."/" = {
proxyPass = "http://localhost:${builtins.toString config.services.grafana.settings.server.http_port}";
};
};
}
+35
View File
@@ -0,0 +1,35 @@
{ config, pkgs, ... }:
let
ncDomain = "${config.clan.core.vars.generators.b4l-nextcloud.files.subdomain.value}.${config.networking.fqdn}";
in
{
clan.core.vars.generators.b4l-nextcloud = {
files.subdomain.secret = false;
prompts = {
subdomain = {
persist = true;
type = "line";
description = "Sub-domain for Nextcloud app. Default:(cloud)";
};
};
script = ''cat $prompts/subdomain || echo -n "cloud" > $out/subdomain'';
};
services.nextcloud = {
hostName = ncDomain;
package = pkgs.nextcloud31;
settings = {
overwriteprotocol = "https";
trusted_domains = [ ];
trusted_proxies = [ ];
};
};
services.nginx.virtualHosts."${ncDomain}" = {
useACMEHost = "${config.networking.fqdn}";
forceSSL = true;
};
}
+67
View File
@@ -0,0 +1,67 @@
{ config, pkgs, ... }:
let
serviceName = "${config.networking.hostName}-paperless";
domain-name = "${
config.clan.core.vars.generators."${serviceName}".files.subdomain.value
}.${config.networking.fqdn}";
in
{
clan.core.vars.generators."${serviceName}" = {
files = {
subdomain.secret = false;
adminpassword = {
secret = true;
owner = config.services.paperless.user;
group = config.services.paperless.user;
};
};
prompts = {
subdomain = {
persist = true;
type = "line";
description = "Sub-domain for Paperless. Default:(paperless)";
};
adminpassword = {
persist = true;
type = "hidden";
description = "Password for the admin user. Leave empty to auto-generate.";
};
};
runtimeInputs = [
pkgs.xkcdpass
pkgs.coreutils
];
script = ''
prompt_domain=$(cat "$prompts"/subdomain)
if [[ -n "''${prompt_domain-}" ]]; then
echo $prompt_domain | tr -d "\n" > "$out"/subdomain
else
echo -n "paperless" > "$out"/subdomain
fi
prompt_password=$(cat "$prompts"/adminpassword)
if [[ -n "''${prompt_password-}" ]]; then
echo "$prompt_password" | tr -d "\n" > "$out"/adminpassword
else
xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/adminpassword
fi
'';
};
environment.systemPackages = [ pkgs.toybox ];
services.paperless = {
passwordFile = config.clan.core.vars.generators."${serviceName}".files.adminpassword.path;
};
services.nginx.virtualHosts."${domain-name}" = {
forceSSL = true;
useACMEHost = "${config.networking.fqdn}";
locations."/" = {
proxyPass = "http://localhost:${builtins.toString config.services.paperless.port}";
};
};
}
+45
View File
@@ -0,0 +1,45 @@
{
pkgs,
config,
...
}:
let
serviceName = "${config.networking.hostName}-pingvin";
domain-name = "${
config.clan.core.vars.generators."${serviceName}".files.subdomain.value
}.${config.networking.fqdn}";
in
{
clan.core.vars.generators."${serviceName}" = {
files = {
subdomain.secret = false;
};
prompts = {
subdomain = {
persist = true;
type = "line";
description = "Sub-domain for Pingvin. Default:(share)";
};
};
runtimeInputs = [
pkgs.xkcdpass
pkgs.coreutils
];
script = ''
prompt_domain=$(cat "$prompts"/subdomain)
if [[ -n "''${prompt_domain-}" ]]; then
echo $prompt_domain | tr -d "\n" > "$out"/subdomain
else
echo -n "share" > "$out"/subdomain
fi
'';
};
services.pingvin-share = {
nginx.enable = true;
https = true;
hostname = domain-name;
};
}
+35
View File
@@ -0,0 +1,35 @@
{ config, ... }:
let
pidDomain = "${config.clan.core.vars.generators.b4l-pocket-id.files.subdomain.value}.${config.networking.fqdn}";
in
{
clan.core.vars.generators.b4l-pocket-id = {
files.subdomain.secret = false;
prompts = {
subdomain = {
persist = true;
type = "line";
description = "Sub-domain for Pocket-ID app. Default:(auth)";
};
};
script = ''cat $prompts/subdomain || echo -n "auth" > $out/subdomain'';
};
services.pocket-id = {
settings = {
APP_ENV = "production";
APP_URL = "https://${pidDomain}";
TRUST_PROXY = true;
};
};
services.nginx.virtualHosts."${pidDomain}" = {
useACMEHost = "${config.networking.fqdn}";
forceSSL = true;
locations."/" = {
proxyPass = "http://localhost:${builtins.toString config.services.pocket-id.settings.PORT}";
};
};
}
+26
View File
@@ -0,0 +1,26 @@
{ config, ... }:
let
stDomain = "${config.clan.core.vars.generators.b4l-stirling-pdf.files.subdomain.value}.${config.networking.fqdn}";
in
{
clan.core.vars.generators.b4l-stirling-pdf = {
files.subdomain.secret = false;
prompts = {
subdomain = {
persist = true;
type = "line";
description = "Sub-domain for Stirling PDF app. Default:(pdf)";
};
};
script = ''cat $prompts/subdomain || echo -n "pdf" > $out/subdomain'';
};
services.nginx.virtualHosts."${stDomain}" = {
forceSSL = true;
useACMEHost = "${config.networking.fqdn}";
locations."/" = {
proxyPass = "http://localhost:${builtins.toString config.services.stirling-pdf.environment.SERVER_PORT}";
};
};
}
+73
View File
@@ -0,0 +1,73 @@
{ config, pkgs, ... }:
let
vmDomain = "${config.clan.core.vars.generators.b4l-victoriametrics.files.subdomain.value}.${config.networking.fqdn}";
in
{
clan.core.vars.generators.b4l-victoriametrics = {
files.subdomain.secret = false;
files.adminuser.secret = false;
files.adminpassword.secret = true;
prompts = {
subdomain = {
persist = true;
type = "line";
description = "Sub-domain for Victoria Metrics app. Default:(metrics)";
};
adminuser = {
persist = true;
type = "line";
description = "Username for an admin user. Default:(admin)";
};
adminpassword = {
persist = true;
type = "hidden";
description = "Password for the admin user. Leave empty to auto-generate.";
};
};
runtimeInputs = [
pkgs.xkcdpass
pkgs.coreutils
];
script = ''
prompt_domain=$(cat "$prompts"/subdomain)
if [[ -n "''${prompt_domain-}" ]]; then
echo $prompt_domain | tr -d "\n" > "$out"/subdomain
else
echo -n "metrics" > "$out"/subdomain
fi
prompt_adminuser=$(cat "$prompts"/adminuser)
if [[ -n "''${prompt_adminuser-}" ]]; then
echo $prompt_adminuser | tr -d "\n" > "$out"/adminuser
else
echo -n "admin" > "$out"/adminuser
fi
prompt_password=$(cat "$prompts"/adminpassword)
if [[ -n "''${prompt_password-}" ]]; then
echo "$prompt_password" | tr -d "\n" > "$out"/adminpassword
else
xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/adminpassword
fi
'';
};
services.victoriametrics = {
extraOptions = [
"-httpAuth.username=file://${config.clan.core.vars.generators.b4l-victoriametrics.files.adminuser.path}"
"-httpAuth.password=file://${config.clan.core.vars.generators.b4l-victoriametrics.files.adminpassword.path}"
];
};
services.nginx.virtualHosts."${vmDomain}" = {
forceSSL = true;
useACMEHost = "${config.networking.fqdn}";
locations."/" = {
proxyPass = "http://localhost${builtins.toString config.services.victoriametrics.listenAddress}";
};
};
}
+26
View File
@@ -0,0 +1,26 @@
{ config, ... }:
{
clan.core.vars.generators.b4l-vikunja = {
files.subdomain.secret = false;
prompts = {
subdomain = {
persist = true;
type = "line";
description = "Sub-domain for Vikunja todo app. Default:(todo)";
};
};
script = ''cat $prompts/subdomain || echo "todo" > $out/subdomain'';
};
services.vikunja = {
frontendHostname = "${config.clan.core.vars.generators.b4l-vikunja.files.subdomain.value}.${config.networking.fqdn}";
};
services.nginx.virtualHosts."${config.services.vikunja.frontendHostname}" = {
useACMEHost = "${config.networking.fqdn}";
forceSSL = true;
locations."/" = {
proxyPass = "${config.services.vikunja.frontendScheme}://${config.services.vikunja.frontendHostname}:${builtins.toString config.services.vikunja.port}";
};
};
}
-107
View File
@@ -1,107 +0,0 @@
{
inputs,
pkgs,
config,
...
}:
let
sitename = "tempoerp.newedge.house";
in
{
clan.core.settings.machine.description = "VM machine that host ERPNext for tempo";
imports = [
inputs.frappix.nixosModules.x86_64-linux.frappix
];
nixpkgs.overlays = [
inputs.self.overlays.frappixFrappeOverlay
inputs.self.overlays.frappixLibsOverlay
inputs.self.overlays.frappixPythonOverlay
inputs.self.overlays.frappixToolsOverlay
inputs.self.overlays.posthogPr578265Overlay # TEMPORARY, see overlays/nixpkgs-pr-578265-posthog.nix
inputs.self.overlays.frappixFixupsOverlay
];
clan.core.vars.generators.frappix = {
files = {
sslCertificate.secret = false;
sslCertificateKey = {
owner = "nginx";
group = "nginx";
secret = true;
};
adminPassword.secret = true;
};
runtimeInputs = with pkgs; [
openssl
xkcdpass
];
script = ''
openssl req -x509 -newkey rsa:4096 -keyout $out/sslCertificateKey -out $out/sslCertificate -sha256 -days 3650 -nodes -subj "/C=TH/ST=ChiangMai/L=ChiangMai/O=kurogeek/CN=kurogeek.home"
xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/adminPassword
'';
};
services.frappe = {
enable = true;
project = "poyerp";
gunicorn_workers = 2;
adminPassword = config.clan.core.vars.generators.frappix.files.adminPassword.path;
apps = [
pkgs.frappix.erpnext
pkgs.frappix.hrms
pkgs.frappix.crm
];
sites = {
"${sitename}" = {
domains = [ sitename ];
apps = [
"frappe"
"erpnext"
"hrms"
"crm"
];
};
};
};
services.nginx.virtualHosts."${sitename}" = {
sslCertificate = config.clan.core.vars.generators.frappix.files.sslCertificate.path;
sslCertificateKey = config.clan.core.vars.generators.frappix.files.sslCertificateKey.path;
};
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
clan.core.vars.generators.nginx = {
files = {
sslCert = {
owner = "nginx";
group = "nginx";
secret = true;
};
sslKey = {
owner = "nginx";
group = "nginx";
secret = true;
};
};
runtimeInputs = [
pkgs.openssl
];
script = ''
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout $out/sslKey \
-out $out/sslCert \
-subj "/CN=localhost"
'';
};
networking.firewall.allowedTCPPorts = [
80
443
];
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
-14
View File
@@ -1,14 +0,0 @@
{ config, ... }:
{
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
system.stateVersion = "25.11";
clan.core.sops.defaultGroups = [ "admins" ];
# clan.core.networking.targetHost = "root@";
clan.core.settings.name = "buna";
clan.core.settings.machine.description =
"Radxa X4 SBC board for one of w phone network. (With w whitehouse)";
}
-56
View File
@@ -1,56 +0,0 @@
{ ... }:
let
hashDisk = disk: "os-${builtins.substring 0 5 (builtins.hashString "sha256" disk)}";
os = "/dev/disk/by-id/usb-Generic_MassStorageClass_000000001539-0:0";
in
{
boot.loader = {
systemd-boot = {
enable = true;
};
efi = {
canTouchEfiVariables = true;
};
};
disko.devices = {
disk = {
"os-${hashDisk os}" = {
type = "disk";
device = os;
content = {
type = "gpt";
partitions = {
ESP = {
end = "500M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
root = {
name = "root";
end = "-0";
content = {
type = "filesystem";
format = "f2fs";
mountpoint = "/";
extraArgs = [
"-O"
"extra_attr,inode_checksum,sb_checksum,compression"
];
mountOptions = [
"compress_algorithm=zstd:6,compress_chksum,atgc,gc_merge,lazytime,nodiscard"
];
};
};
};
};
};
};
};
}
File diff suppressed because it is too large. Load diff
-111
View File
@@ -1,111 +0,0 @@
{
inputs,
pkgs,
config,
...
}:
let
sitename = "glomerp.newedge.house";
nbClientName = "netbird-b4l";
in
{
clan.core.settings.machine.description = "VM machine that host ERPNext for glomglom";
imports = [ inputs.frappix.nixosModules.x86_64-linux.frappix ];
nixpkgs.overlays = [
inputs.self.overlays.frappixFrappeOverlay
inputs.self.overlays.frappixLibsOverlay
inputs.self.overlays.frappixPythonOverlay
inputs.self.overlays.frappixToolsOverlay
inputs.self.overlays.posthogPr578265Overlay # TEMPORARY, see overlays/nixpkgs-pr-578265-posthog.nix
inputs.self.overlays.frappixFixupsOverlay
];
clan.core.vars.generators.frappix = {
files = {
sslCertificate.secret = false;
sslCertificateKey = {
owner = "nginx";
group = "nginx";
secret = true;
};
adminPassword.secret = true;
};
runtimeInputs = with pkgs; [
openssl
xkcdpass
];
script = ''
openssl req -x509 -newkey rsa:4096 -keyout $out/sslCertificateKey -out $out/sslCertificate -sha256 -days 3650 -nodes -subj "/C=TH/ST=ChiangMai/L=ChiangMai/O=kurogeek/CN=kurogeek.home"
xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/adminPassword
'';
};
services.frappe = {
enable = true;
project = "glomerp";
gunicorn_workers = 2;
adminPassword = config.clan.core.vars.generators.frappix.files.adminPassword.path;
apps = [
pkgs.frappix.erpnext
pkgs.frappix.hrms
];
sites = {
"${sitename}" = {
domains = [ sitename ];
apps = [
"frappe"
"erpnext"
"hrms"
];
};
};
};
services.nginx.virtualHosts."${sitename}" = {
sslCertificate = config.clan.core.vars.generators.frappix.files.sslCertificate.path;
sslCertificateKey = config.clan.core.vars.generators.frappix.files.sslCertificateKey.path;
};
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
clan.core.vars.generators.nginx = {
files = {
sslCert = {
owner = "nginx";
group = "nginx";
secret = true;
};
sslKey = {
owner = "nginx";
group = "nginx";
secret = true;
};
};
runtimeInputs = [
pkgs.openssl
];
script = ''
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout $out/sslKey \
-out $out/sslCert \
-subj "/CN=localhost"
'';
};
networking.firewall.allowedTCPPorts = [
80
443
];
# 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" ];
}
-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
-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
+2 -14
View File
@@ -1,23 +1,11 @@
{
inputs,
self,
...
}:
{ inputs, self, ... }:
{
imports = [
inputs.clan-core.flakeModules.default
];
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"
-128
View File
@@ -1,128 +0,0 @@
{
inputs,
pkgs,
config,
...
}:
let
sitename = "poyerp.newedge.house";
in
{
clan.core.settings.machine.description = "VM machine that host ERPNext for poysound";
imports = [
inputs.frappix.nixosModules.x86_64-linux.frappix
# (import ../../lib/auto-accept-zerotier-members.nix {
# memberIds = [
# # Alex Caddy gateway
# "dbe44c0287"
# "e3d6559697"
# ];
# })
];
nixpkgs.overlays = [
inputs.self.overlays.frappixFrappeOverlay
inputs.self.overlays.frappixLibsOverlay
inputs.self.overlays.frappixPythonOverlay
inputs.self.overlays.frappixToolsOverlay
inputs.self.overlays.frappixAppsOverlay
inputs.self.overlays.posthogPr578265Overlay # TEMPORARY, see overlays/nixpkgs-pr-578265-posthog.nix
inputs.self.overlays.frappixFixupsOverlay
];
fonts.packages = [ pkgs.tlwg ];
clan.core.vars.generators.frappix = {
files = {
sslCertificate.secret = false;
sslCertificateKey = {
owner = "nginx";
group = "nginx";
secret = true;
};
adminPassword.secret = true;
};
runtimeInputs = with pkgs; [
openssl
xkcdpass
];
script = ''
openssl req -x509 -newkey rsa:4096 -keyout $out/sslCertificateKey -out $out/sslCertificate -sha256 -days 3650 -nodes -subj "/C=TH/ST=ChiangMai/L=ChiangMai/O=kurogeek/CN=kurogeek.home"
xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/adminPassword
'';
};
services.frappe = {
enable = true;
project = "poyerp";
gunicorn_workers = 2;
adminPassword = config.clan.core.vars.generators.frappix.files.adminPassword.path;
apps = [
pkgs.frappix.erpnext
pkgs.frappix.hrms
pkgs.frappix.crm
pkgs.frappix.posprinter
pkgs.frappix.default_thai_company
];
sites = {
"${sitename}" = {
domains = [ sitename ];
apps = [
"frappe"
"erpnext"
"hrms"
"crm"
"posprinter"
"default_thai_company"
];
};
};
};
services.nginx.virtualHosts."${sitename}" = {
sslCertificate = config.clan.core.vars.generators.frappix.files.sslCertificate.path;
sslCertificateKey = config.clan.core.vars.generators.frappix.files.sslCertificateKey.path;
};
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
clan.core.vars.generators.nginx = {
files = {
sslCert = {
owner = "nginx";
group = "nginx";
secret = true;
};
sslKey = {
owner = "nginx";
group = "nginx";
secret = true;
};
};
runtimeInputs = [
pkgs.openssl
];
script = ''
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout $out/sslKey \
-out $out/sslCert \
-subj "/CN=localhost"
'';
};
networking.firewall.allowedTCPPorts = [
80
443
];
# 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" ];
}
-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
-87
View File
@@ -1,87 +0,0 @@
{
inputs,
config,
pkgs,
...
}:
let
domain = "w-inventory.newedge.house";
in
{
clan.core.settings.machine.description = "VM machine that host Inventree system for Poy";
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
clan.core.vars.generators.inventree = {
files = {
secret-key = {
owner = "inventree";
group = "inventree";
secret = true;
};
oidc-key = {
owner = "inventree";
group = "inventree";
secret = true;
};
admin-password = {
owner = "inventree";
group = "inventree";
secret = true;
};
};
runtimeInputs = [
pkgs.pwgen
pkgs.xkcdpass
];
script = ''
pwgen -s 32 1 > $out/secret-key
pwgen -s 32 1 > $out/oidc-key
xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/admin-password
'';
};
clan.core.vars.generators.nginx = {
files = {
sslCert = {
owner = "nginx";
group = "nginx";
secret = true;
};
sslKey = {
owner = "nginx";
group = "nginx";
secret = true;
};
};
runtimeInputs = [
pkgs.openssl
];
script = ''
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout $out/sslKey \
-out $out/sslCert \
-subj "/CN=localhost"
'';
};
networking.firewall.allowedTCPPorts = [
80
443
];
services.inventree = {
enable = true;
inherit domain;
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}";
settings.INVENTREE_FRONTEND_SETTINGS = ''{"mobile_mode": "allow-ignore"}'';
};
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
-13
View File
@@ -1,13 +0,0 @@
{ config, ... }:
{
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
system.stateVersion = "25.11";
clan.core.sops.defaultGroups = [ "admins" ];
# clan.core.networking.targetHost = "root@";
clan.core.settings.name = "mirach";
clan.core.settings.machine.description = "Radxa X4 SBC board for one of w phone network.";
}
-92
View File
@@ -1,92 +0,0 @@
{ ... }:
let
hashDisk = disk: "os-${builtins.substring 0 5 (builtins.hashString "sha256" disk)}";
os = "/dev/disk/by-id/mmc-CUTB42_0x95d64f33";
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";
};
};
swap = {
size = "4G";
content = {
type = "swap";
};
};
};
};
};
};
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
-61
View File
@@ -1,61 +0,0 @@
{
inputs,
config,
lib,
...
}:
{
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
system.stateVersion = "25.11";
clan.core.sops.defaultGroups = [ "admins" ];
networking.interfaces.enx00e04c106368.useDHCP = true; # recovery
clan.core.vars.generators.wireless-credentials = {
files = {
essid.secret = false;
psk.secret = true;
};
prompts = {
essid.persist = true;
psk.persist = true;
};
script = ''
cat "$prompts"/essid > $out/essid
prompt_psk=$(cat "$prompts"/psk)
echo "psk=$prompt_psk" > $out/psk
'';
};
networking.wireless =
let
credentials = config.clan.core.vars.generators.wireless-credentials.files;
in
{
enable = true;
secretsFile = credentials.psk.path;
networks.${credentials.essid.value}.pskRaw = "ext:psk";
};
networking.interfaces.wlp1s0 = {
useDHCP = false;
ipv4.addresses = [
{
address = "10.0.0.9";
prefixLength = 24;
}
];
};
services.yggdrasil.settings.Peers = lib.mkForce [
"tcp://newt.barry.town:1337"
"tls://yg-hkg.magicum.net:32333"
"tls://astrra.space:55535"
];
clan.core.settings.name = "neptune";
clan.core.settings.machine.description = "Radxa SBC board for testing. (With vi)";
}
-92
View File
@@ -1,92 +0,0 @@
{ ... }:
let
hashDisk = disk: "os-${builtins.substring 0 5 (builtins.hashString "sha256" disk)}";
os = "/dev/disk/by-id/mmc-CUTB42_0x9d59499c";
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";
};
};
swap = {
size = "16G";
content = {
type = "swap";
};
};
};
};
};
};
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
-13
View File
@@ -1,13 +0,0 @@
{ self, ... }:
{
imports = [
self.nixosModules.common
];
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
system.stateVersion = "25.11";
clan.core.sops.defaultGroups = [ "admins" ];
clan.core.settings.machine.description = "A personal computer for Chocolate Shop";
}
-79
View File
@@ -1,79 +0,0 @@
{ ... }:
let
hashDisk = disk: "os-${builtins.substring 0 5 (builtins.hashString "sha256" disk)}";
os = "/dev/disk/by-id/ata-TOSHIBA_MQ01ABD100_85N8C2DPT";
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";
};
};
swap = {
size = "16G";
content = {
type = "swap";
};
};
};
};
};
};
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 = "/";
};
};
};
};
};
}
File diff suppressed because it is too large. Load diff
-86
View File
@@ -1,86 +0,0 @@
{
inputs,
config,
pkgs,
...
}:
let
domain = "glom-inventory.newedge.house";
in
{
clan.core.settings.machine.description = "VM machine that host Inventree system for Glom";
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
clan.core.vars.generators.inventree = {
files = {
secret-key = {
owner = "inventree";
group = "inventree";
secret = true;
};
oidc-key = {
owner = "inventree";
group = "inventree";
secret = true;
};
admin-password = {
owner = "inventree";
group = "inventree";
secret = true;
};
};
runtimeInputs = [
pkgs.pwgen
pkgs.xkcdpass
];
script = ''
pwgen -s 32 1 > $out/secret-key
pwgen -s 32 1 > $out/oidc-key
xkcdpass --numwords 4 --delimiter - --count 1 | tr -d "\n" > "$out"/admin-password
'';
};
clan.core.vars.generators.nginx = {
files = {
sslCert = {
owner = "nginx";
group = "nginx";
secret = true;
};
sslKey = {
owner = "nginx";
group = "nginx";
secret = true;
};
};
runtimeInputs = [
pkgs.openssl
];
script = ''
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout $out/sslKey \
-out $out/sslCert \
-subj "/CN=localhost"
'';
};
networking.firewall.allowedTCPPorts = [
80
443
];
services.inventree = {
enable = true;
inherit domain;
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}";
};
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
-32
View File
@@ -1,32 +0,0 @@
{ self, config, ... }:
{
system.stateVersion = "25.11";
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
clan.core.settings.name = "ramus";
clan.core.settings.machine.description = "A Hetzner VPS machine own by Alex.";
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 = [ ./think-greater-chiangmai.nix ];
}
-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_107266387";
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
-141
View File
@@ -1,141 +0,0 @@
{ self, config, ... }:
let
commonSettings = rec {
APP_NAME = "Laravel";
APP_ENV = "local";
APP_KEY._secret = config.clan.core.vars.generators.greaterchiangmai.files.app_key.path;
APP_DEBUG = "false";
APP_URL = "http://localhost";
DB_CONNECTION = "mysql";
DB_HOST = "localhost";
DB_PORT = 3306;
DB_DATABASE = "thinkgtcm";
DB_USERNAME = "gtcm";
R2_SCHEMA_URL = "https://${R2_BUCKET}.${R2_REGION}.your-objectstorage.com/test-large-files/";
R2_ACCESS_KEY_ID = config.clan.core.vars.generators.greaterchiangmai-s3.files.access_key_id.value;
R2_SECRET_ACCESS_KEY._secret =
config.clan.core.vars.generators.greaterchiangmai-s3.files.secret_access_key.path;
R2_REGION = config.clan.core.vars.generators.greaterchiangmai-s3.files.region.value;
R2_BUCKET = config.clan.core.vars.generators.greaterchiangmai-s3.files.bucket.value;
R2_ENDPOINT = config.clan.core.vars.generators.greaterchiangmai-s3.files.endpoint.value;
R2_BUCKET_NAME = R2_BUCKET;
LOG_CHANNEL = "stack";
LOG_LEVEL = "debug";
FILESYSTEM_DISK = "local";
BROADCAST_DRIVER = "log";
CACHE_DRIVER = "file";
QUEUE_CONNECTION = "sync";
SESSION_DRIVER = "file";
SESSION_LIFETIME = 120;
MEMCACHED_HOST = "127.0.0.1";
REDIS_HOST = "127.0.0.1";
REDIS_PORT = 6379;
UPLOAD_MAX_FILESIZE = "5000M";
POST_MAX_SIZE = "5000M";
TEST_LOCAL = true;
};
baseDomain = "greaterchiangmai.com";
domain = "think.${baseDomain}";
domainBackend = "think-backend.${baseDomain}";
in
{
imports = [
self.nixosModules.think-gtcm
self.nixosModules.think-backend-gtcm
];
nixpkgs.overlays = [
self.overlays.packagesOverlay
];
clan.core.vars.generators.greaterchiangmai = {
files = {
app_key = {
secret = true;
owner = config.services.think-greaterchiangmai.user;
group = config.services.think-greaterchiangmai.group;
};
};
prompts = {
app_key.persist = true;
};
script = ''
cat $prompts/app_key > $out/app_key
'';
};
clan.core.vars.generators.greaterchiangmai-s3 = {
files = {
access_key_id.secret = false;
secret_access_key = {
secret = true;
owner = config.services.think-greaterchiangmai.user;
group = config.services.think-greaterchiangmai.group;
};
endpoint.secret = false;
region.secret = false;
bucket.secret = false;
};
prompts = {
access_key_id.persist = true;
secret_access_key.persist = true;
endpoint.persist = true;
region.persist = true;
bucket.persist = true;
};
script = ''
cat $prompts/access_key_id > $out/access_key_id
cat $prompts/secret_access_key > $out/secret_access_key
cat $prompts/endpoint > $out/endpoint
cat $prompts/region > $out/region
cat $prompts/bucket > $out/bucket
'';
};
services.think-greaterchiangmai = {
enable = true;
domain = domain;
settings = commonSettings;
};
services.think-backend-greaterchiangmai = {
enable = true;
domain = domainBackend;
settings = commonSettings;
};
security.acme.certs = {
"${domain}" = {
email = config.clan.core.vars.generators.acme.files.email.value;
webroot = "/var/lib/acme/acme-challenge/${domain}";
};
"${domainBackend}" = {
email = config.clan.core.vars.generators.acme.files.email.value;
webroot = "/var/lib/acme/acme-challenge/${domainBackend}";
};
};
services.nginx.virtualHosts.${domain} = {
forceSSL = true;
useACMEHost = domain;
acmeRoot = config.security.acme.certs.${domain}.webroot;
};
services.nginx.virtualHosts.${domainBackend} = {
forceSSL = true;
useACMEHost = domainBackend;
acmeRoot = config.security.acme.certs.${domainBackend}.webroot;
};
}
-22
View File
@@ -1,22 +0,0 @@
{ self, pkgs, ... }:
{
clan.core.settings.machine.description = "Emmie personal computer";
imports = [
self.nixosModules.common
];
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
system.stateVersion = "25.11";
clan.core.sops.defaultGroups = [ "admins" ];
boot.kernelParams = [
"amdgpu.dcdebugmask=0x10"
"amdgpu.cwsr_enable=0"
"amdgpu.gpu_recovery=1"
];
boot.kernelPackages = pkgs.linuxKernel.packages.linux_6_12;
}
-95
View File
@@ -1,95 +0,0 @@
{ ... }:
let
hashDisk = disk: "os-${builtins.substring 0 5 (builtins.hashString "sha256" disk)}";
os = "/dev/disk/by-id/nvme-SAMSUNG_MZVL81T0HFLB-00BLL_S7XKNF0Y966645";
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";
};
};
swap = {
size = "16G";
content = {
type = "swap";
};
};
};
};
};
};
zpool = {
zroot = {
type = "zpool";
rootFsOptions = {
encryption = "aes-256-gcm";
keyformat = "passphrase";
keylocation = "file:///tmp/secret.key";
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
+9 -3
View File
@@ -1,7 +1,13 @@
{ config, ... }:
{
imports = [
(import ../../lib/auto-accept-zerotier-members.nix {
memberIds = [
"dbe44c0287" # Alex-gateway
"1b495eede9" # kurogeek-thinkpad
];
})
];
system.stateVersion = "25.11";
clan.core.sops.defaultGroups = [ "admins" ];
clan.core.settings.machine.description = "Zima board computer for testing in B4L";
}
-21
View File
@@ -1,21 +0,0 @@
## How to setup this machine.
This machine cannot be setup the same way as other machines are setup. Meaning that `clan machine install` won't work. Because of `disko` issue. So, below is how the machine is setup.
1. Build an image to flash to an sd-card using
```
nix build -L --show-trace .\#nixosConfigurations.sirius.config.system.build.images.sd-card
```
2. Import the `zdata`
```
zpool import zdata
```
3. Update configuration
```
clan machine update sirius
```
-108
View File
@@ -1,108 +0,0 @@
{
self,
pkgs,
...
}:
{
imports = [
./hardware-configuration.nix
];
image.modules.sd-card = {
disabledModules = [
./hardware-configuration.nix
];
};
clan.core.settings.machine.description = "w NAS";
clan.core.sops.defaultGroups = [ "admins" ];
nixpkgs.hostPlatform = {
system = "aarch64-linux";
};
nixpkgs.buildPlatform = {
system = "x86_64-linux";
};
system.stateVersion = "25.11";
services.udisks2.enable = false;
nix.settings.log-lines = 25;
nix.settings.auto-optimise-store = true;
nix.gc = {
automatic = true;
dates = "weekly";
options = "--delete-older-than 15d";
};
boot.loader.grub.enable = false;
boot.loader.generic-extlinux-compatible.enable = true;
boot.zfs.forceImportRoot = false;
boot.zfs.extraPools = [ "zdata" ];
boot.supportedFilesystems = [ "zfs" ];
boot.initrd.availableKernelModules = [
"usb_storage"
"sd_mod"
];
boot = {
consoleLogLevel = 0;
kernel.sysctl = {
"fs.suid_dumpable" = 0;
"kernel.core_pattern" = "/dev/null";
};
tmp = {
useTmpfs = true;
};
};
services.journald.settings.Journal.Storage = "none";
systemd = {
coredump.enable = false;
};
fileSystems."/mnt/hdd" = {
device = "zdata/nas";
fsType = "zfs";
mountPoint = "/mnt/hdd";
options = [
"nofail"
"zfsutil"
];
};
fileSystems."/var/lib" = {
device = "zdata/service-data";
fsType = "zfs";
mountPoint = "/var/lib";
options = [
"x-initrd.mount"
"nofail"
"zfsutil"
];
};
systemd.services.heartbeat-push = {
description = "Heartbeat push to uptime monitor";
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.curl}/bin/curl -s -o /dev/null https://uptime.b4l.co.th/api/push/X0WCHAcY5gPf1U8If7BT1FLjpacZqGZu?status=up&msg=OK&ping=";
};
};
systemd.timers.heartbeat-push = {
description = "Heartbeat push timer";
wantedBy = [ "timers.target" ];
timerConfig = {
OnBootSec = "60s";
OnUnitActiveSec = "60s";
Unit = "heartbeat-push.service";
};
};
}
-150
View File
@@ -1,150 +0,0 @@
{ lib, pkgs, ... }:
let
hashDisk = disk: "os-${builtins.substring 0 5 (builtins.hashString "sha256" disk)}";
# os = "/dev/disk/by-id/mmc-SD64G_0x8336354b";
vdev = [
"/dev/disk/by-id/ata-ST20000NM002H-3KV133_ZYDBVV7Z"
"/dev/disk/by-id/ata-ST20000NM002H-3KV133_ZYDBSJRE"
];
configTxt = pkgs.writeText "config.txt" ''
[pi4]
kernel=u-boot-rpi4.bin
enable_gic=1
# Otherwise the resolution will be weird in most cases, compared to
# what the pi3 firmware does by default.
disable_overscan=1
# Supported in newer board revisions
arm_boost=1
[all]
# Boot in 64-bit mode.
arm_64bit=1
# U-Boot needs this to work, regardless of whether UART is actually used or not.
# Look in arch/arm/mach-bcm283x/Kconfig in the U-Boot tree to see if this is still
# a requirement in the future.
enable_uart=1
# Prevent the firmware from smashing the framebuffer setup done by the mainline kernel
# when attempting to show low-voltage or overtemperature warnings.
avoid_warnings=1
'';
in
{
boot.loader = {
systemd-boot = {
enable = true;
};
efi = {
canTouchEfiVariables = true;
};
};
# boot.tmp.useTmpfs = true;
disko.devices = {
disk = {
# "os-${hashDisk os}" = {
# type = "disk";
# device = os;
# content = {
# type = "gpt";
# partitions = {
# firmware = {
# size = "60M";
# priority = 1;
# type = "0700";
# content = {
# type = "filesystem";
# format = "vfat";
# mountpoint = "/firmware";
# postMountHook = toString (
# pkgs.writeScript "postMountHook.sh" ''
# (cd ${pkgs.raspberrypifw}/share/raspberrypi/boot && cp bootcode.bin fixup*.dat start*.elf *.dtb /mnt/firmware/)
# cp ${pkgs.ubootRaspberryPi4_64bit}/u-boot.bin /mnt/firmware/u-boot-rpi4.bin
# cp ${configTxt} /mnt/firmware/config.txt
# ''
# );
# };
# };
# ESP = {
# size = "2G";
# type = "EF00";
# content = {
# type = "filesystem";
# format = "vfat";
# mountpoint = "/boot";
# mountOptions = [ "umask=0077" ];
# };
# };
# root = {
# name = "root";
# end = "-0";
# content = {
# type = "filesystem";
# format = "f2fs";
# mountpoint = "/";
# extraArgs = [
# "-O"
# "extra_attr,inode_checksum,sb_checksum,compression"
# ];
# mountOptions = [ "compress_algorithm=zstd:6,compress_chksum,atgc,gc_merge,lazytime,nodiscard" ];
# };
# };
# };
# };
# };
}
// (lib.listToAttrs (
map (disk: {
name = "data-${hashDisk disk}";
value = {
type = "disk";
device = disk;
content = {
type = "zfs";
pool = "zdata";
};
};
}) vdev
));
zpool = {
zdata = {
type = "zpool";
options.ashift = "12";
rootFsOptions = {
mountpoint = "none";
compression = "lz4";
acltype = "posixacl";
xattr = "sa";
"com.sun:auto-snapshot" = "true";
};
mode = {
topology = {
type = "topology";
vdev = [
{
mode = "mirror";
members = vdev;
}
];
};
};
datasets = {
"nas" = {
type = "zfs_fs";
mountpoint = "/mnt/hdd";
mountOptions = [ "nofail" ];
};
"service-data" = {
type = "zfs_fs";
mountpoint = "/var/lib";
mountOptions = [ "nofail" ];
};
};
};
};
};
}
@@ -1,6 +0,0 @@
{
fileSystems."/" = {
device = "/dev/disk/by-uuid/44444444-4444-4444-8888-888888888888";
fsType = "ext4";
};
}
-197
View File
@@ -1,197 +0,0 @@
{
config,
inputs,
lib,
pkgs,
...
}:
{
imports = [
inputs.matthew-hardware.nixosModules.mt7986a-glinet-gl-mt6000
];
config = {
hardware.mt7986a-glinet-gl-mt6000.enable = true;
hardware.mt7986a-glinet-gl-mt6000.zealous = true;
hardware.mt7986a-glinet-gl-mt6000.image.repart.enable = true;
nixpkgs.hostPlatform.system = "aarch64-linux";
nixpkgs.buildPlatform.system = "x86_64-linux";
system.stateVersion = "26.11";
clan.core.sops.defaultGroups = [ "admins" ];
clan.core.settings.name = "stellio";
clan.core.settings.machine.description = "Flint-2 router";
# Root is ext4 on the Flint 2's eMMC: keep steady-state writes off it.
# The journal is persistent but bounded (256M) and synced once a minute
# (the router needs logs for pppd/kea debugging and, after the Sep 2026
# unlogged reboots, for post-mortem; volatile storage left nothing).
# /tmp is tmpfs, no core dumps, and ext4 skips atime updates and
# flushes its journal every 60 s instead of 5 s so the small periodic
# writes (Kea leases, timesyncd clock, speedtest textfile, journal)
# coalesce. A power cut loses at most a minute of that state.
fileSystems."/".options = [
"noatime"
"commit=60"
];
boot.tmp.useTmpfs = true;
services.journald.settings.Journal = {
Storage = "persistent";
SystemMaxUse = "256M";
SyncIntervalSec = "1m";
};
systemd.coredump.enable = false;
# Upstream 07d9958739 (mainline 2026-05, not in linux-6.18.y). The MT7531
# switch on the Flint 2 hangs off MDIO, and mt7530_get_stats64 took the
# MDIO mutex under the RCU read lock that /proc/net/dev holds, so any
# stats reader (zerotier-one, node exporter, `ip -s link`) that raced a
# PHY access oopsed the box: "BUG: scheduling while atomic" ->
# "Unable to handle kernel paging request" on 2026-09-20 09:02 UTC.
# Drop once boot.kernelPackages moves to a kernel that carries it.
boot.kernelPatches = [
{
name = "mt7530-get-stats64-atomic";
patch = ./mt7530-get-stats64-atomic.patch;
}
];
# nixpkgs' services.blocky check runs the aarch64 blocky in a
# system.checks derivation, which an x86_64 builder without binfmt cannot
# execute (`--max-jobs 0` -> Exec format error). Validate the same YAML
# with the build host's blocky instead. Drop once cnx-network's router
# service carries this itself (router/dns: validate the Blocky config
# with the build host's binary).
services.blocky.enableConfigCheck = false;
system.checks = [
(pkgs.runCommand "check-blocky-config" { } ''
${lib.getExe pkgs.buildPackages.blocky} --config ${
(pkgs.formats.yaml { }).generate "blocky-config.yaml" config.services.blocky.settings
} validate && touch $out
'')
];
# The router service opens SSH only to the mgmt VLAN, the staging port
# and the ZeroTier mesh (inventories/router.nix). Also admit it over
# Yggdrasil (fleet-wide instance in inventories/default.nix) so the box
# stays reachable when ZeroTier's controller/relays are down. Scoped to
# the tunnel interface (clan-core's yggdrasil service names it `ygg`):
# only decrypted 200::/7 traffic arrives there, so a spoofed source on
# the WAN never matches.
networking.firewall.interfaces.${config.services.yggdrasil.settings.IfName}.allowedTCPPorts = [
22
];
# AIS delegates a single /64 over PPPoE (seen 2026-10-02: "ppp0: DHCP:
# received delegated prefix 2405:9800:b910:1f5d::/64"). The router
# service hands out sub-prefixes with SubnetId=auto, so whichever VLAN
# interface comes up first takes the whole /64 -- on this box vlan-mgmt
# did, and vlan-lan logged "Couldn't find a suitable prefix. Ran out of
# address space": no RA prefix on lan, so clients had no global IPv6.
# Pin the ids: lan (where the clients are) always gets subnet 0, i.e.
# the entire prefix when it is a /64; mgmt asks for subnet 1, which
# fails harmlessly on a /64 (mgmt is reached over v4 and the meshes) and
# starts working unchanged if AIS ever delegates wider. Drop once
# cnx-network's router service exposes a per-VLAN subnet id.
systemd.network.networks."40-vlan-lan".dhcpPrefixDelegationConfig.SubnetId = lib.mkForce "0x0";
systemd.network.networks."40-vlan-mgmt".dhcpPrefixDelegationConfig.SubnetId = lib.mkForce "0x1";
# Interim copy of cnx-network-clan 45643d6 (router/ipv6: deprecate
# withdrawn DHCPv6-PD prefixes); drop when the input is bumped past it.
# networkd never deprecates a prefix it stops announcing (systemd#29651):
# on every reboot the first PPPoE session lands on another AIS BNG, is
# torn down minutes later, and the reconnect brings a different /64.
# networkd announces the new prefix at once but clients keep the old
# one preferred for the rest of its 1800 s lifetime, so RFC 6724 source
# selection picks the dead prefix and every v6 connection fails for up
# to 30 minutes (2026-10-08 07:57). Watch vlan-* for networkd removing a
# dynamic (PD) address and send up to three RAs with that /64 at
# preferred lifetime 0, one short-lived radvd per RA (SIGKILLed: no
# shutdown RA with router lifetime 0), stopping as soon as the prefix is
# back on the interface -- a plain flap re-delegates the same /64 within
# seconds and a deprecating RA sent after networkd re-announced it would
# leave clients deprecated until the next periodic RA (08:19 today).
systemd.services.router-radv-deprecate = {
description = "Deprecate withdrawn DHCPv6-PD prefixes on the VLANs";
wantedBy = [ "multi-user.target" ];
after = [ "systemd-networkd.service" ];
path = [
pkgs.iproute2
pkgs.ipcalc
pkgs.radvd
];
serviceConfig = {
Restart = "always";
RestartSec = 2;
RuntimeDirectory = "router-radv-deprecate";
};
script = ''
conf=$RUNTIME_DIRECTORY/radvd.conf
pid=$RUNTIME_DIRECTORY/radvd.pid
# /64s of the global addresses currently on an interface.
prefixes_on() {
ip -o -6 addr show dev "$1" scope global | while read -r _ _ _ a _; do
echo "$(ipcalc --no-decorate -n "$a")/''${a##*/}"
done
}
# "Deleted 4: vlan-lan inet6 2001:db8::1/64 scope global dynamic mngtmpaddr \ valid_lft ..."
ip -o -6 monitor address | while read -r event _ dev _ addr _ scope rest; do
[[ $event == Deleted && $dev == vlan-* && $scope == global && $rest == *dynamic* ]] || continue
prefix="$(ipcalc --no-decorate -n "$addr")/''${addr##*/}"
cat > "$conf" <<EOF
interface $dev {
AdvSendAdvert on;
MinRtrAdvInterval 3;
MaxRtrAdvInterval 4;
AdvDefaultLifetime 1800;
AdvCurHopLimit 0;
prefix $prefix {
AdvOnLink on;
AdvAutonomous on;
AdvPreferredLifetime 0;
AdvValidLifetime 7200;
};
};
EOF
for _ in 1 2 3; do
if prefixes_on "$dev" | grep -qxF "$prefix"; then
echo "$dev: $prefix is back, leaving it announced"
break
fi
echo "$dev: deprecating withdrawn prefix $prefix"
rm -f "$pid"
# radvd sends its first RA on start; the next would follow 3-4 s later.
radvd -C "$conf" -p "$pid" -n -m stderr &
sleep 1
kill -KILL $! 2>/dev/null || true
wait $! || true
sleep 2
done
done
'';
};
systemd.services.heartbeat-push = {
description = "Heartbeat push to uptime monitor";
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.curl}/bin/curl -s -o /dev/null https://uptime.b4l.co.th/api/push/X0WCHAcY5gPf1U8If7BT1FLjpacZqGZu?status=up&msg=OK&ping=";
};
};
systemd.timers.heartbeat-push = {
description = "Heartbeat push timer";
wantedBy = [ "timers.target" ];
timerConfig = {
OnBootSec = "60s";
OnUnitActiveSec = "60s";
Unit = "heartbeat-push.service";
};
};
};
}
-13
View File
@@ -1,13 +0,0 @@
{ inputs, ... }:
{
disko = {
imageBuilder = {
# Avoid double emulation to significantly speed up image building process.
# Update the system according to your host system.
# See https://github.com/nix-community/disko/issues/856
qemu =
inputs.nixpkgs.legacyPackages.x86_64-linux.qemu
+ "/bin/qemu-system-aarch64 -M virt -cpu cortex-a57";
};
};
}
@@ -1,230 +0,0 @@
From 07d99587396024932e02474c3a5bede71d108454 Mon Sep 17 00:00:00 2001
From: Daniel Golle <daniel@makrotopia.org>
Date: Sat, 2 May 2026 11:55:02 +0100
Subject: net: dsa: mt7530: fix .get_stats64 sleeping in atomic context
The .get_stats64 callback runs in atomic context, but on
MDIO-connected switches every register read acquires the MDIO bus
mutex, which can sleep:
[ 12.645973] BUG: sleeping function called from invalid context at kernel/locking/mutex.c:609
[ 12.654442] in_atomic(): 0, irqs_disabled(): 0, non_block: 0, pid: 759, name: grep
[ 12.663377] preempt_count: 0, expected: 0
[ 12.667410] RCU nest depth: 1, expected: 0
[ 12.671511] INFO: lockdep is turned off.
[ 12.675441] CPU: 0 UID: 0 PID: 759 Comm: grep Tainted: G S W 7.0.0+ #0 PREEMPT
[ 12.675453] Tainted: [S]=CPU_OUT_OF_SPEC, [W]=WARN
[ 12.675456] Hardware name: Bananapi BPI-R64 (DT)
[ 12.675459] Call trace:
[ 12.675462] show_stack+0x14/0x1c (C)
[ 12.675477] dump_stack_lvl+0x68/0x8c
[ 12.675487] dump_stack+0x14/0x1c
[ 12.675495] __might_resched+0x14c/0x220
[ 12.675504] __might_sleep+0x44/0x80
[ 12.675511] __mutex_lock+0x50/0xb10
[ 12.675523] mutex_lock_nested+0x20/0x30
[ 12.675532] mt7530_get_stats64+0x40/0x2ac
[ 12.675542] dsa_user_get_stats64+0x2c/0x40
[ 12.675553] dev_get_stats+0x44/0x1e0
[ 12.675564] dev_seq_printf_stats+0x24/0xe0
[ 12.675575] dev_seq_show+0x14/0x3c
[ 12.675583] seq_read_iter+0x37c/0x480
[ 12.675595] seq_read+0xd0/0xec
[ 12.675605] proc_reg_read+0x94/0xe4
[ 12.675615] vfs_read+0x98/0x29c
[ 12.675625] ksys_read+0x54/0xdc
[ 12.675633] __arm64_sys_read+0x18/0x20
[ 12.675642] invoke_syscall.constprop.0+0x54/0xec
[ 12.675653] do_el0_svc+0x3c/0xb4
[ 12.675662] el0_svc+0x38/0x200
[ 12.675670] el0t_64_sync_handler+0x98/0xdc
[ 12.675679] el0t_64_sync+0x158/0x15c
For MDIO-connected switches, poll MIB counters asynchronously using a
delayed workqueue every second and let .get_stats64 return the cached
values under a spinlock. A mod_delayed_work() call on each read
triggers an immediate refresh so counters stay responsive when queried
more frequently.
MMIO-connected switches (MT7988, EN7581, AN7583) are not affected
because their regmap does not sleep, so they continue to read MIB
counters directly in .get_stats64.
Fixes: 88c810f35ed5 ("net: dsa: mt7530: implement .get_stats64")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Acked-by: Chester A. Unal <chester.a.unal@arinc9.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/6940b913da2c29156f0feff74b678d3c526ee84c.1777719253.git.daniel@makrotopia.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/dsa/mt7530.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++--
drivers/net/dsa/mt7530.h | 8 ++++++
2 files changed, 80 insertions(+), 3 deletions(-)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index b9423389c2ef0..44d670904ad89 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -25,6 +25,9 @@
#include "mt7530.h"
+#define MT7530_STATS_POLL_INTERVAL (1 * HZ)
+#define MT7530_STATS_RATE_LIMIT (HZ / 10)
+
static struct mt753x_pcs *pcs_to_mt753x_pcs(struct phylink_pcs *pcs)
{
return container_of(pcs, struct mt753x_pcs, pcs);
@@ -906,10 +909,9 @@ static void mt7530_get_rmon_stats(struct dsa_switch *ds, int port,
*ranges = mt7530_rmon_ranges;
}
-static void mt7530_get_stats64(struct dsa_switch *ds, int port,
- struct rtnl_link_stats64 *storage)
+static void mt7530_read_port_stats64(struct mt7530_priv *priv, int port,
+ struct rtnl_link_stats64 *storage)
{
- struct mt7530_priv *priv = ds->priv;
uint64_t data;
/* MIB counter doesn't provide a FramesTransmittedOK but instead
@@ -951,6 +953,54 @@ static void mt7530_get_stats64(struct dsa_switch *ds, int port,
&storage->rx_crc_errors);
}
+static void mt7530_stats_refresh(struct mt7530_priv *priv)
+{
+ struct rtnl_link_stats64 stats = {};
+ struct dsa_port *dp;
+ int port;
+
+ dsa_switch_for_each_user_port(dp, priv->ds) {
+ port = dp->index;
+
+ mt7530_read_port_stats64(priv, port, &stats);
+
+ spin_lock_bh(&priv->stats_lock);
+ priv->ports[port].stats = stats;
+ priv->stats_last = jiffies;
+ spin_unlock_bh(&priv->stats_lock);
+ }
+}
+
+static void mt7530_stats_poll(struct work_struct *work)
+{
+ struct mt7530_priv *priv = container_of(work, struct mt7530_priv,
+ stats_work.work);
+
+ mt7530_stats_refresh(priv);
+ schedule_delayed_work(&priv->stats_work,
+ MT7530_STATS_POLL_INTERVAL);
+}
+
+static void mt7530_get_stats64(struct dsa_switch *ds, int port,
+ struct rtnl_link_stats64 *storage)
+{
+ struct mt7530_priv *priv = ds->priv;
+ bool refresh;
+
+ if (priv->bus) {
+ spin_lock_bh(&priv->stats_lock);
+ *storage = priv->ports[port].stats;
+ refresh = time_after(jiffies, priv->stats_last +
+ MT7530_STATS_RATE_LIMIT);
+ spin_unlock_bh(&priv->stats_lock);
+ if (refresh)
+ mod_delayed_work(system_percpu_wq,
+ &priv->stats_work, 0);
+ } else {
+ mt7530_read_port_stats64(priv, port, storage);
+ }
+}
+
static void mt7530_get_eth_ctrl_stats(struct dsa_switch *ds, int port,
struct ethtool_eth_ctrl_stats *ctrl_stats)
{
@@ -3137,9 +3187,24 @@ mt753x_setup(struct dsa_switch *ds)
if (ret && priv->irq_domain)
mt7530_free_mdio_irq(priv);
+ if (!ret && priv->bus) {
+ mt7530_stats_refresh(priv);
+ schedule_delayed_work(&priv->stats_work,
+ MT7530_STATS_POLL_INTERVAL);
+ }
+
return ret;
}
+static void
+mt753x_teardown(struct dsa_switch *ds)
+{
+ struct mt7530_priv *priv = ds->priv;
+
+ if (priv->bus)
+ cancel_delayed_work_sync(&priv->stats_work);
+}
+
static int mt753x_set_mac_eee(struct dsa_switch *ds, int port,
struct ethtool_keee *e)
{
@@ -3257,6 +3322,7 @@ static int mt7988_setup(struct dsa_switch *ds)
static const struct dsa_switch_ops mt7530_switch_ops = {
.get_tag_protocol = mtk_get_tag_protocol,
.setup = mt753x_setup,
+ .teardown = mt753x_teardown,
.preferred_default_local_cpu_port = mt753x_preferred_default_local_cpu_port,
.get_strings = mt7530_get_strings,
.get_ethtool_stats = mt7530_get_ethtool_stats,
@@ -3395,6 +3461,9 @@ mt7530_probe_common(struct mt7530_priv *priv)
priv->ds->ops = &mt7530_switch_ops;
priv->ds->phylink_mac_ops = &mt753x_phylink_mac_ops;
mutex_init(&priv->reg_mutex);
+ spin_lock_init(&priv->stats_lock);
+ INIT_DELAYED_WORK(&priv->stats_work, mt7530_stats_poll);
+
dev_set_drvdata(dev, priv);
return 0;
diff --git a/drivers/net/dsa/mt7530.h b/drivers/net/dsa/mt7530.h
index 3e0090bed298d..dd33b0df3419e 100644
--- a/drivers/net/dsa/mt7530.h
+++ b/drivers/net/dsa/mt7530.h
@@ -796,6 +796,7 @@ struct mt7530_fdb {
* @pvid: The VLAN specified is to be considered a PVID at ingress. Any
* untagged frames will be assigned to the related VLAN.
* @sgmii_pcs: Pointer to PCS instance for SerDes ports
+ * @stats: Cached port statistics for MDIO-connected switches
*/
struct mt7530_port {
bool enable;
@@ -803,6 +804,7 @@ struct mt7530_port {
u32 pm;
u16 pvid;
struct phylink_pcs *sgmii_pcs;
+ struct rtnl_link_stats64 stats;
};
/* Port 5 mode definitions of the MT7530 switch */
@@ -875,6 +877,9 @@ struct mt753x_info {
* @create_sgmii: Pointer to function creating SGMII PCS instance(s)
* @active_cpu_ports: Holding the active CPU ports
* @mdiodev: The pointer to the MDIO device structure
+ * @stats_lock: Protects cached per-port stats from concurrent access
+ * @stats_work: Delayed work for polling MIB counters on MDIO switches
+ * @stats_last: Jiffies timestamp of last MIB counter poll
*/
struct mt7530_priv {
struct device *dev;
@@ -900,6 +905,9 @@ struct mt7530_priv {
int (*create_sgmii)(struct mt7530_priv *priv);
u8 active_cpu_ports;
struct mdio_device *mdiodev;
+ spinlock_t stats_lock; /* protects cached stats counters */
+ struct delayed_work stats_work;
+ unsigned long stats_last;
};
struct mt7530_hw_vlan_entry {
--
cgit 1.3.1-korg
-33
View File
@@ -1,33 +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
+6 -5
View File
@@ -1,21 +1,22 @@
{
inputs,
config,
self,
...
}:
{
imports = [
self.nixosModules.common
(inputs.import-tree ./services)
(import ../../lib/auto-accept-zerotier-members.nix {
memberIds = [
"dbe44c0287" # Alex-gateway
"1b495eede9" # kurogeek-thinkpad
];
})
];
clan.core.sops.defaultGroups = [ "admins" ];
clan.core.settings.machine.description = "Glom NAS";
nixpkgs.hostPlatform = {
system = "x86_64-linux";
};
+1 -3
View File
@@ -1,7 +1,7 @@
{ lib, ... }:
let
hashDisk = disk: "os-${builtins.substring 0 5 (builtins.hashString "sha256" disk)}";
os = "/dev/disk/by-id/mmc-CUTB42_0x95d14f9e";
os = "/dev/disk/by-id/mmc-CUTB42_0x9d59499c";
vdev = [
"/dev/disk/by-id/ata-ST20000NM002H-3KV133_ZYD5RYRG"
"/dev/disk/by-id/ata-ST20000NM002H-3KV133_ZYD5S02X"
@@ -18,8 +18,6 @@ in
};
};
boot.zfs.forceImportRoot = true;
disko.devices = {
disk = {
"os-${hashDisk os}" = {
+245 -155
View File
@@ -23,8 +23,8 @@
},
"bluetooth": [
{
"index": 31,
"attached_to": 33,
"index": 33,
"attached_to": 34,
"class_list": ["usb", "bluetooth"],
"bus_type": {
"hex": "0086",
@@ -99,7 +99,7 @@
},
{
"index": 36,
"attached_to": 33,
"attached_to": 34,
"class_list": ["usb", "bluetooth"],
"bus_type": {
"hex": "0086",
@@ -597,7 +597,7 @@
"fpu_exception": true,
"cpuid_level": 32,
"write_protect": false,
"tlb_size": 32764,
"tlb_size": 32767,
"clflush_size": 64,
"cache_alignment": 64,
"address_sizes": {
@@ -636,7 +636,7 @@
},
"device": {
"hex": "0561",
"name": "1",
"name": "0",
"value": 1377
},
"revision": {
@@ -645,10 +645,10 @@
"value": 0
},
"serial": "000000004EBF",
"model": "1",
"model": "0",
"sysfs_id": "/class/block/sdb",
"sysfs_bus_id": "1:0:0:1",
"sysfs_device_link": "/devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host1/target1:0:0/1:0:0:1",
"sysfs_bus_id": "1:0:0:0",
"sysfs_device_link": "/devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host1/target1:0:0/1:0:0:0",
"unix_device_name": "/dev/sdb",
"unix_device_number": {
"type": 98,
@@ -657,10 +657,10 @@
"range": 16
},
"unix_device_names": [
"/dev/disk/by-id/ata-ST20000NM002H-3KV133_ZYD5S02X",
"/dev/disk/by-id/usb-USB_3.0_Device_1_000000004EBF-0:1",
"/dev/disk/by-path/pci-0000:00:14.0-usb-0:3:1.0-scsi-0:0:0:1",
"/dev/disk/by-path/pci-0000:00:14.0-usbv3-0:3:1.0-scsi-0:0:0:1",
"/dev/disk/by-id/ata-ST20000NM002H-3KV133_ZYD5RYRG",
"/dev/disk/by-id/usb-USB_3.0_Device_0_000000004EBF-0:0",
"/dev/disk/by-path/pci-0000:00:14.0-usb-0:3:1.0-scsi-0:0:0:0",
"/dev/disk/by-path/pci-0000:00:14.0-usbv3-0:3:1.0-scsi-0:0:0:0",
"/dev/sdb"
],
"unix_device_name2": "/dev/sg1",
@@ -706,7 +706,7 @@
"name": "Disk",
"value": 0
},
"serial": "0x95d14f9e",
"serial": "0x9d59499c",
"model": "Disk",
"sysfs_id": "/class/block/mmcblk0",
"sysfs_bus_id": "mmc0:0001",
@@ -719,7 +719,7 @@
"range": 32
},
"unix_device_names": [
"/dev/disk/by-id/mmc-CUTB42_0x95d14f9e",
"/dev/disk/by-id/mmc-CUTB42_0x9d59499c",
"/dev/mmcblk0"
],
"resources": [
@@ -745,6 +745,180 @@
},
{
"index": 29,
"attached_to": 25,
"class_list": ["disk", "block_device"],
"base_class": {
"hex": "0106",
"name": "Mass Storage Device",
"value": 262
},
"sub_class": {
"hex": "0000",
"name": "Disk",
"value": 0
},
"model": "Disk",
"sysfs_id": "/class/block/mmcblk0boot0",
"sysfs_bus_id": "mmcblk0",
"sysfs_device_link": "/devices/pci0000:00/0000:00:1a.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0",
"unix_device_name": "/dev/mmcblk0boot0",
"unix_device_number": {
"type": 98,
"major": 179,
"minor": 32,
"range": 32
},
"unix_device_names": ["/dev/mmcblk0boot0"],
"resources": [
{
"type": "disk_geo",
"cylinders": 128,
"heads": 4,
"sectors": 16,
"size": "0x0",
"geo_type": "logical"
},
{
"type": "size",
"unit": "sectors",
"value_1": 8192,
"value_2": 512
}
],
"driver": "mmcblk",
"drivers": ["mmcblk"]
},
{
"index": 30,
"attached_to": 22,
"class_list": ["disk", "usb", "scsi", "block_device"],
"bus_type": {
"hex": "0084",
"name": "SCSI",
"value": 132
},
"slot": {
"bus": 1,
"number": 0
},
"base_class": {
"hex": "0106",
"name": "Mass Storage Device",
"value": 262
},
"sub_class": {
"hex": "0000",
"name": "Disk",
"value": 0
},
"vendor": {
"hex": "152d",
"value": 5421
},
"device": {
"hex": "0561",
"name": "1",
"value": 1377
},
"revision": {
"hex": "0000",
"name": "~",
"value": 0
},
"serial": "000000004EBF",
"model": "1",
"sysfs_id": "/class/block/sdc",
"sysfs_bus_id": "1:0:0:1",
"sysfs_device_link": "/devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host1/target1:0:0/1:0:0:1",
"unix_device_name": "/dev/sdc",
"unix_device_number": {
"type": 98,
"major": 8,
"minor": 32,
"range": 16
},
"unix_device_names": [
"/dev/disk/by-id/ata-ST20000NM002H-3KV133_ZYD5S02X",
"/dev/disk/by-id/usb-USB_3.0_Device_1_000000004EBF-0:1",
"/dev/disk/by-path/pci-0000:00:14.0-usb-0:3:1.0-scsi-0:0:0:1",
"/dev/disk/by-path/pci-0000:00:14.0-usbv3-0:3:1.0-scsi-0:0:0:1",
"/dev/sdc"
],
"unix_device_name2": "/dev/sg2",
"unix_device_number2": {
"type": 99,
"major": 21,
"minor": 2,
"range": 1
},
"resources": [
{
"type": "disk_geo",
"cylinders": 19074048,
"heads": 64,
"sectors": 32,
"size": "0x0",
"geo_type": "logical"
},
{
"type": "size",
"unit": "sectors",
"value_1": 39063650304,
"value_2": 512
}
],
"driver": "uas",
"driver_module": "uas",
"drivers": ["sd", "uas"],
"driver_modules": ["sd_mod", "uas"]
},
{
"index": 31,
"attached_to": 25,
"class_list": ["disk", "block_device"],
"base_class": {
"hex": "0106",
"name": "Mass Storage Device",
"value": 262
},
"sub_class": {
"hex": "0000",
"name": "Disk",
"value": 0
},
"model": "Disk",
"sysfs_id": "/class/block/mmcblk0boot1",
"sysfs_bus_id": "mmcblk0",
"sysfs_device_link": "/devices/pci0000:00/0000:00:1a.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0",
"unix_device_name": "/dev/mmcblk0boot1",
"unix_device_number": {
"type": 98,
"major": 179,
"minor": 64,
"range": 32
},
"unix_device_names": ["/dev/mmcblk0boot1"],
"resources": [
{
"type": "disk_geo",
"cylinders": 128,
"heads": 4,
"sectors": 16,
"size": "0x0",
"geo_type": "logical"
},
{
"type": "size",
"unit": "sectors",
"value_1": 8192,
"value_2": 512
}
],
"driver": "mmcblk",
"drivers": ["mmcblk"]
},
{
"index": 32,
"attached_to": 22,
"class_list": ["disk", "usb", "scsi", "block_device"],
"bus_type": {
@@ -783,27 +957,27 @@
},
"serial": "000000001532",
"model": "Generic STORAGE DEVICE",
"sysfs_id": "/class/block/sdc",
"sysfs_id": "/class/block/sda",
"sysfs_bus_id": "0:0:0:0",
"sysfs_device_link": "/devices/pci0000:00/0000:00:14.0/usb3/3-1/3-1:1.0/host0/target0:0:0/0:0:0:0",
"unix_device_name": "/dev/sdc",
"sysfs_device_link": "/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0/host0/target0:0:0/0:0:0:0",
"unix_device_name": "/dev/sda",
"unix_device_number": {
"type": 98,
"major": 8,
"minor": 32,
"minor": 0,
"range": 16
},
"unix_device_names": [
"/dev/disk/by-id/usb-Generic_STORAGE_DEVICE_000000001532-0:0",
"/dev/disk/by-path/pci-0000:00:14.0-usb-0:1:1.0-scsi-0:0:0:0",
"/dev/disk/by-path/pci-0000:00:14.0-usbv2-0:1:1.0-scsi-0:0:0:0",
"/dev/sdc"
"/dev/disk/by-path/pci-0000:00:14.0-usb-0:2:1.0-scsi-0:0:0:0",
"/dev/disk/by-path/pci-0000:00:14.0-usbv2-0:2:1.0-scsi-0:0:0:0",
"/dev/sda"
],
"unix_device_name2": "/dev/sg2",
"unix_device_name2": "/dev/sg0",
"unix_device_number2": {
"type": 99,
"major": 21,
"minor": 2,
"minor": 0,
"range": 1
},
"resources": [
@@ -835,90 +1009,6 @@
"drivers": ["sd", "usb-storage"],
"driver_modules": ["sd_mod", "usb_storage"],
"module_alias": "usb:v05E3p0749d1532dc00dsc00dp00ic08isc06ip50in00"
},
{
"index": 30,
"attached_to": 22,
"class_list": ["disk", "usb", "scsi", "block_device"],
"bus_type": {
"hex": "0084",
"name": "SCSI",
"value": 132
},
"slot": {
"bus": 1,
"number": 0
},
"base_class": {
"hex": "0106",
"name": "Mass Storage Device",
"value": 262
},
"sub_class": {
"hex": "0000",
"name": "Disk",
"value": 0
},
"vendor": {
"hex": "152d",
"value": 5421
},
"device": {
"hex": "0561",
"name": "0",
"value": 1377
},
"revision": {
"hex": "0000",
"name": "~",
"value": 0
},
"serial": "000000004EBF",
"model": "0",
"sysfs_id": "/class/block/sda",
"sysfs_bus_id": "1:0:0:0",
"sysfs_device_link": "/devices/pci0000:00/0000:00:14.0/usb4/4-3/4-3:1.0/host1/target1:0:0/1:0:0:0",
"unix_device_name": "/dev/sda",
"unix_device_number": {
"type": 98,
"major": 8,
"minor": 0,
"range": 16
},
"unix_device_names": [
"/dev/disk/by-id/ata-ST20000NM002H-3KV133_ZYD5RYRG",
"/dev/disk/by-id/usb-USB_3.0_Device_0_000000004EBF-0:0",
"/dev/disk/by-path/pci-0000:00:14.0-usb-0:3:1.0-scsi-0:0:0:0",
"/dev/disk/by-path/pci-0000:00:14.0-usbv3-0:3:1.0-scsi-0:0:0:0",
"/dev/sda"
],
"unix_device_name2": "/dev/sg0",
"unix_device_number2": {
"type": 99,
"major": 21,
"minor": 0,
"range": 1
},
"resources": [
{
"type": "disk_geo",
"cylinders": 19074048,
"heads": 64,
"sectors": 32,
"size": "0x0",
"geo_type": "logical"
},
{
"type": "size",
"unit": "sectors",
"value_1": 39063650304,
"value_2": 512
}
],
"driver": "uas",
"driver_module": "uas",
"drivers": ["sd", "uas"],
"driver_modules": ["sd_mod", "uas"]
}
],
"graphics_card": [
@@ -1028,7 +1118,7 @@
],
"hub": [
{
"index": 33,
"index": 34,
"attached_to": 22,
"class_list": ["usb", "hub"],
"bus_type": {
@@ -1178,7 +1268,7 @@
"module_alias": "usb:v1D6Bp0003d0615dc09dsc00dp03ic09isc00ip00in00"
},
{
"index": 38,
"index": 39,
"attached_to": 9,
"class_list": ["usb", "hub"],
"bus_type": {
@@ -1258,7 +1348,7 @@
"module_alias": "usb:v1D6Bp0002d0615dc09dsc00dp01ic09isc00ip00in00"
},
{
"index": 40,
"index": 41,
"attached_to": 9,
"class_list": ["usb", "hub"],
"bus_type": {
@@ -1330,8 +1420,8 @@
],
"keyboard": [
{
"index": 39,
"attached_to": 33,
"index": 38,
"attached_to": 34,
"class_list": ["keyboard", "usb"],
"bus_type": {
"hex": "0086",
@@ -1368,8 +1458,8 @@
"value": 0
},
"model": "Logitech USB Receiver",
"sysfs_id": "/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.0",
"sysfs_bus_id": "3-2:1.0",
"sysfs_id": "/devices/pci0000:00/0000:00:14.0/usb3/3-5/3-5:1.0",
"sysfs_bus_id": "3-5:1.0",
"resources": [
{
"type": "baud",
@@ -1439,7 +1529,7 @@
{
"type": "mem",
"base": 0,
"range": 8097124352,
"range": 8096096256,
"enabled": true,
"access": "read_write",
"prefetch": "unknown"
@@ -1628,8 +1718,8 @@
],
"mouse": [
{
"index": 32,
"attached_to": 33,
"index": 42,
"attached_to": 34,
"class_list": ["mouse", "usb"],
"bus_type": {
"hex": "0086",
@@ -1668,8 +1758,8 @@
"compat_vendor": "Unknown",
"compat_device": "Generic USB Mouse",
"model": "Logitech USB Receiver",
"sysfs_id": "/devices/pci0000:00/0000:00:14.0/usb3/3-2/3-2:1.1",
"sysfs_bus_id": "3-2:1.1",
"sysfs_id": "/devices/pci0000:00/0000:00:14.0/usb3/3-5/3-5:1.1",
"sysfs_bus_id": "3-5:1.1",
"resources": [
{
"type": "baud",
@@ -1874,7 +1964,7 @@
"resources": [
{
"type": "hwaddr",
"address": 54
"address": 48
},
{
"type": "io",
@@ -1899,7 +1989,7 @@
},
{
"type": "phwaddr",
"address": 53
"address": 54
},
{
"type": "wlan",
@@ -1992,8 +2082,8 @@
],
"network_interface": [
{
"index": 41,
"attached_to": 0,
"index": 43,
"attached_to": 13,
"class_list": ["network_interface"],
"base_class": {
"hex": "0107",
@@ -2001,17 +2091,32 @@
"value": 263
},
"sub_class": {
"hex": "0000",
"name": "Loopback",
"value": 0
"hex": "000a",
"name": "WLAN",
"value": 10
},
"model": "Loopback network interface",
"sysfs_id": "/class/net/lo",
"unix_device_name": "lo",
"unix_device_names": ["lo"]
"model": "WLAN network interface",
"sysfs_id": "/class/net/wlan0",
"sysfs_device_link": "/devices/pci0000:00/0000:00:1c.0/0000:01:00.0",
"unix_device_name": "wlan0",
"unix_device_names": ["wlan0"],
"resources": [
{
"type": "hwaddr",
"address": 48
},
{
"type": "phwaddr",
"address": 54
}
],
"driver": "rtw89_8852be",
"driver_module": "rtw89_8852be",
"drivers": ["rtw89_8852be"],
"driver_modules": ["rtw89_8852be"]
},
{
"index": 42,
"index": 44,
"attached_to": 11,
"class_list": ["network_interface"],
"base_class": {
@@ -2045,8 +2150,8 @@
"driver_modules": ["igc"]
},
{
"index": 43,
"attached_to": 13,
"index": 45,
"attached_to": 0,
"class_list": ["network_interface"],
"base_class": {
"hex": "0107",
@@ -2054,29 +2159,14 @@
"value": 263
},
"sub_class": {
"hex": "000a",
"name": "WLAN",
"value": 10
"hex": "0000",
"name": "Loopback",
"value": 0
},
"model": "WLAN network interface",
"sysfs_id": "/class/net/wlan0",
"sysfs_device_link": "/devices/pci0000:00/0000:00:1c.0/0000:01:00.0",
"unix_device_name": "wlan0",
"unix_device_names": ["wlan0"],
"resources": [
{
"type": "hwaddr",
"address": 54
},
{
"type": "phwaddr",
"address": 53
}
],
"driver": "rtw89_8852be",
"driver_module": "rtw89_8852be",
"drivers": ["rtw89_8852be"],
"driver_modules": ["rtw89_8852be"]
"model": "Loopback network interface",
"sysfs_id": "/class/net/lo",
"unix_device_name": "lo",
"unix_device_names": ["lo"]
}
],
"pci": [
+34
View File
@@ -0,0 +1,34 @@
{ config, pkgs, ... }:
let
# ncDomain = "${config.clan.core.vars.generators.vega-nextcloud.files.subdomain.value}.${config.networking.fqdn}";
ncDomain = "${config.networking.fqdn}";
in
{
clan.core.vars.generators.vega-nextcloud = {
files.subdomain.secret = false;
prompts = {
subdomain = {
persist = true;
type = "line";
description = "Sub-domain for Nextcloud app. Default:(cloud)";
};
};
script = ''cat $prompts/subdomain || echo -n "cloud" > $out/subdomain'';
};
networking.firewall.allowedTCPPorts = [
80
443
];
services.nextcloud = {
hostName = ncDomain;
package = pkgs.nextcloud31;
};
# services.nginx.virtualHosts."${ncDomain}" = {
# # useACMEHost = "${config.networking.fqdn}";
# # forceSSL = true;
# };
}
-96
View File
@@ -1,96 +0,0 @@
{
config,
lib,
...
}:
let
sambaUser = lib.filterAttrs (
name: user: user.isNormalUser && builtins.elem "samba" user.extraGroups
) config.users.users;
sharedFolders = {
GLOM.users = [
"w"
"kurogeek"
"berwn"
];
};
in
{
services.samba = {
enable = true;
openFirewall = true;
settings = {
global = {
security = "user";
workgroup = "WORKGROUP";
"server string" = "Glom Vega";
interfaces = "eth* en*";
"max log size" = "50";
"dns proxy" = false;
"syslog only" = true;
"map to guest" = "Bad User";
"guest account" = "nobody";
};
}
// lib.mapAttrs (share: opts: {
path = "/mnt/hdd/samba/${share}";
comment = share;
"force user" = share;
"force group" = share;
public = "yes";
"guest ok" = "yes";
"create mask" = "0640";
"directory mask" = "0750";
writable = "no";
browseable = "yes";
printable = "no";
# TODO
# "valid users" = toString opts.users;
}) sharedFolders;
};
users.users = lib.mapAttrs (share: opts: {
isSystemUser = true;
group = share;
}) sharedFolders;
users.groups = lib.mapAttrs (share: opts: { }) sharedFolders;
systemd.services.samba-smbd.postStart =
lib.concatMapStrings (
user:
let
password = config.clan.core.vars.generators."${user}-smb-password".files.password.path;
in
''
mkdir -p /mnt/hdd/samba/${user}
chown ${user}:users /mnt/hdd/samba/${user}
# if a password is unchanged, this will error
(echo $(<${password}); echo $(<${password})) | ${config.services.samba.package}/bin/smbpasswd -s -a ${user}
''
) (lib.attrNames sambaUser)
+ lib.concatMapStrings (share: ''
mkdir -p /mnt/hdd/samba/${share}
chown ${share}:${share} /mnt/hdd/samba/${share}
'') (lib.attrNames sharedFolders);
services.samba-wsdd = {
enable = true;
openFirewall = true;
};
services.avahi = {
settings.publish = {
disable-publishing = false;
disable-user-service-publishing = false;
publish-addresses = true;
};
# ^^ Needed to allow samba to automatically register mDNS records (without the need for an `extraServiceFile`
nssmdns4 = true;
# ^^ Not one hundred percent sure if this is needed- if it aint broke, don't fix it
enable = true;
openFirewall = true;
};
}
+33
View File
@@ -0,0 +1,33 @@
{ config, ... }:
{
clan.core.vars.generators.ups = {
dependencies = [ "root-password" ];
files.password = {
secret = true;
owner = "nutmon";
group = "nutmon";
};
script = ''
cat $in/root-password/password > $out/password
'';
};
power.ups = {
enable = true;
mode = "standalone";
ups."apc" = {
driver = "usbhid-ups";
port = "auto";
};
upsmon.monitor."test-monitor" = {
powerValue = 1;
user = "root";
type = "primary";
passwordFile = config.clan.core.vars.generators.ups.files.password.path;
};
upsmon.settings = {
RUN_AS_USER = "root";
};
};
}
-2
View File
@@ -3,11 +3,9 @@
_class = "clan.service";
manifest.name = "actual-budget";
manifest.description = "A local-first personal finance app ";
manifest.readme = "A local-first personal finance app";
manifest.categories = [ "System" ];
roles.default = {
description = "A default server role.";
perInstance.nixosModule =
{
+1 -1
View File
@@ -10,7 +10,7 @@ in
perSystem =
{ ... }:
{
clan.nixosTests.service-actual-budget = {
clan.nixosTests.actual-budget = {
imports = [ ./tests/vm/default.nix ];
clan.modules."@clan/actual-budget" = module;
@@ -5,7 +5,6 @@
name = "service-actual-budget";
clan = {
test.useContainers = false;
directory = ./.;
inventory = {
machines.server = { };
-3
View File
@@ -1,3 +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"
}
}
Loaded 100 of 1812 files, more files were not shown because too many files have changed in this diff. Show more