Matrix packages (mautrix-*, matrix-continuwuity) only exist in nixpkgs-unstable, not in nixpkgs 24.05 stable. This commit updates all module defaults and references to use pkgs-unstable. Changes: - Add pkgs-unstable to module function signatures (4 modules) - Update package option defaults from pkgs.* to pkgs-unstable.* - Configure pkgs-unstable in flake.nix to permit olm-3.2.16 - Add VM config permittedInsecurePackages for olm (mautrix dependency) The olm library is deprecated with known CVEs but required by mautrix bridges. This is acceptable for testing; production should migrate to newer cryptography implementations when available. This maintains our stable base system (NixOS 24.05) while using unstable only for Matrix ecosystem packages under active development.
308 lines
8.7 KiB
Nix
308 lines
8.7 KiB
Nix
# Development services module - Matrix, Forgejo, and Slack bridge
|
|
{ config, pkgs, pkgs-unstable, lib, ... }:
|
|
|
|
with lib;
|
|
|
|
let
|
|
cfg = config.services.dev-platform;
|
|
in
|
|
{
|
|
options.services.dev-platform = {
|
|
enable = mkEnableOption "development platform with Matrix and Forgejo";
|
|
|
|
domain = mkOption {
|
|
type = types.str;
|
|
default = "localhost";
|
|
description = "Base domain for services";
|
|
};
|
|
|
|
matrix = {
|
|
enable = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = "Enable Matrix server";
|
|
};
|
|
|
|
serverName = mkOption {
|
|
type = types.str;
|
|
default = cfg.domain;
|
|
description = "Matrix server name";
|
|
};
|
|
|
|
port = mkOption {
|
|
type = types.port;
|
|
default = 8008;
|
|
description = "Matrix server port";
|
|
};
|
|
};
|
|
|
|
forgejo = {
|
|
enable = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = "Enable Forgejo git service";
|
|
};
|
|
|
|
subdomain = mkOption {
|
|
type = types.str;
|
|
default = "git";
|
|
description = "Subdomain for Forgejo";
|
|
};
|
|
|
|
port = mkOption {
|
|
type = types.port;
|
|
default = 3000;
|
|
description = "Forgejo port";
|
|
};
|
|
};
|
|
|
|
slackBridge = {
|
|
enable = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = "Enable Slack bridge";
|
|
};
|
|
|
|
workspace = mkOption {
|
|
type = types.str;
|
|
default = "";
|
|
description = "Slack workspace name";
|
|
};
|
|
|
|
port = mkOption {
|
|
type = types.port;
|
|
default = 29319;
|
|
description = "Slack bridge port";
|
|
};
|
|
};
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
# PostgreSQL for Forgejo and bridge services (Matrix uses RocksDB)
|
|
services.postgresql = {
|
|
enable = true;
|
|
ensureDatabases = [
|
|
"forgejo"
|
|
] ++ optional cfg.slackBridge.enable "mautrix_slack";
|
|
|
|
ensureUsers = [
|
|
{
|
|
name = "forgejo";
|
|
ensureDBOwnership = true;
|
|
}
|
|
] ++ optional cfg.slackBridge.enable {
|
|
name = "mautrix_slack";
|
|
ensureDBOwnership = true;
|
|
};
|
|
};
|
|
|
|
# Matrix Continuwuity server
|
|
systemd.services.matrix-continuwuity = mkIf cfg.matrix.enable {
|
|
description = "Continuwuity Matrix homeserver";
|
|
after = [ "network.target" ];
|
|
wants = [ "network-online.target" ];
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
preStart = ''
|
|
# Generate config file at runtime with secret injection from systemd credentials
|
|
cat > /var/lib/matrix-continuwuity/continuwuity.toml <<EOF
|
|
[global]
|
|
server_name = "${cfg.matrix.serverName}"
|
|
address = "127.0.0.1"
|
|
port = ${toString cfg.matrix.port}
|
|
allow_registration = true
|
|
registration_token = "$(cat $CREDENTIALS_DIRECTORY/matrix-registration-token)"
|
|
allow_encryption = true
|
|
allow_federation = false
|
|
database_backend = "rocksdb"
|
|
database_path = "/var/lib/matrix-continuwuity/db/"
|
|
log = "info"
|
|
admin_room_tag = "m.server_notice"
|
|
EOF
|
|
'';
|
|
|
|
serviceConfig = {
|
|
Type = "simple";
|
|
DynamicUser = true;
|
|
StateDirectory = "matrix-continuwuity";
|
|
WorkingDirectory = "/var/lib/matrix-continuwuity";
|
|
|
|
# Load secrets via systemd credentials (proper way for DynamicUser)
|
|
LoadCredential = "matrix-registration-token:/run/secrets/matrix-registration-token";
|
|
|
|
ExecStart = "${pkgs-unstable.matrix-continuwuity}/bin/conduwuit -c /var/lib/matrix-continuwuity/continuwuity.toml";
|
|
|
|
Restart = "always";
|
|
RestartSec = "10s";
|
|
|
|
# Security hardening
|
|
NoNewPrivileges = true;
|
|
ProtectSystem = "strict";
|
|
ProtectHome = true;
|
|
PrivateTmp = true;
|
|
ProtectKernelTunables = true;
|
|
ProtectKernelModules = true;
|
|
ProtectControlGroups = true;
|
|
};
|
|
};
|
|
|
|
# Forgejo git service
|
|
services.forgejo = mkIf cfg.forgejo.enable {
|
|
enable = true;
|
|
stateDir = "/var/lib/forgejo";
|
|
|
|
database = {
|
|
type = "postgres";
|
|
host = "/run/postgresql";
|
|
name = "forgejo";
|
|
user = "forgejo";
|
|
createDatabase = false; # We handle this with ensureDatabases
|
|
};
|
|
|
|
settings = {
|
|
server = {
|
|
DOMAIN = "${cfg.forgejo.subdomain}.${cfg.domain}";
|
|
ROOT_URL = "https://${cfg.forgejo.subdomain}.${cfg.domain}";
|
|
PROTOCOL = "http";
|
|
HTTP_ADDR = "127.0.0.1";
|
|
HTTP_PORT = cfg.forgejo.port;
|
|
};
|
|
|
|
service = {
|
|
DISABLE_REGISTRATION = true; # Disable public registration
|
|
DEFAULT_KEEP_EMAIL_PRIVATE = true;
|
|
DEFAULT_ALLOW_CREATE_ORGANIZATION = true;
|
|
};
|
|
|
|
log = {
|
|
LEVEL = "Info";
|
|
MODE = "console";
|
|
};
|
|
|
|
repository = {
|
|
DEFAULT_BRANCH = "main";
|
|
};
|
|
|
|
ui = {
|
|
DEFAULT_THEME = "arc-green";
|
|
};
|
|
|
|
# Enable Actions for CI/CD
|
|
actions = {
|
|
ENABLED = true;
|
|
};
|
|
};
|
|
|
|
lfs.enable = true;
|
|
};
|
|
|
|
# mautrix-slack bridge
|
|
services.mautrix-slack = mkIf cfg.slackBridge.enable {
|
|
enable = true;
|
|
package = pkgs-unstable.mautrix-slack or (pkgs-unstable.callPackage ../pkgs/mautrix-slack {});
|
|
|
|
matrix = {
|
|
homeserverUrl = "http://localhost:${toString cfg.matrix.port}";
|
|
serverName = cfg.matrix.serverName;
|
|
};
|
|
|
|
appservice = {
|
|
port = cfg.slackBridge.port;
|
|
hostname = "127.0.0.1";
|
|
};
|
|
|
|
database = {
|
|
type = "postgres";
|
|
uri = "postgresql:///mautrix_slack?host=/run/postgresql";
|
|
};
|
|
};
|
|
|
|
# Basic Nginx reverse proxy
|
|
services.nginx = {
|
|
enable = true;
|
|
recommendedProxySettings = true;
|
|
recommendedTlsSettings = true;
|
|
recommendedOptimisation = true;
|
|
recommendedGzipSettings = true;
|
|
|
|
# Rate limiting for login endpoints
|
|
appendHttpConfig = ''
|
|
limit_req_zone $binary_remote_addr zone=logins:10m rate=5r/m;
|
|
'';
|
|
|
|
virtualHosts = {
|
|
# Matrix endpoints
|
|
"${cfg.domain}" = mkIf cfg.matrix.enable {
|
|
enableACME = true;
|
|
forceSSL = true;
|
|
extraConfig = ''
|
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
|
'';
|
|
locations = {
|
|
"~ ^/_matrix/client/(r0|v3)/login" = {
|
|
proxyPass = "http://localhost:${toString cfg.matrix.port}";
|
|
proxyWebsockets = true;
|
|
extraConfig = ''
|
|
limit_req zone=logins burst=10 nodelay;
|
|
'';
|
|
};
|
|
"/_matrix" = {
|
|
proxyPass = "http://localhost:${toString cfg.matrix.port}";
|
|
proxyWebsockets = true;
|
|
};
|
|
"/.well-known/matrix/server" = {
|
|
extraConfig = ''
|
|
add_header Content-Type application/json;
|
|
return 200 '{"m.server": "${cfg.matrix.serverName}:443"}';
|
|
'';
|
|
};
|
|
"/.well-known/matrix/client" = {
|
|
extraConfig = ''
|
|
add_header Content-Type application/json;
|
|
add_header Access-Control-Allow-Origin *;
|
|
return 200 '{"m.homeserver": {"base_url": "https://${cfg.domain}"}}';
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
|
|
# Forgejo git service (subdomain-based, requires DNS)
|
|
"${cfg.forgejo.subdomain}.${cfg.domain}" = mkIf cfg.forgejo.enable {
|
|
enableACME = true;
|
|
forceSSL = true;
|
|
extraConfig = ''
|
|
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
|
'';
|
|
locations."/user/login" = {
|
|
proxyPass = "http://localhost:${toString cfg.forgejo.port}";
|
|
proxyWebsockets = true;
|
|
extraConfig = ''
|
|
limit_req zone=logins burst=10 nodelay;
|
|
'';
|
|
};
|
|
locations."/user/sign_up" = {
|
|
proxyPass = "http://localhost:${toString cfg.forgejo.port}";
|
|
proxyWebsockets = true;
|
|
extraConfig = ''
|
|
limit_req zone=logins burst=10 nodelay;
|
|
'';
|
|
};
|
|
locations."/" = {
|
|
proxyPass = "http://localhost:${toString cfg.forgejo.port}";
|
|
proxyWebsockets = true;
|
|
extraConfig = ''
|
|
client_max_body_size 512M;
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
# Systemd tmpfiles for data directories
|
|
# Note: matrix-continuwuity directory managed by StateDirectory with DynamicUser
|
|
systemd.tmpfiles.rules = [
|
|
"d /var/lib/forgejo 0750 forgejo forgejo -"
|
|
] ++ optional cfg.slackBridge.enable
|
|
"d /var/lib/mautrix-slack 0750 mautrix_slack mautrix_slack -";
|
|
};
|
|
} |