1
0

Compare commits

..

19 Commits

Author SHA1 Message Date
Flake Update Bot
9cd78ef9c3 Update nixpkgs 2025-10-28-02-03 2025-10-28 03:03:19 +01:00
f3629c2653 profiles/ds-lite: Connect to Netcologne with PPP DS-Lite 2025-10-27 21:26:28 +01:00
44afbff445 hosts/carbon: Change DSL uplink to netcologne 2025-10-24 21:36:41 +02:00
92817fdcad hosts/clerie-backup: Export metrics for backup replication to Hetzner 2025-10-24 18:13:24 +02:00
e8cca7b1b6 pkgs/http.server: Add shortcut command for python3 http.server 2025-10-07 19:11:22 +02:00
102509b9a8 hosts/krypton: Add tuba and flare apps 2025-09-27 18:43:16 +02:00
eaa4ee6d05 hosts/storage-2: Provide mixcloud directory listing as json too 2025-09-26 15:51:55 +02:00
9659885079 pkgs/grow-last-partition-and-filesystem: Add missing dependency reference 2025-09-21 18:02:14 +02:00
50b575dcb3 hosts/storage-2: Convert em to mp3 2025-09-21 18:01:46 +02:00
165839be07 pkgs/convert-flac-dir-to-mp3: Use tmpfile for ffmpeg so we don't have broken files laying around 2025-09-21 17:18:08 +02:00
ce99bb114b pkgs/convert-flac-dir-to-mp3: Add script for coverting music libraries 2025-09-21 17:06:36 +02:00
23629e0662 pkgs/build-support: writePythonScript add runtimeInput option 2025-09-21 16:58:15 +02:00
6954e75a5c pkgs/grow-last-partition-and-filesystem: Automatically move GPT backup header to end of device 2025-09-21 14:36:04 +02:00
539502cea0 flake.lock: Update mu5001tool 2025-09-12 00:10:03 +02:00
00a7eee2af hosts/astatine: Update mu5001tool and restart on failure 2025-09-11 12:39:04 +02:00
e82132b86e hosts/astatine: Add stack to monitor zte hypermobile 5g 2025-09-08 23:32:57 +02:00
503dca182e pkgs/curl-timings: Add curl shortcut to show connection timings 2025-09-03 13:05:55 +02:00
82f8064956 pkgs/grow-last-partition-and-filesystem: Add command to easily grow a filesystem on a disk resized by Proxmox 2025-08-30 11:11:57 +02:00
342d50d936 pkgs/bijwerken-system-upgrade: Copy system store path from any configured nix cache 2025-08-30 09:52:25 +02:00
35 changed files with 773 additions and 53 deletions

View File

@@ -6,6 +6,7 @@
# My system is fucked # My system is fucked
gptfdisk gptfdisk
parted parted
grow-last-partition-and-filesystem
# Normal usage # Normal usage
htop htop

27
flake.lock generated
View File

@@ -404,6 +404,26 @@
"url": "https://git.clerie.de/clerie/mitel_ommclient2.git" "url": "https://git.clerie.de/clerie/mitel_ommclient2.git"
} }
}, },
"mu5001tool": {
"inputs": {
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1757627777,
"narHash": "sha256-NGUqHQ+/BaUhjgSYQauTihTtNyhhnQRMJ8t7ZSPNpmk=",
"ref": "refs/heads/main",
"rev": "b7b0f0d5191433bca1377f7d818b800627a83fda",
"revCount": 9,
"type": "git",
"url": "https://git.clerie.de/clerie/mu5001tool.git"
},
"original": {
"type": "git",
"url": "https://git.clerie.de/clerie/mu5001tool.git"
}
},
"nix2container": { "nix2container": {
"flake": false, "flake": false,
"locked": { "locked": {
@@ -646,11 +666,11 @@
}, },
"nixpkgs_5": { "nixpkgs_5": {
"locked": { "locked": {
"lastModified": 1756266583, "lastModified": 1761373498,
"narHash": "sha256-cr748nSmpfvnhqSXPiCfUPxRz2FJnvf/RjJGvFfaCsM=", "narHash": "sha256-Q/uhWNvd7V7k1H1ZPMy/vkx3F8C13ZcdrKjO7Jv7v0c=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "8a6d5427d99ec71c64f0b93d45778c889005d9c2", "rev": "6a08e6bb4e46ff7fcbb53d409b253f6bad8a28ce",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -743,6 +763,7 @@
"hydra": "hydra", "hydra": "hydra",
"lix": "lix_2", "lix": "lix_2",
"lix-module": "lix-module", "lix-module": "lix-module",
"mu5001tool": "mu5001tool",
"nixos-exporter": "nixos-exporter", "nixos-exporter": "nixos-exporter",
"nixos-hardware": "nixos-hardware", "nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs_5", "nixpkgs": "nixpkgs_5",

View File

@@ -40,6 +40,10 @@
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
fieldpoc.url = "git+https://git.clerie.de/clerie/fieldpoc.git"; fieldpoc.url = "git+https://git.clerie.de/clerie/fieldpoc.git";
mu5001tool = {
url = "git+https://git.clerie.de/clerie/mu5001tool.git";
inputs.nixpkgs.follows = "nixpkgs";
};
nixos-exporter = { nixos-exporter = {
url = "git+https://git.clerie.de/clerie/nixos-exporter.git"; url = "git+https://git.clerie.de/clerie/nixos-exporter.git";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";

View File

@@ -5,6 +5,7 @@
, chaosevents , chaosevents
, harmonia , harmonia
, hydra , hydra
, mu5001tool
, nurausstieg , nurausstieg
, rainbowrss , rainbowrss
, scan-to-gpg , scan-to-gpg
@@ -25,6 +26,8 @@ final: prev: {
harmonia; harmonia;
inherit (hydra.packages.${final.system}) inherit (hydra.packages.${final.system})
hydra; hydra;
inherit (mu5001tool.packages.${final.system})
mu5001tool;
inherit (nurausstieg.packages.${final.system}) inherit (nurausstieg.packages.${final.system})
nurausstieg; nurausstieg;
inherit (rainbowrss.packages.${final.system}) inherit (rainbowrss.packages.${final.system})

View File

@@ -4,6 +4,10 @@
imports = imports =
[ [
./hardware-configuration.nix ./hardware-configuration.nix
./grafana.nix
./mu5001tool.nix
./prometheus.nix
]; ];
profiles.clerie.network-fallback-dhcp.enable = true; profiles.clerie.network-fallback-dhcp.enable = true;
@@ -18,6 +22,16 @@
terminal_output serial terminal_output serial
"; ";
sops.secrets.monitoring-htpasswd = {
owner = "nginx";
group = "nginx";
};
services.nginx = {
enable = true;
};
networking.firewall.allowedTCPPorts = [ 80 443 ];
profiles.clerie.wg-clerie = { profiles.clerie.wg-clerie = {
enable = true; enable = true;
ipv6s = [ "2a01:4f8:c0c:15f1::8108/128" ]; ipv6s = [ "2a01:4f8:c0c:15f1::8108/128" ];

View File

@@ -0,0 +1,45 @@
{ config, ... }:
{
services.grafana = {
enable = true;
settings = {
server = {
domain = "grafana.astatine.net.clerie.de";
root_url = "https://grafana.astatine.net.clerie.de";
http_port = 3001;
http_addr = "::1";
};
"auth.anonymous" = {
enabled = true;
};
};
provision = {
enable = true;
datasources.settings.datasources = [
{
type = "prometheus";
name = "Prometheus";
url = "http://[::1]:9090";
isDefault = true;
}
];
};
};
services.nginx = {
virtualHosts = {
"grafana.astatine.net.clerie.de" = {
enableACME = true;
forceSSL = true;
basicAuthFile = config.sops.secrets.monitoring-htpasswd.path;
locations."/".proxyPass = "http://[::1]:3001/";
locations."= /api/live/ws" = {
proxyPass = "http://[::1]:3001";
proxyWebsockets = true;
};
};
};
};
}

View File

@@ -0,0 +1,18 @@
{ config, pkgs, lib, ... }:
{
systemd.services."mu5001tool" = {
wantedBy = [ "multi-user.target" ];
serviceConfig = {
DynamicUser = true;
LoadCredential = "zte-hypermobile-5g-password:${config.sops.secrets."zte-hypermobile-5g-password".path}";
Restart = "on-failure";
RestartSec = "15s";
};
script = ''
${lib.getExe pkgs.mu5001tool} --password-file ''${CREDENTIALS_DIRECTORY}/zte-hypermobile-5g-password prometheus-exporter --listen-port 9242
'';
};
}

View File

@@ -0,0 +1,46 @@
{ config, ... }:
{
services.prometheus = {
enable = true;
enableReload = true;
listenAddress = "[::1]";
scrapeConfigs = [
{
job_name = "prometheus";
scrape_interval = "20s";
scheme = "http";
static_configs = [
{
targets = [
"[::1]:9090"
];
}
];
}
{
job_name = "mu5001tool";
scrape_interval = "20s";
static_configs = [
{
targets = [
"[::1]:9242"
];
}
];
}
];
};
services.nginx = {
virtualHosts = {
"prometheus.astatine.net.clerie.de" = {
enableACME = true;
forceSSL = true;
basicAuthFile = config.sops.secrets.monitoring-htpasswd.path;
locations."/".proxyPass = "http://[::1]:9090/";
};
};
};
}

View File

@@ -1,19 +1,17 @@
{ {
"wg-clerie": "ENC[AES256_GCM,data:DbchcO6GTmSFyoHrRAkfu2flaKYrQHPk+rIerekYO4Cto9sqaWLgaSigpS8=,iv:no1xNRVqsKzAN6ssYA0Ir+utOM9tg8OBUT9PY2v0HPA=,tag:lZj1wEPFWHaf52N7YHEQKQ==,type:str]", "wg-clerie": "ENC[AES256_GCM,data:DbchcO6GTmSFyoHrRAkfu2flaKYrQHPk+rIerekYO4Cto9sqaWLgaSigpS8=,iv:no1xNRVqsKzAN6ssYA0Ir+utOM9tg8OBUT9PY2v0HPA=,tag:lZj1wEPFWHaf52N7YHEQKQ==,type:str]",
"wg-monitoring": "ENC[AES256_GCM,data:dTKKeieaGvECkHUpATLorhOgr9Re5CAH25y1WTcSqJZDsvnwD4CBbqMv2QQ=,iv:u1n1wyAW5aNcVYfGN8BmrEhIhtA3EfRDBNu65IdBZMI=,tag:RJYgOpel9uy6dC72MmqS5A==,type:str]", "wg-monitoring": "ENC[AES256_GCM,data:dTKKeieaGvECkHUpATLorhOgr9Re5CAH25y1WTcSqJZDsvnwD4CBbqMv2QQ=,iv:u1n1wyAW5aNcVYfGN8BmrEhIhtA3EfRDBNu65IdBZMI=,tag:RJYgOpel9uy6dC72MmqS5A==,type:str]",
"monitoring-htpasswd": "ENC[AES256_GCM,data:0uQ+Gwedi9kTaOzrwVzkNkS9qL0Dwmph1leK2sj/TndfSn3yaq7ur7ZHoPjWUl5Oy1poxU2rIUxWHajYC0n3yHv2AuGT,iv:FyH4MHcgW5iHkAsahNFtshnqqPOMlukg8aYfhcN9onw=,tag:q3BsnyKLrKYi/xDP6GmSkA==,type:str]",
"zte-hypermobile-5g-password": "ENC[AES256_GCM,data:lqxQICmWYwMejn8=,iv:TPYOs/cL/ETw7Ee0+YG/+Fhd7ASi0kr4rDLEiste+2Y=,tag:6O6AXIHkIjPm7hJVC4Y/1g==,type:str]",
"sops": { "sops": {
"kms": null,
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": [ "age": [
{ {
"recipient": "age1fffvnazdv3ys9ww8v4g832hv5nkvnk6d728syerzvpgskfmfkq8q00whpv", "recipient": "age1fffvnazdv3ys9ww8v4g832hv5nkvnk6d728syerzvpgskfmfkq8q00whpv",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMQUF5dkRwdXRmUkJ1SXN5\nLzdOVkhWYUJGdFd4Qklsa1BXeVZlTGx0eDE0ClZmYWNLMEVzaVVXWGkwQUt5ZHF5\nS1c5OU9PWjBTelM5R2phNFdVNncxUUkKLS0tIDlwSXFyZWNVT1dtdGU5dVFSRHNE\nUUpJZHJZRTd6TnBUU2dCWW90UTRVb0UKCWrHWmQTNhez16wgEKj4EQA4+UBRmGQn\n+NHSjBCMBmmTdHb05nENYVK515Z0T/60+9N3VlNyHWS9IgC3mZRUBg==\n-----END AGE ENCRYPTED FILE-----\n" "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBMQUF5dkRwdXRmUkJ1SXN5\nLzdOVkhWYUJGdFd4Qklsa1BXeVZlTGx0eDE0ClZmYWNLMEVzaVVXWGkwQUt5ZHF5\nS1c5OU9PWjBTelM5R2phNFdVNncxUUkKLS0tIDlwSXFyZWNVT1dtdGU5dVFSRHNE\nUUpJZHJZRTd6TnBUU2dCWW90UTRVb0UKCWrHWmQTNhez16wgEKj4EQA4+UBRmGQn\n+NHSjBCMBmmTdHb05nENYVK515Z0T/60+9N3VlNyHWS9IgC3mZRUBg==\n-----END AGE ENCRYPTED FILE-----\n"
} }
], ],
"lastmodified": "2024-04-21T16:03:13Z", "lastmodified": "2025-09-08T21:03:41Z",
"mac": "ENC[AES256_GCM,data:fA8fhOZbX30TYgwZXB7sQDNmck0JRDyAnEXf5nCYtli/Qvs78fTs4DdC08VOpOni8uAVARkFsGSo6Fjo/MpTSDVA8VNYZig/we/bWF+LQlEMCmiqwOI1R6eQ3GPxcRXltlO2aPPlT9BpLwIVZjGGjIsmjpVE8xjkCbLUUqj+UxY=,iv:fHLyw96QLVRrAQky2kR7TDDxf8CNXDV9lVQ5RETzJEI=,tag:y+cG9u3d6vCUmPyNMDRWpA==,type:str]", "mac": "ENC[AES256_GCM,data:ztS/Z6mn8hFAPsks2evJRJFocw/3oz22O2HeSEkY7Mu+bfNvClsJuvuTbnDadB0IwKiLDFWRMGs/UPFmNP6J/euro4cFHDWXopdXg7eDFGDoJDKIg4fBUtofdXIqWvDoQ9LeZNvc5Z4EEQYhs3LwFnAU0x15acwIIxr5TB9l8g8=,iv:WVjavmcrEs2CyYTfoTTP44c9TqFubUdE+PBN2jRPR+s=,tag:fBXzU69Q9MwD3o/Nyu5OZA==,type:str]",
"pgp": [ "pgp": [
{ {
"created_at": "2024-04-21T16:02:41Z", "created_at": "2024-04-21T16:02:41Z",
@@ -24,4 +22,4 @@
"unencrypted_suffix": "_unencrypted", "unencrypted_suffix": "_unencrypted",
"version": "3.8.1" "version": "3.8.1"
} }
} }

View File

@@ -6,6 +6,7 @@
./hardware-configuration.nix ./hardware-configuration.nix
./dns.nix ./dns.nix
./ds-lite-ncfttb.nix
./mdns.nix ./mdns.nix
./net-dsl.nix ./net-dsl.nix
./net-gastnetz.nix ./net-gastnetz.nix
@@ -16,7 +17,7 @@
./net-printer.nix ./net-printer.nix
./net-voip.nix ./net-voip.nix
./ntp.nix ./ntp.nix
./ppp.nix ./ppp-ncfttb.nix
./scan-to-gpg.nix ./scan-to-gpg.nix
./wg-clerie.nix ./wg-clerie.nix
]; ];
@@ -39,7 +40,7 @@
networking.nat = { networking.nat = {
enableIPv6 = true; enableIPv6 = true;
enable = true; enable = true;
externalInterface = "ppp-dtagdsl"; externalInterface = "ppp-ncfttb";
internalIPv6s = [ "fd00:152:152::/48" "fd00:3214:9453:4920::/64"]; internalIPv6s = [ "fd00:152:152::/48" "fd00:3214:9453:4920::/64"];
internalIPs = [ "10.152.0.0/16" "192.168.32.0/24" ]; internalIPs = [ "10.152.0.0/16" "192.168.32.0/24" ];
}; };

View File

@@ -0,0 +1,18 @@
{ ... }:
{
profiles.clerie.ds-lite = {
enable = true;
wanInterfaceName = "ppp-ncfttb";
tunnelInterfaceName = "ds-lite-ncfttb";
lanInterfaces = [
{
name = "net-heimnetz";
sla_id = 201;
prefix_len = 64;
}
];
};
}

View File

@@ -3,17 +3,17 @@
{ {
## DSL-Uplink ## DSL-Uplink
networking.vlans."enp1s0.7" = { networking.vlans."enp1s0.10" = {
id = 7; id = 10;
interface = "enp1s0"; interface = "enp1s0";
}; };
networking.vlans."enp3s0.7" = { networking.vlans."enp3s0.10" = {
id = 7; id = 10;
interface = "enp3s0"; interface = "enp3s0";
}; };
networking.bridges."net-dsl".interfaces = [ networking.bridges."net-dsl".interfaces = [
"enp1s0.7" "enp1s0.10"
"enp3s0.7" "enp3s0.10"
]; ];
} }

View File

@@ -61,7 +61,7 @@
# net-gastnetz can only access internet # net-gastnetz can only access internet
clerie.firewall.extraForwardFilterCommands = '' clerie.firewall.extraForwardFilterCommands = ''
ip46tables -A forward-filter -i net-gastnetz -o ppp-dtagdsl -j ACCEPT ip46tables -A forward-filter -i net-gastnetz -o ppp-ncfttb -j ACCEPT
ip46tables -A forward-filter -i net-gastnetz -j DROP ip46tables -A forward-filter -i net-gastnetz -j DROP
ip46tables -A forward-filter -o net-gastnetz -j DROP ip46tables -A forward-filter -o net-gastnetz -j DROP
''; '';

View File

@@ -4,11 +4,11 @@
services.pppd = { services.pppd = {
enable = true; enable = true;
peers.dtagdsl = { peers.ncfttb = {
config = '' config = ''
plugin pppoe.so net-dsl plugin pppoe.so net-dsl
user "''${PPPD_DTAGDSL_USERNAME}" user "''${PPPD_NETCOLOGNE_USERNAME}"
ifname ppp-dtagdsl ifname ppp-ncfttb
persist persist
maxfail 0 maxfail 0
holdoff 5 holdoff 5
@@ -24,9 +24,9 @@
}; };
}; };
environment.etc."ppp/peers/dtagdsl".enable = false; environment.etc."ppp/peers/ncfttb".enable = false;
systemd.services."pppd-dtagdsl".serviceConfig = let systemd.services."pppd-ncfttb".serviceConfig = let
preStart = '' preStart = ''
mkdir -p /etc/ppp/peers mkdir -p /etc/ppp/peers
@@ -34,22 +34,22 @@
umask u=rw,g=,o= umask u=rw,g=,o=
# Copy config and substitute username # Copy config and substitute username
rm -f /etc/ppp/peers/dtagdsl rm -f /etc/ppp/peers/ncfttb
${pkgs.envsubst}/bin/envsubst -i "${config.environment.etc."ppp/peers/dtagdsl".source}" > /etc/ppp/peers/dtagdsl ${pkgs.envsubst}/bin/envsubst -i "${config.environment.etc."ppp/peers/ncfttb".source}" > /etc/ppp/peers/ncfttb
# Copy login secrets # Copy login secrets
rm -f /etc/ppp/pap-secrets rm -f /etc/ppp/pap-secrets
cat ${config.sops.secrets.pppd-dtagdsl-secrets.path} > /etc/ppp/pap-secrets cat ${config.sops.secrets.pppd-ncfttb-secrets.path} > /etc/ppp/pap-secrets
rm -f /etc/ppp/chap-secrets rm -f /etc/ppp/chap-secrets
cat ${config.sops.secrets.pppd-dtagdsl-secrets.path} > /etc/ppp/chap-secrets cat ${config.sops.secrets.pppd-ncfttb-secrets.path} > /etc/ppp/chap-secrets
''; '';
preStartFile = pkgs.writeShellApplication { preStartFile = pkgs.writeShellApplication {
name = "pppd-dtagdsl-pre-start"; name = "pppd-ncfttb-pre-start";
text = preStart; text = preStart;
}; };
in { in {
EnvironmentFile = config.sops.secrets.pppd-dtagdsl-username.path; EnvironmentFile = config.sops.secrets.pppd-ncfttb-username.path;
ExecStartPre = [ ExecStartPre = [
# "+" marks script to be executed without priviledge restrictions # "+" marks script to be executed without priviledge restrictions
"+${lib.getExe preStartFile}" "+${lib.getExe preStartFile}"

View File

@@ -1,21 +1,17 @@
{ {
"wg-monitoring": "ENC[AES256_GCM,data:+k5MgBrj/psMCE1T2jDtCCJI9Q7L+wJ3j83inNkeGp3LSUjoAPtBp4YoyL4=,iv:C19g/Lqi+cWAyiJBMNDtgLc3SDNI9bMBrBPWn+26mVY=,tag:9zIoawuGeGCMbOX1HKR/sQ==,type:str]", "wg-monitoring": "ENC[AES256_GCM,data:+k5MgBrj/psMCE1T2jDtCCJI9Q7L+wJ3j83inNkeGp3LSUjoAPtBp4YoyL4=,iv:C19g/Lqi+cWAyiJBMNDtgLc3SDNI9bMBrBPWn+26mVY=,tag:9zIoawuGeGCMbOX1HKR/sQ==,type:str]",
"pppd-dtagdsl-username": "ENC[AES256_GCM,data:JC7EyyMoN0p5YwnS9W5I0G5Omhk5usw28UiJrCfifGr+2FUgMrtFYAHQdrtWAELvYNBQDPgrHMmQjGQLhpqqK0hH,iv:/q+Fm63GVBApGInyS8i39V/lo6iv+I2omVh47deq+o8=,tag:LkR+1zTDNWuYkhH2iWT7SA==,type:str]", "pppd-ncfttb-username": "ENC[AES256_GCM,data:vyOCNm23xsD3Kj+R7zqnBjH4jEIfYpx/YUUGPcVzqMs9pnFEembahtFTl2sNzOFXLfYCYg==,iv:gMfi/6jldkXCnfdvhu5X1VKj58sVsPR8IX8iEECPfgk=,tag:PJGyIASP6RPAdVULEnn+Gg==,type:str]",
"pppd-dtagdsl-secrets": "ENC[AES256_GCM,data:c5pOb8It1py/9NXNTgLvt9zmsBVbSLHJt4iXWiNA+Osvomw3r7pgoO/JJh9ujomPMnOlDwN7g+pJ,iv:W36gA8E1mWchN6+8hdMdt2epv/RdS91T5ANB/JTcHCE=,tag:7eZ3fZkjERCVJCXYrABnlQ==,type:str]", "pppd-ncfttb-secrets": "ENC[AES256_GCM,data:IEAguET78vdzRo47UvxbDdz+kKgYWVxYakPPu5rNAZ4BCui7DUG3qm2X9bBdHSMA,iv:Q8D58HXkCoVbqwFoYk+dizXNcEP1J63uMaDSNEzfg2g=,tag:R/xG3owmbVDOLM79sfBQjA==,type:str]",
"wg-clerie": "ENC[AES256_GCM,data:OEZg8ZoLAdVhKkvB0ai13ID3gPnVUU/xkOjZ4KiJ9MnRbcFu5HBd7Nw6iNwh,iv:edPuaehya2ZvYKkiBqNUbXVDAxAT6yNgETnWtd6it94=,tag:cX12szdQfAcC6cij6zk6Dw==,type:str]", "wg-clerie": "ENC[AES256_GCM,data:OEZg8ZoLAdVhKkvB0ai13ID3gPnVUU/xkOjZ4KiJ9MnRbcFu5HBd7Nw6iNwh,iv:edPuaehya2ZvYKkiBqNUbXVDAxAT6yNgETnWtd6it94=,tag:cX12szdQfAcC6cij6zk6Dw==,type:str]",
"sops": { "sops": {
"kms": null,
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": [ "age": [
{ {
"recipient": "age16mln27e2p58gu6dpxfclttmuzfnq39mv62kthjpps33g3nl3scfq449857", "recipient": "age16mln27e2p58gu6dpxfclttmuzfnq39mv62kthjpps33g3nl3scfq449857",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3Rkd5WFE3aE5EQzY5ZXV4\nbXVGYmxTdVg1ekRpVjlRUnozY2tMTGloL21RCktjZW95OU9ZZ2owTCtMR1NxaXJn\na2VYS2ttb3VhSjNXOG84UUJtYU04QjAKLS0tIGd3aHM0RldFYnVFdDRVS0Vhc3BF\nckJhYmN6a1FJUC9ibks1cGlRaU1zbFkKE4ClunQ3XGAILwluC6iYFs+rlR02PdhK\njOmPbOlS0aNG0hoC7Z6aetgpj689AkJgl68QVcyvm+ecHH7TOT7l1A==\n-----END AGE ENCRYPTED FILE-----\n" "enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3Rkd5WFE3aE5EQzY5ZXV4\nbXVGYmxTdVg1ekRpVjlRUnozY2tMTGloL21RCktjZW95OU9ZZ2owTCtMR1NxaXJn\na2VYS2ttb3VhSjNXOG84UUJtYU04QjAKLS0tIGd3aHM0RldFYnVFdDRVS0Vhc3BF\nckJhYmN6a1FJUC9ibks1cGlRaU1zbFkKE4ClunQ3XGAILwluC6iYFs+rlR02PdhK\njOmPbOlS0aNG0hoC7Z6aetgpj689AkJgl68QVcyvm+ecHH7TOT7l1A==\n-----END AGE ENCRYPTED FILE-----\n"
} }
], ],
"lastmodified": "2024-08-13T14:06:43Z", "lastmodified": "2025-10-24T19:16:49Z",
"mac": "ENC[AES256_GCM,data:yGKY0fi3KQWGHBeyNtQ8EJ6561dKRZ5aAjO9zq3odDtX75i2RSjORIlNjBsVvegBzeo8AkwwnzxNPt2sHl6MKDZfEsysWAi8Wolh4UvHk087AnR/uKvtG6t4uUaNIWej2DEzxUtTQ8QP1afsdqGCf0vZVruNcJ4u2xiQbN2vJPc=,iv:CDXJ5/P+h0Enq/0EL1su1Mw55FVYLy4XPSoUCkRkt+U=,tag:AvRfEDYMBunyIQIVCPbXag==,type:str]", "mac": "ENC[AES256_GCM,data:ADhCQ7JxrEq+5ssevuuQVf3uyHcrcNVSzdT8bkFfDFVEE1hKv8q9QsGxhIaKtv4N2gt079fy0YA+WFKH6H8zWb5ONepH4H/mAek2SYgAtmVsxwdWY13zswsJUPi2CfbaCWOqppb9IiDb8+RCbzY2u/8Qqwk8gx/0uw2hr3IJrhM=,iv:c1/TS+W4pQgh2oPT77LX+dUL929YppRYdZCmMl2yN+M=,tag:fTk1sxdeT9xFjDMhqiHZAg==,type:str]",
"pgp": [ "pgp": [
{ {
"created_at": "2024-05-10T13:05:56Z", "created_at": "2024-05-10T13:05:56Z",
@@ -24,6 +20,6 @@
} }
], ],
"unencrypted_suffix": "_unencrypted", "unencrypted_suffix": "_unencrypted",
"version": "3.8.1" "version": "3.10.2"
} }
} }

View File

@@ -45,13 +45,18 @@
"/mnt/clerie-backup" "/mnt/clerie-backup"
]; ];
doInit = true; doInit = true;
repo = "u275370-sub2@u275370.your-storagebox.de:./clerie-backup/" ; repo = "u275370-sub2@u275370.your-storagebox.de:./clerie-backup/";
encryption = { encryption = {
mode = "none"; mode = "none";
}; };
environment = { BORG_RSH = "ssh -p 23 -i /var/src/secrets/ssh/borg-backup-replication-hetzner"; }; environment = { BORG_RSH = "ssh -p 23 -i /var/src/secrets/ssh/borg-backup-replication-hetzner"; };
compression = "auto,lzma"; compression = "auto,lzma";
startAt = "*-*-* 04:07:00"; startAt = "*-*-* 04:07:00";
readWritePaths = [ "/var/lib/prometheus-node-exporter/textfiles" ];
postPrune = ''
echo "backup_replication_hetzner_last_successful_run_time $(date +%s)" > /var/lib/prometheus-node-exporter/textfiles/backup-replication-hetzner.prom
'';
}; };
}; };

View File

@@ -11,6 +11,8 @@
signal-desktop signal-desktop
dino dino
fractal fractal
tuba
flare-signal
tio tio
xournalpp xournalpp
@@ -23,6 +25,7 @@
wireshark wireshark
tcpdump tcpdump
nmap nmap
pkgs."http.server"
kdePackages.okular kdePackages.okular
chromium-incognito chromium-incognito

View File

@@ -11,7 +11,28 @@ with lib;
}; };
users.groups.data-em = {}; users.groups.data-em = {};
users.users.data-em-mp3 = {
group = "data-em-mp3";
home = "/data/em-mp3";
useDefaultShell = true;
isSystemUser = true;
};
users.groups.data-em-mp3 = {};
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
"d /data/em - data-em data-em - -" "d /data/em - data-em data-em - -"
"d /data/em-mp3 - data-em-mp3 data-em-mp3 - -"
]; ];
systemd.services.convert-flac-dir-to-mp3 = {
serviceConfig = {
Type = "oneshot";
ExecStart = "${lib.getExe pkgs.convert-flac-dir-to-mp3} /data/em /data/em-mp3";
StateDirectory = "convert-flac-dir-to-mp3";
WorkingDirectory = "/var/lib/convert-flac-dir-to-mp3";
User = "data-em-mp3";
Group = "data-em-mp3";
};
startAt = "*-*-* 03:47:00";
};
} }

View File

@@ -53,17 +53,23 @@ in {
"mixcloud.clerie.de" = { "mixcloud.clerie.de" = {
enableACME = true; enableACME = true;
forceSSL = true; forceSSL = true;
basicAuthFile = config.sops.secrets.mixcloud-htpasswd.path;
locations."/" = { locations."/" = {
alias = "/data/mixcloud/"; alias = "/data/mixcloud/";
basicAuthFile = config.sops.secrets.mixcloud-htpasswd.path;
extraConfig = '' extraConfig = ''
autoindex on; autoindex on;
autoindex_exact_size off; autoindex_exact_size off;
''; '';
}; };
locations."/api/" = {
alias = "/data/mixcloud/";
extraConfig = ''
autoindex on;
autoindex_format json;
'';
};
locations."/media/" = { locations."/media/" = {
alias = "/data/media/"; alias = "/data/media/";
basicAuthFile = config.sops.secrets.mixcloud-htpasswd.path;
extraConfig = '' extraConfig = ''
autoindex on; autoindex on;
autoindex_exact_size off; autoindex_exact_size off;

View File

@@ -40,7 +40,7 @@ if [[ -z $NO_CONFIRM ]]; then
fi fi
echo "Download ${STORE_PATH}" echo "Download ${STORE_PATH}"
nix copy --from "https://nix-cache.clerie.de" "${STORE_PATH}" nix copy --to daemon "${STORE_PATH}"
echo "Add to system profile" echo "Add to system profile"
nix-env -p "/nix/var/nix/profiles/system" --set "${STORE_PATH}" nix-env -p "/nix/var/nix/profiles/system" --set "${STORE_PATH}"

View File

@@ -1,6 +1,7 @@
{ {
python3, python3,
writeTextFile, makeWrapper,
runCommand,
lib, lib,
}: }:
@@ -9,6 +10,7 @@
text, text,
runtimePackages ? ps: [], runtimePackages ? ps: [],
pythonPackage ? python3, pythonPackage ? python3,
runtimeInputs ? [],
meta ? {}, meta ? {},
passthru ? {}, passthru ? {},
derivationArgs ? {}, derivationArgs ? {},
@@ -18,13 +20,17 @@ let
pythonWithPackages = pythonPackage.withPackages runtimePackages; pythonWithPackages = pythonPackage.withPackages runtimePackages;
in writeTextFile { in runCommand name ({
inherit passAsFile = [ "text" ] ++ (derivationArgs.passAsFile or []);
name
meta meta = {
passthru mainProgram = name;
derivationArgs } // meta // (derivationArgs.meta or {});
;
passthru = passthru // (derivationArgs.passthru or {});
nativeBuildInputs = [ makeWrapper ] ++ (derivationArgs.nativeBuildInputs or []);
executable = true; executable = true;
destination = "/bin/${name}"; destination = "/bin/${name}";
allowSubstitutes = true; allowSubstitutes = true;
@@ -34,4 +40,17 @@ in writeTextFile {
${text} ${text}
''; '';
} } // (
builtins.removeAttrs derivationArgs [ "passAsFile" "meta" "passthru" "nativeBuildInputs" ]
))
''
mkdir -p $out/bin
target=$out/bin/${lib.escapeShellArg name}
cp "$textPath" "$target"
chmod +x "$target"
wrapProgram "$target" --prefix PATH : "${lib.makeBinPath runtimeInputs}"
''

View File

@@ -0,0 +1,109 @@
#!/usr/bin/env python
import argparse
from pathlib import Path
from progress.bar import Bar
import shutil
import subprocess
def files_and_dirs_for_directory(path):
filepaths = []
dirpaths = []
for dirpath, dirnames, filenames in path.walk():
dirpaths.append(dirpath)
for filename in filenames:
filepath = dirpath / filename
filepaths.append(filepath)
return set(filepaths), set(dirpaths)
def make_paths_relative(paths, relative_to_path):
return set(path.relative_to(relative_to_path) for path in paths)
def replace_suffix(path, suffix):
return path.with_name(path.stem + suffix)
def convert_filepath(path):
if path.suffix == ".flac":
return replace_suffix(path, ".mp3")
return path
def ffmpeg_flac_to_mp3(in_path, out_path):
print("")
subprocess.run(["ffmpeg", "-hide_banner", "-loglevel", "warning", "-stats", "-i", in_path, "-ab", "320k", "-map_metadata", "0", "-id3v2_version", "3", out_path], check=True)
print("")
if __name__ == "__main__":
parser = argparse.ArgumentParser(prog="convert-flac-dir-to-mp3")
parser.add_argument("from_dir", type=Path)
parser.add_argument("to_dir", type=Path)
args = parser.parse_args()
from_path = args.from_dir.absolute()
to_path = args.to_dir.absolute()
if not from_path.exists():
raise Exception("from_path does not exist")
if not to_path.exists():
raise Exception("to_path does not exist")
if not from_path.is_dir():
raise Exception("from_path is not a directory")
if not to_path.is_dir():
raise Exception("to_path is not a directory")
print(f"Converting {from_path} to {to_path}")
from_filepaths, from_dirpaths = files_and_dirs_for_directory(from_path)
to_filepaths, to_dirpaths = files_and_dirs_for_directory(to_path)
relative_from_filepaths = make_paths_relative(from_filepaths, from_path)
relative_to_filepaths = make_paths_relative(to_filepaths, to_path)
converted_from_filepaths = set(convert_filepath(filepath) for filepath in relative_from_filepaths)
filepaths_missing_in_to_path = converted_from_filepaths - relative_to_filepaths
relative_from_dirpaths = make_paths_relative(from_dirpaths, from_path)
relative_to_dirpaths = make_paths_relative(to_dirpaths, to_path)
dirpaths_missing_in_to_path = relative_from_dirpaths - relative_to_dirpaths
print(f"Missing {len(filepaths_missing_in_to_path)} files and {len(dirpaths_missing_in_to_path)} directories")
if len(dirpaths_missing_in_to_path) > 0:
for dirpath in Bar("Creating directories").iter(dirpaths_missing_in_to_path):
(to_path / dirpath).mkdir(parents=True, exist_ok=True)
if len(filepaths_missing_in_to_path) > 0:
for filepath in Bar("Creating files").iter(filepaths_missing_in_to_path):
if filepath in relative_from_filepaths:
# Just copy the file
shutil.copy(from_path / filepath, to_path / filepath)
elif filepath.suffix == ".mp3" and replace_suffix(filepath, ".flac") in relative_from_filepaths:
# Convert from flac
print("")
print(f"Converting {to_path / filepath}")
# Tempfile for ffmpeg
tmpfilepath = filepath.with_name(".~" + filepath.name)
(to_path / tmpfilepath).unlink(missing_ok=True)
print(f"Using tempfile for ffmpeg {to_path / tmpfilepath}")
# Convert
ffmpeg_flac_to_mp3(from_path / replace_suffix(filepath, ".flac"), to_path / tmpfilepath)
# Rename tempfile
(to_path / tmpfilepath).rename(to_path / filepath)
else:
raise Exception("Unable to figure out how to get {to_path / filepath} from {from_path}")

View File

@@ -0,0 +1,8 @@
{ pkgs, ... }:
pkgs.clerie-build-support.writePythonScript {
name = "convert-flac-dir-to-mp3";
runtimePackages = ps: with ps; [ progress ];
runtimeInputs = [ pkgs.ffmpeg-headless ];
text = builtins.readFile ./convert-flac-dir-to-mp3.py;
}

View File

@@ -0,0 +1,16 @@
#!/usr/bin/env bash
curl -w "Request to %{url}
time_namelookup: %{time_namelookup}s
time_connect: %{time_connect}s
time_appconnect: %{time_appconnect}s
time_pretransfer: %{time_pretransfer}s
time_starttransfer: %{time_starttransfer}s
time_posttransfer: %{time_posttransfer}s
time_queue: %{time_queue}s
time_redirect: %{time_redirect}s
time_starttransfer: %{time_starttransfer}s
time_total: %{time_total}s
" -o /dev/null -s "$@"

View File

@@ -0,0 +1,12 @@
{
curl,
writeShellApplication,
}:
writeShellApplication {
name = "curl-timings";
text = builtins.readFile ./curl-timings.sh;
runtimeInputs = [
curl
];
}

View File

@@ -0,0 +1,12 @@
{ pkgs, ... }:
pkgs.writeShellApplication {
name = "ds-lite-dhcpcd-hook";
text = builtins.readFile ./ds-lite-dhcpcd-hook.sh;
runtimeInputs = with pkgs; [
iproute2
jq
dig
gawk
];
}

View File

@@ -0,0 +1,102 @@
#!/usr/bin/env bash
set -euo pipefail
# Setting up required environment variables
# shellcheck disable=SC2154
WAN_INTERFACE_NAME="${DS_LITE_WAN_INTERFACE_NAME}"
# shellcheck disable=SC2154
TUNNEL_INTERFACE_NAME="${DS_LITE_TUNNEL_INTERFACE_NAME}"
log_dhcp () {
echo "<ds-lite-dhcpcd-hook> ${WAN_INTERFACE_NAME}: $1"
}
log_tunnel () {
echo "<ds-lite-dhcpcd-hook> ${WAN_INTERFACE_NAME} (${TUNNEL_INTERFACE_NAME}): $1"
}
# Check if the event calling this hook is for the wan interface
# exit immediately if not
# shellcheck disable=SC2154
if [[ "$interface" != "$WAN_INTERFACE_NAME" ]]; then
exit
fi
# Make sure the event calling this hook carries the environment variable
# in question. The environment variable is not provided with every call
# and we just want to exit if it is not provided
# shellcheck disable=SC2154
if [[ ! -v new_dhcp6_aftr_name ]]; then
# Variable is not set
exit
fi
# shellcheck disable=SC2154
if [[ -z "${new_dhcp6_aftr_name}" ]]; then
# Variable is empty, can't do anything
exit
fi
# shellcheck disable=SC2154
AFTR_NAME="$new_dhcp6_aftr_name"
log_dhcp "Received new AFTR_NAME ${AFTR_NAME}"
# Make sure we have a nameserver to resolve aftr name against
# shellcheck disable=SC2154
if [[ ! -v new_dhcp6_name_servers ]]; then
# Variable is not set
exit
fi
# shellcheck disable=SC2154
if [[ -z "${new_dhcp6_name_servers}" ]]; then
# Variable is empty, can't do anything
exit
fi
# shellcheck disable=SC2154
NAME_SERVERS="$new_dhcp6_name_servers"
log_dhcp "Received new NAME_SERVERS ${NAME_SERVERS}"
# Select first nameserver
NAME_SERVER="$(echo "${NAME_SERVERS}" | awk '{print $1;}')"
log_dhcp "Selected NAME_SERVER ${NAME_SERVER}"
# Figure out a usable IPv6 address on the wan interface, to origin our DNS requests and tunnel
WAN_INTERFACE_ADDRESS="$(ip --json address show "${WAN_INTERFACE_NAME}" | jq -r '.[0].addr_info[] | select(.family == "inet6" and .scope == "global" and .mngtmpaddr == true) | .local')"
log_dhcp "Using WAN_INTERFACE_ADDRESS ${WAN_INTERFACE_ADDRESS}"
AFTR_ADDRESS="$(dig "@${NAME_SERVER}" -b "${WAN_INTERFACE_ADDRESS}" AAAA "${AFTR_NAME}" +short | head -1)"
log_dhcp "Resolved AFTR_NAME ${AFTR_NAME} to ${AFTR_ADDRESS}"
# Check if there is already a tunnel interface
if TUNNEL_INTERFACE_CONFIG="$(ip --json link show "${TUNNEL_INTERFACE_NAME}")"; then
TUNNEL_INTERFACE_OPERSTATE="$(echo "${TUNNEL_INTERFACE_CONFIG}" | jq -r '.[0].operstate')"
TUNNEL_INTERFACE_ORIGIN_ADDRESS="$(echo "${TUNNEL_INTERFACE_CONFIG}" | jq -r '.[0].address')"
TUNNEL_INTERFACE_REMOTE_ADDRESS="$(echo "${TUNNEL_INTERFACE_CONFIG}" | jq -r '.[0].broadcast')"
# Reconfigure tunnel interface, if not already in state we want
if [[ "${TUNNEL_INTERFACE_ORIGIN_ADDRESS}" != "${WAN_INTERFACE_ADDRESS}" || "${TUNNEL_INTERFACE_REMOTE_ADDRESS}" != "${AFTR_ADDRESS}" || "${TUNNEL_INTERFACE_OPERSTATE}" != "UNKNOWN" ]]; then
log_tunnel "Bad configuration, fixing tunnel parameter"
ip tunnel change "${TUNNEL_INTERFACE_NAME}" mode ipip6 local "${WAN_INTERFACE_ADDRESS}" remote "${AFTR_ADDRESS}"
ip link set "$TUNNEL_INTERFACE_NAME" up
else
log_tunnel "Tunnel already configured"
fi
else
log_tunnel "Setting up DS-Lite tunnel"
ip tunnel add "${TUNNEL_INTERFACE_NAME}" mode ipip6 local "${WAN_INTERFACE_ADDRESS}" remote "${AFTR_ADDRESS}"
ip link set "$TUNNEL_INTERFACE_NAME" up
fi
log_tunnel "Setting default route"
ip route replace default dev "${TUNNEL_INTERFACE_NAME}"
log_tunnel "Tunnel setup finished"

View File

@@ -0,0 +1,19 @@
{
e2fsprogs,
gptfdisk,
jq,
parted,
writeShellApplication,
}:
writeShellApplication {
name = "grow-last-partition-and-filesystem";
text = builtins.readFile ./grow-last-partition-and-filesystem.sh;
runtimeInputs = [
e2fsprogs
gptfdisk
jq
parted
];
}

View File

@@ -0,0 +1,32 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ $# -ne 1 ]]; then
echo "Pass device to grow as first argument:"
echo "grow-last-partition-and-filesystem DEVICE"
exit 1
fi
DEVICE="$1"
echo "Move GTP backup header to end of disk"
sgdisk "${DEVICE}" --move-second-header
PARTITIONDATA="$(parted --script --json --fix "${DEVICE}" print)"
PARTNUMBER="$(echo "${PARTITIONDATA}" | jq -r '.disk.partitions | last | .number')"
PARTNAME="$(echo "${PARTITIONDATA}" | jq -r '.disk.partitions | last | .name')"
echo "Growing partition ${DEVICE}${PARTNUMBER} (${PARTNAME})"
echo
parted "${DEVICE}" resizepart "${PARTNUMBER}" 100%
echo
echo "Resizing filesystem"
echo
resize2fs "${DEVICE}${PARTNUMBER}"
echo "Done."

View File

@@ -0,0 +1,14 @@
{
python3,
writeShellApplication,
}:
writeShellApplication {
name = "http.server";
text = ''
python3 -m http.server "$@"
'';
runtimeInputs = [
python3
];
}

View File

@@ -12,6 +12,9 @@ final: prev: {
clerie-sops-edit = final.callPackage ./clerie-sops/clerie-sops-edit.nix {}; clerie-sops-edit = final.callPackage ./clerie-sops/clerie-sops-edit.nix {};
clerie-update-nixfiles = final.callPackage ./clerie-update-nixfiles/clerie-update-nixfiles.nix {}; clerie-update-nixfiles = final.callPackage ./clerie-update-nixfiles/clerie-update-nixfiles.nix {};
chromium-incognito = final.callPackage ./chromium-incognito {}; chromium-incognito = final.callPackage ./chromium-incognito {};
convert-flac-dir-to-mp3 = final.callPackage ./convert-flac-dir-to-mp3 {};
curl-timings = final.callPackage ./curl-timings {};
ds-lite-dhcpcd-hook = final.callPackage ./ds-lite-dhcpcd-hook {};
factorio-launcher = final.callPackage ./factorio-launcher {}; factorio-launcher = final.callPackage ./factorio-launcher {};
feeds-dir = final.callPackage ./feeds-dir {}; feeds-dir = final.callPackage ./feeds-dir {};
generate-blocked-prefixes = final.callPackage ./generate-blocked-prefixes {}; generate-blocked-prefixes = final.callPackage ./generate-blocked-prefixes {};
@@ -19,6 +22,8 @@ final: prev: {
git-diff-word = final.callPackage ./git-diff-word {}; git-diff-word = final.callPackage ./git-diff-word {};
git-pp = final.callPackage ./git-pp {}; git-pp = final.callPackage ./git-pp {};
git-show-link = final.callPackage ./git-show-link {}; git-show-link = final.callPackage ./git-show-link {};
grow-last-partition-and-filesystem = final.callPackage ./grow-last-partition-and-filesystem {};
"http.server" = final.callPackage ./http.server {};
nix-remove-result-links = final.callPackage ./nix-remove-result-links {}; nix-remove-result-links = final.callPackage ./nix-remove-result-links {};
nixfiles-auto-install = final.callPackage ./nixfiles/nixfiles-auto-install.nix {}; nixfiles-auto-install = final.callPackage ./nixfiles/nixfiles-auto-install.nix {};
nixfiles-generate-config = final.callPackage ./nixfiles/nixfiles-generate-config.nix {}; nixfiles-generate-config = final.callPackage ./nixfiles/nixfiles-generate-config.nix {};

View File

@@ -0,0 +1,20 @@
final: prev:
prev.dhcpcd.overrideAttrs (finalAttrs: prevAttrs: {
configureFlags = [
"--sysconfdir=/etc/ds-lite-dhcpcd"
"--localstatedir=/var"
"--disable-fork"
"--disable-privsep"
"--dbdir=/var/lib/ds-lite-dhcpcd"
"--rundir=/var/run/ds-lite-dhcpcd"
"--with-default-hostname=ds-lite"
"--disable-ipv4"
"--disable-arp"
"--disable-arpping"
"--disable-ipv4ll"
"--disable-ntp"
];
})

View File

@@ -1,4 +1,5 @@
final: prev: { final: prev: {
dino = import ./dino.nix final prev; dino = import ./dino.nix final prev;
ds-lite-dhcpcd = import ./ds-lite-dhcpcd.nix final prev;
xmppc = import ./xmppc.nix final prev; xmppc = import ./xmppc.nix final prev;
} }

View File

@@ -11,6 +11,7 @@
./cybercluster-vm ./cybercluster-vm
./desktop ./desktop
./dn42-router ./dn42-router
./ds-lite
./fem-net ./fem-net
./firefox ./firefox
./gpg-ssh ./gpg-ssh

View File

@@ -0,0 +1,150 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.profiles.clerie.ds-lite;
dsLiteDhcpcdConfig = ''
allowinterfaces ${cfg.wanInterfaceName} ${concatMapStringsSep " " (interface: interface.name) cfg.lanInterfaces}
option dhcp6_name_servers
option dhcp6_aftr_name
waitip 6
ipv6only
ipv6ra_noautoconf
noipv6rs
interface ${cfg.wanInterfaceName}
ipv6ra_autoconf
ipv6rs
ia_pd 1/::/48 ${concatMapStringsSep " " (interface: "${interface.name}/${toString interface.sla_id}/${toString interface.prefix_len}") cfg.lanInterfaces}
${concatMapStrings (interface: ''
interface ${interface.name}
nolink
'') cfg.lanInterfaces}
'';
dsLiteDhcpcdConfigFile = pkgs.writeTextFile {
name = "dhcpcd.conf";
text = dsLiteDhcpcdConfig;
};
dsLiteDhcpcdHookWrapperFile = pkgs.writeShellScript "ds-lite-dhcpcd-hook-wrapper" ''
DS_LITE_WAN_INTERFACE_NAME=${lib.escapeShellArg cfg.wanInterfaceName};
export DS_LITE_WAN_INTERFACE_NAME
DS_LITE_TUNNEL_INTERFACE_NAME=${lib.escapeShellArg cfg.tunnelInterfaceName};
export DS_LITE_TUNNEL_INTERFACE_NAME
exec ${lib.getExe pkgs.ds-lite-dhcpcd-hook}
'';
in {
options.profiles.clerie.ds-lite = {
enable = mkEnableOption "DS-Lite setup";
wanInterfaceName = mkOption {
type = types.str;
description = "Interface with IPv6 connectivity to provider";
};
tunnelInterfaceName = mkOption {
type = types.str;
description = "Interface with IPv4 connectivity to provider";
};
lanInterfaces = mkOption {
type = with types; listOf (submodule ({ ... }: {
options = {
name = mkOption {
type = types.str;
};
sla_id = mkOption {
type = types.ints.unsigned;
};
prefix_len = mkOption {
type = types.ints.between 48 128;
};
};
}));
default = [];
description = "Interfaces to provisn with an IPv6 prefix";
};
};
config = mkIf cfg.enable {
systemd.services.ds-lite-dhcpcd = {
description = "DS-Lite dhcpcd";
wantedBy = [ "multi-user.target" ];
environment = {
};
serviceConfig = {
Type = "simple";
User = "ds-lite";
Group = "ds-lite";
StateDirectory = "ds-lite-dhcpcd";
RuntimeDirectory = "ds-lite-dhcpcd";
ExecStart = "${pkgs.ds-lite-dhcpcd}/bin/dhcpcd --ipv6only --nobackground --config ${dsLiteDhcpcdConfigFile} --script ${dsLiteDhcpcdHookWrapperFile}";
Restart = "always";
AmbientCapabilities = [
"CAP_NET_ADMIN"
"CAP_NET_RAW"
"CAP_NET_BIND_SERVICE"
];
ReadWritePaths = [
"/proc/sys/net/ipv6"
];
DeviceAllow = "";
LockPersonality = true;
MemoryDenyWriteExecute = true;
PrivateDevices = true;
PrivateMounts = true;
PrivateTmp = true;
PrivateUsers = false;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = "tmpfs"; # allow exceptions to be added to ReadOnlyPaths, etc.
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
ProtectSystem = "strict";
RemoveIPC = true;
RestrictAddressFamilies = [
"AF_UNIX"
"AF_INET"
"AF_INET6"
"AF_NETLINK"
"AF_PACKET"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallFilter = [
"@system-service"
"~@keyring"
"~@memlock"
"~@mount"
];
SystemCallArchitectures = "native";
UMask = "0027";
};
};
users.users.ds-lite = {
isSystemUser = true;
group = "ds-lite";
};
users.groups.ds-lite = { };
};
}