aboutsummaryrefslogtreecommitdiffstats
path: root/modules/by-name
diff options
context:
space:
mode:
Diffstat (limited to 'modules/by-name')
-rw-r--r--modules/by-name/ba/back/module.nix92
-rw-r--r--modules/by-name/ba/backup/module.nix91
-rw-r--r--modules/by-name/co/constants/module.nix96
-rw-r--r--modules/by-name/co/coredump/module.nix18
-rw-r--r--modules/by-name/dh/dhcpcd/module.nix18
-rw-r--r--modules/by-name/di/disko/module.nix78
-rw-r--r--modules/by-name/dn/dns/dns/default.nix13
-rw-r--r--modules/by-name/dn/dns/dns/types/default.nix16
-rw-r--r--modules/by-name/dn/dns/dns/types/record.nix75
-rw-r--r--modules/by-name/dn/dns/dns/types/records/A.nix19
-rw-r--r--modules/by-name/dn/dns/dns/types/records/AAAA.nix19
-rw-r--r--modules/by-name/dn/dns/dns/types/records/CAA.nix42
-rw-r--r--modules/by-name/dn/dns/dns/types/records/CNAME.nix27
-rw-r--r--modules/by-name/dn/dns/dns/types/records/DKIM.nix75
-rw-r--r--modules/by-name/dn/dns/dns/types/records/DMARC.nix108
-rw-r--r--modules/by-name/dn/dns/dns/types/records/DNAME.nix15
-rw-r--r--modules/by-name/dn/dns/dns/types/records/DNSKEY.nix63
-rw-r--r--modules/by-name/dn/dns/dns/types/records/DS.nix48
-rw-r--r--modules/by-name/dn/dns/dns/types/records/HTTPS.nix5
-rw-r--r--modules/by-name/dn/dns/dns/types/records/MTA-STS.nix42
-rw-r--r--modules/by-name/dn/dns/dns/types/records/MX.nix32
-rw-r--r--modules/by-name/dn/dns/dns/types/records/NS.nix24
-rw-r--r--modules/by-name/dn/dns/dns/types/records/OPENPGPKEY.nix18
-rw-r--r--modules/by-name/dn/dns/dns/types/records/PTR.nix92
-rw-r--r--modules/by-name/dn/dns/dns/types/records/SOA.nix65
-rw-r--r--modules/by-name/dn/dns/dns/types/records/SRV.nix51
-rw-r--r--modules/by-name/dn/dns/dns/types/records/SSHFP.nix39
-rw-r--r--modules/by-name/dn/dns/dns/types/records/SVCB.nix100
-rw-r--r--modules/by-name/dn/dns/dns/types/records/TLSA.nix50
-rw-r--r--modules/by-name/dn/dns/dns/types/records/TXT.nix24
-rw-r--r--modules/by-name/dn/dns/dns/types/records/default.nix43
-rw-r--r--modules/by-name/dn/dns/dns/types/records/dnssec.nix48
-rw-r--r--modules/by-name/dn/dns/dns/types/simple.nix9
-rw-r--r--modules/by-name/dn/dns/dns/types/zone.nix119
-rw-r--r--modules/by-name/dn/dns/dns/util/default.nix76
-rw-r--r--modules/by-name/dn/dns/module.nix86
-rw-r--r--modules/by-name/et/etesync/module.nix80
-rw-r--r--modules/by-name/fa/fail2ban/module.nix58
-rw-r--r--modules/by-name/ga/gallery/module.nix22
-rw-r--r--modules/by-name/gi/git-server/css.nix119
-rw-r--r--modules/by-name/gi/git-server/module.nix188
-rw-r--r--modules/by-name/im/impermanence/module.nix30
-rw-r--r--modules/by-name/in/invidious-router/module.nix70
-rw-r--r--modules/by-name/ma/mail/module.nix167
-rw-r--r--modules/by-name/ma/mastodon/module.nix128
-rw-r--r--modules/by-name/ma/mastodon/patches/0001-feat-treewide-Increase-character-limit-to-5000-in-me.patch40
-rw-r--r--modules/by-name/ma/matrix/module.nix179
-rw-r--r--modules/by-name/mi/miniflux/module.nix55
-rw-r--r--modules/by-name/mu/murmur/module.nix80
-rw-r--r--modules/by-name/ne/nextcloud/module.nix78
-rw-r--r--modules/by-name/ng/nginx/module.nix74
-rw-r--r--modules/by-name/ni/nix-sync/internal_module.nix299
-rw-r--r--modules/by-name/ni/nix-sync/module.nix108
-rw-r--r--modules/by-name/ni/nixconfig/module.nix28
-rw-r--r--modules/by-name/ns/nscd/module.nix25
-rw-r--r--modules/by-name/oo/oomd/module.nix19
-rw-r--r--modules/by-name/op/openssh/module.nix60
-rw-r--r--modules/by-name/pe/peertube/module.nix124
-rw-r--r--modules/by-name/po/postgresql/module.nix19
-rw-r--r--modules/by-name/re/redlib/module.nix41
-rw-r--r--modules/by-name/re/resolvconf/module.nix16
-rw-r--r--modules/by-name/ru/rust-motd/module.nix92
-rw-r--r--modules/by-name/sh/sharkey/module.nix298
-rw-r--r--modules/by-name/st/stalwart-mail/module.nix428
-rw-r--r--modules/by-name/st/stalwart-mail/settings.nix552
-rw-r--r--modules/by-name/sy/system-info/module.nix79
-rw-r--r--modules/by-name/ta/taskchampion-sync/module.nix34
-rw-r--r--modules/by-name/us/users/module.nix82
68 files changed, 0 insertions, 5508 deletions
diff --git a/modules/by-name/ba/back/module.nix b/modules/by-name/ba/back/module.nix
deleted file mode 100644
index d47ffce..0000000
--- a/modules/by-name/ba/back/module.nix
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- config,
- lib,
- vhackPackages,
- pkgs,
- ...
-}: let
- cfg = config.vhack.back;
-in {
- options.vhack.back = {
- enable = lib.mkEnableOption "Back issue tracker (inspired by tvix's panettone)";
-
- domain = lib.mkOption {
- type = lib.types.str;
- description = "The domain to host this `back` instance on.";
- };
-
- settings = {
- scan_path = lib.mkOption {
- type = lib.types.path;
- description = "The path to the directory under which all the repositories reside";
- };
- project_list = lib.mkOption {
- type = lib.types.path;
- description = "The path to the `projects.list` file.";
- };
-
- source_code_repository_url = lib.mkOption {
- description = "The url to the source code of this instance of back";
- default = "https://git.foss-syndicate.org/vhack.eu/nixos-server/tree/pkgs/by-name/ba/back";
- type = lib.types.str;
- };
-
- root_url = lib.mkOption {
- type = lib.types.str;
- description = "The url to this instance of back.";
- default = "https://${cfg.domain}";
- };
- };
- };
-
- config = lib.mkIf cfg.enable {
- systemd.services."back" = {
- description = "Back issue tracking system.";
- requires = ["network-online.target"];
- after = ["network-online.target"];
- wantedBy = ["default.target"];
-
- serviceConfig = {
- ExecStart = "${lib.getExe vhackPackages.back} ${(pkgs.formats.json {}).generate "config.json" cfg.settings}";
-
- # Ensure that the service can read the repository
- # FIXME(@bpeetz): This has the implied assumption, that all the exposed git
- # repositories are readable for the git group. This should not be necessary. <2024-12-23>
- User = "git";
- Group = "git";
-
- DynamicUser = true;
- Restart = "always";
-
- # Sandboxing
- ProtectSystem = "strict";
- ProtectHome = true;
- PrivateTmp = true;
- PrivateDevices = true;
- ProtectHostname = true;
- ProtectClock = true;
- ProtectKernelTunables = true;
- ProtectKernelModules = true;
- ProtectKernelLogs = true;
- ProtectControlGroups = true;
- RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6"];
- RestrictNamespaces = true;
- LockPersonality = true;
- MemoryDenyWriteExecute = true;
- RestrictRealtime = true;
- RestrictSUIDSGID = true;
- RemoveIPC = true;
- PrivateMounts = true;
- # System Call Filtering
- SystemCallArchitectures = "native";
- SystemCallFilter = ["~@cpu-emulation @debug @keyring @mount @obsolete @privileged @setuid"];
- };
- };
- services.nginx.virtualHosts."${cfg.domain}" = {
- locations."/".proxyPass = "http://127.0.0.1:8000";
-
- enableACME = true;
- forceSSL = true;
- };
- };
-}
diff --git a/modules/by-name/ba/backup/module.nix b/modules/by-name/ba/backup/module.nix
deleted file mode 100644
index 856a1c3..0000000
--- a/modules/by-name/ba/backup/module.nix
+++ /dev/null
@@ -1,91 +0,0 @@
-{
- config,
- pkgs,
- lib,
- ...
-}: let
- cfg = config.vhack.backup;
- snapshots = "/srv/snapshots";
- postgresUser = "postgres";
-in {
- options.vhack.backup = {
- enable = lib.mkEnableOption "backups with restic";
- user = lib.mkOption {
- type = lib.types.str;
- description = "The storagebox-user to use";
- example = "u384702-sub2";
- };
- privateSshKey = lib.mkOption {
- type = lib.types.path;
- description = "The age-encrypted ssh-key, passed to agenix";
- };
- privatePassword = lib.mkOption {
- type = lib.types.path;
- description = "The age-encrypted restic password, passed to agenix";
- };
- };
- config = lib.mkIf cfg.enable {
- vhack.persist.directories = [
- {
- directory = "/root/.ssh";
- user = "root";
- group = "root";
- mode = "0700";
- }
- ];
- age.secrets = {
- resticpass = {
- file = cfg.privatePassword;
- mode = "0700";
- owner = "root";
- group = "root";
- };
- resticssh = {
- file = cfg.privateSshKey;
- mode = "0700";
- owner = "root";
- group = "root";
- };
- };
- services.restic.backups = {
- storagebox = {
- initialize = true;
- backupPrepareCommand = ''
- ${pkgs.sudo}/bin/sudo -u ${postgresUser} ${pkgs.postgresql}/bin/pg_dumpall --clean --if-exists --quote-all-identifiers > /srv/db_backup.sql
-
- [ -d /srv/snapshots ] || ${pkgs.btrfs-progs}/bin/btrfs subvolume create /srv/snapshots;
- [ -d /srv/snapshots/srv ] && ${pkgs.btrfs-progs}/bin/btrfs subvolume delete /srv/snapshots/srv;
- ${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot -r /srv /srv/snapshots/srv;
-
- # dump() {
- # # compression:
- # # pg_dump -F t -v "$1" | xz -z -9 -e -T0 > "db_$1.tar.xz"
- # pg_dump -v "$1" > "db_$1.tar.xz"
- # }
- # # List all databases, and dump each of them in its own file
- # # psql --list --csv | while read -r line; do echo "$line" | grep ','; done | while IFS=, read -r name _; do echo "$name"; done | sed '1d' | while read -r db_name; do dump "$db_name"; done
- '';
- paths = [
- snapshots
- ];
- exclude = [
- ".snapshots"
- "/var/lib/postgresql" # included in the db dump
- ];
- extraBackupArgs = [
- "--verbose" # spam log
- ];
- passwordFile = config.age.secrets.resticpass.path;
- extraOptions = [
- "rclone.program='ssh -p 23 ${cfg.user}@${cfg.user}.your-storagebox.de -i ${config.age.secrets.resticssh.path}'"
- ];
- repository = "rclone: "; # There is only one repository served
- timerConfig = {
- Requires = "network-online.target";
- OnCalendar = "daily";
- Persistent = true;
- };
- };
- };
- };
-}
diff --git a/modules/by-name/co/constants/module.nix b/modules/by-name/co/constants/module.nix
deleted file mode 100644
index 2115a37..0000000
--- a/modules/by-name/co/constants/module.nix
+++ /dev/null
@@ -1,96 +0,0 @@
-# This file is inspired by the `nixos/modules/misc/ids.nix`
-# file in nixpkgs.
-{
- lib,
- config,
- ...
-}: {
- options.vhack.constants = {
- ids.uids = lib.mkOption {
- internal = true;
- description = ''
- The user IDs used in the vhack.eu nixos config.
- '';
- type = lib.types.attrsOf (lib.types.ints.between 0 400);
- };
- ids.gids = lib.mkOption {
- internal = true;
- description = ''
- The group IDs used in the vhack.eu nixos config.
- '';
- type = lib.types.attrsOf (lib.types.ints.between 0 400);
- };
- };
-
- config.vhack.constants = {
- ids.uids = {
- # Keep this sorted with `!sort --numeric-sort --key=2 --field-separator="="`
- systemd-coredump = 151; # GROUP
- opendkim = 221;
- mautrix-whatsapp = 222;
- etebase-server = 223;
- matrix-synapse = 224;
- rspamd = 225;
- knot-resolver = 226;
- peertube = 231;
- redis-mastodon = 232;
- redis-peertube = 233;
- redis-rspamd = 234;
- redis-stalwart-mail = 235;
- mastodon = 236;
- stalwart-mail = 238;
- acme = 328;
- dhcpcd = 329;
- nscd = 330;
- sshd = 331;
- systemd-oom = 332;
- resolvconf = 333; # GROUP
- nix-sync = 334;
- nextcloud = 335;
- redis-nextcloud = 336;
- taskchampion = 337;
- stalwart-mail-certificates = 338; # GROUP
- sharkey = 339;
- redis-sharkey = 340;
-
- # As per the NixOS file, the uids should not be greater or equal to 400;
- };
- ids.gids = let
- inherit (config.vhack.constants.ids) uids;
- in {
- # Please add your groups to the users and inherit them here.
- # This avoids having an user/group id mismatch.
- inherit
- (uids)
- acme
- dhcpcd
- etebase-server
- knot-resolver
- mastodon
- matrix-synapse
- mautrix-whatsapp
- nextcloud
- nix-sync
- nscd
- opendkim
- peertube
- redis-mastodon
- redis-nextcloud
- redis-peertube
- redis-rspamd
- redis-stalwart-mail
- rspamd
- sshd
- stalwart-mail
- systemd-oom
- sharkey
- redis-sharkey
- systemd-coredump # matches systemd-coredump user
- resolvconf # This group is not matched to an user?
- stalwart-mail-certificates # This group is used to connect nginx and stalwart-mail
- ;
-
- # The gid should match the uid. Thus should not be >= 400;
- };
- };
-}
diff --git a/modules/by-name/co/coredump/module.nix b/modules/by-name/co/coredump/module.nix
deleted file mode 100644
index ce28ed9..0000000
--- a/modules/by-name/co/coredump/module.nix
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.systemd.coredump;
-in {
- options.vhack.systemd.coredump = {
- # NOTE(@bpeetz): Enabled by default, because that is what NixOS also does. <2024-12-25>
- enable = (lib.mkEnableOption "oomd") // {default = true;};
- };
-
- config = lib.mkIf cfg.enable {
- users = {
- groups.systemd-coredump.gid = config.vhack.constants.ids.gids.systemd-coredump;
- };
- };
-}
diff --git a/modules/by-name/dh/dhcpcd/module.nix b/modules/by-name/dh/dhcpcd/module.nix
deleted file mode 100644
index 0e35af3..0000000
--- a/modules/by-name/dh/dhcpcd/module.nix
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.dhcpcd;
-in {
- options.vhack.dhcpcd = {
- enable = (lib.mkEnableOption "dhcpcd") // {default = config.networking.dhcpcd.enable;};
- };
-
- config = lib.mkIf cfg.enable {
- users = {
- users.dhcpcd.uid = config.vhack.constants.ids.uids.dhcpcd;
- groups.dhcpcd.gid = config.vhack.constants.ids.gids.dhcpcd;
- };
- };
-}
diff --git a/modules/by-name/di/disko/module.nix b/modules/by-name/di/disko/module.nix
deleted file mode 100644
index b4fc3c8..0000000
--- a/modules/by-name/di/disko/module.nix
+++ /dev/null
@@ -1,78 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.disko;
-
- defaultMountOptions = ["compress-force=zstd:15" "noatime"];
-in {
- options.vhack.disko = {
- enable = lib.mkEnableOption "disk configuration via disko";
-
- disk = lib.mkOption {
- type = lib.types.path;
- example = "/dev/disk/by-id/ata-WDC_WD10SDRW-11A0XS0_WD-WXP2A901KJN5";
- description = "Path to the main disk";
- };
- };
-
- config = lib.mkIf cfg.enable {
- disko.devices = {
- disk.main = {
- type = "disk";
- device = cfg.disk;
-
- content = {
- type = "gpt";
- partitions = {
- boot = {
- size = "1M";
- type = "EF02"; # for grub MBR
- };
- root = {
- size = "100%";
- content = {
- type = "btrfs";
- extraArgs = ["-f" "--label nixos"]; # f: Override existing partitions
-
- subvolumes = {
- "/nix" = {
- mountpoint = "/nix";
- mountOptions = defaultMountOptions;
- };
- "/srv" = {
- mountpoint = "/srv";
- mountOptions = defaultMountOptions;
- };
- "/srv/.snapshots" = {
- mountpoint = "/srv/.snapshots";
- mountOptions = defaultMountOptions;
- };
- "/boot" = {
- mountpoint = "/boot";
- mountOptions = defaultMountOptions;
- };
- };
- };
- };
- };
- };
- };
-
- nodev."/" = {
- fsType = "tmpfs";
- mountOptions = ["defaults" "size=6G" "mode=755"];
- };
- };
-
- fileSystems = {
- "/srv" = {
- neededForBoot = true;
- };
- "/boot" = {
- neededForBoot = true;
- };
- };
- };
-}
diff --git a/modules/by-name/dn/dns/dns/default.nix b/modules/by-name/dn/dns/dns/default.nix
deleted file mode 100644
index 4ce07d8..0000000
--- a/modules/by-name/dn/dns/dns/default.nix
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2019 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-{lib}: let
- util = import ./util {inherit lib;};
- types = import ./types {inherit lib util;};
-in {
- inherit
- types
- ;
-}
diff --git a/modules/by-name/dn/dns/dns/types/default.nix b/modules/by-name/dn/dns/dns/types/default.nix
deleted file mode 100644
index ece315f..0000000
--- a/modules/by-name/dn/dns/dns/types/default.nix
+++ /dev/null
@@ -1,16 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2019 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-{
- lib,
- util,
-}: let
- simple = {types = import ./simple.nix {inherit lib;};};
-in {
- record = import ./record.nix {inherit lib util;};
- records = import ./records {inherit lib util simple;};
-
- zone = import ./zone.nix {inherit lib util simple;};
-}
diff --git a/modules/by-name/dn/dns/dns/types/record.nix b/modules/by-name/dn/dns/dns/types/record.nix
deleted file mode 100644
index e992bf9..0000000
--- a/modules/by-name/dn/dns/dns/types/record.nix
+++ /dev/null
@@ -1,75 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2019 Kirill Elagin <https://kir.elagin.me/>
-# SPDX-FileCopyrightText: 2021 Naïm Favier <n@monade.li>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-{lib, ...}: let
- inherit (lib) hasSuffix isString mkOption removeSuffix types;
-
- recordType = rsubt: let
- submodule = types.submodule {
- options =
- {
- class = mkOption {
- type = types.enum ["IN"];
- default = "IN";
- example = "IN";
- description = "Resource record class. Only IN is supported";
- };
- ttl = mkOption {
- type = types.nullOr types.ints.unsigned; # TODO: u32
- default = null;
- example = 300;
- description = "Record caching duration (in seconds)";
- };
- }
- // rsubt.options;
- };
- in
- (
- if rsubt ? fromString
- then types.either types.str
- else lib.id
- )
- submodule;
-
- # name == "@" : use unqualified domain name
- writeRecord = name: rsubt: data: let
- data' =
- if isString data && rsubt ? fromString
- then
- # add default values for the record type
- (recordType rsubt).merge [] [
- {
- file = "";
- value = rsubt.fromString data;
- }
- ]
- else data;
- name' = let
- fname = rsubt.nameFixup or (n: _: n) name data';
- in
- if name == "@"
- then name
- else if (hasSuffix ".@" name)
- then removeSuffix ".@" fname
- else "${fname}.";
- inherit (rsubt) rtype;
- in
- lib.concatStringsSep " " (with data';
- [
- name'
- ]
- ++ lib.optionals (ttl != null) [
- (toString ttl)
- ]
- ++ [
- class
- rtype
- (rsubt.dataToString data')
- ]);
-in {
- inherit recordType;
- inherit writeRecord;
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/A.nix b/modules/by-name/dn/dns/dns/types/records/A.nix
deleted file mode 100644
index 296943e..0000000
--- a/modules/by-name/dn/dns/dns/types/records/A.nix
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2019 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-{lib, ...}: let
- inherit (lib) mkOption types;
-in {
- rtype = "A";
- options = {
- address = mkOption {
- type = types.str;
- example = "26.3.0.103";
- description = "IP address of the host";
- };
- };
- dataToString = {address, ...}: address;
- fromString = address: {inherit address;};
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/AAAA.nix b/modules/by-name/dn/dns/dns/types/records/AAAA.nix
deleted file mode 100644
index 4717176..0000000
--- a/modules/by-name/dn/dns/dns/types/records/AAAA.nix
+++ /dev/null
@@ -1,19 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2019 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-{lib, ...}: let
- inherit (lib) mkOption types;
-in {
- rtype = "AAAA";
- options = {
- address = mkOption {
- type = types.str;
- example = "4321:0:1:2:3:4:567:89ab";
- description = "IPv6 address of the host";
- };
- };
- dataToString = {address, ...}: address;
- fromString = address: {inherit address;};
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/CAA.nix b/modules/by-name/dn/dns/dns/types/records/CAA.nix
deleted file mode 100644
index 4b40510..0000000
--- a/modules/by-name/dn/dns/dns/types/records/CAA.nix
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2019 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-# RFC 8659
-{lib, ...}: let
- inherit (lib) mkOption types;
-in {
- rtype = "CAA";
- options = {
- issuerCritical = mkOption {
- type = types.bool;
- example = true;
- description = ''
- If set to '1', indicates that the corresponding property tag
- MUST be understood if the semantics of the CAA record are to be
- correctly interpreted by an issuer
- '';
- };
- tag = mkOption {
- type = types.enum ["issue" "issuewild" "iodef"];
- example = "issue";
- description = "One of the defined property tags";
- };
- value = mkOption {
- type = types.str; # section 4.1.1: not limited in length
- example = "ca.example.net";
- description = "Value of the property";
- };
- };
- dataToString = {
- issuerCritical,
- tag,
- value,
- ...
- }: ''${
- if issuerCritical
- then "128"
- else "0"
- } ${tag} "${value}"'';
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/CNAME.nix b/modules/by-name/dn/dns/dns/types/records/CNAME.nix
deleted file mode 100644
index 095b078..0000000
--- a/modules/by-name/dn/dns/dns/types/records/CNAME.nix
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2019 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-# RFC 1035, 3.3.1
-{
- lib,
- simple,
- ...
-}: let
- inherit (lib) mkOption;
-in {
- rtype = "CNAME";
- options = {
- cname = mkOption {
- type = simple.types.domain-name;
- example = "www.test.com";
- description = ''
- A <domain-name> which specifies the canonical or primary name
- for the owner. The owner name is an alias.
- '';
- };
- };
- dataToString = {cname, ...}: "${cname}";
- fromString = cname: {inherit cname;};
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/DKIM.nix b/modules/by-name/dn/dns/dns/types/records/DKIM.nix
deleted file mode 100644
index 31b2f67..0000000
--- a/modules/by-name/dn/dns/dns/types/records/DKIM.nix
+++ /dev/null
@@ -1,75 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2020 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-# This is a “fake” record type, not actually part of DNS.
-# It gets compiled down to a TXT record.
-# RFC 6376
-{
- lib,
- util,
- ...
-}: let
- inherit (lib) mkOption types;
-in rec {
- rtype = "TXT";
- options = {
- selector = mkOption {
- type = types.str;
- example = "mail";
- description = "DKIM selector name";
- };
- h = mkOption {
- type = types.listOf types.str;
- default = [];
- example = ["sha1" "sha256"];
- description = "Acceptable hash algorithms. Empty means all of them";
- apply = lib.concatStringsSep ":";
- };
- k = mkOption {
- type = types.nullOr types.str;
- default = "rsa";
- example = "rsa";
- description = "Key type";
- };
- n = mkOption {
- type = types.str;
- default = "";
- example = "Just any kind of arbitrary notes.";
- description = "Notes that might be of interest to a human";
- };
- p = mkOption {
- type = types.str;
- example = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDwIRP/UC3SBsEmGqZ9ZJW3/DkMoGeLnQg1fWn7/zYtIxN2SnFCjxOCKG9v3b4jYfcTNh5ijSsq631uBItLa7od+v/RtdC2UzJ1lWT947qR+Rcac2gbto/NMqJ0fzfVjH4OuKhitdY9tf6mcwGjaNBcWToIMmPSPDdQPNUYckcQ2QIDAQAB";
- description = "Public-key data (base64)";
- };
- s = mkOption {
- type = types.listOf (types.enum ["*" "email"]);
- default = ["*"];
- example = ["email"];
- description = "Service Type";
- apply = lib.concatStringsSep ":";
- };
- t = mkOption {
- type = types.listOf (types.enum ["y" "s"]);
- default = [];
- example = ["y"];
- description = "Flags";
- apply = lib.concatStringsSep ":";
- };
- };
- dataToString = data: let
- items =
- ["v=DKIM1"]
- ++ lib.pipe data [
- (builtins.intersectAttrs options) # remove garbage list `_module`
- (lib.filterAttrs (_k: v: v != null && v != ""))
- (lib.filterAttrs (k: _v: k != "selector"))
- (lib.mapAttrsToList (k: v: "${k}=${v}"))
- ];
- result = lib.concatStringsSep "; " items + ";";
- in
- util.writeCharacterString result;
- nameFixup = name: self: "${self.selector}._domainkey.${name}";
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/DMARC.nix b/modules/by-name/dn/dns/dns/types/records/DMARC.nix
deleted file mode 100644
index 0f10f2c..0000000
--- a/modules/by-name/dn/dns/dns/types/records/DMARC.nix
+++ /dev/null
@@ -1,108 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2020 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-# This is a “fake” record type, not actually part of DNS.
-# It gets compiled down to a TXT record.
-# RFC 7489
-{
- lib,
- util,
- ...
-}: let
- inherit (lib) mkOption types;
-in rec {
- rtype = "TXT";
- options = {
- adkim = mkOption {
- type = types.enum ["relaxed" "strict"];
- default = "relaxed";
- example = "strict";
- description = "DKIM Identifier Alignment mode";
- apply = builtins.substring 0 1;
- };
- aspf = mkOption {
- type = types.enum ["relaxed" "strict"];
- default = "relaxed";
- example = "strict";
- description = "SPF Identifier Alignment mode";
- apply = builtins.substring 0 1;
- };
- fo = mkOption {
- type = types.listOf (types.enum ["0" "1" "d" "s"]);
- default = ["0"];
- example = ["0" "1" "s"];
- description = "Failure reporting options";
- apply = lib.concatStringsSep ":";
- };
- p = mkOption {
- type = types.enum ["none" "quarantine" "reject"];
- example = "quarantine";
- description = "Requested Mail Receiver policy";
- };
- pct = mkOption {
- type = types.ints.between 0 100;
- default = 100;
- example = 30;
- description = "Percentage of messages to which the DMARC policy is to be applied";
- apply = builtins.toString;
- };
- rf = mkOption {
- type = types.listOf (types.enum ["afrf"]);
- default = ["afrf"];
- example = ["afrf"];
- description = "Format to be used for message-specific failure reports";
- apply = lib.concatStringsSep ":";
- };
- ri = mkOption {
- type = types.ints.unsigned; # FIXME: u32
- default = 86400;
- example = 12345;
- description = "Interval requested between aggregate reports";
- apply = builtins.toString;
- };
- rua = mkOption {
- type = types.oneOf [types.str (types.listOf types.str)];
- default = [];
- example = "mailto:dmarc+rua@example.com";
- description = "Addresses to which aggregate feedback is to be sent";
- apply = val:
- # FIXME: need to encode commas in URIs
- if builtins.isList val
- then lib.concatStringsSep "," val
- else val;
- };
- ruf = mkOption {
- type = types.listOf types.str;
- default = [];
- example = ["mailto:dmarc+ruf@example.com" "mailto:another+ruf@example.com"];
- description = "Addresses to which message-specific failure information is to be reported";
- apply = val:
- # FIXME: need to encode commas in URIs
- if builtins.isList val
- then lib.concatStringsSep "," val
- else val;
- };
- sp = mkOption {
- type = types.nullOr (types.enum ["none" "quarantine" "reject"]);
- default = null;
- example = "quarantine";
- description = "Requested Mail Receiver policy for all subdomains";
- };
- };
- dataToString = data: let
- # The specification could be more clear on this, but `v` and `p` MUST
- # be the first two tags in the record.
- items =
- ["v=DMARC1; p=${data.p}"]
- ++ lib.pipe data [
- (builtins.intersectAttrs options) # remove garbage list `_module`
- (lib.filterAttrs (k: v: v != null && v != "" && k != "p"))
- (lib.mapAttrsToList (k: v: "${k}=${v}"))
- ];
- result = lib.concatStringsSep "; " items + ";";
- in
- util.writeCharacterString result;
- nameFixup = name: _self: "_dmarc.${name}";
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/DNAME.nix b/modules/by-name/dn/dns/dns/types/records/DNAME.nix
deleted file mode 100644
index 042ce95..0000000
--- a/modules/by-name/dn/dns/dns/types/records/DNAME.nix
+++ /dev/null
@@ -1,15 +0,0 @@
-# RFC 6672
-{lib, ...}: let
- inherit (lib) dns mkOption;
-in {
- rtype = "DNAME";
- options = {
- dname = mkOption {
- type = dns.types.domain-name;
- example = "www.test.com";
- description = "A <domain-name> which provides redirection from a part of the DNS name tree to another part of the DNS name tree";
- };
- };
- dataToString = {dname, ...}: "${dname}";
- fromString = dname: {inherit dname;};
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/DNSKEY.nix b/modules/by-name/dn/dns/dns/types/records/DNSKEY.nix
deleted file mode 100644
index 86ce3a1..0000000
--- a/modules/by-name/dn/dns/dns/types/records/DNSKEY.nix
+++ /dev/null
@@ -1,63 +0,0 @@
-# SPDX-FileCopyrightText: 2020 Aluísio Augusto Silva Gonçalves <https://aasg.name>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-# RFC 4034, 2
-{lib, ...}: let
- inherit (builtins) isInt split;
- inherit (lib) concatStrings flatten mkOption types;
-
- dnssecOptions = import ./dnssec.nix {inherit lib;};
- inherit (dnssecOptions) mkDNSSECAlgorithmOption;
-in {
- rtype = "DNSKEY";
- options = {
- flags = mkOption {
- description = "Flags pertaining to this RR.";
- type = types.either types.ints.u16 (types.submodule {
- options = {
- zoneSigningKey = mkOption {
- description = "Whether this RR holds a zone signing key (ZSK).";
- type = types.bool;
- default = false;
- };
- secureEntryPoint = mkOption {
- type = types.bool;
- description = ''
- Whether this RR holds a secure entry point.
- In general, this means the key is a key-signing key (KSK), as opposed to a zone-signing key.
- '';
- default = false;
- };
- };
- });
- apply = value:
- if isInt value
- then value
- else
- (
- if value.zoneSigningKey
- then 256
- else 0
- )
- + (
- if value.secureEntryPoint
- then 1
- else 0
- );
- };
- algorithm = mkDNSSECAlgorithmOption {
- description = "Algorithm of the key referenced by this RR.";
- };
- publicKey = mkOption {
- type = types.str;
- description = "Base64-encoded public key.";
- apply = value: concatStrings (flatten (split "[[:space:]]" value));
- };
- };
- dataToString = {
- flags,
- algorithm,
- publicKey,
- ...
- }: "${toString flags} 3 ${toString algorithm} ${publicKey}";
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/DS.nix b/modules/by-name/dn/dns/dns/types/records/DS.nix
deleted file mode 100644
index 76fac9a..0000000
--- a/modules/by-name/dn/dns/dns/types/records/DS.nix
+++ /dev/null
@@ -1,48 +0,0 @@
-# SPDX-FileCopyrightText: 2020 Aluísio Augusto Silva Gonçalves <https://aasg.name>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-# RFC 4034, 5
-{lib, ...}: let
- inherit (lib) mkOption types;
-
- dnssecOptions = import ./dnssec.nix {inherit lib;};
- inherit (dnssecOptions) mkRegisteredNumberOption mkDNSSECAlgorithmOption;
-
- mkDSDigestTypeOption = args:
- mkRegisteredNumberOption {
- registryName = "Delegation Signer (DS) Resource Record (RR) Type Digest Algorithms";
- numberType = types.ints.u8;
- # These mnemonics are unofficial, unlike the DNSSEC algorithm ones.
- mnemonics = {
- "sha-1" = 1;
- "sha-256" = 2;
- "gost" = 3;
- "sha-384" = 4;
- };
- };
-in {
- rtype = "DS";
- options = {
- keyTag = mkOption {
- description = "Tag computed over the DNSKEY referenced by this RR to identify it.";
- type = types.ints.u16;
- };
- algorithm = mkDNSSECAlgorithmOption {
- description = "Algorithm of the key referenced by this RR.";
- };
- digestType = mkDSDigestTypeOption {
- description = "Type of the digest given in the `digest` attribute.";
- };
- digest = mkOption {
- description = "Digest of the DNSKEY referenced by this RR.";
- type = types.strMatching "[[:xdigit:]]+";
- };
- };
- dataToString = {
- keyTag,
- algorithm,
- digestType,
- digest,
- ...
- }: "${toString keyTag} ${toString algorithm} ${toString digestType} ${digest}";
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/HTTPS.nix b/modules/by-name/dn/dns/dns/types/records/HTTPS.nix
deleted file mode 100644
index 6e2ef3d..0000000
--- a/modules/by-name/dn/dns/dns/types/records/HTTPS.nix
+++ /dev/null
@@ -1,5 +0,0 @@
-args:
-import ./SVCB.nix args
-// {
- rtype = "HTTPS";
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/MTA-STS.nix b/modules/by-name/dn/dns/dns/types/records/MTA-STS.nix
deleted file mode 100644
index 030490e..0000000
--- a/modules/by-name/dn/dns/dns/types/records/MTA-STS.nix
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-# This is a “fake” record type, not actually part of DNS.
-# It gets compiled down to a TXT record.
-# RFC 8461
-{
- lib,
- util,
- ...
-}: let
- inherit (lib) mkOption types;
-in rec {
- rtype = "TXT";
- options = {
- id = mkOption {
- type = types.str;
- example = "20160831085700Z";
- description = ''
- A short string used to track policy updates. This string MUST
- uniquely identify a given instance of a policy, such that senders
- can determine when the policy has been updated by comparing to the
- "id" of a previously seen policy. There is no implied ordering of
- "id" fields between revisions.
- '';
- };
- };
- dataToString = data: let
- items =
- ["v=STSv1"]
- ++ lib.pipe data [
- (builtins.intersectAttrs options) # remove garbage list `_module`
- (lib.filterAttrs (k: v: v != null && v != ""))
- (lib.mapAttrsToList (k: v: "${k}=${v}"))
- ];
- result = lib.concatStringsSep "; " items + ";";
- in
- util.writeCharacterString result;
- nameFixup = name: _self: "_mta-sts.${name}";
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/MX.nix b/modules/by-name/dn/dns/dns/types/records/MX.nix
deleted file mode 100644
index c25b89c..0000000
--- a/modules/by-name/dn/dns/dns/types/records/MX.nix
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2019 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-# RFC 1035, 3.3.9
-{
- lib,
- simple,
- ...
-}: let
- inherit (lib) mkOption types;
-in {
- rtype = "MX";
- options = {
- preference = mkOption {
- type = types.ints.u16;
- example = 10;
- description = "The preference given to this RR among others at the same owner. Lower values are preferred";
- };
- exchange = mkOption {
- type = simple.types.domain-name;
- example = "smtp.example.com.";
- description = "A <domain-name> which specifies a host willing to act as a mail exchange for the owner name";
- };
- };
- dataToString = {
- preference,
- exchange,
- ...
- }: "${toString preference} ${exchange}";
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/NS.nix b/modules/by-name/dn/dns/dns/types/records/NS.nix
deleted file mode 100644
index ea60a91..0000000
--- a/modules/by-name/dn/dns/dns/types/records/NS.nix
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2019 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-# RFC 1035, 3.3.11
-{
- lib,
- simple,
- ...
-}: let
- inherit (lib) mkOption;
-in {
- rtype = "NS";
- options = {
- nsdname = mkOption {
- type = simple.types.domain-name;
- example = "ns2.example.com";
- description = "A <domain-name> which specifies a host which should be authoritative for the specified class and domain";
- };
- };
- dataToString = {nsdname, ...}: "${nsdname}";
- fromString = nsdname: {inherit nsdname;};
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/OPENPGPKEY.nix b/modules/by-name/dn/dns/dns/types/records/OPENPGPKEY.nix
deleted file mode 100644
index 1f39cb9..0000000
--- a/modules/by-name/dn/dns/dns/types/records/OPENPGPKEY.nix
+++ /dev/null
@@ -1,18 +0,0 @@
-# RFC7929
-{
- lib,
- util,
- ...
-}: let
- inherit (lib) mkOption types;
-in {
- rtype = "OPENPGPKEY";
- options = {
- data = mkOption {
- type = types.str;
- };
- };
-
- dataToString = {data, ...}: util.writeCharacterString data;
- fromString = data: {inherit data;};
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/PTR.nix b/modules/by-name/dn/dns/dns/types/records/PTR.nix
deleted file mode 100644
index 075f82e..0000000
--- a/modules/by-name/dn/dns/dns/types/records/PTR.nix
+++ /dev/null
@@ -1,92 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2019 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-# RFC 1035, 3.3.12
-{
- lib,
- simple,
- ...
-}: let
- inherit (lib) mkOption;
-
- inherit (lib.strings) stringToCharacters splitString;
-
- reverseIpv4 = input:
- builtins.concatStringsSep "." (lib.lists.reverseList (splitString "."
- input));
-
- reverseIpv6 = input: let
- split = splitString ":" input;
- elementLength = builtins.length split;
-
- reverseString = string:
- builtins.concatStringsSep "" (lib.lists.reverseList
- (stringToCharacters string));
- in
- reverseString (builtins.concatStringsSep "." (stringToCharacters (builtins.concatStringsSep
- "" (builtins.map (
- part: let
- c = stringToCharacters part;
- in
- if builtins.length c == 4
- then
- # valid part
- part
- else if builtins.length c < 4 && builtins.length c > 0
- then
- # leading zeros were elided
- (builtins.concatStringsSep "" (
- builtins.map builtins.toString (
- builtins.genList (_: 0) (4 - (builtins.length c))
- )
- ))
- + part
- else if builtins.length c == 0
- then
- # Multiple full blocks were elided. Only one of these can be in an
- # IPv6 address, as such we can simply add (8 - (elementLength - 1)) `0000`
- # blocks. We need to substract one from `elementLength` because
- # this empty part is included in the `elementLength`.
- builtins.concatStringsSep "" (builtins.genList (_: "0000") (8 - (elementLength - 1)))
- else builtins.throw "Impossible"
- )
- split))));
-in {
- rtype = "PTR";
- options = {
- name = mkOption {
- type = simple.types.domain-name;
- example = "mail2.server.com";
- description = "The <domain-name> which is defined by the IP.";
- };
- ip = {
- v4 = mkOption {
- type = lib.types.nullOr lib.types.str;
- example = "192.168.1.4";
- description = "The IPv4 address of the host.";
- default = null;
- apply = v:
- if v != null
- then reverseIpv4 v
- else v;
- };
- v6 = mkOption {
- type = lib.types.nullOr lib.types.str;
- example = "192.168.1.4";
- description = "The IPv6 address of the host.";
- default = null;
- apply = v:
- if v != null
- then reverseIpv6 v
- else v;
- };
- };
- };
- dataToString = {name, ...}: "${name}.";
- nameFixup = name: self:
- if self.ip.v6 == null
- then "${self.ip.v4}.in-addr.arpa"
- else "${self.ip.v6}.ip6.arpa";
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/SOA.nix b/modules/by-name/dn/dns/dns/types/records/SOA.nix
deleted file mode 100644
index db7436e..0000000
--- a/modules/by-name/dn/dns/dns/types/records/SOA.nix
+++ /dev/null
@@ -1,65 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2019 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-# RFC 1035, 3.3.13
-{
- lib,
- simple,
- ...
-}: let
- inherit (lib) concatStringsSep removeSuffix replaceStrings;
- inherit (lib) mkOption types;
-in {
- rtype = "SOA";
- options = {
- nameServer = mkOption {
- type = simple.types.domain-name;
- example = "ns1.example.com";
- description = "The <domain-name> of the name server that was the original or primary source of data for this zone. Don't forget the dot at the end!";
- };
- adminEmail = mkOption {
- type = simple.types.domain-name;
- example = "admin@example.com";
- description = "An email address of the person responsible for this zone. (Note: in traditional zone files you are supposed to put a dot instead of `@` in your address; you can use `@` with this module and it is recommended to do so. Also don't put the dot at the end!)";
- apply = s: replaceStrings ["@"] ["."] (removeSuffix "." s);
- };
- serial = mkOption {
- type = types.ints.unsigned; # TODO: u32
- example = 20;
- description = "Version number of the original copy of the zone";
- };
- refresh = mkOption {
- type = types.ints.unsigned; # TODO: u32
- default = 24 * 60 * 60;
- example = 7200;
- description = "Time interval before the zone should be refreshed";
- };
- retry = mkOption {
- type = types.ints.unsigned; # TODO: u32
- default = 10 * 60;
- example = 600;
- description = "Time interval that should elapse before a failed refresh should be retried";
- };
- expire = mkOption {
- type = types.ints.unsigned; # TODO: u32
- default = 10 * 24 * 60 * 60;
- example = 3600000;
- description = "Time value that specifies the upper limit on the time interval that can elapse before the zone is no longer authoritative";
- };
- minimum = mkOption {
- type = types.ints.unsigned; # TODO: u32
- default = 60;
- example = 60;
- description = "Minimum TTL field that should be exported with any RR from this zone";
- };
- };
- dataToString = data @ {
- nameServer,
- adminEmail,
- ...
- }: let
- numbers = map toString (with data; [serial refresh retry expire minimum]);
- in "${nameServer} ${adminEmail}. (${concatStringsSep " " numbers})";
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/SRV.nix b/modules/by-name/dn/dns/dns/types/records/SRV.nix
deleted file mode 100644
index 5f558ed..0000000
--- a/modules/by-name/dn/dns/dns/types/records/SRV.nix
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2019 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-# RFC 2782
-{
- lib,
- simple,
- ...
-}: let
- inherit (lib) mkOption types;
-in {
- rtype = "SRV";
- options = {
- service = mkOption {
- type = types.str;
- example = "foobar";
- description = "The symbolic name of the desired service. Do not add the underscore!";
- };
- proto = mkOption {
- type = types.str;
- example = "tcp";
- description = "The symbolic name of the desired protocol. Do not add the underscore!";
- };
- priority = mkOption {
- type = types.ints.u16;
- default = 0;
- example = 0;
- description = "The priority of this target host";
- };
- weight = mkOption {
- type = types.ints.u16;
- default = 100;
- example = 20;
- description = "The weight field specifies a relative weight for entries with the same priority. Larger weights SHOULD be given a proportionately higher probability of being selected";
- };
- port = mkOption {
- type = types.ints.u16;
- example = 9;
- description = "The port on this target host of this service";
- };
- target = mkOption {
- type = simple.types.domain-name;
- example = "";
- description = "The domain name of the target host";
- };
- };
- dataToString = data: with data; "${toString priority} ${toString weight} ${toString port} ${target}";
- nameFixup = name: self: "_${self.service}._${self.proto}.${name}";
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/SSHFP.nix b/modules/by-name/dn/dns/dns/types/records/SSHFP.nix
deleted file mode 100644
index 1409860..0000000
--- a/modules/by-name/dn/dns/dns/types/records/SSHFP.nix
+++ /dev/null
@@ -1,39 +0,0 @@
-# RFC 4255
-{lib, ...}: let
- inherit (lib) mkOption types;
- inherit (builtins) attrNames;
- algorithm = {
- "rsa" = 1;
- "dsa" = 2;
- "ecdsa" = 3; # RFC 6594
- "ed25519" = 4; # RFC 7479 / RFC 8709
- "ed448" = 6; # RFC 8709
- };
- mode = {
- "sha1" = 1;
- "sha256" = 2; # RFC 6594
- };
-in {
- rtype = "SSHFP";
- options = {
- algorithm = mkOption {
- example = "ed25519";
- type = types.enum (attrNames algorithm);
- apply = value: algorithm.${value};
- };
- fingerprintType = mkOption {
- example = "sha256";
- type = types.enum (attrNames mode);
- apply = value: mode.${value};
- };
- fingerprint = mkOption {
- type = types.str;
- };
- };
- dataToString = {
- algorithm,
- fingerprintType,
- fingerprint,
- ...
- }: "${toString algorithm} ${toString fingerprintType} ${fingerprint}";
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/SVCB.nix b/modules/by-name/dn/dns/dns/types/records/SVCB.nix
deleted file mode 100644
index 62cbc3d..0000000
--- a/modules/by-name/dn/dns/dns/types/records/SVCB.nix
+++ /dev/null
@@ -1,100 +0,0 @@
-# rfc9460
-{lib, ...}: let
- inherit
- (lib)
- concatStringsSep
- filter
- isInt
- isList
- mapAttrsToList
- mkOption
- types
- ;
-
- mkSvcParams = params:
- concatStringsSep " " (
- filter (s: s != "") (
- mapAttrsToList (
- name: value:
- if value
- then name
- else if isList value
- then "${name}=${concatStringsSep "," value}"
- else if isInt value
- then "${name}=${builtins.toString value}"
- else ""
- )
- params
- )
- );
-in {
- rtype = "SVCB";
- options = {
- svcPriority = mkOption {
- example = 1;
- type = types.ints.u16;
- };
- targetName = mkOption {
- example = ".";
- type = types.str;
- };
- mandatory = mkOption {
- example = ["ipv4hint"];
- default = null;
- type = types.nullOr (types.nonEmptyListOf types.str);
- };
- alpn = mkOption {
- example = ["h2"];
- default = null;
- type = types.nullOr (types.nonEmptyListOf types.str);
- };
- no-default-alpn = mkOption {
- example = true;
- default = false;
- type = types.bool;
- };
- port = mkOption {
- example = 443;
- default = null;
- type = types.nullOr types.port;
- };
- ipv4hint = mkOption {
- example = ["127.0.0.1"];
- default = null;
- type = types.nullOr (types.nonEmptyListOf types.str);
- };
- ipv6hint = mkOption {
- example = ["::1"];
- default = null;
- type = types.nullOr (types.nonEmptyListOf types.str);
- };
- ech = mkOption {
- type = types.nullOr types.str;
- default = null;
- };
- };
- dataToString = {
- svcPriority,
- targetName,
- mandatory ? null,
- alpn ? null,
- no-default-alpn ? null,
- port ? null,
- ipv4hint ? null,
- ipv6hint ? null,
- ech ? null,
- ...
- }: "${toString svcPriority} ${targetName} ${
- mkSvcParams {
- inherit
- alpn
- ech
- ipv4hint
- ipv6hint
- mandatory
- no-default-alpn
- port
- ;
- }
- }";
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/TLSA.nix b/modules/by-name/dn/dns/dns/types/records/TLSA.nix
deleted file mode 100644
index d92a29b..0000000
--- a/modules/by-name/dn/dns/dns/types/records/TLSA.nix
+++ /dev/null
@@ -1,50 +0,0 @@
-# RFC 6698
-{lib, ...}: let
- inherit (lib) mkOption types;
- inherit (builtins) attrNames;
-
- certUsage = {
- "pkix-ta" = 0;
- "pkix-ee" = 1;
- "dane-ta" = 2;
- "dane-ee" = 3;
- };
- selectors = {
- "cert" = 0;
- "spki" = 1;
- };
- match = {
- "exact" = 0;
- "sha256" = 1;
- "sha512" = 2;
- };
-in {
- rtype = "TLSA";
- options = {
- certUsage = mkOption {
- example = "dane-ee";
- type = types.enum (attrNames certUsage);
- apply = value: certUsage.${value};
- };
- selector = mkOption {
- example = "spki";
- type = types.enum (attrNames selectors);
- apply = value: selectors.${value};
- };
- matchingType = mkOption {
- example = "sha256";
- type = types.enum (attrNames match);
- apply = value: match.${value};
- };
- certificate = mkOption {
- type = types.str;
- };
- };
- dataToString = {
- certUsage,
- selector,
- matchingType,
- certificate,
- ...
- }: "${toString certUsage} ${toString selector} ${toString matchingType} ${certificate}";
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/TXT.nix b/modules/by-name/dn/dns/dns/types/records/TXT.nix
deleted file mode 100644
index d605ce8..0000000
--- a/modules/by-name/dn/dns/dns/types/records/TXT.nix
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2019 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-# RFC 1035, 3.3.14
-{
- lib,
- util,
- ...
-}: let
- inherit (lib) mkOption types;
-in {
- rtype = "TXT";
- options = {
- data = mkOption {
- type = types.str;
- example = "favorite drink=orange juice";
- description = "Arbitrary information";
- };
- };
- dataToString = {data, ...}: util.writeCharacterString data;
- fromString = data: {inherit data;};
-}
diff --git a/modules/by-name/dn/dns/dns/types/records/default.nix b/modules/by-name/dn/dns/dns/types/records/default.nix
deleted file mode 100644
index 76a86cd..0000000
--- a/modules/by-name/dn/dns/dns/types/records/default.nix
+++ /dev/null
@@ -1,43 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2019 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-{
- lib,
- util,
- simple,
-}: let
- inherit (lib.attrsets) genAttrs;
-
- types = [
- "A"
- "AAAA"
- "CAA"
- "CNAME"
- "DNAME"
- "MX"
- "NS"
- "SOA"
- "SRV"
- "TXT"
- "PTR"
-
- # DNSSEC types
- "DNSKEY"
- "DS"
-
- # DANE types
- "SSHFP"
- "TLSA"
- "OPENPGPKEY"
- "SVCB"
- "HTTPS"
-
- # Pseudo types
- "DKIM"
- "DMARC"
- "MTA-STS"
- ];
-in
- genAttrs types (t: import (./. + "/${t}.nix") {inherit lib simple util;})
diff --git a/modules/by-name/dn/dns/dns/types/records/dnssec.nix b/modules/by-name/dn/dns/dns/types/records/dnssec.nix
deleted file mode 100644
index 648f676..0000000
--- a/modules/by-name/dn/dns/dns/types/records/dnssec.nix
+++ /dev/null
@@ -1,48 +0,0 @@
-# SPDX-FileCopyrightText: 2020 Aluísio Augusto Silva Gonçalves <https://aasg.name>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-{lib}: let
- inherit (builtins) attrNames isInt removeAttrs;
- inherit (lib) mkOption types;
-in rec {
- mkRegisteredNumberOption = {
- registryName,
- numberType,
- mnemonics,
- } @ args:
- mkOption
- {
- type =
- types.either numberType (types.enum (attrNames mnemonics))
- // {
- name = "registeredNumber";
- description = "number in IANA registry '${registryName}'";
- };
- apply = value:
- if isInt value
- then value
- else mnemonics.${value};
- }
- // removeAttrs args ["registryName" "numberType" "mnemonics"];
-
- mkDNSSECAlgorithmOption = args:
- mkRegisteredNumberOption {
- registryName = "Domain Name System Security (DNSSEC) Algorithm Numbers";
- numberType = types.ints.u8;
- mnemonics = {
- "dsa" = 3;
- "rsasha1" = 5;
- "dsa-nsec3-sha1" = 6;
- "rsasha1-nsec3-sha1" = 7;
- "rsasha256" = 8;
- "rsasha512" = 10;
- "ecc-gost" = 12;
- "ecdsap256sha256" = 13;
- "ecdsap384sha384" = 14;
- "ed25519" = 15;
- "ed448" = 16;
- "privatedns" = 253;
- "privateoid" = 254;
- };
- };
-}
diff --git a/modules/by-name/dn/dns/dns/types/simple.nix b/modules/by-name/dn/dns/dns/types/simple.nix
deleted file mode 100644
index fece2c9..0000000
--- a/modules/by-name/dn/dns/dns/types/simple.nix
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-FileCopyrightText: 2021 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-{lib}: let
- inherit (builtins) stringLength;
-in {
- # RFC 1035, 3.1
- domain-name = lib.types.addCheck lib.types.str (s: stringLength s <= 255);
-}
diff --git a/modules/by-name/dn/dns/dns/types/zone.nix b/modules/by-name/dn/dns/dns/types/zone.nix
deleted file mode 100644
index 44ccb15..0000000
--- a/modules/by-name/dn/dns/dns/types/zone.nix
+++ /dev/null
@@ -1,119 +0,0 @@
-#
-# SPDX-FileCopyrightText: 2019 Kirill Elagin <https://kir.elagin.me/>
-# SPDX-FileCopyrightText: 2021 Naïm Favier <n@monade.li>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-#
-{
- lib,
- util,
- simple,
-}: let
- inherit (builtins) filter removeAttrs;
- inherit
- (lib)
- concatMapStringsSep
- concatStringsSep
- mapAttrs
- mapAttrsToList
- optionalString
- ;
- inherit (lib) mkOption literalExample types;
-
- inherit (import ./record.nix {inherit lib;}) recordType writeRecord;
-
- rsubtypes = import ./records {inherit lib util simple;};
- rsubtypes' = removeAttrs rsubtypes ["SOA"];
-
- subzoneOptions =
- {
- subdomains = mkOption {
- type = types.attrsOf subzone;
- default = {};
- example = {
- www = {
- A = [{address = "1.1.1.1";}];
- };
- staging = {
- A = [{address = "1.0.0.1";}];
- };
- };
- description = "Records for subdomains of the domain";
- };
- }
- // mapAttrs (n: t:
- mkOption {
- type = types.listOf (recordType t);
- default = [];
- # example = [ t.example ]; # TODO: any way to auto-generate an example for submodule?
- description = "List of ${n} records for this zone/subzone";
- })
- rsubtypes';
-
- subzone = types.submodule {
- options = subzoneOptions;
- };
-
- writeSubzone = name: zone: let
- groupToString = pseudo: subt:
- concatMapStringsSep "\n" (writeRecord name subt) zone."${pseudo}";
- groups = mapAttrsToList groupToString rsubtypes';
- groups' = filter (s: s != "") groups;
-
- writeSubzone' = subname: writeSubzone "${subname}.${name}";
- sub = concatStringsSep "\n\n" (mapAttrsToList writeSubzone' zone.subdomains);
- in
- concatStringsSep "\n\n" groups'
- + optionalString (sub != "") ("\n\n" + sub);
- zone = types.submodule ({name, ...}: {
- options =
- {
- useOrigin = mkOption {
- type = types.bool;
- default = false;
- description = "Wether to use $ORIGIN and unqualified name or fqdn when exporting the zone.";
- };
-
- TTL = mkOption {
- type = types.ints.unsigned;
- default = 24 * 60 * 60;
- example = literalExample "60 * 60";
- description = "Default record caching duration. Sets the $TTL variable";
- };
- SOA = mkOption rec {
- type = recordType rsubtypes.SOA;
- example =
- {
- ttl = 24 * 60 * 60;
- }
- // type.example;
- description = "SOA record";
- };
- }
- // subzoneOptions;
- });
- renderToString = name: {
- useOrigin,
- TTL,
- SOA,
- ...
- } @ zone:
- if useOrigin
- then ''
- $ORIGIN ${name}.
- $TTL ${toString TTL}
-
- ${writeRecord "@" rsubtypes.SOA SOA}
-
- ${writeSubzone "@" zone}
- ''
- else ''
- $TTL ${toString TTL}
-
- ${writeRecord name rsubtypes.SOA SOA}
-
- ${writeSubzone name zone}
- '';
-in {
- inherit zone subzone renderToString;
-}
diff --git a/modules/by-name/dn/dns/dns/util/default.nix b/modules/by-name/dn/dns/dns/util/default.nix
deleted file mode 100644
index 59e661d..0000000
--- a/modules/by-name/dn/dns/dns/util/default.nix
+++ /dev/null
@@ -1,76 +0,0 @@
-# SPDX-FileCopyrightText: 2021 Kirill Elagin <https://kir.elagin.me/>
-#
-# SPDX-License-Identifier: MPL-2.0 or MIT
-{lib}: let
- inherit
- (builtins)
- concatStringsSep
- genList
- stringLength
- substring
- ;
- inherit
- (lib.strings)
- concatMapStrings
- concatMapStringsSep
- fixedWidthString
- splitString
- stringToCharacters
- ;
- inherit (lib.lists) filter reverseList;
-
- /*
- Split a string into byte chunks, such that each output String is less then or equal to
- `n` bytes.
-
- # Type
-
- splitInGroupsOf :: Integer -> String -> [String]
-
- # Arguments
-
- n
- : The number of bytes to put into each String.
-
- s
- : The String to split.
- */
- splitInGroupsOf = n: s: let
- groupCount = (stringLength s - 1) / n + 1;
- in
- genList (i: substring (i * n) n s) groupCount;
-
- # : str -> str
- # Prepares a Nix string to be written to a zone file as a character-string
- # literal: breaks it into chunks of 255 (per RFC 1035, 3.3) and encloses
- # each chunk in quotation marks.
- writeCharacterString = s:
- if stringLength s <= 255
- then ''"${s}"''
- else concatMapStringsSep " " (x: ''"${x}"'') (splitInGroupsOf 255 s);
-
- # : str -> str, with length 4 (zeros are padded to the left)
- align4Bytes = fixedWidthString 4 "0";
-
- # : int -> str -> str
- # Expands "" to 4n zeros and aligns the rest on 4 bytes
- align4BytesOrExpand = n: v:
- if v == ""
- then (fixedWidthString (4 * n) "0" "")
- else align4Bytes v;
-
- # : str -> [ str ]
- # Returns the record of the ipv6 as a list
- mkRecordAux = v6: let
- splitted = splitString ":" v6;
- n = 8 - builtins.length (filter (x: x != "") splitted);
- in
- stringToCharacters (concatMapStrings (align4BytesOrExpand n) splitted);
-
- # : str -> str
- # Returns the reversed record of the ipv6
- mkReverseRecord = v6:
- concatStringsSep "." (reverseList (mkRecordAux v6)) + ".ip6.arpa";
-in {
- inherit writeCharacterString mkReverseRecord;
-}
diff --git a/modules/by-name/dn/dns/module.nix b/modules/by-name/dn/dns/module.nix
deleted file mode 100644
index 8f4ad37..0000000
--- a/modules/by-name/dn/dns/module.nix
+++ /dev/null
@@ -1,86 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.dns;
-
- zones =
- builtins.mapAttrs (name: value: {
- data =
- dns.types.zone.renderToString name value;
- })
- cfg.zones;
-
- dns = import ./dns {inherit lib;};
-
- ports = let
- parsePorts = listeners: let
- splitAddress = addr: lib.splitString "@" addr;
-
- extractPort = addr: let
- split = splitAddress addr;
- in
- lib.toInt (
- if (builtins.length split) == 2
- then builtins.elemAt split 1
- else "53"
- );
- in
- builtins.map extractPort listeners;
- in
- lib.unique (parsePorts cfg.interfaces);
-in {
- options.vhack.dns = {
- enable = lib.mkEnableOption "custom dns server";
-
- openFirewall = lib.mkOption {
- type = lib.types.bool;
- default = false;
- description = ''
- Open the following ports:
- TCP (${lib.concatStringsSep ", " (map toString ports)})
- UDP (${lib.concatStringsSep ", " (map toString ports)})
- '';
- };
-
- interfaces = lib.mkOption {
- type = lib.types.listOf lib.types.str;
- description = ''
- A list of the interfaces to bind to. To select the port add `@` to the end of the
- interface. The default port is 53.
- '';
- example = [
- "192.168.1.3"
- "2001:db8:1::3"
- ];
- };
-
- zones = lib.mkOption {
- type = lib.types.attrsOf dns.types.zone.zone;
- description = "DNS zones";
- };
- };
-
- config = lib.mkIf cfg.enable {
- services.nsd = {
- enable = true;
- verbosity = 4;
- inherit (cfg) interfaces;
- inherit zones;
- };
-
- networking.firewall.allowedUDPPorts = lib.mkIf cfg.openFirewall ports;
- networking.firewall.allowedTCPPorts = lib.mkIf cfg.openFirewall ports;
-
- systemd.services.nsd = {
- requires = [
- "network-online.target"
- ];
- after = [
- "network.target"
- "network-online.target"
- ];
- };
- };
-}
diff --git a/modules/by-name/et/etesync/module.nix b/modules/by-name/et/etesync/module.nix
deleted file mode 100644
index bcabc8a..0000000
--- a/modules/by-name/et/etesync/module.nix
+++ /dev/null
@@ -1,80 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.etesync;
-in {
- options.vhack.etesync = {
- enable = lib.mkEnableOption ''
- a secure, end-to-end encrypted, and privacy respecting sync for your contacts, calendars, tasks and notes.
- '';
- secretFile = lib.mkOption {
- type = lib.types.path;
- description = "The age encrypted globale etebase secretfile passed to agenix";
- };
- };
-
- config = lib.mkIf cfg.enable {
- services.etebase-server = {
- enable = true;
- port = 8001;
- settings = {
- global.secret_file = "${config.age.secrets.etebase-server.path}";
- allowed_hosts = {
- allowed_host1 = "etebase.vhack.eu";
- allowed_host2 = "dav.vhack.eu";
- };
- };
- };
-
- age.secrets.etebase-server = {
- file = cfg.secretFile;
- mode = "700";
- owner = "etebase-server";
- group = "etebase-server";
- };
-
- vhack.persist.directories = [
- {
- directory = "/var/lib/etebase-server";
- user = "etebase-server";
- group = "etebase-server";
- mode = "0700";
- }
- ];
-
- services.nginx = {
- enable = true;
- recommendedTlsSettings = true;
- recommendedOptimisation = true;
- recommendedGzipSettings = true;
- recommendedProxySettings = true;
-
- virtualHosts = {
- "etebase.vhack.eu" = {
- enableACME = true;
- forceSSL = true;
-
- locations = {
- # TODO: Maybe fix permissions to use pregenerated static files which would
- # improve performance.
- #"/static" = {
- # root = config.services.etebase-server.settings.global.static_root;
- #};
- "/" = {
- proxyPass = "http://127.0.0.1:${builtins.toString config.services.etebase-server.port}";
- };
- };
- serverAliases = [
- "dav.vhack.eu"
- ];
- };
- };
- };
- users = {
- users.etebase-server.uid = config.vhack.constants.ids.uids.etebase-server;
- groups.etebase-server.gid = config.vhack.constants.ids.gids.etebase-server;
- };
- };
-}
diff --git a/modules/by-name/fa/fail2ban/module.nix b/modules/by-name/fa/fail2ban/module.nix
deleted file mode 100644
index c619ef9..0000000
--- a/modules/by-name/fa/fail2ban/module.nix
+++ /dev/null
@@ -1,58 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.fail2ban;
-in {
- options.vhack.fail2ban = {
- enable = lib.mkEnableOption "fail2ban";
- };
-
- config = lib.mkIf cfg.enable {
- vhack.persist.directories = [
- {
- directory = "/var/lib/fail2ban";
- # TODO: Fail2ban should probably run under a dedicated `fail2ban` user. <2024-12-25>
- user = "root";
- group = "root";
- mode = "0700";
- }
- ];
-
- services.fail2ban = {
- enable = true;
- maxretry = 7; # ban after 7 failures
- daemonSettings = {
- Definition = {
- logtarget = "SYSLOG";
- socket = "/run/fail2ban/fail2ban.sock";
- pidfile = "/run/fail2ban/fail2ban.pid";
- dbfile = "/var/lib/fail2ban/db.sqlite3";
- };
- };
- bantime-increment = {
- enable = true;
- rndtime = "8m";
- overalljails = true;
- multipliers = "2 4 16 128 256";
- maxtime = "72h";
- };
- jails = {
- dovecot = ''
- # block IPs which failed to log-in
- # aggressive mode add blocking for aborted connections
- enabled = true
- filter = dovecot[mode=aggressive]
- maxretry = 2
- '';
- postfix = ''
- enabled = true
- filter = postfix[mode=aggressive]
- findtime = 600
- maxretry = 3
- '';
- };
- };
- };
-}
diff --git a/modules/by-name/ga/gallery/module.nix b/modules/by-name/ga/gallery/module.nix
deleted file mode 100644
index a5237e6..0000000
--- a/modules/by-name/ga/gallery/module.nix
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.sils.gallery;
-in {
- options.sils.gallery = {
- enable = lib.mkEnableOption "a stateful static gallery site";
- domain = lib.mkOption {
- type = lib.types.str;
- };
- };
- config = lib.mkIf cfg.enable {
- vhack.nginx.enable = true;
- services.nginx.virtualHosts."${cfg.domain}" = {
- forceSSL = true;
- enableACME = true;
- root = "/srv/${cfg.domain}";
- };
- };
-}
diff --git a/modules/by-name/gi/git-server/css.nix b/modules/by-name/gi/git-server/css.nix
deleted file mode 100644
index 7d0ad06..0000000
--- a/modules/by-name/gi/git-server/css.nix
+++ /dev/null
@@ -1,119 +0,0 @@
-{
- cgitPkg,
- pkgs,
-}: let
- /*
- Adapted from `https://git.qyliss.net/nixlib/sys/atuin.nix`, originally distributed under
- the MIT license.
- */
- cgitCss =
- pkgs.runCommand "cgit-extra.css" {
- licenseHeader = ''
- /*
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License v2 as published
- * by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * See <https://www.gnu.org/licenses/>.
- */
-
- '';
-
- # Adapted from
- # <https://git.causal.agency/src/plain/www/git.causal.agency/custom.css>,
- # distributed as a Larger Work under a Secondary License,
- # as permitted by the terms of the
- # Mozilla Public License Version 2.0.
- extraCss = ''
- * { line-height: 1.25em; }
-
- article {
- font-family: sans-serif;
- max-width: 70ch;
- margin-left: auto;
- margin-right: auto;
- }
-
- div#cgit {
- margin: auto;
- font-family: monospace;
- -moz-tab-size: 4;
- tab-size: 4;
- display: table;
- }
-
- div#cgit table#header {
- margin-left: auto;
- margin-right: auto;
- }
- div#cgit table#header td.logo {
- display: none;
- }
- div#cgit table#header td.main {
- font-size: 1em;
- font-weight: bold;
- }
- div#cgit table#header td.sub {
- border-top: none;
- }
- div#cgit table.tabs {
- margin-left: auto;
- margin-right: auto;
- border-bottom: none;
- }
- div#cgit div.content {
- border-bottom: none;
- min-width: 108ch;
- }
- div#cgit div.content div#summary {
- display: table;
- margin-left: auto;
- margin-right: auto;
- }
- div#cgit div.notes {
- border: none;
- background: transparent;
- padding: 0;
- }
- div#cgit table.list {
- margin-left: auto;
- margin-right: auto;
- }
- div#cgit table.list th a {
- color: inherit;
- }
- div#cgit table.list tr:nth-child(even) {
- background: inherit;
- }
- div#cgit table.list tr:hover {
- background: inherit;
- }
- div#cgit table.list tr.nohover-highlight:hover:nth-child(even) {
- background: inherit;
- }
- div#cgit div.footer {
- font-size: 1em;
- margin-top: 0;
- }
-
- div#cgit table.blob td.linenumbers:nth-last-child(3) {
- display: none;
- }
-
- div#cgit table.blob td.linenumbers a:target {
- color: goldenrod;
- text-decoration: underline;
- outline: none;
- }
- '';
- passAsFile = ["licenseHeader" "extraCss"];
- } ''
- cat $licenseHeaderPath ${cgitPkg}/cgit/cgit.css $extraCssPath > $out
- '';
-in
- cgitCss
diff --git a/modules/by-name/gi/git-server/module.nix b/modules/by-name/gi/git-server/module.nix
deleted file mode 100644
index db35897..0000000
--- a/modules/by-name/gi/git-server/module.nix
+++ /dev/null
@@ -1,188 +0,0 @@
-{
- config,
- lib,
- pkgs,
- ...
-}: let
- cfg = config.vhack.git-server;
-
- cgitCss = import ./css.nix {
- inherit pkgs;
- cgitPkg =
- config.services.cgit."${cfg.domain}".package;
- };
-in {
- options.vhack.git-server = {
- enable = lib.mkEnableOption ''
- a lightweight git-server, realised with cgit and gitolite.
- '';
-
- domain = lib.mkOption {
- type = lib.types.str;
- default = "git.vhack.eu";
- description = ''
- The domain this git instance will run under.
- '';
- };
-
- gitolite = {
- adminPubkey = lib.mkOption {
- description = ''
- The initial key to use for gitolite. This will only be used for the initial
- clone of the `gitolite-admin` repository.
- '';
- type = lib.types.str;
- default = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAe4o1PM6VasT3KZNl5NYvgkkBrPOg36dqsywd10FztS openpgp:0x21D20D6A";
- };
- };
- };
-
- config = lib.mkIf cfg.enable {
- programs.git = {
- enable = true;
- config = {
- init = {
- defaultBranch = "main";
- };
- };
- };
-
- # Needed for the nginx proxy and the virtual host
- vhack = {
- nginx.enable = true;
- persist.directories = [
- {
- directory = "/var/lib/gitolite";
- user = "git";
- group = "git";
- mode = "0755";
- }
- ];
- };
-
- services = {
- gitolite = {
- inherit (cfg.gitolite) adminPubkey;
- enable = true;
- dataDir = "/var/lib/gitolite";
- user = "git";
- group = "git";
- extraGitoliteRc = ''
- $RC{UMASK} = 0027; # Enable group access, important for cgit.
-
- # Enable modifing git variables (for cgit.owner and such things)
- # These must be enable in the gitolite-admin repo (option user-configs = ...)
- push( @{$RC{ENABLE}}, 'config' );
- push( @{$RC{ENABLE}}, 'git-config' );
-
- push( @{$RC{ENABLE}}, 'expand-deny-messages' );
- push( @{$RC{ENABLE}}, 'Motd' );
-
- push( @{$RC{ENABLE}}, 'cgit' );
- '';
- };
-
- cgit."${cfg.domain}" = {
- enable = true;
- package = pkgs.cgit-pink;
- scanPath = "${config.services.gitolite.dataDir}/repositories";
- user = "git";
- group = "git";
- settings = {
- branch-sort = "age";
-
- # Allow users to download a repo checkout with these compression formats
- snapshots = ["tar.gz" "zip"];
- # The template used to generate the clone url for https clone.
- clone-url = [
- "https://${cfg.domain}/$CGIT_REPO_URL"
- "ssh://git@${cfg.domain}/$CGIT_REPO_URL"
- ];
- enable-http-clone = true;
-
- # TODO: We might want to add an logo and readme here <2024-07-31>
- # logo = "<url>";
- # root-readme = "/some/readme/file"
- root-desc = "The cgit instance of ${cfg.domain}!";
- root-title = "${
- lib.strings.toUpper (builtins.substring 0 1 cfg.domain) + builtins.substring 1 (builtins.stringLength cfg.domain) cfg.domain
- } cgit instace";
-
- # Set the default maximum statistics period. Valid values are "week",
- # "month", "quarter" and "year".
- max-stats = "week";
-
- readme = [
- ":README.md"
- ":readme.md"
- ":README.mkd"
- ":readme.mkd"
- ":README.rst"
- ":readme.rst"
- ":README.html"
- ":readme.html"
- ":README.htm"
- ":readme.htm"
- ":README.txt"
- ":readme.txt"
- ":README"
- ":readme"
- ":INSTALL.md"
- ":install.md"
- ":INSTALL.mkd"
- ":install.mkd"
- ":INSTALL.rst"
- ":install.rst"
- ":INSTALL.html"
- ":install.html"
- ":INSTALL.htm"
- ":install.htm"
- ":INSTALL.txt"
- ":install.txt"
- ":INSTALL"
- ":install"
- ];
-
- enable-blame = true;
- enable-commit-graph = true;
- enable-subject-links = true;
- enable-follow-links = true;
- enable-index-links = true;
- enable-index-owner = true;
-
- # NOTE: This allows cgit to take configuration from the bare git repositories:
- # All `repo.<key>` can be set by setting `cgit.<key>` in the git config. E.g.:
- # setting the owner (i.e. `repo.owner`) would be done by setting the
- # `cgit.owner` config. All repo options are outline in the cgitrc (5) man page.
- enable-git-config = true;
-
- # Remove the `.git` suffix from scanned repositories (this must be set _before_ `scan-path`)
- remove-suffix = true;
-
- css = "/custom_cgit.css";
-
- # This is a number of path elements to treat as section.
- # `-1` means that we treat the last element as name, all others as sections
- section-from-path = -1;
-
- project-list = "${config.services.gitolite.dataDir}/projects.list";
-
- # TODO: We might want to use the kernel.org `libravatar.lua` email-filter <2024-07-31>
- source-filter = "${config.services.cgit."${cfg.domain}".package}/lib/cgit/filters/syntax-highlighting.py";
- about-filter = "${config.services.cgit."${cfg.domain}".package}/lib/cgit/filters/about-formatting.sh";
- };
- };
-
- nginx.virtualHosts."${cfg.domain}" = {
- enableACME = true;
- forceSSL = true;
-
- locations = {
- "= /custom_cgit.css" = {
- alias = cgitCss.outPath;
- };
- };
- };
- };
- };
-}
diff --git a/modules/by-name/im/impermanence/module.nix b/modules/by-name/im/impermanence/module.nix
deleted file mode 100644
index 1c916e2..0000000
--- a/modules/by-name/im/impermanence/module.nix
+++ /dev/null
@@ -1,30 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.persist;
-in {
- options.vhack.persist = {
- enable = lib.mkEnableOption "impermanence";
-
- directories = lib.mkOption {
- description = "The list of directories to persist";
- type = lib.types.listOf (lib.types.coercedTo lib.types.str (d: {directory = d;}) (lib.types.attrsOf lib.types.anything));
- };
- };
-
- config = lib.mkIf cfg.enable {
- environment.persistence."/srv" = {
- hideMounts = true;
- directories =
- [
- "/etc/nixos"
- ]
- ++ cfg.directories;
- files = [
- "/etc/machine-id"
- ];
- };
- };
-}
diff --git a/modules/by-name/in/invidious-router/module.nix b/modules/by-name/in/invidious-router/module.nix
deleted file mode 100644
index f85a06c..0000000
--- a/modules/by-name/in/invidious-router/module.nix
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- config,
- lib,
- pkgsUnstable,
- ...
-}: let
- cfg = config.vhack.invidious-router;
-in {
- options.vhack.invidious-router = {
- enable = lib.mkEnableOption "invidious-router";
- domain = lib.mkOption {
- type = lib.types.str;
- description = "The domain invidious-router should be served on";
- };
- extraDomains = lib.mkOption {
- type = lib.types.listOf lib.types.str;
- default = [];
- description = "Addtional domains invidious-router should be served on";
- };
- };
- config = lib.mkIf cfg.enable {
- services.invidious-router = {
- enable = true;
- package = pkgsUnstable.invidious-router;
- settings = {
- app = {
- listen = "127.0.0.1:8050";
- enable_youtube_fallback = false;
- reload_instance_list_interval = "60s";
- not_available_message = ''
- No available invidious instance found!
- [link]View this video on YouTube[/link], a proprietary
- platform that collects and uses your data without respecting
- your privacy.
- '';
- };
- api = {
- enabled = true;
- url = "https://api.invidious.io/instances.json";
- filter_regions = false;
- allowed_regions = [
- "AT"
- "DE"
- "CH"
- ];
- };
- healthcheck = {
- path = "/watch?v=uSvJaYxRoB4";
- allowed_status_codes = [
- 200
- ];
- timeout = "1s";
- interval = "10s";
- filter_by_response_time = {
- enabled = true;
- qty_of_top_results = 4;
- };
- minimum_ratio = 0.2;
- remove_no_ratio = false;
- text_not_present = "YouTube is currently trying to block Invidious instances";
- };
- };
- nginx = {
- enable = true;
- inherit (cfg) domain extraDomains;
- };
- };
- vhack.nginx.enable = true;
- };
-}
diff --git a/modules/by-name/ma/mail/module.nix b/modules/by-name/ma/mail/module.nix
deleted file mode 100644
index 55f2fb8..0000000
--- a/modules/by-name/ma/mail/module.nix
+++ /dev/null
@@ -1,167 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.mail;
- all_admins = [
- "sils@vhack.eu"
- "soispha@vhack.eu"
- "nightingale@vhack.eu"
- ];
-in {
- options.vhack.mail = {
- enable = lib.mkEnableOption "sophisticated mail setup with simple-nixos-mailserver";
- fqdn = lib.mkOption {
- type = lib.types.str;
- description = "The fqdn mailserver should be served on.";
- };
- };
-
- config = lib.mkIf cfg.enable {
- vhack.persist.directories = [
- {
- directory = "/var/lib/mail/backup";
- user = "virtualMail";
- group = "virtualMail";
- mode = "0700";
- }
- {
- directory = "/var/lib/mail/sieve";
- user = "virtualMail";
- group = "virtualMail";
- mode = "0700";
- }
- {
- directory = "/var/lib/mail/vmail";
- user = "virtualMail";
- group = "virtualMail";
- mode = "0700";
- }
- {
- directory = "/var/lib/mail/dkim";
- user = "opendkim";
- group = "opendkim";
- mode = "0700";
- }
- {
- directory = "/var/lib/postfix/data";
- user = "postfix";
- group = "postfix";
- mode = "0700";
- }
- {
- directory = "/var/lib/postfix/queue";
- user = "postfix";
- group = "postfix";
- mode = "0700";
- }
- {
- directory = "/var/lib/rspamd";
- user = "rspamd";
- group = "rspamd";
- mode = "0700";
- }
- ];
- vhack.nginx.enable = true;
- security.acme.certs = {
- "${cfg.fqdn}" = {
- domain = cfg.fqdn;
- };
- };
- mailserver = {
- enable = true;
- inherit (cfg) fqdn;
-
- useFsLayout = true;
-
- extraVirtualAliases = {
- "abuse@vhack.eu" = all_admins;
- "postmaster@vhack.eu" = all_admins;
- "admin@vhack.eu" = all_admins;
- };
-
- mailDirectory = "/var/lib/mail/vmail";
- dkimKeyDirectory = "/var/lib/mail/dkim";
- sieveDirectory = "/var/lib/mail/sieve";
- backup.snapshotRoot = "/var/lib/mail/backup";
-
- enableImap = false;
- enableImapSsl = true;
- enablePop3 = false;
- enablePop3Ssl = true;
- # SMTP
- enableSubmission = false;
- enableSubmissionSsl = true;
- openFirewall = true;
-
- keyFile = "/var/lib/acme/${cfg.fqdn}/key.pem";
- certificateScheme = "acme";
- certificateFile = "/var/lib/acme/${cfg.fqdn}/fullchain.pem";
-
- domains = [
- "vhack.eu"
-
- "s-schoeffel.de"
- "b-peetz.de"
-
- "sils.li"
- "nightingale.sils.li"
- "sils.sils.li"
- ];
-
- loginAccounts = {
- "sils@vhack.eu" = {
- hashedPassword = "$2b$05$RW/Svgk7iGxvP5W7ZwUZ1e.a3fj4fteevb2MtfFYYD0d1DQ17y9Fm";
- };
- "soispha@vhack.eu" = {
- hashedPassword = "$2b$05$XX36sJuHNbTFvi8DFldscOeQBHahluSkiUqD9QGzQaET7NJusSuQW";
- };
-
- "benedikt.peetz@b-peetz.de" = {
- hashedPassword = "$2b$05$MfET8utot2OolPZNASqoDe4VXNoG2chnEWhdfQ2E92mit0TvI2gBy";
- aliases = ["@b-peetz.de"];
- };
- "silas.schoeffel@s-schoeffel.de" = {
- hashedPassword = "$2b$05$Qb8rl7ncpCcTbsSdsduJBuOITp8RTD6sfOTjuxJsVtD9vjAYY9n8e";
- aliases = ["@s-schoeffel.de"];
- };
-
- "nightingale@vhack.eu" = {
- hashedPassword = "$2b$05$nDKVVq1EktKXWqGFhnOLP.plLovXFyvWSuptK9GIkxA5DScKFx6YS";
- aliases = [
- "@nightingale.sils.li"
- ];
- };
- "sils@sils.li" = {
- hashedPassword = "$2b$05$Ebzh2ZhuWkz1p4tqJ172IejNZg10FtCxPDY4k6umYrpirXg7ezIRq";
- aliases = [
- "@sils.sils.li"
- "@sils.li"
- ];
- };
-
- # Mail-Account used by hosted software
- "mastodon@vhack.eu" = {
- hashedPassword = "$2b$05$pSby3x2p3cHg0FyAE8IiJ.nYUqtAIR10JA8HNpHwMAiLXqc.ltSK.";
- };
- "peertube@vhack.eu" = {
- hashedPassword = "$y$j9T$hyWQ8Awd2Xrc6qsK.2hwE1$LxACfaeW.yHGbkQL95dWtID9.zXL/aMwT6lp.yU/0g0";
- };
- };
- };
-
- users = {
- users = {
- knot-resolver.uid = config.vhack.constants.ids.uids.knot-resolver;
- redis-rspamd.uid = config.vhack.constants.ids.uids.redis-rspamd;
- rspamd.uid = config.vhack.constants.ids.uids.rspamd;
- };
- groups = {
- knot-resolver.gid = lib.mkForce config.vhack.constants.ids.gids.knot-resolver;
- redis-rspamd.gid = config.vhack.constants.ids.gids.redis-rspamd;
- rspamd.gid = config.vhack.constants.ids.gids.rspamd;
- };
- };
- };
-}
diff --git a/modules/by-name/ma/mastodon/module.nix b/modules/by-name/ma/mastodon/module.nix
deleted file mode 100644
index 84f3ec8..0000000
--- a/modules/by-name/ma/mastodon/module.nix
+++ /dev/null
@@ -1,128 +0,0 @@
-{
- config,
- pkgs,
- lib,
- ...
-}: let
- emailAddress = "mastodon@vhack.eu";
- applyPatches = pkg:
- pkg.overrideAttrs (attrs: {
- patches = (attrs.patches or []) ++ [./patches/0001-feat-treewide-Increase-character-limit-to-5000-in-me.patch];
- });
- cfg = config.vhack.mastodon;
-in {
- options.vhack.mastodon = {
- enable = lib.mkEnableOption "a mastodon instance";
- domain = lib.mkOption {
- type = lib.types.str;
- description = "The Domain mastodon should be served on";
- example = "mastodon.vhack.eu";
- };
- enableTLD = lib.mkEnableOption "using the tld as handle, configured via
- webfinger (note: this requires the tld to point to the same server as domain)";
- tld = lib.mkOption {
- type = lib.types.nullOr lib.types.str;
- default = null;
- example = "vhack.eu";
- };
- mailPwFile = lib.mkOption {
- type = lib.types.path;
- description = "The age encrypted mail password file passed to agenix";
- };
- };
- config = lib.mkIf cfg.enable {
- age.secrets.mastodonMail = {
- file = cfg.mailPwFile;
- mode = "700";
- owner = "mastodon";
- group = "mastodon";
- };
-
- vhack = {
- persist.directories = [
- {
- directory = "/var/lib/mastodon";
- user = "mastodon";
- group = "mastodon";
- mode = "0700";
- }
- ];
-
- postgresql.enable = true;
-
- nginx.enable = true;
- };
-
- services.mastodon = {
- enable = true;
-
- package = applyPatches pkgs.mastodon;
-
- # Unstable Mastodon package, used if
- # security updates aren't backported.
- #package = applyPatches pkgsUnstable.mastodon;
-
- localDomain =
- if cfg.enableTLD
- then cfg.tld
- else cfg.domain;
- smtp = {
- authenticate = true;
- createLocally = false;
- fromAddress = emailAddress;
- user = emailAddress;
- host = "mail.foss-syndicate.org";
- passwordFile = config.age.secrets.mastodonMail.path;
- };
- streamingProcesses = 3; # Number of Cores - 1
- extraConfig = {
- WEB_DOMAIN = cfg.domain;
- EMAIL_DOMAIN_ALLOWLIST = "vhack.eu|sils.li";
- };
- };
-
- services.nginx = {
- enable = true;
- recommendedProxySettings = true; # required for redirections to work
- virtualHosts = {
- "${cfg.domain}" = {
- root = "${config.services.mastodon.package}/public/";
- # mastodon only supports https, but you can override this if you offload tls elsewhere.
- forceSSL = true;
- enableACME = true;
-
- locations = {
- "/system/".alias = "/var/lib/mastodon/public-system/";
- "/".tryFiles = "$uri @proxy";
- "@proxy" = {
- proxyPass = "http://unix:/run/mastodon-web/web.socket";
- proxyWebsockets = true;
- };
- "/api/v1/streaming/" = {
- proxyPass = "http://unix:/run/mastodon-streaming/streaming.socket";
- proxyWebsockets = true;
- };
- };
- };
- "${cfg.tld}" =
- if cfg.enableTLD
- then {
- locations."/.well-known/webfinger".return = "301 https://${cfg.domain}$request_uri";
- }
- else {};
- };
- };
-
- users = {
- users.mastodon.uid = config.vhack.constants.ids.uids.mastodon;
- users.redis-mastodon.uid = config.vhack.constants.ids.uids.redis-mastodon;
- groups.redis-mastodon.gid = config.vhack.constants.ids.gids.redis-mastodon;
- groups.mastodon = {
- gid = config.vhack.constants.ids.gids.mastodon;
- members = [
- config.services.nginx.user
- ];
- };
- };
- };
-}
diff --git a/modules/by-name/ma/mastodon/patches/0001-feat-treewide-Increase-character-limit-to-5000-in-me.patch b/modules/by-name/ma/mastodon/patches/0001-feat-treewide-Increase-character-limit-to-5000-in-me.patch
deleted file mode 100644
index 35dc809..0000000
--- a/modules/by-name/ma/mastodon/patches/0001-feat-treewide-Increase-character-limit-to-5000-in-me.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From ab67426c53d343eee349de501767ecbbf5d211ad Mon Sep 17 00:00:00 2001
-From: Benedikt Peetz <benedikt.peetz@b-peetz.de>
-Date: Sat, 21 Dec 2024 20:07:11 +0100
-Subject: [PATCH] feat(treewide): Increase character limit to 5000 in messages
-
-The default of 500 was just not enough.
----
- .../features/compose/containers/compose_form_container.js | 2 +-
- app/validators/status_length_validator.rb | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/app/javascript/mastodon/features/compose/containers/compose_form_container.js b/app/javascript/mastodon/features/compose/containers/compose_form_container.js
-index bda2edba6..76ac65bf3 100644
---- a/app/javascript/mastodon/features/compose/containers/compose_form_container.js
-+++ b/app/javascript/mastodon/features/compose/containers/compose_form_container.js
-@@ -28,7 +28,7 @@ const mapStateToProps = state => ({
- anyMedia: state.getIn(['compose', 'media_attachments']).size > 0,
- isInReply: state.getIn(['compose', 'in_reply_to']) !== null,
- lang: state.getIn(['compose', 'language']),
-- maxChars: state.getIn(['server', 'server', 'configuration', 'statuses', 'max_characters'], 500),
-+ maxChars: state.getIn(['server', 'server', 'configuration', 'statuses', 'max_characters'], 5000),
- });
-
- const mapDispatchToProps = (dispatch) => ({
-diff --git a/app/validators/status_length_validator.rb b/app/validators/status_length_validator.rb
-index dc841ded3..9cb1ec94b 100644
---- a/app/validators/status_length_validator.rb
-+++ b/app/validators/status_length_validator.rb
-@@ -1,7 +1,7 @@
- # frozen_string_literal: true
-
- class StatusLengthValidator < ActiveModel::Validator
-- MAX_CHARS = 500
-+ MAX_CHARS = 5000
- URL_PLACEHOLDER_CHARS = 23
- URL_PLACEHOLDER = 'x' * 23
-
---
-2.47.0
-
diff --git a/modules/by-name/ma/matrix/module.nix b/modules/by-name/ma/matrix/module.nix
deleted file mode 100644
index f34ecf4..0000000
--- a/modules/by-name/ma/matrix/module.nix
+++ /dev/null
@@ -1,179 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.matrix;
- clientConfig."m.homeserver".base_url = "https://${cfg.fqdn}";
- serverConfig."m.server" = "${cfg.fqdn}:443";
- mkWellKnown = data: ''
- add_header Content-Type application/json;
- add_header Access-Control-Allow-Origin *;
- return 200 '${builtins.toJSON data}';
- '';
-in {
- options.vhack.matrix = {
- enable = lib.mkEnableOption "matrix setup based on synapse";
- fqdn = lib.mkOption {
- type = lib.types.str;
- description = "The FQDN on which matrix-synapse should be served.";
- example = "matrix.vhack.eu";
- };
- url = lib.mkOption {
- type = lib.types.str;
- description = "The url the matrix-server should be known under.";
- };
- sharedSecretFile = lib.mkOption {
- type = lib.types.path;
- description = "The age encrypted shared secret file for synapse, passed to agenix";
- };
- };
-
- config = lib.mkIf cfg.enable {
- age.secrets.matrix-synapse_registration_shared_secret = {
- file = cfg.sharedSecretFile;
- mode = "700";
- owner = "matrix-synapse";
- group = "matrix-synapse";
- };
- networking.firewall.allowedTCPPorts = [80 443];
-
- vhack = {
- persist.directories = [
- {
- directory = "/var/lib/matrix";
- user = "matrix-synapse";
- group = "matrix-synapse";
- mode = "0700";
- }
- {
- directory = "/var/lib/mautrix-whatsapp";
- user = "mautrix-whatsapp";
- group = "matrix-synapse";
- mode = "0750";
- }
- ];
-
- postgresql.enable = true;
- nginx.enable = true;
- };
-
- systemd = {
- tmpfiles.rules = [
- "d /etc/matrix 0755 matrix-synapse matrix-synapse"
- ];
- services.postgresql.postStart = ''
- $PSQL -tAc "ALTER ROLE matrix-synapse WITH ENCRYPTED PASSWORD 'synapse';"
- $PSQL -tAc "ALTER ROLE mautrix-whatsapp WITH ENCRYPTED PASSWORD 'whatsapp';"
- '';
- };
-
- services = {
- postgresql = {
- enable = true;
- ensureUsers = [
- {
- name = "matrix-synapse";
- ensureDBOwnership = true;
- }
- {
- name = "mautrix-whatsapp";
- ensureDBOwnership = true;
- }
- ];
- ensureDatabases = [
- "matrix-synapse"
- "mautrix-whatsapp"
- ];
- };
-
- nginx = {
- enable = true;
- recommendedTlsSettings = true;
- recommendedOptimisation = true;
- recommendedGzipSettings = true;
- recommendedProxySettings = true;
- virtualHosts = {
- "${cfg.url}" = {
- enableACME = true;
- forceSSL = true;
- locations = {
- "/.well-known/matrix/server".extraConfig = mkWellKnown serverConfig;
- "/.well-known/matrix/client".extraConfig = mkWellKnown clientConfig;
- };
- };
- "${cfg.fqdn}" = {
- enableACME = true;
- forceSSL = true;
- locations = {
- "/".return = "404";
- "/_matrix".proxyPass = "http://[::1]:8008";
- "/_synapse/client".proxyPass = "http://[::1]:8008";
- };
- };
- };
- };
-
- mautrix-whatsapp = {
- # FIXME(@bpeetz): This was disabled because `mautrix-whatsapp` dependends on libolm.
- # Re-enable it, when this has changed. <2024-09-06>
- enable = false;
- settings = {
- appservice = {
- database = {
- type = "postgres";
- uri = "postgres:///mautrix-whatsapp?host=/run/postgresql";
- };
- whatsapp = {
- # TODO: See https://github.com/tulir/whatsmeow/blob/efc632c008604016ddde63bfcfca8de4e5304da9/binary/proto/def.proto#L43-L64 for a list.
- # This also determines the WhatsApp icon
- browser_name = "unknown";
- };
- };
- homeserver.address = "https://${cfg.fqdn}";
- bridge.permissions = {
- "@soispha:vhack.eu" = "admin";
- "@sils:vhack.eu" = "admin";
- "@nightingale:vhack.eu" = "admin";
- };
- };
- };
-
- matrix-synapse = {
- enable = true;
- dataDir = "/var/lib/matrix";
- configFile = "/etc/matrix/matrix.conf";
- settings = {
- media_store_path = "/var/lib/matrix/media_store";
- registration_shared_secret_path = "${config.age.secrets.matrix-synapse_registration_shared_secret.path}";
- server_name = cfg.url;
- listeners = [
- {
- port = 8008;
- bind_addresses = ["::1"];
- type = "http";
- tls = false;
- x_forwarded = true;
- resources = [
- {
- names = ["client" "federation"];
- compress = true;
- }
- ];
- }
- ];
- };
- };
- };
- users = {
- users = {
- matrix-synapse.uid = config.vhack.constants.ids.uids.matrix-synapse;
- mautrix-whatsapp = {
- uid = config.vhack.constants.ids.uids.mautrix-whatsapp;
- group = "matrix-synapse";
- };
- };
- groups.matrix-synapse.gid = config.vhack.constants.ids.gids.matrix-synapse;
- };
- };
-}
diff --git a/modules/by-name/mi/miniflux/module.nix b/modules/by-name/mi/miniflux/module.nix
deleted file mode 100644
index 0075bca..0000000
--- a/modules/by-name/mi/miniflux/module.nix
+++ /dev/null
@@ -1,55 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.miniflux;
-in {
- options.vhack.miniflux = {
- enable = lib.mkEnableOption "miniflux, an simple web rss reading software";
- domain = lib.mkOption {
- type = lib.types.str;
- description = "The primary domain miniflux should be served on";
- };
- extraDomains = lib.mkOption {
- type = lib.types.listOf lib.types.str;
- description = "Additional domains to serve miniflux on";
- default = [];
- };
- adminCredentialsFile = lib.mkOption {
- type = lib.types.path;
- description = "The age encrypted admin credentials file passed to agenix";
- };
- };
- config = lib.mkIf cfg.enable {
- age.secrets = {
- minifluxAdmin = {
- file = cfg.adminCredentialsFile;
- mode = "700";
- owner = "root";
- group = "root";
- };
- };
- services.miniflux = {
- enable = true;
- config = {
- LISTEN_ADDR = "127.0.0.1:5892";
- };
- adminCredentialsFile = config.age.secrets.minifluxAdmin.path;
- };
-
- vhack = {
- nginx.enable = true;
- postgresql.enable = true;
- };
- services.nginx = {
- virtualHosts.${cfg.domain} = {
- locations."/".proxyPass = "http://${config.services.miniflux.config.LISTEN_ADDR}";
-
- enableACME = true;
- forceSSL = true;
- serverAliases = cfg.extraDomains;
- };
- };
- };
-}
diff --git a/modules/by-name/mu/murmur/module.nix b/modules/by-name/mu/murmur/module.nix
deleted file mode 100644
index 5cc6f7d..0000000
--- a/modules/by-name/mu/murmur/module.nix
+++ /dev/null
@@ -1,80 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.murmur;
-in {
- options.vhack.murmur = {
- enable = lib.mkEnableOption "murmur, a mumble server software";
- murmurStore = lib.mkOption {
- type = lib.types.str;
- default = "/var/lib/murmur";
- description = "The location of murmurs data dir.";
- };
- host = lib.mkOption {
- type = lib.types.str;
- description = "The domain murmur should be served on.";
- example = "mumble.vhack.eu";
- };
- url = lib.mkOption {
- type = lib.types.str;
- description = "The url this instance should be registered under. Note that
- this is not the domain mumur is served on";
- example = "vhack.eu";
- };
- name = lib.mkOption {
- type = lib.types.str;
- description = "The name this instance should be registered under.";
- example = "vhack";
- };
- };
- config = lib.mkIf cfg.enable {
- vhack.persist.directories = [
- {
- directory = cfg.murmurStore;
- user = "murmur";
- group = "murmur";
- mode = "0700";
- }
- ];
-
- services.murmur = {
- enable = true;
- openFirewall = true;
- welcometext = ''
- <b>You never get a second chance to make a first impression</b><br>
-
- The entire team of [name of the company] is thrilled to welcome you on board. We hope you’ll do some amazing work here!
- '';
- sslKey = "${cfg.murmurStore}/key.pem";
- sslCert = "${cfg.murmurStore}/fullchain.pem";
-
- registerUrl = cfg.url;
- registerName = cfg.name;
- registerHostname = cfg.host;
- hostName = cfg.host;
- clientCertRequired = true;
- bandwidth = 7200000;
- };
-
- security.acme.certs.murmur = {
- domain = cfg.host;
- postRun =
- /*
- bash
- */
- ''
- set -x
- rm "${cfg.murmurStore}/key.pem"
- rm "${cfg.murmurStore}/fullchain.pem"
-
- cp key.pem "${cfg.murmurStore}";
- cp fullchain.pem "${cfg.murmurStore}";
-
- chown murmur:murmur "${cfg.murmurStore}/key.pem"
- chown murmur:murmur "${cfg.murmurStore}/fullchain.pem"
- '';
- };
- };
-}
diff --git a/modules/by-name/ne/nextcloud/module.nix b/modules/by-name/ne/nextcloud/module.nix
deleted file mode 100644
index 2e40970..0000000
--- a/modules/by-name/ne/nextcloud/module.nix
+++ /dev/null
@@ -1,78 +0,0 @@
-{
- config,
- pkgs,
- lib,
- ...
-}: let
- cfg = config.vhack.nextcloud;
-in {
- options.vhack.nextcloud = {
- enable = lib.mkEnableOption "a sophisticated nextcloud setup";
- package = lib.mkOption {
- type = lib.types.package;
- default = pkgs.nextcloud31;
- description = "The nextcloud package to use";
- };
- hostname = lib.mkOption {
- type = lib.types.str;
- description = "The nextcloud hostname (fqdn)";
- };
- adminpassFile = lib.mkOption {
- type = lib.types.path;
- description = "The age encrypted admin password file";
- };
- };
- config = lib.mkIf cfg.enable {
- vhack = {
- nginx.enable = true;
- postgresql.enable = true;
- persist.directories = [
- "/var/lib/nextcloud"
- ];
- };
- age.secrets = {
- adminpassFile = {
- file = cfg.adminpassFile;
- mode = "0700";
- owner = "nextcloud";
- group = "nextcloud";
- };
- };
-
- services = {
- nextcloud = {
- enable = true;
- configureRedis = true;
- config = {
- adminuser = "admin";
- adminpassFile = config.age.secrets.adminpassFile.path;
- dbname = "nextcloud";
- dbuser = "nextcloud";
- dbtype = "pgsql";
- };
- database.createLocally = true;
- hostName = cfg.hostname;
- https = true;
- maxUploadSize = "5G";
- package = cfg.package;
- settings = {
- default_phone_region = "DE";
- };
- };
- nginx.virtualHosts.${cfg.hostname} = {
- forceSSL = true;
- enableACME = true;
- };
- };
- users = {
- users = {
- "nextcloud".uid = config.vhack.constants.ids.uids.nextcloud;
- "redis-nextcloud".uid = config.vhack.constants.ids.uids.redis-nextcloud;
- };
- groups = {
- "nextcloud".gid = config.vhack.constants.ids.gids.nextcloud;
- "redis-nextcloud".gid = config.vhack.constants.ids.gids.redis-nextcloud;
- };
- };
- };
-}
diff --git a/modules/by-name/ng/nginx/module.nix b/modules/by-name/ng/nginx/module.nix
deleted file mode 100644
index fa3337d..0000000
--- a/modules/by-name/ng/nginx/module.nix
+++ /dev/null
@@ -1,74 +0,0 @@
-{
- lib,
- config,
- ...
-}: let
- mkRedirect = _: value: {
- forceSSL = true;
- enableACME = true;
- locations."/".return = "301 ${value}$request_uri";
- };
-
- redirects = builtins.mapAttrs mkRedirect cfg.redirects;
-
- cfg = config.vhack.nginx;
-in {
- options.vhack.nginx = {
- enable = lib.mkEnableOption ''
- a default nginx config.
- '';
-
- selfsign = lib.mkOption {
- type = lib.types.bool;
- default = false;
- description = ''
- Whether to selfsign the acme certificates. This should only
- really be useful for tests.
- '';
- };
-
- redirects = lib.mkOption {
- type = lib.types.attrsOf lib.types.str;
- default = {};
- description = ''
- An attrset of redirects to add.
- The keys are the domain that should than be redirected to the url specified as
- value.
- '';
- };
- };
-
- config = lib.mkIf cfg.enable {
- vhack.persist.directories = [
- "/var/lib/acme"
- ];
-
- users = {
- users.acme = {
- uid = config.vhack.constants.ids.uids.acme;
- group = "acme";
- };
- groups.acme.gid = config.vhack.constants.ids.gids.acme;
- };
-
- security.acme = {
- acceptTerms = true;
- defaults = {
- email = "admin@vhack.eu";
- webroot = "/var/lib/acme/acme-challenge";
-
- # Avoid spamming the acme server, if we run in a test, and only really want self-signed
- # certificates
- server = lib.mkIf cfg.selfsign "https://127.0.0.1";
- };
- };
-
- networking.firewall = {
- allowedTCPPorts = [80 443];
- };
- services.nginx = {
- enable = true;
- virtualHosts = redirects;
- };
- };
-}
diff --git a/modules/by-name/ni/nix-sync/internal_module.nix b/modules/by-name/ni/nix-sync/internal_module.nix
deleted file mode 100644
index 4e28586..0000000
--- a/modules/by-name/ni/nix-sync/internal_module.nix
+++ /dev/null
@@ -1,299 +0,0 @@
-{
- config,
- lib,
- pkgs,
- ...
-}: let
- cfg = config.services.nix-sync;
- esa = lib.strings.escapeShellArg;
-
- mkTimer = name: repo: {
- description = "Nix sync ${name} timer";
- wantedBy = ["timers.target"];
- timerConfig = {
- OnUnitActiveSec = repo.interval;
- };
- wants = ["network-online.target"];
- after = ["network-online.target"];
- };
-
- parents = path: let
- split_path = builtins.split "/" path;
- filename = builtins.elemAt split_path (builtins.length split_path - 1);
- path_build =
- lib.strings.removeSuffix "/" (builtins.replaceStrings [filename] [""] path);
- final_path =
- if filename == ""
- then parents path_build
- else path_build;
- in
- final_path;
-
- mkUnit = name: repo: let
- optionalPathSeparator =
- if lib.strings.hasPrefix "/" repo.path
- then ""
- else "/";
- /*
- * `ln` tries to create a symlink in the directory, if the target ends with a '/',
- * thus remove it.
- */
- repoPath = lib.strings.removeSuffix "/" repo.path;
-
- repoCachePath = cfg.cachePath + optionalPathSeparator + repo.path;
- execStartScript = pkgs.writeScript "nix-sync-exec" ''
- #! /usr/bin/env dash
- export XDG_CACHE_HOME="$CACHE_DIRECTORY";
- cd ${esa repoCachePath};
-
- git fetch
- origin="$(git rev-parse @{u})";
- branch="$(git rev-parse @)";
-
- if ! [ "$origin" = "$branch" ]; then
- git pull --rebase;
-
- out_paths=$(mktemp);
- nix build . --print-out-paths --experimental-features 'nix-command flakes' > "$out_paths";
- [ "$(wc -l < "$out_paths")" -gt 1 ] && { echo "To many out-paths"; exit 1; }
- out_path="$(cat "$out_paths")";
- rm ${esa repoPath};
- ln -s "$out_path" ${esa repoPath};
- rm "$out_paths";
- fi
- '';
- execStartPreScript = ''
- export XDG_CACHE_HOME="$CACHE_DIRECTORY";
-
- if ! [ -d ${esa repoCachePath}/.git ]; then
- mkdir --parents ${esa repoCachePath};
- git clone ${esa repo.uri} ${esa repoCachePath};
-
- out_paths=$(mktemp);
- nix build ${esa repoCachePath} --print-out-paths --experimental-features 'nix-command flakes' > "$out_paths";
- [ "$(wc -l < "$out_paths")" -gt 1 ] && { echo "To many out-paths"; exit 1; }
- out_path="$(cat "$out_paths")";
- ln -s "$out_path" ${esa repoPath};
- rm "$out_paths";
- fi
-
- if ! [ -L ${esa repoPath} ]; then
- cd ${esa repoCachePath};
-
- git pull --rebase;
-
- out_paths=$(mktemp);
- nix build . --print-out-paths --experimental-features 'nix-command flakes' > "$out_paths";
- [ "$(wc -l < "$out_paths")" -gt 1 ] && { echo "To many out-paths"; exit 1; }
- out_path="$(cat "$out_paths")";
-
- if [ -d ${esa repoPath} ]; then
- rm -d ${esa repoPath};
- else
- mkdir --parents "$(dirname ${esa repoPath})";
- fi
- [ -e ${esa repoPath} ] && rm ${esa repoPath};
-
- ln -s "$out_path" ${esa repoPath};
- rm "$out_paths";
- fi
- '';
- in {
- description = "Nix Sync ${name}";
- wantedBy = ["default.target"];
- after = ["network.target"];
- path = with pkgs; [openssh git nix mktemp coreutils dash];
- preStart = execStartPreScript;
-
- serviceConfig = {
- TimeoutSec = 0;
- ExecStart = execStartScript;
- Restart = "on-abort";
- # User and group
- User = cfg.user;
- Group = cfg.group;
- # Runtime directory and mode
- RuntimeDirectory = "nix-sync";
- RuntimeDirectoryMode = "0750";
- # Cache directory and mode
- CacheDirectory = "nix-sync";
- CacheDirectoryMode = "0750";
- # Logs directory and mode
- LogsDirectory = "nix-sync";
- LogsDirectoryMode = "0750";
- # Proc filesystem
- ProcSubset = "all";
- ProtectProc = "invisible";
- # New file permissions
- UMask = "0027"; # 0640 / 0750
- # Capabilities
- AmbientCapabilities = ["CAP_CHOWN"];
- CapabilityBoundingSet = ["CAP_CHOWN"];
- # Security
- NoNewPrivileges = true;
- # Sandboxing (sorted by occurrence in https://www.freedesktop.org/software/systemd/man/systemd.exec.html)
- ReadWritePaths = ["${esa (parents repo.path)}" "-${esa (parents repoCachePath)}" "-${esa cfg.cachePath}"];
- ReadOnlyPaths = ["/nix"]; # TODO: Should be irrelevant, as we have ProtectSystem=Strict <2024-06-01>
- ProtectSystem = "strict";
- ProtectHome = true;
- PrivateTmp = true;
- PrivateDevices = true;
- ProtectHostname = true;
- ProtectClock = true;
- ProtectKernelTunables = true;
- ProtectKernelModules = true;
- ProtectKernelLogs = true;
- ProtectControlGroups = true;
- RestrictAddressFamilies = ["AF_UNIX" "AF_INET" "AF_INET6"];
- RestrictNamespaces = true;
- LockPersonality = true;
- MemoryDenyWriteExecute = true;
- RestrictRealtime = true;
- RestrictSUIDSGID = true;
- RemoveIPC = true;
- PrivateMounts = true;
- # System Call Filtering
- SystemCallArchitectures = "native";
- SystemCallFilter = ["~@cpu-emulation @debug @keyring @mount @obsolete @privileged @setuid"];
- };
- };
-
- services =
- lib.mapAttrs' (name: repo: {
- name = "nix-sync-${name}";
- value = mkUnit name repo;
- })
- cfg.repositories;
- timers =
- lib.mapAttrs' (name: repo: {
- name = "nix-sync-${name}";
- value = mkTimer name repo;
- })
- cfg.repositories;
-
- # generate the websites directory, so systemd can mount it read write
- generatedDirectories =
- lib.mapAttrsToList (
- _: repo: "d ${esa (parents repo.path)} 0755 ${cfg.user} ${cfg.group}"
- )
- cfg.repositories;
-
- repositoryType = lib.types.submodule ({name, ...}: {
- options = {
- name = lib.mkOption {
- internal = true;
- default = name;
- type = lib.types.str;
- description = "The name that should be given to this unit.";
- };
-
- path = lib.mkOption {
- type = lib.types.str;
- description = "The path at which to sync the repository";
- };
-
- uri = lib.mkOption {
- type = lib.types.str;
- example = "ssh://user@example.com:/~[user]/path/to/repo.git";
- description = ''
- The URI of the remote to be synchronized. This is only used in the
- event that the directory does not already exist. See
- <link xlink:href="https://git-scm.com/docs/git-clone#_git_urls"/>
- for the supported URIs.
- '';
- };
-
- extraSettings = lib.mkOption {
- type = lib.types.attrsOf lib.types.anything;
- example = lib.literalExpression ''
- {
- locations."/.well-known/openpgpkey/hu/" = {
- extraConfig = \'\'
- default_type application/octet-stream;
-
- add_header Access-Control-Allow-Origin * always;
- \'\';
- };
- }
- '';
- description = ''
- Extra config to add the the nginx virtual host.
- '';
- };
-
- interval = lib.mkOption {
- type = lib.types.int;
- default = 500;
- description = ''
- The interval, specified in seconds, at which the synchronization will
- be triggered.
- '';
- };
- };
- });
-in {
- options = {
- services.nix-sync = {
- enable = lib.mkEnableOption "nix-sync services";
-
- user = lib.mkOption {
- type = lib.types.str;
- default = "nix-sync";
- description = lib.mdDoc "User account under which nix-sync units runs.";
- };
-
- group = lib.mkOption {
- type = lib.types.str;
- default = "nix-sync";
- description = lib.mdDoc "Group account under which nix-sync units runs.";
- };
-
- cachePath = lib.mkOption {
- type = lib.types.str;
- default = "/var/lib/nix-sync";
- description = lib.mdDoc ''
- Where to cache git directories. Should not end with a slash ("/")
- '';
- };
-
- repositories = lib.mkOption {
- type = with lib.types; attrsOf repositoryType;
- description = ''
- The repositories that should be synchronized.
- '';
- };
- };
- };
-
- config = lib.mkIf cfg.enable {
- assertions = [
- {
- assertion = !lib.strings.hasSuffix "/" cfg.cachePath;
- message = "Your cachePath ('${cfg.cachePath}') ends with a slash ('/'), please use: '${lib.strings.removeSuffix "/" cfg.cachePath}'.";
- }
- ];
- systemd = {
- tmpfiles.rules =
- generatedDirectories;
-
- inherit services timers;
- };
- users.users =
- if cfg.user == "nix-sync"
- then {
- nix-sync = {
- group = "${cfg.group}";
- isSystemUser = true;
- };
- }
- else lib.warnIf (cfg.user != "nix-sync") "The user (${cfg.user}) is not \"nix-sync\", thus you are responible for generating it.";
- users.groups =
- if cfg.group == "nix-sync"
- then {
- nix-sync = {
- members = ["${cfg.user}"];
- };
- }
- else lib.warnIf (cfg.group != "nix-sync") "The group (${cfg.group}) is not \"nix-sync\", thus you are responible for generating it.";
- };
-}
diff --git a/modules/by-name/ni/nix-sync/module.nix b/modules/by-name/ni/nix-sync/module.nix
deleted file mode 100644
index 9ddd210..0000000
--- a/modules/by-name/ni/nix-sync/module.nix
+++ /dev/null
@@ -1,108 +0,0 @@
-{
- config,
- lib,
- modulesPath,
- nixLib,
- ...
-}: let
- cfg = config.vhack.nix-sync;
-
- mkNixSyncRepository = {
- domain,
- repositoryUrl,
- extraSettings,
- }: {
- name = "${domain}";
- value = {
- path = "/etc/nginx/websites/${domain}";
- uri = "${repositoryUrl}";
- inherit extraSettings;
- };
- };
- nixSyncRepositories = builtins.listToAttrs (builtins.map mkNixSyncRepository cfg.domains);
-
- mkVirtHost = {
- domain,
- repositoryUrl,
- extraSettings,
- }: {
- name = "${domain}";
- value =
- # FIXME(@bpeetz): We cannot use something like `lib.recursiveUpdate` because the
- # `extraSettings` are instantiated from the “real” nginx type. As such the
- # `extaSettings` would override our values here. Therefore, the direct merge. <2025-02-07>
- extraSettings
- // {
- forceSSL = true;
- enableACME = true;
- root = "/etc/nginx/websites/${domain}";
- };
- };
- virtHosts = builtins.listToAttrs (builtins.map mkVirtHost cfg.domains);
-in {
- imports = [
- ./internal_module.nix
- ];
-
- options.vhack.nix-sync = {
- enable = lib.mkEnableOption ''
- a website git ops solution.
- '';
-
- domains = lib.mkOption {
- type = lib.types.listOf (lib.types.submodule {
- options = {
- domain = lib.mkOption {
- type = lib.types.str;
- example = "b-peetz.de";
- description = ''
- The fully qualified domain to use as base of this website.
- '';
- };
- repositoryUrl = lib.mkOption {
- type = lib.types.str;
- example = "b-peetz.de";
- description = ''
- The url used for the source git repository, which is deployed at this domain.
- '';
- };
- extraSettings = lib.mkOption {
- type =
- lib.types.submodule (import (modulesPath + "/services/web-servers/nginx/vhost-options.nix") {inherit config lib;});
- example = {
- locations."/.well-known/openpgpkey/".extraConfig = "default_type application/octet-stream";
- };
- default = {};
- description = ''
- Extra configuration to add to the nginx virtual host.
- '';
- };
- };
- });
- };
- };
-
- config = lib.mkIf cfg.enable {
- vhack.persist.directories = [
- {
- directory = "/var/lib/nix-sync";
- user = "nix-sync";
- group = "nix-sync";
- mode = "0700";
- }
- ];
-
- services.nix-sync = {
- enable = true;
- repositories = nixSyncRepositories;
- };
-
- vhack.nginx.enable = true;
- services.nginx.virtualHosts = virtHosts;
-
- users = {
- users.nix-sync.uid = config.vhack.constants.ids.uids.nix-sync;
- groups.nix-sync.gid = config.vhack.constants.ids.gids.nix-sync;
- };
- };
-}
diff --git a/modules/by-name/ni/nixconfig/module.nix b/modules/by-name/ni/nixconfig/module.nix
deleted file mode 100644
index a5bf950..0000000
--- a/modules/by-name/ni/nixconfig/module.nix
+++ /dev/null
@@ -1,28 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.nixconfig;
-in {
- options.vhack.nixconfig = {
- enable = lib.mkEnableOption "sophisticated nix settings";
- };
- config = lib.mkIf cfg.enable {
- nix = {
- # gc = {
- # automatic = true;
- # dates = "daily";
- # options = "--delete-older-than 3";
- # };
- settings = {
- auto-optimise-store = true;
- experimental-features = ["nix-command" "flakes"];
- trusted-users = [
- "root"
- "@wheel"
- ];
- };
- };
- };
-}
diff --git a/modules/by-name/ns/nscd/module.nix b/modules/by-name/ns/nscd/module.nix
deleted file mode 100644
index 428ae3b..0000000
--- a/modules/by-name/ns/nscd/module.nix
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.nscd;
-in {
- options.vhack.nscd = {
- # NOTE(@bpeetz): This is enabled by default in NixOS.
- # Because of this reason:
- # > Whether to enable the Name Service Cache Daemon. Disabling this is
- # > strongly discouraged, as this effectively disables NSS Lookups from
- # > all non-glibc NSS modules, including the ones provided by systemd.
- #
- # As such we should also always enable it. <2024-12-25>
- enable = (lib.mkEnableOption "nscd") // {default = true;};
- };
-
- config = lib.mkIf cfg.enable {
- users = {
- users.nscd.uid = config.vhack.constants.ids.uids.nscd;
- groups.nscd.gid = config.vhack.constants.ids.gids.nscd;
- };
- };
-}
diff --git a/modules/by-name/oo/oomd/module.nix b/modules/by-name/oo/oomd/module.nix
deleted file mode 100644
index 3b39236..0000000
--- a/modules/by-name/oo/oomd/module.nix
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.systemd.oomd;
-in {
- options.vhack.systemd.oomd = {
- # NOTE(@bpeetz): Enabled by default, because that is what NixOS also does. <2024-12-25>
- enable = (lib.mkEnableOption "oomd") // {default = true;};
- };
-
- config = lib.mkIf cfg.enable {
- users = {
- users.systemd-oom.uid = config.vhack.constants.ids.uids.systemd-oom;
- groups.systemd-oom.gid = config.vhack.constants.ids.gids.systemd-oom;
- };
- };
-}
diff --git a/modules/by-name/op/openssh/module.nix b/modules/by-name/op/openssh/module.nix
deleted file mode 100644
index 83aeadf..0000000
--- a/modules/by-name/op/openssh/module.nix
+++ /dev/null
@@ -1,60 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.openssh;
-in {
- options.vhack.openssh = {
- enable = lib.mkEnableOption ''
- a sane openssh implementation.
- '';
- };
-
- config = lib.mkIf cfg.enable {
- /*
- FIXME(@bpeetz):
- This results in a boot error, as the `/var/lib/sshd` directory
- is only mounted _after_ the stage 2 init and with it the system
- activation. `agenix` needs the sshd hostkey however to decrypt the
- secrets and thus we have to ensure that this directory is mounted
- _before_ the system activation. Alas the only way I see to achieve
- that is to store the ssh hostkey directly on /srv, which is mounted
- before (it's marked as 'neededForBoot' after all).
-
- It should be possible to achieve this with impermanence however,
- as `/var/log` is mounted in the stage 1 init; The problem is that
- I have no idea _why_ only this is mounted and nothing else.
-
-
- vhack.persist.directories = [
- {
- directory = "/var/lib/sshd";
- user = "root";
- group = "root";
- mode = "0755";
- }
- ];
- */
-
- users = {
- users.sshd.uid = config.vhack.constants.ids.uids.sshd;
- groups.sshd.gid = config.vhack.constants.ids.gids.sshd;
- };
-
- services.openssh = {
- enable = true;
- settings.PasswordAuthentication = false;
- hostKeys = [
- {
- # FIXME: Remove the dependency on `/srv` this workaround.
- # See the explanation for using `/srv` above.
- path = "/srv/var/lib/sshd/ssh_host_ed25519_key";
-
- rounds = 1000;
- type = "ed25519";
- }
- ];
- };
- };
-}
diff --git a/modules/by-name/pe/peertube/module.nix b/modules/by-name/pe/peertube/module.nix
deleted file mode 100644
index e65e0b5..0000000
--- a/modules/by-name/pe/peertube/module.nix
+++ /dev/null
@@ -1,124 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.peertube;
-in {
- options.vhack.peertube = {
- enable = lib.mkEnableOption ''
- the peertube video platform.
- '';
- peertubeGeneral = lib.mkOption {
- type = lib.types.path;
- description = "The age encrypted general secret file passed to agenix";
- };
- smtpPasswordFile = lib.mkOption {
- type = lib.types.path;
- description = "The age encrypted smtp password file passed to agenix";
- };
- };
-
- config = lib.mkIf cfg.enable {
- services.peertube = {
- enable = true;
-
- configureNginx = true;
- localDomain = "peertube.vhack.eu";
- enableWebHttps = true;
- listenWeb = 443;
-
- smtp = {
- createLocally = false;
- passwordFile = "${config.age.secrets.peertubeSmtp.path}";
- };
- database = {
- createLocally = true;
- };
- redis = {
- enableUnixSocket = true;
- createLocally = true;
- };
-
- secrets.secretsFile = "${config.age.secrets.peertubeGeneral.path}";
-
- settings = {
- signup = {
- enabled = true;
-
- limit = 10; # When the limit is reached, registrations are disabled. -1 == unlimited
-
- minimum_age = 18; # Used to configure the signup form
-
- # Users fill a form to register so moderators can accept/reject the registration
- requires_approval = true;
- requires_email_verification = true;
- };
- user = {
- video_quota = "10GB";
- video_quota_daily = "2GB";
- };
- auto_blacklist = {
- videos = {
- of_users = {
- enabled = true;
- };
- };
- };
- listen.hostname = "127.0.0.1";
- instance.name = "PeerTube at Vhack.eu";
-
- admin.email = "admin@vhack.eu";
-
- smtp = let
- emailAddress = "peertube@vhack.eu";
- in {
- transport = "smtp";
- hostname = "mail.foss-syndicate.org";
- port = 587;
- username = emailAddress;
- tls = true;
- disable_starttls = true;
- from_address = emailAddress;
- };
- };
- };
-
- # The `configureNginx` option does not do this for some reason
- # TODO(@bpeetz): Find out why <2024-06-27>
- services.nginx.virtualHosts."${config.services.peertube.localDomain}" = {
- enableACME = true;
- forceSSL = true;
- };
-
- age.secrets = {
- peertubeGeneral = {
- file = cfg.peertubeGeneral;
- mode = "700";
- owner = "peertube";
- group = "peertube";
- };
- peertubeSmtp = {
- file = cfg.smtpPasswordFile;
- mode = "700";
- owner = "peertube";
- group = "peertube";
- };
- };
-
- vhack.persist.directories = [
- {
- directory = "/var/lib/peertube";
- user = "peertube";
- group = "peertube";
- mode = "0700";
- }
- ];
- users = {
- users.peertube.uid = config.vhack.constants.ids.uids.peertube;
- groups.peertube.gid = config.vhack.constants.ids.gids.peertube;
- users.redis-peertube.uid = config.vhack.constants.ids.uids.redis-peertube;
- groups.redis-peertube.gid = config.vhack.constants.ids.gids.redis-peertube;
- };
- };
-}
diff --git a/modules/by-name/po/postgresql/module.nix b/modules/by-name/po/postgresql/module.nix
deleted file mode 100644
index 319c3ac..0000000
--- a/modules/by-name/po/postgresql/module.nix
+++ /dev/null
@@ -1,19 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.postgresql;
-in {
- options.vhack.postgresql = {
- enable = lib.mkEnableOption "postgresql";
- };
-
- config = lib.mkIf cfg.enable {
- vhack.persist.directories = [
- "/var/lib/postgresql"
- ];
-
- services.postgresql.enable = true;
- };
-}
diff --git a/modules/by-name/re/redlib/module.nix b/modules/by-name/re/redlib/module.nix
deleted file mode 100644
index eb5edba..0000000
--- a/modules/by-name/re/redlib/module.nix
+++ /dev/null
@@ -1,41 +0,0 @@
-{
- config,
- pkgsUnstable,
- lib,
- ...
-}: let
- domain = "redlib.vhack.eu";
-
- cfg = config.vhack.redlib;
-in {
- options.vhack.redlib = {
- enable = lib.mkEnableOption ''
- the redlib reddit frontend
- '';
- };
-
- config = lib.mkIf cfg.enable {
- services.redlib = {
- enable = true;
- package = pkgsUnstable.redlib;
- port = 8080;
- address = "127.0.0.1";
- openFirewall = false;
- };
-
- services.nginx = {
- enable = true;
- virtualHosts.${domain} = {
- locations."/".proxyPass = "http://127.0.0.1:${toString config.services.redlib.port}";
-
- enableACME = true;
- forceSSL = true;
- };
- };
-
- # TODO(@bpeetz): Remove this at some point. <2025-02-04>
- vhack.nginx.redirects = {
- "libreddit.vhack.eu" = "${domain}";
- };
- };
-}
diff --git a/modules/by-name/re/resolvconf/module.nix b/modules/by-name/re/resolvconf/module.nix
deleted file mode 100644
index ff99696..0000000
--- a/modules/by-name/re/resolvconf/module.nix
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.resolvconf;
-in {
- options.vhack.resolvconf = {
- # NOTE(@bpeetz): This condition is taken directly from NixOS. <2024-12-25>
- enable = lib.mkEnableOption "resolvconf" // {default = !(config.environment.etc ? "resolv.conf");};
- };
-
- config = lib.mkIf cfg.enable {
- users.groups.resolvconf.gid = config.vhack.constants.ids.gids.resolvconf;
- };
-}
diff --git a/modules/by-name/ru/rust-motd/module.nix b/modules/by-name/ru/rust-motd/module.nix
deleted file mode 100644
index a6998f4..0000000
--- a/modules/by-name/ru/rust-motd/module.nix
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- config,
- lib,
- pkgs,
- ...
-}: let
- cfg = config.vhack.rust-motd;
-
- # List all users that can login
- pred = n: v: (
- false # <- just here for neat formatting
- || v.initialHashedPassword != null
- || v.initialPassword != null
- || v.hashedPassword != null
- || v.hashedPasswordFile != null
- || v.password != null
- || v.passwordFile != null
- || v.openssh.authorizedKeys.keys != []
- || v.openssh.authorizedKeys.keyFiles != []
- );
- userList = builtins.mapAttrs (n: v: 2) (lib.filterAttrs pred config.users.users);
-in {
- options.vhack.rust-motd = {
- enable = lib.mkEnableOption "rust-motd";
- };
-
- config = lib.mkIf cfg.enable {
- systemd.services.rust-motd = {
- path = with pkgs; [
- bash
- fail2ban # Needed for rust-motd fail2ban integration
- ];
- };
-
- programs.rust-motd = {
- enable = true;
- enableMotdInSSHD = true;
- refreshInterval = "*:0/5"; # 0/5 means: hour 0 AND all hour wich match (0 + 5 * x) (is the same as: 0, 5, 10, 15, 20)
-
- # An example is here: https://raw.githubusercontent.com/rust-motd/rust-motd/refs/heads/main/example_config.toml
- settings = {
- global = {
- progress_full_character = "=";
- progress_empty_character = "-";
- progress_prefix = "[";
- progress_suffix = "]";
- time_format = "%Y-%m-%d %H:%M:%S";
- };
-
- banner = {
- color = "red";
- command = "${pkgs.hostname}/bin/hostname | ${pkgs.figlet}/bin/figlet -f slant";
- # if you don't want a dependency on figlet, you can generate your
- # banner however you want, put it in a file, and then use something like:
- # command = "cat banner.txt"
- };
-
- uptime = {
- prefix = "Uptime:";
- };
-
- # ssl_certificates = {
- # sort_method = "manual";
- #
- # certs = {
- # "server1.vhack.eu" = "/var/lib/acme/server1.vhack.eu/cert.pem";
- # "vhack.eu" = "/var/lib/acme/vhack.eu/cert.pem";
- # };
- # };
-
- filesystems = {
- root = "/";
- persistent = "/srv";
- store = "/nix";
- boot = "/boot";
- };
-
- memory = {
- swap_pos = "beside"; # or "below" or "none"
- };
-
- fail2_ban = {
- jails = ["sshd"]; #, "anotherjail"]
- };
-
- last_login = userList;
-
- last_run = {};
- };
- };
- };
-}
diff --git a/modules/by-name/sh/sharkey/module.nix b/modules/by-name/sh/sharkey/module.nix
deleted file mode 100644
index 2b50cf0..0000000
--- a/modules/by-name/sh/sharkey/module.nix
+++ /dev/null
@@ -1,298 +0,0 @@
-# Source: https://github.com/sodiboo/system/blob/b63c7b27f49043e8701b3ff5e1441cd27d5a2fff/sharkey/module.nix
-{
- config,
- lib,
- pkgs,
- vhackPackages,
- ...
-}: let
- cfg = config.vhack.sharkey;
-
- createDB = cfg.database.host == "127.0.0.1" && cfg.database.createLocally;
-
- settingsFormat = pkgs.formats.yaml {};
- configFile = settingsFormat.generate "sharkey-config.yml" cfg.settings;
-in {
- options.vhack.sharkey = {
- enable = lib.mkEnableOption "sharkey";
-
- fqdn = lib.mkOption {
- description = "The fully qualified domain name of this instance.";
- type = lib.types.str;
- example = "sharkey.shonk.social";
- };
-
- package = lib.mkOption {
- type = lib.types.package;
- default = vhackPackages.sharkey;
- defaultText = lib.literalExpression "vhackPackages.sharkey";
- description = "Sharkey package to use.";
- };
-
- dataDirectory = lib.mkOption {
- type = lib.types.path;
- default = "/var/lib/sharkey";
- description = "The directory where sharkey stores it's data.";
-
- # This is already set in the package.
- readOnly = true;
- };
-
- database = {
- createLocally = lib.mkOption {
- description = "Whether to enable local db creation.";
- type = lib.types.bool;
- default = true;
- };
-
- host = lib.mkOption {
- type = lib.types.str;
- default = "127.0.0.1";
- description = "The database host.";
- };
-
- port = lib.mkOption {
- type = lib.types.port;
- default = 5432;
- description = "The database port.";
- };
-
- name = lib.mkOption {
- type = lib.types.str;
- default = "sharkey";
- description = "The database name in postgresql.";
- };
- };
-
- settings = lib.mkOption {
- inherit (settingsFormat) type;
- default = {};
- description = ''
- Configuration for Sharkey, see
- <link xlink:href="https://activitypub.software/TransFem-org/Sharkey/-/blob/develop/.config/example.yml"/>
- for supported settings.
- '';
- };
- };
-
- config = lib.mkIf cfg.enable {
- environment.systemPackages = [cfg.package];
-
- vhack = {
- nginx.enable = true;
-
- sharkey.settings = {
- id = "aidx";
-
- url = "https://${cfg.fqdn}/";
- port = 5312;
-
- db = {
- inherit (cfg.database) host port;
- db = cfg.database.name;
- user = cfg.database.name;
- pass = "sharkey-password";
- };
- redis = {
- path = config.services.redis.servers."sharkey".unixSocket;
- };
- };
-
- persist.directories = [
- {
- directory = "${config.services.redis.servers."sharkey".settings.dir}";
- user = "sharkey";
- group = "redis-sharey";
- mode = "0770";
- }
- {
- directory = "${cfg.dataDirectory}";
- user = "sharkey";
- group = "sharkey";
- mode = "0770";
- }
- ];
- };
-
- services = {
- nginx.virtualHosts."${cfg.fqdn}" = {
- locations."/" = {
- proxyPass = "http://127.0.0.1:${toString cfg.settings.port}";
- proxyWebsockets = true;
- };
-
- # proxy_set_header Host $host;
- # proxy_http_version 1.1;
- # proxy_redirect off;
- #
- # # If it's behind another reverse proxy or CDN, remove the following.
- # proxy_set_header X-Real-IP $remote_addr;
- # proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- # proxy_set_header X-Forwarded-Proto https;
- #
- # # For WebSocket
- # proxy_set_header Upgrade $http_upgrade;
- # proxy_set_header Connection $connection_upgrade;
- #
- # # Cache settings
- # proxy_cache cache1;
- # proxy_cache_lock on;
- # proxy_cache_use_stale updating;
- # proxy_force_ranges on;
- # add_header X-Cache $upstream_cache_status;
-
- enableACME = true;
- forceSSL = true;
- };
-
- postgresql = lib.mkIf createDB {
- enable = true;
- settings.port = cfg.database.port;
- ensureUsers = [
- {
- inherit (cfg.database) name;
- ensureDBOwnership = true;
- }
- ];
- ensureDatabases = [cfg.database.name];
- };
-
- redis = {
- servers."sharkey" = {
- enable = true;
-
- user = "sharkey";
-
- # Disable TCP listening. (We have a UNIX socket)
- port = 0;
- bind = null;
-
- settings = {
- protected-mode = true;
- enable-protected-configs = false;
- enable-debug-command = false;
- enable-module-command = false;
-
- supervised = "systemd";
- stop-writes-on-bgsave-error = true;
- sanitize-dump-payload = "clients";
- };
- };
- };
- };
-
- systemd.services.postgresql.postStart = ''
- $PSQL -tAc "ALTER ROLE ${cfg.database.name} WITH ENCRYPTED PASSWORD 'sharkey-password';"
- '';
-
- systemd.services.sharkey = {
- requires =
- [
- "redis-sharkey.service"
- "network-online.target"
- ]
- ++ lib.optionals createDB ["postgresql.service"];
-
- after =
- [
- "redis-sharkey.service"
- "network-online.target"
- ]
- ++ lib.optionals createDB ["postgresql.service"];
-
- wantedBy = ["multi-user.target"];
-
- environment = {
- MISSKEY_CONFIG_YML = "${configFile}";
- NODE_ENV = "production";
- };
-
- serviceConfig = {
- Type = "simple";
-
- StateDirectory = "sharkey";
- StateDirectoryMode = "0700";
- CacheDirectory = "sharkey";
- RuntimeDirectory = "sharkey";
- RuntimeDirectoryMode = "0700";
- ExecStart = "${lib.getExe cfg.package} migrateandstart";
-
- TimeoutSec = 60;
- Restart = "no";
-
- StandardOutput = "journal";
- StandardError = "journal";
- SyslogIdentifier = "sharkey";
-
- User = "sharkey";
- Group = "sharkey";
-
- # Bind standard privileged ports
- AmbientCapabilities = [];
- CapabilityBoundingSet = [];
-
- ReadWritePaths = [
- "${cfg.dataDirectory}"
- ];
-
- # Hardening
- DeviceAllow = [""];
- LockPersonality = true;
- # Probably needed for v8's JIT (crashes with it on).
- MemoryDenyWriteExecute = false;
- PrivateDevices = true;
- PrivateUsers = true;
- # Sharkey needs access to the hosts CPUs
- ProcSubset = "all";
- PrivateTmp = true;
- ProtectClock = true;
- ProtectControlGroups = true;
- ProtectHome = true;
- ProtectHostname = true;
- ProtectKernelLogs = true;
- ProtectKernelModules = true;
- ProtectKernelTunables = true;
- ProtectProc = "invisible";
- ProtectSystem = "strict";
- RestrictAddressFamilies = [
- "AF_UNIX" # Local communication unix(7)
- "AF_INET" # IPv4 Internet protocols ip(7)
- "AF_INET6" # IPv6 Internet protocols ipv6(7)
- # Needed for nodes `os.networkInterfaces()` function.
- "AF_NETLINK" # Kernel user interface device netlink(7)
- ];
- RestrictNamespaces = true;
- RestrictRealtime = true;
- RestrictSUIDSGID = true;
- SystemCallArchitectures = "native";
- SystemCallFilter = [
- "@system-service"
- "@chown"
- "~@mount"
- ];
- UMask = "0077";
- };
- };
-
- users = {
- groups.sharkey = {
- gid = config.vhack.constants.ids.gids.sharkey;
- };
- users.sharkey = {
- isSystemUser = true;
- group = "sharkey";
- uid = config.vhack.constants.ids.uids.sharkey;
- home = cfg.package;
- packages = [cfg.package];
- };
-
- groups.redis-sharkey = {
- gid = config.vhack.constants.ids.gids.redis-sharkey;
- };
- users.redis-sharkey = {
- group = "redis-sharkey";
- uid = config.vhack.constants.ids.uids.redis-sharkey;
- };
- };
- };
-}
diff --git a/modules/by-name/st/stalwart-mail/module.nix b/modules/by-name/st/stalwart-mail/module.nix
deleted file mode 100644
index 7bd985f..0000000
--- a/modules/by-name/st/stalwart-mail/module.nix
+++ /dev/null
@@ -1,428 +0,0 @@
-{
- lib,
- config,
- pkgs,
- vhackPackages,
- ...
-}: let
- cfg = config.vhack.stalwart-mail;
- topCfg = config.services.stalwart-mail;
-
- configFormat = pkgs.formats.toml {};
- configFile = configFormat.generate "stalwart-mail.toml" topCfg.settings;
-in {
- imports = [
- ./settings.nix
- ];
-
- options.vhack.stalwart-mail = {
- enable = lib.mkEnableOption "starwart-mail";
-
- package = lib.mkPackageOption vhackPackages "stalwart-mail-free" {};
-
- admin = lib.mkOption {
- description = ''
- Email address to advertise as administrator. This is the address, where dkim, spv
- etc. refusal reports are sent to.
-
- The format should be: `mailto:<name>@<domain>`
- '';
- type = lib.types.str;
- example = "mailto:dmarc+rua@example.com";
- default = "";
- };
-
- fqdn = lib.mkOption {
- type = lib.types.str;
- example = "mail.foss-syndicate.org";
- description = ''
- The fully qualified domain name for this mail server.
- '';
- };
-
- principals = lib.mkOption {
- default = null;
- type = lib.types.nullOr (lib.types.listOf (lib.types.submodule {
- options = {
- name = lib.mkOption {
- type = lib.types.str;
- description = "Specifies the username of the account";
- };
-
- class = lib.mkOption {
- type = lib.types.enum ["individual" "admin"];
- description = "Specifies the account type";
- };
-
- description = lib.mkOption {
- type = lib.types.str;
- description = "Provides a description or full name for the user";
- default = "";
- };
-
- secret = lib.mkOption {
- type = let
- prefix = pre: lib.types.strMatching "^${lib.strings.escapeRegex pre}.*";
- in
- lib.types.oneOf [
- (prefix "$argon2")
- (prefix "$pbkdf2")
- (prefix "$scrypt")
- (prefix "$2") # bcrypt
- (prefix "$6$") # sha-512
- (prefix "$5$") # sha-256
- (prefix "$sha1")
- (prefix "$1") # md5
- (prefix "_") # BSDi crypt
- (prefix "{SHA}") # base64 sha
- (prefix "{SSHA}") # base64 salted sha
-
- # unix crypt
- (prefix "{CRYPT}")
- (prefix "{crypt}")
-
- # Plain text
- (prefix "{PLAIN}")
- (prefix "{plain}")
- (prefix "{CLEAR}")
- (prefix "{clear}")
- ];
- description = ''
- Sets the password for the user account.
- Passwords can be stored hashed or in plain text (not recommended).
- See <https://stalw.art/docs/auth/authentication/password/> for a description
- of password encoding.
- '';
- };
- email = lib.mkOption {
- type = lib.types.listOf lib.types.str;
- description = ''
- A list of email addresses associated with the user.
- The first address in the list is considered the primary address.
- '';
- };
- };
- }));
- };
-
- dataDirectory = lib.mkOption {
- description = ''
- The directory in which to store all storage things.
- '';
- default = "/var/lib/stalwart-mail";
- type = lib.types.path;
- readOnly = true;
- };
-
- openFirewall = lib.mkOption {
- type = lib.types.bool;
- default = false;
- description = ''
- Whether to open TCP firewall ports, which are specified in
- {option}`services.stalwart-mail.settings.listener` on all interfaces.
- '';
- };
-
- security = lib.mkOption {
- type = lib.types.nullOr (lib.types.submodule {
- options = {
- verificationMode = lib.mkOption {
- type = lib.types.enum ["relaxed" "strict"];
- description = ''
- Whether to allow invalid signatures/checks or not.
- '';
- default = "relaxed";
- };
-
- dkimKeys = lib.mkOption {
- type = lib.types.attrsOf (lib.types.submodule {
- options = {
- dkimPublicKey = lib.mkOption {
- type = lib.types.str;
- description = ''
- The base 64 encoded representation of the public dkim key.
- '';
- };
- dkimPrivateKeyPath = lib.mkOption {
- type = lib.types.path;
- description = ''
- The path to the dkim private key agenix file.
- Generate it via the `./gen_key` script:
- '';
- };
- keyAlgorithm = lib.mkOption {
- type = lib.types.enum ["ed25519-sha256" "rsa-sha-256" "rsa-sha-1"];
- description = "The algorithm of the used key";
- };
- };
- });
- description = ''
- Which key to use for which domain. The attr keys are the domains
- '';
- default = {};
- };
- };
- });
- description = ''
- Security options. This should only be set to `null` when testing.
- '';
- };
- };
-
- config = lib.mkIf cfg.enable {
- assertions = [
- {
- assertion = cfg.admin != "";
- message = "You need to specify an admin address.";
- }
- ];
-
- vhack.nginx.enable = true;
- services = {
- stalwart-mail = {
- # NOTE(@bpeetz): We do not use the NixOS service, as it comes with too much
- # bothersome default configuration and not really any useful configuration.
- # However, this decision could obviously be reversed in the future. <2025-02-08>
- enable = false;
- inherit (cfg) package;
- };
-
- nginx.virtualHosts."${cfg.fqdn}" = {
- locations."/" = {
- proxyPass = "http://${builtins.elemAt config.services.stalwart-mail.settings.server.listener.http.bind 0}";
- recommendedProxySettings = true;
- };
-
- useACMEHost = "${cfg.fqdn}";
- forceSSL = true;
- };
-
- redis = {
- servers = {
- "stalwart-mail" = {
- enable = true;
-
- user = "stalwart-mail";
-
- # Disable TCP listening. (We have a UNIX socket)
- port = 0;
- bind = null;
-
- settings = {
- protected-mode = true;
- enable-protected-configs = false;
- enable-debug-command = false;
- enable-module-command = false;
-
- supervised = "systemd";
- stop-writes-on-bgsave-error = true;
- sanitize-dump-payload = "clients";
- };
- };
- };
- };
- };
- security.acme.certs = {
- "${cfg.fqdn}" = {
- domain = cfg.fqdn;
- group = "stalwart-mail-certificates";
- };
- };
-
- age.secrets = let
- keys =
- lib.mapAttrs' (
- keyDomain: keyConfig:
- lib.nameValuePair "stalwartMail${keyDomain}"
- {
- file = keyConfig.dkimPrivateKeyPath;
- mode = "600";
- owner = "stalwart-mail";
- group = "stalwart-mail";
- }
- )
- cfg.security.dkimKeys;
- in
- lib.mkIf (cfg.security != null) keys;
-
- vhack.persist.directories = [
- {
- directory = "${cfg.dataDirectory}";
- user = "stalwart-mail";
- group = "stalwart-mail";
- mode = "0700";
- }
- {
- directory = "${config.services.redis.servers."stalwart-mail".settings.dir}";
- user = "stalwart-mail";
- group = "redis-stalwart-mail";
- mode = "0770";
- }
- ];
-
- # This service stores a potentially large amount of data.
- # Running it as a dynamic user would force chown to be run every time the
- # service is restarted on a potentially large number of files.
- # That would cause unnecessary and unwanted delays.
- users = {
- groups = {
- stalwart-mail = {
- gid = config.vhack.constants.ids.gids.stalwart-mail;
- };
- stalwart-mail-certificates = {
- gid = config.vhack.constants.ids.gids.stalwart-mail-certificates;
- };
- redis-stalwart-mail = {
- gid = config.vhack.constants.ids.gids.redis-stalwart-mail;
- };
- };
- users = {
- nginx = {
- extraGroups = ["stalwart-mail-certificates"];
- };
- stalwart-mail = {
- isSystemUser = true;
- group = "stalwart-mail";
- uid = config.vhack.constants.ids.uids.stalwart-mail;
- extraGroups = ["stalwart-mail-certificates"];
- };
- redis-stalwart-mail = {
- group = "redis-stalwart-mail";
- uid = config.vhack.constants.ids.uids.redis-stalwart-mail;
- };
- };
- };
-
- systemd.tmpfiles.rules = [
- "d '${cfg.dataDirectory}' - stalwart-mail stalwart-mail - -"
- ];
-
- systemd = {
- services.stalwart-mail = {
- wantedBy = ["multi-user.target"];
- requires =
- [
- "redis-stalwart-mail.service"
- "network-online.target"
- ]
- ++ (lib.optional (cfg.security != null) "acme-${cfg.fqdn}.service");
- after = [
- "local-fs.target"
- "network.target"
- "network-online.target"
- "redis-stalwart-mail.service"
- "acme-${cfg.fqdn}.service"
- ];
- conflicts = [
- "postfix.service"
- "sendmail.service"
- "exim4.service"
- ];
- description = "Stalwart Mail Server";
-
- environment = {
- SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
- NIX_SSL_CERT_FILE = "/etc/ssl/certs/ca-certificates.crt";
- };
-
- preStart = let
- esa = lib.strings.escapeShellArg;
- mkTmpFile = path: "[ -d ${esa path} ] || mkdir --parents ${esa path}";
-
- # Create the directories for stalwart
- storageDirectories = lib.lists.filter (v: v != null) (lib.attrsets.mapAttrsToList (_: {path ? null, ...}:
- if (path != null)
- then mkTmpFile path
- else null)
- topCfg.settings.store);
- in
- ''
- # Stalwart actually wants to store _data_ (e.g., blocked ips) in it's own config file.
- # Thus we need to make it writable.
- cat ${esa configFile} >$CACHE_DIRECTORY/mutable_config_file.toml
- ''
- + (builtins.concatStringsSep "\n" storageDirectories);
-
- serviceConfig = {
- ExecStart = pkgs.writers.writeDash "start-stalwart-mail" ''
- ${lib.getExe cfg.package} --config="$CACHE_DIRECTORY/mutable_config_file.toml"
- '';
-
- Restart = "no";
-
- KillMode = "process";
- KillSignal = "SIGINT";
-
- Type = "simple";
- LimitNOFILE = 65536;
-
- StandardOutput = "journal";
- StandardError = "journal";
-
- ReadWritePaths = [
- cfg.dataDirectory
- ];
- CacheDirectory = "stalwart-mail";
- StateDirectory = "stalwart-mail";
-
- User = "stalwart-mail";
- Group = "stalwart-mail";
-
- SyslogIdentifier = "stalwart-mail";
-
- # 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"
- "AF_UNIX"
- ];
- 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];
-
- networking.firewall = let
- parsePorts = listeners: let
- parseAddresses = listeners: lib.flatten (lib.mapAttrsToList (name: value: value.bind) listeners);
- splitAddress = addr: lib.splitString ":" addr;
- extractPort = addr: lib.toInt (builtins.foldl' (a: b: b) "" (splitAddress addr));
- in
- builtins.map extractPort (parseAddresses listeners);
- in
- lib.mkIf (cfg.openFirewall && (builtins.hasAttr "listener" topCfg.settings.server))
- {
- allowedTCPPorts = parsePorts topCfg.settings.server.listener;
- };
- };
-}
diff --git a/modules/by-name/st/stalwart-mail/settings.nix b/modules/by-name/st/stalwart-mail/settings.nix
deleted file mode 100644
index 907cea9..0000000
--- a/modules/by-name/st/stalwart-mail/settings.nix
+++ /dev/null
@@ -1,552 +0,0 @@
-{
- config,
- lib,
- pkgs,
- ...
-}: let
- cfg = config.vhack.stalwart-mail;
-
- signaturesByDomain =
- (builtins.map ({name, ...}: {
- "if" = "sender_domain = '${name}'";
- "then" = "'${name}'";
- })
- (lib.attrsToList cfg.security.dkimKeys))
- ++ [{"else" = false;}];
-
- maybeVerificationMode =
- if cfg.security != null
- then cfg.security.verificationMode
- else "disable";
-
- directory =
- if cfg.principals == null
- then "internal"
- else "in-memory";
-in {
- config.services.stalwart-mail.settings = lib.mkIf cfg.enable {
- # https://www.rfc-editor.org/rfc/rfc6376.html#section-3.3
- signature = let
- signatures =
- lib.mapAttrs (keyDomain: keyConfig: {
- private-key = "%{file:${config.age.secrets."stalwartMail${keyDomain}".path}}%";
-
- domain = keyDomain;
-
- selector = "mail";
- headers = ["From" "To" "Cc" "Date" "Subject" "Message-ID" "Organization" "MIME-Version" "Content-Type" "In-Reply-To" "References" "List-Id" "User-Agent" "Thread-Topic" "Thread-Index"];
- algorithm = keyConfig.keyAlgorithm;
-
- # How do we canonicalize the headers/body?
- # https://www.rfc-editor.org/rfc/rfc6376.html#section-3.4
- canonicalization = "simple/simple";
-
- expire = "50d";
- report = true;
- })
- cfg.security.dkimKeys;
- in
- lib.mkIf (cfg.security != null) signatures;
-
- auth = let
- # NOTE(@bpeetz): We disable all the checks if the `listener` is submissions, because the
- # user's email client will obviously not have the right IP address to pass SPF or
- # IPREV. It will also not be able to sign the message with DKIM (as we has to key). <2025-02-25>
- ifNotSmpt = valueTrue: valueFalse: [
- {
- "if" = "listener != 'submissions'";
- "then" = valueTrue;
- }
- {"else" = valueFalse;}
- ];
- in {
- iprev = {
- verify = ifNotSmpt maybeVerificationMode "disable";
- };
- spf = {
- verify = {
- ehlo = ifNotSmpt maybeVerificationMode "disable";
-
- mail-from = ifNotSmpt maybeVerificationMode "disable";
- };
- };
- dmarc = {
- verify = ifNotSmpt maybeVerificationMode "disable";
- };
- arc = {
- seal = lib.mkIf (cfg.security != null) signaturesByDomain;
- verify = ifNotSmpt maybeVerificationMode "disable";
- };
- dkim = {
- verify = ifNotSmpt maybeVerificationMode "disable";
-
- # Ignore insecure dkim signed messages (i.e., messages containing both
- # signed and appended not-signed content.)
- strict = true;
-
- sign =
- lib.mkIf (cfg.security != null) signaturesByDomain;
- };
- };
- report = {
- domain = "${cfg.fqdn}";
- submitter = "'${cfg.fqdn}'";
- analysis = {
- addresses = ["dmarc@*" "abuse@*"];
- forward = true;
- store = "30d";
- };
- tls.aggregate = {
- from-name = "'TLS Report'";
- from-address = "'noreply-tls@${cfg.fqdn}'";
- org-name = "'Foss Syndicate Mail Handling'";
- contact-info = "'${cfg.admin}'";
- send = "daily";
- max-size = 26214400; # 25 MiB
- sign = lib.mkIf (cfg.security != null) "'${cfg.fqdn}'";
- };
- dmarc = {
- aggregate = {
- from-name = "'DMARC Report'";
- from-address = "'noreply-dmarc@${cfg.fqdn}'";
- org-name = "'Foss Syndicate Mail Handling'";
- contact-info = "'${cfg.admin}'";
- send = "weekly";
- max-size = 26214400; # 25MiB
- sign = lib.mkIf (cfg.security != null) "'${cfg.fqdn}'";
- };
- from-name = "'Report Subsystem'";
- from-address = "'noreply-dmarc@${cfg.fqdn}'";
- subject = "'DMARC Authentication Failure Report'";
- send = "1/1d";
- sign = lib.mkIf (cfg.security != null) signaturesByDomain;
- };
- spf = {
- from-name = "'Report Subsystem'";
- from-address = "'noreply-spf@${cfg.fqdn}'";
- subject = "'SPF Authentication Failure Report'";
- send = "1/1d";
- sign = lib.mkIf (cfg.security != null) signaturesByDomain;
- };
- dkim = {
- from-name = "'Report Subsystem'";
- from-address = "'noreply-dkim@${cfg.fqdn}'";
- subject = "'DKIM Authentication Failure Report'";
- send = "1/1d";
- sign = lib.mkIf (cfg.security != null) signaturesByDomain;
- };
- dsn = {
- from-name = "'Mail Delivery Subsystem'";
- from-address = "'MAILER-DAEMON@${cfg.fqdn}'";
- sign = lib.mkIf (cfg.security != null) signaturesByDomain;
- };
- };
- queue = {
- schedule = {
- retry = "[2m, 5m, 10m, 15m, 30m, 1h, 2h]";
- notify = "[2h, 7h, 1d, 3d]";
- expire = "5d";
- };
- outbound = {
- tls = {
- starttls =
- if maybeVerificationMode == "strict"
- then "require"
- else "optional";
- allow-invalid-certs = false;
- ip-strategy = "ipv6_then_ipv4";
- mta-sts =
- if maybeVerificationMode == "strict"
- then "require"
- else "optional";
- };
- };
- };
- resolver = {
- type = "system";
- preserve-intermediates = true;
- concurrency = 2;
- timeout = "5s";
- attempts = 2;
- try-tcp-on-error = true;
- public-suffix = [
- "file://${pkgs.publicsuffix-list}/share/publicsuffix/public_suffix_list.dat"
- ];
- };
-
- spam-filter = {
- enable = true;
- header = {
- status = {
- enable = true;
- name = "X-Spam-Status";
- };
- result = {
- enable = true;
- name = "X-Spam-Result";
- };
- };
- bayes = {
- enable = true;
-
- # Learn from users putting mail into JUNK or taking mail out of it.
- account = {
- enable = true;
- };
- };
-
- # Fetch the newest spam-filter rules not from github, but from the nix
- # package.
- resource = "file://${cfg.package.passthru.spamfilter}/spam-filter.toml";
- auto-update = false;
- };
-
- webadmin = {
- # Fetch the newest webadmin bundle not from github, but from the nix
- # package.
- resource = "file://${cfg.package.passthru.webadmin}/webadmin.zip";
- auto-update = false;
- path = "/var/cache/stalwart-mail";
- };
-
- session = {
- milter = {
- # TODO: Add this <2025-02-07>
- # "clamav" = {
- # enable = true;
- # hostname = "127.0.0.1";
- # port = 15112;
- # tls = false;
- # allow-invalid-certs = false;
- # };
- };
- ehlo = {
- require = true;
- };
- rcpt = {
- directory = "'${directory}'";
- catch-all = true;
- subaddressing = true;
- };
- data = {
- spam-filter = true;
- add-headers = {
- received = true;
- received-spf = true;
- auth-results = true;
- message-id = true;
- date = true;
- return-path = true;
- delivered-to = true;
- };
- auth = {
- mechanisms = ["LOGIN" "PLAIN"];
- directory = "'${directory}'";
- require = true;
- must-match-sender = true;
- errors = {
- total = 3;
- wait = "5s";
- };
- };
- };
- extensions = {
- pipelining = true;
- chunking = true;
- requiretls = true;
- no-soliciting = "";
- dsn = [
- {
- "if" = "!is_empty(authenticated_as)";
- "then" = true;
- }
- {"else" = false;}
- ];
- future-release = [
- {
- "if" = "!is_empty(authenticated_as)";
- "then" = "7d";
- }
- {"else" = false;}
- ];
- deliver-by = [
- {
- "if" = "!is_empty(authenticated_as)";
- "then" = "15d";
- }
- {"else" = false;}
- ];
- mt-priority = [
- {
- "if" = "!is_empty(authenticated_as)";
- "then" = "mixer";
- }
- {"else" = false;}
- ];
- vrfy = [
- {
- "if" = "!is_empty(authenticated_as)";
- "then" = true;
- }
- {"else" = false;}
- ];
- expn = [
- {
- "if" = "!is_empty(authenticated_as)";
- "then" = true;
- }
- {"else" = false;}
- ];
- };
- };
-
- jmap = {
- account = {
- purge.frequency = "0 0 *";
- };
- protocol = {
- changes.max-history = "14d";
- };
- email = {
- # NOTE(@bpeetz): We probably want to enable the auto-deletion of emails in
- # the "Junk" and "Deleted" items mail folders, but this should be
- # communicated to the users. <2025-02-07>
- auto-expunge = false;
- };
- mailbox = {
- max-depth = 50;
- max-name-length = 255;
- };
- folders = let
- mkFolder = name: {
- inherit name;
- create = true;
- subscribe = true;
- };
- in {
- inbox = mkFolder "INBOX";
- drafts = mkFolder "DRAFTS";
- sent = mkFolder "SENT";
- trash = mkFolder "TRASH";
- archive = mkFolder "ARCHIVE";
- junk = mkFolder "JUNK";
- shared = {name = "SHARED";};
- };
- };
- imap = {
- auth = {
- # Allow password login over non tls connection
- allow-plain-text = false;
- };
- };
-
- server = {
- hostname = cfg.fqdn;
-
- listener = {
- # HTTP (used for jmap)
- "http" = {
- bind = ["127.0.0.1:8112"];
- protocol = "http";
- # handled by ngnix
- tls.implicit = false;
- };
-
- # IMAP
- "imap" = {
- bind = ["[::]:993"];
- protocol = "imap";
- tls.implicit = true;
- };
-
- # SMTP
- "submissions" = {
- bind = ["[::]:465"];
- protocol = "smtp";
- tls.implicit = true;
- };
- "input" = {
- bind = ["[::]:25"];
- protocol = "smtp";
- tls = {
- enable = true;
- # Require an explicit `STARTTLS`
- implicit = false;
- };
- };
-
- # # POP3 (should be disabled, unless there is a real reason to use it)
- # "pop3" = {
- # bind = ["[::]:995"];
- # protocol = "pop3";
- # tls.implicit = true;
- # };
-
- # # LMTP
- # "lmtp" = {
- # bind = ["[::]:24"];
- # protocol = "lmtp";
- # };
-
- # ManageSieve
- "managesieve" = {
- bind = ["[::]:4190"];
- protocol = "managesieve";
- tls.implicit = true;
- };
- };
-
- tls = {
- enable = true;
-
- # Expect the client connection to be encrypted from the start (i.e.,
- # without STARTTLS)
- implicit = true;
-
- certificate = "default";
- };
-
- http = {
- url = "protocol + '://' + config_get('server.hostname') + ':' + local_port";
-
- # We are behind a nginx proxy, and can thus trust this header.
- use-x-forwarded = true;
- };
-
- auto-ban = {
- # Ban if the same IP fails to login 10 times in a day
- rate = "10/1d";
-
- # Ban the login for an user account, if different IP-Addresses tried and
- # failed to login 100 times in single day
- auth.rate = "100/1d";
-
- abuse.rate = "35/1d";
-
- loiter.rate = "150/1d";
-
- scan.rate = "150/1d";
- };
-
- cache = let
- MiB = 1024 * 1024;
- in {
- access-token.size = 10 * MiB;
- http-auth.size = 1 * MiB;
- permission.size = 5 * MiB;
- account.size = 10 * MiB;
- mailbox.size = 10 * MiB;
- thread.size = 10 * MiB;
- bayes.size = 10 * MiB;
- dns = {
- txt.size = 5 * MiB;
- mx.size = 5 * MiB;
- ptr.size = 1 * MiB;
- ipv4.size = 5 * MiB;
- ipv6.size = 5 * MiB;
- tlsa.size = 1 * MiB;
- mta-sts.size = 1 * MiB;
- rbl.size = 5 * MiB;
- };
- };
- };
-
- tracer = {
- # NOTE(@bpeetz):
- # We are using the console logger, because that has nice color output.
- # Simply using the console should be fine, as systemd pipes that to the journal
- # either way. <2025-02-08>
- console = {
- enable = true;
- ansi = true;
- level = "info";
- type = "console";
- };
- };
-
- store = {
- "rocksdb-data" = {
- type = "rocksdb";
- path = "${cfg.dataDirectory}/storage/data";
- compression = "lz4";
-
- # Perform “maintenance” every day at 3 am local time.
- purge.frequency = "0 3 *";
- };
- "rocksdb-directory" = lib.mkIf (cfg.principals == null) {
- type = "rocksdb";
- path = "${cfg.dataDirectory}/storage/directory";
- compression = "lz4";
-
- # Perform “maintenance” every day at 1 am local time.
- purge.frequency = "0 1 *";
- };
- "rocksdb-full-text-search" = {
- type = "rocksdb";
- path = "${cfg.dataDirectory}/storage/full-text-search";
- compression = "lz4";
-
- # Perform “maintenance” every day at 2 am local time.
- purge.frequency = "0 2 *";
- };
- "file-system" = {
- type = "fs";
- path = "${cfg.dataDirectory}/storage/blobs";
- depth = 2;
- compression = "lz4";
-
- # Perform “maintenance” every day at 5:30 am local time.
- purge.frequency = "30 5 *";
- };
- "redis" = {
- type = "redis";
- redis-type = "single";
- urls = "unix://${config.services.redis.servers."stalwart-mail".unixSocket}";
- timeout = "10s";
-
- # Perform “maintenance” every day at 2:30 am local time.
- purge.frequency = "30 2 *";
- };
- };
- storage = {
- # PostgreSQL is an option, but this is recommended for single node
- # configurations.
- data = "rocksdb-data";
-
- # We could also re-use the data storage backend for that.
- blob = "file-system";
-
- full-text.default-language = "en";
- fts = "rocksdb-full-text-search";
-
- directory = "${directory}";
-
- lookup = "redis";
-
- # NOTE(@bpeetz): This will encrypt all emails with the users pgp key (if it
- # can be determined.) This is a wonderful feature, but quite tiresome, if
- # the user intends to read their email without a their pgp key present (for
- # example via their smartphone.) <2025-02-07>
- encryption.enable = false;
- };
-
- directory = {
- "in-memory" = lib.mkIf (cfg.principals != null) {
- type = "memory";
- inherit (cfg) principals;
- };
- "internal" = lib.mkIf (cfg.principals == null) {
- type = "internal";
- store = "rocksdb-directory";
- };
- };
-
- certificate = {
- "default" = {
- cert = "%{file:${config.security.acme.certs.${cfg.fqdn}.directory}/fullchain.pem}%";
- private-key = "%{file:${config.security.acme.certs.${cfg.fqdn}.directory}/key.pem}%";
- default = true;
- };
- };
- };
-}
diff --git a/modules/by-name/sy/system-info/module.nix b/modules/by-name/sy/system-info/module.nix
deleted file mode 100644
index 8136ae5..0000000
--- a/modules/by-name/sy/system-info/module.nix
+++ /dev/null
@@ -1,79 +0,0 @@
-{
- lib,
- config,
- pkgs,
- ...
-}: let
- mkVirtualHostDisplay = name: value: let
- aliases =
- if value.serverAliases != []
- then
- ": "
- + builtins.concatStringsSep " " value.serverAliases
- else "";
- in ''
- ${name}${aliases}
- '';
- vHosts = builtins.concatStringsSep "" (builtins.attrValues (builtins.mapAttrs mkVirtualHostDisplay config.services.nginx.virtualHosts));
-
- mkOpenPortDisplay = mode: port: let
- checkEnabled = service: name:
- if config.vhack.${service}.enable
- then name
- else "<port is '${name}' but service 'vhack.${service}' is not enabled.>";
- mappings = {
- "22" = checkEnabled "openssh" "ssh";
- "80" = checkEnabled "nginx" "http";
- "443" = checkEnabled "nginx" "https";
-
- "53" = checkEnabled "dns" "dns";
-
- "24" = checkEnabled "mail" "mail-lmtp";
- "465" = checkEnabled "mail" "mail-smtp-tls";
- "25" = checkEnabled "mail" "mail-smtp";
- "993" = checkEnabled "mail" "mail-imap-tls";
- "995" = checkEnabled "mail" "mail-pop3-tls";
-
- "10222" = checkEnabled "taskchampion-sync" "taskchampion-sync";
-
- # TODO(@bpeetz): Check which service opens these ports: <2025-01-28>
- "64738" = "???";
- "4190" = "???";
- };
- in ''
- ${mode} ${builtins.toString port}: ${
- if (builtins.hasAttr "${builtins.toString port}" mappings)
- then mappings.${builtins.toString port}
- else
- builtins.throw
- "'${builtins.toString port}' is still missing from the system info port -> name map. Maybe add it?"
- }
- '';
-
- # TODO(@bpeetz): This should probably also include the allowed TCP/UDP port ranges. <2025-01-28>
- openTCPPorts = builtins.concatStringsSep "" (builtins.map (mkOpenPortDisplay "TCP") config.networking.firewall.allowedTCPPorts);
- openUDPPorts = builtins.concatStringsSep "" (builtins.map (mkOpenPortDisplay "UDP") config.networking.firewall.allowedUDPPorts);
-
- markdown = pkgs.writeText "${config.networking.hostName}-system-info.md" ''
- ## Virtual Hosts
- ${vHosts}
- ## Open ports
- ${openTCPPorts}
- ${openUDPPorts}
- '';
-in {
- options.vhack.system-info = {
- markdown = lib.mkOption {
- type = lib.types.package;
- description = ''
- A derivation, that builds a markdown file, showing relevant system
- information for this host.
- '';
- readOnly = true;
- };
- };
-
- config.vhack.system-info = {
- inherit markdown;
- };
-}
diff --git a/modules/by-name/ta/taskchampion-sync/module.nix b/modules/by-name/ta/taskchampion-sync/module.nix
deleted file mode 100644
index 1870186..0000000
--- a/modules/by-name/ta/taskchampion-sync/module.nix
+++ /dev/null
@@ -1,34 +0,0 @@
-{
- config,
- lib,
- ...
-}: let
- cfg = config.vhack.taskchampion-sync;
- dataDirectory = "/var/lib/taskchampion-sync-server";
-in {
- options.vhack.taskchampion-sync = {
- enable = lib.mkEnableOption "taskchampion-sync";
- };
-
- config = lib.mkIf cfg.enable {
- users = {
- users.taskchampion.uid = config.vhack.constants.ids.uids.taskchampion;
- groups.taskchampion.gid = config.vhack.constants.ids.uids.taskchampion;
- };
-
- vhack.persist.directories = [
- {
- directory = dataDirectory;
- user = "taskchampion";
- group = "taskchampion";
- mode = "0700";
- }
- ];
-
- services.taskchampion-sync-server = {
- enable = true;
- openFirewall = true;
- dataDir = dataDirectory;
- };
- };
-}
diff --git a/modules/by-name/us/users/module.nix b/modules/by-name/us/users/module.nix
deleted file mode 100644
index a197b13..0000000
--- a/modules/by-name/us/users/module.nix
+++ /dev/null
@@ -1,82 +0,0 @@
-{
- config,
- lib,
- pkgs,
- ...
-}: let
- cfg = config.vhack.users;
-
- mkUser = {
- name,
- password,
- uid,
- sshKey,
- }: {
- inherit name;
- value = {
- inherit name uid;
- isNormalUser = true;
- home = "/home/${name}";
- hashedPassword = password;
- extraGroups = [
- "wheel"
- ];
- openssh.authorizedKeys.keys = [
- sshKey
- ];
- };
- };
-
- extraUsers = lib.listToAttrs (builtins.map mkUser [
- {
- name = "soispha";
- password = "$y$jFT$3.8XmUyukZvpExMUxDZkI.$IVrJgm8ysNDF/0vDD2kF6w73ozXgr1LMVRNN4Bq7pv1";
- sshKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIME4ZVa+IoZf6T3U08JG93i6QIAJ4amm7mkBzO14JSkz cardno:000F_18F83532";
- uid = 1000;
- }
- {
- name = "sils";
- password = "$y$jFT$KpFnahVCE9JbE.5P3us8o.$ZzSxCusWqe3sL7b6DLgOXNNUf114tiiptM6T8lDxtKC";
- sshKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAe4o1PM6VasT3KZNl5NYvgkkBrPOg36dqsywd10FztS openpgp:0x21D20D6A";
- uid = 1001;
- }
- ]);
-in {
- options.vhack.users = {
- enable = lib.mkEnableOption "user setup";
- };
-
- config = lib.mkIf cfg.enable {
- users = {
- mutableUsers = false;
- defaultUserShell = pkgs.bashInteractive;
-
- users =
- {
- root = {
- hashedPassword = lib.mkForce null; # to lock root
- openssh.authorizedKeys.keys = lib.mkForce [];
- };
- }
- // extraUsers;
-
- # TODO(@bpeetz): Is this still relevant?
- # If it is, it should be moved to a separate module. <2024-12-24>
- # nixremote = {
- # name = "nixremote";
- # isNormalUser = true;
- # createHome = true;
- # home = "/home/nixremote";
- # uid = 1003;
- # group = "nixremote";
- # openssh.authorizedKeys.keys = [
- # "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCbSWqFzb+WTq2JVoRGoTkCkP7AM3bNY91bsUBeoQQc8gKAWuqCrpAOmr2Q2QMaTTGEOM0CsWfWLs3ZYtynHmc7wIFc4T/sUloV+dB9oSCmOk5ePxtj8+gpPK35Ja+ug5zmXsaI4s+n9mEbuuEjn33MxDYCUzAI+aWvWe68u/j+FM3u9c3Ta009rotajjSZ/cmIltgNLsG1rnAZRpwmLVg5UL4cb9um54o/NLYFd2KAekQFVbwUQDzzqriZhWmzkfhnznBMDblf9R1xvZ18Lqv3JF21shdaR43NW1wtuntBvAdsVYK2VUEbj+3MxTkK0aQ/E9SHMtH8MRE4oxU74TeTWfIhuSZk9/wekzSNMkHP3ReFC6B9xCMYa+ZqaTaGSWLQi78AQDeM2F9rAfp3hQzyRa7T7qKlgbae/hEb07xZglqmG7eml9vPSt4AHv5Y176Q95NiiWduGoLQOmjvSBMU9/KEGrGKyLfGH1Wa2EOfPxKKcvcHW0Xi9PlPiuP0nYk= root@thinklappi"
- # ];
- # };
- # };
- # groups.nixremote = {
- # gid = 1004;
- # };
- };
- };
-}