Move everyting to hel1 except emails

This commit is contained in:
Paul-Henri Froidmont 2024-12-10 11:39:55 +01:00
parent 0d3f1b4afc
commit f18644f8a1
Signed by: phfroidmont
GPG key ID: BE948AFD7E7873BE
18 changed files with 476 additions and 448 deletions

View file

@ -1,4 +1,5 @@
{ config, pkgs, ... }: {
{ ... }:
{
imports = [
./backup-job.nix
./monit.nix
@ -20,5 +21,6 @@
./roundcube.nix
./dokuwiki.nix
./postgresql.nix
./foundryvtt.nix
];
}

44
modules/foundryvtt.nix Normal file
View file

@ -0,0 +1,44 @@
{
inputs,
pkgs,
config,
lib,
...
}:
let
cfg = config.custom.services.foundryvtt;
in
{
options.custom.services.foundryvtt = {
enable = lib.mkEnableOption "foundryvtt";
};
config = lib.mkIf cfg.enable {
services.foundryvtt = {
enable = true;
package = inputs.foundryvtt.packages.${pkgs.system}.foundryvtt_12;
hostName = "vtt.${config.networking.domain}";
language = "fr.core";
proxyPort = 443;
proxySSL = true;
upnp = false;
dataDir = "/nix/var/data/foundryvtt";
};
systemd.services.foundryvtt.serviceConfig = {
StateDirectory = lib.mkForce null;
ReadWritePaths = config.services.foundryvtt.dataDir;
};
services.nginx.virtualHosts."vtt.${config.networking.domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://127.0.0.1:${toString config.services.foundryvtt.port}";
extraConfig = ''
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
'';
};
};
};
}

View file

@ -1,15 +1,17 @@
{ config, lib, ... }:
let cfg = config.custom.services.jellyfin;
in {
let
cfg = config.custom.services.jellyfin;
in
{
options.custom.services.jellyfin = {
enable = lib.mkEnableOption "jellyfin";
};
config = lib.mkIf cfg.enable {
services.jellyfin = { enable = true; };
systemd.services.jellyfin.serviceConfig.ExecStart = lib.mkOverride 10
"${config.services.jellyfin.package}/bin/jellyfin --datadir '/nix/var/data/jellyfin' --cachedir '/var/cache/jellyfin'";
services.jellyfin = {
enable = true;
dataDir = "/nix/var/data/jellyfin";
};
services.nginx.virtualHosts."jellyfin.${config.networking.domain}" = {
enableACME = true;

View file

@ -1,5 +1,4 @@
{
pkgs,
config,
lib,
...

View file

@ -1,7 +1,11 @@
{ config, lib, ... }:
let cfg = config.custom.services.murmur;
in {
options.custom.services.murmur = { enable = lib.mkEnableOption "murmur"; };
let
cfg = config.custom.services.murmur;
in
{
options.custom.services.murmur = {
enable = lib.mkEnableOption "murmur";
};
config = lib.mkIf cfg.enable {
sops.secrets.murmurEnvFile = {
@ -16,6 +20,7 @@ in {
password = "$MURMURD_PASSWORD";
environmentFile = config.sops.secrets.murmurEnvFile.path;
imgMsgLength = 13107200;
openFirewall = true;
};
};
}

View file

@ -1,20 +1,19 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.custom.services.nextcloud;
uidFile = pkgs.writeText "uidfile" ''
nextcloud:993
'';
gidFile = pkgs.writeText "gidfile" ''
nextcloud:991
'';
in {
in
{
options.custom.services.nextcloud = {
enable = lib.mkEnableOption "nextcloud";
};
config = lib.mkIf cfg.enable {
sops.secrets = {
sshfsKey = { key = "sshfs_keys/private"; };
nextcloudDbPassword = {
owner = config.users.users.nextcloud.name;
key = "nextcloud/db_password";
@ -29,31 +28,6 @@ in {
environment.systemPackages = with pkgs; [ sshfs ];
systemd.services.nextcloud-data-sshfs = {
wantedBy = [ "multi-user.target" "nextcloud-setup.service" ];
before = [ "phpfpm-nextcloud.service" ];
restartIfChanged = false;
serviceConfig = {
ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p /var/lib/nextcloud/data";
ExecStart = let
options = builtins.concatStringsSep "," [
"identityfile=${config.sops.secrets.sshfsKey.path}"
"ServerAliveInterval=15"
"idmap=file"
"uidfile=${uidFile}"
"gidfile=${gidFile}"
"allow_other"
"default_permissions"
"nomap=ignore"
];
in "${pkgs.sshfs}/bin/mount.fuse.sshfs www-data@10.0.2.3:/nix/var/data/nextcloud/data "
+ "/var/lib/nextcloud/data -o ${options}";
ExecStopPost =
"-${pkgs.fuse}/bin/fusermount -u /var/lib/nextcloud/data";
KillMode = "process";
};
};
services.nginx.virtualHosts."${config.services.nextcloud.hostName}" = {
enableACME = true;
forceSSL = true;
@ -61,6 +35,9 @@ in {
services.nextcloud = {
enable = true;
# Can't be changed for now, could use a bind mount as workaround
# https://github.com/NixOS/nixpkgs/issues/356973
# home = "/nix/var/data/nextcloud";
package = pkgs.nextcloud29;
hostName = "cloud.${config.networking.domain}";
https = true;
@ -69,7 +46,7 @@ in {
config = {
dbtype = "pgsql";
dbuser = "nextcloud";
dbhost = "10.0.1.11";
dbhost = "127.0.0.1";
dbname = "nextcloud";
dbpassFile = "${config.sops.secrets.nextcloudDbPassword.path}";
adminpassFile = "${config.sops.secrets.nextcloudAdminPassword.path}";

View file

@ -22,9 +22,6 @@ in
root_as_others root synapse
root_as_others root nextcloud
root_as_others root roundcube
root_as_others root mastodon
root_as_others root dolibarr
root_as_others root odoo
'';
authentication = ''
local all postgres peer
@ -35,12 +32,10 @@ in
sops.secrets = {
synapseDbPassword = {
owner = config.services.postgresql.superUser;
key = "synapse/db_password";
restartUnits = [ "postgresql-setup.service" ];
};
nextcloudDbPassword = {
owner = config.services.postgresql.superUser;
key = "nextcloud/db_password";
restartUnits = [ "postgresql-setup.service" ];
};
@ -49,16 +44,6 @@ in
key = "roundcube/db_password";
restartUnits = [ "postgresql-setup.service" ];
};
mastodonDbPassword = {
owner = config.services.postgresql.superUser;
key = "mastodon/db_password";
restartUnits = [ "postgresql-setup.service" ];
};
dolibarrDbPassword = {
owner = config.services.postgresql.superUser;
key = "dolibarr/db_password";
restartUnits = [ "postgresql-setup.service" ];
};
};
systemd.services.postgresql-setup =
@ -82,23 +67,14 @@ in
PSQL -tAc "SELECT 1 FROM pg_roles WHERE rolname = 'synapse'" | grep -q 1 || PSQL -tAc 'CREATE ROLE "synapse"'
PSQL -tAc "SELECT 1 FROM pg_roles WHERE rolname = 'nextcloud'" | grep -q 1 || PSQL -tAc 'CREATE ROLE "nextcloud"'
PSQL -tAc "SELECT 1 FROM pg_roles WHERE rolname = 'roundcube'" | grep -q 1 || PSQL -tAc 'CREATE ROLE "roundcube"'
PSQL -tAc "SELECT 1 FROM pg_roles WHERE rolname = 'mastodon'" | grep -q 1 || PSQL -tAc 'CREATE ROLE "mastodon"'
PSQL -tAc "SELECT 1 FROM pg_roles WHERE rolname = 'dolibarr'" | grep -q 1 || PSQL -tAc 'CREATE ROLE "dolibarr"'
PSQL -tAc "SELECT 1 FROM pg_roles WHERE rolname = 'odoo'" | grep -q 1 || PSQL -tAc 'CREATE ROLE "odoo"'
PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = 'synapse'" | grep -q 1 || PSQL -tAc 'CREATE DATABASE "synapse" OWNER "synapse" TEMPLATE template0 LC_COLLATE = "C" LC_CTYPE = "C"'
PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = 'nextcloud'" | grep -q 1 || PSQL -tAc 'CREATE DATABASE "nextcloud" OWNER "nextcloud"'
PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = 'roundcube'" | grep -q 1 || PSQL -tAc 'CREATE DATABASE "roundcube" OWNER "roundcube"'
PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = 'mastodon'" | grep -q 1 || PSQL -tAc 'CREATE DATABASE "mastodon" OWNER "mastodon"'
PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = 'dolibarr'" | grep -q 1 || PSQL -tAc 'CREATE DATABASE "dolibarr" OWNER "dolibarr"'
PSQL -tAc "SELECT 1 FROM pg_database WHERE datname = 'odoo'" | grep -q 1 || PSQL -tAc 'CREATE DATABASE "odoo" OWNER "odoo"'
PSQL -tAc "ALTER ROLE synapse LOGIN"
PSQL -tAc "ALTER ROLE nextcloud LOGIN"
PSQL -tAc "ALTER ROLE roundcube LOGIN"
PSQL -tAc "ALTER ROLE mastodon LOGIN"
PSQL -tAc "ALTER ROLE dolibarr LOGIN"
PSQL -tAc "ALTER ROLE odoo LOGIN"
synapse_password="$(<'${config.sops.secrets.synapseDbPassword.path}')"
PSQL -tAc "ALTER ROLE synapse WITH PASSWORD '$synapse_password'"
@ -106,11 +82,6 @@ in
PSQL -tAc "ALTER ROLE nextcloud WITH PASSWORD '$nextcloud_password'"
roundcube_password="$(<'${config.sops.secrets.roundcubeDbPassword.path}')"
PSQL -tAc "ALTER ROLE roundcube WITH PASSWORD '$roundcube_password'"
mastodon_password="$(<'${config.sops.secrets.mastodonDbPassword.path}')"
PSQL -tAc "ALTER ROLE mastodon WITH PASSWORD '$mastodon_password'"
dolibarr_password="$(<'${config.sops.secrets.dolibarrDbPassword.path}')"
PSQL -tAc "ALTER ROLE dolibarr WITH PASSWORD '$dolibarr_password'"
PSQL -tAc "ALTER ROLE odoo WITH PASSWORD 'odoo'"
'';
serviceConfig = {

View file

@ -1,6 +1,13 @@
{ pkgs, lib, config, ... }:
let cfg = config.custom.services.roundcube;
in {
{
pkgs,
lib,
config,
...
}:
let
cfg = config.custom.services.roundcube;
in
{
options.custom.services.roundcube = {
enable = lib.mkEnableOption "roundcube";
};
@ -17,16 +24,17 @@ in {
};
};
# Required because roundcube uses psql: https://github.com/NixOS/nixpkgs/blob/46397778ef1f73414b03ed553a3368f0e7e33c2f/nixos/modules/services/mail/roundcube.nix#L247
services.postgresql.package = pkgs.postgresql_15;
services.roundcube = {
enable = true;
plugins = [ "managesieve" ];
dicts = with pkgs.aspellDicts; [ en fr de ];
dicts = with pkgs.aspellDicts; [
en
fr
de
];
hostName = "webmail.banditlair.com";
database = {
host = "10.0.1.11";
host = "127.0.0.1";
username = "roundcube";
dbname = "roundcube";
passwordFile = config.sops.secrets.pgPassFile.path;
@ -35,10 +43,10 @@ in {
extraConfig = ''
# This override is required as a workaround for the nixpkgs config because we need a plain password instead of a pgpass file
$password = file_get_contents('${config.sops.secrets.dbPassword.path}');
$config['db_dsnw'] = 'pgsql://roundcube:' . $password . '@10.0.1.11/roundcube';
$config['db_dsnw'] = 'pgsql://roundcube:' . $password . '@127.0.0.1/roundcube';
$config['default_host'] = 'ssl://mail.banditlair.com:993';
$config['smtp_server'] = 'ssl://%h';
$config['imap_host'] = 'ssl://mail.banditlair.com:993';
$config['smtp_host'] = 'ssl://%h';
$config['smtp_user'] = '%u';
$config['smtp_pass'] = '%p';
$config['identities_level'] = 0;

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
let
cfg = config.custom.services.stb;
uploadWordpressConfig = pkgs.writeText "upload.ini" ''
@ -8,10 +13,17 @@ let
post_max_size = 64M
max_execution_time = 600
'';
in {
options.custom.services.stb = { enable = lib.mkEnableOption "stb"; };
in
{
options.custom.services.stb = {
enable = lib.mkEnableOption "stb";
};
config = lib.mkIf cfg.enable {
virtualisation.podman.defaultNetwork.settings = {
dns_enabled = true;
};
systemd.services.init-stb-network = {
description = "Create the network bridge stb-br for wordpress.";
after = [ "network.target" ];
@ -19,15 +31,17 @@ in {
serviceConfig.Type = "oneshot";
script =
let dockercli = "${config.virtualisation.docker.package}/bin/docker";
in ''
let
podmancli = "${pkgs.podman}/bin/podman";
in
''
# Put a true at the end to prevent getting non-zero return code, which will
# crash the whole service.
check=$(${dockercli} network ls | grep "stb-br" || true)
check=$(${podmancli} pod ps | grep "stb" || true)
if [ -z "$check" ]; then
${dockercli} network create stb-br
${podmancli} pod create --publish 8180:80 stb
else
echo "stb-br already exists in docker"
echo "stb pod already exists"
fi
'';
};
@ -42,7 +56,7 @@ in {
"MYSQL_DATABASE" = "stb";
};
volumes = [ "/var/lib/mariadb/stb:/var/lib/mysql" ];
extraOptions = [ "--network=stb-br" ];
extraOptions = [ "--pod=stb" ];
autoStart = true;
};
@ -52,8 +66,7 @@ in {
"/nix/var/data/stb-wordpress:/var/www/html"
"${uploadWordpressConfig}:/usr/local/etc/php/conf.d/uploads.ini"
];
ports = [ "127.0.0.1:8180:80" ];
extraOptions = [ "--network=stb-br" ];
extraOptions = [ "--pod=stb" ];
autoStart = true;
};
};
@ -63,7 +76,9 @@ in {
forceSSL = true;
enableACME = true;
locations."/" = { proxyPass = "http://127.0.0.1:8180"; };
locations."/" = {
proxyPass = "http://127.0.0.1:8180";
};
};
};
}

View file

@ -1,16 +1,22 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
let
cfg = config.custom.services.synapse;
fqdn = let
join = hostName: domain:
hostName + lib.optionalString (domain != null) ".${domain}";
in join "matrix" config.networking.domain;
fqdn =
let
join = hostName: domain: hostName + lib.optionalString (domain != null) ".${domain}";
in
join "matrix" config.networking.domain;
synapseDbConfig = pkgs.writeText "synapse-db-config.yaml" ''
database:
name: psycopg2
args:
database: synapse
host: "10.0.1.11"
host: "127.0.0.1"
user: "synapse"
password: "SYNAPSE_DB_PASSWORD"
email:
@ -24,8 +30,11 @@ let
macaroon_secret_key: "MACAROON_SECRET_KEY"
turn_shared_secret: "TURN_SHARED_SECRET"
'';
in {
options.custom.services.synapse = { enable = lib.mkEnableOption "synapse"; };
in
{
options.custom.services.synapse = {
enable = lib.mkEnableOption "synapse";
};
config = lib.mkIf cfg.enable {
services.nginx = {
@ -38,25 +47,35 @@ in {
forceSSL = true;
# acmeFallbackHost = "storage1.banditlair.com";
locations."= /.well-known/matrix/server".extraConfig = let
# use 443 instead of the default 8448 port to unite
# the client-server and server-server port for simplicity
server = { "m.server" = "${fqdn}:443"; };
in ''
add_header Content-Type application/json;
return 200 '${builtins.toJSON server}';
'';
locations."= /.well-known/matrix/client".extraConfig = let
client = {
"m.homeserver" = { "base_url" = "https://${fqdn}"; };
"m.identity_server" = { "base_url" = "https://vector.im"; };
};
locations."= /.well-known/matrix/server".extraConfig =
let
# use 443 instead of the default 8448 port to unite
# the client-server and server-server port for simplicity
server = {
"m.server" = "${fqdn}:443";
};
in
''
add_header Content-Type application/json;
return 200 '${builtins.toJSON server}';
'';
locations."= /.well-known/matrix/client".extraConfig =
let
client = {
"m.homeserver" = {
"base_url" = "https://${fqdn}";
};
"m.identity_server" = {
"base_url" = "https://vector.im";
};
};
in
# ACAO required to allow element-web on any URL to request this json file
in ''
add_header Content-Type application/json;
add_header Access-Control-Allow-Origin *;
return 200 '${builtins.toJSON client}';
'';
''
add_header Content-Type application/json;
add_header Access-Control-Allow-Origin *;
return 200 '${builtins.toJSON client}';
'';
};
# Reverse proxy for Matrix client-server and server-server communication
@ -98,7 +117,10 @@ in {
group = "turnserver";
mode = "0440";
key = "synapse/turn_shared_secret";
restartUnits = [ "matrix-synapse-setup" "coturn" ];
restartUnits = [
"matrix-synapse-setup"
"coturn"
];
};
};
@ -124,7 +146,10 @@ in {
};
systemd.services.matrix-synapse = {
after = [ "matrix-synapse-setup.service" "network.target" ];
after = [
"matrix-synapse-setup.service"
"network.target"
];
bindsTo = [ "matrix-synapse-setup.service" ];
};
@ -138,14 +163,22 @@ in {
listeners = [
{
port = 8008;
bind_addresses = [ "::1" "127.0.0.1" ];
bind_addresses = [
"::1"
"127.0.0.1"
];
type = "http";
tls = false;
x_forwarded = true;
resources = [{
names = [ "client" "federation" ];
compress = false;
}];
resources = [
{
names = [
"client"
"federation"
];
compress = false;
}
];
}
{
port = 9000;
@ -214,17 +247,21 @@ in {
'';
};
networking.firewall = let
range = with config.services.coturn; [{
from = min-port;
to = max-port;
}];
in {
allowedUDPPortRanges = range;
allowedUDPPorts = [ 3478 ];
allowedTCPPortRanges = range;
allowedTCPPorts = [ 3478 ];
};
networking.firewall =
let
range = with config.services.coturn; [
{
from = min-port;
to = max-port;
}
];
in
{
allowedUDPPortRanges = range;
allowedUDPPorts = [ 3478 ];
allowedTCPPortRanges = range;
allowedTCPPorts = [ 3478 ];
};
security.acme.certs.${config.services.coturn.realm} = {
postRun = "systemctl restart coturn.service";

View file

@ -1,14 +1,25 @@
{ config, lib, pkgs, ... }:
let cfg = config.custom.services.torrents;
in {
{
config,
lib,
pkgs,
...
}:
let
cfg = config.custom.services.torrents;
in
{
options.custom.services.torrents = {
enable = lib.mkEnableOption "torrents";
};
config = lib.mkIf cfg.enable {
sops.secrets = {
vpnCredentials = { key = "openvpn/credentials"; };
transmissionRpcCredentials = { key = "transmission/rpc_config.json"; };
vpnCredentials = {
key = "openvpn/credentials";
};
transmissionRpcCredentials = {
key = "transmission/rpc_config.json";
};
};
containers.torrents = {
@ -60,7 +71,9 @@ in {
isSystemUser = true;
group = config.users.groups.www-data.name;
};
users.groups.www-data = { gid = 991; };
users.groups.www-data = {
gid = 991;
};
services.openvpn.servers.client = {
updateResolvConf = true;
config = ''
@ -194,41 +207,51 @@ in {
};
};
virtualisation.oci-containers.containers.flaresolverr = {
image = "ghcr.io/flaresolverr/flaresolverr:v3.3.11";
environment = {
"LOG_LEVEL" = "debug";
"CAPTCHA_SOLVER" = "hcaptcha-solver";
};
ports = [ "192.168.1.1:8191:8191" ];
autoStart = true;
};
# virtualisation.oci-containers.containers.flaresolverr = {
# image = "ghcr.io/flaresolverr/flaresolverr:v3.3.11";
# environment = {
# "LOG_LEVEL" = "debug";
# "CAPTCHA_SOLVER" = "hcaptcha-solver";
# };
# ports = [ "192.168.1.1:8191:8191" ];
# autoStart = true;
# };
services.nginx.virtualHosts = {
"transmission.${config.networking.domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = { proxyPass = "http://192.168.1.2:9091"; };
locations."/" = {
proxyPass = "http://192.168.1.2:9091";
};
};
"jackett.${config.networking.domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = { proxyPass = "http://192.168.1.2:9117"; };
locations."/" = {
proxyPass = "http://192.168.1.2:9117";
};
};
"sonarr.${config.networking.domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = { proxyPass = "http://192.168.1.2:8989"; };
locations."/" = {
proxyPass = "http://192.168.1.2:8989";
};
};
"radarr.${config.networking.domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = { proxyPass = "http://192.168.1.2:7878"; };
locations."/" = {
proxyPass = "http://192.168.1.2:7878";
};
};
"lidarr.${config.networking.domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = { proxyPass = "http://192.168.1.2:8686"; };
locations."/" = {
proxyPass = "http://192.168.1.2:8686";
};
};
};
};