This commit is contained in:
XenGi 2025-11-24 19:37:52 +01:00
parent 7597938a1e
commit 9dd5d2ef2e
Signed by: xengi
SSH key fingerprint: SHA256:FGp51kRvGOcWnTHiOI39ImwVO4A3fpvR30nPX3LpV7g
11 changed files with 503 additions and 38 deletions

35
README.md Normal file
View file

@ -0,0 +1,35 @@
# HTTP
Configure `berlin.ccc.de` web server to send federation traffic to the matrix server:
```nginx
server {
hostname berlin.ccc.de;
location "/.well-known/matrix/server" {
default_type application/json;
return 200 '{"m.server":"matrix.berlin.ccc.de:443"}';
}
}
```
# DNS
```
_matrix-fed._tcp.matrix.berlin.ccc.de. IN SRV 10 0 443 matrix.berlin.ccc.de.
#_matrix._tcp.matrix.berlin.ccc.de. IN SRV 10 0 443 matrix.berlin.ccc.de.
#_matrix._tcp.berlin.ccc.de. IN SRV 10 0 443 matrix.berlin.ccc.de.
_matrix-fed._tcp.berlin.ccc.de. IN SRV 10 0 443 matrix.berlin.ccc.de.
matrix.berlin.ccc.de. IN A <IPv4>
matrix.berlin.ccc.de. IN AAAA <IPv6>
```
# Bots
```bash
register_new_matrix_user \
-c homeserver.yaml https://matrix.berlin.ccc.de \
--user_domain berlin.ccc.de \
--user <YOUR_BOT> \
--password <YOUR_PASSWORD>
```

145
configuration.nix Normal file
View file

@ -0,0 +1,145 @@
{
config,
modulesPath,
pkgs,
lib,
...
}:
{
imports = [ (modulesPath + "/virtualisation/proxmox-lxc.nix") ];
nix = {
optimise = {
automatic = true;
dates = [ "11:00" ];
};
settings = {
auto-optimise-store = true;
sandbox = false;
trusted-users = [
"root"
"@wheel"
]; # Allow remote updates
experimental-features = [
"nix-command"
"flakes"
]; # Enable flakes
};
gc = {
automatic = true;
options = "--delete-older-then 14d";
};
};
nixpkgs.hostPlatform = "x86_64-linux";
environment.systemPackages = with pkgs; [
vim
git
];
proxmoxLXC = {
manageNetwork = false;
manageHostName = false;
privileged = true;
};
users.users.root = {
packages = with pkgs; [
kitty # for terminfo
neofetch # for shits and giggles
];
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICW1+Ml8R9x1LCJaZ8bIZ1qIV4HCuZ6x7DziFW+0Nn5T xengi@kanae_2022-12-09"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICmb+mJfo84IagUaRoDEqY9ROjjQUOQ7tMclpN6NDPrX xengi@kota_2022-01-16"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICyklb7dvEHH0VBEMmTUQFKHN6ekBQqkDKj09+EilUIQ xengi@lucy_2018-09-08"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICjv9W8WXq9QGkgmANNPQR24/I1Pm1ghxNIHftEI+jlZ xengi@mayu_2021-06-11"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGhyfD+8jMl6FDSADb11sfAsJk0KNoVzjjiDRZjUOtmf xengi@nana_2019-08-16"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMPtGqhV7io3mhIoZho4Yf7eCo0sUZvjT2NziM2PkXSo xengi@nyu_2017-10-11"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILwYcSxbP6Hon//kZFIZJSHdqvsJ6AyCwH4JP9/t4q46 xengi@yuka_2020-12-16"
];
};
networking = {
useNetworkd = true;
nftables.enable = true;
dhcpcd.enable = false;
firewall = {
enable = true;
allowedTCPPorts = [
22 # SSH
80 # HTTP/1
443 # HTTP/2
8448 # Matrix federation
];
allowedUDPPorts = [
443 # HTTP/3
];
};
};
time.timeZone = "Europe/Berlin";
i18n.defaultLocale = "en_US.UTF-8";
console.font = "Lat2-Terminus16";
services = {
fstrim.enable = false; # Let Proxmox host handle fstrim
openssh = {
enable = true;
openFirewall = true;
settings = {
PermitEmptyPasswords = "no";
PermitRootLogin = "prohibit-password";
PasswordAuthentication = false;
KbdInteractiveAuthentication = false;
};
banner = ''
__ __
/\ \__ __ /\ \
___ ___ __ \ \ ,_\ _ __ /\_\ __ _ ___ ___ ___\ \ \____
/' __` __`\ /'__`\ \ \ \/ /\`'__\/\ \ /\ \/'\ /'___\ /'___\ /'___\ \ '__`\
/\ \/\ \/\ \/\ \L\.\_\ \ \_\ \ \/ \ \ \\/> </ /\ \__//\ \__//\ \__/\ \ \L\ \
\ \_\ \_\ \_\ \__/.\_\\ \__\\ \_\ \ \_\/\_/\_\ \ \____\ \____\ \____\\ \_,__/
\/_/\/_/\/_/\/__/\/_/ \/__/ \/_/ \/_/\//\/_/ \/____/\/____/\/____/ \/___/
'';
};
# Cache DNS lookups to improve performance
resolved = {
enable = true;
fallbackDns = [
"1.1.1.1#one.one.one.one"
"9.9.9.9#dns.quad9.net"
];
dnssec = "allow-downgrade";
dnsovertls = "true";
extraConfig = ''
Cache=true
CacheFromLocalhost=true
'';
};
};
programs = {
vim = {
enable = true;
defaultEditor = true;
};
ssh.startAgent = true;
};
security = {
acme = {
acceptTerms = true;
defaults = {
validMinDays = 14;
renewInterval = "daily";
email = "acme@xengi.de";
group = "nginx";
webroot = "/var/lib/acme/acme-challenge";
};
};
};
system.stateVersion = "25.05";
}

109
flake.lock generated Normal file
View file

@ -0,0 +1,109 @@
{
"nodes": {
"agenix": {
"inputs": {
"darwin": "darwin",
"home-manager": "home-manager",
"nixpkgs": [
"nixpkgs"
],
"systems": "systems"
},
"locked": {
"lastModified": 1762618334,
"narHash": "sha256-wyT7Pl6tMFbFrs8Lk/TlEs81N6L+VSybPfiIgzU8lbQ=",
"owner": "ryantm",
"repo": "agenix",
"rev": "fcdea223397448d35d9b31f798479227e80183f6",
"type": "github"
},
"original": {
"owner": "ryantm",
"repo": "agenix",
"type": "github"
}
},
"darwin": {
"inputs": {
"nixpkgs": [
"agenix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1744478979,
"narHash": "sha256-dyN+teG9G82G+m+PX/aSAagkC+vUv0SgUw3XkPhQodQ=",
"owner": "lnl7",
"repo": "nix-darwin",
"rev": "43975d782b418ebf4969e9ccba82466728c2851b",
"type": "github"
},
"original": {
"owner": "lnl7",
"ref": "master",
"repo": "nix-darwin",
"type": "github"
}
},
"home-manager": {
"inputs": {
"nixpkgs": [
"agenix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1745494811,
"narHash": "sha256-YZCh2o9Ua1n9uCvrvi5pRxtuVNml8X2a03qIFfRKpFs=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "abfad3d2958c9e6300a883bd443512c55dfeb1be",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1763622513,
"narHash": "sha256-1jQnuyu82FpiSxowrF/iFK6Toh9BYprfDqfs4BB+19M=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "c58bc7f5459328e4afac201c5c4feb7c818d604b",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.05",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"agenix": "agenix",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View file

@ -2,6 +2,7 @@
description = "Matrix server for CCCB"; description = "Matrix server for CCCB";
inputs = { inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05";
#flake-utils.url = "github:numtide/flake-utils";
agenix = { agenix = {
url = "github:ryantm/agenix"; url = "github:ryantm/agenix";
inputs = { inputs = {
@ -9,10 +10,18 @@
}; };
}; };
}; };
outputs = {self, nixpkgs, agenix}: outputs =
{
self,
nixpkgs,
#flake-utils,
agenix,
}:
#flake-utils.lib.eachDefaultSystem (
# system:
let let
system = "x86_64-linux";
pkgs = import nixpkgs { inherit system; }; pkgs = import nixpkgs { inherit system; };
system = "x86_64-linux";
in in
{ {
formatter.${system} = pkgs.nixfmt-tree; formatter.${system} = pkgs.nixfmt-tree;
@ -22,11 +31,12 @@
pkgs.age pkgs.age
]; ];
}; };
nixosConfigurtions."matrix" = nixpkgs.lib.nixosSystem { nixosConfigurations."matrix" = nixpkgs.lib.nixosSystem {
inherit system; #system = "x86_64-linux";
#pkgs = import nixpkgs { inherit system; };
modules = [ modules = [
agenix.nixosModules.default agenix.nixosModules.default
{ environment.systemPackages = [(agenix.packages.${system}.default)]; } { environment.systemPackages = [ (agenix.packages.${system}.default) ]; }
{ {
age.secrets = { age.secrets = {
pushover_app_token = { pushover_app_token = {
@ -44,9 +54,11 @@
}; };
} }
./configuration.nix ./configuration.nix
./services/nginx.nix
./services/postgres.nix
./services/synapse.nix ./services/synapse.nix
]; ];
}; };
}; };
#);
} }

Binary file not shown.

View file

@ -0,0 +1,17 @@
age-encryption.org/v1
-> ssh-ed25519 uH+n1w EMOmmGlZ2rnqAaqcHHQ9conaa8YH/3TBFRpUlssNuGw
jyXUxitYHc/vNpab9winTCqCWBQYtmDGdZortYYlMAI
-> ssh-ed25519 EvLbWw K+NOnJui0ASn3lPsP1xZ2X4fdfSBQ1woOnD3c4Zk/xE
FDYbrduCSWvo5NSzyAgwNa7tU4c3r7Fcoizfph3fqF4
-> ssh-ed25519 dM+fLQ Ji3jw0haPByWaQ68rHxFmj1xjSG9EVfyYTtZZpAFYFg
cHPTEfHWjwIVUBaDB85vGCfatd4Wtuq7QT3mIcdaF7M
-> ssh-ed25519 jxWM2Q ZTbjGk18JyognAJwUQIfwy3YlHALXsfyUICiGrG/ij0
/eyD/UoQZ33s2geZ6212ZMOLhyzKCbryR1HDYW02dfg
-> ssh-ed25519 /yCUCg cM7meOfoTt4UlsODZeSrLFkMtIAInASm0uDrMHDDnXY
LCdZCjhp+/i7bGkXhHJ4Jv6C2ikcPsL3i7W/tap7AMs
-> ssh-ed25519 FGp51g zZFF/qLQDbKpkBQiEJJQrtoJVxrdrWeqziwNq/rP2jY
jJ/ivlZIfn6/oh7yZSCNmQGikvwdSVAzxkLj/tc2Eys
-> ssh-ed25519 alMFaA y5NuhEOK3lijncBscuSCfOTpepiIkAYW/W5kG+wscRE
a/z+2jHk1ERmNXFv+h1B7BpavjbemqOON5ruHP5U6dY
--- 6e7V59HtYHOi9koxczT0hwL6wk1/QkmDOkUGGlZCmo8
[5°Ì“¬rl*X*…_€'-˜ú¿`‹“ó|<7C>3A<33>3£N>¨Ñ

View file

@ -0,0 +1,17 @@
age-encryption.org/v1
-> ssh-ed25519 uH+n1w EMOmmGlZ2rnqAaqcHHQ9conaa8YH/3TBFRpUlssNuGw
jyXUxitYHc/vNpab9winTCqCWBQYtmDGdZortYYlMAI
-> ssh-ed25519 EvLbWw K+NOnJui0ASn3lPsP1xZ2X4fdfSBQ1woOnD3c4Zk/xE
FDYbrduCSWvo5NSzyAgwNa7tU4c3r7Fcoizfph3fqF4
-> ssh-ed25519 dM+fLQ Ji3jw0haPByWaQ68rHxFmj1xjSG9EVfyYTtZZpAFYFg
cHPTEfHWjwIVUBaDB85vGCfatd4Wtuq7QT3mIcdaF7M
-> ssh-ed25519 jxWM2Q ZTbjGk18JyognAJwUQIfwy3YlHALXsfyUICiGrG/ij0
/eyD/UoQZ33s2geZ6212ZMOLhyzKCbryR1HDYW02dfg
-> ssh-ed25519 /yCUCg cM7meOfoTt4UlsODZeSrLFkMtIAInASm0uDrMHDDnXY
LCdZCjhp+/i7bGkXhHJ4Jv6C2ikcPsL3i7W/tap7AMs
-> ssh-ed25519 FGp51g zZFF/qLQDbKpkBQiEJJQrtoJVxrdrWeqziwNq/rP2jY
jJ/ivlZIfn6/oh7yZSCNmQGikvwdSVAzxkLj/tc2Eys
-> ssh-ed25519 alMFaA y5NuhEOK3lijncBscuSCfOTpepiIkAYW/W5kG+wscRE
a/z+2jHk1ERmNXFv+h1B7BpavjbemqOON5ruHP5U6dY
--- 6e7V59HtYHOi9koxczT0hwL6wk1/QkmDOkUGGlZCmo8
[5°Ì“¬rl*X*…_€'-˜ú¿`‹“ó|<7C>3A<33>3£N>¨Ñ

23
secrets/secrets.nix Normal file
View file

@ -0,0 +1,23 @@
let
kanae = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICW1+Ml8R9x1LCJaZ8bIZ1qIV4HCuZ6x7DziFW+0Nn5T xengi@kanae_2022-12-09";
kota = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICmb+mJfo84IagUaRoDEqY9ROjjQUOQ7tMclpN6NDPrX xengi@kota_2022-01-16";
lucy = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICyklb7dvEHH0VBEMmTUQFKHN6ekBQqkDKj09+EilUIQ xengi@lucy_2018-09-08";
mayu = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICjv9W8WXq9QGkgmANNPQR24/I1Pm1ghxNIHftEI+jlZ xengi@mayu_2021-06-11";
nana = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGhyfD+8jMl6FDSADb11sfAsJk0KNoVzjjiDRZjUOtmf xengi@nana_2019-08-16";
nyu = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMPtGqhV7io3mhIoZho4Yf7eCo0sUZvjT2NziM2PkXSo xengi@nyu_2017-10-11";
users = [
kanae
kota
lucy
mayu
nana
nyu
];
_matrix = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIM7AZkepRXoY+DJeSLOU+GR60S62p6+0X/PDeEUZ0yHx root@matrix";
in
{
"matrix-registration-shared-secret.age".publicKeys = users ++ [ _matrix ];
"pushover_app_token.age".publicKeys = users ++ [ _matrix ];
"pushover_user_key.age".publicKeys = users ++ [ _matrix ];
}

44
services/nginx.nix Normal file
View file

@ -0,0 +1,44 @@
{ config, pkgs, ... }:
let
fqdn = "matrix.berlin.ccc.de";
in
{
services.nginx = {
enable = true;
package = pkgs.nginxQuic;
resolver.addresses = ["[2606:4700:4700::1111]" "[2620:fe::fe]" "1.1.1.1" "9.9.9.9"];
statusPage = true; # http://127.0.0.1/nginx_status
sslProtocols = "TLSv1.3";
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedZstdSettings = true;
recommendedGzipSettings = true;
recommendedBrotliSettings = true;
virtualHosts."${fqdn}" = {
quic = true;
kTLS = true;
forceSSL = true;
useACMEHost = fqdn;
locations = {
"/.well-known/matrix/client" = {
return = "200 '{\"m.homeserver\": {\"base_url\": \"https://matrix.berlin.ccc.de\"}}'";
extraConfig = ''
default_type application/json;
add_header Access-Control-Allow-Origin "*";
'';
};
"/" = {
recommendedProxySettings = true;
proxyPass = "unix:/run/matrix-synapse.sock";
};
};
extraConfig = ''
'';
};
};
security.acme.certs."${fqdn}" = {
reloadServices = ["nginx"];
};
}

15
services/postgres.nix Normal file
View file

@ -0,0 +1,15 @@
{ config, ... }:
{
services.postgresql = {
enable = true;
enableJIT = true;
ensureUsers = [
{
name = config.services.matrix-synapse.settings.database.args.user;
ensureDBOwnership = true;
}
];
ensureDatabases = [ config.services.matrix-synapse.settings.database.args.database ];
};
}

48
services/synapse.nix Normal file
View file

@ -0,0 +1,48 @@
{ config, ... }:
let
domain = "berlin.ccc.de";
in
{
services.matrix-synapse = {
enable = false;
settings = {
server_name = domain;
public_baseurl = "https://matrix.${domain}:443/";
#signing_key_path = config.age.secrets.signing_key.path; # "/var/lib/matrix-synapse/homeserver.signing.key"
database.name = "psycopg2";
listeners = [
{
path = "/run/matrix-synapse.sock";
x_forwarded = true;
resources = [
{
compress = false;
names = [
"client"
"federation"
];
}
];
}
];
dynamic_thumbnails = true;
max_upload_size = "128M";
max_image_pixels = "64M";
retention = {
enabled = true;
default_policy = {
min_lifetime = "1d";
max_lifetime = "1y";
};
allowed_lifetime_min = "1d";
allowed_lifetime_max = "1y";
};
};
extraConfigFiles = [
config.age.secrets.matrix-registration-shared-secret.path
];
enableRegistrationScript = true;
};
}