From f4615cbae90f813a8bbaced2e6e59481146e91f3 Mon Sep 17 00:00:00 2001 From: Grimmauld Date: Wed, 8 May 2024 21:49:37 +0200 Subject: [PATCH] server config --- authorizedKeys.nix | 7 + common/network/default.nix | 5 + common/tooling/default.nix | 23 ++- common/tooling/nix.nix | 4 +- common/tooling/security.nix | 1 - configuration.nix | 2 + fake_flake.nix | 27 ++- modules/discord-matrix-bridge.nix | 43 +++++ modules/email.nix | 47 +++++ modules/fail2ban.nix | 19 ++ modules/gitea.nix | 50 +++++ modules/grafana.nix | 43 +++++ modules/letsencrypt.nix | 15 ++ modules/mailpass/admin | 1 + modules/mailpass/contact | 1 + modules/mailpass/grimmauld | 1 + modules/mastodon.nix | 17 ++ modules/matrix.nix | 175 ++++++++++++++++++ modules/matrix_synapse_log_config.yaml | 25 +++ modules/mjolnir.nix | 69 +++++++ modules/nextcloud.nix | 82 ++++++++ modules/patch_bridge_perms.patch | 12 ++ modules/prometheus.nix | 52 ++++++ modules/ptero.nix | 130 +++++++++++++ modules/puffer.nix | 50 +++++ modules/toolchains.nix | 50 +++++ nix/sources.json | 18 ++ secrets/grafana_admin_pass.age | 15 ++ secrets/matrix_admin_pass.age | 16 ++ secrets/matrix_discord_bridge_token.age | 15 ++ secrets/matrix_mjolnir_pass.age | 16 ++ secrets/matrix_mjolnir_tle_pass.age | 15 ++ secrets/nextcloud_admin_pass.age | 15 ++ secrets/nextcloud_db_pass.age | 15 ++ secrets/ptero_env.age | Bin 0 -> 960 bytes secrets/secrets.nix | 16 ++ secrets/synapse_db_pass.age | 15 ++ secrets/synapse_db_pass_prepared.age | Bin 0 -> 899 bytes .../synapse_registration_shared_secret.age | Bin 0 -> 844 bytes .../grimmauld-nixos-server/configuration.nix | 35 ++++ .../hardware-configuration.nix | 13 ++ users.nix | 3 + 42 files changed, 1144 insertions(+), 14 deletions(-) create mode 100644 authorizedKeys.nix create mode 100644 modules/discord-matrix-bridge.nix create mode 100644 modules/email.nix create mode 100644 modules/fail2ban.nix create mode 100644 modules/gitea.nix create mode 100644 modules/grafana.nix create mode 100644 modules/letsencrypt.nix create mode 100644 modules/mailpass/admin create mode 100644 modules/mailpass/contact create mode 100644 modules/mailpass/grimmauld create mode 100644 modules/mastodon.nix create mode 100644 modules/matrix.nix create mode 100644 modules/matrix_synapse_log_config.yaml create mode 100644 modules/mjolnir.nix create mode 100644 modules/nextcloud.nix create mode 100644 modules/patch_bridge_perms.patch create mode 100644 modules/prometheus.nix create mode 100644 modules/ptero.nix create mode 100644 modules/puffer.nix create mode 100644 modules/toolchains.nix create mode 100644 secrets/grafana_admin_pass.age create mode 100644 secrets/matrix_admin_pass.age create mode 100644 secrets/matrix_discord_bridge_token.age create mode 100644 secrets/matrix_mjolnir_pass.age create mode 100644 secrets/matrix_mjolnir_tle_pass.age create mode 100644 secrets/nextcloud_admin_pass.age create mode 100644 secrets/nextcloud_db_pass.age create mode 100644 secrets/ptero_env.age create mode 100644 secrets/synapse_db_pass.age create mode 100644 secrets/synapse_db_pass_prepared.age create mode 100644 secrets/synapse_registration_shared_secret.age create mode 100644 specific/grimmauld-nixos-server/configuration.nix create mode 100644 specific/grimmauld-nixos-server/hardware-configuration.nix diff --git a/authorizedKeys.nix b/authorizedKeys.nix new file mode 100644 index 0000000..55144a6 --- /dev/null +++ b/authorizedKeys.nix @@ -0,0 +1,7 @@ +# these are public keys. Publishing them shouldn't be an issue until there is quantum computers breaking rsa. +# todo: use post-quantum keys for ssh (not possible yet, yikes) +[ + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCy7X5ByG4/9y2XkQSnXcpMGnV5WPGUd+B6FaYCDNmPQ7xIZEteS+kCpu9oiMP6C/H/FT+i9DZvCflkzgdFAyujYLKRYaZbZ3K6F60qN0rkJ0z/ZO5c6rqwIwR6BEoB7dq5inkyH9fZ8/SI+PXxELmeWF9ehT7kkQC+o9Ujpcjd7ZuZllbAz4UQZFRbbpwdVJCEDenu9/63yuYbvMupgGk0edaTiFT0Q9MSzs/3pNP8xlAxmmZ3HzSjeF7gUzBF7CaIroTeguiUjSVybUEx48P8fy878t7dUZf4anEno9MS0B3aqfZvCKuuPdAUdeBfCbFHRqN7GuCylFIXGPe95Mxl grimmauld@grimmauld-nixos" + "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQClLZhya2A7SoRSX2DNNM6OWgnGhtOFUor/WdyY59L0l6u5tEo9VyX5bCR84eo+uN4jyahSiGD1WC3RGIoNtHuSkKPxr0rqQhlbuyxraHGj7hOLhcGWRd2eIdsntbma7uPsn4zC0skKjpVNR7PU4LfSxti0gBhgq6uQhMtlfywwJshmwt55q7oT/zC449Uz2vyviy7sQ53R9YoOWEjB/+vU8jHxGlqLatXhOGKlBtrQxKm8PZ6jBYxAC6sGA4APIHWC3KC0S0X7wlmi42Dx9bbBm0rUjy095vRZ22fkE8x9OSTKDY/vFTLw5vwVMa8dACfA1Kc0+EpgOK77lZddeTvD grimmauld.de" + "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJhM1Fk5ix4OZAdlfCxL891KxeEKpyIFrP5yYkC9mg7E grimmauld@grimmauld-nixos" +] diff --git a/common/network/default.nix b/common/network/default.nix index dcdc58f..e467a16 100644 --- a/common/network/default.nix +++ b/common/network/default.nix @@ -20,6 +20,11 @@ in wireguard-tools openconnect ]; + + networking.firewall = { + enable = true; + allowPing = true; + }; }; imports = [ ./bluetooth.nix ]; diff --git a/common/tooling/default.nix b/common/tooling/default.nix index 9827c8c..6da5b2c 100644 --- a/common/tooling/default.nix +++ b/common/tooling/default.nix @@ -24,10 +24,20 @@ in (writeShellScriptBin "systemd-owner" "systemctl show -pUser,UID $@") (writeShellScriptBin "tree" "${lib.getExe pkgs.eza} -T --git -lh --no-permissions --no-user --no-filesize --no-time") (writeShellScriptBin "spawn" ''exec "$@" &> /dev/null &'') + (writeShellScriptBin "silent-add" "git add --intent-to-add $@ ; git update-index --assume-unchanged $@") + urlencode pstree dos2unix treefmt + file + wget + hyfetch + util-linux + btop + neovim-remote + linuxPackages.perf + eza gcc jdk17 @@ -36,25 +46,19 @@ in p7zip tea - eza fbcat gomuks - btop ranger - wget - file - util-linux + visualvm imagemagick nmap - - hyfetch + parted glib glibc expect - neovim-remote ] ++ lib.optionals cfg.graphical [ wev @@ -107,6 +111,9 @@ in fugitive ]; + boot.tmp.cleanOnBoot = true; + zramSwap.enable = true; + programs.neovim = { enable = true; viAlias = true; diff --git a/common/tooling/nix.nix b/common/tooling/nix.nix index aaf4d1b..b6ddda3 100644 --- a/common/tooling/nix.nix +++ b/common/tooling/nix.nix @@ -10,7 +10,6 @@ let in { environment.systemPackages = with pkgs; [ - (writeShellScriptBin "silent-add" "git add --intent-to-add $@ ; git update-index --assume-unchanged $@") (writeShellScriptBin "nix-referrers" "nix-store --query --referrers $@") (writeShellScriptBin "nixpkgs-review-head" "nixpkgs-review rev HEAD") (writeShellScriptBin "rebuild" "bash -c \"nixos-rebuild switch |& nom\"") @@ -23,6 +22,7 @@ in nix-output-monitor nix-search-cli niv + vulnix ]; environment.sessionVariables = lib.mkIf pkgs.config.allowUnfree { NIXPKGS_ALLOW_UNFREE = "1"; }; @@ -43,6 +43,4 @@ in }; # nix.package = pkgs.nixVersions.latest; nix.optimise.automatic = true; - - boot.tmp.cleanOnBoot = true; } diff --git a/common/tooling/security.nix b/common/tooling/security.nix index 61d8884..20456db 100644 --- a/common/tooling/security.nix +++ b/common/tooling/security.nix @@ -12,7 +12,6 @@ in with cfg; lib.mkIf enable { security.polkit.enable = true; - networking.firewall.enable = lib.mkIf network true; security.rtkit.enable = true; security.doas.enable = true; diff --git a/configuration.nix b/configuration.nix index f2d78bd..b85ea8b 100644 --- a/configuration.nix +++ b/configuration.nix @@ -13,6 +13,8 @@ kernelPackages = pkgs.linuxPackages_zen; }; + services.logrotate.checkConfig = false; # fixme: actually needed? + grimmShared = { enable = true; locale = true; diff --git a/fake_flake.nix b/fake_flake.nix index 6697119..8ce0d30 100644 --- a/fake_flake.nix +++ b/fake_flake.nix @@ -15,6 +15,23 @@ let grimmauld-nixos = [ ./specific/grimm-nixos-laptop/configuration.nix ]; + + grimmauld-nixos-server = [ + ./specific/grimmauld-nixos-server/configuration.nix + ./modules/letsencrypt.nix + + ./modules/matrix.nix + ./modules/puffer.nix + ./modules/gitea.nix + ./modules/grafana.nix + ./modules/nextcloud.nix + ./modules/prometheus.nix + # ./modules/mjolnir.nix + ./modules/fail2ban.nix + ./modules/email.nix + ./modules/discord-matrix-bridge.nix + ./modules/mastodon.nix + ]; }; nixpkgs_patches = [ @@ -29,8 +46,14 @@ in imports = [ "${nivSources.agenix}/modules/age.nix" (import "${nivSources.lix-module}/module.nix" { lix = nivSources.lix-pkg; }) - (builtins.getFlake (asGithubRef nivSources.chaotic)).nixosModules.default # fixme: ideally we'd not rely on the flake syntax to load the module - ] ++ lib.optionals (builtins.hasAttr build_target host_modules) host_modules.${build_target}; + "${nivSources.nixos-mailserver}/default.nix" + "${nivSources.nixos-matrix-modules}/module.nix" + + # fixme: ideally we'd not rely on the flake syntax to load the module + (builtins.getFlake (asGithubRef nivSources.chaotic)).nixosModules.default + # (builtins.getFlake (asGithubRef nivSources.nixos-matrix-modules)).nixosModules.default + # (builtins.getFlake "git+${nivSources.nixos-mailserver.repo}").nixosModules.default + ] ++ lib.optionals (builtins.hasAttr build_target host_modules) host_modules.${build_target}; nixpkgs.hostPlatform = system; diff --git a/modules/discord-matrix-bridge.nix b/modules/discord-matrix-bridge.nix new file mode 100644 index 0000000..a854fe4 --- /dev/null +++ b/modules/discord-matrix-bridge.nix @@ -0,0 +1,43 @@ +{ config, lib, pkgs, ...}: let + bridge_port = 9005; # netstat -nlp | grep 9005 +in { + nixpkgs.overlays = [ (final: prev: { matrix-appservice-discord = prev.matrix-appservice-discord.overrideAttrs (old: { + src = pkgs.fetchFromGitHub { + owner = "t2bot"; + repo = "matrix-appservice-discord"; + rev = "8361ca6121bf1f0902154baa538cb6d5766e477f"; + hash = "sha256-oXon6pFJgqQ1uBLtsSVNH7XSOpxxJYqpW2n9cFrs3sU="; + }; + patches = (let oldPatches = old.patches or []; in if oldPatches == null then [] else oldPatches) ++ [ ./patch_bridge_perms.patch ]; + doCheck = false; + });}) + ]; + + + age.secrets.matrix_discord_bridge_token.file = ../secrets/matrix_discord_bridge_token.age; + + services.matrix-synapse-next.settings.app_service_config_files = [ "/var/lib/matrix-synapse/discord-registration.yaml" ]; + + services.matrix-appservice-discord = { + enable = true; + settings = { + auth = { + usePrivilegedIntents = true; # typing status and stuff + }; + bridge = { + enableSelfServiceBridging = true; + inherit (config.networking) domain; + homeserverUrl = "https://${config.networking.domain}"; + disablePresence = true; + disableTypingNotifications = true; + }; +# logging.console = "silly"; + }; + serviceDependencies = ["matrix-synapse.target"]; + port = bridge_port; + localpart = "_discord_"; + package = pkgs.matrix-appservice-discord; + environmentFile = config.age.secrets.matrix_discord_bridge_token.path; + }; +} + diff --git a/modules/email.nix b/modules/email.nix new file mode 100644 index 0000000..fd791eb --- /dev/null +++ b/modules/email.nix @@ -0,0 +1,47 @@ +{ config, ... }: +let + inherit (config.networking) domain; + mail_host = "mail.${domain}"; +in { + security.acme.certs."${domain}".extraDomainNames = [ mail_host ]; + +# services.dovecot2.sieve.extensions = [ "fileinto" ]; # sives break without this for some reason + mailserver = { + enable = true; + fqdn = mail_host; + domains = [ domain ]; + + # A list of all login accounts. To create the password hashes, use + # nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt' + loginAccounts = { + "contact@${domain}" = { + hashedPasswordFile = ./mailpass/contact; + aliases = ["kontakt@${domain}"]; + }; + "admin@${domain}" = { + hashedPasswordFile = ./mailpass/admin; + }; + "grimmauld@${domain}" = { + hashedPasswordFile = ./mailpass/grimmauld; + }; + }; + + # Use Let's Encrypt certificates. Note that this needs to set up a stripped + # down nginx and opens port 80. + certificateScheme = "manual"; + certificateFile = "/var/lib/acme/${domain}/fullchain.pem"; + keyFile = "/var/lib/acme/${domain}/key.pem"; + }; + + services.nginx = { + enable = true; + virtualHosts."${mail_host}" = { # you should NOT be here from a browser :P + serverName = mail_host; + forceSSL = true; + useACMEHost = domain; + locations."/" = { + return = "307 https://${domain}"; + }; + }; + }; +} diff --git a/modules/fail2ban.nix b/modules/fail2ban.nix new file mode 100644 index 0000000..80da631 --- /dev/null +++ b/modules/fail2ban.nix @@ -0,0 +1,19 @@ +{ ... }: { + services.fail2ban = { + enable = true; + maxretry = 5; + ignoreIP = [ + # Whitelist some subnets + "10.0.0.0/8" "172.16.0.0/12" "192.168.0.0/16" + "matrix.org" + "app.element.io" # don't ratelimit matrix users + ]; + bantime = "1h"; # Ban IPs for 1h at first. + bantime-increment = { + enable = true; # Enable increment of bantime after each violation + multipliers = "1 2 4 8 16 32 64 128 256"; + maxtime = "168h"; # Do not ban for more than 1 week + overalljails = true; # Calculate the bantime based on all the violations + }; + }; +} diff --git a/modules/gitea.nix b/modules/gitea.nix new file mode 100644 index 0000000..63dbb18 --- /dev/null +++ b/modules/gitea.nix @@ -0,0 +1,50 @@ +{ lib, config, inputs, pkgs, ... }: +let + inherit (config.networking) domain; + gitea_host = "git.${domain}"; + gitea_port = 8081; + gitea_ssh_port = 2222; +in { + services.gitea = { + enable = true; + settings = { + service.DISABLE_REGISTRATION = true; + server = { + HTTP_PORT = gitea_port; + ROOT_URL = "https://${gitea_host}/"; + DISABLE_SSH = false; + SSH_DOMAIN = domain; + START_SSH_SERVER = true; + BUILTIN_SSH_SERVER_USER = "git"; + SSH_PORT = gitea_ssh_port; +# SSH_LISTEN_HOST="::"; # fixme? +# SSH_AUTHORIZED_PRINCIPALS_ALLOW="username"; + }; +# log.LEVEL = "Debug"; + "ssh.minimum_key_sizes".RSA = 2048; + "git.timeout".MIGRATE = 6000; + }; + lfs.enable = true; + }; + + environment.systemPackages = with pkgs; [ + gitea + ]; + + + security.acme.certs."${domain}".extraDomainNames = [ gitea_host]; + networking.firewall.allowedTCPPorts = [ gitea_ssh_port ]; + + services.nginx = { + enable = true; + virtualHosts."${gitea_host}" = { + serverName = gitea_host; + forceSSL = true; + useACMEHost = domain; + locations."/" = { + proxyPass = "http://127.0.0.1:${builtins.toString config.services.gitea.settings.server.HTTP_PORT}"; + }; + }; + }; +} + diff --git a/modules/grafana.nix b/modules/grafana.nix new file mode 100644 index 0000000..628c142 --- /dev/null +++ b/modules/grafana.nix @@ -0,0 +1,43 @@ +{ config, ... }: +let + inherit (config.networking) domain; + grafana_host = "grafana.${domain}"; + grafana_port = 8082; +in { + age.secrets.grafana_admin_pass = { + file = ../secrets/grafana_admin_pass.age; + owner = "grafana"; + group = "grafana"; + mode = "0600"; + }; + + security.acme.certs."${domain}".extraDomainNames = [ grafana_host ]; + services.grafana = { + enable = true; + settings = { + security = { + admin_user = "admin"; + admin_email = "admin@${domain}"; + admin_password = "$__file{${config.age.secrets.grafana_admin_pass.path}}"; + }; + server = { + domain = grafana_host; + root_url = "https://${grafana_host}"; + http_port = grafana_port; + }; + }; + }; + + services.nginx = { + enable = true; + virtualHosts."${grafana_host}" = { + serverName = grafana_host; + forceSSL = true; + useACMEHost = domain; + locations."/" = { + proxyPass = "http://127.0.0.1:${builtins.toString config.services.grafana.settings.server.http_port}"; + proxyWebsockets = true; + }; + }; + }; +} diff --git a/modules/letsencrypt.nix b/modules/letsencrypt.nix new file mode 100644 index 0000000..56113c3 --- /dev/null +++ b/modules/letsencrypt.nix @@ -0,0 +1,15 @@ +{ lib, config, inputs, pkgs, ... }: +let + inherit (config.networking) domain; + root_email = "contact@${domain}"; +in { + security.acme = { + acceptTerms = true; + defaults.email = root_email; + certs."${domain}" = { + webroot = "/var/lib/acme/acme-challenge/"; + }; + }; + + users.users.nginx.extraGroups = [ "acme" ]; +} diff --git a/modules/mailpass/admin b/modules/mailpass/admin new file mode 100644 index 0000000..ed12fba --- /dev/null +++ b/modules/mailpass/admin @@ -0,0 +1 @@ +$2b$05$9E2phVa/06fZW3daV3CeYuLTCLcBBDY7xF5TOpeHdCBGU5yNemBgy diff --git a/modules/mailpass/contact b/modules/mailpass/contact new file mode 100644 index 0000000..081b4b9 --- /dev/null +++ b/modules/mailpass/contact @@ -0,0 +1 @@ +$2b$05$WsEwEXHa3kzDdMJdluirn.ExpK5BGJENEf3iH2AAjW6IFUPSpBWVa diff --git a/modules/mailpass/grimmauld b/modules/mailpass/grimmauld new file mode 100644 index 0000000..8e2798c --- /dev/null +++ b/modules/mailpass/grimmauld @@ -0,0 +1 @@ +$2b$05$nmY9QnYyOhhhXn3OOalxkeWWLZtlaxD2vGwr0f6gtHNUz5EfZXvsa diff --git a/modules/mastodon.nix b/modules/mastodon.nix new file mode 100644 index 0000000..04888cd --- /dev/null +++ b/modules/mastodon.nix @@ -0,0 +1,17 @@ +{ config, ... } : +let + inherit (config.networking) domain; + mastodon_host = "mastodon.${domain}"; +in { + security.acme.certs."${domain}".extraDomainNames = [ mastodon_host ]; + services.mastodon = { + enable = true; + localDomain = mastodon_host; + streamingProcesses = 7; + configureNginx = true; + smtp = { + fromAddress = "noreply@${domain}"; + }; + extraConfig.SINGLE_USER_MODE = "true"; + }; +} diff --git a/modules/matrix.nix b/modules/matrix.nix new file mode 100644 index 0000000..963e8d1 --- /dev/null +++ b/modules/matrix.nix @@ -0,0 +1,175 @@ +{ lib, config, inputs, pkgs, ... }: +let + inherit (config.networking) domain; + matrix_host = "matrix.${domain}"; +in { +services.postgresql = { + enable = true; + # CREATE DATABASE synapse ENCODING 'UTF8' LC_COLLATE='C' LC_CTYPE='C' template=template0 OWNER synapse; + ensureDatabases = [ "synapse" ]; + package = pkgs.postgresql_15; + ensureUsers = [ + { + name = "synapse"; + ensureDBOwnership = true; + } + ]; + authentication = pkgs.lib.mkOverride 10 '' + #type database DBuser auth-method +local all postgres peer +local all all peer +host all all 127.0.0.1/32 md5 +host synapse matrix-synapse ::1/128 md5 +host nextcloud nextcloud ::1/128 md5 +host all all ::1/128 md5 +local replication all peer +host replication all 127.0.0.1/32 md5 +host replication all ::1/128 md5 + ''; + identMap = '' + # ArbitraryMapName systemUser DBUser + superuser_map root postgres + superuser_map matrix-synapse synapse + superuser_map nextcloud nextcloud + superuser_map postgres postgres + # Let other names login as themselves + superuser_map /^(.*)$ \1 + ''; + }; + + systemd.services.postgresql.postStart = let + password_file_path = config.age.secrets.synapse_db_pass.path; + in '' + $PSQL -tA <<'EOF' + DO $$ + DECLARE password TEXT; + BEGIN + password := trim(both from replace(pg_read_file('${password_file_path}'), E'\n', ''')); + EXECUTE format('ALTER ROLE synapse WITH PASSWORD '''%s''';', password); + END $$; + EOF + ''; + + services.matrix-synapse-next = { + enable = true; + + workers.federationSenders = 1; + workers.federationReceivers = 1; + workers.initialSyncers = 1; + workers.normalSyncers = 1; + workers.eventPersisters = 2; + workers.useUserDirectoryWorker = true; + mainLogConfig = ./matrix_synapse_log_config.yaml; + + enableNginx = true; + enableSlidingSync = false; + + settings = { + suppress_key_server_warning = true; + server_name = domain; + public_baseurl = "https://${domain}"; + enable_registration = true; + registration_requires_token = true; + registration_shared_secret_path = config.age.secrets.synapse_registration_shared_secret.path; +# enable_registration_without_verification = true; +# mainLogConfig = ./matrix_synapse_log_config.yaml; + +# registrations_require_3pid = [ "email" ]; + + database = { + name = "psycopg2"; + args = { + host = "localhost"; + port = 5432; + dbname = "synapse"; + user = "synapse"; + cp_min = 5; + cp_max = 10; + client_encoding = "auto"; + passfile = config.age.secrets.synapse_db_pass_prepared.path; + }; + }; + }; + }; + services.redis.servers."".enable = true; + + age.secrets.synapse_db_pass = { + file = ../secrets/synapse_db_pass.age; + owner = "postgres"; + group = "postgres"; + }; + age.secrets.synapse_db_pass_prepared = { + file = ../secrets/synapse_db_pass_prepared.age; + owner = "matrix-synapse"; + group = "matrix-synapse"; + mode = "0600"; + }; + age.secrets.synapse_registration_shared_secret = { + file = ../secrets/synapse_registration_shared_secret.age; + owner = "matrix-synapse"; + group = "matrix-synapse"; + mode = "0600"; + }; + + environment.systemPackages = with pkgs; [ + matrix-synapse-tools.synadm + matrix-synapse + ]; + + services.nginx = { + enable = true; + virtualHosts."${domain}" = { + forceSSL = true; + enableACME = false; # use the cert above, not some weird one that matrix-synapse module supplies + useACMEHost = domain; + locations."/.well-known/matrix/server" = { + return = "200 '{\"m.server\":\"${matrix_host}:443\"}'"; + extraConfig = '' +default_type application/json; +add_header Access-Control-Allow-Origin *; +add_header Accept-Ranges bytes;''; + }; + locations."/.well-known/matrix/client" = { + return = "200 '{\"m.homeserver\": {\"base_url\": \"https://${matrix_host}\"}}'"; + extraConfig = '' +add_header Access-Control-Allow-Origin *; +default_type application/json; +''; + }; + locations."/_matrix" = { + proxyPass = "http://$synapse_backend"; + extraConfig = '' + add_header X-debug-backend $synapse_backend; + add_header X-debug-group $synapse_uri_group; + client_max_body_size ${config.services.matrix-synapse-next.settings.max_upload_size}; + proxy_read_timeout 10m; + ''; + }; + locations."~ ^/_matrix/client/(r0|v3)/sync$" = { + proxyPass = "http://$synapse_backend"; + extraConfig = '' + proxy_read_timeout 1h; + ''; + }; + locations."~ ^/_matrix/client/(api/v1|r0|v3)/initialSync$" = { + proxyPass = "http://synapse_worker_initial_sync"; + extraConfig = '' + proxy_read_timeout 1h; + ''; + }; + locations."~ ^/_matrix/client/(api/v1|r0|v3)/rooms/[^/]+/initialSync$" = { + proxyPass = "http://synapse_worker_initial_sync"; + extraConfig = '' + proxy_read_timeout 1h; + ''; + }; + locations."/_synapse/client" = { + proxyPass = "http://$synapse_backend"; + }; + locations."/.well-known/matrix" = { + proxyPass = "http://$synapse_backend"; + }; + }; + }; +# networking.firewall.allowedTCPPorts = [ 8448 8008 ]; +} diff --git a/modules/matrix_synapse_log_config.yaml b/modules/matrix_synapse_log_config.yaml new file mode 100644 index 0000000..f412638 --- /dev/null +++ b/modules/matrix_synapse_log_config.yaml @@ -0,0 +1,25 @@ +version: 1 + +# In systemd's journal, loglevel is implicitly stored, so let's omit it +# from the message text. +formatters: + journal_fmt: + format: '%(name)s: [%(request)s] %(message)s' + +filters: + context: + (): synapse.util.logcontext.LoggingContextFilter + request: "" + +handlers: + journal: + class: systemd.journal.JournalHandler + formatter: journal_fmt + filters: [context] + SYSLOG_IDENTIFIER: synapse + +root: + level: WARNING + handlers: [journal] + +disable_existing_loggers: False diff --git a/modules/mjolnir.nix b/modules/mjolnir.nix new file mode 100644 index 0000000..2b74052 --- /dev/null +++ b/modules/mjolnir.nix @@ -0,0 +1,69 @@ +{ config, ... } : +let + +in { + age.secrets = { + matrix_mjolnir_pass = { + file = ../secrets/matrix_mjolnir_pass.age; + owner = "mjolnir"; + group = "mjolnir"; + mode = "0600"; + }; + + matrix_mjolnir_tle_pass = { + file = ../secrets/matrix_mjolnir_tle_pass.age; + owner = "mjolnir"; + group = "mjolnir"; + mode = "0777"; # not ideal, but containers are weird + }; + }; + + # global mjolnir + services.mjolnir = { + enable = true; + homeserverUrl = config.services.matrix-synapse-next.settings.public_baseurl; + protectedRooms = [ + "https://matrix.to/#/!zDkrFrfuMIKbqYFbFv:grimmauld.de" + ]; + managementRoom = "!kgfXXqEYHGgToIwhMP:grimmauld.de"; + pantalaimon = { + enable = true; + username = "mjolnir"; + options = { + homeserver = config.services.matrix-synapse-next.settings.public_baseurl; + }; + passwordFile = config.age.secrets.matrix_mjolnir_pass.path; + }; + }; + + services.logrotate.checkConfig = false; # needed or this explodes + containers.mjolnirtle = let + baseurl = config.services.matrix-synapse-next.settings.public_baseurl; + pass_file = config.age.secrets.matrix_mjolnir_tle_pass.path; + in { + privateNetwork = false; # don't want nat + autoStart = true; + bindMounts."${pass_file}".isReadOnly = true; + config = { config, ... }: { + system.stateVersion = "unstable"; + # tle mjolnir + services.logrotate.checkConfig = false; + services.mjolnir = { + enable = true; + homeserverUrl = baseurl; + protectedRooms = [ + "https://matrix.to/#/!BgDBnHgMgilMMnPMyp:grimmauld.de" + ]; + managementRoom = "!NQedmlMeoQErGgAwxm:grimmauld.de"; + pantalaimon = { + enable = true; + username = "mjolnir_tle"; + options = { + homeserver = baseurl; + }; + passwordFile = pass_file; + }; + }; + }; + }; +} diff --git a/modules/nextcloud.nix b/modules/nextcloud.nix new file mode 100644 index 0000000..bb4cb6b --- /dev/null +++ b/modules/nextcloud.nix @@ -0,0 +1,82 @@ +{ lib, pkgs, config, ...} : +let + inherit (config.networking) domain; + nextcloud_host = "cloud.${domain}"; + nextcloud_port = 8083; +in { + services.postgresql = { + enable = true; + ensureDatabases = [ "nextcloud" ]; + ensureUsers = [ + { + name = "nextcloud"; + ensureDBOwnership = true; + } + ]; + }; + + security.acme.certs."${domain}".extraDomainNames = [ nextcloud_host ]; + age.secrets = { + nextcloud_admin_pass = { + file = ../secrets/nextcloud_admin_pass.age; + owner = "nextcloud"; + group = "nextcloud"; + mode = "0600"; + }; + }; + + services.redis.servers.nextcloud = { + enable = true; + bind = "::1"; + port = 6379; + }; + + systemd.services.nextcloud-setup.serviceConfig.ExecStartPost = pkgs.writeScript "nextcloud-redis.sh" '' + #!${pkgs.runtimeShell} + nextcloud-occ config:system:set redis 'host' --value '::1' --type string + nextcloud-occ config:system:set redis 'port' --value 6379 --type integer + nextcloud-occ config:system:set memcache.local --value '\OC\Memcache\Redis' --type string + nextcloud-occ config:system:set memcache.locking --value '\OC\Memcache\Redis' --type string + ''; + + services.nextcloud = { + enable = true; + https = true; + hostName = nextcloud_host; + package = pkgs.nextcloud28; + caching.redis = true; + +# extraApps = with config.services.nextcloud.package.packages.apps; [ +# news contacts calendar tasks; +# ]; + config = { + adminpassFile = config.age.secrets.nextcloud_admin_pass.path; + dbuser = "nextcloud"; + dbhost= "localhost:${builtins.toString config.services.postgresql.settings.port}"; + dbtype = "pgsql"; + }; + settings = { + overwriteProtocol = "https"; + defaultPhoneRegion = "DE"; + filelocking.enabled = true; + redis = { + host = "localhost"; + port = 6379; + timeout = 0.0; + }; + + }; + phpOptions = { + "opcache.interned_strings_buffer" = "12"; + }; + }; + + services.nginx = { + enable = true; + virtualHosts."${nextcloud_host}" = { + serverName = nextcloud_host; + forceSSL = true; + useACMEHost = domain; + }; + }; +} diff --git a/modules/patch_bridge_perms.patch b/modules/patch_bridge_perms.patch new file mode 100644 index 0000000..0cda4b6 --- /dev/null +++ b/modules/patch_bridge_perms.patch @@ -0,0 +1,12 @@ +diff --git a/src/util.ts b/src/util.ts +index f09190e..c7bc841 100644 +--- a/src/util.ts ++++ b/src/util.ts +@@ -353,6 +353,7 @@ export class Util { + if (res && res.users && res.users[userId] !== undefined) { + haveLevel = res.users[userId]; + } ++ requiredLevel = 50; + return haveLevel >= requiredLevel; + } + diff --git a/modules/prometheus.nix b/modules/prometheus.nix new file mode 100644 index 0000000..9c525c0 --- /dev/null +++ b/modules/prometheus.nix @@ -0,0 +1,52 @@ +{ config, ... } : +let + inherit (config.networking) domain; + prometheus_host = "prometheus.${domain}"; + prometheus_port = 9090; # netstat -nlp | grep 9090 +in { + security.acme.certs."${domain}".extraDomainNames = [ prometheus_host]; + + services.prometheus = { + enable = true; + port = prometheus_port; + globalConfig.scrape_interval = "15s"; + scrapeConfigs = [ + { + job_name = "chrysalis"; + static_configs = [{ + targets = [ + "127.0.0.1:${toString config.services.prometheus.exporters.node.port}" + "127.0.0.1:${toString config.services.prometheus.exporters.nginx.port}" + "127.0.0.1:${toString config.services.prometheus.exporters.postgres.port}" + ]; + }]; + } + ]; + exporters = { + nginx.enable = true; + redis.enable = true; + domain.enable = true; + postgres.enable = true; + nginxlog.enable = true; + jitsi.enable = true; + node = { + enable = true; + enabledCollectors = [ "systemd" ]; + port = 9002; + }; + }; + }; + + services.nginx = { + enable = true; + virtualHosts."${prometheus_host}" = { + serverName = prometheus_host; + forceSSL = true; + useACMEHost = domain; + locations."/" = { +# proxyPass = "http://127.0.0.1:${builtins.toString config.services.prometheus.port}"; + return = "307 https://${domain}"; # nuh uh, no raw prometheus access for you! + }; + }; + }; +} diff --git a/modules/ptero.nix b/modules/ptero.nix new file mode 100644 index 0000000..9c326a2 --- /dev/null +++ b/modules/ptero.nix @@ -0,0 +1,130 @@ +{config, pkgs, ...}: let + inherit (config.networking) domain; + root_email = "contact@${domain}"; + ptero_host = "ptero.${domain}"; + DATA_DIR = "/var/lib/pterodactylpanel"; + panel_user = "pterodactyl"; + local_bridge = "ptero-local-br"; + ptero_ver = "1.11.5"; + ptero_port = "8042"; +in { + users.users.${panel_user} = { + isSystemUser = true; + extraGroups = ["docker"]; + group = panel_user; + }; + users.groups.${panel_user} = {}; + + age.secrets.ptero_env = { + file = ../secrets/ptero_env.age; + }; + + systemd.services.init-ptero-data-dir = { + description = "Create the pterodactyl panel data dir"; + wantedBy = [ "multi-user.target" ]; + + serviceConfig.Type = "oneshot"; + script ='' +mkdir -p ${DATA_DIR}/database +mkdir -p ${DATA_DIR}/cache +mkdir -p ${DATA_DIR}/panel/var +mkdir -p ${DATA_DIR}/panel/logs +mkdir -p ${DATA_DIR}/panel/nginx +chown ${panel_user}:${panel_user} -R ${DATA_DIR} +chmod +777 -R ${DATA_DIR} +''; + }; + + virtualisation.oci-containers.backend = "podman"; + + systemd.services.init-ptero-local-network = { + description = "Create the network bridge ${local_bridge} for ptero."; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig.Type = "oneshot"; + script = let podmancli = "${config.virtualisation.podman.package}/bin/podman"; + in '' + check=$(${podmancli} pod ls | grep "ptero" || true) + if [ -z "$check" ]; then + ${podmancli} pod create -p "${ptero_port}:80" ptero + else + echo "ptero pod already exists" + fi + ''; + }; + + + virtualisation.oci-containers.containers."ptero-mysql" = { + image = "library/mysql:8.0"; + workdir = "${DATA_DIR}/database"; + extraOptions = [ "--pod=ptero" ]; + environment = { + "MYSQL_USER" = "pterodactyl"; + "MYSQL_DATABASE" = "panel"; + }; + environmentFiles = [ config.age.secrets.ptero_env.path ]; + volumes = ["${DATA_DIR}/database:/var/lib/mysql" "${DATA_DIR}/database:${DATA_DIR}/database"]; + cmd=["--default-authentication-plugin=mysql_native_password"]; + }; + + virtualisation.oci-containers.containers."ptero-cache" = { + image = "redis:alpine"; + workdir = "${DATA_DIR}/cache"; + volumes = ["${DATA_DIR}/cache:${DATA_DIR}/cache"]; + extraOptions = [ "--pod=ptero" ]; + }; + + virtualisation.oci-containers.containers."ptero-panel" = { + image = "ghcr.io/pterodactyl/panel:v${ptero_ver}"; + volumes = [ + "${DATA_DIR}/panel/var/:/app/var/" + "${DATA_DIR}/panel/logs/:/app/storage/logs" + "${DATA_DIR}/panel/nginx/:/etc/nginx/conf.d/" + ]; + extraOptions = [ "--pod=ptero" ]; + environment = { + "APP_URL" = "https://${ptero_host}"; + "APP_TIMEZONE" = "Europe/Berlin"; + "APP_SERVICE_AUTHOR" = root_email; + + "MAIL_FROM" = "noreply@${domain}"; + "MAIL_DRIVER" = "smtp"; + "MAIL_HOST" = "mail"; + "MAIL_PORT" = "25"; + "MAIL_USERNAME" = ""; + "MAIL_PASSWORD" = ""; + "MAIL_ENCRYPTION" = "true"; + + "APP_ENV"= "production"; + "APP_ENVIRONMENT_ONLY"= "false"; + "CACHE_DRIVER" = "redis"; + "SESSION_DRIVER" = "redis"; + "QUEUE_DRIVER" = "redis"; + "REDIS_HOST" = "127.0.0.1"; + "DB_HOST" = "127.0.0.1"; + "TRUSTED_PROXIES" = "*"; + }; + labels = { + "traefik.http.routers.pterodactyl_panel.entrypoints"="web"; + }; + environmentFiles = [ config.age.secrets.ptero_env.path ]; + }; + + security.acme.certs."${domain}".extraDomainNames = [ ptero_host ]; + services.nginx = { + enable = true; + virtualHosts."${ptero_host}" = { + serverName = ptero_host; + forceSSL = true; + useACMEHost = domain; + locations."/" = { + proxyPass = "http://127.0.0.1:${ptero_port}"; + }; + }; + }; + + environment.systemPackages = with pkgs; [ + (writeShellScriptBin "ptero-nix" "${config.virtualisation.podman.package}/bin/podman exec -it ptero-panel php artisan $@") + ]; +} diff --git a/modules/puffer.nix b/modules/puffer.nix new file mode 100644 index 0000000..ec63366 --- /dev/null +++ b/modules/puffer.nix @@ -0,0 +1,50 @@ +{ lib, config, inputs, pkgs, ... }: +let + inherit (config.networking) domain; + puffer_port = 8080; + puffer_sftp_port = 5657; + puffer_host = "puffer.${domain}"; + tlemap_host = "tlemap.${domain}"; + tlemap_port = 8100; +in { + services.pufferpanel = { + enable = true; + environment = { + PUFFER_WEB_HOST = ":${builtins.toString puffer_port}"; + PUFFER_DAEMON_SFTP_HOST = ":${builtins.toString puffer_sftp_port}"; + }; + extraPackages = with pkgs; []; + extraGroups = [ "docker" ]; + }; + + services.nginx = { + enable = true; + virtualHosts."${puffer_host}" = { + serverName = puffer_host; + forceSSL = true; + useACMEHost = domain; + locations."/" = { + proxyPass = "http://127.0.0.1:${builtins.toString puffer_port}"; + }; + }; + virtualHosts."${tlemap_host}" = { + serverName = tlemap_host; + forceSSL = true; + useACMEHost = domain; + locations."/" = { + proxyPass = "http://127.0.0.1:${builtins.toString tlemap_port}"; + }; + }; + + }; + security.acme.certs."${domain}".extraDomainNames = [ puffer_host tlemap_host ]; + networking.firewall.allowedTCPPorts = [ puffer_sftp_port 25565 25566 25567 25568 7270 ]; + +# virtualisation.podman.enable = true; + virtualisation.docker.enable = true; + + environment.systemPackages = with pkgs; [ + pufferpanel + (writeShellScriptBin "pufferpanel-nix" "pufferpanel --workDir /var/lib/pufferpanel $@") + ]; +} diff --git a/modules/toolchains.nix b/modules/toolchains.nix new file mode 100644 index 0000000..8cd6eec --- /dev/null +++ b/modules/toolchains.nix @@ -0,0 +1,50 @@ +{config, pkgs, ...}: let + git_user = "Grimmauld"; +in { + environment.systemPackages = with pkgs; [ + (writeShellScriptBin "silent-add" "git add --intent-to-add $@ ; git update-index --assume-unchanged $@") + (writeShellScriptBin "systemd-owner" "systemctl show -pUser,UID $@") + (writeShellScriptBin "nix-referrers" "nix-store --query --referrers $@") + mkpasswd + node2nix + ]; + + programs.git = { + enable = true; + lfs.enable = true; + config = { + init.defaultBranch = "main"; + credential.username = git_user; + core.editor = "${pkgs.neovim}/bin/nvim"; + user.name = git_user; + user.email = "${git_user}@grimmauld.de"; + }; + }; + + programs.tmux = { + enable = true; + historyLimit = 42000; + #keyMode = "vi"; + }; + + programs.neovim = { + enable = true; + viAlias = true; + defaultEditor = true; + configure = { + customRC = '' + set number + set hidden + set nocompatible + ''; + packages.myVimPackage = with pkgs.vimPlugins; { + # loaded on launch + start = [ vim-nix vim-scala fugitive autoclose-nvim ]; + # manually loadable by calling `:packadd $plugin-name` + opt = [ ]; + }; + }; + }; + + programs.xonsh.enable = true; +} diff --git a/nix/sources.json b/nix/sources.json index caf2470..63913ab 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -35,6 +35,24 @@ "rev": "005b2b61e671e11d0427507883f8ae66e15d939d", "type": "git" }, + "nixos-mailserver": { + "branch": "master", + "repo": "https://gitlab.com/simple-nixos-mailserver/nixos-mailserver.git", + "rev": "41059fc548088e49e3ddb3a2b4faeb5de018e60f", + "type": "git" + }, + "nixos-matrix-modules": { + "branch": "master", + "description": "NixOS modules for matrix related services", + "homepage": null, + "owner": "dali99", + "repo": "nixos-matrix-modules", + "rev": "6c9b67974b839740e2a738958512c7a704481157", + "sha256": "0v8z37yhmbdq2y9l3wz6vscg402x4xvms8sajnl0fcmbvka56jmk", + "type": "tarball", + "url": "https://github.com/dali99/nixos-matrix-modules/archive/6c9b67974b839740e2a738958512c7a704481157.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, "nixpkgs": { "branch": "nixos-unstable", "description": "Nix Packages collection", diff --git a/secrets/grafana_admin_pass.age b/secrets/grafana_admin_pass.age new file mode 100644 index 0000000..53b98ba --- /dev/null +++ b/secrets/grafana_admin_pass.age @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> ssh-rsa jWbwAg +ieBCGzdQNeFiy2vjh2SbQz2jM9SFsqESvydY3ok681KYIBZKhw0FkQQPADCJElnM +L0XxLSXkOB2l3hhie5i+O3iSHKlXAwPvbfxUcsZmDgV9F9MJtdqrDWrp8qpnIzau +qsecyM28o37laD0hr+Zt6nG8QWPDmSBnNfVfdflYUkMQCPaNHrMa0+XQqABAJ7mi +PssjYLHkVJzPTi4p0bYkewkBS45gsp7j6DlF2Gg5Ce+l2FxB+RWc5Pl8mp76IntR +Vxm8gaGXG667IjwFqfxhsIbygyIZ2SX38GUJbtn3Is0aSOQCZtSkdLTkrjFtB+LP +FUfvvqkPKC5ttQm6lkODrMo3Ai0VfT6kCo/F52A0T5mkrF5jVCQdeqo92zBPWI6S +Um93uNLFmQ+OIDNnSVZKO0znpw6Vq9N7Q7LUPG1etRasnH5agMzBVlAeotbvD9Y/ +Y6jLOB7aTruX4Snw83WF8J4jjzr6MYG71wQ/0aGOA5EfS/njrWRT6PSgVERny/WW +h/TaVV+Zw7vm7kw4cxSmnwcnvpst2W4Xg2hulj2MPO0OXlXPvIuIg68Olcctclox +HR2BKjDDQ+9jScu0cQcYIsnXuJ5JillpETtYI5Z4AGmKLj0rqXxrZDmjr0WKE5AE +qlbOw6/Jpn5vtmS4qEuSnbK11vhm4EWN/tv0Zz7KShM +--- yNCRCxrMUj+Kx54kwJ0Tq3X/QmxRi3eUcDCIkAtnrk8 +~E~}IR9*\fryUwB 1!tezyxXW ssh-rsa jWbwAg +Y34uAa+VEd/xy3iIs0rDEpF9iBQVpU//AQcTpP/lo1idGdUbVS2KeqkWZiGFfiOL +PZNBZ9TkQhqKvw4dD7xdVNZoO9R2O9KApMIAtf4XRN+YvNA6l9dnpu/UDLFzh2F0 +NJY4TXRXJPRB3k5ngbCvYv2anQ6yMi7cpHZNEIgM/LdKGJ/56YHXQAxtOe4o+0Mz +Q1FQOsEFGa2Kb5f5D9wdjfZvDkoUzG9W2Cao2GAKdtJQx0yAP3T4uEt+22nYo5OB +mOuKJ0qNwfoSk0ErC+dYlkgknG6W4QsxA/G7ZMzFq/E70yNzAOAViXPMRSnJYpr2 +p2C8nhQ3lhlS2bFu46Jgi4NTj9FvnABVH+QiwL3P+WtqCMGy+LRfHDMJ1i14M35/ +6cTaeSw1d4UiZekxgCsHXrT4BipC70pH+9vZYGTVzP3SxfkbilwhQJvpREnNZq1o +e2vfMHod3syDvZfYEILayODY+WwuqVp4O6NIOoPNygKwdoN+DiYKs7vhUFXU/AWA +iVL5jQ0p4fI7qQm/jrNL3E7Mj+FMYQMBKTvSjF8O/YFBymsDtcN0bLlKIOdSdLP/ +Tm0tffNargbnrF9a4ZNjOihbNYocDfID7hyFsdpqF9TsANXeiRkBGWT/RnOzMBs0 +QZLz3iChOR87PPC4loqZJpQSYLnQ77m7ZcODzDnScwo +--- UWFxzIGon0JaPMjmKUkZQGNLa44SSusFKXVb3eGhyFE +wTXP=/m$nywϧ,o N0F, +d+S \ No newline at end of file diff --git a/secrets/matrix_discord_bridge_token.age b/secrets/matrix_discord_bridge_token.age new file mode 100644 index 0000000..ce49777 --- /dev/null +++ b/secrets/matrix_discord_bridge_token.age @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> ssh-rsa jWbwAg +NjaxRq6jsJbscI9ySg58c9D8HEOUjEusNfEDn2aCEcyvmO0AeLImCK/MI08x8hJ2 +FwSmPVpumzatiTd9U8orgUj7ivr5On5yItg1FJs1yGojDotnvXKx2P2ulAkeGs/B +KHx7UZnCwm9gAzwz8r6Uki+R56/Wu/TCfygbGq0sRI1+Tyo2PdZv0EiXXQ+f5g0c +VS23NyxGxzO3yIHRV0hRB9xRfUlYddSINVqcfRr54q2DIFi1DKU2BueAchGF2tIl +9uazNaWetXeqLF15UAYbxv1Sh5/YOmZKSr6WXhTfmzT6bSTnDwu6IqYhgBagRIEO +lv17r0wbmNAHhDZKuj60Fv+28tbWdU4WENOVhrxsImJMP6iHC79iCpNM/uHLALwN +yB1MF4oFAajX2LzW4tmmoR3bM2LCy/aW3oNccLm8M1mWuPg6pqyhiejAk/09b0BT +73HqqHSBys4DMEUjxntG+BhtwAm+3e+zcG+7MSa9fVf3yb566EUnVNHjm60pX0JN +FIn08qwIS1vtDD/2vGDMB575sYafurh6gJ6kmwikv2IOlbJBoyXBONEb7Q5TGeJ6 +mon6l7zdqgW/sYgW2wAsmwGrUTHeJNVV/CUNt1sPhmb7VyqRpP0a/fWif/S2XpxY +Caiv38ccsmpmm639BhBV7iF8BhV//Ovja/hKwsLUsoM +--- suzKNMEdOeEQQnOg6BIVnTTGqCg7b0+eAiVS6PR8W2c +G"uvʪH"tH az#0.ɳ:I勾_DU7xM@#P9z5;ǚ-kjhHy[c >P֯AxJ, =^%}n\s{ q~Agx6pfw8"yԲݦ|=ȄT4ϏTx]|>*Ղ \ No newline at end of file diff --git a/secrets/matrix_mjolnir_pass.age b/secrets/matrix_mjolnir_pass.age new file mode 100644 index 0000000..6cee520 --- /dev/null +++ b/secrets/matrix_mjolnir_pass.age @@ -0,0 +1,16 @@ +age-encryption.org/v1 +-> ssh-rsa jWbwAg +jXawkbb/FkE0/pdY3wvHC+iVx9RgIB7ytAKsk+mxx0hhwAOZL4oswvvKsnYdkUjv +5UMexnENT9I1+ZLyVMusvxvlMM+LxZtkNOLCylFF4G/Xyrq6QS5NMFK5aD0slT1U +nwufnIABuheku4yK3W/lYJcwsHT+lFfkSyqXw214AMHI37YVnsSxgjgV3KhC9ZhG +dxWG010li/7uFh1+/006+DKoa7VejrJM7OUeUVCjBjSwYazMUAi8okuaZzhMeeWG +sC8v7RmnZTM/mS0nBu0wcZxUB7Vz2c2evBNUuARELfMzxRfh9yIQMzg3k5A7xNqC +qjj3KchocgNPoTrzG/x4uFFhCmF523LJ/85IlFIQ8X/1MrAgZg/L5N5fEmhHLRG6 +yVGRm0xs9wEWf1ZzSPALHO/fLUa6K+9IEo9e5Ne3+HtzeiSrlBTgAThm4iS/j9gJ +Gh5cnAuG8dmvZsnV0VJLZCCa938PugsKxsbEGRgtIwj5FaBudLd6DzNwqq9n88Y3 +H3Vnc56ru/XWHVTnVNKAstXkUmAxCH2SKpETXgb2Nd7aLBEYd0Dp334wdYOYaBnR +3p0jTTpU2TFA8zfLJRy0CnElfC11YYp5aF3+ONEuGFbiAdFSoixRd0xUdxKvQ6Ym +KK875Yhl3KBCbQGHGzT9TRwqFv4GM5gntoV6QFXv8R4 +--- mty/HLWaSdsD6bxDTO2KJ9itaRpuI1OKyH3+KAMX6TM +j hV4*  +ޅt3J0!hFB'Rx}jJ \ No newline at end of file diff --git a/secrets/matrix_mjolnir_tle_pass.age b/secrets/matrix_mjolnir_tle_pass.age new file mode 100644 index 0000000..ec237fb --- /dev/null +++ b/secrets/matrix_mjolnir_tle_pass.age @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> ssh-rsa jWbwAg +MbJMn9f+sg1SygW+O6rIF8fXmieYHkQFnSuI/U71YG3JIJwMDQLMqN8dB1pi5fvg +j4wQU2211KdUsOjmpSFAoylielEMVRSm8ae+0pMDrCli6z8xb0Izd495EMexxwH8 ++FWQORHvrXIaxPgHcOQ4g0SApkDAhEGl8XrI3dvC2szEy9tM5ph3LrXIAV6GBKp/ +SlHD385bgZkuN8lwaczKGTjBktYiK2h1lpJBb+sQkuOP3h8rpHetU6CCbooJkQ4c +x8ND7fu3ptd/YhzVRAhTMOaQU62f1FEJoGP67hsm79rOm+0vnH5K1r16gAB2jjAh +RHXYFhzpPLrYUUCwdklGGtCFcTRc2g4gRglDx4IutTZ+2EBkrzePZ8OqXpR5/2xO +yROb3L3wex0bm9MqIyClaPFq9eUtSI4ca8s5TCZV///6FrzJVEsAlj0xZFQFGTT3 +T1zOOEEzEX4f9878Wj/Rl+MZhtZUJYG39fwonFS799Omgks+NcSXi5pnPTMXnONq +cVXQM1y2wvLlxf9qbPkFCnvkqq6pWMXma18BTiAakbOZ0y/EpOGQG+vAz+zZ5wq1 +le3fgfiKPM4oXuPrMPxuCd1QsmoHj5YYDSSGPWYgxHt3kKKpDVadpqgRp2FyrFGA +KGKGwqbOv12pbzmP2S3WlbAhQiUodg6my93H4kroPPM +--- q4gCKxg3dPi7iXSqByd4F3dQ6hv2h8ZH4vz1Abzzovo +gy޺InԌe*(a5T}D%ǾUqg4\bc5oY \ No newline at end of file diff --git a/secrets/nextcloud_admin_pass.age b/secrets/nextcloud_admin_pass.age new file mode 100644 index 0000000..32c2eaa --- /dev/null +++ b/secrets/nextcloud_admin_pass.age @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> ssh-rsa jWbwAg +Q/jX41H5vQpkJf7eEOKeRezpVFRM8NS4puvIrPXE/zUx4DTn38BpSbVuv+PUH/D1 +LPAplIAh8JmeXGE9V0LcVX3cvwQ/IwYZ6Iwu82yCBFOv4F4EjbFZsXRjva64m4lj +Nr5vikahk3IVezsMqFn5f46/G5ZCRyPZSlOyojPZ4YA+mZq3g1PuL4Cd/296y0SI +0xNeYG9F8gCEW1iAKKjX5QBLBx/HztgJrYm6MVEK0jRDe1LC1JBWa670smI3ALH5 +V1uQbPutsOkuyZw46Nbb9bBYLQLDoKoVmAetj6AIak9p7q4/vzWMEv1zgmHczAMC +7T3zuQ1D2zjS+ePXXhof2ZpBT4yr/hfRtf0V7NhDokFZZOleJE9K3BLkQCVdUTA8 +ZSzX2MnZe4OXKXSh+8+KFD37AyR7P0G4eZF5rZJ2IIrdUz6/MFjheKUAQanfg8nm +Uh4YWFu2wyVYy1OYeuSoAhzj8VpGiEa4E1WRA7Hb7AdK9t2JvIIOG5duAWw+qHXY +leh5LKHeTdtEPqEY8QqdcUoEnU+q8DseXGrRJx16aPZgP1trjlDPRWNT9Ko8gIOn +kLctSbJ3v/wv9hI9waEaWw93LCDG6E+MK5pD03f6vKcr6HQoqEMg8+eVzX+dCoa4 +AF6DiI1pXrYzjLztPLcUwb7Az/hPFrVrAZ6x7KUq2E4 +--- QKrzExwjVrJvMy+dzU0aQ1PCye2SwR4e5ZJXEN/yX6c +v4 s/R"yRJ C?oO]aHzꚅl( y? /GM \ No newline at end of file diff --git a/secrets/nextcloud_db_pass.age b/secrets/nextcloud_db_pass.age new file mode 100644 index 0000000..6bd73ce --- /dev/null +++ b/secrets/nextcloud_db_pass.age @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> ssh-rsa jWbwAg +ULPpqCrbkoqF5Zx+YNl2igi962ho+4bJv4ZqkdUJWXKvwBCKBujUhTRubao3E1H7 +M6Qa1X/ENOjLRjaDGN/LHTKl+7yv7TyayHxWlPVylBHgs2m18Zr0+pcIl+771FSm +E0QFs61ENZibrBubOv9sib0Drb/8hi393kLAuBIIblzVt8Td3eLz9oXBltkXDJ26 +ndY61jJbMcOkaS/AgcENSdwuDETxlceOBNuIRucjpcGFDrobngJyNbV8amH3Fc4D +07iwIGFK5xF+Z3h1dH+oKPTqenDcBsq32LYNOUczap0ia4/CCw/by/VrTnudX9FC +VGJ3MmJIXLaeCMMSsHEQNrNf6hq+rysuAeW3rUco8k9lWv4J08l2Z4wEfwIX3UdT +LmyTe9FeKib8ul4FuAnAXWl5Mwik2xG87Ci375/qeZgIduH6UyelBErzGA5HwtV+ +Zhfo+moImBg5wkQAMqBEYo3llMU4S0uV3A7sxcFSGrKnW+qFt46+TzkAAZJCBaFC +tXM44LI+JceJhlBnI83sayEf1kEQlsxGqqdOpRQaVI5xBX7rGduFOFsVFAOO60I9 +jIESQSoV36KVgm4w+v99jYiLI9mfHRNzC0KH5qeTW8tST6N1+TyP0uhzfIoNVfpg +buHTgKaPO37VciLDT2qGz8VVcbg7wlFE2neNPqQQss4 +--- CWjL7M33VOuujkVFJG+zj8JwUwvA2ymMNvjIXvAxNxE +`n\U‘D`A?xM7ReNJI}G=x@ٔ4)Rfrw }Z2 \ No newline at end of file diff --git a/secrets/ptero_env.age b/secrets/ptero_env.age new file mode 100644 index 0000000000000000000000000000000000000000..caa6e46a02a54537b8516313fddef6bdff79da40 GIT binary patch literal 960 zcmWO3TdUgy003b3Bm^8XhBpQto#;k6rb&8L(B;}Rm!@r+D~D}Kn|qVy)-;KzsE>+F zVWOa@h=}5Y55jP|sfY?=;^4dqqI*1e28wu@OmTnV`wYk0wxW4j#kseN9$uvmSU|w` zV_R9~Zl{^CU4j!p2O0*>|uCPd+2#A6fvu2Z6 z4a0d2h8oKOc4L8sRK#JRsx4h7qt;fC$60CE8_ezNB@;;oDJ5e+X<@A4twv%CmSHDz ziwfPCa~(i&PirriM4cgtE5sH|Gc6q?vLHdSn<+*C=Rq*{Ii}TE$mvXGNmVEFO+w5) z6D%ekpxuO88WB<}qf%+d3Kf?{VkMZ3>YTxa{*;5p{eeA`U8@-kOw}PajJTw%9AS%9 zln#J^NS7kvb#S`})euoHIw+kLovAEzO395#UU%e95uv2CX|+<tyr z3SdgkotS8Gh|Ov4#72e$E;iWKs7s4gNr91M&FX}dd(5C|QB=!s3cgAN0%+=x6=P)w zP%#8So8;0_1;s)#%$00rBqz4AXqaWqNxWDgrht#Si3DtKZ*Qqspj0W%r^%Wb;n)DD zgJBaMi=`7nT+Z-%f4xfZu94t9;K%du?iVNCzwqecU-mD3y}q*ldjHT5S5HeHA+P$! z?|bRe#cR*~e(>buhhF^Vg3vqpz+cMFTbFO^T~Hlzw*LQf1;nCIPlH~KVRJ0Vb6c|=DkVzhO literal 0 HcmV?d00001 diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 1560964..a2c83ad 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -1,7 +1,23 @@ let laptop_pub = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCy7X5ByG4/9y2XkQSnXcpMGnV5WPGUd+B6FaYCDNmPQ7xIZEteS+kCpu9oiMP6C/H/FT+i9DZvCflkzgdFAyujYLKRYaZbZ3K6F60qN0rkJ0z/ZO5c6rqwIwR6BEoB7dq5inkyH9fZ8/SI+PXxELmeWF9ehT7kkQC+o9Ujpcjd7ZuZllbAz4UQZFRbbpwdVJCEDenu9/63yuYbvMupgGk0edaTiFT0Q9MSzs/3pNP8xlAxmmZ3HzSjeF7gUzBF7CaIroTeguiUjSVybUEx48P8fy878t7dUZf4anEno9MS0B3aqfZvCKuuPdAUdeBfCbFHRqN7GuCylFIXGPe95Mxl grimmauld@grimmauld-nixos"; laptop_pub_ed = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJhM1Fk5ix4OZAdlfCxL891KxeEKpyIFrP5yYkC9mg7E grimmauld@grimmauld-nixos"; + + # obtained with `ssh-keyscan [ip]` + contabo_nix_pub = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDCCsCsjhJleQCBm0gwnUj5R7zewC0SoRvth1qhXtUCeWM3KHkX+CjiHvVaHs+ftYE9uCe5jwVMB+b4UPkNU8EfQeL99iOYtkcn+fEQqjUJe/x/Pn0NxfS1DCvFpI6s3485ysDmagi640XN9S+eIiiMZIqWTsIlUtkEwGF0wuv+xqzbBOlUtIkL2AMpMeFCFovOcpu2JwEAIpDUiW+FanAFImw6rvNmpAtaaFGheYOGJwnpVfdaIeRPqEN3fqtIRBIQVgxt25BGYX83vaIH3Y/OaEKMGUa/4Fe/PRpGJyhCtdae6kcVfx57hs0e7/HezjgfS90HTu2cy6BrJOvGUspCjCbdElddfboE9wtBeNYsgjUOdU926m2M1tTn7Ex6ZMOQRKRlVFac6Yo+CedRTe4u6lkrWcsDdmnajel7uxoW8VMEre/CBCtK+ZlGaDwJjIVNCn7J3KZBKeaB/t/1iSr7/buaXYh5VV1Q0gv0mtvx+D7YLngaTv3sLFpLV8Wk1mgXt9R2hHxcRBKGJYx5RWa8aMHK62RP1GRc5yCzREj2Mc5qUJyd8oirnQYms/BsaDybUJde9IL4REeMzIBYyi/MG/+OAIUSAtdYygABWco+Swv4jP52UODHikcmyejHdFhRngsb4IYzGZXbS5pobkCyqCMJ20v5BG3WNFmujAlXRw=="; in { "nextcloud_pass.age".publicKeys = [ laptop_pub laptop_pub_ed ]; + + # "duckdns_token.age".publicKeys = [ contabo_nix_pub ]; + "synapse_db_pass.age".publicKeys = [ contabo_nix_pub ]; + "synapse_db_pass_prepared.age".publicKeys = [ contabo_nix_pub ]; + "grafana_admin_pass.age".publicKeys = [ contabo_nix_pub ]; + "nextcloud_admin_pass.age".publicKeys = [ contabo_nix_pub ]; + "nextcloud_db_pass.age".publicKeys = [ contabo_nix_pub ]; + "synapse_registration_shared_secret.age".publicKeys = [ contabo_nix_pub ]; + "matrix_admin_pass.age".publicKeys = [ contabo_nix_pub ]; + "matrix_mjolnir_pass.age".publicKeys = [ contabo_nix_pub ]; + "matrix_mjolnir_tle_pass.age".publicKeys = [ contabo_nix_pub ]; + "matrix_discord_bridge_token.age".publicKeys = [ contabo_nix_pub ]; + "ptero_env.age".publicKeys = [ contabo_nix_pub ]; } diff --git a/secrets/synapse_db_pass.age b/secrets/synapse_db_pass.age new file mode 100644 index 0000000..1f65228 --- /dev/null +++ b/secrets/synapse_db_pass.age @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> ssh-rsa jWbwAg +uphSCXWnsU8Ffn8E3G3cQFlU+Op480vwqkDZKcvwGo/7aPeSKvcxpDkkvZbBSpeJ +agOsx9umGm2xJd38ss7vUYiTGZFyXVRVR0ECRLUSjmt4U1fbdIXM1JijKPJBNPFf +rZWc/+6uXXHFwv0633SyM6swuytmo6jKbdExclY1Q5bwYHfTAUvHaeUW1AFWd24d +HWJCLXEY3VK7WvcH3nvpzeNvRMbkaOBrcPnt7rqWmKH0F92tFP3mNiOtbHRZgSe8 +aJodlNU390gLqED/BOqKjLxCYvfiVSSRu6ziP/h3VKqmC8HDD8e+nSQwS7qMlgXi +4i6kgZQr+is1rsU5GMLe+H7jw/ZI+hOxNyutGXi1wd1qgrM1qbCfJmUS8tYUP2kw +NsD4+h1xz2Hkop+6MKursOPsD6Vw/TFuNKDXyQstbrz8jU8rP5jvkIn6o7PT4rVm +HyJ4sHlabnmqufyVCtjfZz84fyOjHqeoqeS0ST5zH1VcjGh9pEJiMOK0FoiJlDaQ +hyzKhREJ/iAlb1EJ9IRu+rVgO9hamj4ZyqE4kFrTfp9/bb5HbH04km+WZByzcenA +G8aOVUwk/IvC77jjMBKwn8i09DgBbjz5RHD6hXZwHOnPPQctBO8TDRIreQ9IHBsv +xIpQuRIf1GAiGwbVdGxffwsS38Aw6h2EDzX436NFJmc +--- AK4cj1yXlOGE07/jrzEfZ1RRwYnabyglA78+X54ON2E +/ɳbm/ը(N]Mc$5&ڬxfp*qlt朁164˛o(,* \ No newline at end of file diff --git a/secrets/synapse_db_pass_prepared.age b/secrets/synapse_db_pass_prepared.age new file mode 100644 index 0000000000000000000000000000000000000000..40711061dddeb5e1e75f062f1e64f8a2dcc4a55e GIT binary patch literal 899 zcmWO1%gfsY003~$;RBI+reR;018G7x;hDsS*oNU2k!04qZOg|$+Fn$vr_Np`oZ@G^N4wFu1JK;2yJ%K zIK1Xj+f0BF!I3=EmC`|A;*~WLY9Db#Bg$vqlG+Qq*lj3dF`66OUatjwdprpN1d4K9 z`t59!w!nc#nc7BiAvSN-0K@tz@2pk{P7CT023LGlD@VT42SP*_ z5vp*2UyTr&fFONvK*Av`QtutvOf9;lm?Mm5Vw=j+9<-RS;`7O9!slUwz)rv$eG>2W z5)g{hLBlOnB&TLRR*uH>t?r>?t+qgm=x7P?oud@~9(Nr!wx97MGfn_2Cpyg|3Xcs#xs5lx%by%>0|w680!(90TMbzLz@eVg6I zL2$zGf;z~-0(kG*)hC|5@%vk5^x(O_@84#bOD_}eEdF@tYvuN9>a+L%z4qppcVGSS z$=~$&^I!NMJ~?M^Ji;k2efPosi%YMgICseI(xdGX`maBq{d4d7yB~dg o_3YMPckX`n&G(N!_S9NC|MRE!H{ae0@0?wJ{=xY(Z;SW-0~#_s`~Uy| literal 0 HcmV?d00001 diff --git a/secrets/synapse_registration_shared_secret.age b/secrets/synapse_registration_shared_secret.age new file mode 100644 index 0000000000000000000000000000000000000000..2dfd2261f7fe493c8a517c6d21d811b25e701c2f GIT binary patch literal 844 zcmWO0JI||R003ZDF)^-A=Zh!0kjk|b987?gd&}i*ff5%eFSi2aRxVx6c>aNj$w|J= z@yr?r7kB@Fi81E5p18WG&o6kw6s}->>6T{5Z}peAF2zOyS$+M~_t~oJ!>7WFCO$=M zl(vK&w`NK*YO+CNBY%u-@bu9WGz1;;`rZ96T{F^JDK!ag8` zXKxQ7xUiZ!WC?bC#1+;1MdkqSQSp>c0|E5OF}Vp*w1c->BUynBTu3R4ifH6TZSXPFH&+?CHYe%KT*kd) z;*)2%)g%;PjhY4wjXEP6i=9BaA&m*p83EQ@b1$TDV?#L>tHM(*2;O@kH;Y)!F*6A8 zJslI|y5#_?*02m5MY#K#37G7VkDaOJF~&K&L^mW%8ynV}X=H3hRQW#-(N-MjecNZI zkwf?1VTWqRDJH5@>h9s0(qK*JLM^s^EAE=c_NuYd)EkSG#U)IB&uCFtvOQUwu_!6`6Se(tyCk_4HoV@+Kcxz<0Ctb*ijahXT5F|OPa@{%lS#sWH zMxM*F-rfZ6wrg^JM8}o{N3Ni5+C~X*&-V`&l0kore3}HETstn@Gcz~A(G2`(Fb@6( zW#}=cifL-@r=g$7=vw*-6>5jWG6lqJgh=Yl6biQ5Jgn1zIc|M@;my!_m;~G$^z%Y! zk5JwUr^-DctJUhs#O1DvE5IJlk;m+vU~B_du`tnJn=mWrKm&UIkoW31A@y&Z{pQ~F_`KkTl;}^gG NYmtAw{p!Q#{{VU59t!{f literal 0 HcmV?d00001 diff --git a/specific/grimmauld-nixos-server/configuration.nix b/specific/grimmauld-nixos-server/configuration.nix new file mode 100644 index 0000000..533a2d0 --- /dev/null +++ b/specific/grimmauld-nixos-server/configuration.nix @@ -0,0 +1,35 @@ +{ lib, config, inputs, pkgs, ... }: +let + inherit (config.networking) domain; +in { + imports = [ + ./hardware-configuration.nix + ]; + + networking.firewall.allowedTCPPorts = [ 80 443 ]; + networking.hostName = "grimmauld-nixos-server"; + networking.domain = "grimmauld.de"; + services.openssh.enable = true; + system.stateVersion = "23.11"; + + services.nginx = { + # package = pkgs.nginxStable.override { openssl = pkgs.libressl; }; + enable = true; + recommendedGzipSettings = true; + recommendedOptimisation = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + sslCiphers = "AES256+EECDH:AES256+EDH:!aNULL"; + + virtualHosts."${domain}" = { + forceSSL = true; + enableACME = lib.mkForce false; # use the correct cert, not some weird one that matrix-synapse module supplies + useACMEHost = domain; + locations."/" = { + root = "/var/www/${domain}"; + }; + }; + }; + + # users.users.root.openssh.authorizedKeys.keys = (import ./authorizedKeys.nix); +} diff --git a/specific/grimmauld-nixos-server/hardware-configuration.nix b/specific/grimmauld-nixos-server/hardware-configuration.nix new file mode 100644 index 0000000..4cf2f82 --- /dev/null +++ b/specific/grimmauld-nixos-server/hardware-configuration.nix @@ -0,0 +1,13 @@ +{ modulesPath, ... }: +{ + imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; + boot.loader.grub.device = "/dev/sda"; + boot.initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "xen_blkfront" "vmw_pvscsi" ]; + boot.initrd.kernelModules = [ "nvme" ]; + fileSystems."/" = { device = "/dev/sda3"; fsType = "ext4"; }; + + environment.sessionVariables = { + OMP_NUM_THREADS = "8"; + }; + +} diff --git a/users.nix b/users.nix index 617e340..e8731cf 100644 --- a/users.nix +++ b/users.nix @@ -9,10 +9,13 @@ isNormalUser = true; # shell = pkgs.xonsh; description = "grimmauld"; + + openssh.authorizedKeys.keys = (import ./authorizedKeys.nix); extraGroups = lib.intersectLists (lib.attrNames config.users.groups) [ "networkmanager" "kvm" "wheel" + "docker" "input" "video" "lp"