diff --git a/hosts/tsuki/services/matrix/bridges/matrix-appservice-irc.nix b/hosts/tsuki/services/matrix/bridges/matrix-appservice-irc.nix index 9f9f8fe..f06ade7 100644 --- a/hosts/tsuki/services/matrix/bridges/matrix-appservice-irc.nix +++ b/hosts/tsuki/services/matrix/bridges/matrix-appservice-irc.nix @@ -1,6 +1,54 @@ -{ config, ... }: let +{ config, pkgs, lib, ... }: let cfg = config.services.matrix-appservice-irc; in { + sops = { + secrets = { + "matrix/bridges/irc/id" = {}; + "matrix/bridges/irc/hs_token" = {}; + "matrix/bridges/irc/as_token" = {}; + }; + + templates."matrix-appservice-irc-registration.yml" = { + owner = "matrix-appservice-irc"; + group = "matrix-synapse"; + mode = "0440"; + file = let + inherit (config.sops) placeholder; + in (pkgs.formats.yaml {}).generate "matrix-appservice-irc-registration.yml" { + id = placeholder."matrix/bridges/irc/id"; + hs_token = placeholder."matrix/bridges/irc/hs_token"; + as_token = placeholder."matrix/bridges/irc/as_token"; + url = cfg.registrationUrl; + sender_localpart = cfg.localpart; + "de.sorunome.msc2409.push_ephemeral" = true; + protocols = [ "irc" ]; + namespaces = { + aliases = [ + { + exclusive = true; + regex = "#lainchanirc_.*:nani\\.wtf"; + } + { + exclusive = true; + regex = "#liberairc_.*:nani\\.wtf"; + } + ]; + users = [ + { + exclusive = true; + regex = "@lainanon_.*:nani\\.wtf"; + } + { + exclusive = true; + regex = "@liberauser_.*:nani\\.wtf"; + } + ]; + }; + rate_limited = false; + }; + }; + }; + services.matrix-appservice-irc = { enable = true; registrationUrl = "http://localhost:${toString cfg.port}"; @@ -14,64 +62,145 @@ in { database = { engine = "postgres"; + # TODO: use unix socket connectionString = "postgres://matrix-appservice-irc:@localhost:${toString config.services.postgresql.port}/matrix-appservice-irc?sslmode=disable"; }; - ircService.servers."irc.lainchan.org" = { - name = "lainchan"; - port = 6697; - ssl = true; - networkId = "ircLainchanOrg"; + ircService = { + mediaProxy.publicUrl = "https://irc-matrix.nani.wtf/media"; - botConfig.enable = false; + servers = { + "irc.libera.chat" = { + name = "libera"; + port = 6697; + ssl = true; + networkId = "ircLiberaChat"; - dynamicChannels = { - enabled = true; - createAlias = true; - aliasTemplate = "#lainchanirc_$CHANNEL"; - published = true; - useHomeserverDirectory = true; - joinRule = "public"; - federate = true; - }; + botConfig.enable = false; - matrixClients = { - userTemplate = "@lainanon_$NICK"; - }; - - ircClients = { - nickTemplate = "$LOCALPART[m]"; - allowNickChanges = true; - }; - - membershipLists = { - enabled = true; - global = { - ircToMatrix = { - initial = true; - incremental = true; + dynamicChannels = { + enabled = true; + createAlias = true; + aliasTemplate = "#liberairc_$CHANNEL"; + published = true; + useHomeserverDirectory = true; + joinRule = "public"; + federate = true; }; - matrixToIrc = { - initial = true; - incremental = true; + + matrixClients = { + userTemplate = "@liberauser_$NICK"; }; + + ircClients = { + nickTemplate = "$LOCALPART[m]"; + allowNickChanges = true; + }; + + membershipLists = { + enabled = true; + global = { + ircToMatrix = { + initial = true; + incremental = true; + }; + matrixToIrc = { + initial = true; + incremental = true; + }; + }; + }; + + permissions."@h7x4:nani.wtf" = "admin"; + + # TODO: Port forward + ident.enable = true; + + # TODO: Metrics + }; + + "irc.lainchan.org" = { + name = "lainchan"; + port = 6697; + ssl = true; + networkId = "ircLainchanOrg"; + + botConfig.enable = false; + + dynamicChannels = { + enabled = true; + createAlias = true; + aliasTemplate = "#lainchanirc_$CHANNEL"; + published = true; + useHomeserverDirectory = true; + joinRule = "public"; + federate = true; + }; + + matrixClients = { + userTemplate = "@lainanon_$NICK"; + }; + + ircClients = { + nickTemplate = "$LOCALPART[m]"; + allowNickChanges = true; + }; + + membershipLists = { + enabled = true; + global = { + ircToMatrix = { + initial = true; + incremental = true; + }; + matrixToIrc = { + initial = true; + incremental = true; + }; + }; + }; + + permissions."@h7x4:nani.wtf" = "admin"; + + # TODO: Port forward + ident.enable = true; + + # TODO: Metrics }; }; - - permissions."@h7x4:nani.wtf" = "admin"; - - # TODO: Port forward - ident.enable = true; - - # TODO: Metrics }; }; }; + services.matrix-synapse-next.settings.app_service_config_files = [ + config.sops.templates."matrix-appservice-irc-registration.yml".path + ]; + systemd.services.matrix-appservice-irc = { + enableStrictShellChecks = false; requires = [ "matrix-synapse.service" "postgresql.service" ]; + + serviceConfig.BindReadOnlyPaths = [ + "${config.sops.templates."matrix-appservice-irc-registration.yml".path}:/var/lib/matrix-appservice-irc/registration.yml" + ]; + + preStart = lib.mkForce '' + umask 077 + # Generate key for crypting passwords + if ! [ -f "${cfg.settings.ircService.passwordEncryptionKeyPath}" ]; then + ${pkgs.openssl}/bin/openssl genpkey \ + -out "${cfg.settings.ircService.passwordEncryptionKeyPath}" \ + -outform PEM \ + -algorithm RSA \ + -pkeyopt "rsa_keygen_bits:${toString cfg.passwordEncryptionKeyLength}" + fi + + if ! [ -f "${cfg.settings.ircService.mediaProxy.signingKeyPath}"]; then + ${lib.getExe pkgs.nodejs} ${pkgs.matrix-appservice-irc}/lib/generate-signing-key.js > "${cfg.settings.ircService.mediaProxy.signingKeyPath}" + fi + ''; }; } diff --git a/hosts/tsuki/services/matrix/default.nix b/hosts/tsuki/services/matrix/default.nix index bf0c8b0..01b32ce 100644 --- a/hosts/tsuki/services/matrix/default.nix +++ b/hosts/tsuki/services/matrix/default.nix @@ -73,12 +73,6 @@ }; }; - # TODO: Figure out a way to do this declaratively. - # The files need to be owned by matrix-synapse - app_service_config_files = [ - "/var/lib/matrix-synapse/irc-registration.yml" - ]; - # redis.enabled = true; max_upload_size = "100M"; dynamic_thumbnails = true; diff --git a/hosts/tsuki/services/nginx/default.nix b/hosts/tsuki/services/nginx/default.nix index fabdfc0..d6c70df 100644 --- a/hosts/tsuki/services/nginx/default.nix +++ b/hosts/tsuki/services/nginx/default.nix @@ -46,6 +46,7 @@ "headscale".servers."localhost:${s srv.headscale.port}" = { }; "hedgedoc".servers."unix:${srv.hedgedoc.settings.path}" = { }; "idrac".servers."10.0.0.201" = { }; + "irc-matrix-bridge-media".servers."localhost:${s srv.matrix-appservice-irc.settings.ircService.mediaProxy.bindPort}" = { }; "kanidm".servers."localhost:8300" = { }; "osuchan".servers."localhost:${s srv.osuchan.port}" = { }; "plex".servers."localhost:32400" = { }; @@ -150,7 +151,9 @@ enableACME = lib.mkForce false; locations."/_synapse".proxyPass = "http://$synapse_backend"; }) - (host ["madmin"] { root = "${pkgs.synapse-admin}/"; }) + (proxy ["irc-matrix"] "http://irc-matrix-bridge-media" {}) + + # (host ["madmin"] { root = "${pkgs.synapse-admin}/"; }) # (host ["cache"] { root = "/var/lib/nix-cache"; }) # (proxy ["slack-bot"] "http://localhost:9898" {}) (proxy ["atuin"] "http://atuin" {}) diff --git a/secrets/tsuki.yaml b/secrets/tsuki.yaml index 0ef227a..6d890a8 100644 --- a/secrets/tsuki.yaml +++ b/secrets/tsuki.yaml @@ -26,6 +26,12 @@ postgres: matrix_synapse: ENC[AES256_GCM,data:hg3ubE2GdxgX6+1wcAsvKzFzeUXGSftWYgiH/dhP12g=,iv:9/DwL7JwKsgSHIEp5ECCAgnBd1yg7KHAIOLrQzsFb04=,tag:Vkh+r/RmC+tH5kTQhw+vwA==,type:str] paperless: password: ENC[AES256_GCM,data:Ey1Y/0e/DxB42aSvbw+mrGUmuA6i0fQ6sAKwW7mSqfA=,iv:lHSG0sdkY5Ag5r4PVFmdOpMyzAoDv0Ech5aKs9yUQPc=,tag:KA89xKeATNOoPXTmO8IL3w==,type:str] +matrix: + bridges: + irc: + id: ENC[AES256_GCM,data:OugWObu794xODuagQTWaX+q60+gbnQfxJK2YEn4QbvS17PUyKPfNg04L9pV9KJvBVRGY3K49M4SNiFdRbMyQbg==,iv:FZaXXBCNjYkO/oECFC8ECt4JQ3VCN+IciFclZs8x0LI=,tag:sbHUvA3cWtoj4RSPAjYzfA==,type:str] + hs_token: ENC[AES256_GCM,data:De/ARHF65mJIXZ/N8BmAi0S/F0tC06PkuPATwNm+VzngJCTSxVQnkDZAmqnutQMaHP9ZgJrdCQ7UDCsQhSldEw==,iv:am9m1Fcp1Ale4eH9yknieHL2AinecSrCoqnVPJJqJ1Q=,tag:s8gXMt5CB6W0iuBx6IJ2GQ==,type:str] + as_token: ENC[AES256_GCM,data:dT2SesB0kKOdtl8EbSQS7uTX05/cm+6jOAkMlL0liSfttZElTWcA0YXE7X3Xl8hiy5vB0ONS9dA/7RQWKMG1Tw==,iv:icVAE0G1XiQlJpeN9W20MQ3lRDBvnptS5Sj8xiRNa2w=,tag:P8gekOyAhOhfGIUd1fSyKw==,type:str] matrix_synapse: oauth2_secret: ENC[AES256_GCM,data:Mxzhek6YeRg6lgGvGzrmJz9EakT4sLE5Gw0oyHzF9TjybtjjRmUK4XeEDg8yx2Nt,iv:f656nD6ziJantu7ihmfYvJzxZ1ytvbVS3hezSU75g5A=,tag:G3cwIxcWxLOVAmqmyHDVTg==,type:str] registration_secret: ENC[AES256_GCM,data:Sc5piAESWk9HUe3ZOQ+7ZB9aCZwjTdFrfYkU+XFuXGUZ3xCkCt7QDPmDQBIs+lYOLV9Y165cObKDgMNHBaMkRQ5wXVBrd0l9js70h9LC3IGuK+BOa5tZa4u0zku4zStRuN7xCeGNeAWFOPCQ4a5rQMqbDz6iwWkMQvlHqwzBYtP7PuTuAocwkjlo+3AOnw92DjY4xODPgHR7w4rNSvoSZIUjlAIk3yyHNLV68UiTPoJ5lUqGleLznCpqjLhpxAycfEbWUXCNx8Z5oJ+czptWzhb/hhjH/SgeMvflk8KFwJAYBXxA+YgM+unlWS500OGsgYIbhPyvSzSrs1JkDQBVXA==,iv:/Q4gTEe6WU7XID2ayCFq6xmF6J5UrQw4OjmpU4dhZSA=,tag:kLTdqoanqUAlVrRcKZRxcw==,type:str] @@ -47,8 +53,8 @@ sops: MThmQ1Iza0F6Q0Y4N1JpT2V5a0FrTGMKIzpNe4dyCLuyKjjXjadZepRYvULr3j3i 7SSwFgVvESj0aVwcGMW1swkhdb2evZgcghhrJpiK8kKIPrWEuFiCcw== -----END AGE ENCRYPTED FILE----- - lastmodified: "2024-06-25T17:16:35Z" - mac: ENC[AES256_GCM,data:/7giUW/ZvBzpMZv4cmYawhQpz4cxOMrswRT1E6B5jO4nSUtViVT2FmobWcYL0WFrSETU7ivuClKeyWMfJSRhg7FHrcoJa/O2jYvj1IVmXm/TsZPvX0wdIH38aIjxGSh6MwOOauPMKwmeRTknucAPitGGH9/jXteoAGy+D9Fo+ns=,iv:bUFT++JGgJJ2WAtDQH8CB0rUllTp8L0Q2eKurtxMhXo=,tag:MR8CTopTIYoSGjlX1wvHGg==,type:str] + lastmodified: "2024-11-28T14:01:15Z" + mac: ENC[AES256_GCM,data:x5EUjXx2SeNWkxeMDiYtWCz938dPZv5zlxTjGf4ewWnJ6FJP6GAuY+aKucK9L21AlbQ39osTPRbH/fTLBP/hmZM5yvarFmelfhFZzXyRj1t4USy8Ms+VwwelWcG0WClbMGVT/SUCvyK5IoUL6J4ZYC1aqAPr3q8MR/y/wYW5QPU=,iv:bF24zQk0+G/EtBoIvlxKZz6v/Ud1URguExOJg2Nf5O0=,tag:0VAzdDyB8MgQhUDjz7S1jQ==,type:str] pgp: - created_at: "2024-06-25T17:16:27Z" enc: |- @@ -71,4 +77,4 @@ sops: -----END PGP MESSAGE----- fp: F7D37890228A907440E1FD4846B9228E814A2AAC unencrypted_suffix: _unencrypted - version: 3.8.1 + version: 3.9.1