initial commit
Some checks failed
Nix CI / build (push) Failing after 31s

This commit is contained in:
Rustam Efimov 2026-04-01 08:50:01 +03:00
commit 30ce0dafc2
No known key found for this signature in database
195 changed files with 8902 additions and 0 deletions

View file

@ -0,0 +1,26 @@
{
config,
lib,
...
}:
let
pgsqlEnable = config.machine.postgresql.enable;
inherit (config.machine.synapse) enable;
in
with lib; mkIf enable {
services.postgresql = with lib; mkIf pgsqlEnable {
ensureUsers = [
{
name = "matrix-synapse";
ensureDBOwnership = true;
}
];
ensureDatabases = [ "matrix-synapse" ];
};
services.matrix-synapse.settings.database = {
name = if pgsqlEnable then "psycopg2" else "sqlite3";
args = with lib; mkIf pgsqlEnable {
host = "/run/postgresql";
};
};
}

View file

@ -0,0 +1,13 @@
{
imports = [
./database.nix
./element.nix
./mail.nix
./nginx.nix
./options.nix
./redis.nix
./secrets.nix
./synapse.nix
./turn.nix
];
}

View file

@ -0,0 +1,64 @@
{
lib,
config,
pkgs,
...
}:
let
inherit (config.machine.synapse.element) domain enable;
elementConfig = {
default_server_config = {
"m.homeserver" = with config.services.matrix-synapse.settings; {
base_url = public_baseurl;
inherit server_name;
};
"m.identity_server" = {
base_url = "";
};
};
disable_custom_urls = false;
disable_guests = true;
disable_login_language_selector = false;
disable_3pid_login = false;
brand = "Element";
default_country_code = "US";
show_labs_settings = true;
features = {
feature_video_rooms = true;
feature_group_calls = true;
feature_element_call_video_rooms = true;
feature_new_device_manager = true;
feature_wysiwyg_composer = true;
};
default_federate = true;
room_directory = with config.services.matrix-synapse.settings; {
servers = [
server_name
"matrix.org"
];
};
setting_defaults = {
breadcrumbs = true;
"MessageComposerInput.autoReplaceEmoji" = true;
sendTypingNotifications = true;
showTypingNotifications = true;
showReadReceipts = true;
showJoinLeaves = false;
urlPreviewsEnabled = true;
};
sso_redirect_options = {
immediate = false;
on_welcome_page = true;
};
};
in
with lib; mkIf enable {
services.nginx.virtualHosts.${domain} = {
enableACME = true;
forceSSL = true;
root = pkgs.element-web.override (_old: {
conf = elementConfig;
});
};
}

39
services/synapse/mail.nix Normal file
View file

@ -0,0 +1,39 @@
{
config,
lib,
sec,
...
}:
let
inherit (config.machine.synapse)
enable
domain
;
address = "noreply@${domain}";
in
with lib; mkIf (enable && config.machine.mail.enable) {
services.matrix-synapse = {
settings = {
admin_contact = address;
registrations_require_3pid = [ "email" ];
email = {
smtp_host = config.machine.mail.fqdn;
smtp_port = 465;
smtp_user = address;
require_transport_security = true;
enable_tls = true;
notif_from = "RuJect Matrix <${address}>";
app_name = "RuJect Matrix";
};
};
};
mailserver = {
domains = [ domain ];
accounts.${address} = {
hashedPasswordFile = sec."mail/serviceHashedPassword".path;
aliases = [ ];
sendOnly = true;
};
};
}

View file

@ -0,0 +1,98 @@
{ config, ... }:
let
inherit (config.machine.synapse) domain port;
maxUploadSize = config.services.matrix-synapse.settings.max_upload_size;
in
{
systemd.services.nginx.serviceConfig.SupplementaryGroups = [ "matrix-synapse" ];
services.nginx = {
appendHttpConfig = ''
limit_req_zone $binary_remote_addr zone=matrix_login:10m rate=1r/s;
limit_req_zone $binary_remote_addr zone=matrix_register:10m rate=1r/m;
limit_req_zone $binary_remote_addr zone=matrix_api:10m rate=20r/s;
limit_req_zone $binary_remote_addr zone=matrix_media:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=matrix_federation:10m rate=50r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
'';
upstreams."matrix-synapse".servers = {
"unix:/run/matrix-synapse/matrix-synapse.sock" = { };
};
virtualHosts.${domain} = {
forceSSL = true;
enableACME = true;
locations = {
# Synapse client API
"/_matrix/client" = {
proxyPass = "http://127.0.0.1:${toString port}";
extraConfig = ''
limit_req zone=matrix_api burst=50 nodelay;
client_max_body_size ${maxUploadSize};
'';
};
# Login endpoint with stricter rate limiting
"~ ^/_matrix/client/(r0|v3)/login$" = {
proxyPass = "http://127.0.0.1:${toString port}";
extraConfig = ''
limit_req zone=matrix_login burst=3 nodelay;
'';
};
# Registration with very strict rate limiting
"~ ^/_matrix/client/(r0|v3)/register" = {
proxyPass = "http://127.0.0.1:${toString port}";
extraConfig = ''
limit_req zone=matrix_register burst=2 nodelay;
'';
};
# Sync endpoint with longer timeout
"~ ^/_matrix/client/(r0|v3|unstable)/sync" = {
proxyPass = "http://127.0.0.1:${toString port}";
extraConfig = ''
limit_req zone=matrix_api burst=50 nodelay;
proxy_read_timeout 600s;
'';
};
# Media
"/_matrix/media" = {
proxyPass = "http://127.0.0.1:${toString port}";
extraConfig = ''
limit_req zone=matrix_media burst=100 nodelay;
client_max_body_size ${maxUploadSize};
'';
};
# Federation
"/_matrix/federation" = {
proxyPass = "http://127.0.0.1:${toString port}";
extraConfig = ''
limit_req zone=matrix_federation burst=100 nodelay;
client_max_body_size 50M;
'';
};
"/_matrix/key" = {
proxyPass = "http://127.0.0.1:${toString port}";
extraConfig = ''
limit_req zone=matrix_federation burst=50 nodelay;
'';
};
# Health check
"= /health" = {
proxyPass = "http://127.0.0.1:${toString port}";
extraConfig = ''
access_log off;
'';
};
# Block admin API from public
"/_synapse/admin".return = "404";
};
};
};
}

View file

@ -0,0 +1,37 @@
{
lib,
config,
...
}:
with lib;
{
options.machine.synapse = {
enable = mkEnableOption "Synapse";
element = {
enable = mkEnableOption "Elemenet web";
domain = mkOption {
type = types.nullOr types.str;
default = "chat.${config.machine.synapse.domain}";
description = "Domain name.";
};
};
domain = mkOption {
type = types.str;
default = "example.com";
description = "Domain name.";
};
port = mkOption {
type = types.port;
default = 8008;
description = "Listen port.";
};
metrics = {
enable = mkEnableOption "Synapse metrics";
port = mkOption {
type = types.port;
default = 9000;
description = "Listen port.";
};
};
};
}

View file

@ -0,0 +1,19 @@
{
config,
lib,
...
}:
let
redisEnable = config.machine.redis.enable;
inherit (config.machine.synapse) enable;
in
with lib; mkIf (redisEnable && enable) {
services.redis.servers.matrix-synapse = {
enable = true;
};
systemd.services.matrix-synapse.serviceConfig.SupplementaryGroups = [ "redis-matrix-synapse" ];
services.matrix-synapse.settings.redis = {
enabled = true;
path = config.services.redis.servers.matrix-synapse.unixSocket;
};
}

View file

@ -0,0 +1,46 @@
{
config,
lib,
...
}:
let
inherit (config.machine.synapse)
enable
;
in
with lib; mkIf enable {
sops.secrets = {
"matrix/registrationSharedSecret" = {
sopsFile = ./../../secrets/common.yaml;
owner = config.users.users.matrix-synapse.name;
inherit (config.users.users.matrix-synapse) group;
restartUnits = [ "matrix-synapse.service" ];
};
"matrix/signingKey" = {
sopsFile = ./../../secrets/common.yaml;
owner = config.users.users.matrix-synapse.name;
inherit (config.users.users.matrix-synapse) group;
restartUnits = [ "matrix-synapse.service" ];
};
"turn/authSecret" = {
sopsFile = ./../../secrets/common.yaml;
owner = config.users.users.turnserver.name;
inherit (config.users.users.turnserver) group;
restartUnits = [ "coturn.service" ];
};
};
sops.templates.matrix-synapse-config = {
owner = config.users.users.matrix-synapse.name;
inherit (config.users.users.matrix-synapse) group;
restartUnits = [ "matrix-synapse.service" ];
content = ''
registration_shared_secret: ${config.sops.placeholder."matrix/registrationSharedSecret"}
turn_shared_secret: ${config.sops.placeholder."turn/authSecret"}
mail:
smtp_pass: ${config.sops.placeholder."mail/servicePassword"}
'';
};
services.matrix-synapse.extraConfigFiles = with lib; mkIf config.machine.synapse.enable [
config.sops.templates.matrix-synapse-config.path
];
}

View file

@ -0,0 +1,94 @@
{
config,
lib,
sec,
...
}:
let
inherit (config.machine.synapse)
domain
enable
port
metrics
;
in
with lib; mkIf enable {
services.matrix-synapse = {
inherit enable;
enableRegistrationScript = true;
settings = {
server_name = domain;
public_baseurl = "https://${domain}";
signing_key_path = sec."matrix/signingKey".path;
listeners = [
{
inherit port;
bind_addresses = [ "127.0.0.1" ];
type = "http";
tls = false;
x_forwarded = true;
resources = [
{
compress = true;
names = [
"client"
"federation"
];
}
];
}
]
++ (optionals metrics.enable [
{
inherit (metrics) port;
bind_addresses = [ "127.0.0.1" ];
type = "metrics";
tls = false;
resources = [
{
names = [ "metrics" ];
}
];
}
]);
enable_metrics = metrics.enable;
enable_registration = true;
enable_registration_without_verification = false;
allow_public_rooms_over_federation = true;
federation_domain_whitelist = [ ];
allow_public_rooms_without_auth = true;
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"
"169.254.0.0/16"
"::1/128"
"fe80::/10"
"fc00::/7"
];
dynamic_thumbnails = true;
max_upload_size = "50M";
media_retention = {
local_media_lifetime = "90d";
remote_media_lifetime = "14d";
};
retention = {
enabled = true;
default_policy.max_lifetime = "180d";
purge_jobs = [
{ interval = "1d"; }
];
};
};
};
}

18
services/synapse/turn.nix Normal file
View file

@ -0,0 +1,18 @@
{
config,
lib,
...
}:
let
inherit (config.machine.coturn) enable;
in
with lib; mkIf (enable && config.machine.coturn.enable) {
services.matrix-synapse.settings = with config.services.coturn; {
turn_uris = [
"turn:${realm}:3478?transport=udp"
"turn:${realm}:3478?transport=tcp"
];
turn_user_lifetime = "1h";
turn_allow_guests = false;
};
}