initial commit
Some checks failed
Deploy configs / deploy-configs (push) Failing after 11s

This commit is contained in:
sid 2026-02-23 20:53:29 +01:00
commit 7d364cdfac
69 changed files with 5268 additions and 0 deletions

7
hosts/rx4/boot.nix Normal file
View file

@ -0,0 +1,7 @@
{
boot.loader.systemd-boot = {
enable = true;
configurationLimit = 20;
};
boot.loader.efi.canTouchEfiVariables = true;
}

26
hosts/rx4/default.nix Normal file
View file

@ -0,0 +1,26 @@
{
inputs,
outputs,
...
}:
{
imports = [
./boot.nix
./hardware.nix
./networking.nix
./packages.nix
./secrets
./services
../../users/sid
inputs.synix.nixosModules.common
inputs.synix.nixosModules.device.server
outputs.nixosModules.common
outputs.nixosModules.deploy
];
system.stateVersion = "25.11";
}

63
hosts/rx4/disks.sh Normal file
View file

@ -0,0 +1,63 @@
#!/usr/bin/env bash
SSD='/dev/disk/by-id/nvme-KINGSTON_SNV3SM3500G_50026B7283B1AFB4_1'
MNT='/mnt'
SWAP_GB=8
# Helper function to wait for devices
wait_for_device() {
local device=$1
echo "Waiting for device: $device ..."
while [[ ! -e $device ]]; do
sleep 1
done
echo "Device $device is ready."
}
# Function to install a package if it's not already installed
install_if_missing() {
local cmd="$1"
local package="$2"
if ! command -v "$cmd" &> /dev/null; then
echo "$cmd not found, installing $package..."
nix-env -iA "nixos.$package"
fi
}
install_if_missing "sgdisk" "gptfdisk"
install_if_missing "partprobe" "parted"
wait_for_device $SSD
echo "Wiping filesystem on $SSD..."
wipefs -a $SSD
echo "Clearing partition table on $SSD..."
sgdisk --zap-all $SSD
echo "Partitioning $SSD..."
sgdisk -n1:1M:+1G -t1:EF00 -c1:BOOT $SSD
sgdisk -n2:0:+"$SWAP_GB"G -t2:8200 -c2:SWAP $SSD
sgdisk -n3:0:0 -t3:8304 -c3:ROOT $SSD
partprobe -s $SSD
udevadm settle
wait_for_device ${SSD}-part1
wait_for_device ${SSD}-part2
wait_for_device ${SSD}-part3
echo "Formatting partitions..."
mkfs.vfat -F 32 -n BOOT "${SSD}-part1"
mkswap -L SWAP "${SSD}-part2"
mkfs.ext4 -L ROOT "${SSD}-part3"
echo "Mounting partitions..."
mount -o X-mount.mkdir "${SSD}-part3" "$MNT"
mkdir -p "$MNT/boot"
mount -t vfat -o fmask=0077,dmask=0077,iocharset=iso8859-1 "${SSD}-part1" "$MNT/boot"
echo "Enabling swap..."
swapon "${SSD}-part2"
echo "Partitioning and setup complete:"
lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL

48
hosts/rx4/hardware.nix Normal file
View file

@ -0,0 +1,48 @@
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [
"nvme"
"sd_mod"
"sdhci_pci"
"usb_storage"
"usbhid"
"xhci_pci"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-label/ROOT";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-label/BOOT";
fsType = "vfat";
options = [
"fmask=0022"
"dmask=0022"
];
};
swapDevices = [
{ device = "/dev/disk/by-label/SWAP"; }
];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}

51
hosts/rx4/networking.nix Normal file
View file

@ -0,0 +1,51 @@
{
networking.hostName = "rx4";
networking.domain = "sid.ovh";
# boot.kernel.sysctl = {
# "net.ipv4.conf.all.forwarding" = 1;
# "net.ipv6.conf.all.forwarding" = 1;
# };
#
# networking.interfaces.enp2s0 = {
# useDHCP = false;
# ipv4.addresses = [
# {
# address = "192.168.100.1";
# prefixLength = 24;
# }
# ];
# };
#
# networking.nat = {
# enable = true;
# internalInterfaces = [ "enp2s0" ];
# externalInterface = "enp0s20f0u1";
# };
#
# services.dnsmasq = {
# enable = true;
# settings = {
# interface = "enp2s0";
# bind-interfaces = true;
# dhcp-range = "192.168.100.10,192.168.100.50,24h";
# dhcp-option = [
# "3,192.168.100.1" # default Gateway
# "6,192.168.100.1" # DNS
# ];
# };
# };
#
# networking.firewall.interfaces."enp2s0" = {
# allowedUDPPorts = [
# 53
# 67
# ];
# allowedTCPPorts = [ 53 ];
# };
#
# networking.firewall.extraCommands = ''
# iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE
# iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
# '';
}

7
hosts/rx4/packages.nix Normal file
View file

@ -0,0 +1,7 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
gitMinimal
];
}

View file

@ -0,0 +1,5 @@
{ inputs, ... }:
{
imports = [ inputs.synix.nixosModules.sops ];
}

View file

@ -0,0 +1,42 @@
tailscale:
auth-key: ENC[AES256_GCM,data:T4w4IbcQRPYEqAWLE0QhZGG7gx50TN8YPvGvtselFKJruOyW3fTQABQ7vbxJeEw8,iv:/STVNXjA4RHdIXtOn8kq0oke+GS3dD14/RxOdbBRZLQ=,tag:8UNhM6PIPq0LoVO9sYiJQw==,type:str]
alditalk:
username: ENC[AES256_GCM,data:QFcW1IIEbALNeagT8Q==,iv:nXDJUPMZc95YSCabTouYqT0Rw5FIlGH/VzizzDr5vmI=,tag:aOqN1bI8lm3dEd1bIEtSew==,type:str]
password: ENC[AES256_GCM,data:JP2I4nYQnKpCKL6qyXHc0kVu5Sc=,iv:QsjmGhLHS7FHsWirpYaRrSNvbo1SjjYtzG8F8GeBS6s=,tag:prjUsIG+tk69GKmq2knasw==,type:str]
netdata:
stream:
rx4:
uuid: ENC[AES256_GCM,data:2X2wlQwU+EdiPB9xXwNgttcrELX+NPKFsrqfi24+EOY0GgZC,iv:CTapkA5NiItbOPM5dl1Q2GOilVcHz0RlTkilEscSmeg=,tag:0BoLmmNriYJNo0YGKR93OA==,type:str]
miniflux:
admin-password: ENC[AES256_GCM,data:a2M7rkxkOLuNM3DIPJe7dUIMMRY=,iv:NlgjXkqtbZOHkzpohr0EKBYrVdhsm+wuQu24o7X91QA=,tag:HAkH50jm9CSW+r44N3cwSg==,type:str]
syncthing:
gui-pw: ENC[AES256_GCM,data:mN4rxYr5DZgvbpIkwSFIuPvviJE=,iv:Kyl3mZFOejVwEwBCKteJQpgbCosREp9C4T4JYhWz6KQ=,tag:6myk9lr/44CH/hyUPgRH0Q==,type:str]
forgejo-runner:
token: ENC[AES256_GCM,data:DZgi6ocpV0MplgQ6Et85vHxmkMfC4qYbLLdyRuj/4z8tJauz1w6DUQ==,iv:+SZYsv6sDn2Nc1WxhTn0dJGN9nXYZw16/HVtXJGXpHc=,tag:8Oa5mC7cUy85+lXHbRcCcg==,type:str]
webdav:
user: ENC[AES256_GCM,data:vCLx,iv:Nra/FprNfd02HpvqOb5uYK+IGRFHhNwnFXWrX71c0C0=,tag:TjbKKOKBTq31o/5MxmqIsA==,type:str]
pass: ENC[AES256_GCM,data:jfIoob6R6OhqKa2EujRzTQbvIlA=,iv:HvB088H2Z2uLCveT4YfNEdkK5VU0lBFD5FrZhx79fg0=,tag:1RnrfeUEURx0C575GTxi9A==,type:str]
sops:
age:
- recipient: age19yeqvv28fgrtk6jsh3xyaf0lch86kna6rcz4dwe962yyyyevu30sx474xy
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQenJrZTFtMlRIK0lIQUFQ
KzdXWEt0ekRxdnREaEx4R1lYU2hINkl6UkJzCkNsbDlvcFlIcVk3aTk2eHNNNVJ5
QVNtTWZsbTRHVTl5MjBmd05Ed2E5emcKLS0tIExJME56bWZGbVNoTitucEdNT1FC
cE5FZitXSFlFT0xjTENaejFtRyt0QjQKYDiGb/dIBrWwxOrbNPUkNUwSOKK3++gN
SYkc6TsJdLK9WNaIt2IyQiL3FQ28NEs9cm+kg/3PRUkYzWwxRzGXqQ==
-----END AGE ENCRYPTED FILE-----
- recipient: age16y79w6d9c607zest8ed8rgxajmqmw86grz8d5e8c34nej36j4gysst8pl9
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3ZWdBSWQvTERSc3JWRHZz
b3FWKzE5R0NZS253UC9NRlNoT3VYOWwvNVFFCk4rbUpnVFBGMHQ2TUlpWEZYS21m
L0ovMVkxT0IvZms5WGFCMjIxNWFpa00KLS0tIDZuWDZ2NXpwMkNHMWxSU1UwTXlv
NE5yK3ZaOG5PdXNSUnlIUmFSSmRFancKk57hCmo79HvI3hzzgQvgOK7oK5/dcQR8
f3R4OGF5+212VXEHR/hAEbKzV7CY4y6HhFyrGZ9bUKm1RrxtnVqUyA==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-02-14T18:41:58Z"
mac: ENC[AES256_GCM,data:2e546c6VEf7vFGgSM344upn5C7YDGAwi8cLA/RV68ukJMKLvH1gdra4ii77uOaC1sCNan5mV0Kjs5ZVYj81O8PU3WJa9ra8TeAt8F690zTxNWSo1F/4sZxAk8d1WIBoNn4IPkYxi8Ry9+xqK13Q9PvplHc14VArMYC86wU+k5hc=,iv:T3td5G+pdfWzSLDuVkb75uWub6eBPxjqJgOrv3wvaiQ=,tag:vlQJVzFJEDncDzjA3JWM6Q==,type:str]
unencrypted_suffix: _unencrypted
version: 3.11.0

View file

@ -0,0 +1,43 @@
{
outputs,
config,
pkgs,
...
}:
{
imports = [
outputs.nixosModules.alditalk-extender
];
services.alditalk-extender = {
enable = true;
package = pkgs.local.alditalk-true-unlimited;
envFile = config.sops.templates.alditalk-extender.path;
};
sops.secrets = {
"alditalk/username" = {
owner = "alditalk";
group = "alditalk";
mode = "0400";
};
"alditalk/password" = {
owner = "alditalk";
group = "alditalk";
mode = "0400";
};
};
sops.templates = {
alditalk-extender = {
owner = "alditalk";
group = "alditalk";
mode = "0400";
content = ''
USERNAME=${config.sops.placeholder."alditalk/username"}
PASSWORD=${config.sops.placeholder."alditalk/password"}
'';
};
};
}

View file

@ -0,0 +1,31 @@
{
inputs,
outputs,
...
}:
{
imports = [
inputs.synix.nixosModules.openssh
inputs.clients.nixosModules.syncthing
outputs.nixosModules.tailscale
./forgejo.nix
./miniflux.nix
./netdata.nix
./nginx.nix
./open-webui-oci.nix
./print-server.nix
./rss-bridge.nix
# ./webdav.nix # FIXME
# ./alditalk-extender.nix # FIXME
];
# bootstrap
# services.syncthing.enable = true;
# services.syncthing.guiAddress = "0.0.0.0:8384";
services.transmission.enable = true;
}

View file

@ -0,0 +1,29 @@
{
outputs,
config,
...
}:
{
imports = [
outputs.nixosModules.forgejo
outputs.nixosModules.forgejo-runner
];
services.forgejo = {
enable = true;
};
services.forgejo-runner = {
enable = true;
url = config.services.forgejo.settings.server.ROOT_URL;
tokenFile = config.sops.templates."forgejo-runner/token".path;
};
sops = {
secrets."forgejo-runner/token" = { };
templates."forgejo-runner/token".content = ''
TOKEN=${config.sops.placeholder."forgejo-runner/token"}
'';
};
}

View file

@ -0,0 +1,13 @@
{ inputs, constants, ... }:
{
imports = [ inputs.synix.nixosModules.miniflux ];
services.miniflux = {
enable = true;
config = {
ADMIN_USERNAME = "sid";
PORT = constants.services.miniflux.port;
};
};
}

View file

@ -0,0 +1,54 @@
{
config,
constants,
...
}:
{
services.netdata = {
enable = true;
config.global = {
"debug log" = "syslog";
"access log" = "syslog";
"error log" = "syslog";
};
configDir = {
"stream.conf" = config.sops.templates."netdata/stream.conf".path;
};
};
sops =
let
owner = config.services.netdata.user;
group = config.services.netdata.group;
mode = "0400";
restartUnits = [ "netdata.service" ];
in
{
# generate with `uuidgen`
secrets."netdata/stream/rx4/uuid" = {
inherit
owner
group
mode
restartUnits
;
};
templates."netdata/stream.conf" = {
inherit
owner
group
mode
restartUnits
;
# child node
content = ''
[stream]
enabled = yes
destination = ${constants.hosts.sid.ip}:${builtins.toString constants.services.netdata.port}
api key = ${config.sops.placeholder."netdata/stream/rx4/uuid"}
'';
};
};
}

View file

@ -0,0 +1,37 @@
{
inputs,
constants,
config,
...
}:
let
cfg = config.services.nginx;
in
{
imports = [
inputs.synix.nixosModules.nginx
];
systemd.tmpfiles.rules = [
"d /var/www 0755 gitea-runner ${cfg.group} -"
];
systemd.services.gitea-runner-default.serviceConfig = {
ReadWritePaths = [ "/var/www" ];
};
services.nginx = {
enable = true;
openFirewall = false;
forceSSL = false;
virtualHosts = {
"${constants.services.docs.fqdn}" = {
locations."/" = {
root = "/var/www/doc";
};
};
};
};
}

View file

@ -0,0 +1,30 @@
{
inputs,
constants,
config,
...
}:
{
imports = [ inputs.synix.nixosModules.open-webui-oci ];
services.open-webui-oci = {
enable = true;
externalUrl = "https://" + constants.services.open-webui-oci.fqdn;
port = 8083;
# environmentFile = config.sops.templates."open-webui-oci/environment".path;
# environment = {
# AUDIO_STT_ENGINE = "openai";
# AUDIO_TTS_ENGINE = "openai";
# };
};
# sops = {
# secrets."open-webui-oci/stt-api-key" = { };
# secrets."open-webui-oci/tts-api-key" = { };
# templates."open-webui-oci/environment".content = ''
# AUDIO_STT_OPENAI_API_KEY=${config.sops.placeholder."open-webui-oci/stt-api-key"}
# AUDIO_TTS_OPENAI_API_KEY=${config.sops.placeholder."open-webui-oci/tts-api-key"}
# '';
# };
}

View file

@ -0,0 +1,12 @@
{
inputs,
...
}:
{
imports = [
inputs.synix.nixosModules.print-server
];
services.print-server.enable = true;
}

View file

@ -0,0 +1,14 @@
{ inputs, constants, ... }:
{
imports = [ inputs.synix.nixosModules.rss-bridge ];
services.rss-bridge = {
enable = true;
reverseProxy = {
enable = true;
subdomain = constants.services.rss-bridge.subdomain;
forceSSL = false;
};
};
}

View file

@ -0,0 +1,86 @@
{ constants, config, ... }:
# FIXME: floccus throws error: NetworkError when attempting to fetch resource.
let
cfg = config.services.webdav;
inherit (constants.services.webdav) fqdn port;
in
{
services.webdav = {
enable = true;
environmentFile = config.sops.templates."webdav/env-file".path;
settings = {
inherit port;
address = "127.0.0.1";
prefix = "/";
directory = "/srv/webdav";
users = [
{
username = "{env}WEBDAV_USER";
password = "{env}WEBDAV_PASS";
permissions = "CRUD";
}
];
};
};
systemd.tmpfiles.rules = [
"d ${cfg.settings.directory} 0750 ${cfg.user} ${cfg.group} -"
];
networking.firewall.allowedTCPPorts = [ port ];
services.nginx = {
enable = true;
virtualHosts."${fqdn}" = {
listen = [
{
addr = "0.0.0.0";
inherit port;
}
];
locations."/" = {
proxyPass = "http://127.0.0.1:${toString port}";
extraConfig = ''
add_header 'Access-Control-Allow-Origin' '*' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PROPFIND, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Depth' always;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PROPFIND, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Depth';
return 204;
}
'';
};
};
};
sops =
let
owner = cfg.user;
group = cfg.group;
mode = "0400";
in
{
secrets = {
"webdav/user" = {
inherit owner group mode;
};
"webdav/pass" = {
inherit owner group mode;
};
};
templates."webdav/env-file" = {
inherit owner group mode;
content = ''
WEBDAV_USER=${config.sops.placeholder."webdav/user"}
WEBDAV_PASS=${config.sops.placeholder."webdav/pass"}
'';
};
};
}

9
hosts/sid/boot.nix Normal file
View file

@ -0,0 +1,9 @@
{
boot.loader = {
grub = {
enable = true;
device = "/dev/sda";
};
timeout = 1;
};
}

28
hosts/sid/default.nix Normal file
View file

@ -0,0 +1,28 @@
{
inputs,
outputs,
...
}:
{
imports = [
./boot.nix
./hardware.nix
./packages.nix
./secrets
./services
../../users/sid
inputs.synix.nixosModules.common
inputs.synix.nixosModules.device.server
outputs.nixosModules.common
outputs.nixosModules.deploy
];
networking.hostName = "sid";
networking.domain = "sid.ovh";
system.stateVersion = "24.11";
}

74
hosts/sid/disks.sh Normal file
View file

@ -0,0 +1,74 @@
#!/usr/bin/env bash
SSD='/dev/sda'
MNT='/mnt'
SWAP_GB=4
# Helper function to wait for devices
wait_for_device() {
local device=$1
echo "Waiting for device: $device ..."
while [[ ! -e $device ]]; do
sleep 1
done
echo "Device $device is ready."
}
swapoff --all
udevadm settle
wait_for_device $SSD
echo "Wiping filesystem on $SSD..."
wipefs -a $SSD
echo "Creating new MBR partition table on $SSD..."
fdisk $SSD << EOF
o
w
EOF
echo "Partitioning $SSD..."
fdisk $SSD << EOF
n
p
1
+512M
a
n
p
2
+${SWAP_GB}G
t
2
82
n
p
3
w
EOF
partprobe -s $SSD
udevadm settle
wait_for_device "${SSD}1"
wait_for_device "${SSD}2"
wait_for_device "${SSD}3"
echo "Formatting partitions..."
mkfs.ext4 -L BOOT "${SSD}1"
mkswap -L SWAP "${SSD}2"
mkfs.ext4 -L ROOT "${SSD}3"
echo "Mounting partitions..."
mount -o X-mount.mkdir "${SSD}3" "$MNT"
mkdir -p "$MNT/boot"
mount "${SSD}1" "$MNT/boot"
echo "Enabling swap..."
swapon "${SSD}2"
echo "Partitioning and setup complete:"
lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL

43
hosts/sid/hardware.nix Normal file
View file

@ -0,0 +1,43 @@
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [
"ahci"
"xhci_pci"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-label/ROOT";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-label/BOOT";
fsType = "ext4";
};
swapDevices = [
{ device = "/dev/disk/by-label/SWAP"; }
];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}

5
hosts/sid/packages.nix Normal file
View file

@ -0,0 +1,5 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [ ];
}

View file

@ -0,0 +1,5 @@
{ inputs, ... }:
{
imports = [ inputs.synix.nixosModules.sops ];
}

View file

@ -0,0 +1,57 @@
matrix:
registration-shared-secret: ENC[AES256_GCM,data:RG+o/Maaot5B1fViX9QVEQbfBNWsMyd1Kbql5jiSrI0=,iv:XyoBa/I2KrUI9rJuojNk0ReoUFLz8aIAXwQOxldX6mM=,tag:C823WZrDfzj7ad79Sb5avQ==,type:str]
coturn:
static-auth-secret: ENC[AES256_GCM,data:xSKcBRxCMQAJYH9P1gWfxITI/f9CxJOcjA==,iv:d5Ta71T0uVPQtuuZpAqqIEwYOWcXrSrqiBwQhm7wxc8=,tag:YTEJjahWatvpZTiFqcAwNQ==,type:str]
maubot:
admins:
sid: ENC[AES256_GCM,data:0pTyD0GqmKY6ESX6IAoLneNcVY4=,iv:7ozvabxUek4ZwmobxoVp/l9diNLfSJ7BV0JLAx+maqI=,tag:iAucMU5DLALzX5B8vXzQFg==,type:str]
mautrix-whatsapp:
encryption-pickle-key: ENC[AES256_GCM,data:QdpAcqhtNwtft2PQZ7thN8+Lp1EuGUFVmf8aTOPyUy7/k/QisxJ5GzoVxoU=,iv:cF3fVXPfYiW6drKYOT8Udln35ljUIojSrKzwFI5ldcg=,tag:UeUqV8RP0kMNGUMXn8+Vkw==,type:str]
provisioning-shared-secret: ENC[AES256_GCM,data:RD6bTfwlnNoqSFHKv2+t2PWTKzqHRUtPY4tjpdN8SNFYbjXhTL6hDByfvkY=,iv:t0x0nGHAdkQcTXj/NLzp87PHkQd+KsEWVE3kjVAGQYc=,tag:wt9v22ZGwib22K7vt2XzSw==,type:str]
public-media-signing-key: ENC[AES256_GCM,data:XRK+kqlauhJrihsZcBjYHgffrg4EaL3OjAxzmLMfKgm/Se83vXuolR1om0c=,iv:JrExIjG9FrUqQysGuCwVM56OHV15H+749uaQN7yOOSI=,tag:/XXWajUFpNyms2SvavNy5A==,type:str]
direct-media-server-key: ENC[AES256_GCM,data:xglwy39u5rQEQCjM4PeZWoKfyCE6cukaxCaIaWx2fsjRRAAUlkpvk0rMWKE=,iv:5SRT3cTeluiQu9fGpnBGZVnICf/+T/tbR+HxRUPwOp4=,tag:tge5A8Egl8A4ipSfW1my+g==,type:str]
mautrix-signal:
encryption-pickle-key: ENC[AES256_GCM,data:6VgqXicsAv8Uk97OFSHmAHyL1UJnpZOZ2dE06hn1VmOFqTJTjyUwfmMZm/Q=,iv:25xFUZtl2oYUR/DjJUAVD9iul2edCywEB5sHH5nX1YU=,tag:W1qBvEjA9nJXTk0vgcUj1g==,type:str]
provisioning-shared-secret: ENC[AES256_GCM,data:CThIqVwTS8ofecQx2qA+DBmK5FrGXqju2B69zQOH1iqRZKXb3pWnO+0zP3M=,iv:WpBoqhH4S4PN3XrBmK5bUDKxX9p7ClPzqoPDWtUbfyM=,tag:Hlnra1FpCGblt58uXQv6dA==,type:str]
public-media-signing-key: ENC[AES256_GCM,data:w174hn2Rkw50RsL0Cai86DW8nsko0E2kMge6XAeimQ21pRyGbsemqvYEOV0=,iv:OcimE4Gu2rnEFUQEiMyhOCLXF1YLiTYgMxsNaqDpFV0=,tag:32vnGX7Ia3YS8bFCHpBzkA==,type:str]
direct-media-server-key: ENC[AES256_GCM,data:hRa+7+4HraXPmei/+yIuegllCnwQgTWQalX4+RKY526VBpprLkhLP1VQOGE=,iv:IX38m+cIWSHvz3gze21sEsqhOcappkYMtboslnOfzFU=,tag:2qSJWA31B5oQpdqI4cxY/w==,type:str]
headplane:
cookie_secret: ENC[AES256_GCM,data:FbD5pttQIRB4IgEAapPVhonG5JrhPczeIGuO63a8IGM=,iv:kyAtWzHbSWpC7VHzQNqYTG5Crm2rdSm5i1aIt2q58fg=,tag:EK3upQ+qabQa1QTuKxn6wg==,type:str]
agent_pre_authkey: ENC[AES256_GCM,data:Vj4aVMl8UASDscqN00xmd/J7DkUXq+XEdD1RZ34R2XhGDICWaV1Cj7wZqfoOYScT,iv:JP9l3Z1Hco+LDuw8nKP9hYtAc3QHYuVkULik1QGG83s=,tag:apBbo0uz8ljWEDNCAjQkGA==,type:str]
livekit:
key: ENC[AES256_GCM,data:QgD9fg6KvY/fGVdYVT9Oks/NkXm26oZaBUiVNpPCm0pvtVbzoiTv5BY9Krk=,iv:ayYBfr8s2MSD1EU809K6XGlP6dLcQVJC5vmscpqb2I4=,tag:juYtwZfUa7IV1Qcc+HnYnA==,type:str]
tailscale:
auth-key: ENC[AES256_GCM,data:BhCC0J0DmVaNAQmPo8I1a+0iBTUsZxBhXQlds2SIT5O/Daf2HGYsaGRg3IhVQmoK,iv:ws9B1V0JyfGyamTmc/pMOkMli1kcgKv6xLwXx6XB+r8=,tag:5KmqglMES7XlotIgQX2sdg==,type:str]
netdata:
stream:
rx4:
uuid: ENC[AES256_GCM,data:keIw+LxhS65mh6A4tQ9BWc/gVfiqfmP0AH1Z3uXwqCrrxrsO,iv:Nziivr53hm9nAwpTY4Y65cXTytuhxEV0IUbpWw1v9lE=,tag:hkV5ixwXoGqscyUNwkLafw==,type:str]
mailserver:
accounts:
sid: ENC[AES256_GCM,data:xnU/+8BEewcZcbTWroIgCx5ceSFtDPe0Pq//qt3RWk81QWvbJxdukF4EyBSoQ7AqBhf4nDFZZxd4s8rZ,iv:OFhRxXHWOEC9mKGyK2ePfVGpBCDTfv0L+q3xzbXFefI=,tag:iO52YhFsSvb59RbcgXb+9w==,type:str]
radicale:
sid: ENC[AES256_GCM,data:/OgIrXnGttIymGw98feiUjKPOIlrgRIC0TNCdBnuJOiA0RzbF0b9SMVzwEZiTEmS82g2lSvxQkE4kZjeOgOC0RLvCyZAmtWojq+g1pN0qhEkhwH0Qtu9wNnSYHuRqh2E5nWzHNGl/eF6zQ==,iv:5XtlyXjpB+XrVvJ7IoM7Gu63xA8vYrcJjUjLPmOMAIU=,tag:SAuYl/wzxnINyVWn9nI5yA==,type:str]
sops:
age:
- recipient: age19yeqvv28fgrtk6jsh3xyaf0lch86kna6rcz4dwe962yyyyevu30sx474xy
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSByRUpBMnV5djEraUZRUmRT
RjZncjZBZk1MOU15WlBWRFlxS2RQZS8vU3hzCnRRQS8rVmgxV2dIbDV5MHNJNGI2
c3drTk5xT2pnS0hVaXk2Uy8vOXhXUFEKLS0tIHFTVERPbklBL2loaDJVWEhOSVk1
RktRV0hxcklSV254bUx1S0paYkluTEUKYSkCqXl20byCtozRkbVmVlXsa7hNoU7a
TJvxj5Qc44on94thkDaD7RFsWTA3VpFXSzDf4VaOaa7Fi0foVWAdUw==
-----END AGE ENCRYPTED FILE-----
- recipient: age1ytfze9tv5l80ujqfd66xp97w2u0lq8jrx45ulf0szey8ny0t837sdktdzf
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0djJpOVp0bjNlendlcFdW
VEs0elo1R0FwaGViMmY1dkJDeTBiYllSNUFrCmRlTTM1SDVOZTB5WlJlVEhSaWZX
ck9VT1JyNUFsanZwYWhPUW5iNWs1clkKLS0tIDZzVVBTOUZKRklCd1RnOUpNRDR0
RzhnczA0S1pxcXZncGpWVHNYQW96L28K+ytH3PPyg4+wibpAQhp02RiSfZ83EDRB
UJ8UV1d+51D0e2A1sI95r2AzDj4jfwUnI+LYDPC/qEpsu5LFLGVyeg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-02-01T22:55:09Z"
mac: ENC[AES256_GCM,data:l+lTLQJ5FRAmvCNIDDFr4gpEvGw0csSKIeI8MnBfM5qsC+wg0d8JSAvBB1m+P/IKLeRoV4AdLuNaflisVoU+dVnk7yX7/lLKt5dfARoFX6zU+u4G4Q6jmpq80CegHFJNWMJE2NAMVrP6m465foWkXlhZIpyT0FBSwtaZkoc74Hg=,iv:H4sxdjPc1C3XxHkHPAooN2cRCHKd4CpzfoH7UM8t/q4=,tag:JHhdlg4g+8kIN0CngGaOaA==,type:str]
unencrypted_suffix: _unencrypted
version: 3.11.0

View file

@ -0,0 +1,20 @@
{
inputs,
outputs,
...
}:
{
imports = [
inputs.synix.nixosModules.openssh
outputs.nixosModules.tailscale
./headscale.nix
./mailserver.nix
./matrix-synapse.nix
./netdata.nix
./nginx.nix
./radicale.nix
];
}

View file

@ -0,0 +1,70 @@
{
inputs,
...
}:
# TODO: use constants.nix
{
imports = [
inputs.synix.nixosModules.headplane
inputs.synix.nixosModules.headscale
];
services.resolved.enable = false;
networking.resolvconf.enable = false;
networking.nameservers = [ "100.64.0.6" ];
services.coredns = {
enable = true;
config = ''
.:53 {
bind 100.64.0.6
hosts {
100.64.0.6 sid.tail
100.64.0.6 netdata.sid.tail
100.64.0.10 rx4.tail
100.64.0.10 dav.rx4.tail
100.64.0.1 vde.tail
fallthrough
}
forward . 1.1.1.1
cache
log
errors
}
'';
};
services.headplane = {
enable = true;
reverseProxy = {
enable = true;
subdomain = "hp";
};
};
services.headscale = {
enable = true;
openFirewall = true;
reverseProxy = {
enable = true;
subdomain = "hs";
};
settings = {
dns = {
magic_dns = true;
base_domain = "tail";
search_domains = [ "tail" ];
override_local_dns = true;
nameservers = {
global = [ "1.1.1.1" ];
split = {
"tail" = [ "100.64.0.6" ];
};
};
};
};
};
}

View file

@ -0,0 +1,15 @@
{ inputs, ... }:
{
imports = [ inputs.synix.nixosModules.mailserver ];
mailserver = {
enable = true;
stateVersion = 3;
accounts = {
sid = {
aliases = [ "postmaster" ];
};
};
};
}

View file

@ -0,0 +1,58 @@
{
inputs,
config,
pkgs,
...
}:
{
imports = [
inputs.synix.nixosModules.baibot
inputs.synix.nixosModules.coturn
inputs.synix.nixosModules.matrix-synapse
inputs.synix.nixosModules.maubot
];
nixpkgs.config.permittedInsecurePackages = [
"olm-3.2.16"
];
services.baibot = {
enable = true;
package = pkgs.synix.baibot;
};
services.coturn = {
enable = true;
sops = true;
openFirewall = true;
};
services.matrix-synapse = {
enable = true;
sops = true;
coturn.enable = true;
bridges = {
whatsapp = {
enable = true;
admin = "@sid:sid.ovh";
};
signal = {
enable = true;
admin = "@sid:sid.ovh";
};
};
};
services.maubot = {
enable = true;
sops = true;
admins = [
"sid"
];
plugins = with config.services.maubot.package.plugins; [
github
reminder
];
};
}

View file

@ -0,0 +1,71 @@
{
config,
pkgs,
...
}:
let
email = "sid@${config.networking.domain}";
in
{
services.netdata = {
enable = true;
package = pkgs.netdata.override {
withCloudUi = true;
};
config.global = {
"debug log" = "syslog";
"access log" = "syslog";
"error log" = "syslog";
};
configDir = {
"stream.conf" = config.sops.templates."netdata/stream.conf".path;
"health_alarm_notify.conf" = pkgs.writeText "health_alarm_notify.conf" ''
SEND_EMAIL="YES"
sendmail="/run/wrappers/bin/sendmail"
EMAIL_SENDER="netdata@${config.networking.domain}"
DEFAULT_RECIPIENT_EMAIL="${email}"
role_recipients_email[sysadmin]="${email}"
role_recipients_email[domainadmin]="${email}"
role_recipients_email[root]="${email}"
'';
};
};
systemd.services.netdata.environment = {
NETDATA_USER_CONFIG_DIR = "/etc/netdata/conf.d";
};
sops =
let
owner = config.services.netdata.user;
group = config.services.netdata.group;
mode = "0400";
restartUnits = [ "netdata.service" ];
in
{
secrets."netdata/stream/rx4/uuid" = {
inherit
owner
group
mode
restartUnits
;
};
templates."netdata/stream.conf" = {
inherit
owner
group
mode
restartUnits
;
# parent node
content = ''
[${config.sops.placeholder."netdata/stream/rx4/uuid"}]
enabled = yes
default history = 3600
'';
};
};
}

View file

@ -0,0 +1,62 @@
{
inputs,
constants,
lib,
...
}:
let
ssl = true;
inherit (lib.utils) mkVirtualHost;
in
{
imports = [
inputs.synix.nixosModules.nginx
];
services.nginx = {
enable = true;
openFirewall = true;
forceSSL = ssl;
virtualHosts."${constants.services.docs.fqdn}" = mkVirtualHost {
inherit ssl;
address = constants.hosts.rx4.ip;
port = 80;
};
virtualHosts."${constants.services.forgejo.fqdn}" = mkVirtualHost {
inherit ssl;
address = constants.hosts.rx4.ip;
port = constants.services.forgejo.port;
};
virtualHosts."${constants.services.miniflux.fqdn}" = mkVirtualHost {
inherit ssl;
port = constants.services.miniflux.port;
};
virtualHosts."${constants.services.netdata.fqdn}" = mkVirtualHost {
ssl = false;
port = constants.services.netdata.port;
};
virtualHosts."${constants.services.open-webui-oci.fqdn}" = mkVirtualHost {
inherit ssl;
address = constants.hosts.rx4.ip;
port = constants.services.open-webui-oci.port;
};
virtualHosts."${constants.services.rss-bridge.fqdn}" = {
enableACME = ssl;
forceSSL = ssl;
locations."/" = {
proxyPass = "http://${constants.hosts.rx4.ip}";
};
};
# FIXME
# virtualHosts."print.sid.ovh" = {
# enableACME = true;
# forceSSL = true;
# locations."/" = {
# proxyPass = "http://100.64.0.5:631";
# proxyWebsockets = true;
# };
# };
};
}

View file

@ -0,0 +1,16 @@
{ inputs, ... }:
{
imports = [ inputs.synix.nixosModules.radicale ];
services.radicale = {
enable = true;
reverseProxy = {
enable = true;
subdomain = "dav";
};
users = [
"sid"
];
};
}

7
hosts/vde/boot.nix Normal file
View file

@ -0,0 +1,7 @@
{
boot.loader.systemd-boot = {
enable = true;
configurationLimit = 10;
};
boot.loader.efi.canTouchEfiVariables = true;
}

31
hosts/vde/default.nix Normal file
View file

@ -0,0 +1,31 @@
{
inputs,
outputs,
...
}:
{
imports = [
./boot.nix
./hardware.nix
./networking.nix
./packages.nix
./secrets
./services
# ./virtualisation.nix
../../users/sid
inputs.synix.nixosModules.common
inputs.synix.nixosModules.device.server
outputs.nixosModules.common
outputs.nixosModules.deploy
outputs.nixosModules.xfce
];
networking.hostName = "vde";
networking.domain = "vde.lan";
system.stateVersion = "25.11";
}

64
hosts/vde/disks.sh Normal file
View file

@ -0,0 +1,64 @@
#!/usr/bin/env bash
SSD='/dev/disk/by-id/wwn-0x500a0751e280a38c'
MNT='/mnt'
SWAP_GB=16
# Helper function to wait for devices
wait_for_device() {
local device=$1
echo "Waiting for device: $device ..."
while [[ ! -e $device ]]; do
sleep 1
done
echo "Device $device is ready."
}
# Function to install a package if it's not already installed
install_if_missing() {
local cmd="$1"
local package="$2"
if ! command -v "$cmd" &> /dev/null; then
echo "$cmd not found, installing $package..."
nix-env -iA "nixos.$package"
fi
}
install_if_missing "sgdisk" "gptfdisk"
install_if_missing "partprobe" "parted"
wait_for_device $SSD
echo "Wiping filesystem on $SSD..."
wipefs -a $SSD
echo "Clearing partition table on $SSD..."
sgdisk --zap-all $SSD
echo "Partitioning $SSD..."
sgdisk -n1:1M:+1G -t1:EF00 -c1:BOOT $SSD
sgdisk -n2:0:+"$SWAP_GB"G -t2:8200 -c2:SWAP $SSD
sgdisk -n3:0:0 -t3:8304 -c3:ROOT $SSD
partprobe -s $SSD
udevadm settle
wait_for_device ${SSD}-part1
wait_for_device ${SSD}-part2
wait_for_device ${SSD}-part3
echo "Formatting partitions..."
mkfs.vfat -F 32 -n BOOT "${SSD}-part1"
mkswap -L SWAP "${SSD}-part2"
mkfs.ext4 -L ROOT "${SSD}-part3"
echo "Mounting partitions..."
mount -o X-mount.mkdir "${SSD}-part3" "$MNT"
mkdir -p "$MNT/boot"
mount -t vfat -o fmask=0077,dmask=0077,iocharset=iso8859-1 "${SSD}-part1" "$MNT/boot"
echo "Enabling swap..."
swapon "${SSD}-part2"
echo "Partitioning and setup complete:"
lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL

76
hosts/vde/hardware.nix Normal file
View file

@ -0,0 +1,76 @@
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [
"xhci_pci"
"ahci"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-label/ROOT";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-label/BOOT";
fsType = "vfat";
options = [
"fmask=0022"
"dmask=0022"
];
};
swapDevices = [
{ device = "/dev/disk/by-label/SWAP"; }
];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
# vesa
# boot.kernelParams = [ "nomodeset" ];
# services.xserver.videoDrivers = [ "vesa" ];
# fbdev
boot.kernelParams = [ "nomodeset" ];
services.xserver.videoDrivers = [ "fbdev" ];
# nouveau
# hardware.graphics.enable = true;
# services.xserver.videoDrivers = [ "nouveau" ];
# modesetting
# services.xserver.videoDrivers = [ "modesetting" ];
# boot.kernelParams = [
# "video=1280x1024"
# "nouveau.modeset=1"
# "nouveau.noaccel=1"
# "nouveau.config=NvBios=0"
# ];
# proprietary drivers
# hardware.graphics.enable = true;
# services.xserver.videoDrivers = [ "nvidia" ];
# hardware.nvidia.open = false;
# hardware.nvidia.package = config.boot.kernelPackages.nvidia_x11_legacy340;
# nixpkgs.config.allowBroken = true;
# nixpkgs.config.allowUnfree = true;
# nixpkgs.config.nvidia.acceptLicense = true;
}

26
hosts/vde/networking.nix Normal file
View file

@ -0,0 +1,26 @@
{
networking.networkmanager.ensureProfiles.profiles = {
enp34s0-profile = {
connection = {
id = "enp34s0";
type = "ethernet";
interface-name = "enp34s0";
};
ipv4 = {
method = "auto";
route-metric = 50;
};
};
enp36s0-profile = {
connection = {
id = "enp36s0";
type = "ethernet";
interface-name = "enp36s0";
};
ipv4 = {
method = "auto";
route-metric = 200;
};
};
};
}

5
hosts/vde/packages.nix Normal file
View file

@ -0,0 +1,5 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [ ];
}

View file

@ -0,0 +1,8 @@
{ inputs, ... }:
{
imports = [ inputs.synix.nixosModules.sops ];
# sops.secrets."github-runners/vde" = { };
# sops.secrets."mailserver/accounts/sid" = { };
}

View file

@ -0,0 +1,26 @@
tailscale:
auth-key: ENC[AES256_GCM,data:Fz1XGaQXERn+3EymtWyq9oYqoX0KrcPJelda+addeX+vhqEAxRe5jRdzK8W6329b,iv:HNlz5f7dscDXsPoKZjSiIl2NZOouEJZyzU3kaiX1NUw=,tag:DdIxWKeZ9kfHUkh0/l1sEw==,type:str]
sops:
age:
- recipient: age19yeqvv28fgrtk6jsh3xyaf0lch86kna6rcz4dwe962yyyyevu30sx474xy
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuNVVVL29xeUQ0WDREREoy
dy83M1ZaYTM4NFlKZUVoVFlrNUEzQmRXMFJjClB2YkZKMUMxWGR4bnRBRzVFSHNG
Z2srYmRDcHhucUFlUVUxN0FGalM3RUEKLS0tIG5HMG5jWFZJcXc4cXB4cThVcmZI
ejVJanRtODh1a1RUQm00OGpoenNqeVUKAuvbRbO9w5KhcNAph+IuSTWxWCu9tF6u
QAVWMoHsMc43FQi72isjL23+nroiNKgxlS9VjSS04K2qvBGl296rtA==
-----END AGE ENCRYPTED FILE-----
- recipient: age1mc07jayz4dpwenh06fzlcgfzk5t7ln0z3n65emwlm5r7nq59m4jstd7y8u
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKQUpaTjRjSU0yaDZSRVBG
SWY1aFIvYzlYbkg1bGpWYXRock1nTHBMRHh3CkVqNlg5aU5rZk1ySmZSbmJEZ3JG
UVhrb1BITkxodmxPU1ZtK2lHcjFSRUUKLS0tIDc1QlMwZlZyNmVJbjNXekYzSkpJ
RjlIQWVIcTY0aUlhelorMDRycVZnOEkK69ZCxeh8IL2LcsjgkBgbIbC6XnDJ8zwd
yCuPYXkYOxeitToIbhHQS4TbgF61/tJqIixqoIe3vG+o112UspGkoQ==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2026-01-12T20:15:19Z"
mac: ENC[AES256_GCM,data:sDbfLjm6ZqkVUMNbB6ikMSlMiXd9Ukf2K8HdAF66JwPB+KQI/rqIRKiSaOEKJ8p1AvpEr86ENlCEZNeslQJAdlqbGy6+VOcbSAz2bfhhXfThaAEgYT9CmXAsJL8lWMI5N2Ti0kiepjk+nMG1bbFyPecHm4AqadMRC/RHprAK4fc=,iv:2UPmmBNATuXvk+LbF9Lwi7Cgi0OFMHr96ONG6bpBDpY=,tag:i5If1ui4XHeuE7BjUEHUCA==,type:str]
unencrypted_suffix: _unencrypted
version: 3.11.0

View file

@ -0,0 +1,15 @@
{
inputs,
outputs,
...
}:
{
imports = [
inputs.synix.nixosModules.openssh
outputs.nixosModules.tailscale
# ./monero.nix
];
}

View file

@ -0,0 +1,19 @@
{ outputs, ... }:
{
imports = [
outputs.nixosModules.monero
];
services = {
monero = {
enable = true;
mining.address = "";
};
xmrig.settings = {
cpu = {
max-threads-hint = 4;
};
};
};
}

View file

@ -0,0 +1,5 @@
{ inputs, ... }:
{
imports = [ inputs.synix.nixosModules.virtualisation ];
}