From 837fc97b30a41d766dd53a2370f6cb1d26364f9a Mon Sep 17 00:00:00 2001 From: Azat Bahawi Date: Wed, 20 Sep 2023 15:26:47 +0300 Subject: 2023-09-20 --- default.nix | 14 + flake.nix | 2 +- lib/my.nix | 1 + modules/common/emacs/default.nix | 2 +- modules/common/emacs/doom/config.el | 11 - modules/common/vscode.nix | 2 +- modules/nixos/clickhouse.nix | 18 ++ modules/nixos/default.nix | 2 + modules/nixos/git/default.nix | 4 +- modules/nixos/nsd.nix | 1 + modules/nixos/plausible-nixpkgs-override.nix | 312 +++++++++++++++++++++++ modules/nixos/plausible.nix | 144 +++++++++++ nixosConfigurations/eonwe/default.nix | 1 + nixosConfigurations/manwe/default.nix | 4 +- nixosConfigurations/manwe/mailserver.nix | 112 -------- nixosConfigurations/manwe/mailserver/default.nix | 96 +++++++ nixosConfigurations/manwe/webserver.nix | 9 +- 17 files changed, 605 insertions(+), 130 deletions(-) create mode 100644 default.nix create mode 100644 modules/nixos/clickhouse.nix create mode 100644 modules/nixos/plausible-nixpkgs-override.nix create mode 100644 modules/nixos/plausible.nix delete mode 100644 nixosConfigurations/manwe/mailserver.nix create mode 100644 nixosConfigurations/manwe/mailserver/default.nix diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..c7d0c26 --- /dev/null +++ b/default.nix @@ -0,0 +1,14 @@ +( + import + ( + let + lock = builtins.fromJSON (builtins.readFile ./flake.lock); + in + fetchTarball { + url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz"; + sha256 = lock.nodes.flake-compat.locked.narHash; + } + ) + {src = ./.;} +) +.defaultNix diff --git a/flake.nix b/flake.nix index 3f16734..27b027a 100644 --- a/flake.nix +++ b/flake.nix @@ -356,7 +356,7 @@ darwinModules.nixfiles = import ./modules/darwin; darwinConfigurations = importConfigurations ./darwinConfigurations; - overlays.default = final: prev: rec { + overlays.default = final: prev: { bruh = prev.callPackage ./packages/bruh.nix {}; mpv-autosub = prev.callPackage ./packages/mpv-autosub.nix {}; myip = prev.callPackage ./packages/myip.nix {}; diff --git a/lib/my.nix b/lib/my.nix index 95b89cf..8ae8840 100644 --- a/lib/my.nix +++ b/lib/my.nix @@ -163,6 +163,7 @@ with lib; "grafana.${shire}" "loki.${shire}" "ntfy.${shire}" + "plausible.${shire}" "prometheus.${shire}" "radicale.${shire}" "rss-bridge.${shire}" diff --git a/modules/common/emacs/default.nix b/modules/common/emacs/default.nix index ed25536..1d205b9 100644 --- a/modules/common/emacs/default.nix +++ b/modules/common/emacs/default.nix @@ -92,7 +92,7 @@ in { jre # :lang plantuml libtool # :term vterm libxml2 # :lang data - nixd # :lang (nix +lsp) + nil # :lang (nix +lsp) nodePackages.bash-language-server # :lang (sh +lsp) nodePackages.eslint # :lang (json +lsp) nodePackages.js-beautify # :lang web diff --git a/modules/common/emacs/doom/config.el b/modules/common/emacs/doom/config.el index e7e0bd4..015954b 100644 --- a/modules/common/emacs/doom/config.el +++ b/modules/common/emacs/doom/config.el @@ -78,17 +78,6 @@ (setq lsp-haskell-formatting-provider "ormolu") -;; -;;; Nix -;; - -(after! lsp-mode - (add-to-list 'lsp-language-id-configuration '(nix-mode . "nix")) - (lsp-register-client - (make-lsp-client :new-connection (lsp-stdio-connection '("nixd")) - :major-modes '(nix-mode) - :server-id 'nix))) - ;; ;;; YAML ;; diff --git a/modules/common/vscode.nix b/modules/common/vscode.nix index d90d301..ab55acc 100644 --- a/modules/common/vscode.nix +++ b/modules/common/vscode.nix @@ -178,7 +178,7 @@ in { nix = { enableLanguageServer = true; - serverPath = "${pkgs.rnix-lsp}/bin/rnix-lsp"; + serverPath = "${pkgs.nil}/bin/nil"; }; python = with pkgs.python311Packages; { diff --git a/modules/nixos/clickhouse.nix b/modules/nixos/clickhouse.nix new file mode 100644 index 0000000..4fae683 --- /dev/null +++ b/modules/nixos/clickhouse.nix @@ -0,0 +1,18 @@ +{ + config, + lib, + ... +}: +with lib; let + cfg = config.nixfiles.modules.clickhouse; +in { + options.nixfiles.modules.clickhouse = { + enable = mkEnableOption "Clickhouse"; + }; + + config = mkIf cfg.enable { + services.clickhouse = { + enable = true; + }; + }; +} diff --git a/modules/nixos/default.nix b/modules/nixos/default.nix index 466e2e0..5b9a3be 100644 --- a/modules/nixos/default.nix +++ b/modules/nixos/default.nix @@ -6,6 +6,7 @@ _: { ./beets.nix ./bluetooth.nix ./chromium.nix + ./clickhouse.nix ./common ./discord.nix ./docker.nix @@ -41,6 +42,7 @@ _: { ./ntfy.nix ./nullmailer.nix ./openssh.nix + ./plausible.nix ./podman.nix ./postgresql.nix ./profiles diff --git a/modules/nixos/git/default.nix b/modules/nixos/git/default.nix index 5fe4391..9fb43db 100644 --- a/modules/nixos/git/default.nix +++ b/modules/nixos/git/default.nix @@ -73,9 +73,9 @@ in { fastcgi_param QUERY_STRING $args; fastcgi_param HTTP_HOST $server_name; - # This makes `go get ...` work. + # This makes `go get ...` work and adds analytics. sub_filter '' - ''; + ''; sub_filter_once on; ''; "~* ^.+(cgit.css|robots.txt)$".extraConfig = '' diff --git a/modules/nixos/nsd.nix b/modules/nixos/nsd.nix index 0060a14..2266ea5 100644 --- a/modules/nixos/nsd.nix +++ b/modules/nixos/nsd.nix @@ -137,6 +137,7 @@ in { grafana = manwe; loki = manwe; ntfy = manwe; + plausible = manwe; prometheus = manwe; radicale = manwe; rss-bridge = manwe; diff --git a/modules/nixos/plausible-nixpkgs-override.nix b/modules/nixos/plausible-nixpkgs-override.nix new file mode 100644 index 0000000..67fffdc --- /dev/null +++ b/modules/nixos/plausible-nixpkgs-override.nix @@ -0,0 +1,312 @@ +{ + lib, + pkgs, + config, + ... +}: +with lib; let + cfg = config.services.plausible; +in { + options.services.plausible = { + enable = mkEnableOption (lib.mdDoc "plausible"); + + package = mkPackageOptionMD pkgs "plausible" {}; + + releaseCookiePath = mkOption { + type = with types; either str path; + description = lib.mdDoc '' + The path to the file with release cookie. (used for remote connection to the running node). + ''; + }; + + adminUser = { + name = mkOption { + default = "admin"; + type = types.str; + description = lib.mdDoc '' + Name of the admin user that plausible will created on initial startup. + ''; + }; + + email = mkOption { + type = types.str; + example = "admin@localhost"; + description = lib.mdDoc '' + Email-address of the admin-user. + ''; + }; + + passwordFile = mkOption { + type = types.either types.str types.path; + description = lib.mdDoc '' + Path to the file which contains the password of the admin user. + ''; + }; + + activate = mkEnableOption (lib.mdDoc "activating the freshly created admin-user"); + }; + + database = { + clickhouse = { + setup = mkEnableOption (lib.mdDoc "creating a clickhouse instance") // {default = true;}; + url = mkOption { + default = "http://localhost:8123/default"; + type = types.str; + description = lib.mdDoc '' + The URL to be used to connect to `clickhouse`. + ''; + }; + }; + postgres = { + setup = mkEnableOption (lib.mdDoc "creating a postgresql instance") // {default = true;}; + dbname = mkOption { + default = "plausible"; + type = types.str; + description = lib.mdDoc '' + Name of the database to use. + ''; + }; + socket = mkOption { + default = "/run/postgresql"; + type = types.str; + description = lib.mdDoc '' + Path to the UNIX domain-socket to communicate with `postgres`. + ''; + }; + }; + }; + + server = { + disableRegistration = mkOption { + default = true; + type = types.bool; + description = lib.mdDoc '' + Whether to prohibit creating an account in plausible's UI. + ''; + }; + secretKeybaseFile = mkOption { + type = types.either types.path types.str; + description = lib.mdDoc '' + Path to the secret used by the `phoenix`-framework. Instructions + how to generate one are documented in the + [ + framework docs](https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Gen.Secret.html#content). + ''; + }; + port = mkOption { + default = 8000; + type = types.port; + description = lib.mdDoc '' + Port where the service should be available. + ''; + }; + baseUrl = mkOption { + type = types.str; + description = lib.mdDoc '' + Public URL where plausible is available. + + Note that `/path` components are currently ignored: + [ + https://github.com/plausible/analytics/issues/1182 + ](https://github.com/plausible/analytics/issues/1182). + ''; + }; + }; + + mail = { + email = mkOption { + default = "hello@plausible.local"; + type = types.str; + description = lib.mdDoc '' + The email id to use for as *from* address of all communications + from Plausible. + ''; + }; + smtp = { + hostAddr = mkOption { + default = "localhost"; + type = types.str; + description = lib.mdDoc '' + The host address of your smtp server. + ''; + }; + hostPort = mkOption { + default = 25; + type = types.port; + description = lib.mdDoc '' + The port of your smtp server. + ''; + }; + user = mkOption { + default = null; + type = types.nullOr types.str; + description = lib.mdDoc '' + The username/email in case SMTP auth is enabled. + ''; + }; + passwordFile = mkOption { + default = null; + type = with types; nullOr (either str path); + description = lib.mdDoc '' + The path to the file with the password in case SMTP auth is enabled. + ''; + }; + enableSSL = mkEnableOption (lib.mdDoc "SSL when connecting to the SMTP server"); + retries = mkOption { + type = types.ints.unsigned; + default = 2; + description = lib.mdDoc '' + Number of retries to make until mailer gives up. + ''; + }; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + { + assertion = cfg.adminUser.activate -> cfg.database.postgres.setup; + message = '' + Unable to automatically activate the admin-user if no locally managed DB for + postgres (`services.plausible.database.postgres.setup') is enabled! + ''; + } + ]; + + services = { + postgresql = mkIf cfg.database.postgres.setup { + enable = true; + }; + + clickhouse = mkIf cfg.database.clickhouse.setup { + enable = true; + }; + + epmd.enable = true; + }; + + environment.systemPackages = [cfg.package]; + + systemd.services = mkMerge [ + { + plausible = { + inherit (cfg.package.meta) description; + documentation = ["https://plausible.io/docs/self-hosting"]; + wantedBy = ["multi-user.target"]; + after = + optional cfg.database.clickhouse.setup "clickhouse.service" + ++ optionals cfg.database.postgres.setup [ + "postgresql.service" + "plausible-postgres.service" + ]; + requires = + optional cfg.database.clickhouse.setup "clickhouse.service" + ++ optionals cfg.database.postgres.setup [ + "postgresql.service" + "plausible-postgres.service" + ]; + + environment = + { + # NixOS specific option to avoid that it's trying to write into its store-path. + # See also https://github.com/lau/tzdata#data-directory-and-releases + STORAGE_DIR = "/var/lib/plausible/elixir_tzdata"; + + # Configuration options from + # https://plausible.io/docs/self-hosting-configuration + PORT = toString cfg.server.port; + DISABLE_REGISTRATION = boolToString cfg.server.disableRegistration; + + RELEASE_TMP = "/var/lib/plausible/tmp"; + # Home is needed to connect to the node with iex + HOME = "/var/lib/plausible"; + + ADMIN_USER_NAME = cfg.adminUser.name; + ADMIN_USER_EMAIL = cfg.adminUser.email; + + DATABASE_SOCKET_DIR = cfg.database.postgres.socket; + DATABASE_NAME = cfg.database.postgres.dbname; + CLICKHOUSE_DATABASE_URL = cfg.database.clickhouse.url; + + BASE_URL = cfg.server.baseUrl; + + MAILER_EMAIL = cfg.mail.email; + SMTP_HOST_ADDR = cfg.mail.smtp.hostAddr; + SMTP_HOST_PORT = toString cfg.mail.smtp.hostPort; + SMTP_RETRIES = toString cfg.mail.smtp.retries; + SMTP_HOST_SSL_ENABLED = boolToString cfg.mail.smtp.enableSSL; + + SELFHOST = "true"; + } + // (optionalAttrs (cfg.mail.smtp.user != null) { + SMTP_USER_NAME = cfg.mail.smtp.user; + }); + + path = + [cfg.package] + ++ optional cfg.database.postgres.setup config.services.postgresql.package; + script = '' + export RELEASE_COOKIE="$(< $CREDENTIALS_DIRECTORY/RELEASE_COOKIE )" + export ADMIN_USER_PWD="$(< $CREDENTIALS_DIRECTORY/ADMIN_USER_PWD )" + export SECRET_KEY_BASE="$(< $CREDENTIALS_DIRECTORY/SECRET_KEY_BASE )" + + ${lib.optionalString (cfg.mail.smtp.passwordFile != null) + ''export SMTP_USER_PWD="$(< $CREDENTIALS_DIRECTORY/SMTP_USER_PWD )"''} + + # setup + ${cfg.package}/createdb.sh + ${cfg.package}/migrate.sh + export IP_GEOLOCATION_DB=${pkgs.dbip-country-lite}/share/dbip/dbip-country-lite.mmdb + ${cfg.package}/bin/plausible eval "(Plausible.Release.prepare() ; Plausible.Auth.create_user(\"$ADMIN_USER_NAME\", \"$ADMIN_USER_EMAIL\", \"$ADMIN_USER_PWD\"))" + ${optionalString cfg.adminUser.activate '' + psql -d plausible <<< "UPDATE users SET email_verified=true where email = '$ADMIN_USER_EMAIL';" + ''} + + exec plausible start + ''; + + serviceConfig = { + DynamicUser = true; + PrivateTmp = true; + WorkingDirectory = "/var/lib/plausible"; + StateDirectory = "plausible"; + LoadCredential = + [ + "ADMIN_USER_PWD:${cfg.adminUser.passwordFile}" + "SECRET_KEY_BASE:${cfg.server.secretKeybaseFile}" + "RELEASE_COOKIE:${cfg.releaseCookiePath}" + ] + ++ lib.optionals (cfg.mail.smtp.passwordFile != null) ["SMTP_USER_PWD:${cfg.mail.smtp.passwordFile}"]; + }; + }; + } + (mkIf cfg.database.postgres.setup { + # `plausible' requires the `citext'-extension. + plausible-postgres = { + after = ["postgresql.service"]; + partOf = ["plausible.service"]; + serviceConfig = { + Type = "oneshot"; + User = config.services.postgresql.superUser; + RemainAfterExit = true; + }; + script = with cfg.database.postgres; '' + PSQL() { + ${config.services.postgresql.package}/bin/psql --port=5432 "$@" + } + # check if the database already exists + if ! PSQL -lqt | ${pkgs.coreutils}/bin/cut -d \| -f 1 | ${pkgs.gnugrep}/bin/grep -qw ${dbname} ; then + PSQL -tAc "CREATE ROLE plausible WITH LOGIN;" + PSQL -tAc "CREATE DATABASE ${dbname} WITH OWNER plausible;" + PSQL -d ${dbname} -tAc "CREATE EXTENSION IF NOT EXISTS citext;" + fi + ''; + }; + }) + ]; + }; + + meta.maintainers = with maintainers; [ma27]; + meta.doc = ./plausible.md; +} diff --git a/modules/nixos/plausible.nix b/modules/nixos/plausible.nix new file mode 100644 index 0000000..856b318 --- /dev/null +++ b/modules/nixos/plausible.nix @@ -0,0 +1,144 @@ +{ + config, + inputs, + lib, + pkgsPr, + ... +}: +with lib; let + cfg = config.nixfiles.modules.plausible; +in { + disabledModules = ["services/web-apps/plausible.nix"]; + imports = [ + # TODO Wait for https://github.com/NixOS/nixpkgs/pull/253687 + ./plausible-nixpkgs-override.nix + ]; + + options.nixfiles.modules.plausible = { + enable = mkEnableOption "Plausible Analytics"; + + port = mkOption { + description = "Port."; + type = with types; port; + default = 8000; + }; + + domain = mkOption { + description = "Domain name sans protocol scheme."; + type = with types; nullOr str; + default = "plausible.${config.networking.domain}"; + }; + }; + + config = let + db = "plausible"; + in + mkIf cfg.enable { + secrets = { + plausible-key = { + file = "${inputs.self}/secrets/plausible-key"; + mode = "0444"; # The user is dynamic so the file must be world-readable. + }; + plausible-admin-password = { + file = "${inputs.self}/secrets/plausible-admin-password"; + mode = "0444"; # The user is dynamic so the file must be world-readable. + }; + plausible-smtp-password = { + file = "${inputs.self}/secrets/smtp-password"; + mode = "0444"; # The user is dynamic so the file must be world-readable. + }; + plausible-release-cookie = { + file = "${inputs.self}/secrets/plausible-release-cookie"; + mode = "0444"; # The user is dynamic so the file must be world-readable. + }; + }; + + nixfiles.modules = { + nginx = { + enable = true; + upstreams.plausible.servers."127.0.0.1:${toString cfg.port}" = {}; + virtualHosts.${cfg.domain} = { + locations."/" = { + proxyPass = "http://plausible"; + proxyWebsockets = true; + }; + extraConfig = nginxInternalOnly; + }; + }; + postgresql = { + enable = true; + extraPostStart = [ + '' + $PSQL "${db}" -tAc 'GRANT ALL ON SCHEMA "public" TO "${db}"' + $PSQL "${db}" -tAc 'CREATE EXTENSION IF NOT EXISTS citext' + '' + ]; + }; + clickhouse.enable = true; + }; + + services.postgresql = { + ensureDatabases = [db]; + ensureUsers = [ + { + name = db; + ensurePermissions."DATABASE \"${db}\"" = "ALL"; + } + ]; + }; + + services.plausible = { + enable = true; + + # TODO Wait for https://github.com/NixOS/nixpkgs/pull/253687 + package = (pkgsPr 253687 "sha256-36nXNVmZDgf//MrM6/VC7W4Vm013tJ6MlXvYQElhRRw=").plausible; + + adminUser = { + name = "admin"; + email = "admin@${my.domain.shire}"; + passwordFile = config.secrets.plausible-admin-password.path; + activate = false; + }; + + mail = { + email = "admin+plausible@${my.domain.shire}"; + smtp = { + hostAddr = my.domain.shire; + hostPort = 465; + enableSSL = true; + user = "azahi@${my.domain.shire}"; + passwordFile = config.secrets.plausible-smtp-password.path; + }; + }; + + database = { + clickhouse = { + setup = false; + url = "http://127.0.0.1:8123/default"; + }; + + postgres = { + setup = true; + dbname = db; + }; + }; + + server = { + baseUrl = "https://${cfg.domain}"; + disableRegistration = true; + inherit (cfg) port; + secretKeybaseFile = config.secrets.plausible-key.path; + }; + + releaseCookiePath = config.secrets.plausible-release-cookie.path; + }; + + systemd.services.plausible = rec { + after = [ + "postgresql.service" + "clickhouse.service" + ]; + requires = after; + }; + }; +} diff --git a/nixosConfigurations/eonwe/default.nix b/nixosConfigurations/eonwe/default.nix index d155cdf..e7f0187 100644 --- a/nixosConfigurations/eonwe/default.nix +++ b/nixosConfigurations/eonwe/default.nix @@ -21,6 +21,7 @@ with lib; { games = { lutris.enable = true; minecraft.client.enable = true; + steam.enable = true; }; android.enable = true; diff --git a/nixosConfigurations/manwe/default.nix b/nixosConfigurations/manwe/default.nix index 267654d..c2ac8be 100644 --- a/nixosConfigurations/manwe/default.nix +++ b/nixosConfigurations/manwe/default.nix @@ -5,7 +5,7 @@ }: with lib; { imports = [ - ./mailserver.nix + ./mailserver ./webserver.nix ]; @@ -23,6 +23,7 @@ with lib; { monitoring.enable = true; postgresql.enable = true; + clickhouse.enable = true; git.server = { enable = true; @@ -43,6 +44,7 @@ with lib; { }; vaultwarden.enable = true; ntfy.enable = true; + plausible.enable = true; }; # A VPN to play old LAN games with the boys. diff --git a/nixosConfigurations/manwe/mailserver.nix b/nixosConfigurations/manwe/mailserver.nix deleted file mode 100644 index 389a9a0..0000000 --- a/nixosConfigurations/manwe/mailserver.nix +++ /dev/null @@ -1,112 +0,0 @@ -{ - config, - inputs, - lib, - ... -}: -with lib; { - imports = [inputs.simple-nixos-mailserver.nixosModule]; - - ark.directories = with config.mailserver; [ - "/var/lib/dovecot" - "/var/lib/postfix" - config.security.dhparams.params.dovecot2.path - dkimKeyDirectory - mailDirectory - sieveDirectory - ]; - - secrets = with config.mailserver; { - dkim-key-azahi-cc = { - file = "${inputs.self}/secrets/dkim-key-azahi-cc"; - path = "${dkimKeyDirectory}/${my.domain.azahi}.${dkimSelector}.key"; - owner = config.services.opendkim.user; - inherit (config.services.opendkim) group; - }; - dkim-key-rohan-net = { - file = "${inputs.self}/secrets/dkim-key-rohan-net"; - path = "${dkimKeyDirectory}/${my.domain.rohan}.${dkimSelector}.key"; - owner = config.services.opendkim.user; - inherit (config.services.opendkim) group; - }; - dkim-key-gondor-net = { - file = "${inputs.self}/secrets/dkim-key-gondor-net"; - path = "${dkimKeyDirectory}/${my.domain.gondor}.${dkimSelector}.key"; - owner = config.services.opendkim.user; - inherit (config.services.opendkim) group; - }; - dkim-key-shire-net = { - file = "${inputs.self}/secrets/dkim-key-shire-net"; - path = "${dkimKeyDirectory}/${my.domain.shire}.${dkimSelector}.key"; - owner = config.services.opendkim.user; - inherit (config.services.opendkim) group; - }; - }; - - nixfiles.modules = { - acme.enable = true; - redis.enable = true; - }; - - mailserver = let - cert = config.certs.${my.domain.shire}; - in { - enable = true; - - fqdn = config.networking.domain; - domains = with my.domain; [azahi gondor rohan shire]; - - localDnsResolver = false; - - certificateScheme = "manual"; - certificateFile = "${cert.directory}/fullchain.pem"; - keyFile = "${cert.directory}/key.pem"; - - lmtpSaveToDetailMailbox = "no"; - - redis = with config.services.redis.servers.default; { - address = bind; - inherit port; - password = requirePass; - }; - - loginAccounts = with my.domain; { - "azahi@${shire}" = { - hashedPassword = "@HASHED_PASSWORD@"; - aliases = [ - "@${azahi}" - "@${rohan}" - "@${gondor}" - "abuse@${shire}" - "admin@${shire}" - "ceo@${shire}" - "postmaster@${shire}" - "root@${shire}" - ]; - }; - "samwise@${shire}" = { - hashedPassword = "@HASHED_PASSWORD@"; - aliases = ["chad@${shire}"]; - quota = "1G"; - }; - }; - }; - - # https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/issues/241 - services.redis.servers.rspamd.enable = mkForce false; - systemd.services.rspamd = { - requires = mkForce ["redis-default.service"]; - after = mkForce ["redis-default.service"]; - }; - - services.fail2ban.jails = { - dovecot = { - enabled = true; - settings.mode = "aggressive"; - }; - postfix = { - enabled = true; - settings.mode = "aggressive"; - }; - }; -} diff --git a/nixosConfigurations/manwe/mailserver/default.nix b/nixosConfigurations/manwe/mailserver/default.nix new file mode 100644 index 0000000..4f58df7 --- /dev/null +++ b/nixosConfigurations/manwe/mailserver/default.nix @@ -0,0 +1,96 @@ +{ + config, + inputs, + lib, + ... +}: +with lib; { + imports = [inputs.simple-nixos-mailserver.nixosModule]; + + # Redis? + ark.directories = with config.mailserver; [ + "/var/lib/dovecot" + "/var/lib/postfix" + config.security.dhparams.params.dovecot2.path + dkimKeyDirectory + mailDirectory + sieveDirectory + ]; + + secrets = with config.mailserver; { + dkim-key-azahi-cc = { + file = "${inputs.self}/secrets/dkim-key-azahi-cc"; + path = "${dkimKeyDirectory}/${my.domain.azahi}.${dkimSelector}.key"; + owner = config.services.opendkim.user; + inherit (config.services.opendkim) group; + }; + dkim-key-rohan-net = { + file = "${inputs.self}/secrets/dkim-key-rohan-net"; + path = "${dkimKeyDirectory}/${my.domain.rohan}.${dkimSelector}.key"; + owner = config.services.opendkim.user; + inherit (config.services.opendkim) group; + }; + dkim-key-gondor-net = { + file = "${inputs.self}/secrets/dkim-key-gondor-net"; + path = "${dkimKeyDirectory}/${my.domain.gondor}.${dkimSelector}.key"; + owner = config.services.opendkim.user; + inherit (config.services.opendkim) group; + }; + dkim-key-shire-net = { + file = "${inputs.self}/secrets/dkim-key-shire-net"; + path = "${dkimKeyDirectory}/${my.domain.shire}.${dkimSelector}.key"; + owner = config.services.opendkim.user; + inherit (config.services.opendkim) group; + }; + }; + + nixfiles.modules = { + acme.enable = true; + redis.enable = true; + }; + + mailserver = let + cert = config.certs.${my.domain.shire}; + in { + enable = true; + + fqdn = config.networking.domain; + domains = with my.domain; [azahi gondor rohan shire]; + + localDnsResolver = false; + + certificateScheme = "manual"; + certificateFile = "${cert.directory}/fullchain.pem"; + keyFile = "${cert.directory}/key.pem"; + + lmtpSaveToDetailMailbox = "no"; + + redis = with config.services.redis.servers.default; { + address = bind; + inherit port; + password = requirePass; + }; + + # Just a list of accounts with aliases and hasedPasswords. Not necessarily + # secret, but kept from prying eyes. + loginAccounts = import ./accounts.nix lib; + }; + + # https://gitlab.com/simple-nixos-mailserver/nixos-mailserver/-/issues/241 + services.redis.servers.rspamd.enable = mkForce false; + systemd.services.rspamd = { + requires = mkForce ["redis-default.service"]; + after = mkForce ["redis-default.service"]; + }; + + services.fail2ban.jails = { + dovecot = { + enabled = true; + settings.mode = "aggressive"; + }; + postfix = { + enabled = true; + settings.mode = "aggressive"; + }; + }; +} diff --git a/nixosConfigurations/manwe/webserver.nix b/nixosConfigurations/manwe/webserver.nix index f07d545..9e19474 100644 --- a/nixosConfigurations/manwe/webserver.nix +++ b/nixosConfigurations/manwe/webserver.nix @@ -13,7 +13,14 @@ with lib; { "bitwarden.${shire}".locations."/".return = "301 https://vaultwarden.${shire}"; ${azahi} = { serverAliases = ["frodo.${gondor}" "frodo.${rohan}"]; - locations."/".root = inputs.azahi-cc; + locations."/" = { + root = inputs.azahi-cc; + extraConfig = '' + sub_filter '' + ''; + sub_filter_once on; + ''; + }; }; } // (let -- cgit 1.4.1