2023-02-20 18:24:12 -08:00
{ config , pkgs , nestedContainerExtras , . . . }:
2023-03-04 18:42:59 -08:00
let
mastodonContainerFactory = import ../modules/mastodon_container.nix { } ;
prodConfig = {
containerName = " m a s t o d o n " ;
hostAddress = " 1 9 2 . 1 6 8 . 4 2 . 1 1 " ;
domain = " s n o o t . t u b e " ;
localAddress = " 1 9 2 . 1 6 8 . 4 2 . 1 2 " ;
2023-03-05 14:48:21 -08:00
autoStart = true ;
2023-03-04 18:42:59 -08:00
useElasticsearch = true ;
mastodonPackage = pkgs . mastodonFork ;
forwardPorts = [
{
containerPort = 443 ;
hostPort = 443 ;
protocol = " t c p " ;
}
{
containerPort = 80 ;
hostPort = 80 ;
protocol = " t c p " ;
}
] ;
imports = nestedContainerExtras . imports ;
disabledModules = nestedContainerExtras . disabledModules ;
acme = {
acceptTerms = true ;
defaults . email = " v i v l i m @ p m . m e " ;
defaults . server =
" h t t p s : / / l o c a l h o s t " ; # 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 = " s n o o t - t u b e - m a s t o d o n @ v v n . s p a c e " ;
host =
" 1 9 2 . 1 6 8 . 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 = " d e v . s n o o t . t u b e , a w a k e . s n o o t . t u b e " ;
#EMAIL_DOMAIN_ALLOWLIST = "vvn.space";
SMTP_AUTH_METHOD = " n o n e " ;
SMTP_OPENSSL_VERIFY_MODE = " n o n e " ;
MAX_TOOT_CHARS = " 4 2 0 6 9 " ;
AUTHORIZED_FETCH = " t r u e " ;
USER_ACTIVE_DAYS = " 1 4 " ;
STATSD_ADDR = " o u t e r : 9 1 2 5 " ;
MAX_REACTIONS = " 8 " ;
SEARCH_SCOPE = " p u b l i c " ;
} ;
oauth2ProxyUsers = ''
viv
itsonlythee
lifning
Skirmisher
'' ;
oauth2ProxyKeys = config . sops . secrets . oauth2_proxy_keys . path ;
} ;
2023-03-05 14:48:21 -08:00
stagingConfig = {
containerName = " m a s t o d o n - s t a g i n g " ;
hostAddress = " 1 9 2 . 1 6 8 . 4 2 . 1 1 " ;
domain = " s t a g i n g . s n o o t . t u b e " ;
localAddress = " 1 9 2 . 1 6 8 . 4 2 . 1 3 " ;
autoStart = false ;
useElasticsearch = true ;
mastodonPackage = pkgs . mastodonStagingFork ;
forwardPorts = [
{
containerPort = 443 ;
hostPort = 4430 ;
protocol = " t c p " ;
}
{
containerPort = 80 ;
hostPort = 800 ;
protocol = " t c p " ;
}
] ;
imports = nestedContainerExtras . imports ;
disabledModules = nestedContainerExtras . disabledModules ;
acme = {
acceptTerms = true ;
defaults . email = " v i v l i m @ p m . m e " ;
defaults . server =
" h t t p s : / / l o c a l h o s t " ; # 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 = " s n o o t - t u b e - m a s t o d o n - s t a g i n g @ v v n . s p a c e " ;
host =
" 1 9 2 . 1 6 8 . 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 = " v v n . s p a c e " ;
SMTP_AUTH_METHOD = " n o n e " ;
SMTP_OPENSSL_VERIFY_MODE = " n o n e " ;
MAX_TOOT_CHARS = " 4 2 0 6 9 " ;
AUTHORIZED_FETCH = " t r u e " ;
LIMITED_FEDERATION_MODE = " t r u e " ;
USER_ACTIVE_DAYS = " 1 4 " ;
MAX_REACTIONS = " 8 " ;
SEARCH_SCOPE = " p u b l i c " ;
} ;
oauth2ProxyUsers = ''
viv
'' ;
oauth2ProxyKeys = config . sops . secrets . oauth2_proxy_keys . path ;
} ;
2023-02-20 18:24:12 -08:00
2023-03-04 18:42:59 -08:00
prodContainer = ( mastodonContainerFactory prodConfig ) ;
2023-03-05 14:48:21 -08:00
stagingContainer = ( mastodonContainerFactory stagingConfig ) ;
2023-03-04 18:42:59 -08:00
in {
2023-02-20 18:24:12 -08:00
config . networking . hostName = " m a s t o d o n - s n o o t t u b e " ;
config . networking . firewall . enable = true ;
2023-03-04 18:42:59 -08:00
config . networking . firewall . allowedTCPPorts =
[ 80 443 22 19999 19998 19980 19981 9102 4040 ] ;
config . networking . firewall . interfaces . " v e - + " . allowedTCPPorts =
[ 3128 ] ; # ssh forwarded http proxy
config . networking . firewall . interfaces . " v e - + " . allowedUDPPorts =
[ 9125 ] ; # statsd
2023-02-20 18:24:12 -08:00
config . networking . firewall . checkReversePath = " l o o s e " ;
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 ;
2023-03-04 18:42:59 -08:00
config . networking . nat . internalInterfaces = [ " v e - + " ] ;
2023-02-20 18:24:12 -08:00
config . networking . nat . externalInterface = " e n s 1 8 " ;
config . services . prometheus_exporters = {
enable = true ;
nodePort = 19982 ;
systemdPort = 19983 ;
combinedPort = 19980 ;
} ;
config . services . autossh = {
sessions = [ {
name = " s n o o t . t u b e _ i n g r e s s " ;
user = " r o o t " ;
monitoringPort = 0 ;
extraArguments =
2023-03-04 18:42:59 -08:00
" - o E x i t O n F o r w a r d F a i l u r e = y e s - o C o n n e c t T i m e o u t = 1 0 - o S e r v e r A l i v e I n t e r v a l = 1 5 - o S e r v e r A l i v e C o u n t M a x = 4 - N - R 4 4 3 3 : ${ prodConfig . localAddress } : 4 4 3 - L 3 1 2 8 : l o c a l h o s t : 3 1 2 8 - L 1 9 9 8 1 : l o c a l h o s t : 1 9 9 8 0 - L 1 9 9 9 8 : l o c a l h o s t : 1 9 9 9 9 - L 4 0 4 0 : l o c a l h o s t : 4 0 4 0 - g - i / r o o t / . s s h / i d _ e d 2 5 5 1 9 _ t o _ i n g r e s s s n o o t . t u b e - p 6 9 2 2 " ;
2023-03-05 14:48:21 -08:00
}
{
name = " s t a g i n g _ i n g r e s s " ;
user = " r o o t " ;
monitoringPort = 0 ;
extraArguments =
" - o E x i t O n F o r w a r d F a i l u r e = y e s - o C o n n e c t T i m e o u t = 1 0 - o S e r v e r A l i v e I n t e r v a l = 1 5 - o S e r v e r A l i v e C o u n t M a x = 4 - N - R 5 4 3 3 : ${ stagingConfig . localAddress } : 4 4 3 - g - i / r o o t / . s s h / i d _ e d 2 5 5 1 9 _ t o _ i n g r e s s s n o o t . t u b e - p 6 9 2 2 " ;
}
] ;
2023-02-20 18:24:12 -08:00
} ;
2023-03-05 14:48:21 -08:00
config . containers = {
mastodon = prodContainer . containerConfig ;
staging = stagingContainer . containerConfig ;
} ;
2023-02-20 18:24:12 -08:00
2023-03-04 18:42:59 -08:00
config . system . activationScripts . createMastodonContainerPaths =
pkgs . lib . stringAfter [ " s e t u p S e c r e t s " " v a r " ]
prodContainer . activationScript ;
2023-03-05 14:48:21 -08:00
config . system . activationScripts . createMastodonStagingContainerPaths =
pkgs . lib . stringAfter [ " s e t u p S e c r e t s " " v a r " ]
stagingContainer . activationScript ;
2023-02-20 18:24:12 -08:00
config . sops . secrets . oauth2_proxy_keys = { } ;
config . environment . systemPackages = [
( let
script = pkgs . writeShellScriptBin " t o o t c t l " ''
echo " u n t e s t e d ! c h e c k i f t h i s w o r k s a n d r e m o v e t h i s e c h o i f i t d o e s "
sudo nixos-container " r u n m a s t o d o n - - t o o t c t l $ @ \" "
'' ;
in pkgs . stdenv . mkDerivation {
name = " m a s t o d o n - c o n t a i n e r - t o o t c t l - w r a p p e r " ;
version = " 1 . 0 . 0 " ;
phases = " i n s t a l l P h a s e " ;
installPhase = ''
mkdir - p $ out/bin
cp $ { script } /bin /* $ o u t / b i n /
'' ;
} )
] ;
config . sops . defaultSopsFile = ../secrets/backend.yaml ;
config . sops . secrets . borg_backup_repo_passphrase = { } ;
2023-03-04 18:42:59 -08:00
config . sops . secrets . borgbase_ssh_private_key =
{ } ; # it is extremely important for this to have a trailing newline, or connecting will fail
2023-02-20 18:24:12 -08:00
config . services . borgbackup . jobs . " b o r g b a s e " = {
paths = [ " / v a r / l i b / m a s t o d o n - c o n t a i n e r " " / v a r / b a c k u p " ] ;
2023-03-04 18:42:59 -08:00
exclude = [ ] ;
2023-02-20 18:24:12 -08:00
repo = " h 5 g 8 7 o 5 w @ h 5 g 8 7 o 5 w . r e p o . b o r g b a s e . c o m : r e p o " ;
encryption = {
mode = " r e p o k e y - b l a k e 2 " ;
passCommand =
" c a t ${ config . sops . secrets . borg_backup_repo_passphrase . path } " ;
} ;
environment . BORG_RSH =
" s s h - i ${ config . sops . secrets . borgbase_ssh_private_key . path } " ;
compression = " a u t o , l z m a " ;
startAt = " d a i l y " ;
} ;
config . systemd . services . statsd-exporter = {
description = " S t a t s D E x p o r t e r " ;
wantedBy = [ " m u l t i - u s e r . t a r g e t " ] ;
after = [ " c o n t a i n e r @ m a s t o d o n . s e r v i c e " ] ;
serviceConfig = let
mappingFile = pkgs . writeText " s t a t s d - m a p p i n g . y a m l " ''
## 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 : " m a s t o d o n _ c o n t r o l l e r _ s t a t u s "
labels :
controller : $ 1
action : $ 2
format : $ 3
status : $ 4
mastodon : " w e b "
- match : Mastodon \ . production \ . web \ . ( . + ) \ . ( . + ) \ . ( . + ) \ . db_time
match_type : regex
name : " m a s t o d o n _ c o n t r o l l e r _ d b _ t i m e "
labels :
controller : $ 1
action : $ 2
format : $ 3
mastodon : " w e b "
- match : Mastodon \ . production \ . web \ . ( . + ) \ . ( . + ) \ . ( . + ) \ . view_time
match_type : regex
name : " m a s t o d o n _ c o n t r o l l e r _ v i e w _ t i m e "
labels :
controller : $ 1
action : $ 2
format : $ 3
mastodon : " w e b "
- match : Mastodon \ . production \ . web \ . ( . + ) \ . ( . + ) \ . ( . + ) \ . total_duration
match_type : regex
name : " m a s t o d o n _ c o n t r o l l e r _ d u r a t i o n "
labels :
controller : $ 1
action : $ 2
format : $ 3
mastodon : " w e b "
## Database collector
- match : Mastodon \ . production \ . db \ . tables \ . ( . + ) \ . queries \ . ( . + ) \ . duration
match_type : regex
name : " m a s t o d o n _ d b _ o p e r a t i o n "
labels :
table : " $ 1 "
operation : " $ 2 "
mastodon : " d b "
## Cache collector
- match : Mastodon \ . production \ . cache \ . ( . + ) \ . duration
match_type : regex
name : " m a s t o d o n _ c a c h e _ d u r a t i o n "
labels :
operation : " $ 1 "
mastodon : " c a c h e "
## Sidekiq collector
- match : Mastodon \ . production \ . sidekiq \ . ( . + ) \ . processing_time
match_type : regex
name : " m a s t o d o n _ s i d e k i q _ w o r k e r _ p r o c e s s i n g _ t i m e "
labels :
worker : " $ 1 "
mastodon : " s i d e k i q "
- match : Mastodon \ . production \ . sidekiq \ . ( . + ) \ . success
match_type : regex
name : " m a s t o d o n _ s i d e k i q _ w o r k e r _ s u c c e s s _ t o t a l "
labels :
worker : " $ 1 "
mastodon : " s i d e k i q "
- match : Mastodon \ . production \ . sidekiq \ . ( . + ) \ . failure
match_type : regex
name : " m a s t o d o n _ s i d e k i q _ w o r k e r _ f a i l u r e _ t o t a l "
labels :
worker : " $ 1 "
mastodon : " s i d e k i q "
- match : Mastodon \ . production \ . sidekiq \ . queues \ . ( . + ) \ . enqueued
match_type : regex
name : " m a s t o d o n _ s i d e k i q _ q u e u e _ e n q u e u e d "
labels :
queue : " $ 1 "
mastodon : " s i d e k i q "
- match : Mastodon \ . production \ . sidekiq \ . queues \ . ( . + ) \ . latency
match_type : regex
name : " m a s t o d o n _ s i d e k i q _ q u e u e _ l a t e n c y "
labels :
queue : " $ 1 "
mastodon : " s i d e k i q "
- match : Mastodon \ . production \ . sidekiq \ . ( . + )
match_type : regex
name : " m a s t o d o n _ s i d e k i q _ $ 1 "
labels :
mastodon : " s i d e k i q "
'' ;
in {
2023-03-04 18:42:59 -08:00
ExecStart =
" ${ pkgs . prometheus-statsd-exporter } / b i n / s t a t s d _ e x p o r t e r - - w e b . l i s t e n - a d d r e s s = ' : 9 1 0 2 ' - - s t a t s d . l i s t e n - u d p = ' : 9 1 2 5 ' - - s t a t s d . m a p p i n g - c o n f i g = ${ mappingFile } " ;
2023-02-20 18:24:12 -08:00
} ;
} ;
}
2023-03-04 18:42:59 -08:00