summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.sops.yaml10
-rw-r--r--certs/pi_ed25519.pub1
-rw-r--r--certs/wilkuu_rsa.pub1
-rw-r--r--flake.lock22
-rw-r--r--flake.nix21
-rw-r--r--hosts/apocalypse/default.nix3
-rw-r--r--hosts/omega-relay/default.nix139
-rw-r--r--hosts/omega-relay/disko.nix70
-rw-r--r--hosts/omega-relay/firewall.nix120
-rw-r--r--hosts/omega-relay/hardware-configuration.nix24
-rw-r--r--hosts/omega-relay/vm.nix43
-rw-r--r--hosts/test_vm/default.nix2
-rw-r--r--modules/default.nix2
-rw-r--r--modules/virt.nix2
-rw-r--r--secrets/omega-relay/freshrss.yaml45
-rw-r--r--secrets/omega-relay/stalwart.yaml44
-rw-r--r--secrets/omega-relay/vaultwarden.yaml45
-rw-r--r--secrets/omega-relay/wakapi.yaml44
-rw-r--r--secrets/omega-relay/wireguard.yaml48
-rw-r--r--services/email.nix174
-rw-r--r--services/freshrss.nix94
-rw-r--r--services/mysql.nix139
-rw-r--r--services/uptimekuma.nix79
-rw-r--r--services/vaultwarden.nix78
-rw-r--r--services/wakapi.nix112
-rw-r--r--users/user-common.nix2
-rw-r--r--users/wilkuu-server.nix53
27 files changed, 1414 insertions, 3 deletions
diff --git a/.sops.yaml b/.sops.yaml
index 1bb53dd..6bbf5cf 100644
--- a/.sops.yaml
+++ b/.sops.yaml
@@ -1,6 +1,10 @@
keys:
- &admin_wilkuu age1hsxrd9shau86k7zz9wfdeplldyg5c2al6umnr7rn6tf7ewus64uswufr0a
- &server_apocalypse age19cw4x4ycrdhfdkwvp009czmvfhucpdtn8lme4ja0rvq7er87z3wsd2fxz7
+ - &virtserver_omega_relay age1n20lpr5x2aep3l3ta62x2c9cnuz3m495f2dmguqs08ezlqgu4vwsqfskyg
+ - &vm_omega_relay age13x9grwfpqjgvjfcnwg5snuntp5emze85hqc8qwuz9nfphfe2pg4skl29r4
+ - &server_omega_relay age18u22lycxtcasvlm298qwzwuc97z56kkhw8ssy9yx4gzlkskuwpyqdz80g4
+
creation_rules:
- path_regex: secrets/[^/]+\.(yaml|json|env|ini)$
@@ -12,4 +16,10 @@ creation_rules:
age:
- *admin_wilkuu
- *server_apocalypse
+ - path_regex: secrets/omega-relay/[^/]+\.(yaml|json|env|ini)$
+ age:
+ - *admin_wilkuu
+ - *virtserver_omega_relay
+ - *vm_omega_relay
+ - *server_omega_relay
diff --git a/certs/pi_ed25519.pub b/certs/pi_ed25519.pub
new file mode 100644
index 0000000..c48e71e
--- /dev/null
+++ b/certs/pi_ed25519.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHyI7t5cN7ClErKx/wCwAMlNZoQqzJr7R3+gWWJ1MGIO wilkuu@iron-curtain
diff --git a/certs/wilkuu_rsa.pub b/certs/wilkuu_rsa.pub
new file mode 100644
index 0000000..de478a5
--- /dev/null
+++ b/certs/wilkuu_rsa.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCc+ueAAfocDsWyNVyzW6NK59I0v79xUALL9gX2OAmh3zKdpoMq1/MiVvdI73HWs9pRzaeH1JrySjENdvScoj1FeEIu2Q1D8bJ9WlTZzXNwwGsVd9IyCPWwwQYah6toZXlpSrpC9pHwGvnjzN6Yz6ka1BDnZTa1bGrGEKMiADIL9yaRAObHcjIVJ9eonViUn3wjyZr3FWUuXXJtfROOAxvWH1OdVJK39Y1QFgp0H4FjAJ3dfJlV81qDMy1+uVTzEfatrm8DUnfmS9xFsTn++KLKUmUXknyeQQ0c0dh/RkG6vbzaNOVZ7YMyFyiJsXM2xLNbWxMDBx+71fYWjR+5I4zBpe19EoARf1ZB78GMOxOJcX0PS1c8jDoLUzZKII3QjDZi81OvhApno6wvyHXHk/3edh5pxCae/rMa1OH9W6Ncdk5CE2JCozR7vdm20NzeEjXtJJzN3pPzm0CrOeQRIsodzV7c9OBKDJz7NjjD9aZxnf9X50edslMxz0Xw0AkWgac= j.stachurski@student.utwente.nl
diff --git a/flake.lock b/flake.lock
index 8c8a7e6..6c6f7a8 100644
--- a/flake.lock
+++ b/flake.lock
@@ -15,6 +15,27 @@
"type": "github"
}
},
+ "disko": {
+ "inputs": {
+ "nixpkgs": [
+ "nixpkgs"
+ ]
+ },
+ "locked": {
+ "lastModified": 1768920986,
+ "narHash": "sha256-CNzzBsRhq7gg4BMBuTDObiWDH/rFYHEuDRVOwCcwXw4=",
+ "owner": "nix-community",
+ "repo": "disko",
+ "rev": "de5708739256238fb912c62f03988815db89ec9a",
+ "type": "github"
+ },
+ "original": {
+ "owner": "nix-community",
+ "ref": "latest",
+ "repo": "disko",
+ "type": "github"
+ }
+ },
"flake-utils": {
"inputs": {
"systems": "systems"
@@ -87,6 +108,7 @@
},
"root": {
"inputs": {
+ "disko": "disko",
"home-manager": "home-manager",
"nixpkgs": "nixpkgs",
"nixpkgs-stable": "nixpkgs-stable",
diff --git a/flake.nix b/flake.nix
index 8a90cec..856d15a 100644
--- a/flake.nix
+++ b/flake.nix
@@ -10,6 +10,11 @@
inputs.nixpkgs.follows = "nixpkgs";
};
+ disko = {
+ url = "github:nix-community/disko/latest";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
+
home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
@@ -31,6 +36,7 @@
self,
nixpkgs,
treefmt-nix,
+ disko,
...
}@inputs:
let
@@ -89,6 +95,21 @@
inputs.sops-nix.nixosModules.sops
];
};
+ omega-relay = nixpkgs.lib.nixosSystem {
+ specialArgs = {
+ inherit inputs;
+ };
+ system = "x86_64-linux";
+ modules = [
+ ./modules
+ ./users/wilkuu-server.nix
+ ./hosts/omega-relay
+ inputs.home-manager.nixosModules.default
+ disko.nixosModules.disko
+ inputs.sops-nix.nixosModules.sops
+ ];
+
+ };
};
};
}
diff --git a/hosts/apocalypse/default.nix b/hosts/apocalypse/default.nix
index d22f2df..587daaf 100644
--- a/hosts/apocalypse/default.nix
+++ b/hosts/apocalypse/default.nix
@@ -9,6 +9,9 @@
## TODO REMOVE LATER TO PREVENT ELI FROM BUILDING REMOTELY
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
+ networking.hosts = {
+ "127.0.0.1" = [ "omega-relay.local" ];
+ };
## Addons for this system
addons = {
diff --git a/hosts/omega-relay/default.nix b/hosts/omega-relay/default.nix
new file mode 100644
index 0000000..3c7272c
--- /dev/null
+++ b/hosts/omega-relay/default.nix
@@ -0,0 +1,139 @@
+{
+ pkgs,
+ lib,
+ config,
+ ...
+}:
+{
+ imports = [
+ ./firewall.nix
+ ./disko.nix
+ ./vm.nix
+ ./hardware-configuration.nix
+ ../../services/mysql.nix
+ ../../services/email.nix
+ ../../services/vaultwarden.nix
+ ../../services/uptimekuma.nix
+ ../../services/freshrss.nix
+ ../../services/wakapi.nix
+ ];
+
+ addons = {
+ desktop.hyprland.enable = lib.mkForce false;
+ # desktop.cosmic.enable = lib.mkForce false;
+ desktop.xfce.enable = lib.mkForce false;
+
+ gpg.enable = true;
+ virtualisation.guest = true;
+ };
+ boot.loader.grub = {
+ enable = true;
+ efiSupport = false;
+ };
+
+
+ environment.systemPackages = with pkgs; [
+ lynx
+ chawan
+ ];
+
+ wilkuu.services =
+ let
+ isVM = config.addons.virtualisation.isTestVM;
+ in
+ {
+ stalwart = {
+ enable = true;
+ domain = if isVM then "mail.omega-relay.local" else "mail.wilkuu.xyz";
+ doACME = !isVM;
+ };
+
+ vaultwarden = {
+ enable = true;
+ signupWhitelist = [
+ "wilkuu.xyz"
+ "omega-relay.local"
+ ];
+ backupDir = "/srv/data/vaultwarden";
+ domain = if isVM then "bitwarden.omega-relay.local" else "bitwarden.wilkuu.xyz";
+ doACME = !isVM;
+ };
+ uptimekuma = {
+ enable = true;
+ domain = if isVM then "uptime.omega-relay.local" else "uptime.wilkuu.xyz";
+ dataDir = "/srv/data/uptimekuma";
+ doACME = !isVM;
+ };
+ freshrss = {
+ enable = true;
+ domain = if isVM then "rss.omega-relay.local" else "rss.wilkuu.xyz";
+ doACME = !isVM;
+ };
+ wakapi = {
+ enable = false;
+ domain = if isVM then "wakapi.omega-relay.local" else "wakapi.wilkuu.xyz";
+ doACME = !isVM;
+ };
+ };
+
+ services.fail2ban = {
+ enable = true;
+ maxretry = 5;
+ ignoreIP = [
+ "192.168.80.0/24"
+ "192.168.80.0/24"
+ ];
+ bantime = "24h";
+ bantime-increment = {
+ enable = true; # Enable increment of bantime after each violation
+ formula = "ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)";
+ # multipliers = "1 2 4 8 16 32 64";
+ maxtime = "168h"; # Do not ban for more than 1 week
+ overalljails = true; # Calculate the bantime based on all the violations
+ };
+ };
+
+ # TODO: Make a nginx module
+ security.acme = lib.mkIf (!config.addons.virtualisation.isTestVM) {
+ acceptTerms = true;
+ defaults.email = "jstachurski9991@gmail.com";
+ };
+ services.nginx =
+ let
+ isVM = config.addons.virtualisation.isTestVM;
+ domain = if isVM then "omega-relay.local" else "wilkuu.xyz";
+ in
+ {
+ enable = true;
+ virtualHosts."${domain}" = {
+ enableACME = !isVM;
+ addSSL = !isVM;
+ root = "/srv/www/wilkuu.xyz/";
+ locations."/" = {
+ index = "index.html";
+ tryFiles = "$uri $uri/ =404";
+ };
+ };
+ };
+
+ networking.hostName = "omega-relay";
+ services.resolved = {
+ enable = true;
+ dnsovertls = "opportunistic";
+ };
+
+ services.openssh = {
+ enable = true;
+ ports = [ 22 ];
+ openFirewall = true;
+ allowSFTP = true;
+ settings = {
+ PasswordAuthentication = false;
+ AllowUsers = [ "wilkuu" ];
+ X11Forwarding = false;
+ PermitRootLogin = "no";
+ PrintMotd = true;
+ };
+ };
+
+}
diff --git a/hosts/omega-relay/disko.nix b/hosts/omega-relay/disko.nix
new file mode 100644
index 0000000..2de6943
--- /dev/null
+++ b/hosts/omega-relay/disko.nix
@@ -0,0 +1,70 @@
+{ config, lib, ... }:
+let
+ cfg = config.hosts.omega-relay;
+in
+{
+ options.hosts.omega-relay = with lib; {
+ root_device = mkOption {
+ type = types.path;
+ default = "/dev/sda";
+ example = "/dev/sda";
+ description = "Root device for disko and grub";
+ };
+
+ do_disko = mkOption {
+ type = types.bool;
+ default = !config.addons.virtualisation.isTestVM;
+ description = "Whenever to do disko or not.";
+ };
+ };
+ config = lib.mkIf (cfg.do_disko) ({
+ services.btrfs.autoScrub = {
+ enable = true;
+ interval = "weekly";
+ };
+
+ boot.loader.grub.device = cfg.root_device;
+ # Workaround
+ boot.loader.grub.devices = lib.mkForce [ cfg.root_device ];
+ boot.loader.efi.canTouchEfiVariables = false;
+
+ # TODO: Mount points
+
+ # Disko for formatting
+ disko.devices = {
+ disk = {
+ main-disk = {
+ device = cfg.root_device;
+ type = "disk";
+ content = {
+ type = "gpt";
+ partitions = {
+ BOOT = {
+ type = "EF02";
+ size = "1M";
+ };
+ ESP = {
+ type = "EF00";
+ size = "128M";
+ content = {
+ type = "filesystem";
+ format = "vfat";
+ mountpoint = "/boot";
+ mountOptions = [ "umask=0077" ];
+ };
+ };
+ root = {
+ size = "100%";
+ content = {
+ type = "filesystem";
+ format = "btrfs";
+ mountpoint = "/";
+ };
+ };
+ };
+ };
+ };
+ };
+ };
+ });
+}
diff --git a/hosts/omega-relay/firewall.nix b/hosts/omega-relay/firewall.nix
new file mode 100644
index 0000000..c90a903
--- /dev/null
+++ b/hosts/omega-relay/firewall.nix
@@ -0,0 +1,120 @@
+{ config, lib, pkgs, ... }:
+let
+ wgHomePort = 16888;
+ baseTCP = [
+ 20
+ 22
+ 25
+ 80
+ 143
+ 443
+ 993
+ 465
+ ];
+ baseUDP = [
+ wgHomePort # Wireguard
+ ];
+ baseTCPRanges = [
+ ];
+
+ baseUDPRanges = [
+ ];
+
+ secureTCP = [
+ # config.wilkuu.services.mysql.port
+ ];
+
+ secureUDP = [
+ ];
+
+ secureTCPRanges = [
+ ];
+
+ secureUDPRanges = [
+ ];
+in
+{
+ sops.secrets = let
+ secrets = [
+ "wg/home/privateKey"
+ "wg/home/chrono/PSK"
+ "wg/home/chrono/PK"
+ "wg/home/chrono/endpoint"
+ ];
+ in lib.genAttrs secrets (name: {
+ sopsFile = ../../secrets/${config.networking.hostName}/wireguard.yaml;
+ key = lib.removePrefix "wg/" name;
+ });
+
+ networking.wireguard = {
+ enable = true;
+ useNetworkd = true;
+ interfaces = {
+ wg-home = {
+ ips = ["192.168.80.100/24"];
+ extraOptions = {
+ DNS = "192.168.88.1";
+ };
+ privateKeyFile = config.sops.secrets."wg/home/privateKey".path;
+ listenPort = wgHomePort;
+ dynamicEndpointRefreshSeconds = 45;
+
+ peers = [
+ {
+ allowedIPs = ["192.168.88.0/24" "192.168.80.0/24"];
+ presharedKeyFile = config.sops.secrets."wg/home/chrono/PSK".path;
+ publicKey = "rP5lJY6ea7BKX40edzqNMJbhfLkSlSwG1FipEufeflk=";
+ # endpoint = "45.138.54.155:16556";
+ endpoint = "wilkuu.duckdns.org:16556";
+ name = "wg-home-chronosphere";
+
+ }
+ ];
+ };
+ };
+ };
+ systemd.network.networks."40-wg-home".dns = ["192.168.88.1"];
+ systemd.network.enable = true;
+ systemd.network.networks."10-uplink" = {
+ matchConfig.Name = "ens18";
+ # TODO: Cloudinit
+ address = ["45.136.141.133/26" "2a12:bec0:650:128::133/64"];
+ gateway = ["45.136.141.129" "2a12:bec0:650:128::"];
+ dns = ["1.1.1.1" "2606:4700:4700:0000:0000:0000:0000:1002"];
+ linkConfig.RequiredForOnline="yes";
+ };
+ systemd.network.networks."99-fallback" = {
+ matchConfig.Type = "ether";
+ networkConfig.DHCP = "ipv4";
+ linkConfig.RequiredForOnline="routable";
+ };
+
+ networking.useDHCP = false;
+ networking.useNetworkd = true;
+ networking.nftables.enable = true;
+ networking.firewall = {
+ enable = true;
+ checkReversePath = false;
+ allowedTCPPorts = baseTCP;
+ allowedUDPPorts = baseUDP;
+ allowedUDPPortRanges = baseUDPRanges;
+ allowedTCPPortRanges = baseTCPRanges;
+ interfaces = {
+ "wg-home" = {
+ allowedTCPPorts = secureTCP;
+ allowedUDPPorts = secureUDP;
+ allowedUDPPortRanges = secureUDPRanges;
+ allowedTCPPortRanges = secureTCPRanges;
+ };
+ };
+ trustedInterfaces = [
+ "docker0"
+ "br-*"
+ "veth*"
+ "vnet*"
+ "virbr*"
+ "lo"
+ ];
+
+ };
+}
diff --git a/hosts/omega-relay/hardware-configuration.nix b/hosts/omega-relay/hardware-configuration.nix
new file mode 100644
index 0000000..aaf9d00
--- /dev/null
+++ b/hosts/omega-relay/hardware-configuration.nix
@@ -0,0 +1,24 @@
+# Do not modify this file! It was generated by ‘nixos-generate-config’
+# and may be overwritten by future invocations. Please make changes
+# to /etc/nixos/configuration.nix instead.
+{ config, lib, pkgs, modulesPath, ... }:
+
+{
+ imports =
+ [ (modulesPath + "/profiles/qemu-guest.nix")
+ ];
+
+ boot.initrd.availableKernelModules = [ "uhci_hcd" "ehci_pci" "ahci" "virtio_pci" "virtio_scsi" "sd_mod" "sr_mod" ];
+ boot.initrd.kernelModules = [ ];
+ boot.kernelModules = [ "kvm-intel" ];
+ boot.extraModulePackages = [ ];
+
+ # Enables DHCP on each ethernet and wireless interface. In case of scripted networking
+ # (the default) this is the recommended approach. When using systemd-networkd it's
+ # still possible to use this option, but it's recommended to use it in conjunction
+ # with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
+ networking.useDHCP = lib.mkDefault true;
+ # networking.interfaces.ens18.useDHCP = lib.mkDefault true;
+
+ nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
+}
diff --git a/hosts/omega-relay/vm.nix b/hosts/omega-relay/vm.nix
new file mode 100644
index 0000000..6672949
--- /dev/null
+++ b/hosts/omega-relay/vm.nix
@@ -0,0 +1,43 @@
+{ ... }:
+let
+ forward = proto: gport: hport: {
+ from = "host";
+ proto = proto;
+ host = {
+ port = hport;
+ # address = "10.0.69.1";
+ };
+ guest = {
+ port = gport;
+ # address = "10.0.69.2";
+ };
+ };
+in
+{
+ # TODO: Make this into a more global module.
+ virtualisation.vmVariant = {
+ addons.virtualisation.isTestVM = true;
+ addons.virtualisation.guest = true;
+ fileSystems."/" = {
+ device = "none";
+ fsType = "tmpfs";
+ options = [
+ "defaults"
+ "size=2G"
+ "mode=755"
+ ];
+ };
+ virtualisation = {
+ forwardPorts = [
+ (forward "tcp" 80 9080)
+ (forward "tcp" 443 9443)
+ (forward "tcp" 143 9143)
+ (forward "tcp" 25 9025)
+ (forward "tcp" 22 9022)
+ ];
+ memorySize = 2048; # Use 2048MiB memory.
+ cores = 3;
+ graphics = false;
+ };
+ };
+}
diff --git a/hosts/test_vm/default.nix b/hosts/test_vm/default.nix
index 6dd2fc1..14ca75b 100644
--- a/hosts/test_vm/default.nix
+++ b/hosts/test_vm/default.nix
@@ -5,7 +5,7 @@
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
- networking.hostName = "cookie_vm"; # Define your hostname.
+ networking.hostName = "omega-relay"; # Define your hostname.
networking.networkmanager.enable = true;
programs.nix-ld.enable = true;
diff --git a/modules/default.nix b/modules/default.nix
index f18f380..3c1dc71 100644
--- a/modules/default.nix
+++ b/modules/default.nix
@@ -37,7 +37,7 @@
time.timeZone = "Europe/Amsterdam"; # Set timezone
sops.defaultSopsFile = ./secrets/secrets.yaml;
- sops.age.sshKeyPaths = [ "/etc/ssh_host_ed25519_key" ];
+ sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
sops.age.keyFile = "/var/lib/sops-nix/key.txt";
sops.age.generateKey = true;
diff --git a/modules/virt.nix b/modules/virt.nix
index 53bd70a..01547b4 100644
--- a/modules/virt.nix
+++ b/modules/virt.nix
@@ -11,6 +11,7 @@ in
options.addons.virtualisation = {
host = lib.mkEnableOption "Allow to host vm's and containers";
guest = lib.mkEnableOption "Enable guest agents";
+ isTestVM = lib.mkEnableOption "Enabled if the system is a test VM";
};
config = lib.mkMerge ([
@@ -34,6 +35,7 @@ in
})
(lib.mkIf cfg.guest {
services.spice-vdagentd.enable = true;
+ services.qemuGuest.enable = true;
})
]);
}
diff --git a/secrets/omega-relay/freshrss.yaml b/secrets/omega-relay/freshrss.yaml
new file mode 100644
index 0000000..9c757fd
--- /dev/null
+++ b/secrets/omega-relay/freshrss.yaml
@@ -0,0 +1,45 @@
+fresh-rss:
+ admin_password: ENC[AES256_GCM,data:ujxub03hX4cIm+U5BnHqdOBkMi4HAMGg,iv:OOHnWL4ya9dJGz78SByO3iRrXZRi6ZQ3BNh23Xga/5M=,tag:ldh7LGkDlAoC/f0C2KmdZg==,type:str]
+ db_pass: ENC[AES256_GCM,data:P0EkUXci1LzZLqd10YCHxAdrPI5Qm5Sg,iv:NaMZ1Abj/gf3C0wUB25SjokI8i23IlZlA2NJevD/Rgs=,tag:kb/cE1PMAddg2+7HxQQVvw==,type:str]
+sops:
+ age:
+ - recipient: age1hsxrd9shau86k7zz9wfdeplldyg5c2al6umnr7rn6tf7ewus64uswufr0a
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxVUxvcWQ5T2lKcFNEOWdk
+ WHI2UlVrM3pGMDVUNlVzTDBvR1dKd0xPbzNnCkt4Rjh1T2tVQzcrMjFVaWpUVkpQ
+ VHdUSElYSlMyNy9EN1dLQVJwdkptcW8KLS0tIG9nSS9LaXI4RGJVRlZZZ3pjSFkr
+ dTF0TWFLcTkxamxpdkJhR2xCOE9PODQK+yTP8Nk0kuhx/kRoQttRadrQEblGhzQn
+ wWpV/fi6N8PFHLTRHr9b/7tjs3HEQjOHdhHR7Te00d7xus51W3sS7Q==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age1n20lpr5x2aep3l3ta62x2c9cnuz3m495f2dmguqs08ezlqgu4vwsqfskyg
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqMzlrc0d5SkYyR2pMRkRp
+ MEF4a2JVSVRTMDVBWlNvL3I2ZDIwMW9pMWdNCjl2RTR4RlU3UXJPOXRaMFVlZmJN
+ UVdVelJtemhYLzg3QWJZeUlLeUVHQ3cKLS0tIDdxU3M3SlczelU1cGt5blppUWN6
+ SDZIQTgwMnI1bnpEakQ2SjlNTTRkZzAKuQcMWPH0qM/Pprhcvfep7cG2VuU+SLvv
+ ENd5GdKX6rYmkaoIGLKTzIdnchhW6pT/24ShG/KXdRZTE1T+i859jw==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age13x9grwfpqjgvjfcnwg5snuntp5emze85hqc8qwuz9nfphfe2pg4skl29r4
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA0YzFSRndkL2NvRVpGT25S
+ N1NzZEc3WVJrT1J0VjUxVURTb3B6dkNyS0VrCk44ZTNRV2xMNUdXWEFPR2gwU0Nt
+ R0tEbDZmMWUrMUtKMCtzeDg5d0sxajQKLS0tIDh0ZUZjZ0xPODdVMHFTckxFRElI
+ SEFzQ05Cd3ZMamY5TldXb2xzdFlyOGcKleeerfbPxt9TXWgV+4ENNGWmXjypbbah
+ U9sN/MJA5G7QCOdGqEVHdu/LTubrfAvSkkGF8qacfntEa3wADtyNYw==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age18u22lycxtcasvlm298qwzwuc97z56kkhw8ssy9yx4gzlkskuwpyqdz80g4
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBYkdDU3NRYVpRdWwyZitM
+ cjRvUHpqZmVYQ3NId2JxTTNvZ250b0Zyc0hZCkFJNHhEVmVOVC9PWjlkdHBZUHYx
+ OXltSGZwRkE5MEZiaEtzOERpcFhQMlEKLS0tIHpoaEIvaG1JcVJTd3hycUZNMlhZ
+ T0pHQTRBa2hzTGQzcXhRb3BHMGRzeEEK3xM2j44QtavaQ33zykfY4dlACS7lOXlS
+ XNwK9MMBhfbnN8ahZPBJiND1sm4iWcrnjWlOajVegppsA+Y0yAJAjw==
+ -----END AGE ENCRYPTED FILE-----
+ lastmodified: "2026-02-01T18:41:41Z"
+ mac: ENC[AES256_GCM,data:75PktshY0baUFCx1eshC7bObCAbo+QvvepN4Ig6JYUr0qWM5PIa2TUfAqbh4MF1kbxysQ43sn66sxvkoyooUdA/Asg7vFdEq/NF7SCpkt/OUaFP5JWSl3i4eLU2Li00bqEkrjN0D+OdxvA8JJXXYZXZ1WA0RewEcDeG/duA3Gto=,iv:mcV3jCIVTatWNGoScAmirbR3dmGwHgH+W9SZwdWD8NM=,tag:az1Tg5/2dgPVtfbBx2rEeQ==,type:str]
+ unencrypted_suffix: _unencrypted
+ version: 3.11.0
diff --git a/secrets/omega-relay/stalwart.yaml b/secrets/omega-relay/stalwart.yaml
new file mode 100644
index 0000000..64d9286
--- /dev/null
+++ b/secrets/omega-relay/stalwart.yaml
@@ -0,0 +1,44 @@
+stalwart:
+ user_admin_password: ENC[AES256_GCM,data:oHKLJRLYCbVO7AQuzqwOd40jTV5Y7M76do9EduXpbas=,iv:u+jwIZL8c603XlbuANNYjXTY1vKan0xO3eWTiW6NlQo=,tag:C81dfQOuqtqnXPxJv5QuHw==,type:str]
+sops:
+ age:
+ - recipient: age1hsxrd9shau86k7zz9wfdeplldyg5c2al6umnr7rn6tf7ewus64uswufr0a
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBZMFJ3ZTZFMzFTSThPTTc5
+ R3hlcXN0d0FKZ0d1Y0F0dkNWaThEcnVsVGt3CmxkcTNXa1hEV0NaUFBQYkZFVWRL
+ T1JMWDMvWTE2RitJZUlHRkpNTXVMRDgKLS0tIHoxd2hmZUx5OGVKMjRyUUt5eWZo
+ WE9tcCsxQThMN3J2SW9iZi9vM1h3NncKDIBFEkix0DG0TpsoAKNmT9y1cPf8QGUY
+ l0DhwfbUy081Qd6EvW3c8WaL4uKiN45PtV5swUl7wZUkExSt8x57yA==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age1n20lpr5x2aep3l3ta62x2c9cnuz3m495f2dmguqs08ezlqgu4vwsqfskyg
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXaWE1bGcvMkhxaVRZa1Jz
+ RTlxR3Joa2xLRjBwVGc4NXdTUXNoZFc5alRnClc3U0wzRlNhWjhUWGJybW1ieHB5
+ NnRRSlQ2WkYwbysyOWNsZzRLcVFEVXcKLS0tIDh1ektNWllFSVBJVzZIVVhBNEUy
+ MXdIdFEvdm1qQXp3aERVVk9BR3J0ekUK0MigpfH9/0kazAnUpCr1ubzSaKBNU+k9
+ bxiK9cEIH8+bhKe5QujimM4/sEtNzTbXo2KzO6s5ez3ba7/VcT6SxA==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age13x9grwfpqjgvjfcnwg5snuntp5emze85hqc8qwuz9nfphfe2pg4skl29r4
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlaC9vS2U2UzZjUmVaeHBz
+ U2lKOHRIN1FUN3VwOTRBSVZjZDVQT0xWb1dzCnlPSmZQb0JuYkFRWWxMQzM2bnp6
+ Q2ZnNDVMRDBtMkR2YmRic3V1N21OQVUKLS0tICs0a3dhSXYyZGNFMi9NdXlVaktK
+ bnlTdksxRjk3ZlhvODZpZjE5RVRHL2sKSjydmq8Yhzn2Ze9/UJBONcv5qHjsEDoP
+ /ERd6jQR9Hi8B6v8fUF5W56VeFcciJhj4Paxt7cpH0xlSAz0XAC8zQ==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age18u22lycxtcasvlm298qwzwuc97z56kkhw8ssy9yx4gzlkskuwpyqdz80g4
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2U2VhSnl4aDN4bmk1elE3
+ NlNjL3d5SG0rNUZDcVZNSmVTMTJTNkRsN1FJCmpjald4YWtGejR2dGI2U3ZNdUtE
+ Rk1PRi9uRFpnUlVrMFpzU0IxNTRicTAKLS0tIG1KNFlJeWtZbjU0a2lsS1NRV3RQ
+ aVVRTjZSUGdsa2lPWmQ1Yk9yYXFrcmcKq3rFIP2fGpqsFujP27bgUhEfbg67ULv8
+ EbaohOYOQJiCeQfRdT7IwWIjTVcBhyU4wDw5Ss9HFk8faQn2wrQdOg==
+ -----END AGE ENCRYPTED FILE-----
+ lastmodified: "2026-01-17T21:45:45Z"
+ mac: ENC[AES256_GCM,data:ZN8Zmo6yvhuyJKrnAw4btIf6FxEWiQuCCBpWedYGj0S973YRgEbl7Q9HKsYrVOwNwGIMS5MBv+hjjvOMZvJU0331V7PefRy4yzqN10pJLgLwyB63ZrhOdY87q9U8Gz3K1qOoPJievJmyxBwUvbdwO7JWoeiNVxsC+YwGZiJ19yg=,iv:OillC3jS5bILDrZahmsN/sztSlFqrr2BpqzUYjdd7vU=,tag:28az0UH1hVcEq9532yY8nw==,type:str]
+ unencrypted_suffix: _unencrypted
+ version: 3.11.0
diff --git a/secrets/omega-relay/vaultwarden.yaml b/secrets/omega-relay/vaultwarden.yaml
new file mode 100644
index 0000000..96f4841
--- /dev/null
+++ b/secrets/omega-relay/vaultwarden.yaml
@@ -0,0 +1,45 @@
+vaultwarden:
+ admin_token: ENC[AES256_GCM,data:d37MTTlBAelmO1ZAv9Qg5DlCUVF1YkqzvkCAq4/CPObvyIi7Km7u1zJGb8lCZx8p9qJRGaJQz6CRhusIH4iGWvg317j9WtO2kUYHhrduXkk9/BIDoW/BaN+9FmxEPSmH7Xpyoss/HnGNNce03KCUjqs7ZA81rXfPa6suVn4HV4+GnoiZJBs=,iv:gQncevzr8VBTLaA9Zd2zWH8xKYzuy8kR04xpwFwYNdM=,tag:H4MQfWrOQGkbY2Ghpd0/XA==,type:str]
+ admin_pass: ENC[AES256_GCM,data:/Acr0LuuWBzMx4Vcz/lV/5HUgNqxyAbhxVpvBFyo,iv:kANWTVPsPo+1VFxSsPqH9sCaH2lFJ5p9X15j12jZ5iU=,tag:4zsUNvFDADvFmW9DmQ/9cw==,type:str]
+sops:
+ age:
+ - recipient: age1hsxrd9shau86k7zz9wfdeplldyg5c2al6umnr7rn6tf7ewus64uswufr0a
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4RU5QRWJmbVRIY1MyODVW
+ MGdCRHVweUU5c0dJdEE5dEo0V2xhM2g1dG5nClpqRjQ0V1N6RXhaUlNyMTlrL3dX
+ c2JOWWxyN1VsOVFrc1JOSUtRbGVPdnMKLS0tIHc3ZGNQTSt0L1FjNlRuWE9MY2dY
+ a3pRRHpNZFladC9hTVk1OUFRL0UvQ0kKO33IpQ+8J9CQ1UGLzVTXXETKflB/68Jf
+ +ouT3ORbnnviO6lI088VQ9Vb29ymFAHPhsBGCe1epsSoEV/fc317dQ==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age1n20lpr5x2aep3l3ta62x2c9cnuz3m495f2dmguqs08ezlqgu4vwsqfskyg
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqekFwWDFKNG83bFBtU2FD
+ QVlUVTVBcHErbGhyYjVOekkwcTRhb3o1bkhrCkFUSjd5bWJ3eVN4RlRnY1NtZVlO
+ MzRIN1pxa3pST21LZHNEWGZRRndVZ0EKLS0tICs5bHMyVmcyOG12VDlWMFdHcFBM
+ ZFZsdkhRM2VQMWZab2dQakYzVzM1T28Kt3WOAaEZoOHJq99TbXfJzogtcqfOJ9hf
+ t4scV+Fi7PKagOd2aSxJeUds7W1lnUMVhDXyWbaWZpUaYwozLvYfLA==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age13x9grwfpqjgvjfcnwg5snuntp5emze85hqc8qwuz9nfphfe2pg4skl29r4
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkazZoa0w2aUF1MG9EMnda
+ eG1MMVprcFVxN3RuQlNWTUNJSUMvaDcvYW1jCjJuSTcxUXVvN1hkZDhzMFFvWlor
+ bjRCY2hxZkdDRTZUZnJSRjhPK2pKQTgKLS0tIEl2TXB3TjVvV2tDWU5jbERnYkNn
+ VWhKNXhhSE5MMm43aWVtYnhxUWZvQjQK2MZq9ERlfDUyeWVCWHteFnkQcFsckUAZ
+ UzQ7MZv01r9s+LCCaPjOMbBW93zKqv3UzSMiVlNjU4OSu1E+WBNkSg==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age18u22lycxtcasvlm298qwzwuc97z56kkhw8ssy9yx4gzlkskuwpyqdz80g4
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWY1pHV3hGL0tzVExwcGdt
+ SUlmNWpqR010NXAyMnFRK2gySjFnUTRVY3dNClUveUpjdlNXWXZueEJDWnFYOGp3
+ b08zM2J1TGxNV0xXU25vRXNLbGgwOUEKLS0tIForWEhaUSt0aEcrSUNOaVhMTDhW
+ ZjhLY2NEK1pnMUtVaXNqWTVPQ083TkEKXsPEdc8ofY17oSU1JwlCE48u3JwWen9q
+ pN/2LN1kGGEupKoBYtDnwHsGWOtopgW5CG3QT6JRGukvXFeK/YxPwQ==
+ -----END AGE ENCRYPTED FILE-----
+ lastmodified: "2026-01-24T19:54:55Z"
+ mac: ENC[AES256_GCM,data:7xNKZSR9CD0U7LhQ0ziHhgafNcvwZdWx+bQAffEVr+zk/1uC4LZn8vpab9Mwkma4ycW0w++LZZxNWx4lDJTLSl/+bGYb13pBGKiai5+4Bi7JIt5z9UAjLasPKTNCZXvXKv4Y2QLGT+Jqqkaa+e92RG3WSdnLwfZpoGUu89v/ifo=,iv:cwYU8650Ro437NpamndB6yMGUsGFxmtmWlwPwyC4VKE=,tag:qJlnztMaE6DhZ2WBQpCzLw==,type:str]
+ unencrypted_suffix: _unencrypted
+ version: 3.11.0
diff --git a/secrets/omega-relay/wakapi.yaml b/secrets/omega-relay/wakapi.yaml
new file mode 100644
index 0000000..c0c6174
--- /dev/null
+++ b/secrets/omega-relay/wakapi.yaml
@@ -0,0 +1,44 @@
+wakapi:
+ password_salt: ENC[AES256_GCM,data:u8gNo915MwX9nWxJHsxI1xx+S7384EahefW5SrdqJVQ=,iv:1SCDw0CwgTIPEICmHwWlrzsguDmlBWSw7yWhw5aguJw=,tag:LvJwUGpNVHaj1EWx8XFXbQ==,type:str]
+sops:
+ age:
+ - recipient: age1hsxrd9shau86k7zz9wfdeplldyg5c2al6umnr7rn6tf7ewus64uswufr0a
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBTOUNpb2ZYREV0S01EbTdn
+ Qk9vcDhVMDNuaE5CK3dIa3VNQmVoUlAvK1Y4CnV1azVXNG5wbmZmRUd1NDlzUTZE
+ Zk93UVNTOWNrZ3ZOSjEzUnQxYXJDZVEKLS0tIFpYUFpDV1R4V3VqTDVEU1VSUTJ6
+ REtYVy8wamtrT3kyM2pJSm5DN1BPb2sKevfns0uEHInZfXCFUGZ4oZ5GEEwNJXSw
+ M78GxitL0clIBWO3F4OZsdnZArW4vM8bNaIBusiD1m9/n9trRFIyEA==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age1n20lpr5x2aep3l3ta62x2c9cnuz3m495f2dmguqs08ezlqgu4vwsqfskyg
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBDcVN2SVVFdEQ3WVIrcHlO
+ UXMrWTBoVDZMend2bW5Mdm1UTm1LM25iWURRCitCTU1wcnVsUkNuZ09yR2phaVRj
+ aTRQTnA3ZTZrMmlpRVhZMk5FL211REUKLS0tIEZnVE5TRzBrOTRKQm5VSkpJRmZy
+ dUFqczdMdlVITVhncVVEZHU3bHp6dXMKVq5oQVEOQOPwIq9cfVS0QalV8lR4UbOF
+ jDMpHeJfA4wTOr/67SagAORPGHQBBplsvLRh4nhhFVci8yhxgSN4XA==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age13x9grwfpqjgvjfcnwg5snuntp5emze85hqc8qwuz9nfphfe2pg4skl29r4
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBuRnhQbElYcVZnQTk4Wml2
+ eVNwYjFWNFNPZ3dXK1hEWGVoVlNCVysycVNBClJ4bzIvbFdxSVRVNXdPYjNrZndF
+ MG5SWVRhemVFZXowNnhWRGFDOGw5MUEKLS0tIGpQQXRVVVFZNVE3bncxcW5mR3NS
+ eENEMnJvWmJ4OUdNdGtVZ3pHbXViYlUKIcYc91zT5x6QxndMCbpZtCl+P4h7neBq
+ PqAlzke7BJd1+bDV3mTnmojQzxp0l4/Lv2wVLiinexOcmMBn8oLm4g==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age18u22lycxtcasvlm298qwzwuc97z56kkhw8ssy9yx4gzlkskuwpyqdz80g4
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxTkFESlZKRWNKMDg0TklC
+ M1h3OENFUlFGOU9MRllHdXBzZjk2Y0RZSTJNCjFXcGtMRnFIcU9uOGhsSXoxVDl2
+ cTRNRFYvUzJUOWVPbWYzOEE4SHNlb0EKLS0tIFF4TGEvb1ZZeUdWV215bk80YzJR
+ TlI2QlJScjZ1aFdBQjFmQlJibEdOZ00K6MxXrgbF+D7LHLteD62Cdo+czJvXfQHW
+ frcqt29Qx/rMjOWJ29XozJHMWqVvH2UKnAYcCjF71FPC5INl1kH85A==
+ -----END AGE ENCRYPTED FILE-----
+ lastmodified: "2026-01-25T12:52:57Z"
+ mac: ENC[AES256_GCM,data:tkmq5bwnqmucoRJuD867q4TL/GWPjDvkQO4LUIsVwXtIj+CUmrh3CS9rAMMS+dcMGuG9e9H3hJX3LKWNWIdHTuA6GqIAU94LmmKI57gm1EPmaakJWB9P9gIP/N1IVQS3fc451RSU1cd94Dy1rApTjsspzpBxeed24KqoY67/76E=,iv:cfQqv2s2bSiB7+T/9OZcaA7N05LqvWIBlMr6NfLoTWE=,tag:4/o3V1CS7urudjqUjN5FkQ==,type:str]
+ unencrypted_suffix: _unencrypted
+ version: 3.11.0
diff --git a/secrets/omega-relay/wireguard.yaml b/secrets/omega-relay/wireguard.yaml
new file mode 100644
index 0000000..95f27da
--- /dev/null
+++ b/secrets/omega-relay/wireguard.yaml
@@ -0,0 +1,48 @@
+home:
+ privateKey: ENC[AES256_GCM,data:PwNzM+UHWum6JBGelD8TtabrqQMaWHOsmF7kRMbkuAsuJiwEweXcorIBJ78=,iv:PxDWTtK7UcjIQgVpccBKi6lCDP5oSqYIox8mKSt0J/8=,tag:+9nVhwL2ofYvf70slwM9ag==,type:str]
+ chrono:
+ PSK: ENC[AES256_GCM,data:G0+qwm6avgdynHrYWUn5VFXEXjc0R46ABaWzCLmLx9FmkrHaMnha+A5fWaA=,iv:VL3fQJ+WTTcnAdT47ONdKVSRv+0tEGDT3FabK1krEbo=,tag:1w5rKM+h/xxlyU0IZdpBLg==,type:str]
+ PK: ENC[AES256_GCM,data:ilTlT/GhuKF/0nb0XPnP/V79djqIoGsue8t1N8u8olW2nlTCZQGSgjF0B+U=,iv:N8yIjZ1QYC0AmXa8NgbsXJpd6aULmDRGoL4FoB+UXrg=,tag:gLJYV/aktHt1AHmWovUdRg==,type:str]
+ endpoint: ENC[AES256_GCM,data:XqCJCDb0G4J71T/JV3ZAIZEN,iv:T9LCW4Ep+sFmQEYVpIO46NR26vdAoLl+TDYEkdK+TpM=,tag:RVR/G4uVQ0F6j4ofjx2HSg==,type:str]
+sops:
+ age:
+ - recipient: age1hsxrd9shau86k7zz9wfdeplldyg5c2al6umnr7rn6tf7ewus64uswufr0a
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBUUFBGcFBaRFZkMktJckc5
+ ZjgxQ3huc3F6ZDlSVjlySFliRDN2WmxtVUFZCkszTkYwcE45TUlUb2UrRFNpS1Rs
+ bUU3SHNJbG4ycnpIcnBzL0VYdVVEb0kKLS0tIDlIblpWbVF1alZ4RDNXcFhQWlBG
+ YlBFbWtaYnh5dlRoY3AzbTlSNnp3czgK6CV8Kccid3ZDRBaFYN9zu6b+2v5DYkVE
+ gd1Gug9snU38FAHyTUFYbuqOa8KhqAjQjMvHf7RXT441yXYgun75Rw==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age1n20lpr5x2aep3l3ta62x2c9cnuz3m495f2dmguqs08ezlqgu4vwsqfskyg
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWaFZBUTBtRWpud3BxSVFz
+ N0lvM3ZCcUhlQnhjZVh5RXlFKzJSOEVrUzJnCm5IOW5yWnFwSTJzVEJWcW9aMWht
+ SngwQzFMdSs0Rzd6QWdpY3F3QmxtUUUKLS0tIG5Nc3NUaU9NUnE2R2diNDFOSGZC
+ QzVLQkxha1gxQnJMVnZCRWowWENQYXcKwZlrSmiz12d6OD79LF8ydzqDmfJBi3or
+ RehJPP8Su92z4ApiC4CoThxu7jh5aeJ9RG4FHaYlGueOek5y7nxGuA==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age13x9grwfpqjgvjfcnwg5snuntp5emze85hqc8qwuz9nfphfe2pg4skl29r4
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQeDZjbmxibUMwUURTcVhF
+ YkFvNm9Uc1JvTWpVaEFjc0Z2SHlENnZmREQwCjN5S2NsYmpGbVpDY3BLdnB5YjZI
+ M2FyVFZVQ1hmb1dBdmtxa0wwaER6SFUKLS0tIDNNbmlPUDkwaFhnNTgvemRwUHBT
+ K0pkT21kMk1OUU40RlQvbllwMGgxbkUKRDCRGs2yHZR6uE+B3kHtxHX99scWY4PV
+ fM0bnhngVts9akxMyhThpsl+5R9O7e0EbQ5xQMIfcFsgiaBCLoxwkg==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age18u22lycxtcasvlm298qwzwuc97z56kkhw8ssy9yx4gzlkskuwpyqdz80g4
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvRENMcVlGaVNaaFZvcEls
+ YlFUVHloS0gyVkpxclptM0VhcVF5dWR1SUZNCjlYc3FUMjlRQkR1M1R3eHpqdWQz
+ NmhJYzI0WVBPKzJ1MEEzLzRBMXFtTmcKLS0tIDQ2MDN0MHAya2hzc3hxdHVPSlVN
+ OWI1UW1kSGVnSGY1VVNwUHZvQk1OcVEKPON0phRrXYGalHpow1WqIfbZVSl8huvq
+ J96723TLUED+Nk9wrXY+q8XzjyI036MMDt6fAYiAZgparb+hNXGyUg==
+ -----END AGE ENCRYPTED FILE-----
+ lastmodified: "2026-02-04T17:22:48Z"
+ mac: ENC[AES256_GCM,data:G7fBQ96Odd3Lp1SRJWOWGaNU2zUdTRe3d0+RkS5/+QubUYLwVdJPSpqpwxQe+O/K+V5qnJJw/AAFdw8qH3OtCDfm6uOARkREWHFPG9msxP56m118ISgMDZMxnij1UBpuU/z2y5UVt4usxNSv+z82Mg3trAesWYFgPMMmrK/xJSA=,iv:/a3bWf97Qc6VGx5WMIRx2lZUW+eKgfYBSGoaU+Hrbi8=,tag:P84BGXpHoJWZR1aIncYeHA==,type:str]
+ unencrypted_suffix: _unencrypted
+ version: 3.11.0
diff --git a/services/email.nix b/services/email.nix
new file mode 100644
index 0000000..906b44d
--- /dev/null
+++ b/services/email.nix
@@ -0,0 +1,174 @@
+{ config, lib, ... }:
+let
+ cfg = config.wilkuu.services.stalwart;
+ hostname = config.networking.hostName;
+in
+{
+ options.wilkuu.services.stalwart = with lib; {
+ domain = mkOption {
+ type = types.str;
+ default = "mail.${hostname}.local";
+ example = "mail.wilkuu.xyz";
+ description = "Domain for http connections.";
+ };
+ wellKnownDomains = mkOption {
+ type = types.listOf types.str;
+ default = [ "${hostname}.local" ];
+ example = [ "wilkuu.xyz" ];
+ description = "Domain for well-known items";
+ };
+ doACME = mkEnableOption "Enable ACME for stalwart here";
+ enable = mkEnableOption "Enable the email service";
+ dataDir = mkOption {
+ type = types.path;
+ description = "Storage localtion for Stalwart user data";
+ default = "/srv/data/stalwart";
+ example = "/srv/data/stalwart";
+ };
+ };
+
+ config = lib.mkIf cfg.enable (
+ let
+ sopsPath = ../secrets/${hostname}/stalwart.yaml;
+ secrets = [ "user_admin_password" ];
+ toSops = (sname: "stalwart/${sname}");
+ toCredfilePath = (name: config.sops.secrets.${toSops name}.path);
+ toStalwartCred = name: "%{file:/run/credentials/${config.systemd.services.stalwart.name}/${name}}%";
+
+ basicListener = proto: port: tls: {
+ bind = [ "[::]:${toString port}" ];
+ protocol = proto;
+ tls.implicit = tls;
+ };
+
+ proxyWellKnown =
+ names:
+ let
+ uris = map (n: "/.well-known/${n}") names;
+ in
+ (lib.genAttrs uris (uri: {
+ proxyPass = "http://localhost:3080${uri}";
+ recommendedProxySettings = true;
+ }));
+
+ makeHttpRedirect = target: https: {
+ return = "302 ${if https then "https" else "http"}://${target}";
+ };
+
+ in
+ {
+ networking.hosts = {
+ "127.0.0.1" = [ cfg.domain ];
+ };
+
+ # Need this bc otherwise sops will complain for some reason
+ users = {
+ groups.stalwart = { };
+ users.stalwart = {
+ isSystemUser = true;
+ group = "stalwart";
+ };
+ };
+
+ # TODO: Move this into a util function or option;
+ sops.secrets = (
+ lib.genAttrs (map toSops secrets) (_name: {
+ sopsFile = sopsPath;
+ mode = "0440";
+ owner = "stalwart-mail";
+ })
+ );
+
+ services.nginx.virtualHosts =
+ (lib.genAttrs cfg.wellKnownDomains (
+ (_wdomain: {
+ locations =
+ (proxyWellKnown [
+ "jmap"
+ "mta-sts.txt"
+ "mail-v1.xml"
+ "autoconfig/mail"
+ ])
+ // (lib.genAttrs [ "/.well_known/caldav" "/.well_known/webdav" ] (
+ uri: (makeHttpRedirect "${cfg.domain}${uri}") cfg.doACME
+ ));
+ })
+ )) //
+ { ${cfg.domain} = {
+ addSSL = cfg.doACME;
+ enableACME = cfg.doACME;
+ serverName = "${cfg.domain}";
+ locations."/" = {
+ proxyPass = "http://localhost:3080";
+ recommendedProxySettings = true;
+ };
+ };};
+
+ services.stalwart = {
+ enable = true;
+ dataDir = cfg.dataDir;
+ openFirewall = false;
+ credentials = (lib.genAttrs secrets toCredfilePath) // (let
+ acme_dir = config.security.acme.certs.${cfg.domain}.directory;
+ cert_path = file: "${acme_dir}/${file}";
+ in (if cfg.doACME then {
+ "tls_cert.pem" = cert_path "cert.pem";
+ "tls_key.pem" = cert_path "key.pem";
+ } else {}));
+
+ settings = {
+ server.listener = {
+ smtp = basicListener "smtp" 25 false;
+ submission = basicListener "smtp" 465 true;
+ imaptls = basicListener "imap" 993 true;
+ imap = basicListener "imap" 143 true;
+ # webdav = basicListener "http" 3080 false;
+ # jmap = basicListener "http" 3080 false;
+ http = basicListener "http" 3080 false;
+ };
+
+ store.rocksdb = {
+ type = "rocksdb";
+ path = cfg.dataDir;
+ compression = "lz4";
+ };
+
+ directory.internal = {
+ type = "internal";
+ store = "rocksdb";
+ };
+
+ storage = {
+ data = "rocksdb";
+ fts = "rocksdb";
+ blob = "rocksdb";
+ lookup = "rocksdb";
+ directory = "internal";
+ };
+
+ authentication.fallback-admin = {
+ user = "admin";
+ secret = toStalwartCred "user_admin_password";
+ };
+
+ http = {
+ use-x-forwarded = true;
+ url = "protocol + \"://${cfg.domain}\"";
+ };
+
+ session.connect = {
+ hostname = "config_get('server.hostname')";
+ };
+
+ server.hostname = "${cfg.domain}";
+
+ certificate."nix_${cfg.domain}" = lib.mkIf cfg.doACME {
+ cert = toStalwartCred "tls_cert.pem";
+ private-key = toStalwartCred "tls_key.pem";
+ default = true;
+ };
+ };
+ };
+ }
+ );
+}
diff --git a/services/freshrss.nix b/services/freshrss.nix
new file mode 100644
index 0000000..26a1853
--- /dev/null
+++ b/services/freshrss.nix
@@ -0,0 +1,94 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+let
+ cfg = config.wilkuu.services.freshrss;
+ hostname = config.networking.hostName;
+in
+{
+
+ options.wilkuu.services.freshrss = with lib; {
+ domain = mkOption {
+ type = types.str;
+ default = "rss.${hostname}.local";
+ example = "rss.wilkuu.xyz";
+ description = "Domain for http connections.";
+ };
+ doACME = mkEnableOption "Enable ACME for fresh-rss here";
+ enable = mkEnableOption "Enable the fresh-rss service";
+ dataDir = mkOption {
+ type = types.path;
+ description = "Storage localtion for fresh-rss data";
+ default = "/srv/data/freshrss";
+ example = "/srv/data/freshrss";
+ };
+ };
+
+ config = lib.mkIf cfg.enable (
+ let
+ sopsPath = ../secrets/${hostname}/freshrss.yaml;
+ secrets = [
+ "admin_password"
+ "db_pass"
+ ];
+ toSops = (sname: "fresh-rss/${sname}");
+ in
+ {
+ networking.hosts = {
+ "127.0.0.1" = [ cfg.domain ];
+ };
+
+ sops.secrets = (
+ lib.genAttrs (map toSops secrets) (_name: {
+ sopsFile = sopsPath;
+ mode = "0440";
+ owner = config.services.freshrss.user;
+ })
+ );
+
+ services.nginx.virtualHosts."${cfg.domain}" = {
+ addSSL = cfg.doACME;
+ enableACME = cfg.doACME;
+ };
+
+ systemd.services.freshrss.after = [ "mysql.service" ];
+ wilkuu.services.mysql = {
+ enable = true;
+ users."freshrss" = {
+ sopsPlaceholder = config.sops.placeholder."fresh-rss/db_pass";
+ host = "localhost";
+ };
+ databases."freshrss" = {
+ enable = true;
+ allowedUsers = [ "freshrss" ];
+ };
+ };
+
+ services.freshrss = {
+ enable = true;
+ # api.enable = true;
+ dataDir = cfg.dataDir;
+ baseUrl = "https://${cfg.domain}";
+ extensions = with pkgs.freshrss-extensions; [
+ youtube
+ title-wrap
+ auto-ttl
+ reading-time
+ ];
+ passwordFile = config.sops.secrets."fresh-rss/admin_password".path;
+ virtualHost = cfg.domain;
+ database = {
+ passFile = config.sops.secrets."fresh-rss/db_pass".path;
+ host = "127.0.0.1";
+ port = config.wilkuu.services.mysql.port;
+ name = "freshrss";
+ user = "freshrss";
+ type = "mysql";
+ };
+ };
+ }
+ );
+}
diff --git a/services/mysql.nix b/services/mysql.nix
new file mode 100644
index 0000000..06edfcb
--- /dev/null
+++ b/services/mysql.nix
@@ -0,0 +1,139 @@
+{
+ pkgs,
+ config,
+ lib,
+ ...
+}:
+let
+ cfg = config.wilkuu.services.mysql;
+
+ create_users_ensure =
+ uname:
+ (lib.genAttrs (lib.map (dn: "${dn}.*") (
+ lib.attrNames (lib.filterAttrs (_: dcfg: (builtins.elem uname dcfg.allowedUsers)) cfg.databases)
+ )) (_: "ALL PRIVILEGES"));
+
+ priviledge_clause =
+ name: db: priv:
+ ("GRANT ${priv} ON ${db} TO ${name};");
+
+ add-user-clauses =
+ name: ucfg:
+ if (!isNull ucfg.sopsPlaceholder) then
+ (
+ ''
+ -- Clauses for user ${name}
+ ALTER USER IF EXISTS '${name}'@'${ucfg.host}' IDENTIFIED BY '${ucfg.sopsPlaceholder}';
+ CREATE USER IF NOT EXISTS '${name}'@'${ucfg.host}' IDENTIFIED BY '${ucfg.sopsPlaceholder}';
+ ''
+ + (lib.concatMapAttrsStringSep "\n" (priviledge_clause "'${name}'@'${ucfg.host}'") (create_users_ensure name))
+ )
+ else
+ " -- Ommitted user ${name}";
+
+ add-unix-user-clauses =
+ name:
+ ''
+ -- Clauses for user ${name}
+ ALTER USER IF EXISTS '${name}'@'localhost' IDENTIFIED VIA unix_socket;
+ CREATE USER IF NOT EXISTS '${name}'@'localhost' IDENTIFIED VIA unix_socket;
+ ''
+ + (lib.concatMapAttrsStringSep "\n" (priviledge_clause "'${name}'@'localhost'") (
+ create_users_ensure name
+ ));
+
+in
+{
+ options.wilkuu.services.mysql = {
+ enable = lib.mkEnableOption "Enable database for containers";
+ port =
+ with lib;
+ mkOption {
+ type = types.port;
+ default = 3306;
+ };
+ databases =
+ with lib;
+ mkOption {
+ type = types.attrsOf (
+ types.submodule {
+ options = {
+ enable = mkEnableOption "Enable the database";
+ allowedUsers = mkOption {
+ type = types.listOf types.str;
+ };
+ };
+ }
+ );
+ default = { };
+ };
+ users =
+ with lib;
+ mkOption {
+ type = types.attrsOf (
+ types.submodule {
+ options = {
+ scramPassword = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ };
+ sopsPlaceholder = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ };
+ allowedRanges = mkOption {
+ type = types.listOf types.str;
+ };
+ host = mkOption {
+ type = types.str;
+ default = "%";
+ };
+ };
+ }
+ );
+ default = { };
+ };
+ unix_users = lib.mkOption {
+ type = lib.types.listOf lib.types.str;
+ description = "Users that can identify using the unix socket";
+ default = [ ];
+ example = [ "wakapi" ];
+ };
+ };
+ # config.sops.secrets = lib.mkIf cfg.enable {
+ # "database/root_pass" = {
+ # sopsFile = ../secrets/${config.networking.hostName}/secrets.yaml;
+ # };
+ # };
+ config.sops.templates."init-mysql" = lib.mkIf cfg.enable {
+ owner = config.systemd.services.mysql.serviceConfig.User;
+ content = (
+ lib.concatLines (
+ (builtins.attrValues (builtins.mapAttrs add-user-clauses cfg.users))
+ ++ (map add-unix-user-clauses cfg.unix_users)
+ ++ [ "FLUSH PRIVILEGES;" ]
+ )
+ );
+ };
+
+ config.services.mysql = {
+ enable = cfg.enable;
+ ensureDatabases = builtins.attrNames cfg.databases;
+ initialScript = config.sops.templates."init-mysql".path;
+ package = pkgs.mariadb;
+ settings = {
+ mysqld = {
+ # socket="/var/lib/mysql/mysql.sock";
+ log_error = "/var/log/mysql_err.log";
+ log_warnings = 2;
+ };
+ };
+ };
+
+ # config.host-config.utilpkgs = lib.mkIf (cfg.enable) (
+ # with pkgs;
+ # [
+ # mycli
+ # ]
+ # );
+}
diff --git a/services/uptimekuma.nix b/services/uptimekuma.nix
new file mode 100644
index 0000000..720040d
--- /dev/null
+++ b/services/uptimekuma.nix
@@ -0,0 +1,79 @@
+{ config, lib, ... }:
+let
+ cfg = config.wilkuu.services.uptimekuma;
+ hostname = config.networking.hostName;
+in
+{
+ options.wilkuu.services.uptimekuma = with lib; {
+ domain = mkOption {
+ type = types.str;
+ default = "uptime.${hostname}.local";
+ example = "uptime.wilkuu.xyz";
+ description = "Domain for http connections.";
+ };
+ doACME = mkEnableOption "Enable ACME for uptime kuma here";
+ enable = mkEnableOption "Enable the uptime-kuma service";
+ dataDir = mkOption {
+ type = types.path;
+ description = "Storage localtion for uptime kuma data, currently ignored, because nixpkgs sucks";
+ default = "/srv/data/uptimekuma";
+ example = "/srv/data/uptimekuma";
+ };
+ };
+
+ config = lib.mkIf cfg.enable ({
+ networking.hosts = {
+ "127.0.0.1" = [ cfg.domain ];
+ };
+
+ users.users.uptimekuma = {
+ isSystemUser = true;
+ group = "uptimekuma";
+ };
+ users.groups.uptimekuma = { };
+
+ systemd.services.uptime-kuma.serviceConfig.User = "uptimekuma";
+ systemd.services.uptime-kuma.after = [ "mysql.service" ];
+
+ # sops.secrets =
+ # (lib.genAttrs (map toSops secrets)
+ # (name: {
+ # sopsFile = sopsPath;
+ # mode = "0440";
+ # owner = "uptime-kuma";
+ # }));
+
+ services.nginx.virtualHosts."${cfg.domain}" = {
+ addSSL = cfg.doACME;
+ enableACME = cfg.doACME;
+ locations."/" = {
+ proxyPass = "http://localhost:3111";
+ recommendedProxySettings = true;
+ };
+ };
+
+ wilkuu.services.mysql =
+ let
+ user = config.systemd.services.uptime-kuma.serviceConfig.User;
+ in
+ {
+ unix_users = [ user ];
+ databases.uptimekuma = {
+ enable = true;
+ allowedUsers = [ user ];
+ };
+ };
+
+ services.uptime-kuma = {
+ enable = true;
+ settings = {
+ UPTIME_KUMA_PORT = "3111";
+ UPTIME_KUMA_HOST = "127.0.0.1";
+ UPTIME_KUMA_DB_TYPE = "sqlite";
+ #UPTIME_KUMA_DB_SOCKET = "/run/mysqld/mysqld.sock";
+ #UPTIME_KUMA_DB_USERNAME = config.systemd.services.uptime-kuma.serviceConfig.User;
+ #UPTIME_KUMA_DB_NAME = "uptimekuma";
+ };
+ };
+ });
+}
diff --git a/services/vaultwarden.nix b/services/vaultwarden.nix
new file mode 100644
index 0000000..ff3466d
--- /dev/null
+++ b/services/vaultwarden.nix
@@ -0,0 +1,78 @@
+{ config, lib, ... }:
+let
+ cfg = config.wilkuu.services.vaultwarden;
+ hostname = config.networking.hostName;
+in
+{
+ options.wilkuu.services.vaultwarden = with lib; {
+ domain = mkOption {
+ type = types.str;
+ default = "bitwarden.${hostname}.local";
+ example = "bitwarden.wilkuu.xyz";
+ description = "Domain for http connections.";
+ };
+ doACME = mkEnableOption "Enable ACME for vaultwarden here";
+ enable = mkEnableOption "Enable the vaultwarden service";
+ backupDir = mkOption {
+ type = types.path;
+ description = "Storage localtion for Vaultwarden user data backup";
+ default = "/srv/data/vaultwarden";
+ example = "/srv/data/vaultwarden";
+ };
+ signupWhitelist = mkOption {
+ type = types.listOf types.str;
+ default = [ ];
+ example = [ "wilkuu.xyz" ];
+ description = "Domains that can sign up on vaultwarden";
+ };
+ };
+
+ config = lib.mkIf cfg.enable (
+ let
+ sopsPath = ../secrets/${hostname}/vaultwarden.yaml;
+ secrets = [ "admin_token" ];
+ toSops = (sname: "vaultwarden/${sname}");
+ in
+ {
+ networking.hosts = {
+ "127.0.0.1" = [ cfg.domain ];
+ };
+
+ sops.secrets = (
+ lib.genAttrs (map toSops secrets) (_name: {
+ sopsFile = sopsPath;
+ mode = "0440";
+ owner = "vaultwarden";
+ })
+ );
+
+ sops.templates.vaultwardenEnvFile.content = ''
+ ADMIN_TOKEN=${config.sops.placeholder."vaultwarden/admin_token"}
+ '';
+
+ services.nginx.virtualHosts."${cfg.domain}" = {
+ enableACME = cfg.doACME;
+ addSSL = cfg.doACME;
+ locations."/" = {
+ proxyPass = "http://localhost:3222";
+ recommendedProxySettings = true;
+ };
+ };
+
+ services.vaultwarden = {
+ enable = cfg.enable;
+ # backupDir = cfg.backupDir;
+ config = {
+ DOMAIN = "${if cfg.doACME then "https" else "http"}://${cfg.domain}";
+ ROCKET_ADDRESS = "127.0.0.1";
+ ROCKET_PORT = "3222";
+ SIGNUPS_DOMAINS_WHITELIST = (lib.concatStringsSep "," cfg.signupWhitelist);
+ SIGNUPS_ALLOWED = "false";
+ IP_HEADER = "X-Forwarded-For";
+ };
+ environmentFile = config.sops.templates.vaultwardenEnvFile.path;
+ };
+
+ }
+ );
+}
diff --git a/services/wakapi.nix b/services/wakapi.nix
new file mode 100644
index 0000000..a350b6a
--- /dev/null
+++ b/services/wakapi.nix
@@ -0,0 +1,112 @@
+{ config, lib, ... }:
+let
+ cfg = config.wilkuu.services.wakapi;
+ hostname = config.networking.hostName;
+ service_user = config.systemd.services.wakapi.serviceConfig.User;
+in
+{
+ options.wilkuu.services.wakapi = with lib; {
+ domain = mkOption {
+ type = types.str;
+ default = "wakapi.${hostname}.local";
+ example = "wakapi.wilkuu.xyz";
+ description = "Domain for http connections.";
+ };
+ email = mkOption {
+ type = types.str;
+ default = "wakapi@${hostname}.local";
+ example = "noreply@wilkuu.xyz";
+ description = "Mailer address";
+ };
+ doACME = mkEnableOption "Enable ACME for wakapi here";
+ enable = mkEnableOption "Enable the wakapi service";
+ dataDir = mkOption {
+ type = types.path;
+ description = "Storage localtion for wakapi data";
+ default = "/srv/data/wakapi";
+ example = "/srv/data/wakapi";
+ };
+ };
+
+ config = lib.mkIf cfg.enable (
+ let
+ sopsPath = ../secrets/${hostname}/wakapi.yaml;
+ secrets = [ "password_salt" ];
+ toSops = (sname: "wakapi/${sname}");
+ in
+ {
+ networking.hosts = {
+ "127.0.0.1" = [ cfg.domain ];
+ };
+
+ sops.secrets = (
+ lib.genAttrs (map toSops secrets) (_name: {
+ sopsFile = sopsPath;
+ mode = "0440";
+ owner = service_user;
+ })
+ );
+
+ services.nginx.virtualHosts."${cfg.domain}" = {
+ enableACME = cfg.doACME;
+ addSSL = cfg.doACME;
+ locations."/" = {
+ proxyPass = "http://localhost:3111";
+ recommendedProxySettings = true;
+ };
+ };
+
+ wilkuu.services.mysql = {
+ unix_users = [ service_user ];
+ databases.wakapi = {
+ enable = true;
+ allowedUsers = [ service_user ];
+ };
+ };
+
+ systemd.services.wakapi.after = [ "mysql.service" ];
+ services.wakapi = {
+ enable = true;
+ stateDir = cfg.dataDir;
+ passwordSaltFile = config.sops.secrets."wakapi/password_salt".path;
+ settings = {
+ server = {
+ port = 3111;
+ public_url = cfg.domain;
+ };
+ app = {
+ leaderboard_enabled = false;
+ leaderboard_require_auth = true;
+ inactive_days = 7; # time of previous days within a user must have logged in to be considered active
+ # go time format strings to format human-readable dates
+ # for details, check https://pkg.go.dev/time#Time.Format
+ date_format = "Mon, 02 Jan 2006";
+ datetime_format = "Mon, 02 Jan 2006 15:04";
+ };
+ db = {
+ socket = "/run/mysqld/mysqld.sock";
+ name = "wakapi";
+ dialect = "mysql";
+ };
+ security = {
+ insecure_cookies = false;
+ trust_reverse_proxy_ips = "127.0.0.1";
+ };
+ mail = {
+ # FIXME: Add email
+ enabled = false;
+ provider = "smtp";
+ sender = "<Wakapi ${cfg.email}>";
+ smtp = {
+ };
+ };
+ };
+ database = {
+ dialect = "mysql";
+ createLocally = false;
+ };
+
+ };
+ }
+ );
+}
diff --git a/users/user-common.nix b/users/user-common.nix
index b021a12..28bf606 100644
--- a/users/user-common.nix
+++ b/users/user-common.nix
@@ -7,7 +7,7 @@
# Pass host config to HM (Common config)
# TODO: Move this somewhere else.
home-manager = {
- #useUserPackages = true;
+ # useUserPackages = true;
useGlobalPkgs = true;
backupFileExtension = "bak";
diff --git a/users/wilkuu-server.nix b/users/wilkuu-server.nix
new file mode 100644
index 0000000..b982ddf
--- /dev/null
+++ b/users/wilkuu-server.nix
@@ -0,0 +1,53 @@
+{
+ pkgs,
+ lib,
+ ...
+}:
+{
+ imports = [ ./user-common.nix ];
+ programs.zsh.enable = true;
+ users.users.wilkuu = {
+ shell = pkgs.zsh;
+ openssh.authorizedKeys.keyFiles = [ ../certs/wilkuu_rsa.pub ../certs/pi_ed25519.pub];
+ isNormalUser = true;
+ initialPassword = "PleazeChangeThis123";
+ extraGroups = [
+ "wheel"
+ "adbusers"
+ "networkmanager"
+ "input"
+ "docker"
+ "adbusers"
+ "libvirtd"
+ "libvirt"
+ ]; # Enable ‘sudo’ for the user.
+ packages = with pkgs; [
+ home-manager
+ ];
+ };
+
+ home-manager.users.wilkuu = {
+ imports = [ ../home-modules ];
+
+ homeapps.presets = lib.genAttrs [ "base" "utils" "browser" ] (_: {
+ enable = true;
+ });
+ # homeapps.vnc = true;
+
+ # services.wayvnc = {
+ # enable = true;
+ # autoStart = false;
+ # settings = {
+ # # Todo, bind to vpn and LAN explicitly somehow
+ # address = "0.0.0.0";
+ # port = 5900;
+ # };
+ # };
+
+ home.username = "wilkuu";
+ home.homeDirectory = "/home/wilkuu";
+ home.stateVersion = "24.11";
+ programs.home-manager.enable = true;
+ };
+
+}