diff --git a/hosts/nachtigall/apps/matrix-log-config.yaml b/hosts/nachtigall/apps/matrix-log-config.yaml new file mode 100644 index 00000000..555f3aaa --- /dev/null +++ b/hosts/nachtigall/apps/matrix-log-config.yaml @@ -0,0 +1,40 @@ +version: 1 + +formatters: + precise: + format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' + +filters: + context: + (): synapse.util.logcontext.LoggingContextFilter + request: "" + +handlers: + console: + class: logging.StreamHandler + formatter: precise + filters: [context] + +loggers: + synapse: + level: WARNING + + synapse.storage.SQL: + # beware: increasing this to DEBUG will make synapse log sensitive + # information such as access tokens. + level: WARNING + + synapse.http.matrixfederationclient: + level: CRITICAL + synapse.federation.sender.per_destination_queue: + level: CRITICAL + synapse.handlers.device: + level: CRITICAL + synapse.replication.tcp.handler: + level: CRITICAL + shared_secret_authenticator: + level: INFO + +root: + level: WARNING + handlers: [console] diff --git a/hosts/nachtigall/apps/matrix.nix b/hosts/nachtigall/apps/matrix.nix new file mode 100644 index 00000000..d0b2fe24 --- /dev/null +++ b/hosts/nachtigall/apps/matrix.nix @@ -0,0 +1,236 @@ +{ flake, config, pkgs, ... }: +let + publicDomain = "matrix.test.pub.solar"; + serverDomain = "test.pub.solar"; +in { + age.secrets."matrix-synapse-signing-key" = { + file = "${flake.self}/secrets/matrix-synapse-signing-key.age"; + mode = "400"; + owner = "matrix-synapse"; + }; + + age.secrets."matrix-synapse-secret-config.yaml" = { + file = "${flake.self}/secrets/matrix-synapse-secret-config.yaml.age"; + mode = "400"; + owner = "matrix-synapse"; + }; + + services.matrix-synapse = { + enable = true; + settings = { + server_name = serverDomain; + public_baseurl = "https://matrix.test.pub.solar/"; + database = { + name = "psycopg2"; + args = { + host = "/run/postgresql"; + cp_max = 10; + cp_min = 5; + database = "matrix"; + }; + allow_unsafe_locale = false; + txn_limit = 0; + }; + + account_threepid_delegates.msisdn = ""; + alias_creation_rules = [{ + action = "allow"; + alias= "*"; + room_id = "*" ; + user_id = "*"; + }]; + allow_guest_access = false; + allow_public_rooms_over_federation = false; + allow_public_rooms_without_auth = false; + auto_join_rooms = [ + "#community:${serverDomain}" + "#general:${serverDomain}" + ]; + + autocreate_auto_join_rooms = true; + caches.global_factor = 0.5; + + default_room_version = "10"; + disable_msisdn_registration = true; + email = { + app_name = "Matrix"; + client_base_url = "https://chat.pub.solar"; + enable_notifs = true; + enable_tls = true; + # FUTUREWORK: Maybe we should change this + invite_client_location = "https://app.element.io"; + notif_for_new_users = true; + notif_from = "Matrix "; + require_transport_security = false; + smtp_host = "matrix-mailer"; + smtp_port = 8025; + }; + + enable_media_repo = true; + enable_metrics = true; + enable_registration = false; + enable_registration_captcha = false; + enable_registration_without_verification = false; + enable_room_list_search = true; + encryption_enabled_by_default_for_room_type = "off"; + event_cache_size = "100K"; + federation_rr_transactions_per_room_per_second = 50; + forget_rooms_on_leave = true; + include_profile_data_on_invite = true; + instance_map = {}; + limit_profile_requests_to_users_who_share_rooms = false; + + log_config = ./matrix-log-config.yaml; + + max_spider_size = "10M"; + max_upload_size = "50M"; + media_storage_providers = []; + + password_config = { + enabled = false; + localdb_enabled = false; + pepper = ""; + }; + + presencee.enabled = true; + push.include_content = false; + + rc_admin_redaction= { + burst_count = 50; + per_second = 1; + }; + rc_federation= { + concurrent = 3; + reject_limit = 50; + sleep_delay = 500; + sleep_limit = 10; + window_size = 1000; + }; + rc_invites= { + per_issuer= { + burst_count = 10; + per_second = 0.3; + }; + per_room= { + burst_count = 10; + per_second = 0.3; + }; + per_user= { + burst_count = 5; + per_second = 0.003; + }; + }; + rc_joins= { + local= { + burst_count = 10; + per_second = 0.1; + }; + remote= { + burst_count = 10; + per_second = 0.01; + }; + }; + rc_login= { + account= { + burst_count = 3; + per_second = 0.17; + }; + address= { + burst_count = 3; + per_second = 0.17; + }; + failed_attempts= { + burst_count = 3; + per_second = 0.17; + }; + }; + rc_message= { + burst_count = 10; + per_second = 0.2; + }; + rc_registration= { + burst_count = 3; + per_second = 0.17; + }; + redaction_retention_period = "7d"; + redis.enabled = false; + registration_requires_token = false; + registrations_require_3pid = ["email"]; + report_stats = false; + require_auth_for_profile_requests = false; + room_list_publication_rules = [{ + action = "allow"; + alias = "*"; + room_id = "*"; + user_id = "*"; + }]; + + signing_key_path = "/run/agenix/matrix-synapse-signing-key"; + + stream_writers = {}; + trusted_key_servers = [{ server_name = "matrix.org";}]; + turn_allow_guests = false; + turn_uris = [ + "turn:matrix.pub.solar?transport=udp" + "turn:matrix.pub.solar?transport=tcp" + ]; + url_preview_accept_language = [ + "en-US" + "en" + ]; + url_preview_enabled = true; + url_preview_ip_range_blacklist = [ + "127.0.0.0/8" + "10.0.0.0/8" + "172.16.0.0/12" + "192.168.0.0/16" + "100.64.0.0/10" + "192.0.0.0/24" + "169.254.0.0/16" + "192.88.99.0/24" + "198.18.0.0/15" + "192.0.2.0/24" + "198.51.100.0/24" + "203.0.113.0/24" + "224.0.0.0/4" + "::1/128" + "fe80::/10" + "fc00::/7" + "2001:db8::/32" + "ff00::/8" + "fec0::/10" + ]; + + user_directory = { + prefer_local_users = false; + search_all_users = false; + }; + user_ips_max_age = "28d"; + + app_service_config_files = [ + "/var/lib/matrix-synapse/telegram-registration.yaml" + # "/matrix-appservice-irc-registration.yaml" + # "/matrix-appservice-slack-registration.yaml" + # "/hookshot-registration.yml" + # "/matrix-mautrix-signal-registration.yaml" + # "/matrix-mautrix-telegram-registration.yaml" + ]; + }; + + extraConfigFiles = [ + "/run/agenix/matrix-synapse-secret-config.yaml" + + # The registration file is automatically generated after starting the + # appservice for the first time. + # cp /var/lib/mautrix-telegram/telegram-registration.yaml \ + # /var/lib/matrix-synapse/ + # chown matrix-synapse:matrix-synapse \ + # /var/lib/matrix-synapse/telegram-registration.yaml + "/var/lib/matrix-synapse/telegram-registration.yaml" + ]; + + plugins = [ + config.services.matrix-synapse.package.plugins.matrix-synapse-shared-secret-auth + ]; + }; +} diff --git a/hosts/nachtigall/apps/mautrix-telegram.nix b/hosts/nachtigall/apps/mautrix-telegram.nix new file mode 100644 index 00000000..f286bd03 --- /dev/null +++ b/hosts/nachtigall/apps/mautrix-telegram.nix @@ -0,0 +1,211 @@ +{ flake, lib, config, pkgs, ... }: +{ + age.secrets."matrix-mautrix-telegram-env-file" = { + file = "${flake.self}/secrets/matrix-mautrix-telegram-env-file.age"; + mode = "400"; + owner = "matrix-synapse"; + }; + + services.mautrix-telegram = { + enable = true; + environmentFile = "/run/agenix/matrix-mautrix-telegram-env-file"; + settings = { + homeserver = { + # TODO: Use the port from synapse config + address = "http://localhost:8008"; + domain = "test.pub.solar"; + verify_ssl = true; + }; + appservice = { + address = "http://localhost:8009"; + bot_avatar = "mxc://maunium.net/tJCRmUyJDsgRNgqhOgoiHWbX"; + bot_displayname = "Telegram bridge bot"; + bot_username = "telegrambot"; + # TODO: See if we can use postgresql + database = "sqlite:////var/lib/mautrix-telegram/sqlite.db"; + hostname = "0.0.0.0"; + id = "telegram"; + max_body_size = 1; + port = 8009; + provisioning = { + enabled = false; + prefix = "/_matrix/provision/v1"; + shared_secret = "generate"; + }; + public = { + enabled = true; + external = "https://matrix.test.pub.solar/c3c3f34b-29fb-5feb-86e5-98c75ec8214b"; + prefix = "/c3c3f34b-29fb-5feb-86e5-98c75ec8214b"; + }; + }; + bridge = { + alias_template = "telegram_{groupname}"; + allow_matrix_login = true; + # Animated stickers conversion requires additional packages in the + # service's path. + # If this isn't a fresh installation, clearing the bridge's uploaded + # file cache might be necessary (make a database backup first!): + # delete from telegram_file where \ + # mime_type in ('application/gzip', 'application/octet-stream') + animated_sticker = { + args = { + background = "'020202'"; # only for gif, transparency not supported + fps = 30; # only for webm + height = 256; + width = 256; + }; + target = "gif"; + }; + bot_messages_as_notices = true; + bridge_notices = { + default = false; + exceptions = []; + }; + command_prefix = "!tg"; + delivery_error_reports = true; + delivery_receipts = false; + displayname_max_length = 100; + displayname_preference = [ + "full name" + "username" + "phone number" + ]; + displayname_template = "'{displayname} (Telegram)'"; + emote_format = "'* $mention $formatted_body'"; + encryption = { + allow = false; + database = "default"; + default = false; + key_sharing = { + allow = false; + require_cross_signing = false; + require_verification = true; + }; + }; + federate_rooms = true; + filter = { + list = []; + mode = "blacklist"; + }; + image_as_file_size = 10; + initial_power_level_overrides = { + group = {}; + user = {}; + }; + inline_images = false; + max_document_size = 100; + max_initial_member_sync = 10; + max_telegram_delete = 10; + message_formats = { + "m.audio" = "'$sender_displayname sent an audio file: $message'"; + "m.emote" = "'* $sender_displayname $message'"; + "m.file" = "'$sender_displayname sent a file: $message'"; + "m.image" = "'$sender_displayname sent an image: $message'"; + "m.location" = "'$sender_displayname sent a location: $message'"; + "m.notice" = "'$sender_displayname: $message'"; + "m.text" = "'$sender_displayname: $message'"; + "m.video" = "'$sender_displayname sent a video: $message'"; + }; + parallel_file_transfer = false; + plaintext_highlights = false; + private_chat_portal_meta = false; + public_portals = true; + relaybot = { + authless_portals = true; + group_chat_invite = []; + ignore_own_incoming_events = true; + ignore_unbridged_group_chat = true; + private_chat = { + invite = []; + message = "This is a Matrix bridge relaybot and does not support direct chats"; + state_changes = true; + }; + whitelist = []; + whitelist_group_admins = true; + }; + resend_bridge_info = false; + skip_deleted_members = true; + startup_sync = true; + state_event_formats = { + join = "$displayname joined the room."; + leave = "$displayname left the room."; + name_change = "$prev_displayname changed their name to $displayname"; + }; + sync_channel_members = false; + sync_dialog_limit = 30; + sync_direct_chats = false; + sync_matrix_state = true; + sync_with_custom_puppets = true; + telegram_link_preview = true; + username_template = "telegram_{userid}"; + + permissions = { + "test.pub.solar" = "full"; + }; + }; + + logging = { + formatters= { + precise = { + format = "[%(asctime)s] [%(levelname)s@%(name)s] %(message)s"; + }; + }; + handlers = { + console = { + class = "logging.StreamHandler"; + formatter = "precise"; + }; + }; + loggers={ + aiohttp.level = "WARNING"; + mau.level = "WARNING"; + telethon.level = "WARNING"; + }; + root = { + handlers = [ "console" ]; + level = "WARNING"; + }; + version = 1; + }; + + telegram = { + connection = { + flood_sleep_threshold = 60; + request_retries = 5; + retries = 5; + retry_delay = 1; + timeout = 120; + }; + device_info = { + app_version = "auto"; + device_model = "auto"; + lang_code = "en"; + system_lang_code = "en"; + system_version = "auto"; + }; + proxy = { + address = "127.0.0.1"; + password = "''"; + port = 1080; + rdns = true; + type = "disabled"; + username = "''"; + }; + server = { + dc = 2; + enabled = false; + ip = "149.154.167.40"; + port = 80; + }; + }; + }; + }; + + systemd.services.mautrix-telegram.path = with pkgs; [ + lottieconverter # for animated stickers conversion, unfree package + ffmpeg # if converting animated stickers to webm (very slow!) + ]; + systemd.services.mautrix-telegram.serviceConfig = { + User = "matrix-synapse"; + }; +} diff --git a/hosts/nachtigall/default.nix b/hosts/nachtigall/default.nix index 5ee4ba96..a9df98fe 100644 --- a/hosts/nachtigall/default.nix +++ b/hosts/nachtigall/default.nix @@ -18,5 +18,8 @@ ./apps/opensearch.nix ./apps/postgresql.nix ./apps/forgejo.nix + + ./apps/matrix.nix + ./apps/mautrix-telegram.nix ]; } diff --git a/secrets/matrix-mautrix-telegram-env-file.age b/secrets/matrix-mautrix-telegram-env-file.age new file mode 100644 index 00000000..2497dfdf Binary files /dev/null and b/secrets/matrix-mautrix-telegram-env-file.age differ diff --git a/secrets/matrix-synapse-secret-config.yaml.age b/secrets/matrix-synapse-secret-config.yaml.age new file mode 100644 index 00000000..eb1dc12a Binary files /dev/null and b/secrets/matrix-synapse-secret-config.yaml.age differ diff --git a/secrets/matrix-synapse-signing-key.age b/secrets/matrix-synapse-signing-key.age new file mode 100644 index 00000000..51eab61c --- /dev/null +++ b/secrets/matrix-synapse-signing-key.age @@ -0,0 +1,28 @@ +age-encryption.org/v1 +-> ssh-ed25519 iDKjwg DIYhq76lfISisIR1cF5QRAHpUOcY73wh2AAIveZzQEU +AaISTQUQHKZPfI3eOmez1LsANCwMiLae6wNDtdGyrk4 +-> ssh-ed25519 uYcDNw aWo4SN3rJXLWjeQFmHWQsWvq6TZysarvk2/ymPNjSW0 +Z8dFM+4R/rCzVsAQtmeO/ANFdeqkcOixgcfp5Pe9FIY +-> ssh-rsa kFDS0A +fNc11rAe6fUi7DaxEGbU84nJ99DCwv2oSs0EXUtXYU7kSQnPzEMvBUmDtsjc/yJK +JrER6X3EZpStvveHs12T2bD8sC7qvpGDM0/yxQaD/g2sebdl/PSdly3PcKZPmFJn +5a8bdFz6auLoxPtV9Ew83rai7/zSGWomD9MtISmtzofQ6ZUMCTHkyv+JFrSGMlDR +/wAPP4AthjlysLgVnpbFixcFaZKA1825H7yk+i+TvIHIZ5YNhcTlvyos5BnKTbjI +JJffhvEz4I3c+v6Nb6tssFs/WcnuylDQZa3YqHT8zaL/pXWKZKwSTMkXMXdN5/V6 +bKwwyuSepbKgcdnYt3qnSRZcGobAD3LISrkyPuh3/6v6mPxX9eriv8A+cCTVFR+H +tx2EEa0PQpgQX7erCxu8n3marv43e6tF58ULJHoBtEcUs0ov5ereNWJBRL5NcZcZ +1jAg3tJtWFcplghJ8oS4ePrCj87ibNeHUW50zTmpoCWnSdl5coKzPtFRjjWJNf0U +mUAqnoCOVSkpy+5tUbCdo3IhxXPwQp70SkBTKqJhLw7AqmqCSEt8IzO7Nmh8Cra7 +CpRvcqLvOjDNKLpc3FZWcJdZyFoQUd+hjqO3GsmYE+0HQm4Prb9bDqRIyUiGa2y8 +8Z/Ae7T/X2hvr/h8by/JI+f67fj9n88LMBIc2+VF17M +-> ssh-ed25519 YFSOsg 7VxASO8bBrWC66jWnFDr/E4uLrE9Eduk1DrxqKBNeAA +ADu0wFcdyO2+Jzb8nbcBl9RArUrA11+Olr+5wT1NpxI +-> ssh-ed25519 iHV63A 5its014WusI08tPQDHHPngzWaMWwbTFXUr3uRSjmgU4 +PjhSqHE9QtLQsOvkTh44TYsf4dlBxlHA+0hbY0P34rI +-> ssh-ed25519 BVsyTA /0Lg7IgQ+ziQPB8zW/g+b9B5MBUmxl44zHKlPC2qgiM +/nGP+6j9jDh/I0ZW4+nkhVtIRf7rqv0RG+sPoGXq/84 +-> fd]-grease "J/'r +1Gqo8aWuDf5XWFLB+OxHs3sNKf/4Kwv8dXBEtn40oL0uk8UZyUkNaLWZ2/GfdO0t +dT7bm5ihzq/7wJsIoNUgGBDprFAZgcEExno +--- zpUnJCx+HoeJm0KW3PIwljBvp/94VsyKfDQ2GRSOd+4 +1I#C[|)܁:dd 3X'qAokCTT3aBt'k\c&a|:R5 \ No newline at end of file diff --git a/secrets/secrets.nix b/secrets/secrets.nix index bcbe6948..cb063560 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -30,6 +30,9 @@ in { "keycloak-database-password.age".publicKeys = nachtigallKeys ++ baseKeys; "forgejo-database-password.age".publicKeys = nachtigallKeys ++ baseKeys; - "forgejo-mailer-password.age".publicKeys = nachtigallKeys ++ baseKeys; + + "matrix-mautrix-telegram-env-file.age".publicKeys = nachtigallKeys ++ baseKeys; + "matrix-synapse-signing-key.age".publicKeys = nachtigallKeys ++ baseKeys; + "matrix-synapse-secret-config.yaml.age".publicKeys = nachtigallKeys ++ baseKeys; }