2022-10-17 22:40:48 +02:00
{ config , pkgs , . . . }:
let
lib = pkgs . lib ;
#webserver = "nginx" # httpd caddy lighttpd
domain = " ${ config . networking . hostName } . ${ config . networking . domain } " ;
mkDomain = subname : " ${ subname } . ${ domain } " ;
subdomains = lib . sort ( x : y : x < y ) ( # TODO: deduplicate <-
lib . flatten (
lib . mapAttrsToList
( k : v : [ k ] ++ v . serverAliases )
config . services . nginx . virtualHosts
)
) ;
in
with builtins ; {
imports = [
#./modules/kukkee.nix
2023-02-24 21:36:30 +01:00
#<nixos-unstable/nixos/modules/services/misc/polaris.nix>
#/home/pbsds/repos/nixpkgs-trees/polaris/nixos/modules/services/misc/polaris.nix
/home/pbsds/repos/nixpkgs/polaris-14/nixos/modules/services/misc/polaris.nix
] ;
disabledModules = [
" s e r v i c e s / m i s c / p o l a r i s . n i x "
] ;
nixpkgs . overlays = [
( final : prev : {
polaris = prev . callPackage /home/pbsds/repos/nixpkgs/polaris-14/pkgs/servers/polaris { } ;
polaris-web = prev . callPackage /home/pbsds/repos/nixpkgs/polaris-14/pkgs/servers/polaris/web.nix { } ;
} )
2022-10-17 22:40:48 +02:00
] ;
# ACME
# regenerate certs with:
# systemctl clean --what=state acme-noximilien.pbsds.net.service
security . acme . acceptTerms = true ;
security . acme . defaults . email = " p b s d s + a c m e @ h o t m a i l . c o m " ;
#security.acme.defaults.renewInterval = "daily";
#security.acme.defaults.reloadServices
# https://www.xf.is/2020/06/30/list-of-free-acme-ssl-providers/
#security.acme.defaults.server = "https://acme-staging-v02.api.letsencrypt.org/directory"; # STAGING
#security.acme.defaults.server = "https://api.buypass.com/acme/directory"; # no wildcards, rate limit: 20 domains/week, 5 duplicate certs / week
#security.acme.defaults.server = "https://api.test4.buypass.no/acme/directory"; # STAGING. no wildcards, rate limit: 20 domains/week, 5 duplicate certs / week
# DNS-based ACME:
# - https://go-acme.github.io/lego/dns/domeneshop/
# - https://nixos.org/manual/nixos/stable/index.html#module-security-acme-config-dns-with-vhosts
#security.acme.defaults.dnsProvider = "domeneshop";
#security.acme.defaults.credentialsFile = "/var/lib/secrets/domeneshop.key"; # TODO: this file must be made by hand, containing env variables.
services . nginx . enable = true ;
2023-02-24 21:36:30 +01:00
networking . firewall . allowedTCPPorts = [ 80 443 ] ;
2022-10-17 22:40:48 +02:00
# Website tunnel
# TODO: move to web profile?
services . nginx . virtualHosts . ${ domain } = {
forceSSL = true ; # addSSL = true;
enableACME = true ;
#acmeRoot = null; # use DNS
default = true ;
serverAliases = map mkDomain [
" w w w "
#"*" # requires DNS ACME
] ;
# The alternative to ^ is: config.security.acme.certs."${acmeDomain}".extraDomainNames = [ (mkDomain "foo") ];
# TODO: 'nox' alias for everything
locations . " / " = {
proxyPass = " h t t p : / / p b u n t u . p b s d s . n e t " ;
proxyWebsockets = true ;
} ;
} ;
#services.nginx.virtualHosts.${mkDomain "www"} = {
# addSSL = true;
# useACMEHost = acmeDomain; #enableACME = true;
# locations."/" = {
# proxyPass = "http://pbuntu.pbsds.net";
# proxyWebsockets = true;
# };
#};
# service index
# TODO: move to web profile?
services . nginx . virtualHosts . ${ mkDomain " i n d e x " } = {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
root = let
getName = domain : head ( lib . splitString " . " domain ) ;
getDomain = domain : concatStringsSep " . " ( tail ( lib . splitString " . " domain ) ) ;
custom = rec {
index = " T h i s p a g e " ;
links = " L i n k t r e e " ;
element = pkgs . element-web . meta . description ;
refleksjon = " M y d a d i s a c h e a p s k a t e " ;
roroslyd = " M y d a d i s a c h e a p s k a t e " ;
www = " w w w w w w w w w w w w w w w " ;
noximilien = www ;
shlink = " U r l s h o r t e n e r " ;
} ;
getDesc = domain : let
name = getName domain ;
in if lib . hasAttr name custom
then custom . ${ name }
else if lib . hasAttr name pkgs . python3Packages
then pkgs . python3Packages . ${ name } . meta . description
else if lib . hasAttr name pkgs
then pkgs . ${ name } . meta . description
else if lib . hasAttrByPath [ name " p a c k a g e " ] config . services
then config . services . ${ name } . package . meta . description
else " " ;
mkRow = domain : '' < t r > < t d > < a h r e f = " / / ${ domain } " > ${ getName domain } < s p a n s t y l e = \ " o p a c i t y : 0 . 6 5 ; \ " > . ${ getDomain domain } < / s p a n > < / a > < t d > ${ getDesc domain } '' ;
in pkgs . writeTextDir " i n d e x . h t m l " ''
< ! DOCTYPE html >
<table>
<tr> <th> url <th> description
$ { lib . concatStringsSep " \n " ( map mkRow subdomains ) }
< /table >
'' ;
} ;
# webdav
# Simple WebDAV server
services . webdav = {
enable = true ;
# the webdav user uid:gid is fixed
settings = {
address = " 1 2 7 . 0 . 0 . 1 " ;
port = 9568 ;
prefix = " / " ;
scope = " / m n t / r e i d u n / p u b " ;
modify = false ;
auth = true ;
users = [
{
username = " z o t e r o " ;
password = " { b c r y p t } $ 2 y $ 1 0 $ 9 z z Z u w d 2 A v N Z X b 8 W C G / b M . . i b O r o N n X 0 s N 9 4 U T A V . J c o 9 L n Z 8 W h s 2 " ;
#prefix = "/zotero/";
scope = " / m n t / r e i d u n / V a r i o u s / Z o t e r o " ;
modify = true ;
}
/* * /
{
username = " g u e s t " ;
password = " h u n t e r 2 " ;
}
/* */
] ;
} ;
} ;
services . nginx . virtualHosts . ${ mkDomain " w e b d a v " } = lib . mkIf config . services . webdav . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . webdav . settings . port } " ;
#proxyWebsockets = true;
extraConfig = ''
proxy_set_header X-Real-IP $ remote_addr ;
proxy_set_header REMOTE-HOST $ remote_addr ;
proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ;
proxy_set_header Host $ host ;
proxy_redirect off ;
client_max_body_size 2 G ;
'' ;
} ;
} ;
# Home assistant
services . home-assistant = {
#enable = true;
config = {
# https://www.home-assistant.io/integrations/default_config/
default_config = { } ;
# https://www.home-assistant.io/integrations/esphome/
#esphome = {};
# https://www.home-assistant.io/integrations/met/
#met = {};
} ;
} ;
# Flexget
# Multipurpose automation tool for all of your media
services . flexget = {
enable = true ;
user = " f l e x g e t " ; # The user under which to run flexget.
homeDir = " / v a r / l i b / f l e x g e t " ;
interval = " 3 0 m " ;
config = ''
tasks :
shanaproject :
rss : ' https://www.shanaproject.com/feeds/secure/user/35853/J98B7OXAHO/'
accept_all : yes
no_entries_ok : yes
transmission :
host : 192 .168 .1 .3
port : 9091
path : ' /Reidun/shared/Downloads/shana project / '
username : pbsds
password : spismeg
'' ;
} ;
users . groups . " ${ config . services . flexget . user } " = lib . mkIf config . services . flexget . enable { } ;
users . users . " ${ config . services . flexget . user } " = lib . mkIf config . services . flexget . enable {
isSystemUser = true ;
createHome = true ;
home = config . services . flexget . homeDir ;
group = " ${ config . services . flexget . user } " ;
} ;
# Graphana
# Gorgeous metric viz, dashboards & editors for Graphite, InfluxDB & OpenTSDB
services . grafana = rec {
#enable = true;
#addr = "127.0.0.1";
2023-02-24 21:36:30 +01:00
settings . server . http_addr = " 0 . 0 . 0 . 0 " ;
settings . server . http_port = 3000 ;
settings . server . domain = mkDomain " g r a f a n a " ;
2022-10-17 22:40:48 +02:00
#rootUrl = "https://${domain}/grafana/"; # Not needed if it is `https://your.domain/`
} ;
2023-02-24 21:36:30 +01:00
services . nginx . virtualHosts . " ${ config . services . grafana . settings . server . domain } " = lib . mkIf config . services . grafana . enable {
2022-10-17 22:40:48 +02:00
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
#locations."/grafana/" = {
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . grafana . port } " ;
proxyWebsockets = true ;
} ;
} ;
# OwnCast
# self-hosted video live streaming solution
services . owncast = {
# the default /admin account is admin:abc123, don't enable if you don't intend to change it!
enable = true ;
port = 3456 ; # default is 8080
rtmp-port = 1935 ; # remember to punch a TCP hole in the NAT
#listen = "0.0.0.0"; # default is "127.0.0.1"
openFirewall = true ; # the rtmp port, and the http port if listen != "127.0.0.1"
} ;
services . nginx . virtualHosts . ${ mkDomain " o w n c a s t " } = lib . mkIf config . services . owncast . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . owncast . port } " ;
proxyWebsockets = true ;
} ;
} ;
# Cryptpad
# A collaborative office suite that is end-to-end encrypted and open-source.
2023-02-24 21:36:30 +01:00
# TODO: https://github.com/NixOS/nixpkgs/pull/180066
/*
2022-10-17 22:40:48 +02:00
services . cryptpad = {
#enable = true; # current node version used is marked insecure
# reference: https://github.com/xwiki-labs/cryptpad/blob/main/config/config.example.js
configFile = toFile " c r y p t p a d - c o n f i g . j s " ''
module . exports = {
httpUnsafeOrigin : ' http://localhost:3457',
httpSafeOrigin : ' https://$ { mkDomain " c r y p t p a d " } ' ,
httpAddress : ' 127 .0 .0 . 1 ' ,
httpPort : 3457 ,
// adminKeys : [ // can be found on the settings page for registered users
// " [ c r y p t p a d - u s e r 1 @ m y . a w e s o m e . w e b s i t e / Y Z g X Q x K R 0 R c b 6 r 6 C m x H P d A G L V l u d r A F 2 l E n k b x 1 v V O o = ] " ,
// ] ,
// storage
// inactiveTime : 90 , // days
// archiveRetentionTime : 15 , // days
// accountRetentionTime : 365 , // days , default is never
// maxUploadSize : 20 * 1024 * 1024 , // bytes
// premiumUploadSize : 100 * 1024 * 1024 , // bytes , ( users with a plan in their customLimit )
filePath : ' ./datastore / ' ,
archivePath : ' ./data/archive ' , // recovery in the event of accidental deletion
pinPath : ' ./data/pins ' , // content stored indefinetly
taskPath : ' ./data/tasks ' , // scheduled tasks
blockPath : ' ./block ' , // users' authenticated blocks
blobPath : ' ./blob ' , // uploaded encrypted blobs
blobStagingPath : ' ./data/blobstage ' , // incomplete blobs
decreePath : ' ./data/decrees ' , // undocumented
logPath : false , // logging of events , may be set to false
logToStdout : true ,
logLevel : ' info' , // silly , verbose , debug , feedback , info , warn , error
logFeedback : false , // data collection
verbose : false , // logging
installMethod : ' nixpkgs' , // telemetry for devs
} ;
'' ;
} ;
services . nginx . virtualHosts . ${ mkDomain " c r y p t p a d " } = lib . mkIf config . services . cryptpad . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : 3 4 5 7 " ;
proxyWebsockets = true ;
} ;
} ;
2023-02-24 21:36:30 +01:00
* /
2022-10-17 22:40:48 +02:00
# Jellyfin
services . jellyfin = {
enable = true ; # don't enable unless you intend to first-time-setup the admin user
# from https://jellyfin.org/docs/general/networking/index.html:
# - 8096/tcp is used by default for HTTP traffic. You can change this in the dashboard.
# - 8920/tcp is used by default for HTTPS traffic. You can change this in the dashboard.
# - 1900/udp is used for service auto-discovery. This is not configurable.
# - 7359/udp is also used for auto-discovery. This is not configurable.
openFirewall = false ; # I do it manually below:
# TODO: configure initial collections and extensions
} ;
2023-02-24 21:36:30 +01:00
# firewall - not needed?
/*
networking . firewall = lib . mkIf config . services . jellyfin . enable {
2022-10-17 22:40:48 +02:00
# TODO: does this overwrite rules set by other stuff? should i use ++ ?
#allowedTCPPorts = [ 8096 8920 ];
allowedUDPPorts = [ 1900 7359 ] ; # TODO: Only if behind a NAT?
} ;
2023-02-24 21:36:30 +01:00
* /
2022-10-17 22:40:48 +02:00
services . nginx . virtualHosts . ${ mkDomain " j e l l y f i n " } = lib . mkIf config . services . jellyfin . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : 8 0 9 6 " ;
proxyWebsockets = true ;
} ;
} ;
# Hardware acceleration
2023-02-24 21:36:30 +01:00
# https://nixos.wiki/wiki/Jellyfin
2022-10-17 22:40:48 +02:00
nixpkgs . config . packageOverrides = pkgs : {
vaapiIntel = pkgs . vaapiIntel . override { enableHybridCodec = true ; } ;
} ;
hardware . opengl = {
enable = true ;
extraPackages = with pkgs ; [
intel-media-driver
vaapiIntel
vaapiVdpau
libvdpau-va-gl
2023-02-24 21:36:30 +01:00
intel-compute-runtime # OpenCL filter support (hardware tonemapping and subtitle burn-in)
2022-10-17 22:40:48 +02:00
] ;
} ;
# Allow Jellyfin access to VAAPI
users . users . ${ config . services . jellyfin . user } . extraGroups = [ " v i d e o " " r e n d e r " ] ;
systemd . services . jellyfin . serviceConfig . PrivateDevices = lib . mkForce false ;
systemd . services . jellyfin . serviceConfig . DeviceAllow = lib . mkForce [ " / d e v / d r i / r e n d e r D 1 2 8 " ] ;
# Navidrome
# Music Server and Streamer compatible with Subsonic/Airsonic
services . navidrome = {
enable = true ;
settings = {
# default hostname:port = "127.0.0.1:4533"
MusicFolder = " / m n t / r e i d u n / M u s i c / A l b u m s " ;
#MusicFolder = pkgs.linkFarm "navidrome-music-library" [
# { name = "Albums"; path = "/mnt/reidun/Music/Albums"; }
# { name = "OST"; path = "/mnt/reidun/Music/OST"; }
# { name = "dojin.co"; path = "/mnt/reidun/Music/dojin.co"; }
# { name = "Touhou"; path = "/mnt/reidun/Music/Touhou"; }
# { name = "Kancolle"; path = "/mnt/reidun/Music/Kancolle"; }
# { name = "Vocaloid"; path = "/mnt/reidun/Music/Vocaloid"; }
#];
UIWelcomeMessage = " S p i s m e g " ;
DefaultTheme = " S p o t i f y - i s h " ;
} ;
} ;
services . nginx . virtualHosts . ${ mkDomain " n a v i d r o m e " } = lib . mkIf config . services . navidrome . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : 4 5 3 3 " ;
proxyWebsockets = true ;
} ;
} ;
# Polaris
# Self-host your music collection, and access it from any computer and mobile device
services . polaris = {
enable = true ;
#user = "pbsds";
#group = "users";
port = 7890 ;
2023-02-24 21:36:30 +01:00
#package = pkgs.unstable.polaris; # instead of my overlay, TODO: move that overlay here
2022-10-17 22:40:48 +02:00
settings = {
settings . reindex_every_n_seconds = 7 * 24 * 60 * 60 ; # weekly, default is 1800, i.e. hourly
settings . album_art_pattern =
" ( [ C c ] o v e r | C O V E R | [ F f ] o l d e r | F O L D E R | [ F f ] r o n t | F R O N T ) \. ( j p e g | J P E G | j p g | J P G | p n g | P N G | b m p | B M P | g i f | G I F ) " ;
#"(?i)(cover|folder|front)\.(jpeg|jpg|png|bmp|gif)";
mount_dirs = [
2023-02-24 21:36:30 +01:00
{ name = " A l b u m s " ; source = " / m n t / r e i d u n / M u s i c / A l b u m s " ; }
{ name = " d o j i n . c o " ; source = " / m n t / r e i d u n / M u s i c / d o j i n . c o " ; }
{ name = " V o c a l o i d " ; source = " / m n t / r e i d u n / M u s i c / V o c a l o i d " ; }
{ name = " T o u h o u " ; source = " / m n t / r e i d u n / M u s i c / T o u h o u " ; }
{ name = " O S T " ; source = " / m n t / r e i d u n / M u s i c / O S T " ; }
{ name = " K a n c o l l e " ; source = " / m n t / r e i d u n / M u s i c / K a n c o l l e " ; }
{ name = " D o w n l o a d s " ; source = " / m n t / r e i d u n / D o w n l o a d s / m u s i c " ; }
2022-10-17 22:40:48 +02:00
] ;
} ;
} ;
services . nginx . virtualHosts . ${ mkDomain " p o l a r i s " } = lib . mkIf config . services . polaris . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . polaris . port } " ;
proxyWebsockets = true ;
} ;
} ;
# Hydra
# Nix-based continuous build system
# https://github.com/NixOS/hydra
# https://nixos.wiki/wiki/Hydra
# sudo -u hydra hydra-create-user 'admin' --full-name '<NAME>' --email-address '<EMAIL>' --password-prompt --role admin
# https://blog.matejc.com/blogs/myblog/nixos-hydra-nginx
services . hydra = {
enable = true ;
hydraURL = " h t t p s : / / ${ mkDomain " h y d r a " } " ;
#smtpHost = ;
listenHost = " l o c a l h o s t " ;
port = 4758 ;
notificationSender = " h y d r a @ ${ domain } " ; # Sender email address used for email notifications.
#buildMachinesFiles = [];
#useSubstitutes = true;
#debugServer = true;
#logo = /some/path.png;
#minimumDiskFree = 0; # Minimum disk space (GiB) determining if queue runner runs or not.
#minimumDiskFreeEvaluator = 0; # Minimum disk space (GiB) determining if evaluator runs or not.
} ;
services . nginx . virtualHosts . ${ mkDomain " h y d r a " } = lib . mkIf config . services . hydra . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . hydra . port } " ;
proxyWebsockets = true ;
extraConfig = ''
proxy_set_header Host $ host ;
proxy_set_header X-Real-IP $ remote_addr ;
proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ;
proxy_set_header X-Forwarded-Proto $ scheme ;
add_header Front-End-Https on ;
'' ;
} ;
} ;
# Sourcegraph
# Understand, fix, and automate across your codebase with this code intelligence platform
/* * /
# First user regitration becomes admin
# data can be destryoed with `nixos-container destroy sourcegraph`
virtualisation . oci-containers . containers . " s o u r c e g r a p h " = {
autoStart = true ;
#image = "sourcegraph/server:3.41.0";
#image = "sourcegraph/server:latest";
image = " s o u r c e g r a p h / s e r v e r : i n s i d e r s " ;
environment = { } ;
ports = [
" 1 2 7 . 0 . 0 . 1 : 7 0 8 0 : 7 0 8 0 / t c p " # webui?
" 1 2 7 . 0 . 0 . 1 : 3 3 7 0 : 3 3 7 0 / t c p " # admin? (graphana and stuff)
] ;
volumes = [
" / v a r / l i b / s o u r c e g r a p h / c o n f i g : / e t c / s o u r c e g r a p h "
" / v a r / l i b / s o u r c e g r a p h / d a t a : / v a r / o p t / s o u r c e g r a p h "
] ;
} ;
systemd . services . " c r e a t e - s o u r c e g r a p h - v o l u m e - d i r s " = {
wantedBy = [ " ${ config . virtualisation . oci-containers . backend } - s o u r c e g r a p h . s e r v i c e " ] ;
serviceConfig . Type = " o n e s h o t " ;
script = ''
mkdir - p /var/lib/sourcegraph/config
mkdir - p /var/lib/sourcegraph/data
'' ;
} ;
services . nginx . virtualHosts . ${ mkDomain " s o u r c e g r a p h " }
= lib . mkIf config . virtualisation . oci-containers . containers . " s o u r c e g r a p h " . autoStart {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : 7 0 8 0 " ;
proxyWebsockets = true ;
} ;
#locations."/graphana/" = {
# proxyPass = "http://127.0.0.1:3370";
# proxyWebsockets = true;
#};
} ;
/* */
# Shlink
# URL shortener with REST API and command line interface
# manage with https://app.shlink.io/
# TODO: self-host shlink web client? https://shlink.io/documentation/shlink-web-client/
/* * /
# data can be destryoed with `nixos-container destroy shlink`
virtualisation . oci-containers . containers . " s h l i n k " = {
autoStart = true ;
image = " s h l i n k i o / s h l i n k : s t a b l e " ;
# https://shlink.io/documentation/install-docker-image/
environment = {
" D E F A U L T _ D O M A I N " = mkDomain " s h l i n k " ;
" I S _ H T T P S _ E N A B L E D " = " t r u e " ;
" T I M E Z O N E " = " E u r o p e / O s l o " ;
#"GEOLITE_LICENSE_KEY" = ; # https://shlink.io/documentation/geolite-license-key/
# TODO: use postgres? default is sqlite3?
} ;
ports = [
" 1 2 7 . 0 . 0 . 1 : 5 7 5 7 : 8 0 8 0 / t c p " # webui
] ;
volumes = [
" / v a r / l i b / s h l i n k / d a t a b a s e . s q l i t e : / e t c / s h l i n k / d a t a / d a t a b a s e . s q l i t e "
# TODO: where is the sqlite file?
] ;
} ;
systemd . services . " c r e a t e - s h l i n k - v o l u m e - d i r s " = {
wantedBy = [ " ${ config . virtualisation . oci-containers . backend } - s h l i n k . s e r v i c e " ] ;
serviceConfig . Type = " o n e s h o t " ;
script = ''
mkdir - p /var/lib/shlink
touch /var/lib/shlink/database.sqlite
'' ;
} ;
services . nginx . virtualHosts . ${ mkDomain " s h l i n k " }
= lib . mkIf config . virtualisation . oci-containers . containers . " s h l i n k " . autoStart {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : 5 7 5 7 " ;
proxyWebsockets = true ;
} ;
} ;
programs . bash . shellAliases = {
shlink = " d o c k e r e x e c - i t s h l i n k s h l i n k " ;
} ;
/* */
# Resilio Sync
# Automatically sync files via secure, distributed technology
services . resilio = {
#enable = true;
#downloadLimit = 0;
#uploadLimit = 0;
#directoryRoot = "/media" # Default directory to add folders in the web UI.
#storagePath = "/var/lib/resilio-sync/"; # Where BitTorrent Sync will store it's database files
httpLogin = " " ;
httpPass = " " ;
deviceName = " ${ config . networking . hostName } " ;
#apiKey = ; # API key, which enables the developer API.
#httpListenPort = 9000;
#httpListenAddr = "[::1]";
enableWebUI = false ; # default is false
} ;
services . nginx . virtualHosts . ${ mkDomain " r e s i l i o " } = let
cfg = config . services . resilio ;
in lib . mkIf ( cfg . enable && cfg . enableWebUI ) {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ cfg . httpListenPort } " ;
proxyWebsockets = true ;
} ;
} ;
# Gitea
# Git with a cup of tea
services . gitea = rec {
enable = true ;
2023-02-24 21:36:30 +01:00
settings . service . DISABLE_REGISTRATION = true ; # disable after initial deploy
2022-10-17 22:40:48 +02:00
#https://docs.gitea.io/en-us/config-cheat-sheet/
#settings = {
# "cron.sync_external_users" = {
# RUN_AT_START = true;
# SCHEDULE = "@every 24h";
# UPDATE_EXISTING = true;
# };
# mailer = {
# ENABLED = true;
# MAILER_TYPE = "sendmail";
# FROM = "do-not-reply@example.org";
# SENDMAIL_PATH = "${pkgs.system-sendmail}/bin/sendmail";
# };
# other = {
# SHOW_FOOTER_VERSION = false;
# };
#};
#appName = "gitea: spis meg";
appName = " g i t e a : p r i v a t e i n s t a n c e " ;
domain = mkDomain " g i t e a " ;
#ssh.enable # default is true
rootUrl = " h t t p s : / / ${ domain } / " ;
#ssh.clonePort # default is 22
#log.level = "Debug"; # default is "Info"
#lfs.enable = true; # default is false
httpPort = 9675 ; # default is 3000
httpAddress = " 1 2 7 . 0 . 0 . 1 " ; # default is "0.0.0.0"
#extraConfig
#database.type # default is "sqlite3"
2023-02-24 21:36:30 +01:00
settings . session . COOKIE_SECURE = true ; # default is false, only send cookies over https
2022-10-17 22:40:48 +02:00
#stateDir # default is "/var/lib/gitea"
#mailerPasswordFile # Path to a file containing the SMTP password
#repositoryRoot # default is "${config.services.gitea.stateDir}/repositories"
#log.rootPath # TODO: move?
#lfs.contentDir
#dump.enable # default is false
staticRootPath = pkgs . symlinkJoin {
name = " g i t e a - s t a t i c - r o o t - d a t a " ;
paths = let
giteaModern = pkgs . fetchFromGitea { # https://codeberg.org/Freeplay/Gitea-Modern
domain = " c o d e b e r g . o r g " ;
owner = " F r e e p l a y " ;
repo = " G i t e a - M o d e r n " ;
rev = " 0 c 0 a 0 5 e 6 f 0 4 9 6 5 2 1 c 1 6 6 4 0 2 d d 5 6 4 4 1 a 7 1 4 4 8 7 f d 8 " ;
sha256 = " q 1 4 E 5 n i 2 B v p G s m G O H W Q g b C q D 4 l B h 4 b F t B F t I y N f A f 0 Q = " ;
} ;
giteaEarlGray = pkgs . fetchFromGitHub { # https://github.com/acoolstraw/earl-grey
owner = " a c o o l s t r a w " ;
repo = " e a r l - g r e y " ;
rev = " a 6 c a 3 d d 3 b 9 e 6 b 4 8 f 6 e 4 5 0 3 2 b 2 a a 6 9 1 c 2 f 1 6 d c 9 b c " ;
sha256 = " 5 5 P i a f c 7 k Q 5 h y b w H Q c z x 3 6 A P + k X 1 A t W u g x E R Y N d m q W k = " ;
} ;
in [
config . services . gitea . package . data
( pkgs . linkFarm " g i t e a - c u s t o m - d i r " [
{ name = " p u b l i c / c s s / t h e m e - g i t e a - m o d e r n . c s s " ; path = " ${ giteaModern } / G i t e a / t h e m e - g i t e a - m o d e r n . c s s " ; }
{ name = " p u b l i c / c s s / t h e m e - e a r l - g r e y . c s s " ; path = " ${ giteaEarlGray } / t h e m e - e a r l - g r e y . c s s " ; }
] )
] ;
} ;
settings = {
# https://docs.gitea.io/en-us/config-cheat-sheet/
ui . THEMES = " g i t e a , a r c - g r e e n , e a r l - g r e y , g i t e a - m o d e r n " ;
ui . DEFAULT_THEME = " e a r l - g r e y " ;
} ;
} ;
services . nginx . virtualHosts . ${ mkDomain " g i t e a " } = lib . mkIf config . services . gitea . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . gitea . httpPort } " ;
proxyWebsockets = true ;
} ;
} ;
# TODO: mailcatcher
# TODO: configure stuff to send its shit here
# ntopng
# High-speed web-based traffic analysis and flow collection tool
# WARNING: default username and password is admin:admin
services . ntopng = {
enable = true ; # also enables redis for persistent data storage
httpPort = 3987 ; # HTTP port of embedded web server
#interfaces = [ "any" ];
#extraConfig = ";
#redis.address = "";
#redis.createInstance = "ntopng";
} ;
services . nginx . virtualHosts . ${ mkDomain " n t o p n g " } = lib . mkIf config . services . ntopng . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . ntopng . httpPort } " ;
proxyWebsockets = true ;
} ;
} ;
# TODO: kukkee or rallly
# https://noted.lol/2-self-hosted-alternatives-to-doodle-meeting-scheduling/
#https://rallly.co/
# Kukkee
# Self-hosted Doodle alternative: a meeting poll tool
/* * /
services . kukkee = {
#enable = true;
port = 5666 ;
baseUrl = " h t t p s : / / ${ mkDomain " k u k k e e " } " ;
#mongodb.enable = false;
} ;
services . nginx . virtualHosts . ${ mkDomain " k u k k e e " } = lib . mkIf config . services . kukkee . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . kukkee . port } " ;
proxyWebsockets = true ;
} ;
} ;
/* */
# Nitter
# Alternative Twitter front-end
services . nitter = {
enable = true ;
package = pkgs . unstable . nitter ;
#openFirewall
#config.base64Media = false; # Use base64 encoding for proxied media URLs.
server . title = " P j i t t e r " ;
server . address = " 1 2 7 . 0 . 0 . 1 " ;
server . hostname = mkDomain " n i t t e r " ;
server . https = true ; # Secure cookies
server . port = 4965 ;
#preferences.autoplayGifs = ; # default is true
#preferences.bidiSupport = ; # Support bidirectional text (makes clicking on tweets harder). default is false
#preferences.hideBanner = ; # Hide profile banner. default is false
#preferences.hidePins = ; # Hide pinned tweets. default is false
#preferences.hideReplies = ; # Hide tweet replies. default is false
#preferences.hideTweetStats = ; # Hide tweet stats (replies, retweets, likes). default is false
preferences . hlsPlayback = true ; # Enable HLS video streaming (requires JavaScript). default is false
preferences . infiniteScroll = true ; # Infinite scrolling (requires JavaScript, experimental!). default is false
#preferences.mp4Playback = ; # Enable MP4 video playback. default is true
#preferences.muteVideos = ; # Mute videos by default. default is false
#preferences.proxyVideos = ; # Proxy video streaming through the server (might be slow). default is true
preferences . replaceInstagram = " b i b l i o g r a m . a r t " ; # Replace Instagram links with links to this instance (blank to disable). default is ""
preferences . replaceTwitter = mkDomain " n i t t e r " ; # Replace Twitter links with links to this instance (blank to disable). default is ""
preferences . replaceYouTube = lib . mkIf config . services . invidious . enable ( mkDomain " i n v i d i o u s " ) ; # Replace YouTube links with links to this instance (blank to disable). default is ""
settings = lib . mkIf config . services . libreddit . enable {
Preferences . replaceReddit = ( mkDomain " l i b r e d d i t " ) ; # Replace Reddit links with links to this instance (blank to disable). default is ""
} ;
#preferences.stickyProfile = ; # Make profile sidebar stick to top. default is true
preferences . theme = " T w i t t e r D a r k " ; # Instance theme. default is "Nitter"
} ;
services . nginx . virtualHosts . ${ mkDomain " n i t t e r " } = lib . mkIf config . services . nitter . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . nitter . server . port } " ;
proxyWebsockets = true ;
} ;
} ;
# Invidious
# An open source alternative front-end to YouTube
services . invidious = {
enable = true ;
domain = mkDomain " i n v i d i o u s " ;
port = 4765 ;
settings = {
host_binding = " 1 2 7 . 0 . 0 . 1 " ;
external_port = 443 ;
https_only = true ;
statistics_enabled = false ; # api endpoint required for public instances
registration_enabled = false ;
login_enabled = false ;
#admins = ["pbsds"];
banner = " s p i s m e g " ;
default_user_preferences = {
#feed_menu = ["Popular", "Trending", "Subscriptions", "Playlists"]
feed_menu = [ " T r e n d i n g " " S u b s c r i p t i o n s " " P l a y l i s t s " ] ;
default_home = " T r e n d i n g " ;
} ;
} ;
} ;
services . nginx . virtualHosts . ${ mkDomain " i n v i d i o u s " } = lib . mkIf config . services . invidious . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . invidious . port } " ;
proxyWebsockets = true ;
} ;
} ;
# Libreddit
# Private front-end for Reddit
services . libreddit = {
enable = true ;
address = " 1 2 7 . 0 . 0 . 1 " ;
port = 4876 ;
} ;
systemd . services . libreddit . environment = lib . mkIf config . services . libreddit . enable {
# https://github.com/spikecodes/libreddit#change-default-settings=
# TODO: merge my module addition
LIBREDDIT_DEFAULT_THEME = " g o l d " ;
} ;
services . nginx . virtualHosts . ${ mkDomain " l i b r e d d i t " } = lib . mkIf config . services . libreddit . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . libreddit . port } " ;
proxyWebsockets = true ;
} ;
} ;
# paperless-ngx
# A supercharged version of paperless: scan, index, and archive all of your physical documents
services . paperless = {
enable = true ;
#package = pkgs.paperless-ngx;
#port = 28981;
#address = "localhost";
#passwordfile = null; # file contining the superuser 'admin' password, optionally set with `${datadir}/paperless-manage createsuperuser`
#datadir = "/var/lib/paperless";
#mediadir = "${datadir}/media";
#consumptiondir = "${datadir}/consume"; # Directory from which new documents are imported. (TODO: zotero)
#extraconfig = {};
#consumptiondirispublic = false; # Whether all users can write to the consumption dir
} ;
services . nginx . virtualHosts . ${ mkDomain " p a p e r l e s s " } = lib . mkIf config . services . paperless . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . paperless . port } " ;
proxyWebsockets = true ;
} ;
} ;
# Netdata
# Real-time performance monitoring tool
services . netdata = {
enable = true ;
#python.enable = false; # default is true
#python.extraPackages = ps: [];
#config = { # https://github.com/netdata/netdata/blob/master/daemon/config/README.md
# hostname = "";
# port = 19999;
#};
#configDir = {};
#extraPluginPaths = [];
} ;
services . nginx . virtualHosts . ${ mkDomain " n e t d a t a " } = lib . mkIf config . services . netdata . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : 1 9 9 9 9 " ;
proxyWebsockets = true ;
} ;
} ;
# upterm
# Secure terminal-session sharing
services . uptermd = {
enable = false ;
openFirewall = true ;
#listenAddress # default is "[::]";
#port = 2222; # default is 2222, uses ssh
#extraFlags
#hostKey = null;
} ;
# thelunge
# The self-hosted Web IRC client
services . thelounge = {
# configure user accounts by using the 'thelounge' command, or by adding entries to /var/lib/thelounge/users
enable = true ;
public = false ;
port = 5876 ;
# theLoungePlugins.themes is view of nodePackages_latest.thelounge-theme-*
# theLoungePlugins.plugins is view of nodePackages_latest.thelounge-plugin-*
plugins = with pkgs . theLoungePlugins ;
( with lib ; attrValues ( filterAttrs ( name : _ : name != " r e c u r s e F o r D e r i v a t i o n s " ) themes ) )
++ [
#plugins.giphy
#plugins.shortcuts
plugins . closepms
] ;
extraConfig . theme = " O n e D a r k " ;
extraConfig . fileUpload . enable = true ;
extraConfig . fileUpload . baseUrl = " ${ mkDomain " t h e l o u n g e " } " ;
} ;
services . nginx . virtualHosts . ${ mkDomain " t h e l o u n g e " } = lib . mkIf config . services . thelounge . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . thelounge . port } " ;
proxyWebsockets = true ;
} ;
} ;
# Convos
# The simplest way to use IRC in your browser
services . convos = {
enable = false ; # user registration is borken. new major version (7) in unstable.
reverseProxy = true ;
listenAddress = " 1 2 7 . 0 . 0 . 1 " ;
listenPort = 44649 ;
} ;
services . nginx . virtualHosts . ${ mkDomain " c o n v o s " } = lib . mkIf config . services . convos . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . convos . listenPort } " ;
proxyWebsockets = true ;
extraConfig = ''
#proxy_redirect off;
client_max_body_size 0 ;
proxy_set_header Upgrade $ http_upgrade ;
proxy_set_header Connection " u p g r a d e " ;
proxy_set_header Host $ host ;
proxy_set_header X-Forwarded-For $ proxy_add_x_forwarded_for ;
proxy_set_header X-Request-Base " $ s c h e m e : / / $ h o s t / " ;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header REMOTE-HOST $remote_addr;
'' ;
} ;
} ;
# Roundcube
# Open Source Webmail Software
services . roundcube = {
enable = true ;
hostName = mkDomain " r o u n d c u b e " ;
plugins = [
" a r c h i v e "
" z i p d o w n l o a d "
" m a n a g e s i e v e "
] ;
extraConfig = ''
$ config [ ' product_name' ] = ' Spis meg' ;
$ config [ ' skin_logo' ] = [
#'elastic:login' => 'https://links.pbsds.net/img/piuy_render.png',
#'elastic:*[small]' => 'https://links.pbsds.net/img/piuy_render.png',
' elastic:*' = > ' https://links.pbsds.net/img/piuy_render.png',
#'elastic:*' => 'https://links.pbsds.net/img/nox.png',
] ;
#$config['blankpage_url'] = '/something.html' # TODO <-
$ config [ ' default_host' ] = [
' tls://imap.fyrkat.no' = > ' Fyrkat' ,
' tls://imap.pvv.ntnu.no' = > ' PVV' ,
' tls://imap.nvg.ntnu.no' = > ' NVG' ,
] ;
$ config [ ' smtp_server' ] = [
' imap . fyrkat . no' = > ' tls://smtp.fyrkat.no',
' imap . pvv . ntnu . no' = > ' tls://smtp.pvv.ntnu.no',
' imap . nvg . ntnu . no' = > ' tls://smtp.nvg.ntnu.no',
] ;
# plugins/managesieve/config.inc.php.dist
$ config [ ' managesieve_host' ] = ' tls://%h' ;
'' ;
} ;
services . nginx . virtualHosts . ${ mkDomain " r o u n d c u b e " } = lib . mkIf config . services . roundcube . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / s k i n s / e l a s t i c / i m a g e s / l o g o . s v g " = {
#alias = "/path/to/file";
#return = "302 https://links.pbsds.net/img/piuy_render.png";
return = " 3 0 2 h t t p s : / / l i n k s . p b s d s . n e t / i m g / n o x . p n g " ;
} ;
} ;
# Galene
# Videoconferencing server that is easy to deploy, written in Go
services . galene = {
#enable = true;
insecure = true ; # reverse proxy instead, but can i feed it the acme cert?
httpAddress = " 1 2 7 . 0 . 0 . 1 " ;
httpPort = 3975 ;
} ;
services . nginx . virtualHosts . ${ mkDomain " g a l e n e " } = lib . mkIf config . services . galene . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . galene . httpPort } " ;
proxyWebsockets = true ;
} ;
} ;
#networking.firewall = lib.mkIf config.service.jellyfin.enable {
# allowedTCPPorts = [ 1194 ];
# allowedUDPPorts = [ 1194 ]; # TODO: Only if behind a NAT?
#};
# Jitsi meet
services . jitsi-meet = {
#enable = true;
hostName = mkDomain " j i t s i - m e e t " ;
config = {
# https://github.com/jitsi/jitsi-meet/blob/master/config.js
#enableWelcomePage = false;
defaultLang = " n b " ;
} ;
interfaceConfig = {
# https://github.com/jitsi/jitsi-meet/blob/master/interface_config.js"
APP_NAME = " S p i s m e g " ;
# SHOW_JITSI_WATERMARK = false;
# SHOW_WATERMARK_FOR_GUESTS = false;
} ;
jibri . enable = false ; # record in a headless chrome instance
nginx . enable = true ; # force ssl, acme, lots of routing rules
} ;
# Rocketchat
# A self-hosted discord/slack alternative
# TODO, docker exists, but no nixos module
# Mattermost
# Open-source, self-hosted Slack-alternative
services . mattermost = {
enable = true ;
# will create and use a psql db
listenAddress = " [ : : 1 ] : 8 0 6 5 " ;
siteName = " S p i s m e g " ;
siteUrl = " h t t p s : / / ${ mkDomain " m a t t e r m o s t " } " ;
#mutableConfig = true; # default is false, if true, see also "preferNixConfig"
extraConfig = {
# https://docs.mattermost.com/configure/configuration-settings.html#reporting
# TODO: smtp
} ;
matterircd = {
#enable = true; # default is false
parameters = [
" - m m s e r v e r c h a t . e x a m p l e . c o m "
" - b i n d [ : : ] : 6 6 6 7 "
] ;
} ;
} ;
services . nginx . virtualHosts . ${ mkDomain " m a t t e r m o s t " } = lib . mkIf config . services . mattermost . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / ${ config . services . mattermost . listenAddress } " ;
proxyWebsockets = true ;
} ;
} ;
# hedgedoc
# Realtime collaborative markdown notes on all platforms
services . hedgedoc = {
#enable = true; # FIXME: make it load
2023-02-24 21:36:30 +01:00
settings . host = " 1 2 7 . 0 . 0 . 1 " ;
settings . port = 44776 ;
settings . db . dialect = " s q l i t e " ;
settings . db . storage = " ${ config . services . hedgedoc . workDir } / d b . h e d g e d o c . s q l i t e " ;
settings . domain = mkDomain " h e d g e d o c " ;
settings . allowAnonymous = true ;
settings . allowEmailRegister = false ; # default is true
settings . allowAnonymousEdits = false ; # default is false
settings . protocolUseSSL = true ; # https prefix
settings . useSSL = false ; # nginx terminates ssl
#settings.csp = {TODO}; # content security policy
#settings.useCDN = true;
#settings.debug = true;
2022-10-17 22:40:48 +02:00
# there are also a metric fuckton of integration services, like github, twitter, minio, mattermost, dropbox etc.
# there are also auth options, like ldap, saml and oauth2
} ;
services . nginx . virtualHosts . ${ mkDomain " h e d g e d o c " } = lib . mkIf config . services . hedgedoc . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
2023-02-24 21:36:30 +01:00
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . hedgedoc . settings . port } " ;
2022-10-17 22:40:48 +02:00
proxyWebsockets = true ;
# TODO: proxy headers:
# https://docs.hedgedoc.org/guides/reverse-proxy/
} ;
} ;
# Cinny
# Yet another Matrix client for the web
services . nginx . virtualHosts . ${ mkDomain " c i n n y " } = {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
root = pkgs . unstable . cinny . override {
conf = {
defaultHomeserver = 0 ;
homeserverList = [
" p v v . n t n u . n o "
" m a t r i x . o r g "
" d o d s o r f . a s "
] ;
} ;
} ;
} ;
# Element-web
# A glossy Matrix collaboration client for the web
services . nginx . virtualHosts . ${ mkDomain " e l e m e n t " } = {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
root = pkgs . element-web . override {
conf = {
# https://github.com/vector-im/element-web/blob/develop/docs/config.md
# https://github.com/vector-im/element-web/blob/develop/config.sample.json
# https://github.com/vector-im/element-web/blob/develop/docs/labs.md
brand = " s p i s m e g " ;
default_country_code = " N O " ;
default_server_config . " m . h o m e s e r v e r " = {
server_name = " p v v . n t n u . n o " ;
base_url = " h t t p s : / / m a t r i x . p v v . n t n u . n o " ;
} ;
roomDirectory . servers = [
" p v v . n t n u . n o "
" m a t r i x . o r g "
" n i x o s . o r g "
" a g d e r s a m . n o "
" t r y g v e . m e "
" u t w e n t e . i o "
] ;
disable_guests = true ;
showLabsSettings = true ;
features . feature_pinning = " l a b s " ;
features . feature_custom_status = " l a b s " ;
features . feature_custom_tags = " l a b s " ;
features . feature_state_counters = " l a b s " ;
features . feature_latex_maths = " l a b s " ;
setting_defaults . breadcrumbs = true ;
UIFeature . urlPreviews = true ;
UIFeature . shareQrCode = true ;
UIFeature . registration = false ;
} ;
} ;
} ;
2023-02-24 21:36:30 +01:00
2022-10-17 22:40:48 +02:00
# vaultwarden
# Unofficial Bitwarden compatible server written in Rust
services . vaultwarden = {
enable = true ;
config = {
# https://github.com/dani-garcia/vaultwarden/blob/1.24.0/.env.template
# camelCase is converted to UPPER_SNAKE_CASE
domain = " h t t p s : / / ${ mkDomain " v a u l t w a r d e n " } " ; # port is supported
signupsAllowed = false ;
# rocket is the http library
rocketAddress = " 1 2 7 . 0 . 0 . 1 " ;
rocketPort = 8222 ;
#rocketWorkers = 10;
rocketLog = " c r i t i c a l " ;
} ;
#dbBackend = "sqlite";
# backupDir = ""; # TODO
} ;
services . nginx . virtualHosts . ${ mkDomain " v a u l t w a r d e n " } = lib . mkIf config . services . vaultwarden . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString config . services . vaultwarden . config . rocketPort } " ;
proxyWebsockets = true ;
} ;
} ;
# matrix-synapse
/* * /
services . matrix-synapse = {
enable = true ;
settings = {
server_name = " p b s d s . n e t "
public_baseurl = mkDomain " m a t r i x " ;
url_preview_enabled = false ;
max_upload_size = " 1 0 0 M " ;
trusted_key_servers = [
{ server_name = " m a t r i x . o r g " ; }
{ server_name = " d o d s o r f . a s " ; }
{ server_name = " p v v . n t n u . n o " ; }
] ;
listeners = [
{
bind_addresses = [
" 1 2 7 . 0 . 0 . 1 "
] ;
port = 8008 ;
resources = [
{
compress = true ;
names = [
" c l i e n t "
] ;
}
{
compress = false ;
names = [
" f e d e r a t i o n "
] ;
}
] ;
tls = false ;
type = " h t t p " ;
x_forwarded = true ;
}
] ;
} ;
} ;
services . nginx . virtualHosts . ${ mkDomain " m a t r i x " } = lib . mkIf config . services . matrix-synapse . enable {
forceSSL = true ; # addSSL = true;
enableACME = true ; #useACMEHost = acmeDomain;
locations . " / _ m a t r i x " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString ( builtins . elemAt 0 config . services . matrix-synaps . listeners ) . port } " ;
#proxyWebsockets = true;
extraConfig = ''
client_max_body_size $ { config . services . matrix-synaps . max_upload_size } ;
'' ;
} ;
locations . " / _ s y n a p s e / c l i e n t " = {
proxyPass = " h t t p : / / 1 2 7 . 0 . 0 . 1 : ${ toString ( builtins . elemAt 0 config . services . matrix-synaps . listeners ) . port } / _ s y n a p s e / c l i e n t " ;
#proxyWebsockets = true;
} ;
} ;
/* */
}