snoottube-ops/configs/backend.nix

327 lines
11 KiB
Nix

{ config, pkgs, nestedContainerExtras, ... }:
let
mastodonContainerFactory = import ../modules/mastodon_container.nix { };
prodConfig = {
containerName = "mastodon";
hostAddress = "192.168.42.11";
domain = "snoot.tube";
localAddress = "192.168.42.12";
autoStart = true;
useElasticsearch = true;
mastodonPackage = pkgs.mastodonFork;
forwardPorts = [
{
containerPort = 443;
hostPort = 443;
protocol = "tcp";
}
{
containerPort = 80;
hostPort = 80;
protocol = "tcp";
}
];
imports = nestedContainerExtras.imports;
disabledModules = nestedContainerExtras.disabledModules;
acme = {
acceptTerms = true;
defaults.email = "vivlim@pm.me";
defaults.server =
"https://localhost"; # try to use localhost as acme server. this request *will* fail, and we'll fall back to self-signed
#defaults.enableDebugLogs = true;
};
smtp = {
createLocally = false;
authenticate = false;
fromAddress = "snoot-tube-mastodon@vvn.space";
host =
"192.168.1.7"; # ts ip isn't reachable from the container. maybe need a mail relay on the host? use lan ip for now "100.109.126.18"; # sky-reflected-in-mirrors ts ip
port = 25;
};
mastodonExtraConfig = {
ALTERNATE_DOMAINS = "dev.snoot.tube,awake.snoot.tube";
#EMAIL_DOMAIN_ALLOWLIST = "vvn.space";
SMTP_AUTH_METHOD = "none";
SMTP_OPENSSL_VERIFY_MODE = "none";
MAX_TOOT_CHARS = "42069";
AUTHORIZED_FETCH = "true";
USER_ACTIVE_DAYS = "14";
STATSD_ADDR = "outer:9125";
MAX_REACTIONS = "8";
SEARCH_SCOPE = "public";
};
oauth2ProxyUsers = ''
viv
itsonlythee
lifning
Skirmisher
'';
oauth2ProxyKeys = config.sops.secrets.oauth2_proxy_keys.path;
};
stagingConfig = {
containerName = "mastodon-staging";
hostAddress = "192.168.42.11";
domain = "staging.snoot.tube";
localAddress = "192.168.42.13";
autoStart = false;
useElasticsearch = true;
mastodonPackage = pkgs.mastodonStagingFork;
forwardPorts = [
{
containerPort = 443;
hostPort = 4430;
protocol = "tcp";
}
{
containerPort = 80;
hostPort = 800;
protocol = "tcp";
}
];
imports = nestedContainerExtras.imports;
disabledModules = nestedContainerExtras.disabledModules;
acme = {
acceptTerms = true;
defaults.email = "vivlim@pm.me";
defaults.server =
"https://localhost"; # try to use localhost as acme server. this request *will* fail, and we'll fall back to self-signed
};
smtp = {
createLocally = false;
authenticate = false;
fromAddress = "snoot-tube-mastodon-staging@vvn.space";
host =
"192.168.1.7"; # ts ip isn't reachable from the container. maybe need a mail relay on the host? use lan ip for now "100.109.126.18"; # sky-reflected-in-mirrors ts ip
port = 25;
};
mastodonExtraConfig = {
EMAIL_DOMAIN_ALLOWLIST = "vvn.space";
SMTP_AUTH_METHOD = "none";
SMTP_OPENSSL_VERIFY_MODE = "none";
MAX_TOOT_CHARS = "42069";
AUTHORIZED_FETCH = "true";
LIMITED_FEDERATION_MODE = "true";
USER_ACTIVE_DAYS = "14";
MAX_REACTIONS = "8";
SEARCH_SCOPE = "public";
};
oauth2ProxyUsers = ''
viv
'';
oauth2ProxyKeys = config.sops.secrets.oauth2_proxy_keys.path;
};
prodContainer = (mastodonContainerFactory prodConfig);
stagingContainer = (mastodonContainerFactory stagingConfig);
in {
config.networking.hostName = "mastodon-snoottube";
config.networking.firewall.enable = true;
config.networking.firewall.allowedTCPPorts =
[ 80 443 22 19999 19998 19980 19981 9102 4040 ];
config.networking.firewall.interfaces."ve-+".allowedTCPPorts =
[ 3128 ]; # ssh forwarded http proxy
config.networking.firewall.interfaces."ve-+".allowedUDPPorts =
[ 9125 ]; # statsd
config.networking.firewall.checkReversePath = "loose";
config.networking.extraHosts = ''
192.168.42.11 outer
192.168.42.12 mastodon-container
'';
config.services.tailscale.enable = true;
# enable containers to reach network
config.networking.nat.enable = true;
config.networking.nat.internalInterfaces = [ "ve-+" ];
config.networking.nat.externalInterface = "ens18";
config.services.prometheus_exporters = {
enable = true;
nodePort = 19982;
systemdPort = 19983;
combinedPort = 19980;
};
config.services.autossh = {
sessions = [{
name = "snoot.tube_ingress";
user = "root";
monitoringPort = 0;
extraArguments =
"-o ExitOnForwardFailure=yes -o ConnectTimeout=10 -o ServerAliveInterval=15 -o ServerAliveCountMax=4 -N -R 4433:${prodConfig.localAddress}:443 -L 3128:localhost:3128 -L 19981:localhost:19980 -L 19998:localhost:19999 -L 4040:localhost:4040 -g -i /root/.ssh/id_ed25519_to_ingress snoot.tube -p 6922";
}
{
name = "staging_ingress";
user = "root";
monitoringPort = 0;
extraArguments =
"-o ExitOnForwardFailure=yes -o ConnectTimeout=10 -o ServerAliveInterval=15 -o ServerAliveCountMax=4 -N -R 5433:${stagingConfig.localAddress}:443 -g -i /root/.ssh/id_ed25519_to_ingress snoot.tube -p 6922";
}
];
};
config.containers = {
mastodon = prodContainer.containerConfig;
staging = stagingContainer.containerConfig;
};
config.system.activationScripts.createMastodonContainerPaths =
pkgs.lib.stringAfter [ "setupSecrets" "var" ]
prodContainer.activationScript;
config.system.activationScripts.createMastodonStagingContainerPaths =
pkgs.lib.stringAfter [ "setupSecrets" "var" ]
stagingContainer.activationScript;
config.sops.secrets.oauth2_proxy_keys = { };
config.environment.systemPackages = [
(let
script = pkgs.writeShellScriptBin "tootctl" ''
echo "untested! check if this works and remove this echo if it does"
sudo nixos-container "run mastodon -- tootctl $@\""
'';
in pkgs.stdenv.mkDerivation {
name = "mastodon-container-tootctl-wrapper";
version = "1.0.0";
phases = "installPhase";
installPhase = ''
mkdir -p $out/bin
cp ${script}/bin/* $out/bin/
'';
})
];
config.sops.defaultSopsFile = ../secrets/backend.yaml;
config.sops.secrets.borg_backup_repo_passphrase = { };
config.sops.secrets.borgbase_ssh_private_key =
{ }; # it is extremely important for this to have a trailing newline, or connecting will fail
config.services.borgbackup.jobs."borgbase" = {
paths = [ "/var/lib/mastodon-container" "/var/backup" ];
exclude = [ ];
repo = "h5g87o5w@h5g87o5w.repo.borgbase.com:repo";
encryption = {
mode = "repokey-blake2";
passCommand =
"cat ${config.sops.secrets.borg_backup_repo_passphrase.path}";
};
environment.BORG_RSH =
"ssh -i ${config.sops.secrets.borgbase_ssh_private_key.path}";
compression = "auto,lzma";
startAt = "daily";
};
config.systemd.services.statsd-exporter = {
description = "StatsD Exporter";
wantedBy = [ "multi-user.target" ];
after = [ "container@mastodon.service" ];
serviceConfig = let
mappingFile = pkgs.writeText "statsd-mapping.yaml" ''
## Prometheus Statsd Exporter mapping for Mastodon 4.0+
##
## Version 1.0, November 2022
##
## Documentation: https://ipng.ch/s/articles/2022/11/27/mastodon-3.html
mappings:
## Web collector
- match: Mastodon\.production\.web\.(.+)\.(.+)\.(.+)\.status\.(.+)
match_type: regex
name: "mastodon_controller_status"
labels:
controller: $1
action: $2
format: $3
status: $4
mastodon: "web"
- match: Mastodon\.production\.web\.(.+)\.(.+)\.(.+)\.db_time
match_type: regex
name: "mastodon_controller_db_time"
labels:
controller: $1
action: $2
format: $3
mastodon: "web"
- match: Mastodon\.production\.web\.(.+)\.(.+)\.(.+)\.view_time
match_type: regex
name: "mastodon_controller_view_time"
labels:
controller: $1
action: $2
format: $3
mastodon: "web"
- match: Mastodon\.production\.web\.(.+)\.(.+)\.(.+)\.total_duration
match_type: regex
name: "mastodon_controller_duration"
labels:
controller: $1
action: $2
format: $3
mastodon: "web"
## Database collector
- match: Mastodon\.production\.db\.tables\.(.+)\.queries\.(.+)\.duration
match_type: regex
name: "mastodon_db_operation"
labels:
table: "$1"
operation: "$2"
mastodon: "db"
## Cache collector
- match: Mastodon\.production\.cache\.(.+)\.duration
match_type: regex
name: "mastodon_cache_duration"
labels:
operation: "$1"
mastodon: "cache"
## Sidekiq collector
- match: Mastodon\.production\.sidekiq\.(.+)\.processing_time
match_type: regex
name: "mastodon_sidekiq_worker_processing_time"
labels:
worker: "$1"
mastodon: "sidekiq"
- match: Mastodon\.production\.sidekiq\.(.+)\.success
match_type: regex
name: "mastodon_sidekiq_worker_success_total"
labels:
worker: "$1"
mastodon: "sidekiq"
- match: Mastodon\.production\.sidekiq\.(.+)\.failure
match_type: regex
name: "mastodon_sidekiq_worker_failure_total"
labels:
worker: "$1"
mastodon: "sidekiq"
- match: Mastodon\.production\.sidekiq\.queues\.(.+)\.enqueued
match_type: regex
name: "mastodon_sidekiq_queue_enqueued"
labels:
queue: "$1"
mastodon: "sidekiq"
- match: Mastodon\.production\.sidekiq\.queues\.(.+)\.latency
match_type: regex
name: "mastodon_sidekiq_queue_latency"
labels:
queue: "$1"
mastodon: "sidekiq"
- match: Mastodon\.production\.sidekiq\.(.+)
match_type: regex
name: "mastodon_sidekiq_$1"
labels:
mastodon: "sidekiq"
'';
in {
ExecStart =
"${pkgs.prometheus-statsd-exporter}/bin/statsd_exporter --web.listen-address=':9102' --statsd.listen-udp=':9125' --statsd.mapping-config=${mappingFile}";
};
};
}