Self-host your own digital island
at main 6.1 kB view raw
1{ lib, config, pkgs, ... }: 2let 3 cfg = config.services.mautrix-messenger; 4 dataDir = "/var/lib/mautrix-messenger"; 5 registrationFile = "${dataDir}/messenger-registration.yaml"; 6 settingsFile = "${dataDir}/config.json"; 7 settingsFileUnsubstituted = 8 settingsFormat.generate "mautrix-messenger-config-unsubstituted.json" 9 cfg.settings; 10 settingsFormat = pkgs.formats.json { }; 11 appservicePort = 29320; 12 13 mkDefaults = lib.mapAttrsRecursive (n: v: lib.mkDefault v); 14 defaultConfig = { 15 homeserver.address = "http://localhost:8448"; 16 meta.mode = "messenger"; 17 appservice = { 18 hostname = "[::]"; 19 port = appservicePort; 20 database.type = "sqlite3"; 21 database.uri = "${dataDir}/mautrix-messenger.db"; 22 id = "messenger"; 23 bot.username = "messengerbot"; 24 bot.displayname = "Messenger Bridge Bot"; 25 bot.avatar = "mxc://maunium.net/ygtkteZsXnGJLJHRchUwYWak"; 26 as_token = ""; 27 hs_token = ""; 28 }; 29 bridge = { 30 username_template = "messenger_{{.}}"; 31 double_puppet_server_map = { }; 32 login_shared_secret_map = { }; 33 permissions."*" = "relay"; 34 relay.enabled = true; 35 }; 36 logging = { 37 min_level = "info"; 38 writers = lib.singleton { 39 type = "stdout"; 40 format = "pretty-colored"; 41 time_format = " "; 42 }; 43 }; 44 }; 45 46in { 47 options.services.mautrix-messenger = { 48 enable = lib.mkEnableOption (lib.mdDoc 49 "mautrix-messenger, a puppeting/relaybot bridge between Matrix and Messenger."); 50 51 settings = lib.mkOption { 52 type = settingsFormat.type; 53 default = defaultConfig; 54 description = lib.mdDoc '' 55 {file}`config.yaml` configuration as a Nix attribute set. 56 Configuration options should match those described in 57 [example-config.yaml](https://github.com/mautrix/messenger/blob/master/example-config.yaml). 58 ''; 59 example = { 60 appservice = { 61 database = { 62 type = "postgres"; 63 uri = "postgresql:///mautrix_messenger?host=/run/postgresql"; 64 }; 65 id = "messenger"; 66 ephemeral_events = false; 67 }; 68 bridge = { 69 history_sync = { request_full_sync = true; }; 70 private_chat_portal_meta = true; 71 mute_bridging = true; 72 encryption = { 73 allow = true; 74 default = true; 75 require = true; 76 }; 77 provisioning = { shared_secret = "disable"; }; 78 permissions = { "example.com" = "user"; }; 79 }; 80 }; 81 }; 82 83 serviceDependencies = lib.mkOption { 84 type = with lib.types; listOf str; 85 default = lib.optional config.services.matrix-synapse.enable 86 config.services.matrix-synapse.serviceUnit; 87 defaultText = lib.literalExpression '' 88 optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnits 89 ''; 90 description = lib.mdDoc '' 91 List of Systemd services to require and wait for when starting the application service. 92 ''; 93 }; 94 }; 95 96 config = lib.mkIf cfg.enable { 97 98 users.users.mautrix-messenger = { 99 isSystemUser = true; 100 group = "mautrix-messenger"; 101 home = dataDir; 102 description = "Mautrix-Messenger bridge user"; 103 }; 104 105 users.groups.mautrix-messenger = { }; 106 107 services.mautrix-messenger.settings = lib.mkMerge (map mkDefaults [ 108 defaultConfig 109 # Note: this is defined here to avoid the docs depending on `config` 110 { 111 homeserver.domain = config.services.matrix-synapse.settings.server_name; 112 } 113 ]); 114 115 systemd.services.mautrix-messenger = { 116 description = "Mautrix-Messenger Service - A Messenger bridge for Matrix"; 117 118 wantedBy = [ "multi-user.target" ]; 119 wants = [ "network-online.target" ] ++ cfg.serviceDependencies; 120 after = [ "network-online.target" ] ++ cfg.serviceDependencies; 121 122 preStart = '' 123 # substitute the settings file by environment variables 124 # in this case read from EnvironmentFile 125 test -f '${settingsFile}' && rm -f '${settingsFile}' 126 old_umask=$(umask) 127 umask 0177 128 ${pkgs.envsubst}/bin/envsubst \ 129 -o '${settingsFile}' \ 130 -i '${settingsFileUnsubstituted}' 131 umask $old_umask 132 133 # generate the appservice's registration file if absent 134 if [ ! -f '${registrationFile}' ]; then 135 ${pkgs.mautrix-meta}/bin/mautrix-meta \ 136 --generate-registration \ 137 --config='${settingsFile}' \ 138 --registration='${registrationFile}' 139 fi 140 chmod 640 ${registrationFile} 141 142 umask 0177 143 ${pkgs.yq}/bin/yq -s '.[0].appservice.as_token = .[1].as_token 144 | .[0].appservice.hs_token = .[1].hs_token 145 | .[0]' '${settingsFile}' '${registrationFile}' \ 146 > '${settingsFile}.tmp' 147 mv '${settingsFile}.tmp' '${settingsFile}' 148 umask $old_umask 149 ''; 150 151 serviceConfig = { 152 User = "mautrix-messenger"; 153 Group = "mautrix-messenger"; 154 StateDirectory = baseNameOf dataDir; 155 WorkingDirectory = dataDir; 156 ExecStart = '' 157 ${pkgs.mautrix-meta}/bin/mautrix-meta \ 158 --config='${settingsFile}' \ 159 --registration='${registrationFile}' 160 ''; 161 LockPersonality = true; 162 MemoryDenyWriteExecute = true; 163 NoNewPrivileges = true; 164 PrivateDevices = true; 165 PrivateTmp = true; 166 PrivateUsers = true; 167 ProtectClock = true; 168 ProtectControlGroups = true; 169 ProtectHome = true; 170 ProtectHostname = true; 171 ProtectKernelLogs = true; 172 ProtectKernelModules = true; 173 ProtectKernelTunables = true; 174 ProtectSystem = "strict"; 175 Restart = "on-failure"; 176 RestartSec = "30s"; 177 RestrictRealtime = true; 178 RestrictSUIDSGID = true; 179 SystemCallArchitectures = "native"; 180 SystemCallErrorNumber = "EPERM"; 181 SystemCallFilter = [ "@system-service" ]; 182 Type = "simple"; 183 UMask = 27; 184 }; 185 restartTriggers = [ settingsFileUnsubstituted ]; 186 }; 187 }; 188}