# adapted from https://nixos.org/manual/nixos/stable/index.html#module-services-matrix { modulesPath, config, lib, pkgs, ... }: let storage-device = "/dev/disk/by-id/scsi-0DO_Volume_matrix-storage"; storage-dir = "/srv/matrix-data"; slackbridge-dir = "${storage-dir}/slackbridge"; pantalaimon-dir = "${storage-dir}/pantalaimon"; secrets = builtins.fromJSON (builtins.readFile ./secrets.json); slack-reg-source-yaml = (builtins.readFile ./slack-registration.yaml); slack-reg-dest-yaml = pkgs.writeText "slack-registration.yaml" "${slack-reg-source-yaml}"; discord-reg-source-yaml = (builtins.readFile ./discord-registration.yaml); discord-reg-dest-yaml = pkgs.writeText "discord-registration.yaml" "${discord-reg-source-yaml}"; discord-envs-src = (builtins.readFile ./discord_envs); discord-envs-dst = pkgs.writeText "discord_envs" "${discord-envs-src}"; fqdn = "${config.networking.hostName}.${config.networking.domain}"; clientConfig = { "m.homeserver".base_url = "https://${fqdn}"; "server_name" = "${config.networking.domain}"; "m.identity_server" = {}; }; serverConfig."m.server" = "${fqdn}:443"; mkWellKnown = data: '' add_header Content-Type application/json; add_header Access-Control-Allow-Origin *; return 200 '${builtins.toJSON data}'; ''; in { imports = [ "${toString modulesPath}/virtualisation/digital-ocean-image.nix" ]; nixpkgs.config = { packageOverrides = pkgs: { pantalaimon = pkgs.pantalaimon.override { enableDbusUi = false; }; }; }; environment.systemPackages = [ pkgs.jq pkgs.matrix-appservice-slack pkgs.pantalaimon pkgs.olm ]; services.openssh.enable = true; networking.firewall.allowedTCPPorts = [ 22 80 443 ]; users.users.root.openssh.authorizedKeys.keys = [ (builtins.readFile "/home/mike/.ssh/id_mops.pub") ]; ### app specific config # mount DigitalOcean volume for use by postgres fileSystems."${storage-dir}" = { device = storage-device; }; networking = { hostName = "matrix"; domain = "waffle.farm"; }; services.postgresql = { enable = true; dataDir = "${storage-dir}/db"; initialScript = pkgs.writeText "synapse-init.sql" '' CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD '${secrets.matrix.psql_password}'; CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse" TEMPLATE template0 LC_COLLATE = "C" LC_CTYPE = "C"; CREATE DATABASE slack_bridge; CREATE USER slackbridge_user WITH PASSWORD '${secrets.matrix.slack_bridge.psql_password}'; GRANT ALL PRIVILEGES ON DATABASE slack_bridge to slackbridge_user; ''; }; services.nginx = { enable = true; recommendedTlsSettings = true; recommendedOptimisation = true; recommendedGzipSettings = true; recommendedProxySettings = true; virtualHosts = { "${config.networking.domain}" = { enableACME = true; forceSSL = true; locations."= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig; locations."= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig; locations."~ ^/slackbridge" = { proxyPass = "http://localhost:9898"; }; }; # Reverse proxy for Matrix client-server and server-server communication ${fqdn} = { enableACME = true; forceSSL = true; # Or do a redirect instead of the 404, or whatever is appropriate for you. # But do not put a Matrix Web client here! See the Element web section below. locations."/".extraConfig = '' return 301 https://chat.waffle.farm; ''; locations."/_matrix" = { proxyPass = "http://[::1]:8008"; }; locations."/_synapse/client" = { proxyPass = "http://[::1]:8008"; }; }; "chat.${config.networking.domain}" = { enableACME = true; forceSSL = true; serverAliases = [ "chat.${config.networking.domain}" ]; root = pkgs.element-web.override { conf = { default_server_config = clientConfig; }; }; }; }; }; services.matrix-synapse = { enable = true; settings = { server_name = config.networking.domain; allow_public_rooms_over_federation = true; auto_join_rooms = [ "#cryptic-chat:waffle.farm" ]; app_service_config_files = [ "${slack-reg-dest-yaml}" "${discord-reg-dest-yaml}" ]; listeners = [ { port = 8008; bind_addresses = ["::1"]; type = "http"; tls = false; x_forwarded = true; resources = [ { names = [ "client" "federation" ]; compress = true; } ]; } ]; }; extraConfigFiles = [ "${storage-dir}/matrix_cfg" ]; }; security.acme.acceptTerms = true; security.acme.certs = { "${fqdn}".email = "mike@betamike.com"; "${config.networking.domain}".email = "mike@betamike.com"; "chat.${config.networking.domain}".email = "mike@betamike.com"; }; users.users.slackbridge = { home = slackbridge-dir; createHome = true; isNormalUser = true; }; # systemd.services.matrix-appservice-slack = let # slackbridge-config-file = pkgs.writeText "matrix-slack-bridge-config.yaml" '' #homeserver: # server_name: waffle.farm # url: http://[::1]:8008 # media_url: "http://matrix.waffle.farm" # appservice_host: localhost # appservice_port: 8090 #username_prefix: "slack_" # #db: # engine: "postgres" # connectionString: "postgresql://slackbridge_user:${secrets.matrix.slack_bridge.psql_password}@localhost/slack_bridge" # #matrix_admin_room: "!tuUJADDNODYliJTxYK:waffle.farm" # #rtm: # enable: true # logging: "debug" # #slack_hook_port: 9898 #inbound_uri_prefix: "https://waffle.farm/slackbridge/" # ## Optional. Allow users to add channels dynamically by using oauth, or puppet themselves. ## #oauth2: # client_id: "4494054004.1702274627236" # client_secret: "${secrets.matrix.slack_bridge.client_secret}" # redirect_prefix: "https://waffle.farm/slackbridge/oauth" # ## Optional. Enable metrics reporting on http://0.0.0.0:bridgePort/metrics which can be scraped by prometheus #enable_metrics: true # #provisioning: # enabled: true # require_public_room: false # allow_private_channels: true # limits: # room_count: 20 # team_count: 1 # #puppeting: # enabled: true # onboard_users: true # #logging: # console: "debug" # #bot_profile: # displayname: "Slack Bridger" # #team_sync: # T04EJ1L04: # channels: # enabled: true # whitelist: # # bot-test # - C04FKFUHK # # generic-gaming # - C2EEUE9UY # # alias_prefix: "slack_" # users: # enabled: true # # default for all other teams # all: # channels: # enabled: false # #encryption: # enabled: true # pantalaimon_url: "http://localhost:8009" # ''; # in { # enable = false; # description = "matrix-appservice-slack daemon"; # wantedBy = [ "multi-user.target" ]; # serviceConfig = { # Type = "simple"; # ExecStart = "${pkgs.matrix-appservice-slack}/bin/matrix-appservice-slack -c ${slackbridge-config-file} -f ${slack-reg-dest-yaml} -p 8090"; # User = "slackbridge"; # Restart = "always"; # }; # }; users.users.pantalaimon = { home = pantalaimon-dir; createHome = true; isNormalUser = true; }; systemd.services.pantalaimon = let pantalaimon-config-file = pkgs.writeText "pantalaimon.conf" '' [local-matrix] Homeserver = http://localhost:8008 ListenAddress = localhost ListenPort = 8009 Notifications = off UseKeyring = no IgnoreVerification = True ''; in { enable = true; description = "pantalaimon daemon"; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "simple"; ExecStart = "${pkgs.pantalaimon}/bin/pantalaimon -c ${pantalaimon-config-file} --data-path ${pantalaimon-dir}"; User = "pantalaimon"; Restart = "always"; }; }; # services.matrix-appservice-discord = { # enable = true; # settings = { # bridge = { # domain = "waffle.farm"; # homeserverUrl = "https://matrix.waffle.farm"; # enableSelfServiceBridging = true; # disableJoinLeaveNotifications = true; # disableInviteNotifications = true; # }; # }; # url = "http://localhost:8008"; # environmentFile = "${discord-envs-dst}"; # }; }