summary refs log tree commit diff
path: root/host/Rory-ovh
diff options
context:
space:
mode:
Diffstat (limited to 'host/Rory-ovh')
-rwxr-xr-xhost/Rory-ovh/configuration.nix122
-rwxr-xr-xhost/Rory-ovh/hooks/post-rebuild.sh30
-rw-r--r--host/Rory-ovh/services/cgit.nix62
-rw-r--r--host/Rory-ovh/services/containers/draupnir-ansible/container.nix37
-rw-r--r--host/Rory-ovh/services/containers/draupnir-ansible/root.nix16
-rw-r--r--host/Rory-ovh/services/containers/draupnir-ansible/services/draupnir.nix30
-rwxr-xr-xhost/Rory-ovh/services/containers/draupnir-cme/container.nix37
-rwxr-xr-xhost/Rory-ovh/services/containers/draupnir-cme/root.nix16
-rwxr-xr-xhost/Rory-ovh/services/containers/draupnir-cme/services/draupnir.nix23
-rw-r--r--host/Rory-ovh/services/containers/draupnir-fedora/container.nix37
-rw-r--r--host/Rory-ovh/services/containers/draupnir-fedora/root.nix16
-rw-r--r--host/Rory-ovh/services/containers/draupnir-fedora/services/draupnir.nix30
-rw-r--r--host/Rory-ovh/services/containers/shared.nix17
-rw-r--r--host/Rory-ovh/services/email/autoconfig.nix18
-rw-r--r--host/Rory-ovh/services/email/maddy.conf124
-rw-r--r--host/Rory-ovh/services/email/maddy.nix71
-rw-r--r--host/Rory-ovh/services/email/nginx.nix32
-rw-r--r--host/Rory-ovh/services/email/root.nix8
-rw-r--r--host/Rory-ovh/services/mastodon.nix12
-rwxr-xr-xhost/Rory-ovh/services/matrix/coturn.nix52
-rwxr-xr-xhost/Rory-ovh/services/matrix/draupnir.nix43
-rwxr-xr-xhost/Rory-ovh/services/matrix/grapevine.nix31
-rwxr-xr-xhost/Rory-ovh/services/matrix/matrix-appservice-discord.nix25
-rw-r--r--host/Rory-ovh/services/matrix/ooye.nix10
-rwxr-xr-xhost/Rory-ovh/services/matrix/root.nix13
-rw-r--r--host/Rory-ovh/services/matrix/synapse/caches.nix25
-rw-r--r--host/Rory-ovh/services/matrix/synapse/db.nix49
-rw-r--r--host/Rory-ovh/services/matrix/synapse/ratelimits.nix97
-rwxr-xr-xhost/Rory-ovh/services/matrix/synapse/synapse-main.nix283
-rwxr-xr-xhost/Rory-ovh/services/nginx/nginx.nix95
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/api.safensound.nix72
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/cgit.nix14
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/conduit.matrixunittests.nix16
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/demo.safensound.nix30
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/ec.nix26
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/jitsi.nix51
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/libmatrix-fed-test.nix26
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/matrix-bak.nix26
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/matrix.nix72
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/matrixunittests.nix16
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/mru.nix30
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/pcpoc.nix15
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/root.nix49
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/safensound.nix30
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/stream.nix34
-rwxr-xr-xhost/Rory-ovh/services/nginx/rory.gay/wad-api.nix32
-rwxr-xr-xhost/Rory-ovh/services/nginx/thearcanebrony.net/awooradio.nix13
-rwxr-xr-xhost/Rory-ovh/services/nginx/thearcanebrony.net/root.nix41
-rwxr-xr-xhost/Rory-ovh/services/nginx/thearcanebrony.net/search.nix10
-rwxr-xr-xhost/Rory-ovh/services/nginx/thearcanebrony.net/sentry.nix10
-rwxr-xr-xhost/Rory-ovh/services/postgres.nix99
-rw-r--r--host/Rory-ovh/services/prometheus.nix8
-rw-r--r--host/Rory-ovh/services/safensound.nix28
-rw-r--r--host/Rory-ovh/services/wireguard/wireguard.nix39
54 files changed, 2248 insertions, 0 deletions
diff --git a/host/Rory-ovh/configuration.nix b/host/Rory-ovh/configuration.nix
new file mode 100755

index 0000000..3ded494 --- /dev/null +++ b/host/Rory-ovh/configuration.nix
@@ -0,0 +1,122 @@ +{ + pkgs, + lib, + nixpkgs-Draupnir, + nixpkgs-DraupnirPkg, + ... +}: + +{ + imports = [ + ../../modules/base-server.nix + ../../modules/users/levi.nix + ../../modules/users/db2k.nix + ../../modules/users/ks.nix + ../../modules/users/Alice.nix + + ./services/prometheus.nix + + ./services/nginx/nginx.nix + ./services/cgit.nix + ./services/postgres.nix + ./services/matrix/synapse/synapse-main.nix + ./services/matrix/draupnir.nix + ./services/email/root.nix + #./services/wireguard/wireguard.nix + ./services/safensound.nix + ]; + + users.groups.ocp = { }; + boot.loader.grub.devices = lib.mkForce [ "nodev" ]; + networking = { + hostName = "Rory-ovh"; + nat = { + enable = true; + internalInterfaces = [ + "ve-+" + "vb-+" + ]; + externalInterface = "enp98s0f0"; + enableIPv6 = false; + }; + enableIPv6 = lib.mkForce false; + nameservers = lib.mkForce [ "1.1.1.1" ]; + firewall.enable = lib.mkForce true; + resolvconf.enable = false; + defaultGateway = lib.mkForce null; + defaultGateway6 = lib.mkForce null; + }; + + systemd.network = { + enable = true; + networks.enp98s0f0 = { + name = "enp98s0f0"; + DHCP = "no"; + #gateway = [ "51.210.113.254" ]; + routes = [ + { + Gateway = "51.210.113.254"; + GatewayOnLink = true; + } + ]; + address = [ "51.210.113.110/32" ]; + }; + }; + + monitoring = { + monitorAll = true; + localPrometheus = true; + exposePrometheus = true; + localGrafana = true; + exposeGrafana = true; + nginxHost = "monitoring.rory.gay"; + nginxSsl = true; + }; + + nixpkgs.config.permittedInsecurePackages = [ + "olm-3.2.16" + "dotnet-runtime-wrapped-7.0.20" + "dotnet-runtime-7.0.20" + "dotnet-sdk-7.0.20" + ]; + services.irqbalance.enable = true; + + environment.memoryAllocator.provider = "jemalloc"; + + containers."draupnir-cme" = import ./services/containers/draupnir-cme/container.nix { + inherit + pkgs + lib + nixpkgs-Draupnir + nixpkgs-DraupnirPkg + ; + }; + + containers."draupnir-fedora" = import ./services/containers/draupnir-fedora/container.nix { + inherit + pkgs + lib + nixpkgs-Draupnir + nixpkgs-DraupnirPkg + ; + }; + + containers."draupnir-ansible" = import ./services/containers/draupnir-ansible/container.nix { + inherit + pkgs + lib + nixpkgs-Draupnir + nixpkgs-DraupnirPkg + ; + }; + + system.stateVersion = "22.11"; # DO NOT EDIT! + + environment.systemPackages = with pkgs; [ waypipe ]; + + nix.nrBuildUsers = 128; + services.owncast = { + enable = true; + port = 1934; + }; +} diff --git a/host/Rory-ovh/hooks/post-rebuild.sh b/host/Rory-ovh/hooks/post-rebuild.sh new file mode 100755
index 0000000..f4f5896 --- /dev/null +++ b/host/Rory-ovh/hooks/post-rebuild.sh
@@ -0,0 +1,30 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash -p curl gnused nix coreutils jq openssl +#set -x +exit +REG_KEY=`cat /var/lib/matrix-synapse/registration_shared_secret.txt` +LOCALPART='rory.gay' +REACHABLE_DOMAIN='http://localhost:8008' + +# -- LICENSE: CNPL v7+ - https://thufie.lain.haus/files/CNPLv7.md +# Modified from Nyaaori (https://nyaaori.cat) <+@nyaaori.cat> +# Explicit authorisation to use the code has been granted by the original author +# for use by members of the Rory& system (https://rory.gay) + +# the magic function: +register(){ + echo "Registering $1" + _nonce=`curl -s http://localhost:8008/_synapse/admin/v1/register | jq -r .nonce` + #data: nonce, domain, username, password + _hmac=`printf '%s\0%s\0%s\0%s' "$_nonce" "$1" "$2" "admin" | openssl dgst -sha1 -hmac "$REG_KEY" | awk '{print $2}'` + curl -s -XPOST -d '{"nonce": "'"$_nonce"'", "username": "'"$1"'", "displayname": "'"$1"'", "password": "'"$2"'", "admin": true, "mac": "'"$_hmac"'"}' $REACHABLE_DOMAIN/_synapse/admin/v1/register | tee -a matrix-user-tokens.txt + echo +} + +# -- END OF LICENSED CODE + +#PASSWD=`cat /etc/matrix-user-pass` +#for u in {draupnir,Alicia,Emma,Rory,root,Quetzelle} +#do +# register $u $PASSWD +#done diff --git a/host/Rory-ovh/services/cgit.nix b/host/Rory-ovh/services/cgit.nix new file mode 100644
index 0000000..cbdc350 --- /dev/null +++ b/host/Rory-ovh/services/cgit.nix
@@ -0,0 +1,62 @@ +{ pkgs, lib, cgit-magenta, ... }: + +let + pkg = cgit-magenta.packages.${pkgs.stdenv.hostPlatform.system}.default; + base_cgit_config = { + enable = true; + nginx.virtualHost = "cgit.rory.gay"; + #package = pkgs.cgit-pink; + package = pkg; + scanPath = "/data/git"; + settings = { + css = "/cgit.css"; + logo = "/cgit.png"; + favicon = "/favicon.ico"; + readme = ":README.MD"; + about-filter = "${pkg}/lib/cgit/filters/about-formatting.sh"; + source-filter = "${pkg}/lib/cgit/filters/syntax-highlighting.py"; + clone-url = ( + lib.concatStringsSep " " [ + "https://cgit.rory.gay/$CGIT_REPO_URL" + "ssh://<user>@git.rory.gay:$CGIT_REPO_URL" + ] + ); + enable-log-filecount = 1; + enable-log-linecount = 1; + enable-git-config = 1; + #testing + enable-blame = 1; + enable-commit-graph = 1; + enable-follow-links = 1; + enable-http-clone = 1; + enable-index-links = 1; + enable-remote-branches = 1; + enable-subject-links = 1; + enable-tree-linenumbers = 1; + max-atom-items = 100; + max-commit-count = 250; + max-repo-count = 500; + snapshots = "tar.xz"; + #side-by-side-diffs = 1; + + root-title = "cgit.rory.gay"; + root-desc = "Rory&s Git Repositories"; + }; + }; +in +{ + services.cgit."main" = base_cgit_config; + services.fcgiwrap.instances."cgit-main".process.prefork = 32; + + services.cgit."ocp" = lib.attrsets.recursiveUpdate base_cgit_config { + scanPath = "/data/git/.ocp"; + nginx.location = "/.ocp/"; + settings.clone-url = ( + lib.concatStringsSep " " [ + "https://cgit.rory.gay/.ocp/$CGIT_REPO_URL" + "ssh://<user>@git.rory.gay:.ocp/$CGIT_REPO_URL" + ] + ); + }; + services.fcgiwrap.instances."cgit-ocp".process.prefork = 32; +} diff --git a/host/Rory-ovh/services/containers/draupnir-ansible/container.nix b/host/Rory-ovh/services/containers/draupnir-ansible/container.nix new file mode 100644
index 0000000..5ab1aed --- /dev/null +++ b/host/Rory-ovh/services/containers/draupnir-ansible/container.nix
@@ -0,0 +1,37 @@ +{ +# nixpkgs-Draupnir, +# nixpkgs-DraupnirPkg, + ... +}: + +{ + privateNetwork = true; + autoStart = true; + specialArgs = { +# inherit nixpkgs-Draupnir; +# inherit nixpkgs-DraupnirPkg; + }; + config = + { lib, pkgs, ... }: + { + imports = [ + ../shared.nix + ./root.nix + ./services/draupnir.nix +# "${nixpkgs-Draupnir}/nixos/modules/services/matrix/draupnir.nix" + ]; +# nixpkgs.overlays = [ +# (final: prev: { +# draupnir = nixpkgs-DraupnirPkg.legacyPackages.${pkgs.stdenv.hostPlatform.system}.draupnir; +# }) +# ]; + }; + hostAddress = "192.168.100.1"; + localAddress = "192.168.100.19"; + + bindMounts."draupnir-access-token" = { + hostPath = "/data/secrets/draupnir-ansible-access-token"; + mountPoint = "/etc/draupnir-access-token"; + isReadOnly = true; + }; +} diff --git a/host/Rory-ovh/services/containers/draupnir-ansible/root.nix b/host/Rory-ovh/services/containers/draupnir-ansible/root.nix new file mode 100644
index 0000000..0ebce9e --- /dev/null +++ b/host/Rory-ovh/services/containers/draupnir-ansible/root.nix
@@ -0,0 +1,16 @@ +{ ... }: + +{ + networking.useHostResolvConf = true; + + networking.hosts = { + "192.168.100.1" = [ + "matrix.rory.gay" + "rory.gay" + ]; + }; + + networking.firewall = { + enable = true; + }; +} diff --git a/host/Rory-ovh/services/containers/draupnir-ansible/services/draupnir.nix b/host/Rory-ovh/services/containers/draupnir-ansible/services/draupnir.nix new file mode 100644
index 0000000..c05b170 --- /dev/null +++ b/host/Rory-ovh/services/containers/draupnir-ansible/services/draupnir.nix
@@ -0,0 +1,30 @@ +{ ... }: + +{ + services.draupnir = { + enable = true; + secrets.accessToken = "/etc/draupnir-access-token"; + + settings = { + homeserverUrl = "https://matrix.rory.gay"; + managementRoom = "#draupnir-ansible-mgmt:rory.gay"; + recordIgnoredInvites = true; # We want to be aware of invites + autojoinOnlyIfManager = true; # ... but we don't want the bot to be invited to eg. Matrix HQ... + automaticallyRedactForReasons = [ "*" ]; # Always autoredact + fasterMembershipChecks = true; + + backgroundDelayMS = 10; # delay isn't needed, I don't mind the performance hit + pollReports = false; + + admin.enableMakeRoomAdminCommand = false; + commands.ban.defaultReasons = [ "spam" ]; + + protections = { + wordlist = { + words = [ "https://postimg.cc/" ]; + minutesBeforeTrusting = 0; + }; + }; + }; + }; +} diff --git a/host/Rory-ovh/services/containers/draupnir-cme/container.nix b/host/Rory-ovh/services/containers/draupnir-cme/container.nix new file mode 100755
index 0000000..b1ee74b --- /dev/null +++ b/host/Rory-ovh/services/containers/draupnir-cme/container.nix
@@ -0,0 +1,37 @@ +{ + #nixpkgs-Draupnir, + #nixpkgs-DraupnirPkg, + ... +}: + +{ + privateNetwork = true; + autoStart = true; + specialArgs = { + #inherit nixpkgs-Draupnir; + #inherit nixpkgs-DraupnirPkg; + }; + config = + { lib, pkgs, ... }: + { + imports = [ + ../shared.nix + ./root.nix + ./services/draupnir.nix + #"${nixpkgs-Draupnir}/nixos/modules/services/matrix/draupnir.nix" + ]; +# nixpkgs.overlays = [ +# (final: prev: { +# draupnir = nixpkgs-DraupnirPkg.legacyPackages.${pkgs.stdenv.hostPlatform.system}.draupnir; +# }) +# ]; + }; + hostAddress = "192.168.100.1"; + localAddress = "192.168.100.17"; + + bindMounts."draupnir-access-token" = { + hostPath = "/data/secrets/draupnir-cme-access-token"; + mountPoint = "/etc/draupnir-access-token"; + isReadOnly = true; + }; +} diff --git a/host/Rory-ovh/services/containers/draupnir-cme/root.nix b/host/Rory-ovh/services/containers/draupnir-cme/root.nix new file mode 100755
index 0000000..0ebce9e --- /dev/null +++ b/host/Rory-ovh/services/containers/draupnir-cme/root.nix
@@ -0,0 +1,16 @@ +{ ... }: + +{ + networking.useHostResolvConf = true; + + networking.hosts = { + "192.168.100.1" = [ + "matrix.rory.gay" + "rory.gay" + ]; + }; + + networking.firewall = { + enable = true; + }; +} diff --git a/host/Rory-ovh/services/containers/draupnir-cme/services/draupnir.nix b/host/Rory-ovh/services/containers/draupnir-cme/services/draupnir.nix new file mode 100755
index 0000000..4b3cd57 --- /dev/null +++ b/host/Rory-ovh/services/containers/draupnir-cme/services/draupnir.nix
@@ -0,0 +1,23 @@ +{ ... }: + +{ + services.draupnir = { + enable = true; + secrets.accessToken = "/etc/draupnir-access-token"; + + settings = { + homeserverUrl = "https://matrix.rory.gay"; + managementRoom = "#draupnir-cme:rory.gay"; + recordIgnoredInvites = true; # We want to be aware of invites + autojoinOnlyIfManager = true; # ... but we don't want the bot to be invited to eg. Matrix HQ... + automaticallyRedactForReasons = [ "*" ]; # Always autoredact + fasterMembershipChecks = true; + + backgroundDelayMS = 10; # delay isn't needed, I don't mind the performance hit + pollReports = false; + + admin.enableMakeRoomAdminCommand = false; + commands.ban.defaultReasons = [ "spam" ]; + }; + }; +} diff --git a/host/Rory-ovh/services/containers/draupnir-fedora/container.nix b/host/Rory-ovh/services/containers/draupnir-fedora/container.nix new file mode 100644
index 0000000..5ba9765 --- /dev/null +++ b/host/Rory-ovh/services/containers/draupnir-fedora/container.nix
@@ -0,0 +1,37 @@ +{ +# nixpkgs-Draupnir, +# nixpkgs-DraupnirPkg, + ... +}: + +{ + privateNetwork = true; + autoStart = true; + specialArgs = { +# inherit nixpkgs-Draupnir; +# inherit nixpkgs-DraupnirPkg; + }; + config = + { lib, pkgs, ... }: + { + imports = [ + ../shared.nix + ./root.nix + ./services/draupnir.nix +# "${nixpkgs-Draupnir}/nixos/modules/services/matrix/draupnir.nix" + ]; +# nixpkgs.overlays = [ +# (final: prev: { +# draupnir = nixpkgs-DraupnirPkg.legacyPackages.${pkgs.stdenv.hostPlatform.system}.draupnir; +# }) +# ]; + }; + hostAddress = "192.168.100.1"; + localAddress = "192.168.100.18"; + + bindMounts."draupnir-access-token" = { + hostPath = "/data/secrets/draupnir-fedora-access-token"; + mountPoint = "/etc/draupnir-access-token"; + isReadOnly = true; + }; +} diff --git a/host/Rory-ovh/services/containers/draupnir-fedora/root.nix b/host/Rory-ovh/services/containers/draupnir-fedora/root.nix new file mode 100644
index 0000000..0ebce9e --- /dev/null +++ b/host/Rory-ovh/services/containers/draupnir-fedora/root.nix
@@ -0,0 +1,16 @@ +{ ... }: + +{ + networking.useHostResolvConf = true; + + networking.hosts = { + "192.168.100.1" = [ + "matrix.rory.gay" + "rory.gay" + ]; + }; + + networking.firewall = { + enable = true; + }; +} diff --git a/host/Rory-ovh/services/containers/draupnir-fedora/services/draupnir.nix b/host/Rory-ovh/services/containers/draupnir-fedora/services/draupnir.nix new file mode 100644
index 0000000..a39b3a9 --- /dev/null +++ b/host/Rory-ovh/services/containers/draupnir-fedora/services/draupnir.nix
@@ -0,0 +1,30 @@ +{ ... }: + +{ + services.draupnir = { + enable = true; + secrets.accessToken = "/etc/draupnir-access-token"; + + settings = { + homeserverUrl = "https://matrix.rory.gay"; + managementRoom = "#draupnir-fedora-mgmt:rory.gay"; + recordIgnoredInvites = true; # We want to be aware of invites + autojoinOnlyIfManager = true; # ... but we don't want the bot to be invited to eg. Matrix HQ... + automaticallyRedactForReasons = [ "*" ]; # Always autoredact + fasterMembershipChecks = true; + + backgroundDelayMS = 10; # delay isn't needed, I don't mind the performance hit + pollReports = false; + + admin.enableMakeRoomAdminCommand = false; + commands.ban.defaultReasons = [ "spam" ]; + + protections = { + wordlist = { + words = [ "https://postimg.cc/" ]; + minutesBeforeTrusting = 0; + }; + }; + }; + }; +} diff --git a/host/Rory-ovh/services/containers/shared.nix b/host/Rory-ovh/services/containers/shared.nix new file mode 100644
index 0000000..f267ff0 --- /dev/null +++ b/host/Rory-ovh/services/containers/shared.nix
@@ -0,0 +1,17 @@ +{ pkgs, ... }: +{ + environment.systemPackages = with pkgs; [ + neofetch + lnav + zsh + git + lsd + htop + btop + duf + kitty.terminfo + neovim + jq + dig + ]; +} diff --git a/host/Rory-ovh/services/email/autoconfig.nix b/host/Rory-ovh/services/email/autoconfig.nix new file mode 100644
index 0000000..5f3bce2 --- /dev/null +++ b/host/Rory-ovh/services/email/autoconfig.nix
@@ -0,0 +1,18 @@ +{ config, ... }: +{ + services.go-autoconfig = { + enable = !config.virtualisation.isVmVariant; + settings = { + service_addr = ":1323"; + domain = "autoconfig.rory.gay"; + imap = { + server = "rory.gay"; + port = 993; + }; + smtp = { + server = "rory.gay"; + port = 587; + }; + }; + }; +} diff --git a/host/Rory-ovh/services/email/maddy.conf b/host/Rory-ovh/services/email/maddy.conf new file mode 100644
index 0000000..1d3eb2f --- /dev/null +++ b/host/Rory-ovh/services/email/maddy.conf
@@ -0,0 +1,124 @@ + +# Minimal configuration with TLS disabled, adapted from upstream example +# configuration here https://github.com/foxcpp/maddy/blob/master/maddy.conf +# Do not use this in production! + +auth.pass_table local_authdb { + table sql_table { + driver sqlite3 + dsn credentials.db + table_name passwords + } +} + +storage.imapsql local_mailboxes { + driver sqlite3 + dsn imapsql.db +} + +table.chain local_rewrites { + optional_step regexp "(.+)\+(.+)@(.+)" "$1@$3" + optional_step static { + entry postmaster root@$(primary_domain) + } + optional_step file /etc/maddy/aliases +} + +msgpipeline local_routing { + destination postmaster $(local_domains) { + modify { + replace_rcpt &local_rewrites + } + deliver_to &local_mailboxes + } + default_destination { + reject 550 5.1.1 "User doesn't exist" + } +} + +smtp tcp://0.0.0.0:25 { + limits { + all rate 20 1s + all concurrency 10 + } + dmarc yes + check { + require_mx_record + dkim + spf + } + source $(local_domains) { + reject 501 5.1.8 "Use Submission for outgoing SMTP" + } + default_source { + destination postmaster $(local_domains) { + deliver_to &local_routing + } + default_destination { + reject 550 5.1.1 "User doesn't exist" + } + } +} + +submission tls://0.0.0.0:465 tcp://0.0.0.0:587 { + limits { + all rate 50 1s + } + auth &local_authdb + source $(local_domains) { + check { + authorize_sender { + prepare_email &local_rewrites + user_to_email identity + } + } + destination postmaster $(local_domains) { + deliver_to &local_routing + } + default_destination { + modify { + dkim $(primary_domain) $(local_domains) default + } + deliver_to &remote_queue + } + } + default_source { + reject 501 5.1.8 "Non-local sender domain" + } +} + +target.remote outbound_delivery { + limits { + destination rate 20 1s + destination concurrency 10 + } + mx_auth { + dane + mtasts { + cache fs + fs_dir mtasts_cache/ + } + local_policy { + min_tls_level encrypted + min_mx_level none + } + } +} + +target.queue remote_queue { + target &outbound_delivery + autogenerated_msg_domain $(primary_domain) + bounce { + destination postmaster $(local_domains) { + deliver_to &local_routing + } + default_destination { + reject 550 5.0.0 "Refusing to send DSNs to non-local addresses" + } + } +} + +imap tls://0.0.0.0:993 tcp://0.0.0.0:143 { + auth &local_authdb + storage &local_mailboxes +} \ No newline at end of file diff --git a/host/Rory-ovh/services/email/maddy.nix b/host/Rory-ovh/services/email/maddy.nix new file mode 100644
index 0000000..548cb1a --- /dev/null +++ b/host/Rory-ovh/services/email/maddy.nix
@@ -0,0 +1,71 @@ +{ + lib, + pkgs, + options, + config, + ... +}: +{ + config = lib.mkIf (!config.virtualisation.isVmVariant) { + services.maddy = { + enable = true; + primaryDomain = "rory.gay"; + hostname = "mail.rory.gay"; + ensureAccounts = [ + "root@rory.gay" + ]; + ensureCredentials = { + "root@rory.gay".passwordFile = "/var/lib/maddy/passwd/root"; + }; + config = builtins.readFile ./maddy.conf; + # builtins.replaceStrings + # [ + # "imap tcp://0.0.0.0:143" + # "submission tcp://0.0.0.0:587" + # "entry postmaster postmaster@$(primary_domain)" + # ] + # [ + # "imap tls://0.0.0.0:993 tcp://0.0.0.0:143" + # "submission tls://0.0.0.0:465 tcp://0.0.0.0:587" + # "entry postmaster root@$(primary_domain)" + # ] + # options.services.maddy.config.default; + + tls = { + loader = "file"; + certificates = [ + { + # certPath = "/var/lib/acme/mail.rory.gay/fullchain.pem"; + # keyPath = "/var/lib/acme/mail.rory.gay/key.pem"; + certPath = "/run/credentials/maddy.service/acme-fullchain.pem"; + keyPath = "/run/credentials/maddy.service/acme-key.pem"; + } + ]; + }; + }; + + networking.firewall.allowedTCPPorts = [ + 25 + 143 + 465 + 587 + 993 + ]; + + users.users.maddy.extraGroups = [ "nginx" ]; + + fileSystems."/var/lib/maddy" = { + depends = [ "/" ]; + device = "/data/maddy"; + fsType = "none"; + options = [ "bind" ]; + }; + + systemd.services.maddy.serviceConfig = { + LoadCredential = [ + "acme-fullchain.pem:/var/lib/acme/rory.gay/fullchain.pem" + "acme-key.pem:/var/lib/acme/rory.gay/key.pem" + ]; + }; + }; +} diff --git a/host/Rory-ovh/services/email/nginx.nix b/host/Rory-ovh/services/email/nginx.nix new file mode 100644
index 0000000..5b04612 --- /dev/null +++ b/host/Rory-ovh/services/email/nginx.nix
@@ -0,0 +1,32 @@ +{ config, ... }: +{ + services.nginx.virtualHosts = { + "mta-sts.rory.gay" = { + enableACME = !config.virtualisation.isVmVariant; + forceSSL = !config.virtualisation.isVmVariant; + locations = { + "/.well-known/mta-sts.txt" = { + # age 604800 + return = '' + 200 "version: STSv1 + mode: enforce + max_age: 120 + mx: mail.rory.gay + "''; + }; + }; + }; + "mail.rory.gay" = { + enableACME = !config.virtualisation.isVmVariant; + forceSSL = !config.virtualisation.isVmVariant; + locations = { + "/".return = "200 'OK'"; + }; + }; + "autoconfig.rory.gay" = { + enableACME = !config.virtualisation.isVmVariant; + forceSSL = !config.virtualisation.isVmVariant; + locations."/".proxyPass = "http://localhost:1323"; + }; + }; +} diff --git a/host/Rory-ovh/services/email/root.nix b/host/Rory-ovh/services/email/root.nix new file mode 100644
index 0000000..7db85d8 --- /dev/null +++ b/host/Rory-ovh/services/email/root.nix
@@ -0,0 +1,8 @@ +{ ... }: +{ + imports = [ + ./autoconfig.nix + ./maddy.nix + ./nginx.nix + ]; +} diff --git a/host/Rory-ovh/services/mastodon.nix b/host/Rory-ovh/services/mastodon.nix new file mode 100644
index 0000000..56f1808 --- /dev/null +++ b/host/Rory-ovh/services/mastodon.nix
@@ -0,0 +1,12 @@ +{ ... }: + +{ + services.mastodon = { + enable = true; + webProcesses = 8; + webThreads = 4; + + streamingProcesses = 63; + localDomain = "rory.gay"; + }; +} diff --git a/host/Rory-ovh/services/matrix/coturn.nix b/host/Rory-ovh/services/matrix/coturn.nix new file mode 100755
index 0000000..805faa9 --- /dev/null +++ b/host/Rory-ovh/services/matrix/coturn.nix
@@ -0,0 +1,52 @@ +{ ... }: + +{ + # coturn (WebRTC) + services.coturn = { + enable = false; # Alicia - figure out secret first... + no-cli = true; + no-tcp-relay = true; + min-port = 49000; + max-port = 50000; + use-auth-secret = true; + static-auth-secret = "will be world readable for local users :("; + realm = "turn.example.com"; + # Alicia - figure out how to get this to work, since nginx runs on separate machine... + #cert = "${config.security.acme.certs.${realm}.directory}/full.pem"; + #pkey = "${config.security.acme.certs.${realm}.directory}/key.pem"; + extraConfig = '' + # for debugging + verbose + # ban private IP ranges + no-multicast-peers + denied-peer-ip=0.0.0.0-0.255.255.255 + denied-peer-ip=10.0.0.0-10.255.255.255 + denied-peer-ip=100.64.0.0-100.127.255.255 + denied-peer-ip=127.0.0.0-127.255.255.255 + denied-peer-ip=169.254.0.0-169.254.255.255 + denied-peer-ip=172.16.0.0-172.31.255.255 + denied-peer-ip=192.0.0.0-192.0.0.255 + denied-peer-ip=192.0.2.0-192.0.2.255 + denied-peer-ip=192.88.99.0-192.88.99.255 + denied-peer-ip=192.168.0.0-192.168.255.255 + denied-peer-ip=198.18.0.0-198.19.255.255 + denied-peer-ip=198.51.100.0-198.51.100.255 + denied-peer-ip=203.0.113.0-203.0.113.255 + denied-peer-ip=240.0.0.0-255.255.255.255 + denied-peer-ip=::1 + denied-peer-ip=64:ff9b::-64:ff9b::ffff:ffff + denied-peer-ip=::ffff:0.0.0.0-::ffff:255.255.255.255 + denied-peer-ip=100::-100::ffff:ffff:ffff:ffff + denied-peer-ip=2001::-2001:1ff:ffff:ffff:ffff:ffff:ffff:ffff + denied-peer-ip=2002::-2002:ffff:ffff:ffff:ffff:ffff:ffff:ffff + denied-peer-ip=fc00::-fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff + denied-peer-ip=fe80::-febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff + ''; + }; + #services.matrix-synapse = with config.services.coturn; { + # turn_uris = ["turn:${realm}:3478?transport=udp" "turn:${realm}:3478?transport=tcp"]; + # turn_shared_secret = static-auth-secret; + # turn_user_lifetime = "1h"; + #}; + +} diff --git a/host/Rory-ovh/services/matrix/draupnir.nix b/host/Rory-ovh/services/matrix/draupnir.nix new file mode 100755
index 0000000..3f6d89a --- /dev/null +++ b/host/Rory-ovh/services/matrix/draupnir.nix
@@ -0,0 +1,43 @@ +{ pkgs, draupnirSrc, ... }: + +{ + services.draupnir = { + + enable = true; + secrets.accessToken = "/data/secrets/draupnir-access-token"; + + settings = { + homeserverUrl = "https://matrix.rory.gay"; + managementRoom = "#draupnir-mgmt:rory.gay"; + recordIgnoredInvites = true; # Let's log ignored invites, just incase + autojoinOnlyIfManager = true; # Let's not open ourselves up to DoS attacks + automaticallyRedactForReasons = [ "*" ]; # I always want autoredact + fasterMembershipChecks = true; + logLevel = "DEBUG"; + #roomStateBackingStore.enabled = true; # broken under nix. + + backgroundDelayMS = 10; # delay isn't needed, I don't mind the performance hit + pollReports = false; # this is a single person homeserver... let's save ourself the work + + admin.enableMakeRoomAdminCommand = true; + commands.ban.defaultReasons = [ + "spam" + "harassment" + "transphobia" + "scam" + ]; + protections = { + wordlist = { + words = [ + "tranny" + "faggot" + "ywnbaw" + "nigger" + "https://postimg.cc/" + ]; + minutesBeforeTrusting = 0; + }; + }; + }; + }; +} diff --git a/host/Rory-ovh/services/matrix/grapevine.nix b/host/Rory-ovh/services/matrix/grapevine.nix new file mode 100755
index 0000000..7368c2a --- /dev/null +++ b/host/Rory-ovh/services/matrix/grapevine.nix
@@ -0,0 +1,31 @@ +{ ... }: + +{ + services.grapevine = { + enable = true; + settings = { + conduit_compat = true; + server_name = "conduit.rory.gay"; + #trusted_servers = [ "rory.gay" ]; + federation.self_test = false; + + listen = [ + { + type = "tcp"; + address = "127.0.0.1"; + port = 6167; + } + ]; + server_discovery.client.base_url = "https://conduit.rory.gay"; # This is required for some reason + + database = { + backend = "rocksdb"; + }; + allow_registration = false; + + #log = "info"; + #log_format = "full"; + #log = "debug"; + }; + }; +} diff --git a/host/Rory-ovh/services/matrix/matrix-appservice-discord.nix b/host/Rory-ovh/services/matrix/matrix-appservice-discord.nix new file mode 100755
index 0000000..3041aaa --- /dev/null +++ b/host/Rory-ovh/services/matrix/matrix-appservice-discord.nix
@@ -0,0 +1,25 @@ +{ ... }: + +{ + # Discord bridge + services.matrix-appservice-discord = { + enable = false; # Alicia - figure out secret first... + environmentFile = /etc/keyring/matrix-appservice-discord/tokens.env; + # The appservice is pre-configured to use SQLite by default. + # It's also possible to use PostgreSQL. + settings = { + bridge = { + domain = "rory.gay"; + homeserverUrl = "https://matrix.rory.gay"; + }; + + # The service uses SQLite by default, but it's also possible to use + # PostgreSQL instead: + database = { + # filename = ""; # empty value to disable sqlite + connString = "postgres://postgres@127.0.0.1/matrix-appservice-discord"; + }; + }; + }; + +} diff --git a/host/Rory-ovh/services/matrix/ooye.nix b/host/Rory-ovh/services/matrix/ooye.nix new file mode 100644
index 0000000..7b9c403 --- /dev/null +++ b/host/Rory-ovh/services/matrix/ooye.nix
@@ -0,0 +1,10 @@ +{ ... }: + +{ + services.matrix-ooye = { + enable = true; + homeserver = "https://matrix.rory.gay"; + homeserverName = "rory.gay"; + enableSynapseIntegration = true; + }; +} diff --git a/host/Rory-ovh/services/matrix/root.nix b/host/Rory-ovh/services/matrix/root.nix new file mode 100755
index 0000000..d32cc54 --- /dev/null +++ b/host/Rory-ovh/services/matrix/root.nix
@@ -0,0 +1,13 @@ +{ ... }: + +{ + imports = [ + ./synapse/synapse-main.nix + ./coturn.nix + ./matrix-appservice-discord.nix + ./draupnir.nix + ./grapevine.nix + ./ooye.nix + ]; + +} diff --git a/host/Rory-ovh/services/matrix/synapse/caches.nix b/host/Rory-ovh/services/matrix/synapse/caches.nix new file mode 100644
index 0000000..f00c78c --- /dev/null +++ b/host/Rory-ovh/services/matrix/synapse/caches.nix
@@ -0,0 +1,25 @@ +{ + gc_min_interval = [ + "15m" + "30m" + "60m" + ]; + gc_thresholds = [ + 10000 + + 5000 + 2500 + ]; + event_cache_size = "12000K"; # defaults to 10K + caches = { + global_factor = 500000.0; + cache_entry_ttl = "24h"; + expire_caches = true; + sync_response_cache_duration = "15m"; + cache_autotuning = { + max_cache_memory_usage = "65536M"; + target_cache_memory_usage = "32768M"; + min_cache_ttl = "6h"; + }; + }; +} diff --git a/host/Rory-ovh/services/matrix/synapse/db.nix b/host/Rory-ovh/services/matrix/synapse/db.nix new file mode 100644
index 0000000..409c039 --- /dev/null +++ b/host/Rory-ovh/services/matrix/synapse/db.nix
@@ -0,0 +1,49 @@ +{ + workerName ? null, + dbGroup ? null, +}: +{ + name = "psycopg2"; + args = { + user = "matrix-synapse-rory-gay"; + password = "somepassword"; + database = "matrix-synapse-rory-gay"; + host = "/run/postgresql"; + application_name = "matrix-synapse (rory.gay) - ${if workerName == null then throw "synapse/db.nix: workerName unspecified" else workerName}"; + cp_min = + if dbGroup == "solo" then + 1 + else if dbGroup == "small" then + 2 + else if dbGroup == "medium" then + 5 + else if dbGroup == "large" then + 10 + else + throw "synapse/db.nix: Invalid dbGroup: ${if dbGroup == null then "null" else dbGroup}"; + cp_max = + if dbGroup == "solo" then + 1 + else if dbGroup == "small" then + 2 + else if dbGroup == "medium" then + 10 + else if dbGroup == "large" then + 10 + else + throw "synapse/db.nix: Invalid dbGroup: ${if dbGroup == null then "null" else dbGroup}"; + + # cp_reconnect - default=True - https://github.com/element-hq/synapse/blob/develop/synapse/storage/database.py#L129 + # cp_noisy - default=False - https://docs.twisted.org/en/stable/api/twisted.enterprise.adbapi.ConnectionPool.html#__init__ - info logs during operation + # check_same_thread - default=False - https://github.com/element-hq/synapse/blob/develop/synapse/config/database.py#L65 - can this even be set? + }; + + # synchronous_commit - default=True - https://github.com/element-hq/synapse/blob/develop/synapse/storage/engines/postgres.py#L56 + # statement_timeout - default=60 * 60 * 1000 ms - https://github.com/element-hq/synapse/blob/develop/synapse/storage/engines/postgres.py#L63 + # allow_unsafe_locale - default=False - https://github.com/element-hq/synapse/blob/develop/synapse/storage/engines/postgres.py#L99 + # allow_outdated_version - default=False - https://github.com/element-hq/synapse/blob/develop/synapse/storage/engines/postgres.py#L92 - needs source link + # txn_limit - default=0 - https://github.com/element-hq/synapse/blob/develop/synapse/storage/database.py#L564 + + statement_timeout = 24 * 60 * 60 * 1000; # 24 hours, good for bg jobs + txn_limit = 500; # maybe dropping old data from pg caches helps? +} diff --git a/host/Rory-ovh/services/matrix/synapse/ratelimits.nix b/host/Rory-ovh/services/matrix/synapse/ratelimits.nix new file mode 100644
index 0000000..85f51f2 --- /dev/null +++ b/host/Rory-ovh/services/matrix/synapse/ratelimits.nix
@@ -0,0 +1,97 @@ +{ + # messages + rc_message = { + per_second = 1000000; + burst_count = 1000000; + }; + rc_admin_redaction = { + per_second = 10000000; + burst_count = 10000000; + }; + + # room joins + rc_joins = { + local = { + per_second = 1000; + burst_count = 1000; + }; + remote = { + per_second = 1000; + burst_count = 1000; + }; + }; + rc_joins_per_room = { + per_second = 1000; + burst_count = 1000; + }; + + # room invites + rc_invites = { + per_room = { + per_second = 1000; + burst_count = 1000; + }; + per_user = { + per_second = 1000; + burst_count = 1000; + }; + per_issuer = { + per_second = 1000; + burst_count = 1000; + }; + }; + rc_third_party_invite = { + per_second = 1000; + burst_count = 1000; + }; + + # federation + rc_federation = { + window_size = 10; + sleep_limit = 1000; + sleep_delay = 100; + reject_limit = 1000; + concurrent = 100; + }; + federation_rr_transactions_per_room_per_second = 100; + + # media + rc_media_create = { + per_second = 1000; + burst_count = 1000; + }; + remote_media_download_burst_count = "512G"; + remote_media_download_per_second = "512G"; + + # authentication + rc_login = { + address = { + per_second = 1000; + burst_count = 1000; + }; + account = { + per_second = 1000; + burst_count = 1000; + }; + failed_attempts = { + per_second = 0.1; + burst_count = 3; + }; + }; + rc_3pid_validation = { + per_second = 1000; + burst_count = 1000; + }; + + #presence + rc_presence.per_user = { + per_second = 1; + burst_count = 2; + }; + + #delayed events + rc_delayed_event_mgmt = { + per_second = 1000; + burst_count = 1000; + }; +} diff --git a/host/Rory-ovh/services/matrix/synapse/synapse-main.nix b/host/Rory-ovh/services/matrix/synapse/synapse-main.nix new file mode 100755
index 0000000..7907927 --- /dev/null +++ b/host/Rory-ovh/services/matrix/synapse/synapse-main.nix
@@ -0,0 +1,283 @@ +{ config, pkgs, ... }: + +{ + # Worker plumbing examples: https://github.com/element-hq/synapse/blob/master/docker/configure_workers_and_start.py + # Documentation: https://github.com/element-hq/synapse/blob/develop/docs/workers.md + services.matrix-synapse = { + enable = true; + withJemalloc = true; + dataDir = "/data/matrix-synapse"; + + nginxVirtualHostName = "matrix.rory.gay"; + enableWorkers = true; + + federationSenders = if config.virtualisation.isVmVariant then 0 else 16; # 16 + pushers = if config.virtualisation.isVmVariant then 1 else 1; + mediaRepoWorkers = if config.virtualisation.isVmVariant then 1 else 2; # 4 + clientReaders = if config.virtualisation.isVmVariant then 2 else 2; # 4 + syncWorkers = if config.virtualisation.isVmVariant then 2 else 2; # 4 + #authWorkers = 0; + + eventCreators = if config.virtualisation.isVmVariant then 2 else 16; + + federationReaders = if config.virtualisation.isVmVariant then 0 else 8; # 8 + federationInboundWorkers = if config.virtualisation.isVmVariant then 0 else 16; # 8 + + enableAppserviceWorker = if config.virtualisation.isVmVariant then true else true; + enableBackgroundWorker = if config.virtualisation.isVmVariant then true else true; + enableUserDirWorker = if config.virtualisation.isVmVariant then true else true; + + accountDataStreamWriters = 1; + eventStreamWriters = 2; # 8 + presenceStreamWriters = 1; + pushRuleStreamWriters = 1; + receiptStreamWriters = 1; + toDeviceStreamWriters = 1; + typingStreamWriters = 1; + + plugins = with pkgs.matrix-synapse-plugins; [ + synapse-http-antispam + ]; + + #untested: + #sharedStreamWriters = 1; + + # https://matrix-org.github.io/synapse/latest/usage/configuration/config_documentation.html + settings = + { + server_name = "rory.gay"; + + # use_frozen_dicts = true; + # user_agent_suffix = " (rory.gay)"; + + # look into later: replication_torture_level - https://github.com/element-hq/synapse/blob/develop/synapse/config/server.py#L560 + # limit_remote_rooms ??? + # cleanup_extremities_with_dummy_events - default=True + # dummy_events_threshold - default=10 - required forward extremities to send dummy event + # enable_ephemeral_messages - default=False - ??? + # rooms_to_exclude_from_sync - default=[] - room ids... + # third_party_event_rules - https://github.com/element-hq/synapse/blob/develop/synapse/config/third_party_event_rules.py - ??? + # default_power_level_content_override - default=None - https://github.com/element-hq/synapse/blob/develop/synapse/config/room.py#L73 + + dummy_events_threshold = 5; + cleanup_extremities_with_dummy_events = true; + + enable_registration = true; + registration_requires_token = true; + + require_membership_for_aliases = false; + redaction_retention_period = null; + user_ips_max_age = null; + allow_device_name_lookup_over_federation = true; + + federation = { + client_timeout = "90s"; # 30 # default=60s + max_short_retries = 6; # 12 + max_short_retry_delay = "10s"; # 5 + max_long_retries = 5; + max_long_retry_delay = "30s"; + + # rapid retry, small increments + destination_min_retry_interval = "1m"; # default=10m + destination_max_retry_interval = "12h"; # default=7d + destination_retry_multiplier = 1.1; # 1.2 # default=2 + }; + + registration_shared_secret_path = "/data/secrets/synapse-shared-secret"; + + listeners = [ + { + port = 8008; + bind_addresses = [ "127.0.0.1" ]; + type = "http"; + tls = false; + x_forwarded = true; + resources = [ + { + names = [ + "client" + "federation" + ]; + compress = false; + } + ]; + } + { + type = "http"; + path = "/run/matrix-synapse/main.sock"; + resources = [ + { + names = [ "replication" ]; + compress = false; + } + ]; + } + ]; + presence = { + enable = true; + update_interval = 60; + }; + database = ( + import ./db.nix { + workerName = "main"; + dbGroup = "medium"; + } + ); + app_service_config_files = [ + #"/etc/matrix-synapse/appservice-registration.yaml" + #"/var/lib/matrix-synapse/modas-registration.yaml" + ]; + + #region Media + max_upload_size = "512M"; + + max_avatar_size = "512M"; + max_image_pixels = "250M"; + + max_pending_media_uploads = 512; + dynamic_thumbnails = true; + + prevent_media_downloads_from = [ + # none, give me all the media + ]; + enable_authenticated_media = false; + + url_preview_enabled = true; + max_spider_size = "50M"; + + #endregion + + ui_auth = { + session_timeout = "1m"; + }; + + login_via_existing_session = { + enabled = true; + require_ui_auth = true; + token_timeout = "1y"; + }; + + report_stats = false; + + user_directory = { + enabled = true; + search_all_users = true; + prefer_local_users = true; + }; + + # https://github.com/element-hq/synapse/blob/master/synapse/config/experimental.py + experimental_features = { + "msc2409_to_device_messages_enabled" = true; + "msc2815_enabled" = true; # Redacted event content + "msc3026_enabled" = true; # Busy presence + "msc3202_transaction_extensions" = true; # appservice transaction extensions (device list/keys) + "msc3266_enabled" = true; # Room summary API + "msc3391_enabled" = true; # Remove account data + "msc3823_account_suspension" = true; # Account suspension + "msc3852_enabled" = true; # Last seen on /devices (CS-API/admin) + "msc3874_enabled" = true; # filtering /messages with rel_types / not_rel_types + "msc3890_enabled" = true; # communicate account data deletion to clients + "msc3912_enabled" = true; # /messages with rel_types / not_rel_types and event id + "msc3916_authenticated_media_enabled" = true; # Authenticated media + "msc4069_profile_inhibit_propagation" = true; # Inhibit profile update propagation + "msc4133_enabled" = true; # Custom profile fields + "msc4151_enabled" = true; # Report room API (CS-API) + "msc4210_enabled" = false; # Remove legacy mentions -- we want this *disabled* for moderation reasons + "msc4222_enabled" = true; # state_after in sync + }; + + redis = { + enabled = true; + path = "/run/redis-matrix-synapse/redis.sock"; + }; + + instance_map = { + main = { + # replication listener + path = "/run/matrix-synapse/main.sock"; + }; + }; + } + // import ./ratelimits.nix + // import ./caches.nix; + }; + + #systemd.services.matrix-synapse-reg-token = { + # description = "Random registration token for Synapse."; + # before = [ "matrix-synapse.service" ]; # So the registration can be used by Synapse + # wantedBy = [ "multi-user.target" ]; + # after = [ "network.target" ]; +# + # script = '' + # set -e -x -o pipefail + # echo "Starting key generation" + # if [ ! -f "registration_shared_secret.txt" ] + # then + # echo "Generating new key" + # strace cat /dev/urandom | tr -dc a-zA-Z0-9 | fold -w 256 | head -n 1 > registration_shared_secret.txt + # echo "Key generation complete" + # else + # echo "Not generating key, key exists" + # fi + # echo "Script complete" + # ''; + # serviceConfig = { + # User = "matrix-synapse"; + # Group = "matrix-synapse"; + # WorkingDirectory = "/var/lib/matrix-synapse"; + # RemainAfterExit = true; + # }; + #}; + + services.redis = { + package = pkgs.valkey; + servers.matrix-synapse = { + enable = true; + user = "matrix-synapse"; + }; + }; + + systemd.tmpfiles.rules = [ "D /run/redis-matrix-synapse 0755 matrix-synapse matrix-synapse" ]; + + virtualisation.vmVariant = { + systemd.tmpfiles.rules = [ "D /run/secrets 0755 nobody nobody" ]; + systemd.services."matrix-synapse-generate-token" = { + # generate /data/secrets/synapse-shared-secret + description = "Generate Synapse shared secret"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + before = [ "matrix-synapse.service" ]; + script = '' + set -e -x -o pipefail + echo "Starting key generation" + if [ ! -f "/data/secrets/synapse-shared-secret" ] + then + echo "Generating new key" + ${pkgs.openssl}/bin/openssl rand -base64 32 > /data/secrets/synapse-shared-secret + echo "Key generation complete" + else + echo "Not generating key, key exists" + fi + echo "Script complete" + ''; + }; + systemd.services."matrix-synapse-postgres-init" = { + description = "Generate synapse postgres user"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" "postgresql.service" ]; + before = [ "matrix-synapse.service" ]; + + script = '' + set -e -x -o pipefail + ${pkgs.postgresql}/bin/createuser ${config.services.matrix-synapse.settings.database.args.user} || true + ${pkgs.postgresql}/bin/createdb --encoding=UTF8 --locale=C --template=template0 --owner=${config.services.matrix-synapse.settings.database.args.user} ${config.services.matrix-synapse.settings.database.args.database} || true + ''; + serviceConfig = { + User = "postgres"; + Group = "postgres"; + WorkingDirectory = config.services.postgresql.dataDir; + RemainAfterExit = true; + }; + }; + }; +} diff --git a/host/Rory-ovh/services/nginx/nginx.nix b/host/Rory-ovh/services/nginx/nginx.nix new file mode 100755
index 0000000..d422cc8 --- /dev/null +++ b/host/Rory-ovh/services/nginx/nginx.nix
@@ -0,0 +1,95 @@ +{ config, pkgs, ... }: +let + serveDir = config: { + enableACME = if config ? ssl then config.ssl else !config.virtualisation.isVmVariant; + addSSL = if config ? ssl then config.ssl else true; + root = if config ? path then config.path else builtins.throw "path is required"; + locations = { + "/" = { + index = "index.html"; + }; + }; + }; +in +{ + services = { + nginx = { + enable = true; + package = pkgs.nginxQuic; + recommendedProxySettings = true; + recommendedTlsSettings = true; + recommendedZstdSettings = true; + #recommendedGzipSettings = true; + recommendedBrotliSettings = true; + recommendedOptimisation = true; + defaultMimeTypes = ../../../../packages/nginx/mime.types; + appendConfig = '' + worker_processes 16; + ''; + eventsConfig = '' + #use kqueue; + worker_connections 512; + ''; + appendHttpConfig = '' + #sendfile on; + disable_symlinks off; + log_format combined_vhosts '$remote_addr - $remote_user [$time_local] {host="$host",server_name="$server_name",upstream=$upstream_addr,t=$request_time[u_conn=$upstream_connect_time,u_hdr=$upstream_header_time,u_resp=$upstream_response_time]} "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"'; + access_log /var/log/nginx/access.log combined_vhosts; + ''; + additionalModules = with pkgs.nginxModules; [ moreheaders ]; + virtualHosts = { + #"boorunav.com" = serveDir { path = "/data/nginx/html_boorunav"; }; + # "catgirlsaresexy.com" = serveDir { path = "/data/nginx/html_catgirlsaresexy"; }; + # "sugarcanemc.org" = serveDir { path = "/data/nginx/html_sugarcanemc"; }; +# + #"siliconheaven.thearcanebrony.net" = serveDir { path = "/data/nginx/html_siliconheaven"; }; + #"lfs.thearcanebrony.net" = serveDir { path = "/data/nginx/html_lfs"; }; + #"git.thearcanebrony.net" = serveDir { path = "/data/nginx/html_git"; }; + #"files.thearcanebrony.net" = serveDir { path = "/data/nginx/html_files"; }; + #"spigotav.thearcanebrony.net" = serveDir { path = "/data/nginx/html_spigotav"; }; + #"terra.thearcanebrony.net" = serveDir { path = "/data/nginx/html_terrarchive"; }; + #"vives.thearcanebrony.net" = serveDir { path = "/data/nginx/html_vives"; }; +# + # "git.rory.gay" = serveDir { path = "/data/nginx/html_git"; }; + # "wad.rory.gay" = serveDir { path = "/data/nginx/html_wad"; } // { + # locations."/".extraConfig = "autoindex on; try_files $uri $uri/ /index.html;"; + # }; + # "wad-api.rory.gay" = import ./rory.gay/wad-api.nix; +# + #"thearcanebrony.net" = import ./thearcanebrony.net/root.nix; + # "sentry.thearcanebrony.net" = import ./thearcanebrony.net/sentry.nix; + # "search.thearcanebrony.net" = import ./thearcanebrony.net/search.nix; +# + "rory.gay" = import ./rory.gay/root.nix { inherit config; }; + # "lfs.rory.gay" = serveDir { path = "/data/nginx/html_lfs"; }; +# + # "awooradio.thearcanebrony.net" = import ./thearcanebrony.net/awooradio.nix; + "cgit.rory.gay" = import ./rory.gay/cgit.nix { inherit config; }; + # #"jitsi.rory.gay" = import ./rory.gay/jitsi.nix; +# + # #matrix... + # "conduit.rory.gay" = import ./rory.gay/conduit.nix; + "matrix.rory.gay" = import ./rory.gay/matrix.nix { inherit config; }; + "libmatrix-fed-test.rory.gay" = import ./rory.gay/libmatrix-fed-test.nix { inherit config; }; + "safensound.rory.gay" = import ./rory.gay/safensound.nix { inherit config; }; + "demo.safensound.rory.gay" = import ./rory.gay/demo.safensound.nix { inherit config; }; + "api.safensound.rory.gay" = import ./rory.gay/api.safensound.nix { inherit config; }; + "stream.rory.gay" = import ./rory.gay/stream.nix { inherit config; }; + # "pcpoc.rory.gay" = import ./rory.gay/pcpoc.nix; + # "matrixunittests.rory.gay" = import ./rory.gay/matrixunittests.nix; + # "conduit.matrixunittests.rory.gay" = import ./rory.gay/conduit.matrixunittests.nix; + "mru.rory.gay" = import ./rory.gay/mru.nix { inherit config; }; + "ec.rory.gay" = import ./rory.gay/ec.nix { inherit config; }; + }; + }; + }; + systemd.services.nginx.serviceConfig = { + LimitNOFILE = 5000000; + }; + security.acme.acceptTerms = true; + security.acme.defaults.email = "root@rory.gay"; + + networking.hosts."127.0.0.1" = builtins.attrNames config.services.nginx.virtualHosts; + networking.firewall.allowedTCPPorts = [ 80 443 ]; + networking.firewall.allowedUDPPorts = [ 443 ]; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/api.safensound.nix b/host/Rory-ovh/services/nginx/rory.gay/api.safensound.nix new file mode 100755
index 0000000..b0ff075 --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/api.safensound.nix
@@ -0,0 +1,72 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = !config.virtualisation.isVmVariant; + locations."/" = { + #proxyPass = "http://127.0.0.1:9001"; + proxyPass = "http://localhost:7645"; + extraConfig = '' + if ($request_method = 'OPTIONS') { + more_set_headers 'Access-Control-Allow-Origin: *'; + more_set_headers 'Access-Control-Allow-Methods: *'; + # + # Custom headers and headers various browsers *should* be OK with but aren't + # + more_set_headers 'Access-Control-Allow-Headers: *, Authorization'; + # + # Tell client that this pre-flight info is valid for 20 days + # + more_set_headers 'Access-Control-Max-Age: 1728000'; + more_set_headers 'Content-Type: text/plain; charset=utf-8'; + more_set_headers 'Content-Length: 0'; + return 204; + } + ''; + }; + + locations."= /.well-known/matrix/server".extraConfig = '' + more_set_headers 'Content-Type application/json'; + more_set_headers 'Access-Control-Allow-Origin *'; + return 200 '${builtins.toJSON { "m.server" = "matrix.rory.gay:443"; }}'; + ''; + locations."= /.well-known/matrix/client".extraConfig = '' + more_set_headers 'Content-Type application/json'; + more_set_headers 'Access-Control-Allow-Origin *'; + return 200 '${ + builtins.toJSON { + "m.homeserver".base_url = "https://matrix.rory.gay"; + "org.matrix.msc3575.proxy".url = "https://matrix.rory.gay"; + } + }'; + ''; + locations."= /.well-known/matrix/support".extraConfig = '' + more_set_headers 'Content-Type application/json'; + more_set_headers 'Access-Control-Allow-Origin *'; + return 200 '${ + builtins.toJSON { + admins = [ + { + matrix_id = "@emma:rory.gay"; + role = "admin"; + } + { + matrix_id = "@alicia:rory.gay"; + role = "admin"; + } + { + matrix_id = "@root:rory.gay"; + role = "admin"; + } + { + matrix_id = "@rory:rory.gay"; + role = "admin"; + } + ]; + } + }'; + ''; + + locations."~ ^/(client/|_matrix/client/unstable/org.matrix.msc3575/sync)" = { + proxyPass = "http://localhost:8100"; + }; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/cgit.nix b/host/Rory-ovh/services/nginx/rory.gay/cgit.nix new file mode 100755
index 0000000..7b49a42 --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/cgit.nix
@@ -0,0 +1,14 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = !config.virtualisation.isVmVariant; + root = "/data/git"; + extraConfig = '' + autoindex on; + more_set_headers 'Access-Control-Allow-Origin: *'; + more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS'; + more_set_headers 'Access-Control-Allow-Headers: DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range'; + more_set_headers 'Access-Control-Expose-Headers: Content-Length,Content-Range'; + more_set_headers 'Access-Control-Allow-Credentials: true'; + ''; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/conduit.matrixunittests.nix b/host/Rory-ovh/services/nginx/rory.gay/conduit.matrixunittests.nix new file mode 100755
index 0000000..231d5e3 --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/conduit.matrixunittests.nix
@@ -0,0 +1,16 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = !config.virtualisation.isVmVariant; + http3 = true; + http3_hq = true; + kTLS = true; + extraConfig = '' + brotli off; + ''; + locations = { + "/" = { + proxyPass = "http://192.168.100.15:80"; + }; + }; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/demo.safensound.nix b/host/Rory-ovh/services/nginx/rory.gay/demo.safensound.nix new file mode 100755
index 0000000..f75c78b --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/demo.safensound.nix
@@ -0,0 +1,30 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = !config.virtualisation.isVmVariant; +# quic = true; + http3 = !config.virtualisation.isVmVariant; + http3_hq = !config.virtualisation.isVmVariant; + kTLS = !config.virtualisation.isVmVariant; + root = "/data/nginx/html_safensound_demo"; +# reuseport = true; + extraConfig = '' + brotli off; + brotli_static off; + ''; + locations = { + "/" = { + index = "index.html"; + extraConfig = '' + more_set_headers 'Access-Control-Allow-Origin: *'; + more_set_headers 'Access-Control-Allow-Methods: *'; + more_set_headers 'Access-Control-Allow-Headers: *'; + more_set_headers 'Access-Control-Expose-Headers: *'; + more_set_headers 'Access-Control-Max-Age' 1728000; + + # default to /index.html if file not found + try_files $uri $uri/ /index.html; + ''; + }; + }; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/ec.nix b/host/Rory-ovh/services/nginx/rory.gay/ec.nix new file mode 100755
index 0000000..c50b1f9 --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/ec.nix
@@ -0,0 +1,26 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = !config.virtualisation.isVmVariant; + root = "/data/nginx/html_ec"; + reuseport = true; + extraConfig = '' + brotli off; + brotli_static off; + ''; + locations = { + "/" = { + index = "index.html"; + extraConfig = '' + more_set_headers 'Access-Control-Allow-Origin: *'; + more_set_headers 'Access-Control-Allow-Methods: *'; + more_set_headers 'Access-Control-Allow-Headers: *'; + more_set_headers 'Access-Control-Expose-Headers: *'; + more_set_headers 'Access-Control-Max-Age' 1728000; + + # default to /index.html if file not found + try_files $uri $uri/ /index.html; + ''; + }; + }; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/jitsi.nix b/host/Rory-ovh/services/nginx/rory.gay/jitsi.nix new file mode 100755
index 0000000..9469087 --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/jitsi.nix
@@ -0,0 +1,51 @@ +{ + config, + pkgs, + lib, + ... +}: + +let + overrideJs = + filePath: varName: newContent: appendExtra: + let + oldContent = builtins.readFile filePath; + regex = "var ${varName} = {[^}]*};"; + newJs = builtins.replaceStrings [ regex ] [ "var ${varName} = ${newContent};" ] oldContent; + in + builtins.writeFile filePath newJs; + + cfg = config.services.jitsi-meet; +in +{ + enableACME = true; + addSSL = true; + extraConfig = '' + ssi on; + ''; + locations."@root_path".extraConfig = '' + rewrite ^/(.*)$ / break; + ''; + locations."~ ^/([^/\\?&:'\"]+)$".tryFiles = "$uri @root_path"; + locations."^~ /xmpp-websocket" = { + priority = 100; + proxyPass = "http://localhost:5280/xmpp-websocket"; + proxyWebsockets = true; + }; + locations."=/http-bind" = { + proxyPass = "http://localhost:5280/http-bind"; + extraConfig = '' + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + ''; + }; + locations."=/external_api.js" = lib.mkDefault { + alias = "${pkgs.jitsi-meet}/libs/external_api.min.js"; + }; + locations."=/config.js" = lib.mkDefault { + alias = overrideJs "${pkgs.jitsi-meet}/config.js" "config" (lib.recursiveUpdate defaultCfg cfg.config) cfg.extraConfig; + }; + locations."=/interface_config.js" = lib.mkDefault { + alias = overrideJs "${pkgs.jitsi-meet}/interface_config.js" "interfaceConfig" cfg.interfaceConfig ""; + }; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/libmatrix-fed-test.nix b/host/Rory-ovh/services/nginx/rory.gay/libmatrix-fed-test.nix new file mode 100755
index 0000000..c2909d6 --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/libmatrix-fed-test.nix
@@ -0,0 +1,26 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = !config.virtualisation.isVmVariant; + locations."/" = { + #proxyPass = "http://127.0.0.1:9001"; + proxyPass = "http://localhost:6500"; + extraConfig = '' + if ($request_method = 'OPTIONS') { + more_set_headers 'Access-Control-Allow-Origin: *'; + more_set_headers 'Access-Control-Allow-Methods: *'; + # + # Custom headers and headers various browsers *should* be OK with but aren't + # + more_set_headers 'Access-Control-Allow-Headers: *, Authorization'; + # + # Tell client that this pre-flight info is valid for 20 days + # + more_set_headers 'Access-Control-Max-Age: 1728000'; + more_set_headers 'Content-Type: text/plain; charset=utf-8'; + more_set_headers 'Content-Length: 0'; + return 204; + } + ''; + }; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/matrix-bak.nix b/host/Rory-ovh/services/nginx/rory.gay/matrix-bak.nix new file mode 100755
index 0000000..1af3669 --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/matrix-bak.nix
@@ -0,0 +1,26 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = !config.virtualisation.isVmVariant; + locations."/_matrix" = { + proxyPass = "http://192.168.1.5:8008"; + extraConfig = '' + if ($request_method = 'OPTIONS') { + more_set_headers 'Access-Control-Allow-Origin: *'; + more_set_headers 'Access-Control-Allow-Methods: *'; + # + # Custom headers and headers various browsers *should* be OK with but aren't + # + more_set_headers 'Access-Control-Allow-Headers: *'; + # + # Tell client that this pre-flight info is valid for 20 days + # + more_set_headers 'Access-Control-Max-Age: 1728000'; + more_set_headers 'Content-Type: text/plain; charset=utf-8'; + more_set_headers 'Content-Length: 0'; + return 204; + } + ''; + }; + locations."/_synapse/client".proxyPass = "http://192.168.1.5:8008"; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/matrix.nix b/host/Rory-ovh/services/nginx/rory.gay/matrix.nix new file mode 100755
index 0000000..45a507f --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/matrix.nix
@@ -0,0 +1,72 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = !config.virtualisation.isVmVariant; + locations."/" = { + #proxyPass = "http://127.0.0.1:9001"; + proxyPass = "http://localhost:8008"; + extraConfig = '' + if ($request_method = 'OPTIONS') { + more_set_headers 'Access-Control-Allow-Origin: *'; + more_set_headers 'Access-Control-Allow-Methods: *'; + # + # Custom headers and headers various browsers *should* be OK with but aren't + # + more_set_headers 'Access-Control-Allow-Headers: *, Authorization'; + # + # Tell client that this pre-flight info is valid for 20 days + # + more_set_headers 'Access-Control-Max-Age: 1728000'; + more_set_headers 'Content-Type: text/plain; charset=utf-8'; + more_set_headers 'Content-Length: 0'; + return 204; + } + ''; + }; + + locations."= /.well-known/matrix/server".extraConfig = '' + more_set_headers 'Content-Type application/json'; + more_set_headers 'Access-Control-Allow-Origin *'; + return 200 '${builtins.toJSON { "m.server" = "matrix.rory.gay:443"; }}'; + ''; + locations."= /.well-known/matrix/client".extraConfig = '' + more_set_headers 'Content-Type application/json'; + more_set_headers 'Access-Control-Allow-Origin *'; + return 200 '${ + builtins.toJSON { + "m.homeserver".base_url = "https://matrix.rory.gay"; + "org.matrix.msc3575.proxy".url = "https://matrix.rory.gay"; + } + }'; + ''; + locations."= /.well-known/matrix/support".extraConfig = '' + more_set_headers 'Content-Type application/json'; + more_set_headers 'Access-Control-Allow-Origin *'; + return 200 '${ + builtins.toJSON { + admins = [ + { + matrix_id = "@emma:rory.gay"; + role = "admin"; + } + { + matrix_id = "@alicia:rory.gay"; + role = "admin"; + } + { + matrix_id = "@root:rory.gay"; + role = "admin"; + } + { + matrix_id = "@rory:rory.gay"; + role = "admin"; + } + ]; + } + }'; + ''; + + locations."~ ^/(client/|_matrix/client/unstable/org.matrix.msc3575/sync)" = { + proxyPass = "http://localhost:8100"; + }; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/matrixunittests.nix b/host/Rory-ovh/services/nginx/rory.gay/matrixunittests.nix new file mode 100755
index 0000000..f23f0dd --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/matrixunittests.nix
@@ -0,0 +1,16 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = !config.virtualisation.isVmVariant; + http3 = !config.virtualisation.isVmVariant; + http3_hq = !config.virtualisation.isVmVariant; + kTLS = !config.virtualisation.isVmVariant; + extraConfig = '' + brotli off; + ''; + locations = { + "/" = { + proxyPass = "http://192.168.100.13:80"; + }; + }; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/mru.nix b/host/Rory-ovh/services/nginx/rory.gay/mru.nix new file mode 100755
index 0000000..6e685de --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/mru.nix
@@ -0,0 +1,30 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = !config.virtualisation.isVmVariant; +# quic = true; + http3 = !config.virtualisation.isVmVariant; + http3_hq = !config.virtualisation.isVmVariant; + kTLS = !config.virtualisation.isVmVariant; + root = "/data/nginx/html_mru"; +# reuseport = true; + extraConfig = '' + brotli off; + brotli_static off; + ''; + locations = { + "/" = { + index = "index.html"; + extraConfig = '' + more_set_headers 'Access-Control-Allow-Origin: *'; + more_set_headers 'Access-Control-Allow-Methods: *'; + more_set_headers 'Access-Control-Allow-Headers: *'; + more_set_headers 'Access-Control-Expose-Headers: *'; + more_set_headers 'Access-Control-Max-Age' 1728000; + + # default to /index.html if file not found + try_files $uri $uri/ /index.html; + ''; + }; + }; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/pcpoc.nix b/host/Rory-ovh/services/nginx/rory.gay/pcpoc.nix new file mode 100755
index 0000000..b62c5fe --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/pcpoc.nix
@@ -0,0 +1,15 @@ +{ + enableACME = true; + addSSL = true; + http3 = true; + http3_hq = true; + kTLS = true; + extraConfig = '' + brotli off; + ''; + locations = { + "/" = { + proxyPass = "http://192.168.100.11:80"; + }; + }; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/root.nix b/host/Rory-ovh/services/nginx/rory.gay/root.nix new file mode 100755
index 0000000..a7720ec --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/root.nix
@@ -0,0 +1,49 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = !config.virtualisation.isVmVariant; + root = "/data/nginx/html_rory_gay"; + extraConfig = ''autoindex on;''; + + locations."= /.well-known/matrix/server".extraConfig = '' + more_set_headers 'Content-Type application/json'; + more_set_headers 'Access-Control-Allow-Origin *'; + return 200 '${builtins.toJSON { "m.server" = "matrix.rory.gay:443"; }}'; + ''; + locations."= /.well-known/matrix/client".extraConfig = '' + more_set_headers 'Content-Type application/json'; + more_set_headers 'Access-Control-Allow-Origin *'; + return 200 '${ + builtins.toJSON { + "m.homeserver".base_url = "https://matrix.rory.gay"; + "org.matrix.msc3575.proxy".url = "https://matrix.rory.gay"; + } + }'; + ''; + locations."= /.well-known/matrix/support".extraConfig = '' + more_set_headers 'Content-Type application/json'; + more_set_headers 'Access-Control-Allow-Origin *'; + return 200 '${ + builtins.toJSON { + admins = [ + { + matrix_id = "@emma:rory.gay"; + role = "admin"; + } + { + matrix_id = "@alicia:rory.gay"; + role = "admin"; + } + { + matrix_id = "@root:rory.gay"; + role = "admin"; + } + { + matrix_id = "@rory:rory.gay"; + role = "admin"; + } + ]; + } + }'; + ''; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/safensound.nix b/host/Rory-ovh/services/nginx/rory.gay/safensound.nix new file mode 100755
index 0000000..9208129 --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/safensound.nix
@@ -0,0 +1,30 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = !config.virtualisation.isVmVariant; +# quic = true; + http3 = !config.virtualisation.isVmVariant; + http3_hq = !config.virtualisation.isVmVariant; + kTLS = !config.virtualisation.isVmVariant; + root = "/data/nginx/html_safensound"; +# reuseport = true; + extraConfig = '' + brotli off; + brotli_static off; + ''; + locations = { + "/" = { + index = "index.html"; + extraConfig = '' + more_set_headers 'Access-Control-Allow-Origin: *'; + more_set_headers 'Access-Control-Allow-Methods: *'; + more_set_headers 'Access-Control-Allow-Headers: *'; + more_set_headers 'Access-Control-Expose-Headers: *'; + more_set_headers 'Access-Control-Max-Age' 1728000; + + # default to /index.html if file not found + try_files $uri $uri/ /index.html; + ''; + }; + }; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/stream.nix b/host/Rory-ovh/services/nginx/rory.gay/stream.nix new file mode 100755
index 0000000..caed22f --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/stream.nix
@@ -0,0 +1,34 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = !config.virtualisation.isVmVariant; + locations = { + "/" = { + proxyPass = "http://localhost:1934"; + proxyWebsockets = true; + recommendedProxySettings = true; + extraConfig = '' + proxy_ssl_verify off; +# proxy_set_header Host youthapp.inuits.dev; + proxy_ssl_server_name on; + + more_set_headers 'Access-Control-Allow-Origin: *'; + more_set_headers 'Access-Control-Allow-Methods: *'; + # + # Custom headers and headers various browsers *should* be OK with but aren't + # + more_set_headers 'Access-Control-Allow-Headers: *, Authorization'; + # + # Tell client that this pre-flight info is valid for 20 days + # + more_set_headers 'Access-Control-Max-Age: 1728000'; + + if ($request_method = 'OPTIONS') { + more_set_headers 'Content-Type: text/plain; charset=utf-8'; + more_set_headers 'Content-Length: 0'; + return 204; + } + ''; + }; + }; +} diff --git a/host/Rory-ovh/services/nginx/rory.gay/wad-api.nix b/host/Rory-ovh/services/nginx/rory.gay/wad-api.nix new file mode 100755
index 0000000..ac07547 --- /dev/null +++ b/host/Rory-ovh/services/nginx/rory.gay/wad-api.nix
@@ -0,0 +1,32 @@ +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = true; + locations = { + "/" = { + proxyPass = "https://youthapp.inuits.dev"; + recommendedProxySettings = false; + extraConfig = '' + proxy_ssl_verify off; + proxy_set_header Host youthapp.inuits.dev; + proxy_ssl_server_name on; + + more_set_headers 'Access-Control-Allow-Origin: *'; + more_set_headers 'Access-Control-Allow-Methods: *'; + # + # Custom headers and headers various browsers *should* be OK with but aren't + # + more_set_headers 'Access-Control-Allow-Headers: *, Authorization'; + # + # Tell client that this pre-flight info is valid for 20 days + # + more_set_headers 'Access-Control-Max-Age: 1728000'; + + if ($request_method = 'OPTIONS') { + more_set_headers 'Content-Type: text/plain; charset=utf-8'; + more_set_headers 'Content-Length: 0'; + return 204; + } + ''; + }; + }; +} diff --git a/host/Rory-ovh/services/nginx/thearcanebrony.net/awooradio.nix b/host/Rory-ovh/services/nginx/thearcanebrony.net/awooradio.nix new file mode 100755
index 0000000..c0ca8b0 --- /dev/null +++ b/host/Rory-ovh/services/nginx/thearcanebrony.net/awooradio.nix
@@ -0,0 +1,13 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = true; + locations = { + "/" = { + extraConfig = '' + rewrite ^/api/(.*) /$1 break; + return 200 $request_uri;''; + proxyPass = "http://localhost:4998"; + }; + }; +} diff --git a/host/Rory-ovh/services/nginx/thearcanebrony.net/root.nix b/host/Rory-ovh/services/nginx/thearcanebrony.net/root.nix new file mode 100755
index 0000000..59cba43 --- /dev/null +++ b/host/Rory-ovh/services/nginx/thearcanebrony.net/root.nix
@@ -0,0 +1,41 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = true; + root = "/data/nginx/html_thearcanebrony"; + extraConfig = ''autoindex on;''; + locations = { + "/" = { + #index = "index.html"; + }; + "/destroy" = { + return = "301 https://gitlab.com/KinoshitaProductions/SecureDestroyer/-/raw/master/run"; + }; + "= /.well-known/matrix/support".extraConfig = '' + more_set_headers 'Content-Type application/json'; + more_set_headers 'Access-Control-Allow-Origin *'; + return 200 '${ + builtins.toJSON { + admins = [ + { + matrix_id = "@emma:rory.gay"; + role = "admin"; + } + { + matrix_id = "@alicia:rory.gay"; + role = "admin"; + } + { + matrix_id = "@root:rory.gay"; + role = "admin"; + } + { + matrix_id = "@rory:rory.gay"; + role = "admin"; + } + ]; + } + }'; + ''; + }; +} diff --git a/host/Rory-ovh/services/nginx/thearcanebrony.net/search.nix b/host/Rory-ovh/services/nginx/thearcanebrony.net/search.nix new file mode 100755
index 0000000..cfb4e1c --- /dev/null +++ b/host/Rory-ovh/services/nginx/thearcanebrony.net/search.nix
@@ -0,0 +1,10 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = true; + locations = { + "/" = { + extraConfig = ''rewrite ^ https://thearcanebrony.net/unavailable.html break;''; + }; + }; +} diff --git a/host/Rory-ovh/services/nginx/thearcanebrony.net/sentry.nix b/host/Rory-ovh/services/nginx/thearcanebrony.net/sentry.nix new file mode 100755
index 0000000..8cd0826 --- /dev/null +++ b/host/Rory-ovh/services/nginx/thearcanebrony.net/sentry.nix
@@ -0,0 +1,10 @@ +{ config }: +{ + enableACME = !config.virtualisation.isVmVariant; + addSSL = true; + locations = { + "/" = { + proxyPass = "http://192.168.1.4:9000"; + }; + }; +} diff --git a/host/Rory-ovh/services/postgres.nix b/host/Rory-ovh/services/postgres.nix new file mode 100755
index 0000000..10d1cb7 --- /dev/null +++ b/host/Rory-ovh/services/postgres.nix
@@ -0,0 +1,99 @@ +{ config, pkgs, ... }: + +{ + systemd.tmpfiles.rules = [ "d /data/dedicated/postgres 0750 postgres postgres" ]; + + services.postgresql = { + enable = true; + package = pkgs.postgresql_17_jit; + enableTCPIP = true; + authentication = pkgs.lib.mkOverride 10 '' + # TYPE, DATABASE, USER, ADDRESS, METHOD + local all all trust + host all all 127.0.0.1/32 trust + host all all ::1/128 trust + host discordbots discordbots 192.168.1.2/32 trust + host matrix-synapse-rory-gay matrix-synapse-rory-gay 192.168.1.5/32 trust + host all all 0.0.0.0/0 md5 + ''; + # initialScript = pkgs.writeText "backend-initScript" '' + # CREATE ROLE nixcloud WITH LOGIN PASSWORD 'nixcloud' CREATEDB; + # CREATE DATABASE nixcloud; + # GRANT ALL PRIVILEGES ON DATABASE nixcloud TO nixcloud; + # ''; + dataDir = "/data/dedicated/postgres"; + settings = { + # https://pgconfigurator.cybertec.at/ + max_connections = 2500; + superuser_reserved_connections = 3; + + shared_buffers = if config.virtualisation.isVmVariant then "128MB" else "64GB"; + work_mem = if config.virtualisation.isVmVariant then "64MB" else "32GB"; + maintenance_work_mem = if config.virtualisation.isVmVariant then "512MB" else "8GB"; + huge_pages = "try"; + effective_cache_size = if config.virtualisation.isVmVariant then "1GB" else "64GB"; # was 22 + effective_io_concurrency = 100; + random_page_cost = 1.1; + + # can use this to view stats: SELECT query, total_time, calls, rows FROM pg_stat_statements ORDER BY total_time DESC LIMIT 10; + shared_preload_libraries = "pg_stat_statements"; + track_io_timing = "on"; + track_functions = "pl"; + "pg_stat_statements.max" = "10000"; # additional + "pg_stat_statements.track" = "all"; # additional + + wal_level = "replica"; + max_wal_senders = 0; + synchronous_commit = "on"; # was ond3 + + checkpoint_timeout = "15min"; + checkpoint_completion_target = "0.9"; + max_wal_size = "2GB"; + min_wal_size = "1GB"; + + wal_compression = "off"; + wal_buffers = "-1"; + wal_writer_delay = "500ms"; # was 100 + wal_writer_flush_after = "32MB"; # was 1 + #checkpoint_segments = "64"; # additional + default_statistics_target = "250"; # additional + + bgwriter_delay = "200ms"; + bgwriter_lru_maxpages = "100"; + bgwriter_lru_multiplier = "2.0"; + bgwriter_flush_after = "0"; + + max_worker_processes = "64"; # was 14 + max_parallel_workers_per_gather = "32"; # was 7 + max_parallel_maintenance_workers = "32"; # was 7 + max_parallel_workers = "64"; # was 14 + parallel_leader_participation = "on"; + + enable_partitionwise_join = "on"; + enable_partitionwise_aggregate = "on"; + jit = "on"; + max_slot_wal_keep_size = "1GB"; + track_wal_io_timing = "on"; + maintenance_io_concurrency = "4"; + wal_recycle = "on"; + + }; + }; + + # services.prometheus.exporters.postgres = { + # enable = true; + # port = 9187; + # extraFlags = [ + # "--collector.database_wraparound" + # "--collector.long_running_transactions" + # "--collector.postmaster" + # "--collector.process_idle" + # "--collector.stat_activity_autovacuum" + # "--collector.stat_statements" + # #"--collector.stat_wal_receiver" #we dont have WAL receivers + # "--collector.statio_user_indexes" + # "--collector.xlog_location" + # ]; + # }; + +} diff --git a/host/Rory-ovh/services/prometheus.nix b/host/Rory-ovh/services/prometheus.nix new file mode 100644
index 0000000..9409529 --- /dev/null +++ b/host/Rory-ovh/services/prometheus.nix
@@ -0,0 +1,8 @@ +{ ... }: + +{ + services.prometheus = { + enable = true; + port = 9001; + }; +} diff --git a/host/Rory-ovh/services/safensound.nix b/host/Rory-ovh/services/safensound.nix new file mode 100644
index 0000000..69f301a --- /dev/null +++ b/host/Rory-ovh/services/safensound.nix
@@ -0,0 +1,28 @@ +{ + config, + pkgs, + lib, + ... +}: + +{ + services.mongodb = { + enable = true; + package = pkgs.mongodb-ce; + enableAuth = true; + initialRootPasswordFile = "/etc/mongo-pass"; + #bind_ip = "/run/mongodb.sock"; + extraConfig = '' + net.unixDomainSocket.filePermissions: 0777 + ''; + }; + + services.safensound = { + enable = true; + dbCredentialsPath = "/data/secrets/safensound-mongodb"; + port = 7645; + logRequests = "-"; + logQueries = true; + logAuth = true; + }; +} diff --git a/host/Rory-ovh/services/wireguard/wireguard.nix b/host/Rory-ovh/services/wireguard/wireguard.nix new file mode 100644
index 0000000..af69f66 --- /dev/null +++ b/host/Rory-ovh/services/wireguard/wireguard.nix
@@ -0,0 +1,39 @@ +{ pkgs, ... }: +{ + networking.nat.internalInterfaces = [ "wg0" ]; + networking.firewall = { + allowedUDPPorts = [ 51820 ]; + }; + + systemd.network = { + enable = true; + netdevs = { + "50-wg0" = { + netdevConfig = { + Kind = "wireguard"; + Name = "wg0"; + MTUBytes = "1300"; + }; + wireguardConfig = { + PrivateKeyFile = "/data/secrets/wireguard-keys/private"; + ListenPort = 51820; + RouteTable = "main"; # wg-quick creates routing entries automatically but we must use use this option in systemd. + }; + wireguardPeers = [ + { + PublicKey = "WLHEyWxEXRn/T0b9xk/8XJnuoCX0fXxWKHUjZ+AORGQ="; + AllowedIPs = [ "10.100.0.2" ]; + } + ]; + }; + }; + networks.wg0 = { + matchConfig.Name = "wg0"; + address = [ "10.100.0.1/24" ]; + networkConfig = { + IPMasquerade = "ipv4"; + IPv4Forwarding = true; + }; + }; + }; +}