Setup mail server and restructure some things

This commit is contained in:
yuri 2023-09-14 14:43:49 +02:00
parent fa3db3bad6
commit 4a802ab44d
90 changed files with 512 additions and 66 deletions

View file

@ -0,0 +1,10 @@
{ ... }:
{
security.acme.certs = {
"turn.nekover.se" = {
listenHTTP = ":80";
group = "turnserver";
reloadServices = [ "coturn.service" ];
};
};
}

View file

@ -0,0 +1,22 @@
{ config, ... }:
{
boot.loader.grub = {
enable = true;
device = "/dev/vda";
};
networking = {
hostName = "coturn";
firewall = {
enable = true;
allowedTCPPorts = [ 80 3478 5349 ];
allowedUDPPorts = [ 3478 5349 ];
allowedUDPPortRanges = [{
from = config.services.coturn.min-port;
to = config.services.coturn.max-port;
}];
};
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,45 @@
{ config, ... }:
{
services.coturn = {
enable = true;
min-port = 49200;
max-port = 49500;
use-auth-secret = true;
static-auth-secret-file = "/secrets/static-auth-secret.secret";
realm = "turn.nekover.se";
cert = "${config.security.acme.certs."turn.nekover.se".directory}/fullchain.pem";
pkey = "${config.security.acme.certs."turn.nekover.se".directory}/key.pem";
no-tcp-relay = true;
no-cli = true;
extraConfig = ''
external-ip=170.133.2.81/10.202.41.118
prometheus
syslog
no-tlsv1
no-tlsv1_1
denied-peer-ip=10.0.0.0-10.255.255.255
denied-peer-ip=192.168.0.0-192.168.255.255
denied-peer-ip=172.16.0.0-172.31.255.255
no-multicast-peers
denied-peer-ip=0.0.0.0-0.255.255.255
denied-peer-ip=100.64.0.0-100.127.255.255
denied-peer-ip=127.0.0.0-127.255.255.255
denied-peer-ip=169.254.0.0-169.254.255.255
denied-peer-ip=192.0.0.0-192.0.0.255
denied-peer-ip=192.0.2.0-192.0.2.255
denied-peer-ip=192.88.99.0-192.88.99.255
denied-peer-ip=198.18.0.0-198.19.255.255
denied-peer-ip=198.51.100.0-198.51.100.255
denied-peer-ip=203.0.113.0-203.0.113.255
denied-peer-ip=240.0.0.0-255.255.255.255
allowed-peer-ip=10.202.41.118
user-quota=12
total-quota=1200
'';
};
}

View file

@ -0,0 +1,8 @@
{ ... }:
{
imports = [
./configuration.nix
./acme.nix
./coturn.nix
];
}

View file

@ -0,0 +1,11 @@
{ ... }:
{
deployment.keys."static-auth-secret.secret" = {
keyCommand = [ "env" "GNUPGHOME=/home/yuri/.passinfra_gnupg" "PASSWORD_STORE_DIR=/home/yuri/pass/infra" "pass" "coturn/static-auth-secret" ];
destDir = "/secrets";
user = "turnserver";
group = "turnserver";
permissions = "0640";
uploadAt = "pre-activation";
};
}

View file

@ -0,0 +1,40 @@
{ ... }:
{
boot = {
loader.grub = {
enable = true;
device = "/dev/vda";
};
binfmt.emulatedSystems = [
"armv6l-linux"
"armv7l-linux"
"aarch64-linux"
];
};
networking = {
hostName = "hydra";
firewall = {
enable = true;
allowedTCPPorts = [ 8443 ];
};
};
nix = {
settings.allowed-uris = "http:// https://";
buildMachines = [
{
hostName = "localhost";
systems = [
"x86_64-linux"
"armv6l-linux"
"armv7l-linux"
"aarch64-linux"
];
}
];
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,9 @@
{ ... }:
{
imports = [
./configuration.nix
./hydra.nix
./nix-serve.nix
./nginx.nix
];
}

View file

@ -0,0 +1,14 @@
{ ... }:
{
services.hydra = {
enable = true;
hydraURL = "https://hydra.nekover.se";
listenHost = "localhost";
port = 3001;
useSubstitutes = true;
notificationSender = "hydra@robot.grzb.de";
extraConfig = "
binary_cache_public_uri = https://nix-cache.nekover.se
";
};
}

View file

@ -0,0 +1,42 @@
{ ... }:
{
services.nginx = {
enable = true;
virtualHosts = {
"hydra.nekover.se" = {
forceSSL = true;
enableACME = true;
listen = [{
addr = "0.0.0.0";
port = 80;
}];
locations."/" = {
proxyPass = "http://localhost:3001";
};
extraConfig = ''
listen 0.0.0.0:8443 http2 ssl proxy_protocol;
set_real_ip_from 10.202.41.100;
real_ip_header proxy_protocol;
'';
};
"nix-cache.nekover.se" = {
forceSSL = true;
enableACME = true;
listen = [ {
addr = "0.0.0.0";
port = 80;
}];
locations."/" = {
proxyPass = "http://localhost:5005";
};
extraConfig = ''
listen 0.0.0.0:8443 http2 ssl proxy_protocol;
set_real_ip_from 10.202.41.100;
real_ip_header proxy_protocol;
'';
};
};
};
}

View file

@ -0,0 +1,9 @@
{ ... }:
{
services.nix-serve = {
enable = true;
port = 5005;
bindAddress = "localhost";
secretKeyFile = "/secrets/signing-key.secret";
};
}

View file

@ -0,0 +1,11 @@
{ ... }:
{
deployment.keys."signing-key.secret" = {
keyCommand = [ "env" "GNUPGHOME=/home/yuri/.passinfra_gnupg" "PASSWORD_STORE_DIR=/home/yuri/pass/infra" "pass" "hydra/signing-key" ];
destDir = "/secrets";
user = "root";
group = "root";
permissions = "0640";
uploadAt = "pre-activation";
};
}

View file

@ -0,0 +1,14 @@
{ ... }:
{
boot.loader.grub = {
enable = true;
device = "/dev/vda";
};
networking = {
hostName = "iperf";
firewall.enable = true;
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,7 @@
{ ... }:
{
imports = [
./configuration.nix
./iperf.nix
];
}

View file

@ -0,0 +1,7 @@
{ ... }:
{
services.iperf3 = {
enable = true;
openFirewall = true;
};
}

View file

@ -0,0 +1,14 @@
{ ... }:
{
boot.loader.grub = {
enable = true;
device = "/dev/vda";
};
networking = {
hostName = "jackett";
firewall.enable = false;
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,7 @@
{ ... }:
{
imports = [
./configuration.nix
./jackett.nix
];
}

View file

@ -0,0 +1,6 @@
{ ... }:
{
services.jackett = {
enable = true;
};
}

View file

@ -0,0 +1,17 @@
{ ... }:
{
boot.loader.grub = {
enable = true;
device = "/dev/vda";
};
networking = {
hostName = "jellyfin";
firewall = {
enable = true;
allowedTCPPorts = [ 80 443 8443 ];
};
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,9 @@
{ ... }:
{
imports = [
./configuration.nix
./hardware-configuration.nix
./jellyfin.nix
./nginx.nix
];
}

View file

@ -0,0 +1,16 @@
{ ... }:
{
fileSystems."/mnt/media" = {
device = "//10.202.46.5/media";
fsType = "cifs";
options = [
"username=jellyfin"
"credentials=/secrets/samba-credentials.secret"
"iocharset=utf8"
"vers=3.1.1"
"uid=jellyfin"
"gid=jellyfin"
"_netdev"
];
};
}

View file

@ -0,0 +1,6 @@
{ ... }:
{
services.jellyfin = {
enable = true;
};
}

View file

@ -0,0 +1,71 @@
{ ... }:
{
services.nginx = {
enable = true;
virtualHosts."jellyfin.grzb.de" = {
forceSSL = true;
enableACME = true;
listen = [
{
addr = "0.0.0.0";
port = 80;
}
{
addr = "0.0.0.0";
port = 443;
ssl = true;
}
{
addr = "0.0.0.0";
port = 8443;
ssl = true;
proxyProtocol = true;
}
];
locations."= /" = {
return = "302 https://$host/web/";
};
locations."/" = {
proxyPass = "http://localhost:8096/";
extraConfig = ''
# Disable buffering when the nginx proxy gets very resource heavy upon streaming
proxy_buffering off;
'';
};
locations."= /web/" = {
proxyPass = "http://localhost:8096/web/index.html";
};
locations."/socket" = {
proxyPass = "http://localhost:8096/socket";
proxyWebsockets = true;
};
extraConfig = ''
client_max_body_size 20M;
# Security / XSS Mitigation Headers
# NOTE: X-Frame-Options may cause issues with the webOS app
add_header X-Frame-Options "SAMEORIGIN";
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options "nosniff";
# COOP/COEP. Disable if you use external plugins/images/assets
add_header Cross-Origin-Opener-Policy "same-origin" always;
add_header Cross-Origin-Embedder-Policy "require-corp" always;
add_header Cross-Origin-Resource-Policy "same-origin" always;
# Permissions policy. May cause issues on some clients
add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), battery=(), bluetooth=(), camera=(), clipboard-read=(), display-capture=(), document-domain=(), encrypted-media=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), interest-cohort=(), keyboard-map=(), local-fonts=(), magnetometer=(), microphone=(), payment=(), publickey-credentials-get=(), serial=(), sync-xhr=(), usb=(), xr-spatial-tracking=()" always;
# Tell browsers to use per-origin process isolation
add_header Origin-Agent-Cluster "?1" always;
# Content Security Policy
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
# Enforces https content and restricts JS/CSS to origin
# External Javascript (such as cast_sender.js for Chromecast) must be whitelisted.
# NOTE: The default CSP headers may cause issues with the webOS app
#add_header Content-Security-Policy "default-src https: data: blob: http://image.tmdb.org; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.gstatic.com/cv/js/sender/v1/cast_sender.js https://www.gstatic.com/eureka/clank/95/cast_sender.js https://www.gstatic.com/eureka/clank/96/cast_sender.js https://www.gstatic.com/eureka/clank/97/cast_sender.js https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'";
'';
};
};
}

View file

@ -0,0 +1,11 @@
{ ... }:
{
deployment.keys."samba-credentials.secret" = {
keyCommand = [ "env" "GNUPGHOME=/home/yuri/.passinfra_gnupg" "PASSWORD_STORE_DIR=/home/yuri/pass/infra" "pass" "jellyfin/samba-credentials" ];
destDir = "/secrets";
user = "root";
group = "root";
permissions = "0640";
uploadAt = "pre-activation";
};
}

View file

@ -0,0 +1,69 @@
{ pkgs, ... }:
{
boot.loader.grub = {
enable = true;
device = "/dev/vda";
};
boot.kernel.sysctl."net.ipv4.conf.all.forwarding" = true;
networking = {
hostName = "lifeline";
useDHCP = true;
wireguard = {
enable = true;
interfaces.wg0 = {
privateKeyFile = "/secrets/wireguard-lifeline-mail-1-lifeline-privatekey.secret";
listenPort = 51820;
ips = [
"172.16.50.1/24"
];
peers = [
{
name = "mail-1";
publicKey = "CyKPjkY1ah/lE6V3R0XugNo28doeAtD8wEtAeDB7bHs=";
presharedKeyFile = "/secrets/wireguard-lifeline-mail-1-lifeline-psk.secret";
allowedIPs = [ "172.16.50.2/32" ];
}
];
postSetup = ''
${pkgs.iptables}/bin/iptables -A FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 172.16.50.0/24 -o ens6 -j MASQUERADE
'';
postShutdown = ''
${pkgs.iptables}/bin/iptables -D FORWARD -i wg0 -j ACCEPT
${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 172.16.50.0/24 -o ens6 -j MASQUERADE
'';
};
};
nat = {
enable = true;
internalInterfaces = [ "wg0" ];
externalInterface = "ens6";
forwardPorts = [
{
destination = "172.16.50.2:25";
proto = "tcp";
sourcePort = 25;
}
{
destination = "172.16.50.2:465";
proto = "tcp";
sourcePort = 465;
}
{
destination = "172.16.50.2:993";
proto = "tcp";
sourcePort = 993;
}
];
};
firewall = {
allowedUDPPorts = [ 51820 ];
};
};
services.prometheus.exporters.node.enable = false;
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,7 @@
{ ... }:
{
imports = [
./configuration.nix
./hardware-configuration.nix
];
}

View file

@ -0,0 +1,16 @@
{ modulesPath, ... }:
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd = {
availableKernelModules = [ "ata_piix" "uhci_hcd" "xen_blkfront" "vmw_pvscsi" ];
kernelModules = [ "nvme" ];
};
fileSystems."/" = {
device = "/dev/vda1";
fsType = "ext4";
};
}

View file

@ -0,0 +1,19 @@
{ ... }:
{
deployment.keys."wireguard-lifeline-mail-1-lifeline-psk.secret" = {
keyCommand = [ "env" "GNUPGHOME=/home/yuri/.passinfra_gnupg" "PASSWORD_STORE_DIR=/home/yuri/pass/infra" "pass" "wireguard/lifeline-mail-1/psk" ];
destDir = "/secrets";
user = "root";
group = "root";
permissions = "0640";
uploadAt = "pre-activation";
};
deployment.keys."wireguard-lifeline-mail-1-lifeline-privatekey.secret" = {
keyCommand = [ "env" "GNUPGHOME=/home/yuri/.passinfra_gnupg" "PASSWORD_STORE_DIR=/home/yuri/pass/infra" "pass" "wireguard/lifeline-mail-1/lifeline-privatekey" ];
destDir = "/secrets";
user = "root";
group = "root";
permissions = "0640";
uploadAt = "pre-activation";
};
}

View file

@ -0,0 +1,61 @@
{ ... }:
{
boot.loader.grub = {
enable = true;
device = "/dev/vda";
};
networking = {
hostName = "mail-1";
useDHCP = true;
defaultGateway = {
address = "172.16.50.1";
interface = "wg0";
};
interfaces.enp6s18.ipv4 = {
routes = [
{
address = "10.201.0.0";
prefixLength = 16;
via = "10.202.41.1";
}
{
address = "10.202.0.0";
prefixLength = 16;
via = "10.202.41.1";
}
{
address = "172.21.87.0"; # management VPN
prefixLength = 24;
via = "10.202.41.1";
}
{
address = "217.160.117.160"; #
prefixLength = 32;
via = "10.202.41.1";
}
];
};
wireguard = {
enable = true;
interfaces.wg0 = {
ips = [
"172.16.50.2/24"
];
peers = [
{
name = "lifeline";
publicKey = "g3xZ5oJCbPtzYDPTVAS400FDw6kirGR+7300bwiZDUY=";
presharedKeyFile = "/secrets/wireguard-lifeline-mail-1-mail-1-psk.secret";
endpoint = "lifeline.io.grzb.de:51820";
allowedIPs = [ "0.0.0.0/0" ];
persistentKeepalive = 25;
}
];
privateKeyFile = "/secrets/wireguard-lifeline-mail-1-mail-1-privatekey.secret";
};
};
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,7 @@
{ ... }:
{
imports = [
./configuration.nix
./simple-nixos-mailserver.nix
];
}

View file

@ -0,0 +1,85 @@
{ keyCommandEnv, ... }:
{
deployment.keys = {
"wireguard-valkyrie-mail-1-mail-1-psk.secret" = {
keyCommand = keyCommandEnv ++ [ "pass" "wireguard/valkyrie-mail-1/psk" ];
destDir = "/secrets";
user = "root";
group = "systemd-network";
permissions = "0640";
uploadAt = "pre-activation";
};
"wireguard-mail-1-wg0-privatekey.secret" = {
keyCommand = keyCommandEnv ++ [ "pass" "wireguard/mail-1-wg0-privatekey" ];
destDir = "/secrets";
user = "root";
group = "systemd-network";
permissions = "0640";
uploadAt = "pre-activation";
};
"mail-fiona-grzb-de.secret" = {
keyCommand = keyCommandEnv ++ [ "pass" "mail/fiona-grzb-de" ];
destDir = "/secrets";
user = "root";
group = "root";
permissions = "0640";
uploadAt = "pre-activation";
};
"mail-yuri-nekover-se.secret" = {
keyCommand = keyCommandEnv ++ [ "pass" "mail/yuri-nekover-se" ];
destDir = "/secrets";
user = "root";
group = "root";
permissions = "0640";
uploadAt = "pre-activation";
};
"mail-mio-vs-grzb-de.secret" = {
keyCommand = keyCommandEnv ++ [ "pass" "mail/mio-vs-grzb-de" ];
destDir = "/secrets";
user = "root";
group = "root";
permissions = "0640";
uploadAt = "pre-activation";
};
"mail-fubuki-wg-grzb-de.secret" = {
keyCommand = keyCommandEnv ++ [ "pass" "mail/fubuki-wg-grzb-de" ];
destDir = "/secrets";
user = "root";
group = "root";
permissions = "0640";
uploadAt = "pre-activation";
};
"mail-cloud-nekover-se.secret" = {
keyCommand = keyCommandEnv ++ [ "pass" "mail/cloud-nekover-se" ];
destDir = "/secrets";
user = "root";
group = "root";
permissions = "0640";
uploadAt = "pre-activation";
};
"mail-status-nekover-se.secret" = {
keyCommand = keyCommandEnv ++ [ "pass" "mail/status-nekover-se" ];
destDir = "/secrets";
user = "root";
group = "root";
permissions = "0640";
uploadAt = "pre-activation";
};
"mail-matrix-nekover-se.secret" = {
keyCommand = keyCommandEnv ++ [ "pass" "mail/matrix-nekover-se" ];
destDir = "/secrets";
user = "root";
group = "root";
permissions = "0640";
uploadAt = "pre-activation";
};
"mail-social-nekover-se.secret" = {
keyCommand = keyCommandEnv ++ [ "pass" "mail/social-nekover-se" ];
destDir = "/secrets";
user = "root";
group = "root";
permissions = "0640";
uploadAt = "pre-activation";
};
};
}

View file

@ -0,0 +1,66 @@
{ simple-nixos-mailserver, ... }:
{
imports = [
simple-nixos-mailserver.nixosModule {
mailserver = {
enable = true;
openFirewall = true;
fqdn = "mail-1.grzb.de";
enableImap = false;
enableImapSsl = true;
enableSubmission = false;
enableSubmissionSsl = true;
lmtpSaveToDetailMailbox = "no";
domains = [ "grzb.de" "vs.grzb.de" "wg.grzb.de" "nekover.se" ];
loginAccounts = {
"fiona@grzb.de" = {
hashedPasswordFile = "/secrets/mail-fiona-grzb-de.secret";
aliases = [ "@grzb.de" ];
catchAll = [ "grzb.de" ];
};
"yuri@nekover.se" = {
hashedPasswordFile = "/secrets/mail-yuri-nekover-se.secret";
aliases = [ "@nekover.se" ];
catchAll = [ "nekover.se" ];
};
"mio@vs.grzb.de" = {
hashedPasswordFile = "/secrets/mail-mio-vs-grzb-de.secret";
sendOnly = true;
aliases = [ "root@vs.grzb.de" ];
};
"fubuki@wg.grzb.de" = {
hashedPasswordFile = "/secrets/mail-fubuki-wg-grzb-de.secret";
sendOnly = true;
aliases = [ "root@wg.grzb.de" ];
};
"cloud@nekover.se" = {
hashedPasswordFile = "/secrets/mail-cloud-nekover-se.secret";
sendOnly = true;
};
"status@nekover.se" = {
hashedPasswordFile = "/secrets/mail-status-nekover-se.secret";
sendOnly = true;
};
"matrix@nekover.se" = {
hashedPasswordFile = "/secrets/mail-matrix-nekover-se.secret";
sendOnly = true;
aliases = [ "nyareply@nekover.se" ];
};
"social@nekover.se" = {
hashedPasswordFile = "/secrets/mail-social-nekover-se.secret";
sendOnly = true;
aliases = [ "nyareply@nekover.se" ];
};
};
certificateScheme = "acme-nginx";
};
}
];
services.postfix = {
transport = "relay:[mail-2.grzb.de]";
extraConfig = ''
proxy_interfaces = 212.53.203.19
'';
};
}

View file

@ -0,0 +1,17 @@
{ ... }:
{
boot.loader.grub = {
enable = true;
device = "/dev/vda";
};
networking = {
hostName = "matrix";
firewall = {
enable = true;
allowedTCPPorts = [ 80 8443 8448 ];
};
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,10 @@
{ ... }:
{
imports = [
./configuration.nix
./hardware-configuration.nix
./postgresql.nix
./matrix-synapse.nix
./nginx.nix
];
}

View file

@ -0,0 +1,21 @@
{ config, ... }:
{
fileSystems."/mnt/data" = {
device = "/dev/disk/by-label/data";
fsType = "ext4";
autoFormat = true;
autoResize = true;
};
fileSystems."/var/lib/matrix-synapse/media_store" = {
depends = [ "/mnt/data" ];
device = "/mnt/data/media_store";
fsType = "none";
options = [ "bind" "X-mount.owner=matrix-synapse" "X-mount.group=matrix-synapse" ];
};
fileSystems."/var/lib/postgresql/${config.services.postgresql.package.psqlSchema}" = {
depends = [ "/mnt/data" ];
device = "/mnt/data/database";
fsType = "none";
options = [ "bind" "X-mount.owner=postgres" "X-mount.group=postgres" ];
};
}

View file

@ -0,0 +1,36 @@
{ ... }:
{
services.matrix-synapse = {
enable = true;
settings = {
server_name = "nekover.se";
public_baseurl = "https://matrix.nekover.se";
database = {
name = "psycopg2";
args.password = "synapse";
};
email = {
smtp_host = "mail.grzb.de";
smtp_port = 465;
smtp_user = "matrix";
force_tls = true;
notif_from = "Nekoverse Matrix Server <nyareply@nekover.se>";
};
max_upload_size = "500M";
signing_key_path = "/secrets/matrix-homeserver-signing-key.secret";
admin_contact = "mailto:admin@nekover.se";
web_client_location = "https://element.nekover.se";
turn_uris = [
"turns:turn.nekover.se?transport=udp"
"turns:turn.nekover.se?transport=tcp"
];
turn_user_lifetime = 86400000;
turn_allow_guests = true;
};
extraConfigFiles = [
"/secrets/matrix-registration-shared-secret.secret"
"/secrets/matrix-turn-shared-secret.secret"
"/secrets/matrix-email-smtp-pass.secret"
];
};
}

View file

@ -0,0 +1,35 @@
{ config, ... }:
{
services.nginx = {
enable = true;
virtualHosts."matrix.nekover.se" = {
forceSSL = true;
enableACME = true;
listen = [
{
addr = "0.0.0.0";
port = 80;
}
{
addr = "0.0.0.0";
port = 8448;
ssl = true;
}
];
locations."~ ^(/_matrix|/_synapse/client)" = {
proxyPass = "http://localhost:8008";
extraConfig = ''
# Nginx by default only allows file uploads up to 1M in size
# Increase client_max_body_size to match max_upload_size defined in homeserver.yaml
client_max_body_size ${config.services.matrix-synapse.settings.max_upload_size};
'';
};
extraConfig = ''
listen 0.0.0.0:8443 http2 ssl proxy_protocol;
set_real_ip_from 10.202.41.100;
real_ip_header proxy_protocol;
'';
};
};
}

View file

@ -0,0 +1,13 @@
{ pkgs, ... }:
{
services.postgresql = {
enable = true;
initialScript = pkgs.writeText "synapse-init.sql" ''
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
TEMPLATE template0
LC_COLLATE = "C"
LC_CTYPE = "C";
'';
};
}

View file

@ -0,0 +1,35 @@
{ ... }:
{
deployment.keys."matrix-registration-shared-secret.secret" = {
keyCommand = [ "env" "GNUPGHOME=/home/yuri/.passinfra_gnupg" "PASSWORD_STORE_DIR=/home/yuri/pass/infra" "pass" "matrix/registration-shared-secret" ];
destDir = "/secrets";
user = "matrix-synapse";
group = "matrix-synapse";
permissions = "0640";
uploadAt = "pre-activation";
};
deployment.keys."matrix-turn-shared-secret.secret" = {
keyCommand = [ "env" "GNUPGHOME=/home/yuri/.passinfra_gnupg" "PASSWORD_STORE_DIR=/home/yuri/pass/infra" "pass" "matrix/turn-shared-secret" ];
destDir = "/secrets";
user = "matrix-synapse";
group = "matrix-synapse";
permissions = "0640";
uploadAt = "pre-activation";
};
deployment.keys."matrix-email-smtp-pass.secret" = {
keyCommand = [ "env" "GNUPGHOME=/home/yuri/.passinfra_gnupg" "PASSWORD_STORE_DIR=/home/yuri/pass/infra" "pass" "matrix/email-smtp-pass" ];
destDir = "/secrets";
user = "matrix-synapse";
group = "matrix-synapse";
permissions = "0640";
uploadAt = "pre-activation";
};
deployment.keys."matrix-homeserver-signing-key.secret" = {
keyCommand = [ "env" "GNUPGHOME=/home/yuri/.passinfra_gnupg" "PASSWORD_STORE_DIR=/home/yuri/pass/infra" "pass" "matrix/homeserver-signing-key" ];
destDir = "/secrets";
user = "matrix-synapse";
group = "matrix-synapse";
permissions = "0640";
uploadAt = "pre-activation";
};
}

View file

@ -0,0 +1,17 @@
{ ... }:
{
boot.loader.grub = {
enable = true;
device = "/dev/vda";
};
networking = {
hostName = "metrics";
firewall = {
enable = true;
allowedTCPPorts = [ 80 443 ];
};
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,9 @@
{ ... }:
{
imports = [
./configuration.nix
./grafana.nix
./prometheus.nix
./nginx.nix
];
}

View file

@ -0,0 +1,36 @@
{ config, ... }:
{
services.grafana = {
enable = true;
settings = {
server = {
domain = "grafana.grzb.de";
root_url = "https://${config.services.grafana.settings.server.domain}";
};
security = {
cookie_secure = true;
cookie_samesite = "strict";
admin_user = "yuri";
admin_password = "$__file{/secrets/metrics-grafana-admin-password.secret}";
admin_email = "yuri@nekover.se";
};
smtp = {
enabled = true;
host = "mail.grzb.de:465";
user = "grafana";
password = "$__file{/secrets/metrics-grafana-smtp-password.secret}";
from_address = "grafana@robot.grzb.de";
from_name = "Grafana";
startTLS_policy = "NoStartTLS";
};
};
provision.datasources.settings.datasources = [
{
name = "Prometheus";
type = "prometheus";
url = "http://localhost:${builtins.toString config.services.prometheus.port}";
isDefault = true;
}
];
};
}

View file

@ -0,0 +1,27 @@
{ config, ... }:
{
services.nginx = {
enable = true;
virtualHosts = {
${config.services.grafana.settings.server.domain} = {
forceSSL = true;
enableACME = true;
listen = [
{
addr = "0.0.0.0";
port = 80;
}
{
addr = "0.0.0.0";
port = 443;
ssl = true;
}
];
locations."/" = {
proxyPass = "http://${config.services.grafana.settings.server.http_addr}:${builtins.toString config.services.grafana.settings.server.http_port}";
proxyWebsockets = true;
};
};
};
};
}

View file

@ -0,0 +1,19 @@
{ hosts, ... }:
{
services.prometheus = {
enable = true;
scrapeConfigs = [
{
job_name = "node";
static_configs = builtins.map (name: {
targets = [
"${name}.${hosts.${name}.site}.grzb.de:9100"
];
labels = {
host = "${name}.${hosts.${name}.site}.grzb.de";
};
}) (builtins.attrNames hosts);
}
];
};
}

View file

@ -0,0 +1,19 @@
{ ... }:
{
deployment.keys."metrics-grafana-admin-password.secret" = {
keyCommand = [ "env" "GNUPGHOME=/home/yuri/.passinfra_gnupg" "PASSWORD_STORE_DIR=/home/yuri/pass/infra" "pass" "metrics/grafana/admin-password" ];
destDir = "/secrets";
user = "grafana";
group = "grafana";
permissions = "0640";
uploadAt = "pre-activation";
};
deployment.keys."metrics-grafana-smtp-password.secret" = {
keyCommand = [ "env" "GNUPGHOME=/home/yuri/.passinfra_gnupg" "PASSWORD_STORE_DIR=/home/yuri/pass/infra" "pass" "metrics/grafana/smtp-password" ];
destDir = "/secrets";
user = "grafana";
group = "grafana";
permissions = "0640";
uploadAt = "pre-activation";
};
}

View file

@ -0,0 +1,17 @@
{ ... }:
{
boot.loader.grub = {
enable = true;
device = "/dev/vda";
};
networking = {
hostName = "netbox";
firewall = {
enable = true;
allowedTCPPorts = [ 80 443 ];
};
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,8 @@
{ ... }:
{
imports = [
./configuration.nix
./netbox.nix
./nginx.nix
];
}

View file

@ -0,0 +1,7 @@
{ ... }:
{
services.netbox = {
enable = true;
secretKeyFile = "/secrets/netbox-secret-key.secret";
};
}

View file

@ -0,0 +1,29 @@
{ config, ... }:
{
services.nginx = {
enable = true;
clientMaxBodySize = "25m";
user = "netbox";
virtualHosts."netbox.grzb.de" = {
forceSSL = true;
enableACME = true;
listen = [
{
addr = "0.0.0.0";
port = 80;
}
{
addr = "0.0.0.0";
port = 443;
ssl = true;
}
];
locations."/static/" = {
alias = "${config.services.netbox.dataDir}/static/";
};
locations."/" = {
proxyPass = "http://${config.services.netbox.listenAddress}:${builtins.toString config.services.netbox.port}";
};
};
};
}

View file

@ -0,0 +1,11 @@
{ ... }:
{
deployment.keys."netbox-secret-key.secret" = {
keyCommand = [ "env" "GNUPGHOME=/home/yuri/.passinfra_gnupg" "PASSWORD_STORE_DIR=/home/yuri/pass/infra" "pass" "netbox/secret-key" ];
destDir = "/secrets";
user = "netbox";
group = "netbox";
permissions = "0640";
uploadAt = "pre-activation";
};
}

View file

@ -0,0 +1,17 @@
{ ... }:
{
boot.loader.grub = {
enable = true;
device = "/dev/vda";
};
networking = {
hostName = "nextcloud";
firewall = {
enable = true;
allowedTCPPorts = [ 8443 ];
};
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,8 @@
{ ... }:
{
imports = [
./configuration.nix
./hardware-configuration.nix
./nextcloud.nix
];
}

View file

@ -0,0 +1,10 @@
{ ... }:
{
fileSystems."/var/lib/nextcloud/data" = {
device = "/dev/vdb";
fsType = "ext4";
autoFormat = true;
autoResize = true;
options = [ "X-mount.owner=nextcloud" "X-mount.group=nextcloud" ];
};
}

View file

@ -0,0 +1,52 @@
{ pkgs, config, ... }:
{
services.nextcloud = {
enable = true;
package = pkgs.nextcloud27;
hostName = "cloud.nekover.se";
https = true;
config = {
dbtype = "pgsql";
adminpassFile = "/secrets/nextcloud-adminpass.secret";
defaultPhoneRegion = "DE";
};
database.createLocally = true;
configureRedis = true;
extraAppsEnable = true;
extraApps = with config.services.nextcloud.package.packages.apps; {
inherit bookmarks contacts calendar tasks twofactor_webauthn;
};
maxUploadSize = "16G";
extraOptions = {
mail_smtpmode = "smtp";
mail_sendmailmode = "smtp";
mail_smtpsecure = "ssl";
mail_from_address = "cloud";
mail_domain = "nekover.se";
mail_smtpauthtype = "LOGIN";
mail_smtpauth = 1;
mail_smtphost = "mail.grzb.de";
mail_smtpport = 465;
mail_smtpname = "nextcloud";
};
# Only contains mail_smtppassword
secretFile = "/secrets/nextcloud-secretfile.secret";
phpOptions = {
# The amount of memory for interned strings in Mbytes
"opcache.interned_strings_buffer" = "64";
};
};
services.nginx = {
virtualHosts.${config.services.nextcloud.hostName} = {
forceSSL = true;
enableACME = true;
extraConfig = ''
listen 0.0.0.0:8443 http2 ssl proxy_protocol;
set_real_ip_from 10.202.41.100;
real_ip_header proxy_protocol;
'';
};
};
}

View file

@ -0,0 +1,21 @@
{ ... }:
{
deployment.keys = {
"nextcloud-adminpass.secret" = {
keyCommand = [ "env" "GNUPGHOME=/home/yuri/.passinfra_gnupg" "PASSWORD_STORE_DIR=/home/yuri/pass/infra" "pass" "nextcloud/adminpass" ];
destDir = "/secrets";
user = "nextcloud";
group = "nextcloud";
permissions = "0640";
uploadAt = "pre-activation";
};
"nextcloud-secretfile.secret" = {
keyCommand = [ "env" "GNUPGHOME=/home/yuri/.passinfra_gnupg" "PASSWORD_STORE_DIR=/home/yuri/pass/infra" "pass" "nextcloud/secretfile" ];
destDir = "/secrets";
user = "nextcloud";
group = "nextcloud";
permissions = "0640";
uploadAt = "pre-activation";
};
};
}

View file

@ -0,0 +1,17 @@
{ ... }:
{
boot.loader.grub = {
enable = true;
device = "/dev/vda";
};
networking = {
hostName = "nitter";
firewall = {
enable = true;
allowedTCPPorts = [ 8443 ];
};
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,8 @@
{ ... }:
{
imports = [
./configuration.nix
./nginx.nix
./nitter.nix
];
}

View file

@ -0,0 +1,23 @@
{ config, ... }:
{
services.nginx = {
enable = true;
virtualHosts."birdsite.nekover.se" = {
forceSSL = true;
enableACME = true;
locations."/robots.txt" = {
return = "200 \"User-agent: *\\nDisallow: /\\n\"";
};
locations."/" = {
proxyPass = "http://${config.services.nitter.server.address}:${builtins.toString config.services.nitter.server.port}";
proxyWebsockets = true;
};
extraConfig = ''
listen 0.0.0.0:8443 http2 ssl proxy_protocol;
set_real_ip_from 10.202.41.100;
real_ip_header proxy_protocol;
'';
};
};
}

View file

@ -0,0 +1,21 @@
{ ... }:
{
services.nitter = {
enable = true;
server = {
title = "Birdsite";
https = true;
address = "127.0.0.1";
port = 8080;
hostname = "birdsite.nekover.se";
};
preferences = {
theme = "Mastodon";
replaceTwitter = "birdsite.nekover.se";
infiniteScroll = true;
hlsPlayback = true;
};
};
}

View file

@ -0,0 +1,29 @@
{ ... }:
{
boot.loader.grub = {
enable = true;
device = "/dev/vda";
};
networking = {
interfaces = {
"enp6s18".ipv6.addresses = [{
address = "2001:470:5429::B3";
prefixLength = 64;
}];
};
defaultGateway6 = {
address = "2001:470:5429::1";
interface = "enp6s18";
};
hostName = "tor-relay";
firewall = {
enable = true;
allowedTCPPorts = [ 9001 9030 ];
};
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,7 @@
{ ... }:
{
imports = [
./configuration.nix
./tor.nix
];
}

View file

@ -0,0 +1,20 @@
{ ... }:
{
services.tor = {
enable = true;
relay = {
enable = true;
role = "relay";
};
settings = {
Nickname = "vsm";
ORPort = 9001;
DirPort = 9030;
ContactInfo = "admin@grzb.de";
RelayBandwidthRate = "40 MBits";
RelayBandwidthBurst = "50 Mbits";
};
};
}

View file

@ -0,0 +1,17 @@
{ ... }:
{
boot.loader.grub = {
enable = true;
device = "/dev/vda";
};
networking = {
hostName = "web-nonpublic-linuxcrewd";
firewall = {
enable = true;
allowedTCPPorts = [ 80 443 ];
};
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,7 @@
{ ... }:
{
imports = [
./configuration.nix
./nginx.nix
];
}

View file

@ -0,0 +1,29 @@
{ ... }:
{
services.nginx = {
enable = true;
virtualHosts."_" = {
listen = [{
addr = "0.0.0.0";
port = 80;
}];
locations."/" = {
return = "301 https://$host$request_uri";
};
};
streamConfig = ''
map $ssl_preread_server_name $address {
jellyfin.grzb.de 10.202.46.101:8443;
}
server {
listen 0.0.0.0:443;
proxy_pass $address;
ssl_preread on;
proxy_protocol on;
}
'';
};
}

View file

@ -0,0 +1,29 @@
{ ... }:
{
boot.loader.grub = {
enable = true;
device = "/dev/vda";
};
networking = {
interfaces = {
"enp6s18".ipv6.addresses = [{
address = "2001:470:5429::96";
prefixLength = 64;
}];
};
defaultGateway6 = {
address = "2001:470:5429::1";
interface = "enp6s18";
};
hostName = "web-public-2";
firewall = {
enable = true;
allowedTCPPorts = [ 80 443 5000 8448 ];
};
};
system.stateVersion = "23.05";
}

View file

@ -0,0 +1,7 @@
{ ... }:
{
imports = [
./configuration.nix
./nginx.nix
];
}

View file

@ -0,0 +1,40 @@
{ ... }:
{
imports = [
./virtualHosts
];
services.nginx = {
enable = true;
streamConfig = ''
map $ssl_preread_server_name $address {
anisync.grzb.de 127.0.0.1:8443;
birdsite.nekover.se 10.202.41.107:8443;
cloud.nekover.se 10.202.41.122:8443;
element.nekover.se 127.0.0.1:8443;
gameserver.grzb.de 127.0.0.1:8443;
git.grzb.de 127.0.0.1:8443;
hydra.nekover.se 10.202.41.121:8443;
matrix.nekover.se 10.202.41.112:8443;
mewtube.nekover.se 127.0.0.1:8443;
nekover.se 127.0.0.1:8443;
nextcloud.grzb.de 127.0.0.1:8443;
nix-cache.nekover.se 10.202.41.121:8443;
social.nekover.se 127.0.0.1:8443;
}
server {
listen 0.0.0.0:443;
listen [::]:443;
proxy_pass $address;
ssl_preread on;
proxy_protocol on;
}
'';
appendHttpConfig = ''
add_header Strict-Transport-Security "max-age=63072000" always;
'';
};
}

View file

@ -0,0 +1,57 @@
{ ... }:
{
services.nginx.virtualHosts."jellyfin.grzb.de" = {
listen = [{
addr = "0.0.0.0";
port = 80;
}];
locations."^~ /.well-known/acme-challenge/" = {
proxyPass = "http://jellyfin.vs.grzb.de:80";
};
};
services.nginx.virtualHosts."mail-1.grzb.de" = {
listen = [{
addr = "0.0.0.0";
port = 80;
}];
locations."^~ /.well-known/acme-challenge/" = {
proxyPass = "http://mail-1.vs.grzb.de:80";
};
};
services.nginx.virtualHosts."matrix.nekover.se" = {
listen = [{
addr = "0.0.0.0";
port = 80;
}];
locations."^~ /.well-known/acme-challenge/" = {
proxyPass = "http://matrix.vs.grzb.de:80";
};
};
services.nginx.virtualHosts."netbox.grzb.de" = {
listen = [{
addr = "0.0.0.0";
port = 80;
}];
locations."^~ /.well-known/acme-challenge/" = {
proxyPass = "http://netbox.vs.grzb.de:80";
};
};
services.nginx.virtualHosts."grafana.grzb.de" = {
listen = [{
addr = "0.0.0.0";
port = 80;
}];
locations."^~ /.well-known/acme-challenge/" = {
proxyPass = "http://metrics.vs.grzb.de:80";
};
};
services.nginx.virtualHosts."turn.nekover.se" = {
listen = [{
addr = "0.0.0.0";
port = 80;
}];
locations."^~ /.well-known/acme-challenge/" = {
proxyPass = "http://coturn.vs.grzb.de:80";
};
};
}

View file

@ -0,0 +1,26 @@
{ ... }:
{
services.nginx.virtualHosts."anisync.grzb.de" = {
forceSSL = true;
enableACME = true;
listen = [
{
addr = "localhost";
port = 1234;
} # workaround for enableACME check
{
addr = "localhost";
port = 8443;
ssl = true;
proxyProtocol = true;
}
];
locations."/" = {
proxyPass = "http://anisync.vs.grzb.de:8080";
proxyWebsockets = true;
};
extraConfig = ''
add_header X-Content-Type-Options nosniff;
'';
};
}

View file

@ -0,0 +1,23 @@
{ ... }:
{
imports = [
./acme-challenge.nix
./anisync.grzb.de.nix
./element.nekover.se.nix
./gameserver.grzb.de.nix
./git.grzb.de.nix
./mewtube.nekover.se.nix
./nekover.se.nix
./social.nekover.se.nix
];
services.nginx.virtualHosts."_" = {
listen = [{
addr = "0.0.0.0";
port = 80;
}];
locations."/" = {
return = "301 https://$host$request_uri";
};
};
}

View file

@ -0,0 +1,48 @@
{
"default_server_config": {
"m.homeserver": {
"base_url": "https://matrix.nekover.se",
"server_name": "Nekoverse"
},
"m.identity_server": {
"base_url": "https://vector.im"
}
},
"disable_custom_urls": false,
"disable_guests": false,
"disable_login_language_selector": false,
"disable_3pid_login": false,
"brand": "Element",
"integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api",
"integrations_widgets_urls": [
"https://scalar.vector.im/_matrix/integrations/v1",
"https://scalar.vector.im/api",
"https://scalar-staging.vector.im/_matrix/integrations/v1",
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
],
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
"uisi_autorageshake_app": "element-auto-uisi",
"defaultCountryCode": "DE",
"showLabsSettings": true,
"features": { },
"default_federate": true,
"default_theme": "dark",
"roomDirectory": {
"servers": [
"matrix.org"
]
},
"piwik": false,
"enable_presence_by_hs_url": {
"https://matrix.org": false,
"https://matrix-client.matrix.org": false
},
"settingDefaults": {
"breadcrumbs": true
},
"jitsi": {
"preferredDomain": "meet.element.io"
}
}

View file

@ -0,0 +1,83 @@
{ pkgs, ... }:
let
element-web = pkgs.fetchzip {
url = "https://github.com/vector-im/element-web/releases/download/v1.11.40/element-v1.11.40.tar.gz";
sha256 = "sha256-IZ1FjT9fAv6wDfgLcCLBHwg6iXGXC4E0/2/67hArD4w=";
};
in
{
services.nginx.virtualHosts."element.nekover.se" = {
forceSSL = true;
enableACME = true;
root = pkgs.buildEnv {
name = "element-web";
paths = [
element-web
./element-web-config
];
};
listen = [
{
addr = "localhost";
port = 1234;
} # workaround for enableACME check
{
addr = "localhost";
port = 8443;
ssl = true;
proxyProtocol = true;
}
];
# Set no-cache for the version, config and index.html
# so that browsers always check for a new copy of Element Web.
# NB http://your-domain/ and http://your-domain/? are also covered by this
locations."= /index.html" = {
extraConfig = ''
add_header Cache-Control "no-cache";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Content-Security-Policy "frame-ancestors 'none'";
add_header Strict-Transport-Security "max-age=63072000" always;
'';
};
locations."= /version" = {
extraConfig = ''
add_header Cache-Control "no-cache";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Content-Security-Policy "frame-ancestors 'none'";
add_header Strict-Transport-Security "max-age=63072000" always;
'';
};
# covers config.json and config.hostname.json requests as it is prefix.
locations."/config" = {
extraConfig = ''
add_header Cache-Control "no-cache";
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Content-Security-Policy "frame-ancestors 'none'";
add_header Strict-Transport-Security "max-age=63072000" always;
'';
};
extraConfig = ''
index index.html;
# Configuration best practices
# See: https://github.com/vector-im/element-web/tree/develop#configuration-best-practices
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Content-Security-Policy "frame-ancestors 'none'";
add_header Strict-Transport-Security "max-age=63072000" always;
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
'';
};
}

View file

@ -0,0 +1,31 @@
{ ... }:
{
services.nginx.virtualHosts."gameserver.grzb.de" = {
forceSSL = true;
enableACME = true;
listen = [
{
addr = "localhost";
port = 1234;
} # workaround for enableACME check
{
addr = "localhost";
port = 8443;
ssl = true;
proxyProtocol = true;
}
];
locations."/" = {
proxyPass = "http://pterodactyl.vs.grzb.de";
extraConfig = ''
proxy_redirect off;
proxy_buffering off;
proxy_request_buffering off;
'';
};
extraConfig = ''
client_max_body_size 1024m;
add_header X-Content-Type-Options nosniff;
'';
};
}

View file

@ -0,0 +1,33 @@
{ ... }:
{
services.nginx.virtualHosts."git.grzb.de" = {
forceSSL = true;
enableACME = true;
listen = [
{
addr = "localhost";
port = 1234;
} # workaround for enableACME check
{
addr = "localhost";
port = 8443;
ssl = true;
proxyProtocol = true;
}
];
locations."/" = {
proxyPass = "http://gitlab.vs.grzb.de:80";
extraConfig = ''
gzip off;
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_redirect off;
'';
};
extraConfig = ''
client_max_body_size 1024m;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
'';
};
}

View file

@ -0,0 +1,22 @@
{ ... }:
{
services.nginx.virtualHosts."mewtube.nekover.se" = {
forceSSL = true;
enableACME = true;
listen = [
{
addr = "localhost";
port = 1234;
} # workaround for enableACME check
{
addr = "localhost";
port = 8443;
ssl = true;
proxyProtocol = true;
}
];
locations."/" = {
proxyPass = "http://cloudtube.vs.grzb.de:10412";
};
};
}

View file

@ -0,0 +1,32 @@
{ ... }:
{
services.nginx.virtualHosts."nekover.se" = {
forceSSL = true;
enableACME = true;
listen = [
{
addr = "localhost";
port = 1234;
} # workaround for enableACME check
{
addr = "localhost";
port = 8443;
ssl = true;
proxyProtocol = true;
}
];
locations."/.well-known/matrix/server" = {
return = "200 '{\"m.server\": \"matrix.nekover.se:443\"}'";
extraConfig = ''
add_header Content-Type application/json;
'';
};
locations."/.well-known/matrix/client" = {
return = "200 '{\"m.homeserver\": {\"base_url\": \"https://matrix.nekover.se\"}, \"m.identity_server\": {\"base_url\": \"https://vector.im\"}}'";
extraConfig = ''
default_type application/json;
add_header Access-Control-Allow-Origin *;
'';
};
};
}

View file

@ -0,0 +1,26 @@
{ ... }:
{
services.nginx.virtualHosts."social.nekover.se" = {
forceSSL = true;
enableACME = true;
listen = [
{
addr = "localhost";
port = 1234;
} # workaround for enableACME check
{
addr = "localhost";
port = 8443;
ssl = true;
proxyProtocol = true;
}
];
locations."/" = {
proxyPass = "http://mastodon.vs.grzb.de:80";
proxyWebsockets = true;
};
extraConfig = ''
client_max_body_size 80m;
'';
};
}