summaryrefslogtreecommitdiff
path: root/os
diff options
context:
space:
mode:
Diffstat (limited to 'os')
-rw-r--r--os/cez/configuration.nix46
-rw-r--r--os/cez/hardware-configuration.nix34
-rw-r--r--os/cez/modules/getty.nix15
-rw-r--r--os/cez/modules/network.nix15
-rw-r--r--os/cez/modules/sshfs.nix27
-rw-r--r--os/cez/modules/tlp.nix26
-rw-r--r--os/cez/modules/wayland.nix72
-rw-r--r--os/cez/modules/wireguard.nix27
-rw-r--r--os/cez/secrets.yaml32
-rw-r--r--os/common/configuration.nix92
-rw-r--r--os/common/modules/dev.nix29
-rw-r--r--os/common/modules/nix.nix6
-rw-r--r--os/common/modules/pppd.nix277
-rw-r--r--os/common/modules/stalwart-mail.nix163
-rw-r--r--os/common/modules/tmux.nix42
-rw-r--r--os/common/pkgs/stalwart-mail-config.nix43
-rw-r--r--os/dspace/configuration.nix19
-rw-r--r--os/dspace/hardware-configuration.nix32
-rw-r--r--os/dspace/modules/network.nix18
-rw-r--r--os/dspace/modules/www.nix39
-rw-r--r--os/dspace/secrets.yaml32
-rw-r--r--os/fscusat/configuration.nix14
-rw-r--r--os/fscusat/hardware-configuration.nix32
-rw-r--r--os/fscusat/modules/mirror/debian/default.nix22
-rw-r--r--os/fscusat/modules/mirror/debian/ftpsync.nix65
-rw-r--r--os/fscusat/modules/mirror/default.nix11
-rw-r--r--os/fscusat/modules/mirror/www.nix11
-rw-r--r--os/fscusat/modules/network.nix18
-rw-r--r--os/fscusat/modules/www.nix36
-rw-r--r--os/fscusat/pkgs/archvsync/Makefile.patch50
-rw-r--r--os/fscusat/pkgs/archvsync/common.patch26
-rw-r--r--os/fscusat/pkgs/archvsync/default.nix52
-rw-r--r--os/fscusat/secrets.yaml32
-rw-r--r--os/kay/configuration.nix18
-rw-r--r--os/kay/hardware-configuration.nix39
-rw-r--r--os/kay/modules/acme.nix23
-rw-r--r--os/kay/modules/cgit.nix33
-rw-r--r--os/kay/modules/dendrite.nix108
-rw-r--r--os/kay/modules/dns/5.6.e.e.0.7.4.0.1.0.0.2.ip6.arpa.zone14
-rw-r--r--os/kay/modules/dns/ddns.nix44
-rw-r--r--os/kay/modules/dns/default.nix137
-rw-r--r--os/kay/modules/dns/sinanmohd.com.zone46
-rw-r--r--os/kay/modules/hurricane.nix115
-rw-r--r--os/kay/modules/iperf3.nix10
-rw-r--r--os/kay/modules/mail.nix110
-rw-r--r--os/kay/modules/matrix-sliding-sync.nix18
-rw-r--r--os/kay/modules/network.nix82
-rw-r--r--os/kay/modules/router.nix43
-rw-r--r--os/kay/modules/sftp.nix44
-rw-r--r--os/kay/modules/sshfwd.nix29
-rw-r--r--os/kay/modules/wireguard.nix57
-rw-r--r--os/kay/modules/www.nix134
-rw-r--r--os/kay/secrets.yaml47
-rw-r--r--os/lia/configuration.nix14
-rw-r--r--os/lia/hardware-configuration.nix29
-rw-r--r--os/lia/modules/lxc.nix41
-rw-r--r--os/lia/modules/network/default.nix19
-rw-r--r--os/lia/modules/network/router.nix47
-rw-r--r--os/lia/modules/sshfwd.nix53
-rw-r--r--os/lia/modules/users.nix18
-rw-r--r--os/lia/secrets.yaml32
61 files changed, 2859 insertions, 0 deletions
diff --git a/os/cez/configuration.nix b/os/cez/configuration.nix
new file mode 100644
index 0000000..00e755a
--- /dev/null
+++ b/os/cez/configuration.nix
@@ -0,0 +1,46 @@
+{ config, pkgs, ... }:
+
+let
+ user = config.userdata.name;
+in
+{
+ imports = [
+ ../common/configuration.nix
+ ./hardware-configuration.nix
+
+ ./modules/wayland.nix
+ ./modules/sshfs.nix
+ ./modules/wireguard.nix
+ ./modules/network.nix
+ ./modules/tlp.nix
+ ./modules/getty.nix
+ ];
+
+ boot = {
+ consoleLogLevel = 3;
+ kernelPackages = pkgs.linuxPackages_latest;
+ };
+
+ sound = {
+ enable = true;
+ extraConfig = ''
+ defaults.pcm.card 1
+ defaults.ctl.card 1
+ '';
+ };
+
+ services.pipewire = {
+ enable = true;
+ pulse.enable = true;
+ };
+
+ programs.adb.enable = true;
+ users.users.${user} = {
+ extraGroups = [ "adbusers" ];
+ packages = with pkgs; [
+ geoipWithDatabase
+ ffmpeg
+ (pass.withExtensions (exts: [ exts.pass-otp ]))
+ ];
+ };
+}
diff --git a/os/cez/hardware-configuration.nix b/os/cez/hardware-configuration.nix
new file mode 100644
index 0000000..b338df5
--- /dev/null
+++ b/os/cez/hardware-configuration.nix
@@ -0,0 +1,34 @@
+{ modulesPath, pkgs, ... }:
+
+{
+ imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
+
+ boot = {
+ kernelParams = [ "quiet" ];
+ loader.systemd-boot.enable = true;
+
+ plymouth = {
+ enable = true;
+ theme = "lone";
+ themePackages = with pkgs; [ adi1090x-plymouth-themes ];
+ };
+
+ initrd = {
+ systemd.enable = true;
+ kernelModules = [ "amdgpu" ];
+ luks.devices."crypt".device =
+ "/dev/disk/by-uuid/84acd784-caad-41a1-a2e4-39468d01fefd";
+ };
+ };
+
+ fileSystems = {
+ "/boot" = {
+ device = "/dev/disk/by-uuid/E37E-F611";
+ fsType = "vfat";
+ };
+ "/" = {
+ device = "/dev/disk/by-uuid/e063c9ad-b48f-4b6c-b94e-4c21d2238bce";
+ fsType = "ext4";
+ };
+ };
+}
diff --git a/os/cez/modules/getty.nix b/os/cez/modules/getty.nix
new file mode 100644
index 0000000..725eb4b
--- /dev/null
+++ b/os/cez/modules/getty.nix
@@ -0,0 +1,15 @@
+{ config, ... }: let
+ user = config.userdata.name;
+in {
+ systemd.services."getty@".serviceConfig.TTYVTDisallocate = "no";
+
+ services.getty = {
+ loginOptions = "-f ${user}";
+ extraArgs = [
+ "--nonewline"
+ "--skip-login"
+ "--noclear"
+ "--noissue"
+ ];
+ };
+}
diff --git a/os/cez/modules/network.nix b/os/cez/modules/network.nix
new file mode 100644
index 0000000..fb30056
--- /dev/null
+++ b/os/cez/modules/network.nix
@@ -0,0 +1,15 @@
+{ ... }:
+
+{
+ networking = {
+ firewall.enable = false;
+
+ wireless.iwd = {
+ enable = true;
+ settings = {
+ General.EnableNetworkConfiguration = true;
+ Network.NameResolvingService = "resolvconf";
+ };
+ };
+ };
+}
diff --git a/os/cez/modules/sshfs.nix b/os/cez/modules/sshfs.nix
new file mode 100644
index 0000000..2431b96
--- /dev/null
+++ b/os/cez/modules/sshfs.nix
@@ -0,0 +1,27 @@
+{ config, pkgs, ... }:
+
+let
+ domain = config.userdata.domain;
+ user = config.userdata.name;
+ uid = config.users.users.${user}.uid;
+ gid = config.users.groups.users.gid;
+in
+{
+ sops.secrets."misc/sftp" = {};
+ system.fsPackages = with pkgs; [ sshfs ];
+
+ fileSystems."/media/kay" = {
+ device = "sftp@${domain}:";
+ fsType = "sshfs";
+ options = [
+ "allow_other" # for non-root access
+ "uid=${toString uid}"
+ "gid=${toString gid}"
+ "_netdev" # this is a network fs
+ "x-systemd.automount" # mount on demand
+ "reconnect" # handle connection drops
+ "ServerAliveInterval=15" # keep connections alive
+ "IdentityFile=${config.sops.secrets."misc/sftp".path}"
+ ];
+ };
+}
diff --git a/os/cez/modules/tlp.nix b/os/cez/modules/tlp.nix
new file mode 100644
index 0000000..912fd5f
--- /dev/null
+++ b/os/cez/modules/tlp.nix
@@ -0,0 +1,26 @@
+{ ... }: {
+ services.tlp = {
+ enable = true;
+
+ settings = {
+ RADEON_DPM_STATE_ON_AC = "performance";
+ RADEON_DPM_STATE_ON_BAT = "battery";
+
+ NMI_WATCHDOG = 0;
+
+ CPU_SCALING_GOVERNOR_ON_AC = "performance";
+ CPU_SCALING_GOVERNOR_ON_BAT = "powersave";
+
+ DEVICES_TO_ENABLE_ON_AC = "bluetooth";
+ DEVICES_TO_DISABLE_ON_BAT_NOT_IN_USE = "bluetooth";
+
+ CPU_BOOST_ON_AC = 1;
+ CPU_BOOST_ON_BAT = 0;
+ CPU_HWP_DYN_BOOST_ON_AC = 1;
+ CPU_HWP_DYN_BOOST_ON_BAT = 0;
+
+ PLATFORM_PROFILE_ON_AC = "balanced";
+ PLATFORM_PROFILE_ON_BAT = "low-power";
+ };
+ };
+}
diff --git a/os/cez/modules/wayland.nix b/os/cez/modules/wayland.nix
new file mode 100644
index 0000000..1ce04cf
--- /dev/null
+++ b/os/cez/modules/wayland.nix
@@ -0,0 +1,72 @@
+{ config, pkgs, ... }: let
+ user = config.userdata.name;
+in {
+ # pkgs
+ environment.systemPackages = with pkgs; [
+ bemenu
+ sway
+ i3status
+ swaylock
+ swayidle
+ swaybg
+ foot
+ wl-clipboard
+ mako
+ xdg-utils
+ libnotify
+ ];
+
+ users.users.${user} = {
+ extraGroups = [ "seat" ];
+ packages = with pkgs; [
+ zathura
+ mpv
+ imv
+ wtype
+ qemu
+ OVMFFull
+ grim
+ slurp
+ tor-browser-bundle-bin
+ element-desktop-wayland
+ pinentry-bemenu
+ ];
+ };
+
+ # font
+ fonts = {
+ packages = with pkgs; [
+ terminus-nerdfont
+ dm-sans
+ ];
+ enableDefaultPackages = true;
+ fontconfig = {
+ hinting.style = "full";
+ subpixel.rgba = "rgb";
+ defaultFonts = {
+ monospace = [ "Terminess Nerd Font" ];
+ serif = [ "DeepMind Sans" ];
+ sansSerif = [ "DeepMind Sans" ];
+ };
+ };
+ };
+
+ # misc
+ services = {
+ seatd.enable = true;
+ dbus = {
+ enable = true;
+ implementation = "broker";
+ };
+ };
+
+ programs = {
+ gnupg.agent = {
+ enable = true;
+ pinentryPackage = pkgs.pinentry-bemenu;
+ };
+ };
+
+ security.pam.services.swaylock.text = "auth include login";
+ hardware.opengl.enable = true;
+}
diff --git a/os/cez/modules/wireguard.nix b/os/cez/modules/wireguard.nix
new file mode 100644
index 0000000..d8e8dd0
--- /dev/null
+++ b/os/cez/modules/wireguard.nix
@@ -0,0 +1,27 @@
+{ config, ... }:
+
+let
+ domain = config.userdata.domain;
+in
+{
+ sops.secrets."misc/wireguard" = {};
+
+ networking.wg-quick.interfaces."kay" = {
+ autostart = false;
+ address = [ "10.0.1.2/24" ];
+ dns = [ "10.0.1.1" ];
+ mtu = 1380;
+ privateKeyFile = config.sops.secrets."misc/wireguard".path;
+
+ peers = [{
+ publicKey = "wJMyQDXmZO4MjYRk6NK4+J6ZKWLTTZygAH+OwbPjOiw=";
+ allowedIPs = [
+ "10.0.1.0/24"
+ "104.16.0.0/12"
+ "172.64.0.0/13"
+ ];
+ endpoint = "${domain}:51820";
+ persistentKeepalive = 25;
+ }];
+ };
+}
diff --git a/os/cez/secrets.yaml b/os/cez/secrets.yaml
new file mode 100644
index 0000000..f72eba6
--- /dev/null
+++ b/os/cez/secrets.yaml
@@ -0,0 +1,32 @@
+misc:
+ sftp: ENC[AES256_GCM,data:xic1JI1RHo3Xc/izQBubMQ5TEvQxeFIOEbkFj/MWjw7UOgQrQEozfhvmGvB3lqjdgO2e2RXYHc7RvwAfquZN9QWFFp7vS7JqhqGTg4+I0JNh28LDsdzeAXe7d4yLkJ5cl4EhU5a6Zd9Qo60JyO8HRAMSXQBuHMzTW0A4achARcTguyJUiCntxvyLiKPZGdGj7HsHfxr32S1ieejGDqxuOLTrssOgyxikWT+PqibWie+JDH20+ZP8l6ip8FdNaWcyzfED/SJybpRbDBvL3iXw9tb67SeRWKR8I91nyyLh69hwLHrp/IgboDlCW8/ZmOYoRWCJF4lH86v3312wuoU60x8IoSL7YhWW5N3WQpWxWeEmLlMFD0x6LcJclUeoIlpVNvR8wDNKeayHhdLChIs2ZiEUAAIaTcUKdWWccY7JraMosqKgS9BmnjLJLEei9kFEF+y97QxQ/q4AfyFPbajxSd7aujqXuUfqpL1aLgt65h1TyOKN3E3Y2faiTaR76EALyv2d4PdYHWhkhxXVATRhsG+N2Mg9FSCciGnD7wlu9IR28HrbLuvX7W2KsLDVdI2oBtfExTf8YQwPSk1vp28=,iv:VyhdbfiiQJqG6cKAz6WjmlG3MkM25VzQzfCt1qYgH4M=,tag:KIoEb/dkEPpeaCJaNkAflw==,type:str]
+ wireguard: ENC[AES256_GCM,data:WUHMeYro1PS25wEtsQKHHtpLXbtox8JtqX5863dHelBIA2SB7YZ+eWyv5hQ=,iv:hGgR3UcFeVGZjWJjdnVuQeUQtz3p4Lh6QRBJDfTr9Qo=,tag:4qpU9Ue4QtfBINdy0CSdvw==,type:str]
+sops:
+ kms: []
+ gcp_kms: []
+ azure_kv: []
+ hc_vault: []
+ age:
+ - recipient: age1q5sfy74d53n6jxlgsc2zrsz4wcl9d830nxuagc3wfmdkrrp55ckq9ev6nv
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLd3E0NC9Vb25ySXR0R0xL
+ b0pLcUdsNjYzZ0F6SkdodFZjT0s2OE5TZ0E0CkM5RHY4MmpBNFR6TWJLejlqS2FC
+ TmpRRUdMRkQ3SnhvY2ZtN3ZzYjRQYmsKLS0tIEZlWkRLVWJOaXV6V3Zmb2hUV0xj
+ d0N3S0ZIR0MyOERHV1k5RVBVVWVHQkkKZVtPjmpOPJM8STs70/nki6vTeo4mp47A
+ xEVUzxeUGpoyAewxSCo9W6IGtKyZQl0TEL3ucAmhOsjX4BWe2JShMA==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age1nur989fnjmfgfk54ctczrwg25epqqr0xgkl5d4swfxka9aw6cdrqdawvaq
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFWENJNzlDL1FpTkYwV1ps
+ V1VWeW4yOFZwZ1h5SGwzV2oyVkJaaHF0a1JRCmpFWWRLZzdUTUliZHpCTzJDYlhu
+ Yk51d1orS0tsMitBM0ZKSTQ4T05sNVEKLS0tIEVuZkY1bld2RldZOVNOc1E3bG5X
+ dVZ3V0VUQzF5VzN0RFM5c0RjZHpJZ0EK09qgyPHEhHgRZt2GZQB5IM9Z/nfYXW28
+ fcfmF6pko9qOYQ72P7vwv8Xub0SEI8GKGQwz2QPDJT9gd1qtipuhuQ==
+ -----END AGE ENCRYPTED FILE-----
+ lastmodified: "2024-01-09T06:00:09Z"
+ mac: ENC[AES256_GCM,data:WkXFwF0bHvFvNTlLKrGk6iQpk5RqMIapluqyv3rcKATP4S1rQSCXwlUn88TNfKeOsJ6pSqoBmwPNjufr9SNrPZZNKYZ4sA4yft9jgCeBcyX6TaPPA123qL8xM3C2TcaE1oBrG9fwmMgEJMYJA7LxBAXz4sW17geb/y4TZgUDwBw=,iv:VJzYR0dbT761ezejxOwPO6x8cKPAzMZtwZHWvPhiDzI=,tag:Xu43SfKeGgCJivfgk+vp3Q==,type:str]
+ pgp: []
+ unencrypted_suffix: _unencrypted
+ version: 3.8.1
diff --git a/os/common/configuration.nix b/os/common/configuration.nix
new file mode 100644
index 0000000..5c3972b
--- /dev/null
+++ b/os/common/configuration.nix
@@ -0,0 +1,92 @@
+{ config, pkgs, lib, ... }:
+
+let
+ host = config.networking.hostName;
+ user = config.userdata.name;
+ email = config.userdata.email;
+in
+{
+ disabledModules = [
+ "services/networking/pppd.nix"
+ "services/mail/stalwart-mail.nix"
+ ];
+ imports = [
+ ./modules/tmux.nix
+ ./modules/dev.nix
+ ./modules/nix.nix
+
+ ./modules/pppd.nix
+ ./modules/stalwart-mail.nix
+ ];
+
+ sops = {
+ defaultSopsFile = ../${host}/secrets.yaml;
+ age.keyFile = "/var/secrets/${host}.sops";
+ };
+ system.stateVersion = "23.11";
+ nix.settings.experimental-features = [ "flakes" "nix-command" ];
+
+ boot = {
+ tmp.useTmpfs = true;
+ loader.timeout = 1;
+ };
+
+ users.users.${user} = {
+ uid = 1000;
+ isNormalUser = true;
+ description = email;
+
+ extraGroups = [ "wheel" ];
+ packages = with pkgs; [
+ bc
+ unzip
+ htop
+ curl
+ file
+ dig
+ tcpdump
+ mtr
+ nnn
+ ps_mem
+ brightnessctl
+ ];
+
+ openssh.authorizedKeys.keys = [
+ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAcCendbKbeoc7hYEEcBt9wwtSXrJUgJ2SuYARO0zPAX sinan@veu"
+ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL8LnyOuPmtKRqAZeHueNN4kfYvpRQVwCivSTq+SZvDU sinan@cez"
+ ];
+ };
+
+ time.timeZone = "Asia/Kolkata";
+ networking.useDHCP = false;
+ environment = {
+ binsh = "${lib.getExe pkgs.dash}";
+ systemPackages = with pkgs; [
+ dash
+ luajit
+ neovim
+ sops
+ ];
+ variables = {
+ EDITOR = "nvim";
+ VISUAL = "nvim";
+ };
+ shellAliases = {
+ ls = "ls --color=auto --group-directories-first";
+ grep = "grep --color=auto";
+ };
+ };
+ services.openssh = {
+ enable = true;
+ settings.PasswordAuthentication = false;
+ };
+ programs.bash.promptInit = ''
+ if [ "$UID" -ne 0 ]; then
+ PROMPT_COLOR="1;32m"
+ else
+ PROMPT_COLOR="1;31m"
+ fi
+
+ PS1="\[\033[$PROMPT_COLOR\][\[\e]0;\u@\h: \w\a\]\u@\h:\w]\\$\[\033[0m\] "
+ '';
+}
diff --git a/os/common/modules/dev.nix b/os/common/modules/dev.nix
new file mode 100644
index 0000000..285dfba
--- /dev/null
+++ b/os/common/modules/dev.nix
@@ -0,0 +1,29 @@
+{ config, pkgs, ... }:
+
+let
+ user = config.userdata.name;
+in
+{
+ users.users.${user}.packages = with pkgs; [
+ gcc
+ git
+ lua
+
+ (python3.withPackages (p: with p; [
+ pip
+ build
+ ]))
+
+ man-pages
+ man-pages-posix
+
+ ccls
+ lua-language-server
+ nil
+ nodePackages.bash-language-server
+ nodePackages.pyright
+ shellcheck
+ ];
+
+ documentation.dev.enable = true;
+}
diff --git a/os/common/modules/nix.nix b/os/common/modules/nix.nix
new file mode 100644
index 0000000..d826e77
--- /dev/null
+++ b/os/common/modules/nix.nix
@@ -0,0 +1,6 @@
+{ ... }: {
+ nix.settings = {
+ auto-optimise-store = true;
+ experimental-features = [ "flakes" "nix-command" "repl-flake" ];
+ };
+}
diff --git a/os/common/modules/pppd.nix b/os/common/modules/pppd.nix
new file mode 100644
index 0000000..772cb29
--- /dev/null
+++ b/os/common/modules/pppd.nix
@@ -0,0 +1,277 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.pppd;
+ shTypes = [ "ip-up" "ip-down" "ipv6-up" "ipv6-down" ];
+in
+{
+ meta = {
+ maintainers = with maintainers; [ danderson ];
+ };
+
+ options.services.pppd = {
+ enable = mkEnableOption (lib.mdDoc "pppd");
+
+ package = mkOption {
+ default = pkgs.ppp;
+ defaultText = literalExpression "pkgs.ppp";
+ type = types.package;
+ description = lib.mdDoc "pppd package to use.";
+ };
+
+ config = mkOption {
+ type = types.lines;
+ default = "";
+ description = lib.mdDoc "default config for pppd";
+ };
+
+ secret = {
+ chap = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ description = lib.mdDoc "path to chap secret for pppd";
+ };
+ pap = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ description = lib.mdDoc "path to pap secret for pppd";
+ };
+ srp = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ description = lib.mdDoc "path to srp secret for pppd";
+ };
+ };
+
+ script = mkOption {
+ default = {};
+ description = lib.mdoc ''
+ script which is executed when the link is available for sending and
+ receiving IP packets or when the link is no longer available for sending
+ and receiving IP packets, see pppd(8) for more details
+ '';
+ type = types.attrsOf (types.submodule (
+ { name, ... }:
+ {
+ options = {
+ name = mkOption {
+ type = types.str;
+ default = name;
+ example = "01-ddns.sh";
+ description = lib.mdDoc "Name of the script.";
+ };
+ type = mkOption {
+ default = "ip-up";
+ type = types.enum shTypes;
+ description = lib.mdDoc "Type of the script.";
+ };
+ text = mkOption {
+ type = types.lines;
+ default = "";
+ description = lib.mdDoc "Shell commands to be executed.";
+ };
+ runtimeInputs = mkOption {
+ type = types.listOf types.package;
+ default = [];
+ description = lib.mdDoc "dependencies of the shell script";
+ };
+ };
+ }
+ ));
+ };
+
+ peers = mkOption {
+ default = {};
+ description = lib.mdDoc "pppd peers.";
+ type = types.attrsOf (types.submodule (
+ { name, ... }:
+ {
+ options = {
+ name = mkOption {
+ type = types.str;
+ default = name;
+ example = "dialup";
+ description = lib.mdDoc "Name of the PPP peer.";
+ };
+
+ enable = mkOption {
+ type = types.bool;
+ default = true;
+ example = false;
+ description = lib.mdDoc "Whether to enable this PPP peer.";
+ };
+
+ autostart = mkOption {
+ type = types.bool;
+ default = true;
+ example = false;
+ description = lib.mdDoc "Whether the PPP session is automatically started at boot time.";
+ };
+
+ config = mkOption {
+ type = types.lines;
+ default = "";
+ description = lib.mdDoc "pppd configuration for this peer, see the pppd(8) man page.";
+ };
+
+ configFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ example = literalExpression "/run/secrets/ppp/peer/options";
+ description = lib.mdDoc "pppd configuration file for this peer, see the pppd(8) man page.";
+ };
+ };
+ }
+ ));
+ };
+ };
+
+ config = let
+ enabledConfigs = filter (f: f.enable) (attrValues cfg.peers);
+
+ defaultCfg = if (cfg.config != "") then {
+ "ppp/options".text = cfg.config;
+ } else {};
+
+ mkPeers = peerCfg: with peerCfg; let
+ key = if (configFile == null) then "text" else "source";
+ val = if (configFile == null) then peerCfg.config else configFile;
+ in
+ {
+ name = "ppp/peers/${name}";
+ value.${key} = val;
+ };
+
+ enabledSh = filter (s: s.text != "") (attrValues cfg.script);
+ mkMsh = name : {
+ name = "ppp/${name}";
+ value.mode = "0755";
+ value.text = ''
+ #!/bin/sh
+
+ # see the pppd(8) man page
+ for s in /etc/ppp/${name}.d/*.sh; do
+ [ -x "$s" ] && "$s" "$@"
+ done
+ '';
+ };
+ mkUsh = shCfg : {
+ name = "ppp/${shCfg.type}.d/${shCfg.name}.sh";
+ value.mode = "0755";
+ value.text = ''
+ #!/bin/sh
+ export PATH="${makeBinPath shCfg.runtimeInputs}:$PATH"
+
+ ${shCfg.text}
+ '';
+ };
+
+ enabledSec = let
+ l = attrNames cfg.secret;
+ f = (s: cfg.secret.${s} != null);
+ in filter f l;
+ mkSec = sec : {
+ name = "ppp/${sec}-secrets";
+ value.source = cfg.secret.${sec};
+ };
+
+ mkSystemd = peerCfg: {
+ name = "pppd-${peerCfg.name}";
+ value = {
+ restartTriggers = [ config.environment.etc."ppp/peers/${peerCfg.name}".source ];
+ before = [ "network.target" ];
+ wants = [ "network.target" ];
+ after = [ "network-pre.target" ];
+ environment = {
+ # pppd likes to write directly into /var/run. This is rude
+ # on a modern system, so we use libredirect to transparently
+ # move those files into /run/pppd.
+ LD_PRELOAD = "${pkgs.libredirect}/lib/libredirect.so";
+ NIX_REDIRECTS = "/var/run=/run/pppd";
+ };
+ serviceConfig = let
+ capabilities = [
+ "CAP_BPF"
+ "CAP_SYS_TTY_CONFIG"
+ "CAP_NET_ADMIN"
+ "CAP_NET_RAW"
+ ];
+ in
+ {
+ ExecStart = "${getBin cfg.package}/sbin/pppd call ${peerCfg.name} nodetach nolog";
+ Restart = "always";
+ RestartSec = 5;
+
+ AmbientCapabilities = capabilities;
+ CapabilityBoundingSet = capabilities;
+ KeyringMode = "private";
+ LockPersonality = true;
+ MemoryDenyWriteExecute = true;
+ NoNewPrivileges = true;
+ PrivateMounts = true;
+ PrivateTmp = true;
+ ProtectControlGroups = true;
+ ProtectHome = true;
+ ProtectHostname = true;
+ ProtectKernelModules = true;
+ # pppd can be configured to tweak kernel settings.
+ ProtectKernelTunables = false;
+ ProtectSystem = "strict";
+ RemoveIPC = true;
+ RestrictAddressFamilies = [
+ "AF_ATMPVC"
+ "AF_ATMSVC"
+ "AF_INET"
+ "AF_INET6"
+ "AF_IPX"
+ "AF_NETLINK"
+ "AF_PACKET"
+ "AF_PPPOX"
+ "AF_UNIX"
+ ];
+ RestrictNamespaces = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ SecureBits = "no-setuid-fixup-locked noroot-locked";
+ SystemCallFilter = "@system-service";
+ SystemCallArchitectures = "native";
+
+ # All pppd instances on a system must share a runtime
+ # directory in order for PPP multilink to work correctly. So
+ # we give all instances the same /run/pppd directory to store
+ # things in.
+ #
+ # For the same reason, we can't set PrivateUsers=true, because
+ # all instances need to run as the same user to access the
+ # multilink database.
+ RuntimeDirectory = "pppd";
+ RuntimeDirectoryPreserve = true;
+ };
+ wantedBy = mkIf peerCfg.autostart [ "multi-user.target" ];
+ };
+ };
+
+ etcFiles = listToAttrs (map mkPeers enabledConfigs) //
+ listToAttrs (map mkMsh shTypes) //
+ listToAttrs (map mkUsh enabledSh) //
+ listToAttrs (map mkSec enabledSec) //
+ defaultCfg;
+
+ systemdConfigs = listToAttrs (map mkSystemd enabledConfigs);
+
+ in mkIf cfg.enable {
+ assertions = map (peerCfg: {
+ assertion = (peerCfg.configFile == null || peerCfg.config == "");
+ message = ''
+ Please specify either
+ 'services.pppd.${peerCfg.name}.config' or
+ 'services.pppd.${peerCfg.name}.configFile'.
+ '';
+ }) enabledConfigs;
+
+ environment.etc = etcFiles;
+ systemd.services = systemdConfigs;
+ };
+}
diff --git a/os/common/modules/stalwart-mail.nix b/os/common/modules/stalwart-mail.nix
new file mode 100644
index 0000000..68e8400
--- /dev/null
+++ b/os/common/modules/stalwart-mail.nix
@@ -0,0 +1,163 @@
+{ config, lib, pkgs, ... }: let
+ cfg = config.services.stalwart-mail;
+ configFormat = pkgs.formats.toml { };
+ configFile = configFormat.generate "stalwart-mail.toml" cfg.settings;
+ dataDir = "/var/lib/stalwart-mail";
+
+ readTOML =
+ path:
+ builtins.fromTOML (builtins.unsafeDiscardStringContext (lib.readFile path));
+ recursiveUpdateList =
+ attrList:
+ lib.lists.foldr (a1: a2: lib.attrsets.recursiveUpdate a1 a2) {} attrList;
+ mkOverrideRec =
+ priority:
+ content:
+ if lib.isAttrs content then
+ lib.mapAttrs (_: v: mkOverrideRec priority v) content
+ else
+ lib.mkOverride priority content;
+ mkOptionDefaultRec = mkOverrideRec 1500;
+
+ cfgPkg = pkgs.callPackage ../pkgs/stalwart-mail-config.nix {};
+ cfgFiles = (readTOML "${cfgPkg}/config.toml").include.files;
+ settingsDefault = recursiveUpdateList (map (path: readTOML path) cfgFiles);
+in {
+ options.services.stalwart-mail = {
+ enable = lib.mkEnableOption "the Stalwart all-in-one email server";
+ package = lib.mkPackageOption pkgs "stalwart-mail" { };
+
+ loadCredential = lib.mkOption {
+ type = lib.types.listOf lib.types.str;
+ default = [];
+ example = [ "dkim.private:/path/to/stalwart.private" ];
+ description = ''
+ This can be used to pass secrets to the systemd service without adding them to
+ the nix store.
+ See the LoadCredential section of systemd.exec manual for more information.
+ '';
+ };
+
+ settings = lib.mkOption {
+ inherit (configFormat) type;
+ default = { };
+ description = ''
+ Configuration options for the Stalwart email server.
+ See <https://stalw.art/docs/category/configuration> for available options.
+
+ By default, the module is configured to store everything locally.
+ '';
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ # set the default upstream settings
+ # assumptions
+ # 1. ./config.toml exists and only containts include.files and macros
+ # 2. no other files containts include.files
+ services.stalwart-mail.settings = mkOptionDefaultRec
+ (lib.attrsets.recursiveUpdate settingsDefault {
+ macros.base_path = dataDir;
+ server.run-as.user = {};
+ server.run-as.group = {};
+ global.tracing.method = "stdout";
+ # outliers as of v0.6.0
+ acme."letsencrypt".cache = "${cfg.settings.macros.base_path}/acme";
+ });
+
+ assertions = let
+ m = cfg.settings.macros;
+
+ mkMacroMessage =
+ opt:
+ "config.stalwart-mail.settings.macros.${opt} can not be empty";
+ in [
+ {
+ assertion = m ? host
+ && m.host != ""
+ && m.host != null;
+ message = mkMacroMessage "host";
+ }
+ {
+ assertion = m ? default_domain
+ && m.default_domain != ""
+ && m.default_domain != null;
+ message = mkMacroMessage "default_domain";
+ }
+ {
+ assertion = m ? default_directory
+ && m.default_directory != ""
+ && m.default_directory != null;
+ message = mkMacroMessage "default_directory";
+ }
+ {
+ assertion = m ? default_store &&
+ m.default_store != ""
+ && m.default_store != null;
+ message = mkMacroMessage "default_store";
+ }
+ ];
+
+ systemd.services.stalwart-mail = {
+ wantedBy = [ "multi-user.target" ];
+ after = [ "local-fs.target" "network.target" ];
+
+ serviceConfig = {
+ ExecStart =
+ "${cfg.package}/bin/stalwart-mail --config=${configFile}";
+
+ # Base from template resources/systemd/stalwart-mail.service
+ Type = "simple";
+ LimitNOFILE = 65536;
+ KillMode = "process";
+ KillSignal = "SIGINT";
+ Restart = "on-failure";
+ RestartSec = 5;
+ StandardOutput = "journal";
+ StandardError = "journal";
+ SyslogIdentifier = "stalwart-mail";
+
+ DynamicUser = true;
+ User = "stalwart-mail";
+ StateDirectory = "stalwart-mail";
+ LoadCredential = cfg.loadCredential;
+
+ # Bind standard privileged ports
+ AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
+ CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
+
+ # Hardening
+ DeviceAllow = [ "" ];
+ LockPersonality = true;
+ MemoryDenyWriteExecute = true;
+ PrivateDevices = true;
+ PrivateUsers = false; # incompatible with CAP_NET_BIND_SERVICE
+ ProcSubset = "pid";
+ PrivateTmp = true;
+ ProtectClock = true;
+ ProtectControlGroups = true;
+ ProtectHome = true;
+ ProtectHostname = true;
+ ProtectKernelLogs = true;
+ ProtectKernelModules = true;
+ ProtectKernelTunables = true;
+ ProtectProc = "invisible";
+ ProtectSystem = "strict";
+ RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
+ RestrictNamespaces = true;
+ RestrictRealtime = true;
+ RestrictSUIDSGID = true;
+ SystemCallArchitectures = "native";
+ SystemCallFilter = [ "@system-service" "~@privileged" ];
+ UMask = "0077";
+ };
+ };
+
+ # Make admin commands available in the shell
+ environment.systemPackages = [ cfg.package cfgPkg ];
+ };
+
+ meta = {
+ maintainers = with lib.maintainers; [ happysalada pacien ];
+ };
+}
diff --git a/os/common/modules/tmux.nix b/os/common/modules/tmux.nix
new file mode 100644
index 0000000..eeaafbb
--- /dev/null
+++ b/os/common/modules/tmux.nix
@@ -0,0 +1,42 @@
+{ pkgs, ... }:
+
+{
+ environment = {
+ systemPackages = with pkgs; [ tmux ];
+
+ etc."tmux.conf".text = ''
+ # base
+ set-option -g prefix C-a
+ unbind-key C-b
+ bind-key C-a send-prefix
+ set -g base-index 1
+ setw -g pane-base-index 1
+ set -g history-limit 10000
+
+ # vim
+ set -g mode-keys vi
+ bind -T copy-mode-vi v send -X begin-selection
+ bind -T copy-mode-vi y send -X copy-selection
+ bind -r C-w last-window
+
+ bind -r h select-pane -L
+ bind -r j select-pane -D
+ bind -r k select-pane -U
+ bind -r l select-pane -R
+
+ bind -r H resize-pane -L 5
+ bind -r J resize-pane -D 5
+ bind -r K resize-pane -U 5
+ bind -r L resize-pane -R 5
+
+ bind -r C-h select-window -t :-
+ bind -r C-l select-window -t :+
+
+ # not eye candy
+ set -g status-style "bg=default fg=7"
+ set -g status-left ""
+ set -g status-right ""
+ set -g status-justify right
+ '';
+ };
+}
diff --git a/os/common/pkgs/stalwart-mail-config.nix b/os/common/pkgs/stalwart-mail-config.nix
new file mode 100644
index 0000000..77fc366
--- /dev/null
+++ b/os/common/pkgs/stalwart-mail-config.nix
@@ -0,0 +1,43 @@
+{ lib,
+ stdenvNoCC,
+ fetchzip,
+ stalwart-mail,
+}:
+
+stdenvNoCC.mkDerivation {
+ pname = stalwart-mail.pname + "-config";
+ version = stalwart-mail.version;
+
+ src = let
+ rev = stalwart-mail.src.rev;
+ owner = stalwart-mail.src.owner;
+ repo = stalwart-mail.src.repo;
+ in fetchzip {
+ url = "https://github.com/${owner}/${repo}/raw/${rev}/resources/config.zip";
+ # gives us a chance to manually verify config changes, if not use
+ # stalwart-mail.src
+ hash = "sha256-ji7+f3BGzVEb9gp5BXCStPR4/Umy93OTMA+DhYI/azk=";
+ };
+
+ outputs = [ "out" ];
+ patchPhase = ''
+ # TODO: remove me
+ # toml spec violation, author said this will be fixed on the next realase
+ sed -e 's/\[storage.fts\]//g' -e 's/default-language = "en"//g' \
+ -i ./common/store.toml
+
+ # outliers as of 0.6.0
+ # smtp/signature.toml:#public-key = "file://%{BASE_PATH}%/etc/dkim/%{DEFAULT_DOMAIN}%.cert"
+ # smtp/signature.toml:private-key = "file://%{BASE_PATH}%/etc/dkim/%{DEFAULT_DOMAIN}%.key"
+ # common/tls.toml:cache = "%{BASE_PATH}%/etc/acme"
+ find -type f \
+ -name '*.toml' \
+ -exec sed 's=%{BASE_PATH}%/etc=${placeholder "out"}=g' -i {} \;
+ '';
+ installPhase = "cp -r ./ $out";
+
+ meta = stalwart-mail.meta // {
+ description = "Configs for" + stalwart-mail.meta.description;
+ maintainers = with lib.maintainers; [ sinanmohd ];
+ };
+}
diff --git a/os/dspace/configuration.nix b/os/dspace/configuration.nix
new file mode 100644
index 0000000..0a28af6
--- /dev/null
+++ b/os/dspace/configuration.nix
@@ -0,0 +1,19 @@
+{ config, ... }:
+
+let
+ user = config.userdata.name;
+in
+{
+ imports = [
+ ../common/configuration.nix
+ ./hardware-configuration.nix
+
+ ./modules/network.nix
+ ./modules/www.nix
+ ];
+
+
+ users.users.${user}.openssh.authorizedKeys.keys = [
+ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILvR5FliFLq1FJWotnBk9deWmbeGi2uq2XVmx0uAr1Lw sinan@fscusat"
+ ];
+}
diff --git a/os/dspace/hardware-configuration.nix b/os/dspace/hardware-configuration.nix
new file mode 100644
index 0000000..7a8d7b2
--- /dev/null
+++ b/os/dspace/hardware-configuration.nix
@@ -0,0 +1,32 @@
+{ lib, modulesPath, ... }:
+
+{
+ imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
+
+ boot = {
+ loader = {
+ systemd-boot.enable = true;
+ efi.canTouchEfiVariables = true;
+ };
+
+ initrd.availableKernelModules = [
+ "ata_piix"
+ "uhci_hcd"
+ "virtio_pci"
+ "virtio_scsi"
+ "sd_mod"
+ "sr_mod"
+ ];
+ };
+
+ fileSystems = {
+ "/" = {
+ device = "/dev/disk/by-uuid/c5b1077e-52e8-4249-8bd7-d53eafa41f5a";
+ fsType = "ext4";
+ };
+ "/boot" = {
+ device = "/dev/disk/by-uuid/9787-FFFE";
+ fsType = "vfat";
+ };
+ };
+}
diff --git a/os/dspace/modules/network.nix b/os/dspace/modules/network.nix
new file mode 100644
index 0000000..007cfba
--- /dev/null
+++ b/os/dspace/modules/network.nix
@@ -0,0 +1,18 @@
+{ ... }:
+
+let
+ wan = "ens18";
+in
+{
+ networking = {
+ interfaces.${wan}.ipv4.addresses = [{
+ address = "10.0.8.107";
+ prefixLength = 16;
+ }];
+ defaultGateway = {
+ address = "10.0.0.1";
+ interface = wan;
+ };
+ nameservers = [ "10.0.0.2" "10.0.0.3" ];
+ };
+}
diff --git a/os/dspace/modules/www.nix b/os/dspace/modules/www.nix
new file mode 100644
index 0000000..90ab841
--- /dev/null
+++ b/os/dspace/modules/www.nix
@@ -0,0 +1,39 @@
+{ config, ... }:
+
+let
+ domain = "dsp.fscusat.ac.in";
+in
+{
+ networking.firewall.allowedTCPPorts = [ 80 443 ];
+
+ sops.secrets = let
+ opts = {
+ owner = config.services.nginx.user;
+ group = config.services.nginx.group;
+ };
+ in{
+ "cusat.ac.in/key" = opts;
+ "cusat.ac.in/crt" = opts;
+ };
+
+ services.nginx = {
+ enable = true;
+ recommendedTlsSettings = true;
+ recommendedZstdSettings = true;
+ recommendedOptimisation = true;
+ recommendedGzipSettings = true;
+ recommendedProxySettings = true;
+ recommendedBrotliSettings = true;
+
+ virtualHosts.${domain} = {
+ forceSSL = true;
+ sslCertificateKey = config.sops.secrets."cusat.ac.in/key".path;
+ sslCertificate = config.sops.secrets."cusat.ac.in/crt".path;
+
+ locations."/" = {
+ return = "200 '<h1>under construction</h1>'";
+ extraConfig = "add_header Content-Type text/html;";
+ };
+ };
+ };
+}
diff --git a/os/dspace/secrets.yaml b/os/dspace/secrets.yaml
new file mode 100644
index 0000000..42143ac
--- /dev/null
+++ b/os/dspace/secrets.yaml
@@ -0,0 +1,32 @@
+cusat.ac.in:
+ key: ENC[AES256_GCM,data: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,iv:dyo8mIJI2o8IerqV9QNziM6Bl8FOkbp31Y3Q/Lr+x/4=,tag:xalsdWTtaqXWLYn6LJJRRA==,type:str]
+ crt: ENC[AES256_GCM,data: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,iv:KrNhOECVu9ZlIMEjxuseREMJe34ke88MbZsns+ug17E=,tag:zVKWzcDNxTujzN1wwNNjRg==,type:str]
+sops:
+ kms: []
+ gcp_kms: []
+ azure_kv: []
+ hc_vault: []
+ age:
+ - recipient: age1q5sfy74d53n6jxlgsc2zrsz4wcl9d830nxuagc3wfmdkrrp55ckq9ev6nv
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQWGxiUlZMN243Yjdtbnla
+ Sitpd0h4VjFuNVdaYldvM1JTT2QxR1dnTXdnCjJ3RmV4WFRPWGhZV1ZvWm00Y29E
+ ck1SMVFkMWQ1WVJqeEdYU3ErQWdJRVUKLS0tIDhTWFZLRnVVRllUa1JaZk0wb2Rj
+ Qk9VZE81YXVaajVISnVLYkNDTHpqaEEKTr5RkhOGSmWu+BHMwXlAcpn5zkqMwJQK
+ VU9mlVGhoXfc9BW8Ucty0a3/VK5Ze6y5V6573S+GKzhLURspmKXyaw==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age15hsgvg3tz9lql0jpr5x8pm66r42kemd65fpz0wa6t8nhvwrxygcssjxd9c
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBhY3FNdGw2bG9HOWlWR05C
+ MUkrVHozakRzTG1iQXd1RjMyeWlPdzRaekRZCk41WGdWZExTK3N3ejczWklaWlY1
+ V2tUSjU3alp1SS9ockg2Mjh6c1BaSUkKLS0tIEYyQWJxek9SRG8zaDBMOE1KYjRZ
+ VzRWd1RNUndzRzR0WWFaL2k1S2dDMTQKPpj0zMSEs0AygU7naxTEy/Bf/XEEN01Y
+ eKmtK73BQWdZ2LIwm81vShh+9Haq2pBkvGaYwu1attCxYq9BZp9lJA==
+ -----END AGE ENCRYPTED FILE-----
+ lastmodified: "2024-01-09T12:21:41Z"
+ mac: ENC[AES256_GCM,data:+BZ5x2zZxCOa3vogr0ohbs/o8uCPxgIjf6SZmHgqBRTVY17NAdEjzRlxcDX7vzDGdX+bLcQdJW3zj2H7BfLdlulldoJfjINIhPVTdrqihVrGC9/JgOy+NrQqD3cr8YJgkqAoELMoDira2oecLlrE4Wan8snD3Ul2nyxFdDOoO0Y=,iv:mCmMWopzWtlTukPTQBZ6Z2CSLMFXe1IUL6Ud0cmU1N8=,tag:7/a1ptXCnDkmxFfIGuGm8A==,type:str]
+ pgp: []
+ unencrypted_suffix: _unencrypted
+ version: 3.8.1
diff --git a/os/fscusat/configuration.nix b/os/fscusat/configuration.nix
new file mode 100644
index 0000000..e515783
--- /dev/null
+++ b/os/fscusat/configuration.nix
@@ -0,0 +1,14 @@
+{ ... }:
+
+{
+ imports = [
+ ../common/configuration.nix
+ ./hardware-configuration.nix
+
+ ./modules/network.nix
+ ./modules/www.nix
+ ./modules/mirror
+ ];
+
+ services.openssh.ports = [ 22 465 ];
+}
diff --git a/os/fscusat/hardware-configuration.nix b/os/fscusat/hardware-configuration.nix
new file mode 100644
index 0000000..8bb54ed
--- /dev/null
+++ b/os/fscusat/hardware-configuration.nix
@@ -0,0 +1,32 @@
+{ modulesPath, ... }:
+
+{
+ imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
+
+ boot = {
+ loader = {
+ systemd-boot.enable = true;
+ efi.canTouchEfiVariables = true;
+ };
+
+ initrd.availableKernelModules = [
+ "ata_piix"
+ "uhci_hcd"
+ "virtio_pci"
+ "virtio_scsi"
+ "sd_mod"
+ "sr_mod"
+ ];
+ };
+
+ fileSystems = {
+ "/" = {
+ device = "/dev/disk/by-uuid/547074b4-4d61-4968-a94f-4f97e1fa2c3c";
+ fsType = "ext4";
+ };
+ "/boot" = {
+ device = "/dev/disk/by-uuid/C634-FE6A";
+ fsType = "vfat";
+ };
+ };
+}
diff --git a/os/fscusat/modules/mirror/debian/default.nix b/os/fscusat/modules/mirror/debian/default.nix
new file mode 100644
index 0000000..c052bdd
--- /dev/null
+++ b/os/fscusat/modules/mirror/debian/default.nix
@@ -0,0 +1,22 @@
+{ config, ... }: let
+ name = config.userdata.name;
+ email = config.userdata.email;
+in {
+ imports = [ ./ftpsync.nix ];
+
+ services.ftpsync = {
+ enable = true;
+
+ settings = {
+ RSYNC_HOST = "ossmirror.mycloud.services";
+ RSYNC_PATH = "debian";
+ ARCH_INCLUDE = "amd64 riscv64";
+
+ INFO_MAINTAINER = "${name} <${email}>";
+ INFO_COUNTRY = "IN";
+ INFO_LOCATION = "Kochi, Kerala";
+ INFO_THROUGHPUT = "1Gb";
+ MAILTO = email;
+ };
+ };
+}
diff --git a/os/fscusat/modules/mirror/debian/ftpsync.nix b/os/fscusat/modules/mirror/debian/ftpsync.nix
new file mode 100644
index 0000000..29fb55b
--- /dev/null
+++ b/os/fscusat/modules/mirror/debian/ftpsync.nix
@@ -0,0 +1,65 @@
+{ config, lib, pkgs, ... }:
+
+let
+ cfg = config.services.ftpsync;
+ archvsync = pkgs.callPackage ../../../pkgs/archvsync {};
+
+ formatKeyValue = k: v: '' ${k}="${v}" '';
+ configFormat = pkgs.formats.keyValue { mkKeyValue = formatKeyValue; };
+ configFile = configFormat.generate "ftpsync.conf" cfg.settings;
+in
+{
+ meta.maintainers = with lib.maintainers; [ sinanmohd ];
+
+ options.services.ftpsync = {
+ enable = lib.mkEnableOption (lib.mdDoc "ftpsync");
+
+ settings = lib.mkOption {
+ inherit (configFormat) type;
+ default = {};
+ description = lib.mdDoc ''
+ Configuration options for ftpsync.
+ See ftpsync.conf(5) man page for available options.
+ '';
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ environment.etc."ftpsync/ftpsync.conf".source = configFile;
+ environment.systemPackages = [ archvsync ];
+
+ services.ftpsync.settings = {
+ TO = lib.mkDefault "$STATE_DIRECTORY";
+ LOGDIR = lib.mkDefault "$LOGS_DIRECTORY";
+ };
+
+ systemd = let
+ name = "ftpsync";
+ meta = {
+ description = "Mirror Debian repositories of packages";
+ documentation = [ "man:ftpsync(1)" ];
+ };
+ in {
+ timers.${name} = meta // {
+ wantedBy = [ "timers.target" ];
+
+ timerConfig = {
+ OnCalendar = "*-*-* 00,06,12,18:00:00";
+ Unit="%i.service";
+ Persistent = true;
+ FixedRandomDelay = true;
+ RandomizedDelaySec = "6h";
+ };
+ };
+
+ services.${name} = meta // {
+ serviceConfig = {
+ LogsDirectory = name;
+ StateDirectory = name;
+
+ ExecStart = "${archvsync}/bin/ftpsync sync:all";
+ };
+ };
+ };
+ };
+}
diff --git a/os/fscusat/modules/mirror/default.nix b/os/fscusat/modules/mirror/default.nix
new file mode 100644
index 0000000..c5fd462
--- /dev/null
+++ b/os/fscusat/modules/mirror/default.nix
@@ -0,0 +1,11 @@
+{ ... }: {
+ imports = [
+ ./debian
+ ./www.nix
+ ];
+
+ systemd.tmpfiles.rules = [
+ "d /var/cache/mirror/ 0755 root root"
+ "L /var/cache/mirror/debian - - - - /var/lib/ftpsync/"
+ ];
+}
diff --git a/os/fscusat/modules/mirror/www.nix b/os/fscusat/modules/mirror/www.nix
new file mode 100644
index 0000000..ebde425
--- /dev/null
+++ b/os/fscusat/modules/mirror/www.nix
@@ -0,0 +1,11 @@
+{ ... }:
+
+let
+ domain = "foss.fscusat.ac.in";
+in
+{
+ services.nginx.virtualHosts.${domain}.locations."/mirror/" = {
+ alias = "/var/cache/mirror/";
+ extraConfig = "autoindex on;";
+ };
+}
diff --git a/os/fscusat/modules/network.nix b/os/fscusat/modules/network.nix
new file mode 100644
index 0000000..53367f8
--- /dev/null
+++ b/os/fscusat/modules/network.nix
@@ -0,0 +1,18 @@
+{ ... }:
+
+let
+ wan = "ens18";
+in
+{
+ networking = {
+ interfaces.${wan}.ipv4.addresses = [{
+ address = "10.0.8.101";
+ prefixLength = 16;
+ }];
+ defaultGateway = {
+ address = "10.0.0.1";
+ interface = wan;
+ };
+ nameservers = [ "10.0.0.2" "10.0.0.3" ];
+ };
+}
diff --git a/os/fscusat/modules/www.nix b/os/fscusat/modules/www.nix
new file mode 100644
index 0000000..24398da
--- /dev/null
+++ b/os/fscusat/modules/www.nix
@@ -0,0 +1,36 @@
+{ config, ... }:
+
+let
+ domain = "foss.fscusat.ac.in";
+in
+{
+ networking.firewall.allowedTCPPorts = [ 80 443 ];
+
+ sops.secrets = let
+ opts = {
+ owner = config.services.nginx.user;
+ group = config.services.nginx.group;
+ };
+ in{
+ "cusat.ac.in/key" = opts;
+ "cusat.ac.in/crt" = opts;
+ };
+
+ services.nginx = {
+ enable = true;
+ recommendedTlsSettings = true;
+ recommendedZstdSettings = true;
+ recommendedOptimisation = true;
+ recommendedGzipSettings = true;
+ recommendedProxySettings = true;
+ recommendedBrotliSettings = true;
+
+ virtualHosts.${domain} = {
+ forceSSL = true;
+ sslCertificateKey = config.sops.secrets."cusat.ac.in/key".path;
+ sslCertificate = config.sops.secrets."cusat.ac.in/crt".path;
+
+ locations."/".extraConfig = "return 307 $scheme://$host/mirror/;";
+ };
+ };
+}
diff --git a/os/fscusat/pkgs/archvsync/Makefile.patch b/os/fscusat/pkgs/archvsync/Makefile.patch
new file mode 100644
index 0000000..e82ada4
--- /dev/null
+++ b/os/fscusat/pkgs/archvsync/Makefile.patch
@@ -0,0 +1,50 @@
+From f2ba21ba678907fac0d3d088ad09b0d140ba7740 Mon Sep 17 00:00:00 2001
+From: sinanmohd <sinan@sinanmohd.com>
+Date: Sat, 17 Feb 2024 11:37:23 +0530
+Subject: [PATCH] Makefile: nix port
+
+---
+ Makefile | 17 ++++++++---------
+ 1 file changed, 8 insertions(+), 9 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index 7a774b4..1efa053 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,9 +1,8 @@
+-include /usr/share/dpkg/pkg-info.mk
++bindir = ${OUT}/bin
++docdir = ${DOC}/share/doc/ftpsync
++mandir = ${MAN}/share/man
+
+-bindir = /usr/bin
+-docdir = /usr/share/doc/ftpsync
+ examplesdir = ${docdir}/examples
+-mandir = /usr/share/man
+ man1dir = ${mandir}/man1
+ man5dir = ${mandir}/man5
+
+@@ -41,15 +40,15 @@ install -D bin/runmirrors.$(1) $(2)/runmirrors
+ endef
+
+ install:
+- $(call install_bin,install,${DESTDIR}/${bindir})
+- install -D -m644 -t ${DESTDIR}/${docdir} \
++ $(call install_bin,install,${bindir})
++ install -D -m644 -t ${docdir} \
+ README.md
+- install -D -m644 -t ${DESTDIR}/${examplesdir} \
++ install -D -m644 -t ${examplesdir} \
+ etc/ftpsync.conf.sample \
+ etc/runmirrors.conf.sample \
+ etc/runmirrors.mirror.sample
+- install -D -m644 -t ${DESTDIR}/${man1dir} ${MAN1:%=doc/%.1}
+- install -D -m644 -t ${DESTDIR}/${man5dir} ${MAN5:%=doc/%.5}
++ install -D -m644 -t ${man1dir} ${MAN1:%=doc/%.1}
++ install -D -m644 -t ${man5dir} ${MAN5:%=doc/%.5}
+
+ install-tar:
+ $(call install_bin,install-tar,${DESTDIR}/bin/)
+--
+2.43.0
+
diff --git a/os/fscusat/pkgs/archvsync/common.patch b/os/fscusat/pkgs/archvsync/common.patch
new file mode 100644
index 0000000..d101f40
--- /dev/null
+++ b/os/fscusat/pkgs/archvsync/common.patch
@@ -0,0 +1,26 @@
+From 0bb6e03dbbf0bd47f6f8cc42274b8f7fa9fc9262 Mon Sep 17 00:00:00 2001
+From: sinanmohd <sinan@sinanmohd.com>
+Date: Sat, 17 Feb 2024 14:31:03 +0530
+Subject: [PATCH] common: fix config location when wrapped
+
+---
+ bin/common | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/bin/common b/bin/common
+index 7ac7977..941e77a 100644
+--- a/bin/common
++++ b/bin/common
+@@ -332,6 +332,9 @@ search_config() {
+ # Read config file
+ read_config() {
+ local name=$(echo "$1" | sed -e 's/[^A-Za-z0-9._-]/_/g')
++ name="${1%-wrapped.conf}"
++ name="${name#.}.conf"
++
+ local config=$(search_config "$name")
+ if [ "$config" ]; then
+ . "$config"
+--
+2.43.0
+
diff --git a/os/fscusat/pkgs/archvsync/default.nix b/os/fscusat/pkgs/archvsync/default.nix
new file mode 100644
index 0000000..bd3560e
--- /dev/null
+++ b/os/fscusat/pkgs/archvsync/default.nix
@@ -0,0 +1,52 @@
+{ lib,
+ stdenvNoCC,
+ fetchFromGitLab,
+ makeWrapper,
+
+ pandoc,
+ rsync,
+ bash,
+ hostname,
+}:
+
+stdenvNoCC.mkDerivation {
+ pname = "archvsync";
+ version = "unstable-2024-02-17";
+
+ src = fetchFromGitLab {
+ domain = "salsa.debian.org";
+ owner = "mirror-team";
+ repo = "archvsync";
+ rev = "653357779c338863917aa069afbae1b24472d32d";
+ hash = "sha256-vI32Cko5jXY/aZI9hKWm3GI26Oy89M5VLUFWBk1HNXQ=";
+ };
+
+ strictDeps = true;
+ nativeBuildInputs = [ makeWrapper pandoc ];
+ outputs = [ "out" "man" "doc" ];
+
+ patches = [ ./Makefile.patch ./common.patch ];
+
+ postInstall = ''
+ for s in $out/bin/*; do
+ wrapProgram $s --prefix PATH : ${lib.makeBinPath
+ [ rsync bash hostname ]
+ }
+ done
+ '';
+
+ makeFlags = [
+ "OUT=${placeholder "out"}"
+ "MAN=${placeholder "man"}"
+ "DOC=${placeholder "doc"}"
+ ];
+
+ meta = with lib; {
+ description = "Scripts for maintaining a Debian archive mirror";
+ homepage = "https://salsa.debian.org/mirror-team/archvsync";
+ license = licenses.gpl2;
+ platforms = platforms.all;
+ maintainers = with maintainers; [ sinanmohd ];
+ mainProgram = "ftpsync";
+ };
+}
diff --git a/os/fscusat/secrets.yaml b/os/fscusat/secrets.yaml
new file mode 100644
index 0000000..bed58ce
--- /dev/null
+++ b/os/fscusat/secrets.yaml
@@ -0,0 +1,32 @@
+cusat.ac.in:
+ key: ENC[AES256_GCM,data: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,iv:CzxdD55Ct099dzWs97h+8y/fJmicQ47QLh5rKU7nRog=,tag:QtaZVWBS7qBQoADJApoErQ==,type:str]
+ crt: ENC[AES256_GCM,data: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,iv:wBY6kIHIDynH4125koMcCGAuxHc/F63Yq3NcMfCqPBU=,tag:zfuizdFXXtdZ2HLJSgHUmw==,type:str]
+sops:
+ kms: []
+ gcp_kms: []
+ azure_kv: []
+ hc_vault: []
+ age:
+ - recipient: age1q5sfy74d53n6jxlgsc2zrsz4wcl9d830nxuagc3wfmdkrrp55ckq9ev6nv
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB5V29tMGtRTXlTZ1czZm4r
+ ZW9halUzbGNJSXJpejVUK1dwN2E2c3BoM253Ck5xWG9id0F6WTBxU3ZKSmREZDBW
+ V3lvUHN1TVhPczJ1WmttK1ArK3FzUGMKLS0tIGhCMVZobGp4TytRS2c2QlhJZTcx
+ NVp3eGpXdE5kTjhtb251UWhmS0dSUU0KB38yJCc7hvUxaY/jri4c3WhbkSW8blHc
+ KOKqYJiK/KE0qmpJ7jssmpSKd7JHGUs3nM4H6EC9kTmObbKBzsHDsg==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age1yqma4xm4qss787cnwv2v7j2e0eswhm5k9f27n6zhp74euyydv9essxdrmn
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYTGYwSnpuZEp6NGNJUDNT
+ RWh1RzBoeGtDSlhKOXRoSU9MK05hcjhTK0NBCmltNlUySktURGo1blFYWUhsenR4
+ VHlXR2R3VUZ3RTIxdms3dThCNUVRb0UKLS0tIDZzTm5TUDFybzVwaHJpRVZWRVZv
+ OHpqelBrU2k5Q0dBL1dzOVhYeXM0QkUKjMu+5qi000GvGgKO9l7UFSytjJHHYfEd
+ 8Mi4pXbgWzncWE6D3i5E7twGSDQVpeWHngX35z8SSiWRuBrbjJvVdA==
+ -----END AGE ENCRYPTED FILE-----
+ lastmodified: "2024-01-15T01:54:13Z"
+ mac: ENC[AES256_GCM,data:nxElGqw+YRErhjpJQcG6hHahAizdWIaD1cP/eCKpmsvr7fd8qCJSyQ6nukJ+jugMkdZUsWaoeAX1Vesf2KkcajulvzK0nD+Vq2jXhAZHpil9KIseLPYMxSnSWGNs7B0vsuLLwXN9GB87URYmeJlTS7a74PoH+IfqzAudUH75drw=,iv:qFOShkqvLiLw00R1K85gmhBXx/h7ZNpxM+x63dbNkDs=,tag:hT7btxu3Cc0vXtdZkCRqaw==,type:str]
+ pgp: []
+ unencrypted_suffix: _unencrypted
+ version: 3.8.1
diff --git a/os/kay/configuration.nix b/os/kay/configuration.nix
new file mode 100644
index 0000000..24cc246
--- /dev/null
+++ b/os/kay/configuration.nix
@@ -0,0 +1,18 @@
+{ ... }:
+
+{
+ imports = [
+ ../common/configuration.nix
+ ./hardware-configuration.nix
+
+ ./modules/network.nix
+ ./modules/www.nix
+ ./modules/sftp.nix
+ ./modules/acme.nix
+ ./modules/mail.nix
+ ./modules/dns
+ ./modules/sshfwd.nix
+ ];
+
+ boot.consoleLogLevel = 3;
+}
diff --git a/os/kay/hardware-configuration.nix b/os/kay/hardware-configuration.nix
new file mode 100644
index 0000000..5e2efdf
--- /dev/null
+++ b/os/kay/hardware-configuration.nix
@@ -0,0 +1,39 @@
+{ modulesPath, ... }:
+
+{
+ imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
+
+ boot = {
+ loader = {
+ systemd-boot.enable = true;
+ efi.canTouchEfiVariables = true;
+ };
+
+ kernelModules = [ "kvm-intel" ];
+ blacklistedKernelModules = [ "nouveau" ];
+ initrd.availableKernelModules = [
+ "xhci_pci"
+ "ehci_pci"
+ "ahci"
+ "usb_storage"
+ "usbhid"
+ "sd_mod"
+ ];
+ };
+
+ fileSystems = {
+ "/" = {
+ device = "/dev/disk/by-uuid/2eeacf49-c51e-4229-bd4a-ae437014725f";
+ fsType = "ext4";
+ };
+ "/boot" = {
+ device = "/dev/disk/by-uuid/A902-90BB";
+ fsType = "vfat";
+ };
+ "/hdd" = {
+ device = "/dev/disk/by-uuid/c941edb4-e393-4254-bbef-d1b3728290e9";
+ fsType = "ext4";
+ options = [ "nofail" ];
+ };
+ };
+}
diff --git a/os/kay/modules/acme.nix b/os/kay/modules/acme.nix
new file mode 100644
index 0000000..f4ded0a
--- /dev/null
+++ b/os/kay/modules/acme.nix
@@ -0,0 +1,23 @@
+{ config, pkgs, ... }: let
+ email = config.userdata.email;
+ domain = config.userdata.domain;
+
+ environmentFile =
+ pkgs.writeText "acme-dns" "RFC2136_NAMESERVER='[2001:470:ee65::1]:53'";
+in {
+ security.acme = {
+ acceptTerms = true;
+ defaults.email = email;
+
+ certs.${domain} = {
+ inherit domain;
+ extraDomainNames = [ "*.${domain}" ];
+
+ dnsProvider = "rfc2136";
+ dnsPropagationCheck = false; # local DNS server
+
+ inherit environmentFile;
+ group = config.services.nginx.group;
+ };
+ };
+}
diff --git a/os/kay/modules/cgit.nix b/os/kay/modules/cgit.nix
new file mode 100644
index 0000000..f8fb25c
--- /dev/null
+++ b/os/kay/modules/cgit.nix
@@ -0,0 +1,33 @@
+{ config, pkgs, ... }:
+
+let
+ domain = config.userdata.domain;
+ user = config.userdata.name;
+in
+{
+ environment.systemPackages = with pkgs; [
+ luajitPackages.luaossl
+ lua52Packages.luaossl
+ ];
+
+ services.cgit."git.${domain}" = {
+ enable = true;
+ nginx.virtualHost = "git.${domain}";
+ scanPath = "/var/lib/git";
+ settings = {
+ project-list = "/var/lib/git/project.list";
+ remove-suffix = 1;
+ enable-commit-graph = 1;
+ root-title = "${user}'s git repository";
+ root-desc = "how do i learn github anon";
+ source-filter = "${pkgs.cgit}/lib/cgit/filters/syntax-highlighting.py";
+ about-filter = "${pkgs.cgit}/lib/cgit/filters/about-formatting.sh";
+ readme = ":README.md";
+ footer = "";
+ enable-blame = 1;
+ clone-url = "https://git.${domain}/$CGIT_REPO_URL";
+ enable-log-filecount = 1;
+ enable-log-linecount = 1;
+ };
+ };
+}
diff --git a/os/kay/modules/dendrite.nix b/os/kay/modules/dendrite.nix
new file mode 100644
index 0000000..8277e21
--- /dev/null
+++ b/os/kay/modules/dendrite.nix
@@ -0,0 +1,108 @@
+{ config, lib, pkgs, ... }:
+
+let
+ domain = config.userdata.domain;
+ database = {
+ connection_string = "postgres:///dendrite?host=/run/postgresql";
+ max_open_conns = 90;
+ max_idle_conns = 5;
+ conn_max_lifetime = -1;
+ };
+in
+{
+ sops.secrets."matrix-${domain}/key" = {};
+
+ services = {
+ postgresql = {
+ enable = true;
+ package = with pkgs; postgresql_15;
+ settings = {
+ log_timezone = config.time.timeZone;
+ listen_addresses = lib.mkForce "";
+ };
+ ensureDatabases = [ "dendrite" ];
+ ensureUsers = [{
+ name = "dendrite";
+ ensureDBOwnership = true;
+ }];
+ authentication = lib.mkForce "local all all trust";
+ };
+
+ dendrite = {
+ enable = true;
+ loadCredential = [
+ "private_key:${config.sops.secrets."matrix-${domain}/key".path}"
+ ];
+
+ settings = {
+ sync_api.search = {
+ enable = true;
+ index_path = "/var/lib/dendrite/searchindex";
+ };
+ global = {
+ server_name = domain;
+ private_key = "$CREDENTIALS_DIRECTORY/private_key";
+ trusted_third_party_id_servers = [
+ "matrix.org"
+ "vector.im"
+ ];
+ inherit database;
+ };
+ logging = [{
+ type = "std";
+ level = "warn";
+ }];
+ mscs = {
+ inherit database;
+ mscs = [ "msc2836" ];
+ };
+ sync_api = {
+ inherit database;
+ real_ip_header = "X-Real-IP";
+ };
+ media_api = {
+ inherit database;
+ dynamic_thumbnails = true;
+ max_file_size_bytes = 12800000000;
+ };
+ federation_api = {
+ inherit database;
+ send_max_retries = 8;
+ key_perspectives = [{
+ server_name = "matrix.org";
+ keys = [
+ {
+ key_id = "ed25519:auto";
+ public_key = "Noi6WqcDj0QmPxCNQqgezwTlBKrfqehY1u2FyWP9uYw";
+ }
+ {
+ key_id = "ed25519:a_RXGa";
+ public_key = "l8Hft5qXKn1vfHrg3p4+W8gELQVo8N13JkluMfmn2sQ";
+ }
+ ];
+ }];
+ };
+
+ app_service_api = {
+ inherit database;
+ };
+ room_server = {
+ inherit database;
+ };
+ push_server = {
+ inherit database;
+ };
+ relay_api = {
+ inherit database;
+ };
+ key_server = {
+ inherit database;
+ };
+ user_api = {
+ account_database = database;
+ device_database = database;
+ };
+ };
+ };
+ };
+}
diff --git a/os/kay/modules/dns/5.6.e.e.0.7.4.0.1.0.0.2.ip6.arpa.zone b/os/kay/modules/dns/5.6.e.e.0.7.4.0.1.0.0.2.ip6.arpa.zone
new file mode 100644
index 0000000..69b3524
--- /dev/null
+++ b/os/kay/modules/dns/5.6.e.e.0.7.4.0.1.0.0.2.ip6.arpa.zone
@@ -0,0 +1,14 @@
+$ORIGIN 5.6.e.e.0.7.4.0.1.0.0.2.ip6.arpa.
+$TTL 2d
+
+@ IN SOA ns1.sinanmohd.com. sinan.sinanmohd.com. (
+ 2024020400 ; serial
+ 2h ; refresh
+ 5m ; retry
+ 1d ; expire
+ 5m ) ; nx ttl
+
+ IN NS ns1.sinanmohd.com.
+
+1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR ns1.sinanmohd.com.
+7.3.3.1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 IN PTR mail.sinanmohd.com.
diff --git a/os/kay/modules/dns/ddns.nix b/os/kay/modules/dns/ddns.nix
new file mode 100644
index 0000000..e6e417a
--- /dev/null
+++ b/os/kay/modules/dns/ddns.nix
@@ -0,0 +1,44 @@
+{ pkgs, ... }: {
+ services.pppd.script = {
+ "02-ddns-ipv4" = {
+ runtimeInputs = with pkgs; [ coreutils knot-dns ];
+ type = "ip-up";
+
+ text = ''
+ cat <<- EOF | knsupdate
+ server 2001:470:ee65::1
+ zone sinanmohd.com.
+
+ update delete sinanmohd.com. A
+ update add sinanmohd.com. 180 A $4
+
+ update delete mail.sinanmohd.com. A
+ update add mail.sinanmohd.com. 180 A $4
+
+ send
+ EOF
+ '';
+ };
+
+ "02-ddns-ipv6" = {
+ runtimeInputs = with pkgs; [ coreutils knot-dns iproute2 gnugrep ];
+ type = "ipv6-up";
+
+ text = ''
+ while ! ipv6="$(ip -6 addr show dev "$1" scope global | grep -o '[0-9a-f:]*::1')"; do
+ sleep 0.2
+ done
+
+ cat <<- EOF | knsupdate
+ server 2001:470:ee65::1
+ zone sinanmohd.com.
+
+ update delete sinanmohd.com. AAAA
+ update add sinanmohd.com. 180 AAAA $ipv6
+
+ send
+ EOF
+ '';
+ };
+ };
+}
diff --git a/os/kay/modules/dns/default.nix b/os/kay/modules/dns/default.nix
new file mode 100644
index 0000000..1146cc3
--- /dev/null
+++ b/os/kay/modules/dns/default.nix
@@ -0,0 +1,137 @@
+{ config, pkgs, ... }: let
+ listen_addr = "2001:470:ee65::1";
+
+ acmeSOA = pkgs.writeText "acmeSOA" ''
+ $TTL 2d
+
+ @ IN SOA ns1.sinanmohd.com. sinan.sinanmohd.com. (
+ 2024020505 ; serial
+ 2h ; refresh
+ 5m ; retry
+ 1d ; expire
+ 5m ) ; nx ttl
+
+ IN NS ns1.sinanmohd.com.
+ '';
+in {
+ imports = [ ./ddns.nix ];
+
+ networking.firewall = {
+ allowedTCPPorts = [ 53 ];
+ allowedUDPPorts = [ 53 ];
+ };
+
+ sops.secrets.dns = {
+ owner = config.systemd.services.knot.serviceConfig.User;
+ group = config.systemd.services.knot.serviceConfig.Group;
+ };
+
+ services.knot = {
+ enable = true;
+ keyFiles = [ config.sops.secrets.dns.path ];
+
+ settings = {
+ server.listen = listen_addr;
+
+ remote = [
+ {
+ id = "ns1.he.net";
+ address = [ "2001:470:100::2" "216.218.130.2" ];
+ via = "2001:470:ee65::1";
+ }
+ {
+ id = "m.gtld-servers.net";
+ address = [ "2001:501:b1f9::30" "192.55.83.30" ];
+ }
+ ];
+
+ submission = [{
+ id = "gtld-servers.net";
+ parent = "m.gtld-servers.net";
+ }];
+
+ policy = [{
+ id = "gtld-servers.net";
+ algorithm = "ecdsap384sha384";
+ ksk-lifetime = "365d";
+ ksk-submission = "gtld-servers.net";
+ }];
+
+ # generate TSIG key with keymgr -t name
+ acl = [
+ {
+ id = "ns1.he.net";
+ key = "ns1.he.net";
+ address = [ "2001:470:600::2" "216.218.133.2" ];
+ action = "transfer";
+ }
+ {
+ id = "localhost";
+ address = [ listen_addr ];
+ update-type = [ "A" "AAAA" ];
+ action = "update";
+ }
+ {
+ id = "acme";
+ address = [ listen_addr ];
+ update-type = [ "TXT" ];
+ action = "update";
+ }
+ ];
+
+ mod-rrl = [{
+ id = "default";
+ rate-limit = 200;
+ slip = 2;
+ }];
+
+ template = [
+ {
+ id = "default";
+ semantic-checks = "on";
+ global-module = "mod-rrl/default";
+ }
+ {
+ id = "master";
+ semantic-checks = "on";
+
+ dnssec-signing = "on";
+ dnssec-policy = "gtld-servers.net";
+
+ notify = [ "ns1.he.net" ];
+ acl = [ "ns1.he.net" "localhost" ];
+
+ zonefile-sync = "-1";
+ zonefile-load = "difference";
+ }
+ {
+ id = "acme";
+ semantic-checks = "on";
+ acl = [ "acme" ];
+
+ zonefile-sync = "-1";
+ zonefile-load = "difference";
+ journal-content = "changes";
+ }
+ ];
+
+ zone = [
+ {
+ domain = "sinanmohd.com";
+ file = ./sinanmohd.com.zone;
+ template = "master";
+ }
+ {
+ domain = "_acme-challenge.sinanmohd.com";
+ file = acmeSOA;
+ template = "acme";
+ }
+ {
+ domain = "5.6.e.e.0.7.4.0.1.0.0.2.ip6.arpa";
+ file = ./5.6.e.e.0.7.4.0.1.0.0.2.ip6.arpa.zone;
+ }
+ ];
+ };
+ };
+
+}
diff --git a/os/kay/modules/dns/sinanmohd.com.zone b/os/kay/modules/dns/sinanmohd.com.zone
new file mode 100644
index 0000000..0409efc
--- /dev/null
+++ b/os/kay/modules/dns/sinanmohd.com.zone
@@ -0,0 +1,46 @@
+$ORIGIN sinanmohd.com.
+$TTL 2d
+
+@ IN SOA ns1 hostmaster (
+ 2024022700 ; serial
+ 2h ; refresh
+ 5m ; retry
+ 1d ; expire
+ 5m ) ; nx ttl
+
+ IN NS ns1
+ IN NS ns2.he.net.
+ IN NS ns3.he.net.
+ IN NS ns4.he.net.
+ IN NS ns5.he.net.
+
+ 30 IN A 127.0.0.1
+ 30 IN AAAA ::1
+
+ IN MX 10 mail
+
+ IN TXT "v=spf1 mx -all"
+_dmarc IN TXT "v=DMARC1; p=reject; rua=mailto:reports@sinanmohd.com; ruf=mailto:reports@sinanmohd.com; adkim=s; aspf=s"
+
+ed25519._domainkey IN TXT "v=DKIM1; k=ed25519; p=EHk924AruF9Y0Xaf009rpRl+yGusjmjT1Zeho67BnDU="
+rsa._domainkey IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4HEqO63fSC0cUnJt9vAQBssTkPfT4QefmAK/1BtAIRIOdGakf7PI7p3A1ETgwfYxuHj7BUSzUtESsHMThbhB1Wko79+AR+5ZBDBmD8CE0dOnZfzeG8xIaGfYkaL4gana6YZWiBT2oi/CimJfc22wacF01SufOs4R8cDpy4BZIgDD/zfF4bFTORQ0vMSJQJkp1zdQelERDU5CEezgxgVYgoSmdEpgkhc23PJSyj4Z7hA69N0amsb3cVVrfVXcYvSqTK3S2vLLA89ws4CUjCCpUW40gVIP8QP6CqTL76936Oo7OVWgmV3Sn3wa8FMN6IATY+fbMlrdOMsPY5PauJyEoQIDAQAB"
+
+ns1 IN AAAA 2001:470:ee65::1
+
+mail 30 IN A 127.0.0.1
+mail IN AAAA 2001:470:ee65::1337
+smtp IN CNAME @
+imap IN CNAME @
+mta-sts IN CNAME @
+
+_mta-sts IN TXT "v=STSv1; id=2024022500"
+_smtp._tls IN TXT "v=TLSRPTv1; rua=mailto:reports@sinanmohd.com"
+
+www IN CNAME @
+git IN CNAME @
+bin IN CNAME @
+static IN CNAME @
+
+lia IN A 65.0.3.127
+
+_acme-challenge IN NS ns1
diff --git a/os/kay/modules/hurricane.nix b/os/kay/modules/hurricane.nix
new file mode 100644
index 0000000..9e22bf5
--- /dev/null
+++ b/os/kay/modules/hurricane.nix
@@ -0,0 +1,115 @@
+{ config, pkgs, lib, ... }:
+
+let
+ iface = "hurricane";
+ remote = "216.218.221.42";
+
+ clinet = "2001:470:35:72a::2";
+ server = "2001:470:35:72a::1";
+
+ prefix64 = "2001:470:36:72a::/64";
+ prefix48 = "2001:470:ee65::/48";
+
+ makeAddr = prefix: host: let
+ split = lib.strings.splitString "/" prefix;
+ in {
+ address = "${lib.head split}${host}";
+ prefixLength = lib.toInt (lib.last split);
+ };
+in
+{
+ networking = {
+ sits.${iface} = {
+ inherit remote;
+ ttl = 225;
+ };
+ interfaces.${iface} = {
+ mtu = 1440; # 1460(ppp0) - 20
+ ipv6.addresses = [
+ {
+ address = clinet;
+ prefixLength = 64;
+ }
+
+ (makeAddr prefix64 "1")
+ (makeAddr prefix48 "1")
+ (makeAddr prefix48 "1337")
+ ];
+ };
+
+ iproute2 = {
+ enable = true;
+ rttablesExtraConfig = "200 hurricane";
+ };
+
+ firewall.extraCommands =
+ "iptables -A INPUT --proto 41 --source ${remote} --jump ACCEPT";
+ };
+
+ sops.secrets = {
+ "hurricane/username" = {};
+ "hurricane/update_key" = {};
+ "hurricane/tunnel_id" = {};
+ };
+
+ systemd.services."network-route-${iface}" = {
+ description = "Routing configuration of ${iface}";
+ wantedBy = [
+ "network-setup.service"
+ "network.target"
+ ];
+ before = [ "network-setup.service" ];
+ bindsTo = [ "network-addresses-hurricane.service" ];
+ after = [ "network-pre.target" "network-addresses-hurricane.service" ];
+ # restart rather than stop+start this unit to prevent the
+ # network from dying during switch-to-configuration.
+ stopIfChanged = false;
+
+ serviceConfig = {
+ Type = "oneshot";
+ RemainAfterExit = true;
+ };
+
+ path = [ pkgs.iproute2 ];
+ script = ''
+ echo -n "adding route"
+
+ ip -6 rule add from ${clinet}/64 table hurricane || exit 1
+ ip -6 rule add from ${prefix64} table hurricane || exit 1
+ ip -6 rule add from ${prefix48} table hurricane || exit 1
+
+ ip -6 route add default via ${server} dev hurricane table hurricane || exit 1
+ '';
+ preStop = ''
+ echo -n "deleting route"
+
+ ip -6 route del default via ${server} dev hurricane table hurricane || exit 1
+
+ ip -6 rule del from ${prefix48} table hurricane || exit 1
+ ip -6 rule del from ${prefix64} table hurricane || exit 1
+ ip -6 rule del from ${clinet}/64 table hurricane || exit 1
+ '';
+ };
+
+
+ services.pppd.script."01-${iface}" = {
+ runtimeInputs = with pkgs; [ curl coreutils iproute2 iputils ];
+ text = ''
+ wan_ip="$4"
+ username="$(cat ${config.sops.secrets."hurricane/username".path})"
+ update_key="$(cat ${config.sops.secrets."hurricane/update_key".path})"
+ tunnel_id="$(cat ${config.sops.secrets."hurricane/tunnel_id".path})"
+
+ auth_url="https://$username:$update_key@ipv4.tunnelbroker.net/nic/update?hostname=$tunnel_id"
+ until curl --silent "$auth_url"; do
+ sleep 1
+ done
+
+ while [ ! -e /sys/class/net/${iface} ]; do
+ sleep 1 # make sure ${iface} is up
+ done
+
+ ip tunnel change ${iface} local "$wan_ip" mode sit
+ '';
+ };
+}
diff --git a/os/kay/modules/iperf3.nix b/os/kay/modules/iperf3.nix
new file mode 100644
index 0000000..901a93d
--- /dev/null
+++ b/os/kay/modules/iperf3.nix
@@ -0,0 +1,10 @@
+{ ... }:
+
+{
+ services.iperf3 = {
+ enable = true;
+
+ bind = "10.0.0.1";
+ openFirewall = true;
+ };
+}
diff --git a/os/kay/modules/mail.nix b/os/kay/modules/mail.nix
new file mode 100644
index 0000000..79e4019
--- /dev/null
+++ b/os/kay/modules/mail.nix
@@ -0,0 +1,110 @@
+{ config, ... }: let
+ ipv6 = "2001:470:ee65::1337";
+ domain = config.userdata.domain;
+
+ username = config.userdata.name;
+ secret = "$argon2i$v=19$m=4096,t=3,p=1$SWV5aWU3YWUgZWFTNm9oc28gTGFvdDdlRG8ga2FTaWVjaDYgYWV0aDFHb28$O/sDv7oy9wUxFjvKoxB5o8ZnPvjYJo9DjX0C/AZQFF0";
+ email = [
+ "${username}@${domain}"
+ "official@${domain}"
+
+ "postmaster@${domain}"
+ "hostmaster@${domain}"
+ ];
+
+ credentials_directory = "/run/credentials/stalwart-mail.service";
+in {
+ networking.firewall.allowedTCPPorts = [
+ 25 # smto
+ 465 # submission
+ 587 # submissions
+ 993 # imap ssl
+ 4190 # managesieve
+ ];
+
+ security.acme.certs.${domain}.postRun = "systemctl restart stalwart-mail.service";
+ sops.secrets = {
+ "mail.${domain}/dkim_rsa" = {};
+ "mail.${domain}/dkim_ed25519" = {};
+ };
+
+ services.stalwart-mail = {
+ enable = true;
+ loadCredential = [
+ "dkim_rsa:${config.sops.secrets."mail.${domain}/dkim_rsa".path}"
+ "dkim_ed25519:${config.sops.secrets."mail.${domain}/dkim_ed25519".path}"
+
+ "cert:${config.security.acme.certs.${domain}.directory}/fullchain.pem"
+ "key:${config.security.acme.certs.${domain}.directory}/key.pem"
+ ];
+
+ settings = {
+ macros = {
+ host = "mail.${domain}";
+ default_domain = domain;
+ default_directory = "in-memory";
+ default_store = "sqlite";
+ };
+
+ queue.outbound = {
+ ip-strategy = "ipv6_then_ipv4";
+ source-ip.v6 = "['${ipv6}']";
+ tls.starttls = "optional";
+ };
+ server.listener = {
+ smtp.bind = [ "[${ipv6}]:25" "0.0.0.0:25" ];
+ jmap.bind = [ "[::]:8034" ];
+ };
+
+ signature = {
+ rsa = {
+ private-key = "file://${credentials_directory}/dkim_rsa";
+ selector = "rsa";
+ set-body-length = true;
+ };
+ ed25519 = {
+ public-key = "EHk924AruF9Y0Xaf009rpRl+yGusjmjT1Zeho67BnDU=";
+ private-key = "file://${credentials_directory}/dkim_ed25519";
+ domain = "%{DEFAULT_DOMAIN}%";
+ selector = "ed25519";
+ headers = [ "From" "To" "Date" "Subject" "Message-ID" ];
+ algorithm = "ed25519-sha256";
+ canonicalization = "relaxed/relaxed";
+ set-body-length = true;
+ report = true;
+ };
+ };
+
+ certificate."default" = {
+ cert = "file://${credentials_directory}/cert";
+ private-key = "file://${credentials_directory}/key";
+ };
+
+ storage.blob = "fs";
+ store = {
+ fs.disable = false;
+ sqlite.disable = false;
+ };
+
+ directory."in-memory" = {
+ type = "memory";
+ options.subaddressing = true;
+
+ principals = [
+ {
+ inherit email;
+ inherit secret;
+ name = username;
+ type = "admin";
+ }
+ { # for mta-sts & dmarc reports
+ email = "reports${domain}";
+ inherit secret;
+ name = "reports";
+ type = "individual";
+ }
+ ];
+ };
+ };
+ };
+}
diff --git a/os/kay/modules/matrix-sliding-sync.nix b/os/kay/modules/matrix-sliding-sync.nix
new file mode 100644
index 0000000..ebdc34d
--- /dev/null
+++ b/os/kay/modules/matrix-sliding-sync.nix
@@ -0,0 +1,18 @@
+{ config, ... }:
+
+let
+ domain = config.userdata.domain;
+in
+{
+ sops.secrets."matrix-${domain}/sliding_sync" = {};
+
+ services.matrix-sliding-sync = {
+ enable = true;
+ environmentFile = config.sops.secrets."matrix-${domain}/sliding_sync".path;
+
+ settings = {
+ SYNCV3_LOG_LEVEL = "warn";
+ SYNCV3_SERVER = "http://127.0.0.1:${toString config.services.dendrite.httpPort}";
+ };
+ };
+}
diff --git a/os/kay/modules/network.nix b/os/kay/modules/network.nix
new file mode 100644
index 0000000..929fb1b
--- /dev/null
+++ b/os/kay/modules/network.nix
@@ -0,0 +1,82 @@
+{ config, ... }:
+
+let
+ inetVlan = 722;
+ voipVlan = 1849;
+ wanInterface = "enp4s0";
+ nameServer = "1.0.0.1";
+in
+{
+ imports = [
+ ./router.nix
+ ./hurricane.nix
+ ];
+
+ sops.secrets = {
+ "ppp/chap-secrets" = {};
+ "ppp/pap-secrets" = {};
+ "ppp/username" = {};
+ };
+
+ networking = let
+ voipVlanIface = "voip";
+ in {
+ vlans = {
+ wan = {
+ id = inetVlan;
+ interface = wanInterface;
+ };
+ ${voipVlanIface} = {
+ id = voipVlan;
+ interface = wanInterface;
+ };
+ };
+
+ interfaces.${voipVlanIface}.useDHCP = true;
+ dhcpcd.extraConfig = ''
+ interface ${voipVlanIface}
+ ipv4only
+ nogateway
+ '';
+ };
+
+ services = {
+ dnsmasq = {
+ enable = true;
+ settings = {
+ server = [ nameServer ];
+ bind-interfaces = true;
+ };
+ };
+
+ pppd = {
+ enable = true;
+
+ config = ''
+ plugin pppoe.so
+ debug
+
+ nic-wan
+ defaultroute
+ ipv6 ::1,
+ noauth
+
+ persist
+ lcp-echo-adaptive
+ lcp-echo-interval 1
+ lcp-echo-failure 5
+ '';
+
+ peers.bsnl = {
+ enable = true;
+ autostart = true;
+ configFile = config.sops.secrets."ppp/username".path;
+ };
+
+ secret = {
+ chap = config.sops.secrets."ppp/chap-secrets".path;
+ pap = config.sops.secrets."ppp/pap-secrets".path;
+ };
+ };
+ };
+}
diff --git a/os/kay/modules/router.nix b/os/kay/modules/router.nix
new file mode 100644
index 0000000..2254c3b
--- /dev/null
+++ b/os/kay/modules/router.nix
@@ -0,0 +1,43 @@
+{ ... }:
+
+let
+ lanInterface = "enp0s20u1";
+ wanInterface = "ppp0";
+ subnet = "10.0.0.0";
+ prefix = 24;
+ host = "10.0.0.1";
+ leaseRangeStart = "10.0.0.100";
+ leaseRangeEnd = "10.0.0.254";
+in
+{
+ imports = [
+ ./wireguard.nix
+ ./iperf3.nix
+ ];
+
+ networking = {
+ nat = {
+ enable = true;
+ externalInterface = wanInterface;
+ internalInterfaces = [ lanInterface ];
+ };
+ interfaces."${lanInterface}" = {
+ ipv4.addresses = [{
+ address = host;
+ prefixLength = prefix;
+ }];
+ };
+ firewall = {
+ allowedUDPPorts = [ 53 67 ];
+ allowedTCPPorts = [ 53 ];
+ extraCommands = ''
+ iptables -t nat -I POSTROUTING 1 -s ${subnet}/${toString prefix} -o ${wanInterface} -j MASQUERADE
+ '';
+ };
+ };
+
+ services.dnsmasq.settings = {
+ dhcp-range = [ "${leaseRangeStart},${leaseRangeEnd}" ];
+ interface = [ lanInterface ];
+ };
+}
diff --git a/os/kay/modules/sftp.nix b/os/kay/modules/sftp.nix
new file mode 100644
index 0000000..bbe055e
--- /dev/null
+++ b/os/kay/modules/sftp.nix
@@ -0,0 +1,44 @@
+{ config, ... }:
+
+let
+ storage = "/hdd/users";
+ user = config.userdata.name;
+ pubKeys = config.users.users.${user}.openssh.authorizedKeys.keys;
+in
+{
+ users = {
+ groups."sftp".members = [];
+
+ users."sftp" = {
+ group = "sftp";
+ shell = "/run/current-system/sw/bin/nologin";
+ isNormalUser = true;
+ openssh.authorizedKeys.keys = [
+ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFmA1dyV+o9gfoxlbVG0Y+dn3lVqdFs5fMqfxyNc5/Lr sftp@cez"
+ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDCbgjAfyDNtLNyOS+sfLirYtfEAkGqV54LOwabpWkvf sftp@veu"
+ ] ++ pubKeys;
+ };
+
+ users."nazer" = {
+ group = "sftp";
+ shell = "/run/current-system/sw/bin/nologin";
+ isNormalUser = true;
+ openssh.authorizedKeys.keys = [
+ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICV09w9Ovk9wk4Bhn/06iOn+Ss8lK3AmQAl8+lXHRycu nazu@pc"
+ ];
+ };
+ };
+
+ services.openssh.extraConfig = ''
+ Match Group sftp
+ # chroot dir should be owned by root
+ # and sub dirs by %u
+ ChrootDirectory ${storage}/%u
+ ForceCommand internal-sftp
+
+ PermitTunnel no
+ AllowAgentForwarding no
+ AllowTcpForwarding no
+ X11Forwarding no
+ '';
+}
diff --git a/os/kay/modules/sshfwd.nix b/os/kay/modules/sshfwd.nix
new file mode 100644
index 0000000..d70b893
--- /dev/null
+++ b/os/kay/modules/sshfwd.nix
@@ -0,0 +1,29 @@
+{ ... }: let
+ group = "sshfwd";
+in {
+ networking.firewall.allowedTCPPorts = [ 2222 ];
+
+ users = {
+ groups.${group}.members = [];
+
+ users."lia" = {
+ inherit group;
+ isSystemUser = true;
+
+ openssh.authorizedKeys.keys
+ = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAe7fJlh9L+9JSq0+hK7jNZjszmZqNXwzqcZ+zx0yJyU lia" ];
+ };
+ };
+
+ services.openssh.extraConfig = ''
+ Match Group ${group}
+ ForceCommand echo 'this account is only usable for remote forwarding'
+ PermitTunnel no
+ AllowAgentForwarding no
+ X11Forwarding no
+
+ AllowTcpForwarding remote
+ GatewayPorts clientspecified
+ PermitListen *:2222
+ '';
+}
diff --git a/os/kay/modules/wireguard.nix b/os/kay/modules/wireguard.nix
new file mode 100644
index 0000000..578a86a
--- /dev/null
+++ b/os/kay/modules/wireguard.nix
@@ -0,0 +1,57 @@
+{ config, ... }:
+
+let
+ wgInterface = "wg";
+ wanInterface = "ppp0";
+ subnet = "10.0.1.0";
+ prefix = 24;
+ port = 51820;
+in
+{
+ sops.secrets."misc/wireguard" = {};
+
+ networking = {
+ nat = {
+ enable = true;
+ externalInterface = wanInterface;
+ internalInterfaces = [ wgInterface ];
+ };
+ firewall = {
+ allowedUDPPorts = [ port ];
+ extraCommands = ''
+ iptables -t nat -I POSTROUTING 1 -s ${subnet}/${toString prefix} -o ${wanInterface} -j MASQUERADE
+ '';
+ };
+
+ wireguard.interfaces.${wgInterface} = {
+ ips = [ "10.0.1.1/${toString prefix}" ];
+ listenPort = port;
+ mtu = 1380; # 1460 (ppp0) - 80
+ privateKeyFile = config.sops.secrets."misc/wireguard".path;
+
+ peers = [
+ { # cez
+ publicKey = "IcMpAs/D0u8O/AcDBPC7pFUYSeFQXQpTqHpGOeVpjS8=";
+ allowedIPs = [ "10.0.1.2/32" ];
+ }
+ { # veu
+ publicKey = "bJ9aqGYD2Jh4MtWIL7q3XxVHFuUdwGJwO8p7H3nNPj8=";
+ allowedIPs = [ "10.0.1.3/32" ];
+ }
+ { # dad
+ publicKey = "q70IyOS2IpubIRWqo5sL3SeEjtUy2V/PT8yqVExiHTQ=";
+ allowedIPs = [ "10.0.1.4/32" ];
+ }
+ { # shambai
+ publicKey = "YYDlp/bNKkqFHAhdgaZ2SSEMnIjKTqPTK7Ju6O9/1gY=";
+ allowedIPs = [ "10.0.1.5/32" ];
+ }
+ ];
+ };
+ };
+
+ services.dnsmasq.settings = {
+ no-dhcp-interface = wgInterface;
+ interface = [ wgInterface ];
+ };
+}
diff --git a/os/kay/modules/www.nix b/os/kay/modules/www.nix
new file mode 100644
index 0000000..3891bf6
--- /dev/null
+++ b/os/kay/modules/www.nix
@@ -0,0 +1,134 @@
+{ config, pkgs, lib, ... }:
+
+let
+ domain = config.userdata.domain;
+ fscusat = "fscusat.org";
+ mark = "themark.ing";
+ storage = "/hdd/users/sftp/shr";
+in
+{
+ imports = [
+ ./dendrite.nix
+ ./matrix-sliding-sync.nix
+ ./cgit.nix
+ ];
+
+ security.acme.certs.${domain}.postRun = "systemctl reload nginx.service";
+ networking.firewall = {
+ allowedTCPPorts = [ 80 443 ];
+ allowedUDPPorts = [ 443 ];
+ };
+
+ services.nginx = {
+ enable = true;
+ package = pkgs.nginxQuic;
+ enableQuicBPF = true;
+
+ recommendedTlsSettings = true;
+ recommendedZstdSettings = true;
+ recommendedOptimisation = true;
+ recommendedGzipSettings = true;
+ recommendedProxySettings = true;
+ recommendedBrotliSettings = true;
+ eventsConfig = "worker_connections 1024;";
+
+ virtualHosts = let
+ defaultOpts = {
+ quic = true;
+ http3 = true;
+ forceSSL = true;
+ useACMEHost = domain;
+ };
+ in {
+ "${domain}" = defaultOpts // {
+ default = true;
+ globalRedirect = "www.${domain}";
+
+ extraConfig = ''
+ client_max_body_size ${toString
+ config.services.dendrite.settings.media_api.max_file_size_bytes
+ };
+ '';
+
+ locations = {
+ "/.well-known/matrix/server".return = ''
+ 200 '{ "m.server": "${domain}:443" }'
+ '';
+
+ "/.well-known/matrix/client".return = ''
+ 200 '${builtins.toJSON {
+ "m.homeserver".base_url = "https://${domain}";
+ "org.matrix.msc3575.proxy".url = "https://${domain}";
+ }}'
+ '';
+
+ "/_matrix".proxyPass = "http://127.0.0.1:${toString
+ config.services.dendrite.httpPort
+ }";
+
+ "/_matrix/client/unstable/org.matrix.msc3575/sync".proxyPass =
+ "http://${config.services.matrix-sliding-sync.settings.SYNCV3_BINDADDR}";
+ };
+ };
+
+ "www.${domain}" = defaultOpts // {
+ root = "/var/www/${domain}";
+ };
+
+ "git.${domain}" = defaultOpts;
+
+ "bin.${domain}" = defaultOpts // {
+ root = "${storage}/bin";
+ locations."= /".return = "307 https://www.${domain}";
+ };
+
+ "static.${domain}" = defaultOpts // {
+ root = "${storage}/static";
+ locations."= /".return = "301 https://www.${domain}";
+ };
+
+ "${fscusat}" = defaultOpts // {
+ useACMEHost = null;
+ enableACME = true;
+
+ globalRedirect = "www.${fscusat}";
+ };
+ "www.${fscusat}" = defaultOpts // {
+ useACMEHost = null;
+ enableACME = true;
+
+ locations."/" = {
+ return = "200 '<h1>under construction</h1>'";
+ extraConfig = "add_header Content-Type text/html;";
+ };
+ };
+
+ "${mark}" = defaultOpts // {
+ useACMEHost = null;
+ enableACME = true;
+
+ globalRedirect = "www.${mark}";
+ };
+ "www.${mark}" = defaultOpts // {
+ useACMEHost = null;
+ enableACME = true;
+
+ locations."/" = {
+ return = "200 '<h1>under construction, see you soon</h1>'";
+ extraConfig = "add_header Content-Type text/html;";
+ };
+ };
+
+ "mta-sts.${domain}" = defaultOpts // {
+ locations."= /.well-known/mta-sts.txt".return = ''200 "${
+ lib.strings.concatStringsSep "\\n" [
+ "version: STSv1"
+ "mode: enforce"
+ "mx: mail.${domain}"
+ "max_age: 86400"
+ ]
+ }"'';
+ };
+ };
+ };
+}
diff --git a/os/kay/secrets.yaml b/os/kay/secrets.yaml
new file mode 100644
index 0000000..47be11b
--- /dev/null
+++ b/os/kay/secrets.yaml
@@ -0,0 +1,47 @@
+ppp:
+ chap-secrets: ENC[AES256_GCM,data:oTwucN94iWIzrCCAQySpkG+uEBERmEjXfoPm6piook8bS/q3kCd/DQ==,iv:IC1Ii+rnTvFa0F2bi0fnEAEO7XWV7Wues9T+28bhDnc=,tag:239vrwVzeTIVCIw8U30jtg==,type:str]
+ pap-secrets: ENC[AES256_GCM,data:S72mx8AP8MDWrYZ3TIOnwoKcVWiUzms1ZpckghHjjFcWhW5orOjPOA==,iv:4kNHSZ3+FMA9ROLEgrU38IWd+MBt+vf8CV3WGHkRCCc=,tag:rBtSZH8i7fE7fJhRRda7eA==,type:str]
+ username: ENC[AES256_GCM,data:GzRdyvnRKSS8iH+RuFU9g6zxXhxl0DeWWkAyF3sefZc0QQ==,iv:yTRruKpMda4N2J3Z8MEesrFxqV4g1usbYoxTeKlWf4M=,tag:8h9cpYn2Zy/32+2HJ76dFw==,type:str]
+hurricane:
+ username: ENC[AES256_GCM,data:pe3igN9AIbc1,iv:stBkppjkDC9nvV/fHaEtfs6KskoiqqEKxCp/KC+Xxeo=,tag:pH5CJXOOp/is7dQmt6wlog==,type:str]
+ update_key: ENC[AES256_GCM,data:wwd+QWTgKEqstY5d2eWBnWJYq2EisTTaa/Ow4WwBNkyh5FYP+7PEyg==,iv:b93JvsfWppqlJtZxGAa3xbXgLEFs0A5Seq5pNjTnRW4=,tag:+W1t1M+Mm4LopVbcI1x+eg==,type:str]
+ tunnel_id: ENC[AES256_GCM,data:WUDOxjmA,iv:W8k0pyrAQz+UWtm76uvmzodJ2lZG4ioxrVMWjX1kIVM=,tag:2Q25MXzlptg/rc0HQ1k6rg==,type:str]
+dns: ENC[AES256_GCM,data:Pa6Oo7UFDqo5ZN+eyz9MKy0p4KU1ePTpWQ+R8PuSFO9JjFt/I86ru/qSKyymIzhJcjj5hXMT2LPjk4MH8BWaO39ACsPDSD09xA6e1GO0rvsvtB9cffuz/GnfveyHmev+7xzdriD4IHqINPE=,iv:zuSfHnmxrjFCX3DJSRxLDs/3IVBRnkn3crar1pCW1EU=,tag:rZ0TlMMsOCF3Shunx8PnfA==,type:str]
+matrix-sinanmohd.com:
+ key: ENC[AES256_GCM,data:xsSYua3g+ySUVBtfVZ2uZR4761MC5LeJGxmcgf+dWb5+tBSmgzAQL9FFcl7GLzhTmvlq13lARUr599wShS/C9IyMVGOOT9A8hxLFF9Kak64hmM7ERGrwbmzBY1mdTtvibJqzHaeybUVIMbDagczF54zpjDGLmdC5V84wduPFCndSA5FW+4Hhqw==,iv:KJtqrGNPgMDR6Sg/fOUzVAiwnPZwve9wpVfDQPc4g/c=,tag:E2jlbt5WbRA9wu16Lr69Bg==,type:str]
+ sliding_sync: ENC[AES256_GCM,data:ubFeb/OgYYHaIHVky6KS3icORbpqf7PO3p8bONA8mwG8vU1LB0TDqVm6vQTa8G9pe96JzJ8+IAgSZafG9PaEJc/Bpj53aWRFO3HEV0Pj,iv:P8VD8utVEwNoeQEZUdS2R9GuDe20nKiXYCfKJl0Id3E=,tag:VksV/4IaKN0C2g/alw6r4Q==,type:str]
+mail.sinanmohd.com:
+ dkim_rsa: ENC[AES256_GCM,data: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,iv:dPnpNUPSDiq5C14YzDM2K4mFHNRFgc6p+X3Zu33OH60=,tag:MhgfV3z1wcbAfpwZmVWczw==,type:str]
+ dkim_ed25519: ENC[AES256_GCM,data:bberg3vGG9M3iPH1aLA+wIU6KNnxHRZxpGU5zT5Gqo9lohQa1wBDXCwsP0JaSfg56dhh9ZxF5HFd4V0nUzL6QMIeiExGkZmtdluaqki3fwFCssILch9pWOuM71Q1d7vi1eIN5PrAuX+6m8bmQBd1JIR+Kbz8dQ==,iv:C7wEFU7/xCh8LzyKXHSzgTX/L9OkmGWTnl5A94GLogw=,tag:j+sYtzzGN9guWa6T+ZUzbw==,type:str]
+ sinan: ENC[AES256_GCM,data:F3lhwjf6dZpDSmU=,iv:TCIzQeUBqgjqc+/z3Hh1tYpm3OeLGLpVUDeo6ufP7/4=,tag:TXUI8noaK5jyLpo8D+94jQ==,type:str]
+misc:
+ wireguard: ENC[AES256_GCM,data:kbUtxJv3xSmikJWgtu87TSo5N8tUb2BiH3dH3oOV36waYyXI3bp2aBeAl1k=,iv:yB4UIyMDNRS+JmSnt9XuBhNRTLz+k0FqkK4ofjosRto=,tag:BDSD9SfQuQppKT4+6Cu65w==,type:str]
+sops:
+ kms: []
+ gcp_kms: []
+ azure_kv: []
+ hc_vault: []
+ age:
+ - recipient: age1q5sfy74d53n6jxlgsc2zrsz4wcl9d830nxuagc3wfmdkrrp55ckq9ev6nv
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2T3NSZ09xUDg5Q2VKM3FB
+ RXNwNTJrVkxScHR2eksrVlZQMFduOGRFT1RFClhQK2xTWXBUMzdlektSWFhHNDBN
+ bEMxelVjK1owZHczMVV3MWI2WlU2TncKLS0tIEovSk1uMnlvWFBya1YxNjArQTdh
+ Unk0a0tvR3VZQmtIU3RZSWNnazZJZTgKe0mjQHEkagnftc2zEbza863dSlnPOM6Q
+ 0Me0paRmqzsYBizp12SHjaXYiXFpvEeGmOVOMoGvD8UzTa+V5klS0w==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age15989j5lkkf2kn5wa2p6qc8wlxjjksc63k5ync8rz8t4e87394pzqm7h4rm
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5NDVlc2crekF2b1lVZnZM
+ YU95N3lRWFhUUzczV1h4eUU0dHdSbWdpWVhZCmREdmFDSzRzY3pZUHpERkhCK1FS
+ cmxRam1vZ2U0dHBYc3hJWG9CRW13bzgKLS0tIFBpMFFXYTZDT09mTTJkWDhoYWVr
+ OXgwSml4bkc1dnloNUFsRGFFcXFHc2cK26l2eiKbZUkogmAXoha6HTUs3YFKixYz
+ bTkpKKyOAIIin3YM975wwvkCuWNG4tbnHBHQFh5JGK2OEyLDXuV7Pg==
+ -----END AGE ENCRYPTED FILE-----
+ lastmodified: "2024-02-25T04:23:28Z"
+ mac: ENC[AES256_GCM,data:SUFBHKTM2tQHX1Xtta3spl/GaaNrIAcNrLFzKzqb2ki3FhXnLLYu0wD+IBxuj1nxICn9TDprHFdcDenfFPV1mYWtmXLmWMeDcIGKXedYex2nakdlIYngGiLkEseuehft46YtoEqLJVksBFoLKmywRi+/ZGux/heSIyD14Toxb3Q=,iv:dqYGObF1SV3VBxSZtrggRdD1ROqvlp7tn8xLdNuDxx4=,tag:N/4L6NgIqYKQ8IbpFGru2g==,type:str]
+ pgp: []
+ unencrypted_suffix: _unencrypted
+ version: 3.8.1
diff --git a/os/lia/configuration.nix b/os/lia/configuration.nix
new file mode 100644
index 0000000..ab4c46b
--- /dev/null
+++ b/os/lia/configuration.nix
@@ -0,0 +1,14 @@
+{ ... }:
+
+{
+ imports = [
+ ../common/configuration.nix
+ ./hardware-configuration.nix
+
+ ./modules/network
+ ./modules/users.nix
+ ./modules/lxc.nix
+ ./modules/sshfwd.nix
+ ];
+}
+
diff --git a/os/lia/hardware-configuration.nix b/os/lia/hardware-configuration.nix
new file mode 100644
index 0000000..8417070
--- /dev/null
+++ b/os/lia/hardware-configuration.nix
@@ -0,0 +1,29 @@
+{ modulesPath, ... }:
+
+{
+ imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
+
+ boot = {
+ loader.systemd-boot.enable = true;
+ kernelModules = [ "kvm-amd" ];
+
+ initrd.availableKernelModules = [
+ "xhci_pci"
+ "ahci"
+ "usb_storage"
+ "usbhid"
+ "sd_mod"
+ ];
+ };
+
+ fileSystems = {
+ "/" = {
+ device = "/dev/disk/by-uuid/9ad3550b-8c9a-4541-8fac-7af185599446";
+ fsType = "ext4";
+ };
+ "/boot" = {
+ device = "/dev/disk/by-uuid/6111-05EC";
+ fsType = "vfat";
+ };
+ };
+}
diff --git a/os/lia/modules/lxc.nix b/os/lia/modules/lxc.nix
new file mode 100644
index 0000000..259c316
--- /dev/null
+++ b/os/lia/modules/lxc.nix
@@ -0,0 +1,41 @@
+{ pkgs, ... }: let
+ container = {
+ name = "ubu";
+ distro = "ubuntu";
+ release = "jammy";
+ };
+
+ bridge = "lan";
+in {
+ virtualisation.lxc.enable = true;
+
+ environment.systemPackages = with pkgs; [ wget ];
+ systemd.services."lxc-${container.name}-provision" = {
+ description = "auto provision ${container.name} lxc container";
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network-online.target" ];
+ wants = [ "network-online.target" ];
+ stopIfChanged = false;
+
+ serviceConfig = {
+ Type = "oneshot";
+ RemainAfterExit = true;
+ };
+
+ path = with pkgs; [ wget lxc util-linux gnutar xz gawk ];
+ script = ''
+ if ! lxc-ls | grep -q ${container.name}; then
+ lxc-create -n ${container.name} -t download -- \
+ --arch amd64 \
+ --release ${container.release} \
+ --dist ${container.distro}
+
+ sed 's/lxcbr0/${bridge}/g' -i /var/lib/lxc/${container.name}/config
+ fi
+
+ lxc-start -n ${container.name}
+ '';
+
+ preStop = "lxc-stop --name ${container.name}";
+ };
+}
diff --git a/os/lia/modules/network/default.nix b/os/lia/modules/network/default.nix
new file mode 100644
index 0000000..c8d9059
--- /dev/null
+++ b/os/lia/modules/network/default.nix
@@ -0,0 +1,19 @@
+{ ... }: let
+ wan = "enp9s0";
+in
+{
+ imports = [
+ ./router.nix
+ ];
+
+ networking = {
+ interfaces.${wan}.ipv4.addresses = [{
+ address = "172.16.148.20";
+ prefixLength = 22;
+ }];
+ defaultGateway = {
+ address = "172.16.148.1";
+ interface = wan;
+ };
+ };
+}
diff --git a/os/lia/modules/network/router.nix b/os/lia/modules/network/router.nix
new file mode 100644
index 0000000..b8cac8c
--- /dev/null
+++ b/os/lia/modules/network/router.nix
@@ -0,0 +1,47 @@
+{ ... }: let
+ wanInterface = "enp9s0";
+ lanInterfaces = [ "enp1s0f0" "enp1s0f1" ];
+
+ prefix = 24;
+ subnet = "192.168.1.0";
+ host = "192.168.1.1";
+
+ leaseRangeStart = "192.168.1.100";
+ leaseRangeEnd = "192.168.1.254";
+ nameServer = [ "10.0.0.2" "10.0.0.3" ];
+in
+{
+ networking = {
+ bridges."lan".interfaces = lanInterfaces;
+
+ nat = {
+ enable = true;
+ externalInterface = wanInterface;
+ internalInterfaces = [ "lan" ];
+ };
+
+ interfaces.lan = {
+ ipv4.addresses = [{
+ address = host;
+ prefixLength = prefix;
+ }];
+ };
+
+ firewall = {
+ allowedUDPPorts = [ 53 67 ];
+ allowedTCPPorts = [ 53 ];
+ extraCommands =
+ "iptables -t nat -I POSTROUTING 1 -s ${subnet}/${toString prefix} -o ${wanInterface} -j MASQUERADE";
+ };
+ };
+
+ services.dnsmasq = {
+ enable = true;
+
+ settings = {
+ server = nameServer;
+ dhcp-range = [ "${leaseRangeStart},${leaseRangeEnd}" ];
+ interface = [ "lan" ];
+ };
+ };
+}
diff --git a/os/lia/modules/sshfwd.nix b/os/lia/modules/sshfwd.nix
new file mode 100644
index 0000000..3c7c006
--- /dev/null
+++ b/os/lia/modules/sshfwd.nix
@@ -0,0 +1,53 @@
+{ pkgs, config, ... }: let
+ mkFwdSrv = {
+ local_port,
+ remote_port,
+ remote_user,
+ remote ? "sinanmohd.com",
+ ssh_port ? 22,
+ key ? config.sops.secrets."sshfwd/${remote}".path,
+ }: {
+ "sshfwd-${toString local_port}-${remote}:${toString remote_port}" = {
+ description = "Forwarding port ${toString local_port} to ${remote}";
+
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network-online.target" ];
+ wants = [ "network-online.target" ];
+ # restart rather than stop+start this unit to prevent
+ # the ssh from dying during switch-to-configuration.
+ stopIfChanged = false;
+
+ serviceConfig = {
+ ExecStart = ''
+ ${pkgs.openssh}/bin/ssh -N ${remote_user}@${remote} -p ${toString ssh_port} \
+ -R '[::]:${toString remote_port}:127.0.0.1:${toString local_port}' \
+ -o ServerAliveInterval=15 \
+ -o ExitOnForwardFailure=yes \
+ -i ${key}
+ '';
+
+ RestartSec = 3;
+ Restart = "always";
+ };
+
+ };
+ };
+in {
+ sops.secrets."sshfwd/sinanmohd.com" = {};
+ sops.secrets."sshfwd/lia.sinanmohd.com" = {};
+
+ environment.systemPackages = with pkgs; [ openssh ];
+ systemd.services
+ = (mkFwdSrv {
+ local_port = 22;
+ remote_user = "lia";
+ remote_port = 2222;
+ }) //
+ (mkFwdSrv {
+ local_port = 22;
+ remote_port = 22;
+ ssh_port = 23;
+ remote_user = "root";
+ remote = "lia.sinanmohd.com";
+ });
+}
diff --git a/os/lia/modules/users.nix b/os/lia/modules/users.nix
new file mode 100644
index 0000000..26f5dc8
--- /dev/null
+++ b/os/lia/modules/users.nix
@@ -0,0 +1,18 @@
+{ pkgs, ... }: {
+ users.users = {
+ "rohit" = {
+ isNormalUser = true;
+ extraGroups = [ "wheel" ];
+
+ packages = with pkgs; [ git htop ];
+ openssh.authorizedKeys.keys =
+ [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOZcWF1zVyxsCdZ/j+h+RlHZlyhgY2Bky03847bxFNSH rohit@victus" ];
+ };
+
+ "sharu" = {
+ isNormalUser = true;
+ openssh.authorizedKeys.keys =
+ [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMAAaAUTiM3YY7E/7lq44aX+2U0IYhp2Qntu7hINcTjF sharu@lappie" ];
+ };
+ };
+}
diff --git a/os/lia/secrets.yaml b/os/lia/secrets.yaml
new file mode 100644
index 0000000..b2b5218
--- /dev/null
+++ b/os/lia/secrets.yaml
@@ -0,0 +1,32 @@
+sshfwd:
+ sinanmohd.com: ENC[AES256_GCM,data:ZB2qbUA4+AcYlIY6IaPf9aUdMV0ltdKveqVSNS2Nhq8h6kWheqWiaXgIK6vuN7oDHKomgVXWaVdxTf6OFvFQHCHMMqtm0KfvSJW+cdORpfZkEZuji5Ob/yQiNllyS8oAw9iT5YdyifLi7XkfD+dHbt+XWLQCMFPirJ8Lz6ynTYxV+N7Pu7yOhfCzPDYfqexW7Ymrjk0PI32OVgo+sE0obnASGW645dP4ydKOZM5xx9NGr/Oao2W5C61qdr2gUCoYQKZXkfItGRfCuWuCeh0ZmbxumS6Q1WeWUW09SY5NN24025TBoZgE+UdJIXuczAQy5wzpXYsDWwBXNod4gAhe76YgLydlYBpBHe6xN6OBgCewHkjCGkirHawmbYxkmJ40L6/lMFPjRmMV7yhj94Vsyx7NAW1H8yKVE/9typXUrIyxbxAOGrwy0TjlGYogAcZ7YYZ+ipmkqNlQ1pliA2Kha+2ZzPG0hV8NKhydNr0cz5ylfL4cQaAXxxg6YHOUYL0DGbfMXMpZKTt47TJcY72RWDaUr2RsmhJ+k2vNBDY3I01n9syWnlk80h2bs1ILJ5Ad3PP8Em8yGaXJLM+3,iv:VoDyy+h3UHL0YJPJ7rbgLTZZzIPCJTD8yBPXNxWjHqo=,tag:zGQXrE066SDMCwgZpC9/Pg==,type:str]
+ lia.sinanmohd.com: ENC[AES256_GCM,data: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,iv:t825d9WWByfMZXwrtKs2JBFVoEAoAXfYOBmlhWN45hU=,tag:ZVPiwtKwhdYzh4IQyzeb9Q==,type:str]
+sops:
+ kms: []
+ gcp_kms: []
+ azure_kv: []
+ hc_vault: []
+ age:
+ - recipient: age1q5sfy74d53n6jxlgsc2zrsz4wcl9d830nxuagc3wfmdkrrp55ckq9ev6nv
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxZzlrOEpXQmdLVyt1MFRS
+ Q2JUU0N1MVNzLzVLcWhMb25uL3VsLzJrdFRNCnI1OWZFTnpqc056M0RYd3gvS1Nr
+ N2VEU1kyU3JuYjhhaUtuajg2cjQ4LzQKLS0tIE5qZmlqVGN1WXhZWkw3dGwyNTdF
+ QTd0V2V3QVVHbnhRUUt6MkRzYm5zeEEKFkqGe6Eg1BEPLqMkxUg56hc+sn0p4KZV
+ kThyib3g0KsrHpQM05v4CK0h6qlf8HXwvwJVx9tis8Nck1IW3zS8Pw==
+ -----END AGE ENCRYPTED FILE-----
+ - recipient: age1l9kd320xj89vdr06u7ej8fhjrxl470t04trgwd3jwzczknf05aesv2pp8x
+ enc: |
+ -----BEGIN AGE ENCRYPTED FILE-----
+ YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6QzhPYXcxQ0lRS2VwaXQ4
+ V3JUVDJyenowSzhFenBKYlBEbGNXTFIxUjFNCjhmWm5aQ1lTcTJidzFiT2J4R2Ux
+ b2ZjTWQ5WWtOY1BpZHVJYzN4clNlU0kKLS0tIHpBWU5zQWNVTWZ0TTdSNFZodkVq
+ RG9hL2hlYjdaYTVJWVFlSE4xN1poUHcKe4BPaVEyc3W1hyu0jOQcEdZ1kl2aQLgZ
+ fHDs4kDeCcfJI/s5Cb/YD3cIp7HB6FBoe7LHiNiJbyJGR0wJecLqxg==
+ -----END AGE ENCRYPTED FILE-----
+ lastmodified: "2024-02-11T16:35:02Z"
+ mac: ENC[AES256_GCM,data:nsLGZ5wvmj25COI4G3BsS8dzwpa59zs85Ztm4eZaXITAdMjEgfmHR8eHItzchSijH+PRaJH+pZZNN3kpkDeujGYTiOzfc1t2dGA3Vx6XACCNaZs35vmvbB45VV07a5mjw/Wy3k0ZDOcRCHXQOQccaPshUMzU7FkXudm7PkvoyTM=,iv:Rgfaab+egy2/AwlM6ZMVA+7E5cqb/r9mI4ptMit/SKo=,tag:LVSYkTzTxBRAIFxDkB1asA==,type:str]
+ pgp: []
+ unencrypted_suffix: _unencrypted
+ version: 3.8.1