Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dabfbc84cb | ||
|
|
1ccf5febc9 | ||
|
|
ec0ac3933b | ||
|
|
5053c766d1 | ||
|
|
4bc135b0ad | ||
|
|
fb26eef750 |
No files matched your search
@@ -3,4 +3,3 @@
|
||||
result
|
||||
result-*
|
||||
run-vm-*
|
||||
.nixos-test-history
|
||||
Generated
+103
-874
File diff suppressed because it is too large.
Load diff
@@ -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";
|
||||
@@ -25,49 +19,20 @@
|
||||
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/nixpkgs-unstable";
|
||||
robotnix = {
|
||||
inputs.treefmt-nix.follows = "treefmt-nix";
|
||||
url = "github:nix-community/robotnix";
|
||||
};
|
||||
treefmt-nix = {
|
||||
url = "github:numtide/treefmt-nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
liminix = {
|
||||
url = "git+https://gti.telent.net/dan/liminix";
|
||||
url = "git+https://git.b4l.co.th/newedge/liminix?ref=refs/heads/fix-gl-ar750&rev=3f1f7c08d440130cce9262a93ce78ed7969d93cd";
|
||||
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,9 +49,9 @@
|
||||
./fmt.nix
|
||||
./shell.nix
|
||||
|
||||
./overlays
|
||||
./machines
|
||||
./routers
|
||||
./phones
|
||||
./inventories
|
||||
./overlays
|
||||
./tests
|
||||
@@ -100,27 +65,12 @@
|
||||
inherit system;
|
||||
overlays = [
|
||||
inputs.self.overlays.packagesOverlay
|
||||
inputs.self.overlays.phpPr576853Overlay # TEMPORARY, see overlays/nixpkgs-pr-576853-php.nix
|
||||
];
|
||||
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;
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
+92
-377
@@ -1,9 +1,5 @@
|
||||
{
|
||||
imports = [
|
||||
./personal-computer.nix
|
||||
./emmie.nix
|
||||
./router.nix
|
||||
];
|
||||
imports = [ ./personal-computer.nix ];
|
||||
clan = {
|
||||
inventory = {
|
||||
|
||||
@@ -11,23 +7,16 @@
|
||||
glom = [
|
||||
"vega"
|
||||
"ramus"
|
||||
"canopus"
|
||||
];
|
||||
poy = [
|
||||
"deneb"
|
||||
"bosona"
|
||||
];
|
||||
w = [
|
||||
"sirius"
|
||||
"stellio"
|
||||
];
|
||||
w = [ "sirius" ];
|
||||
b4l = [
|
||||
"rigel"
|
||||
"neptune"
|
||||
"rana"
|
||||
"petra"
|
||||
"alasia"
|
||||
];
|
||||
phonebox = [
|
||||
"neptune"
|
||||
"rigel"
|
||||
"almach"
|
||||
"alpheratz"
|
||||
@@ -35,193 +24,32 @@
|
||||
"adhil"
|
||||
"buna"
|
||||
];
|
||||
|
||||
prometheus = [
|
||||
"cursa"
|
||||
"rigel"
|
||||
"vega"
|
||||
"buna"
|
||||
];
|
||||
|
||||
dm-bootstrapper = [
|
||||
"rigel"
|
||||
"cursa"
|
||||
"deneb"
|
||||
"bosona"
|
||||
"canopus"
|
||||
];
|
||||
|
||||
dm-pull-deploy = [
|
||||
global-network = [
|
||||
"rana"
|
||||
"rigel"
|
||||
"vega"
|
||||
"sirius"
|
||||
];
|
||||
};
|
||||
|
||||
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/borgbackup/borgbackup.ssh";
|
||||
};
|
||||
};
|
||||
roles.client.machines."hadar".settings.destinations = {
|
||||
alex = {
|
||||
repo = "ssh://borg@10.0.10.225:2222/backup/hadar/backup";
|
||||
rsh = "ssh -i /run/secrets/vars/borgbackup/borgbackup.ssh";
|
||||
};
|
||||
};
|
||||
roles.client.machines."procyon".settings.destinations = {
|
||||
alex = {
|
||||
repo = "ssh://borg@10.0.10.225:2222/backup/procyon/backup";
|
||||
rsh = "ssh -i /run/secrets/vars/borgbackup/borgbackup.ssh";
|
||||
};
|
||||
};
|
||||
roles.client.machines."bosona".settings.destinations = {
|
||||
alex = {
|
||||
repo = "ssh://borg@10.0.10.225:2222/backup/bosona/backup";
|
||||
rsh = "ssh -i /run/secrets/vars/borgbackup/borgbackup.ssh";
|
||||
};
|
||||
};
|
||||
roles.client.machines."canopus".settings.destinations = {
|
||||
alex = {
|
||||
repo = "ssh://borg@10.0.10.225:2222/backup/canopus/backup";
|
||||
rsh = "ssh -i /run/secrets/vars/borgbackup/borgbackup.ssh";
|
||||
};
|
||||
};
|
||||
roles.client.machines."deneb".settings.destinations = {
|
||||
alex = {
|
||||
repo = "ssh://borg@10.0.10.225:2222/backup/deneb/backup";
|
||||
rsh = "ssh -i /run/secrets/vars/borgbackup/borgbackup.ssh";
|
||||
};
|
||||
};
|
||||
roles.client.machines."alasia".settings.destinations = {
|
||||
alex = {
|
||||
repo = "ssh://borg@10.0.10.225:2222/backup/alasia/backup";
|
||||
rsh = "ssh -i /run/secrets/vars/borgbackup/borgbackup.ssh";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
data-mesher = {
|
||||
module = {
|
||||
name = "data-mesher";
|
||||
input = "clan-core";
|
||||
};
|
||||
roles.bootstrap.tags = [ "dm-bootstrapper" ];
|
||||
roles.default.tags = [ "all" ];
|
||||
roles.default.settings.interfaces = [ "ygg" ];
|
||||
};
|
||||
|
||||
auto-pull-update = {
|
||||
module = {
|
||||
name = "dm-pull-deploy";
|
||||
input = "clan-community";
|
||||
};
|
||||
roles.push.machines."rigel".settings = {
|
||||
gitUrl = "https://git.b4l.co.th/newedge/infra.git";
|
||||
branch = "main";
|
||||
};
|
||||
roles.push.extraModules = [
|
||||
(
|
||||
{ pkgs, config, ... }:
|
||||
{
|
||||
# work around until upstream is fixed
|
||||
environment.systemPackages = [
|
||||
(pkgs.writeShellApplication {
|
||||
name = "custom-dm-send-deploy";
|
||||
runtimeInputs = [
|
||||
config.services.data-mesher.package
|
||||
pkgs.git
|
||||
pkgs.nix
|
||||
pkgs.jq
|
||||
];
|
||||
text =
|
||||
let
|
||||
settings.gitUrl = "https://git.b4l.co.th/newedge/infra.git";
|
||||
settings.branch = "main";
|
||||
in
|
||||
''
|
||||
if [ $# -gt 1 ]; then
|
||||
echo "Usage: dm-send-deploy [<flake-ref>]"
|
||||
echo "Without arguments, sends the latest commit on '${settings.branch}' from ${settings.gitUrl}"
|
||||
echo "Example: dm-send-deploy git+https://example.com/repo.git?rev=abc123..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
KEY="${config.clan.core.vars.generators.dm-pull-deploy-signing-key.files."signing.key".path}"
|
||||
if [ ! -r "$KEY" ]; then
|
||||
echo "Error: cannot read signing key at $KEY (are you root?)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ $# -eq 1 ]; then
|
||||
FLAKE_REF="$1"
|
||||
else
|
||||
REV=$(git ls-remote "${settings.gitUrl}" "refs/heads/${settings.branch}" | cut -f1)
|
||||
if [ -z "$REV" ]; then
|
||||
echo "Error: could not determine latest commit on ${settings.branch} from ${settings.gitUrl}"
|
||||
exit 1
|
||||
fi
|
||||
FLAKE_REF="git+${settings.gitUrl}?rev=$REV"
|
||||
fi
|
||||
|
||||
TMPFILE=$(mktemp)
|
||||
trap 'rm -f "$TMPFILE"' EXIT
|
||||
|
||||
printf '%s' "$FLAKE_REF" > "$TMPFILE"
|
||||
|
||||
NETWORK_ID="${config.clan.core.vars.generators.data-mesher-network.files."network.pub".path}"
|
||||
|
||||
data-mesher file update "$TMPFILE" \
|
||||
--url http://localhost:7331 \
|
||||
--network-id "$NETWORK_ID" \
|
||||
--key "$KEY" \
|
||||
--name "dm_pull_deploy/target"
|
||||
|
||||
echo "Deployment target pushed: $FLAKE_REF"
|
||||
'';
|
||||
})
|
||||
];
|
||||
}
|
||||
)
|
||||
];
|
||||
roles.default.tags = [ "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=";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -252,13 +80,7 @@
|
||||
name = "zerotier";
|
||||
input = "clan-core";
|
||||
};
|
||||
roles.controller.machines."vega" = {
|
||||
settings.allowedIds = [
|
||||
"dbe44c0287" # Alex-gateway
|
||||
"b0e0b84fd3" # Alex
|
||||
"2bd36db8cc" # kurogeek-thinkpad
|
||||
];
|
||||
};
|
||||
roles.controller.machines."vega" = { };
|
||||
roles.peer.tags.glom = { };
|
||||
};
|
||||
|
||||
@@ -267,93 +89,36 @@
|
||||
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 = {
|
||||
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.tags."global-network" = { };
|
||||
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"
|
||||
"tls://ygg.jjolly.dev:3443"
|
||||
"tls://[2602:fc24:18:7a42::1]:993"
|
||||
"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 = {
|
||||
yggdrasil-phone-network = {
|
||||
module = {
|
||||
name = "headscale";
|
||||
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";
|
||||
}
|
||||
];
|
||||
};
|
||||
name = "yggdrasil";
|
||||
input = "clan-core";
|
||||
};
|
||||
roles.default.tags."phonebox" = { };
|
||||
roles.default.settings.extraPeers = [
|
||||
"tls://ygg.jjolly.dev:3443"
|
||||
"tls://[2602:fc24:18:7a42::1]:993"
|
||||
"tcp://leo.node.3dt.net:9002"
|
||||
"tcp://ygg-kcmo.incognet.io:8883"
|
||||
];
|
||||
};
|
||||
|
||||
phonebox = {
|
||||
@@ -365,15 +130,64 @@
|
||||
roles.default.machines."adhil".settings = {
|
||||
ata-ethernet-iface = "end0";
|
||||
};
|
||||
roles.default.machines."rigel".settings = {
|
||||
extraClientNumbers = [
|
||||
"01"
|
||||
"02"
|
||||
];
|
||||
extraFixedIPClient = { };
|
||||
};
|
||||
};
|
||||
|
||||
pocket-id = {
|
||||
module = {
|
||||
name = "pocket-id";
|
||||
input = "self";
|
||||
};
|
||||
roles.default.machines.b4l = { };
|
||||
};
|
||||
nextcloud = {
|
||||
module = {
|
||||
name = "nextcloud";
|
||||
input = "self";
|
||||
};
|
||||
roles.default.machines.b4l = { };
|
||||
};
|
||||
stirling-pdf = {
|
||||
module = {
|
||||
name = "stirling-pdf";
|
||||
input = "self";
|
||||
};
|
||||
roles.default.machines.b4l = { };
|
||||
};
|
||||
actual-budget = {
|
||||
module = {
|
||||
name = "actual-budget";
|
||||
input = "self";
|
||||
};
|
||||
roles.default.machines.b4l = { };
|
||||
};
|
||||
victoriametrics = {
|
||||
module = {
|
||||
name = "victoriametrics";
|
||||
input = "self";
|
||||
};
|
||||
roles.default.machines.b4l = { };
|
||||
};
|
||||
vikunja = {
|
||||
module = {
|
||||
name = "vikunja";
|
||||
input = "self";
|
||||
};
|
||||
roles.default.machines.b4l = { };
|
||||
};
|
||||
grafana = {
|
||||
module = {
|
||||
name = "grafana";
|
||||
input = "self";
|
||||
};
|
||||
roles.default.machines.b4l = { };
|
||||
};
|
||||
paperless = {
|
||||
module = {
|
||||
name = "paperless";
|
||||
input = "self";
|
||||
};
|
||||
roles.default.machines.b4l = { };
|
||||
};
|
||||
pulse-stream = {
|
||||
module = {
|
||||
name = "pulse-stream";
|
||||
@@ -466,105 +280,6 @@
|
||||
dataDir = "/mnt/hdd/samba";
|
||||
};
|
||||
};
|
||||
|
||||
wordpress = {
|
||||
module = {
|
||||
name = "wordpress";
|
||||
input = "self";
|
||||
};
|
||||
roles.server.machines."tangra".settings = {
|
||||
tenants = [
|
||||
"poyfestival.com"
|
||||
];
|
||||
phpfpmOptions = ''
|
||||
upload_max_filesize=64M
|
||||
post_max_size=128M
|
||||
'';
|
||||
wpExtraConfig = ''
|
||||
define('WP_MEMORY_LIMIT', '256M');
|
||||
define('WP_DEBUG', false);
|
||||
define('WP_DEBUG_DISPLAY', false);
|
||||
define('WP_DEBUG_LOG', false);
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
prometheus-monitoring = {
|
||||
module = {
|
||||
name = "prometheus";
|
||||
input = "self";
|
||||
};
|
||||
roles.server.machines."cursa".settings = {
|
||||
matrix-alertmanager = {
|
||||
enable = true;
|
||||
homeserverUrl = "https://matrix-client.matrix.org";
|
||||
matrixUser = "@nixapollo:matrix.org";
|
||||
matrixRooms = [
|
||||
{
|
||||
receivers = [
|
||||
"matrix"
|
||||
];
|
||||
roomId = "!rqIrWqPvsXqMgYpcNZ:matrix.org";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
roles.nodes.machines = {
|
||||
vega.settings = {
|
||||
exporters.smartctl = { };
|
||||
exporters.zfs = { };
|
||||
};
|
||||
rigel.settings = {
|
||||
exporters.smartctl = { };
|
||||
};
|
||||
sirius.settings = {
|
||||
exporters.smartctl = { };
|
||||
exporters.zfs = { };
|
||||
};
|
||||
buna.settings = {
|
||||
exporters.smartctl = { };
|
||||
};
|
||||
mirach.settings = {
|
||||
exporters.smartctl = { };
|
||||
};
|
||||
almach.settings = {
|
||||
exporters.smartctl = { };
|
||||
};
|
||||
stellio.settings.exporters.smartctl = { };
|
||||
};
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
)
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -14,9 +14,14 @@
|
||||
instances = {
|
||||
emmie-home = {
|
||||
module = {
|
||||
name = "emmie-home";
|
||||
name = "home-user";
|
||||
input = "self";
|
||||
};
|
||||
roles.default.settings = {
|
||||
username = "emmie";
|
||||
kbLayout = "us,th";
|
||||
kbOptions = "grp:win_space_toggle,grp:alt_shift_toggle";
|
||||
};
|
||||
roles.default.machines."rana" = { };
|
||||
};
|
||||
chocolate-home = {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
+2
-26
@@ -19,40 +19,16 @@
|
||||
"installedAt": 1765277591
|
||||
},
|
||||
"buna": {
|
||||
"installedAt": 1787123510
|
||||
"installedAt": 1765343708
|
||||
},
|
||||
"rana": {
|
||||
"installedAt": 1773134236
|
||||
"installedAt": 1768294839
|
||||
},
|
||||
"petra": {
|
||||
"installedAt": 1769064458
|
||||
},
|
||||
"sirius": {
|
||||
"installedAt": 1770974584
|
||||
},
|
||||
"deneb": {
|
||||
"installedAt": 1775718970
|
||||
},
|
||||
"canopus": {
|
||||
"installedAt": 1775793532
|
||||
},
|
||||
"hadar": {
|
||||
"installedAt": 1774427255
|
||||
},
|
||||
"procyon": {
|
||||
"installedAt": 1775458442
|
||||
},
|
||||
"alasia": {
|
||||
"installedAt": 1778661666
|
||||
},
|
||||
"bosona": {
|
||||
"installedAt": 1779098893
|
||||
},
|
||||
"tangra": {
|
||||
"installedAt": 1779958921
|
||||
},
|
||||
"cursa": {
|
||||
"installedAt": 1782187627
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@
|
||||
# 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)";
|
||||
# clan.meta.description = "Raspberry Pi 4 SBC board for one of w phone network. (With w office)";
|
||||
|
||||
}
|
||||
@@ -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" ];
|
||||
}
|
||||
@@ -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
@@ -8,6 +8,6 @@
|
||||
# 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.";
|
||||
# clan.meta.description = "Radxa X4 SBC board for one of w phone network.";
|
||||
|
||||
}
|
||||
@@ -14,8 +14,6 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
boot.zfs.forceImportRoot = true;
|
||||
|
||||
disko.devices = {
|
||||
disk = {
|
||||
"os-${hashDisk os}" = {
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
# 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.";
|
||||
# clan.meta.description = "Radxa X4 SBC board for one of w phone network.";
|
||||
|
||||
}
|
||||
@@ -14,8 +14,6 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
boot.zfs.forceImportRoot = true;
|
||||
|
||||
disko.devices = {
|
||||
disk = {
|
||||
"os-${hashDisk os}" = {
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
{ self, ... }:
|
||||
{ inputs, config, ... }:
|
||||
{
|
||||
system.stateVersion = "25.11";
|
||||
imports = [
|
||||
(inputs.import-tree ./services)
|
||||
];
|
||||
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";
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
clan.core.vars.generators.acme = {
|
||||
share = true;
|
||||
files.email.secret = false;
|
||||
@@ -24,13 +33,4 @@
|
||||
cat $prompts/email > $out/email
|
||||
'';
|
||||
};
|
||||
|
||||
users.users.nginx.extraGroups = [ "acme" ];
|
||||
|
||||
security.acme.acceptTerms = true;
|
||||
|
||||
imports = [ ];
|
||||
|
||||
# TEMPORARY: wordpress php-fpm pools use pkgs.php; see overlays/nixpkgs-pr-576853-php.nix
|
||||
nixpkgs.overlays = [ self.overlays.phpPr576853Overlay ];
|
||||
}
|
||||
@@ -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}";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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}";
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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.nextcloud32;
|
||||
|
||||
settings = {
|
||||
|
||||
overwriteprotocol = "https";
|
||||
trusted_domains = [ ];
|
||||
trusted_proxies = [ ];
|
||||
};
|
||||
};
|
||||
services.nginx.virtualHosts."${ncDomain}" = {
|
||||
useACMEHost = "${config.networking.fqdn}";
|
||||
forceSSL = true;
|
||||
};
|
||||
}
|
||||
@@ -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}";
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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}";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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}";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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}";
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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}";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,105 +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
|
||||
];
|
||||
|
||||
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" ];
|
||||
}
|
||||
@@ -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
@@ -8,7 +8,6 @@
|
||||
# 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)";
|
||||
# clan.meta.description = "Radxa X4 SBC board for one of w phone network. (With w whitehouse)";
|
||||
|
||||
}
|
||||
+615
-737
File diff suppressed because it is too large.
Load diff
@@ -1,109 +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
|
||||
];
|
||||
|
||||
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" ];
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
let
|
||||
hashDisk = disk: "os-${builtins.substring 0 5 (builtins.hashString "sha256" disk)}";
|
||||
os = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi0";
|
||||
in
|
||||
{
|
||||
|
||||
boot.loader = {
|
||||
systemd-boot = {
|
||||
enable = true;
|
||||
};
|
||||
efi = {
|
||||
canTouchEfiVariables = true;
|
||||
};
|
||||
};
|
||||
|
||||
boot.zfs.forceImportRoot = true;
|
||||
|
||||
disko.devices = {
|
||||
disk = {
|
||||
"os-${hashDisk os}" = {
|
||||
type = "disk";
|
||||
device = os;
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
ESP = {
|
||||
size = "1G";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
mountOptions = [ "nofail" ];
|
||||
};
|
||||
};
|
||||
system = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "zfs";
|
||||
pool = "zroot";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
zpool = {
|
||||
zroot = {
|
||||
type = "zpool";
|
||||
rootFsOptions = {
|
||||
mountpoint = "none";
|
||||
compression = "lz4";
|
||||
acltype = "posixacl";
|
||||
xattr = "sa";
|
||||
"com.sun:auto-snapshot" = "true";
|
||||
};
|
||||
options.ashift = "12";
|
||||
datasets = {
|
||||
"root" = {
|
||||
type = "zfs_fs";
|
||||
options.mountpoint = "none";
|
||||
};
|
||||
"root/nixos" = {
|
||||
type = "zfs_fs";
|
||||
options.mountpoint = "/";
|
||||
mountpoint = "/";
|
||||
};
|
||||
"root/home" = {
|
||||
type = "zfs_fs";
|
||||
options.mountpoint = "/home";
|
||||
mountpoint = "/home";
|
||||
};
|
||||
"root/tmp" = {
|
||||
type = "zfs_fs";
|
||||
mountpoint = "/tmp";
|
||||
options = {
|
||||
mountpoint = "/tmp";
|
||||
sync = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,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" ];
|
||||
}
|
||||
@@ -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
@@ -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"
|
||||
|
||||
@@ -1,126 +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
|
||||
];
|
||||
|
||||
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" ];
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
let
|
||||
hashDisk = disk: "os-${builtins.substring 0 5 (builtins.hashString "sha256" disk)}";
|
||||
os = "/dev/disk/by-id/scsi-0QEMU_QEMU_HARDDISK_drive-scsi0";
|
||||
in
|
||||
{
|
||||
|
||||
boot.loader = {
|
||||
systemd-boot = {
|
||||
enable = true;
|
||||
};
|
||||
efi = {
|
||||
canTouchEfiVariables = true;
|
||||
};
|
||||
};
|
||||
|
||||
boot.zfs.forceImportRoot = true;
|
||||
|
||||
disko.devices = {
|
||||
disk = {
|
||||
"os-${hashDisk os}" = {
|
||||
type = "disk";
|
||||
device = os;
|
||||
content = {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
ESP = {
|
||||
size = "1G";
|
||||
type = "EF00";
|
||||
content = {
|
||||
type = "filesystem";
|
||||
format = "vfat";
|
||||
mountpoint = "/boot";
|
||||
mountOptions = [ "nofail" ];
|
||||
};
|
||||
};
|
||||
system = {
|
||||
size = "100%";
|
||||
content = {
|
||||
type = "zfs";
|
||||
pool = "zroot";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
zpool = {
|
||||
zroot = {
|
||||
type = "zpool";
|
||||
rootFsOptions = {
|
||||
mountpoint = "none";
|
||||
compression = "lz4";
|
||||
acltype = "posixacl";
|
||||
xattr = "sa";
|
||||
"com.sun:auto-snapshot" = "true";
|
||||
};
|
||||
options.ashift = "12";
|
||||
datasets = {
|
||||
"root" = {
|
||||
type = "zfs_fs";
|
||||
options.mountpoint = "none";
|
||||
};
|
||||
"root/nixos" = {
|
||||
type = "zfs_fs";
|
||||
options.mountpoint = "/";
|
||||
mountpoint = "/";
|
||||
};
|
||||
"root/home" = {
|
||||
type = "zfs_fs";
|
||||
options.mountpoint = "/home";
|
||||
mountpoint = "/home";
|
||||
};
|
||||
"root/tmp" = {
|
||||
type = "zfs_fs";
|
||||
mountpoint = "/tmp";
|
||||
options = {
|
||||
mountpoint = "/tmp";
|
||||
sync = "disabled";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,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" ];
|
||||
}
|
||||
@@ -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
@@ -8,6 +8,6 @@
|
||||
# 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.";
|
||||
# clan.meta.description = "Radxa X4 SBC board for one of w phone network.";
|
||||
|
||||
}
|
||||
@@ -14,8 +14,6 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
boot.zfs.forceImportRoot = true;
|
||||
|
||||
disko.devices = {
|
||||
disk = {
|
||||
"os-${hashDisk os}" = {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
};
|
||||
system.stateVersion = "25.11";
|
||||
clan.core.sops.defaultGroups = [ "admins" ];
|
||||
clan.core.networking.targetHost = "root@[${config.clan.core.vars.generators.zerotier.files.zerotier-ip.value}]";
|
||||
|
||||
networking.interfaces.enx00e04c106368.useDHCP = true; # recovery
|
||||
|
||||
@@ -56,6 +57,6 @@
|
||||
];
|
||||
|
||||
clan.core.settings.name = "neptune";
|
||||
clan.core.settings.machine.description = "Radxa SBC board for testing. (With vi)";
|
||||
# clan.meta.description = "Radxa SBC board for testing. (With vi)";
|
||||
|
||||
}
|
||||
@@ -14,8 +14,6 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
boot.zfs.forceImportRoot = true;
|
||||
|
||||
disko.devices = {
|
||||
disk = {
|
||||
"os-${hashDisk os}" = {
|
||||
|
||||
@@ -9,5 +9,4 @@
|
||||
};
|
||||
system.stateVersion = "25.11";
|
||||
clan.core.sops.defaultGroups = [ "admins" ];
|
||||
clan.core.settings.machine.description = "A personal computer for Chocolate Shop";
|
||||
}
|
||||
@@ -14,8 +14,6 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
boot.zfs.forceImportRoot = true;
|
||||
|
||||
disko.devices = {
|
||||
disk = {
|
||||
"os-${hashDisk os}" = {
|
||||
|
||||
@@ -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" ];
|
||||
}
|
||||
@@ -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
@@ -6,9 +6,12 @@
|
||||
};
|
||||
|
||||
clan.core.settings.name = "ramus";
|
||||
clan.core.settings.machine.description = "A Hetzner VPS machine own by Alex.";
|
||||
# clan.meta.description = ''
|
||||
# A Hetzner VPS machine own by Alex.
|
||||
# '';
|
||||
|
||||
clan.core.sops.defaultGroups = [ "admins" ];
|
||||
clan.core.networking.targetHost = "root@[${config.clan.core.vars.generators.zerotier.files.zerotier-ip.value}]";
|
||||
|
||||
clan.core.vars.generators.acme = {
|
||||
share = true;
|
||||
|
||||
@@ -14,8 +14,6 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
boot.zfs.forceImportRoot = true;
|
||||
|
||||
disko.devices = {
|
||||
disk = {
|
||||
"os-${hashDisk os}" = {
|
||||
|
||||
@@ -54,10 +54,7 @@ in
|
||||
self.nixosModules.think-gtcm
|
||||
self.nixosModules.think-backend-gtcm
|
||||
];
|
||||
nixpkgs.overlays = [
|
||||
self.overlays.packagesOverlay
|
||||
self.overlays.phpPr576853Overlay # TEMPORARY, see overlays/nixpkgs-pr-576853-php.nix
|
||||
];
|
||||
nixpkgs.overlays = [ self.overlays.packagesOverlay ];
|
||||
|
||||
clan.core.vars.generators.greaterchiangmai = {
|
||||
files = {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
{ self, pkgs, ... }:
|
||||
{ self, ... }:
|
||||
{
|
||||
clan.core.settings.machine.description = "Emmie personal computer";
|
||||
|
||||
imports = [
|
||||
self.nixosModules.common
|
||||
];
|
||||
@@ -11,12 +9,4 @@
|
||||
};
|
||||
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;
|
||||
}
|
||||
@@ -14,8 +14,6 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
boot.zfs.forceImportRoot = true;
|
||||
|
||||
disko.devices = {
|
||||
disk = {
|
||||
"os-${hashDisk os}" = {
|
||||
@@ -55,9 +53,6 @@ in
|
||||
zroot = {
|
||||
type = "zpool";
|
||||
rootFsOptions = {
|
||||
encryption = "aes-256-gcm";
|
||||
keyformat = "passphrase";
|
||||
keylocation = "file:///tmp/secret.key";
|
||||
mountpoint = "none";
|
||||
compression = "lz4";
|
||||
acltype = "posixacl";
|
||||
|
||||
+681
-779
File diff suppressed because it is too large.
Load diff
@@ -1,7 +1,16 @@
|
||||
{ config, ... }:
|
||||
{
|
||||
imports = [
|
||||
(import ../../lib/auto-accept-zerotier-members.nix {
|
||||
memberIds = [
|
||||
"dbe44c0287" # Alex-gateway
|
||||
"b0e0b84fd3" # Alex
|
||||
"2bd36db8cc" # kurogeek-thinkpad
|
||||
];
|
||||
})
|
||||
];
|
||||
|
||||
system.stateVersion = "25.11";
|
||||
clan.core.sops.defaultGroups = [ "admins" ];
|
||||
|
||||
clan.core.settings.machine.description = "Zima board computer for testing in B4L";
|
||||
clan.core.networking.targetHost = "root@[${config.clan.core.vars.generators.zerotier.files.zerotier-ip.value}]";
|
||||
}
|
||||
@@ -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
|
||||
```
|
||||
@@ -1,32 +1,27 @@
|
||||
{
|
||||
config,
|
||||
self,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
imports = [
|
||||
./hardware-configuration.nix
|
||||
self.nixosModules.common
|
||||
];
|
||||
|
||||
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.journald.extraConfig = ''
|
||||
Storage=volatile
|
||||
RuntimeMaxUse=30M
|
||||
RuntimeMaxFileSize=10M
|
||||
'';
|
||||
|
||||
services.udisks2.enable = false;
|
||||
|
||||
nix.settings.log-lines = 25;
|
||||
@@ -37,72 +32,4 @@
|
||||
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";
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
@@ -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" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
{ lib, ... }:
|
||||
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"
|
||||
];
|
||||
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 = {
|
||||
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" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
// (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" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -1,6 +0,0 @@
|
||||
{
|
||||
fileSystems."/" = {
|
||||
device = "/dev/disk/by-uuid/44444444-4444-4444-8888-888888888888";
|
||||
fsType = "ext4";
|
||||
};
|
||||
}
|
||||
@@ -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";
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -10,11 +10,17 @@
|
||||
|
||||
(inputs.import-tree ./services)
|
||||
|
||||
(import ../../lib/auto-accept-zerotier-members.nix {
|
||||
memberIds = [
|
||||
"dbe44c0287" # Alex-gateway
|
||||
"b0e0b84fd3" # Alex
|
||||
"2bd36db8cc" # kurogeek-thinkpad
|
||||
];
|
||||
})
|
||||
];
|
||||
|
||||
clan.core.sops.defaultGroups = [ "admins" ];
|
||||
|
||||
clan.core.settings.machine.description = "Glom NAS";
|
||||
clan.core.networking.targetHost = "root@[${config.clan.core.vars.generators.zerotier.files.zerotier-ip.value}]";
|
||||
|
||||
nixpkgs.hostPlatform = {
|
||||
system = "x86_64-linux";
|
||||
|
||||
@@ -18,8 +18,6 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
boot.zfs.forceImportRoot = true;
|
||||
|
||||
disko.devices = {
|
||||
disk = {
|
||||
"os-${hashDisk os}" = {
|
||||
|
||||
@@ -82,11 +82,8 @@ in
|
||||
};
|
||||
|
||||
services.avahi = {
|
||||
settings.publish = {
|
||||
disable-publishing = false;
|
||||
disable-user-service-publishing = false;
|
||||
publish-addresses = true;
|
||||
};
|
||||
publish.enable = true;
|
||||
publish.userServices = 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
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
name = "service-actual-budget";
|
||||
|
||||
clan = {
|
||||
test.useContainers = false;
|
||||
directory = ./.;
|
||||
inventory = {
|
||||
machines.server = { };
|
||||
|
||||
@@ -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.
|
||||
@@ -1,139 +0,0 @@
|
||||
{ clanLib, ... }:
|
||||
{
|
||||
_class = "clan.service";
|
||||
manifest.name = "apple-network";
|
||||
manifest.description = "This service will create an instance of `atalkd` for each peer to talk to Apple machines over Apple Talk protocol and automatically connect each peer using vxlan over Yggdrasil network to achieve Apple Talk over internet experience";
|
||||
manifest.readme = builtins.readFile ./README.md;
|
||||
manifest.categories = [ "Network" ];
|
||||
|
||||
roles.peer = {
|
||||
description = "A gateway machine that allow classic Apple machines to connect to other Apple machines over the internet";
|
||||
|
||||
interface =
|
||||
{ lib, ... }:
|
||||
{
|
||||
options = {
|
||||
zone_name = lib.mkOption {
|
||||
type = with lib.types; str;
|
||||
description = "Zone name for Apple Talk protocol";
|
||||
default = "Default";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
perInstance =
|
||||
{ roles, settings, ... }:
|
||||
{
|
||||
nixosModule =
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}:
|
||||
let
|
||||
vxlanPort = 4789;
|
||||
|
||||
getYggdrasilIP =
|
||||
machineName:
|
||||
if config.clan.core.vars.generators.yggdrasil.files.address ? value then
|
||||
clanLib.getPublicValue {
|
||||
flake = config.clan.core.settings.directory;
|
||||
machine = machineName;
|
||||
generator = "yggdrasil";
|
||||
file = "address";
|
||||
default = null;
|
||||
}
|
||||
else
|
||||
throw "clanService/yggdrasil is required";
|
||||
|
||||
noSelfPeers = builtins.filter (peerName: peerName != config.clan.core.settings.machine.name) (
|
||||
lib.mapAttrsToList (machineName: _: machineName) roles.peer.machines
|
||||
);
|
||||
|
||||
sortedPeers = builtins.sort (x: y: x < y) (
|
||||
lib.mapAttrsToList (machineName: _: machineName) roles.peer.machines
|
||||
);
|
||||
|
||||
getMachineIndex = machineName: lib.lists.findFirstIndex (x: x == machineName) null sortedPeers;
|
||||
|
||||
selfVXAddress = "192.168.254.${
|
||||
lib.toString ((getMachineIndex config.clan.core.settings.machine.name) + 1)
|
||||
}/24";
|
||||
in
|
||||
{
|
||||
|
||||
services.atalkd = {
|
||||
enable = true;
|
||||
interfaces = {
|
||||
vxlan.config = ''
|
||||
-router -phase 2 -net 1 -zone "${settings.zone_name}"
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
networking.useNetworkd = true;
|
||||
|
||||
networking.firewall.interfaces."ygg".allowedUDPPorts = [ vxlanPort ];
|
||||
|
||||
boot.kernelModules = [ "vxlan" ];
|
||||
|
||||
systemd.network.netdevs =
|
||||
builtins.listToAttrs (
|
||||
map (
|
||||
peerName:
|
||||
(lib.nameValuePair "10-apl-vxlan-${peerName}" {
|
||||
enable = true;
|
||||
netdevConfig = {
|
||||
Name = "vxlan-${peerName}";
|
||||
Kind = "vxlan";
|
||||
};
|
||||
vxlanConfig = {
|
||||
VNI = (getMachineIndex config.clan.core.settings.machine.name) + (getMachineIndex peerName);
|
||||
Remote = getYggdrasilIP peerName;
|
||||
DestinationPort = vxlanPort;
|
||||
Independent = true;
|
||||
};
|
||||
})
|
||||
) noSelfPeers
|
||||
)
|
||||
// {
|
||||
"10-apl-vxlan" = {
|
||||
enable = true;
|
||||
netdevConfig = {
|
||||
Kind = "bridge";
|
||||
Name = "vxlan";
|
||||
};
|
||||
bridgeConfig = {
|
||||
STP = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.network.networks =
|
||||
builtins.listToAttrs (
|
||||
map (
|
||||
peerName:
|
||||
(lib.nameValuePair "10-apl-vxlan-${peerName}" {
|
||||
enable = true;
|
||||
matchConfig.Name = "vxlan-${peerName}";
|
||||
networkConfig.Bridge = "vxlan";
|
||||
})
|
||||
) noSelfPeers
|
||||
)
|
||||
// {
|
||||
"10-apl-vxlan" = {
|
||||
enable = true;
|
||||
matchConfig.Name = "vxlan";
|
||||
address = [ selfVXAddress ];
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = [
|
||||
pkgs.netatalk
|
||||
pkgs.bridge-utils
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
{ inputs, self, ... }:
|
||||
let
|
||||
module = ./default.nix;
|
||||
in
|
||||
{
|
||||
clan.modules = {
|
||||
apple-network = module;
|
||||
};
|
||||
perSystem =
|
||||
{ ... }:
|
||||
{
|
||||
clan.nixosTests.service-apple-network = {
|
||||
imports = [ ./tests/vm/default.nix ];
|
||||
_module.args = { inherit self inputs; };
|
||||
|
||||
clan.modules."@clan/apple-network" = module;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
{
|
||||
self,
|
||||
lib,
|
||||
config,
|
||||
hostPkgs,
|
||||
...
|
||||
}:
|
||||
{
|
||||
name = "service-apple-network";
|
||||
|
||||
result.update-vars =
|
||||
let
|
||||
relativeDir = lib.removePrefix "${self}/" (toString config.clan.directory);
|
||||
in
|
||||
hostPkgs.writeShellScriptBin "update-vars" ''
|
||||
set -x
|
||||
export PRJ_ROOT=$(git rev-parse --show-toplevel)
|
||||
${
|
||||
self.inputs.clan-core.packages.${hostPkgs.system}.clan-cli
|
||||
}/bin/clan-generate-test-vars $PRJ_ROOT/${relativeDir} ${config.name}
|
||||
'';
|
||||
|
||||
clan = {
|
||||
directory = ./.;
|
||||
test.useContainers = false;
|
||||
|
||||
inventory = {
|
||||
meta.domain = "test.clan";
|
||||
|
||||
machines.peer1 = { };
|
||||
machines.peer2 = { };
|
||||
machines.peer3 = { };
|
||||
|
||||
instances = {
|
||||
apple-network = {
|
||||
module.name = "@clan/apple-network";
|
||||
module.input = "self";
|
||||
roles.peer.machines = {
|
||||
peer1 = { };
|
||||
peer2 = { };
|
||||
peer3 = { };
|
||||
};
|
||||
};
|
||||
yggdrasil = {
|
||||
module.name = "yggdrasil";
|
||||
roles.default.tags.all = { };
|
||||
roles.default.settings.extraPeers = [
|
||||
"tls://ygg.jjolly.dev:3443"
|
||||
"tls://[2602:fc24:18:7a42::1]:993"
|
||||
"tcp://leo.node.3dt.net:9002"
|
||||
"tcp://ygg-kcmo.incognet.io:8883"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nodes = {
|
||||
peer1 = { };
|
||||
peer2 = { };
|
||||
peer3 = { };
|
||||
};
|
||||
|
||||
testScript = _: ''
|
||||
# cannot test connectivity due to Yggdrasil's establishment
|
||||
start_all()
|
||||
peer1.wait_for_unit("atalkd")
|
||||
peer1.succeed("systemctl status atalkd")
|
||||
|
||||
peer2.wait_for_unit("atalkd")
|
||||
peer2.succeed("systemctl status atalkd")
|
||||
|
||||
peer3.wait_for_unit("atalkd")
|
||||
peer3.succeed("systemctl status atalkd")
|
||||
'';
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
[
|
||||
{
|
||||
"publickey": "age1f92zl8y70z5w9gn0l5leg2fhyvxy6m93dfh7n6ltgvuu9nyg6epsrw6t8x",
|
||||
"type": "age"
|
||||
}
|
||||
]
|
||||
@@ -1,6 +0,0 @@
|
||||
[
|
||||
{
|
||||
"publickey": "age1u36fr87cru90vfznf5szasya9nhvvseh4atk8zsdj0rrsu0nnvwqsyt8g6",
|
||||
"type": "age"
|
||||
}
|
||||
]
|
||||
@@ -1,6 +0,0 @@
|
||||
[
|
||||
{
|
||||
"publickey": "age1rka3368ltqc787xw99uu762lqfk7qxld9265u2t62fpxnp9xhufsc2q5rw",
|
||||
"type": "age"
|
||||
}
|
||||
]
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"data": "ENC[AES256_GCM,data:hC4Lle6mXuTFq//wBHUTyH3X778u/gYJSXJOiQ7xUb+gnC8beH1olxL2ZhtUiMkktzhsPM/j6cxhltPp25UTeJnUOcoYesqZcp8=,iv:WOx2P2Cu4v58xM9ePjAw1gdA0fFnGG2UqEXH2iksGoo=,tag:43n1ibVSy2AeS9f5qQBKNQ==,type:str]",
|
||||
"sops": {
|
||||
"age": [
|
||||
{
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtT244N1Q3Zk9pRjFFQlUr\ncDExSTBwSWk5UXVyMjhWclQwSFZaYnpTRFY0CnE5YStVdzMrS3BKYzYvc3V3QVFY\nbDVwVytoNERveU1xQllqNUFGV2hYbGMKLS0tIDJSUmkwMUQzL3Y0MU5qZTJ3eFN3\nNGdwamM1UDBPdzhvSWsyZzR6anZ0eFEKKnr1/7rf3fH1i7KUoZdilLDgb44K2qzn\nI9Y+7FbV4gzQUzKWjAQeFN37Z4Qiuy0xJVA0lw8KvM+NCxSZDfh3kw==\n-----END AGE ENCRYPTED FILE-----\n",
|
||||
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
|
||||
}
|
||||
],
|
||||
"lastmodified": "2026-07-03T10:46:56Z",
|
||||
"mac": "ENC[AES256_GCM,data:hmpbOtra6EyNiPg7EsA3F4elHEO87JPUr4VKVppvzUwLX1HSj67WrU6k3rEoJT+k7Hq1lxnAzDEckSG1fUOap11rk8ksp1IAGR0+yqykC/Qj/Nl8wXqP84gr49bJK6xE/DDdCRCcBff2d6IpnehyEr8fGFEZbWGygblec8U8GPo=,iv:+M1C3rL22foowr0VD80jwrNFb5xz4k5JQ/DJm4ThKHk=,tag:wabFAC5NTCVGfIQQzm0yGg==,type:str]",
|
||||
"version": "3.13.1"
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../../users/admin
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"data": "ENC[AES256_GCM,data:ndWIEOqP2ybCN7Ak5g+8q3YG5rLQ7OuSv/vCbnMA8AK6Lby2JMGRkRGysqJdyEF7eh4w7PpZ/AtKPtPbUucjeTB5+8g76PPJTBE=,iv:EYy0GGqEBmIc5rSWP7Zleb5eQ0JzTz84HqeJPpCSpxk=,tag:iMgTUb9+wxE9S2kKoOEvsQ==,type:str]",
|
||||
"sops": {
|
||||
"age": [
|
||||
{
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQTEF6OXN4K0dHdXhWWmt2\neG5wdkNIc2F0UnFEeHFLQkdTWkFpUWhTa0NBCmw2N2J1T0FJVE9JR3VBRWV0THh5\nVEZlbVZrcXAwK3BsYXFOZUF6c3lRSkUKLS0tIFRCQzNUaGFHdERWNWR4enVWRGpx\nbDEzRU9jWHgxWHovaENjbkFlZERIbkkKvAW31gTJg9izrWuAMeDHS9SWPQYtxRBY\necDCn8QORFrnDdxEusCnGJrAU4kmS3Y3CwSHCtEijs3JdIgg9wl/MA==\n-----END AGE ENCRYPTED FILE-----\n",
|
||||
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
|
||||
}
|
||||
],
|
||||
"lastmodified": "2026-07-03T10:47:04Z",
|
||||
"mac": "ENC[AES256_GCM,data:y1U2vsdqR97fPAnp6iZiLY1KbWYmgDqgZ5bwIkWPCr7Gjjrn+qV+sc2T1BTVz3Zo0JOz4ScCc+f6snVsFKdCDU/NmDVFt/sqyH4NHUPRQ3StsQim8C7IkSwUtm3EhrqpLYFD21MEjrYYdHMHbWybxrOI0qI6mDwZymHJFeCLdQA=,iv:lVvPn69eQE/huwDmwePepfpi2l9ZOPQO7W20o4AJBFQ=,tag:7VPfjKZsBVJTZxNwTcI6sg==,type:str]",
|
||||
"version": "3.13.1"
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../../users/admin
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"data": "ENC[AES256_GCM,data:JPdetkhtF9eSmgEfCO2exXlGQ5KWLeIM3mnW5BfyTY8r0PxWSEGAwBskC1SiDdRERWB2VEbPiPgCNXMnGaYlDqSdZN6R9wSFvsQ=,iv:qGveNhUtgxvKnmdsPoPpffKyi5srlq0Pd6aW283B5C0=,tag:TcJsCrBlzfjXvztcRaxYFQ==,type:str]",
|
||||
"sops": {
|
||||
"age": [
|
||||
{
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvdjNHa1RlcFJHazB5TXFu\nOUQ4REpCZm5Yc3ZhcVhwT1FqRHlvbnoxZWlFCnNrVUEyK2ZYSmlacmJ2b2QrclZl\nSDV1eWxXVmJxZlhMMXgrTWtjcjVhQlkKLS0tIHZPN3pCUVBLQmpRVGx6SDBQNDZo\nSitheGhXNGl5QW9HTGNsTTdTdWVwaE0KfuM5xZOPbR1lxkJPJUOVrtlW5Ujobemp\nid40reDqxKQxP3khJv8lf9ZoN8LAx2Iwh0DeAl+UJpsoVWgS7uI2qQ==\n-----END AGE ENCRYPTED FILE-----\n",
|
||||
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
|
||||
}
|
||||
],
|
||||
"lastmodified": "2026-07-07T04:54:10Z",
|
||||
"mac": "ENC[AES256_GCM,data:Tt8yqzfAnSDe2n7KDt1Z/D73hkS1w7DsqIh+s5WljLzar9PEt5vUCLb8DIvBwITyzGAoHH1ym3v3NrnJWCdxajKExTMBf4aY3MJCtykeCG37701S/KxumjTW9/fJw74gcET5I6NafTWb6H5XHsrRaQX1Xnspcs8B7uLGZZ28dSM=,iv:Fo5UPVhnjuOx6Cp4grofHOiD2pm0TXuRRuoTwvxKn1s=,tag:VQ/TF1TiyJADj7/3RwPCAg==,type:str]",
|
||||
"version": "3.13.1"
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
../../../users/admin
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"publickey": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
|
||||
"type": "age"
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
26.11
|
||||
@@ -1 +0,0 @@
|
||||
200:e6cc:c86:f02d:b0d5:fba9:9b2c:eb77
|
||||
-1
@@ -1 +0,0 @@
|
||||
../../../../../../sops/machines/peer1
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"data": "ENC[AES256_GCM,data:6YDp5S2TzEnhDgGhcz8cA3uBsfDt0Oc4JpztB1JUcg/+tDBbeaQN4MLxuZKstXn2Hb1mYtBLlX0vHw++T181Js2sIznyfC1lr68GOvQAp4NYgf23dXpdZk/CMPNUMiGOYVwKWQ/Z0/p0azJ6xV29dYQcM4Q9hys=,iv:Ijzz8hm0looCWoSpjg/rYKp9jhvzRuLboKWHrlwVeFA=,tag:kJcH/1Pu+9q9f2J68LETug==,type:str]",
|
||||
"sops": {
|
||||
"age": [
|
||||
{
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYNDNEL3kvdEpEMjYyOFJG\nMk5adU04M3hxa21jTTZNM2dQREpmUlVES1NvCjh6eDNFZ1hzUVlTY3Nidnp3TkYr\nRVl4TFlrNUE3dVIzZzg2VWMwTFBYUXMKLS0tIFE0dVFQQmxwOFJ6YkdaQlh6dUlW\nTi8rdXdQbGR1eXpLcTdOandqQmxka3cKImbmJQo2YMYMSQD8kNTgol3VJ4YGIaoz\nl3AY4u/fobg5qlzVQwV33G0/Wf72Z2aTjSLnP4thnasQ89PdYvs7hA==\n-----END AGE ENCRYPTED FILE-----\n",
|
||||
"recipient": "age1f92zl8y70z5w9gn0l5leg2fhyvxy6m93dfh7n6ltgvuu9nyg6epsrw6t8x"
|
||||
},
|
||||
{
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiaWw5SU9KWmJnVVVmTVpr\nL1V6RnRYUGg2UnhXR1BnVTh5eFhnNFpidGdjCmdMeU1nZkZmTTVwbkNaVElFa0Z4\nVkdGdjc4c2lPWGNrVGxocE9iQUZ3QTAKLS0tIHIzTzRRbXVkM3I4ZVRxeSs5eHV5\nTUxOaytzb2MxQ2UybkVCYWVWVmVEcUEKPeK+CC7r3CP5BJqg9thWNHWjPBp/ueHU\nRif6T79kqf+c3B34qXwR0zfyM1+a0r9GAVVC2/q+Ha/As5sPJU39ww==\n-----END AGE ENCRYPTED FILE-----\n",
|
||||
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
|
||||
}
|
||||
],
|
||||
"lastmodified": "2026-07-03T10:46:56Z",
|
||||
"mac": "ENC[AES256_GCM,data:PffiPU1GR9DojTb7TxzBkpivKV2ybmmq9h4pOOyq7p5BAIPF+JSe+BDtbItQ+Gn5LnitQRUVvhat8E2iYfz3JgNxNKcsNFU/mWtCz3PlqyiuRzUBtEL3zYfhdMi8hYYlVdfMumaK3VMk+b4uDGExR+MpURL97TFku47qRbzbILs=,iv:3//fj7WtIX2QNYB9ub1JKAFIn5vJeuZl6rqaEsX0oQc=,tag:njU+WAVq7xBgE0sna2dMKA==,type:str]",
|
||||
"version": "3.13.1"
|
||||
}
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
../../../../../../sops/users/admin
|
||||
@@ -1 +0,0 @@
|
||||
8c99f9bc87e92795022b32698a440d6f9fe01d1110f867de8176bb190b92acab
|
||||
@@ -1 +0,0 @@
|
||||
26.11
|
||||
@@ -1 +0,0 @@
|
||||
200:eb95:7d1b:3ac3:62e7:24af:2274:3771
|
||||
-1
@@ -1 +0,0 @@
|
||||
../../../../../../sops/machines/peer2
|
||||
-18
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"data": "ENC[AES256_GCM,data:vOwMqT12A5ap5hRvCGTjTUX4sXKO3N7KE8eQ+/SCcBWndU9/b2AehiNgplWWMGcYdmeDL9qI8V2pPkgBkQ/tWH6N8DccSM/zQzrBUkXvRApl6hvNZAWuBVf/P4MW4/EbRGtMg2tEXkaPDtRn2TsDK7ygmXmqArI=,iv:FkxFx/ClAftLu85S6Uq3ZOom+YDOpeWGlYLOFBmFfnk=,tag:zprw62qiu+hmLZEZbnqYXA==,type:str]",
|
||||
"sops": {
|
||||
"age": [
|
||||
{
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0WVB1M2ttd0FocGhTSjNo\nUDFIcmpsL051TndWbkJVakJHbUxjY3Q3NjM0CnkrbFlHS1E4bkZJQTIvMDJ3VDFv\nNW1OdmwvalBEelN2d3YwbHVqTW94OFEKLS0tIGtpOWxCM29xdXhQL2Yzb094OG1n\nT21mc25yU1dJL29vekRHdldzdDR3dEkKoZ1dPRaPg8iVsuec6IhV3cLPchokV2wv\nu6qb92hsLQuyPHDA01Oey0jxmaYMQGtAVjo2zEM+E+zrKY+f2pHIUQ==\n-----END AGE ENCRYPTED FILE-----\n",
|
||||
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg"
|
||||
},
|
||||
{
|
||||
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArcmo5d2x6c3J0YTkwMGJE\nanphd2FiUjdGdmdNeW0rL0FpcTVSM3dublZ3CnphajNVV2YrTGl2a3ZqMTJKeU4v\nTzZRS2F5MlA5Ny84cFFoNWZQZnpBZTgKLS0tIHVKQUJWcmlPdy9GNXNBYnpJcEVC\nNmJVMlpvSzZPdk1JY2hIZVEvc3cwV2MKE/cMJU/j5g62njJ49AfnLutmxkpz/gxX\nIqWe1m7Uxl/awVFa7F8N7TUkd0jLbAGXZaonDjiBxOTwg/jr/apnuQ==\n-----END AGE ENCRYPTED FILE-----\n",
|
||||
"recipient": "age1u36fr87cru90vfznf5szasya9nhvvseh4atk8zsdj0rrsu0nnvwqsyt8g6"
|
||||
}
|
||||
],
|
||||
"lastmodified": "2026-07-03T10:47:04Z",
|
||||
"mac": "ENC[AES256_GCM,data:wiIkwEDwGJZe0u8qLHthPkCXubeIGyHV8yBo8CsSengLVTOtRZ877zTrFvE74ATF1pGE3DFJ5qGRrOGgKJ4VOl043LbEBs0bxZC495pPMPYszimp2UAf/XE3QWlNi9p4Ce/kbvUDd0W3SRt4hIv6HOLWApiRoqfS2qSMUnBQeW0=,iv:Hs7EysUnje/iWZRhJLlqf8wuFJnIMpWfXWHrilfmM5I=,tag:Rgj9x4ZOM2fihKKNQ4ux3g==,type:str]",
|
||||
"version": "3.13.1"
|
||||
}
|
||||
}
|
||||
-1
@@ -1 +0,0 @@
|
||||
../../../../../../sops/users/admin
|
||||
@@ -1 +0,0 @@
|
||||
8a354172629e4e8c6da86ec5e447411e4238cf7bb439b798fae56509a82d7472
|
||||
Loaded 100 of 1431 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user