aboutsummaryrefslogtreecommitdiff
path: root/modules/services
diff options
context:
space:
mode:
Diffstat (limited to 'modules/services')
-rw-r--r--modules/services/acme.nix52
-rw-r--r--modules/services/akkoma/blocklist.toml163
-rw-r--r--modules/services/akkoma/default.nix95
-rw-r--r--modules/services/akkoma/favicon-withbg.pngbin0 -> 17246 bytes
-rw-r--r--modules/services/akkoma/favicon.pngbin0 -> 16693 bytes
-rw-r--r--modules/services/akkoma/logo.pngbin0 -> 1304 bytes
-rw-r--r--modules/services/akkoma/logo.svg71
-rw-r--r--modules/services/akkoma/robots.txt2
-rw-r--r--modules/services/akkoma/terms-of-service.html26
-rw-r--r--modules/services/cgit.nix121
-rw-r--r--modules/services/coredns/_corefile.nix3
-rw-r--r--modules/services/coredns/default.nix18
-rw-r--r--modules/services/coturn.nix64
-rw-r--r--modules/services/dendrite.nix230
-rw-r--r--modules/services/dovecot.nix18
-rw-r--r--modules/services/element-web.nix47
-rw-r--r--modules/services/fail2ban.nix17
-rw-r--r--modules/services/git-daemon.nix29
-rw-r--r--modules/services/gitolite/default.nix108
-rw-r--r--modules/services/gitolite/fix-refs9
-rw-r--r--modules/services/gitolite/rename63
-rw-r--r--modules/services/jitsi.nix38
-rw-r--r--modules/services/ldap.nix76
-rw-r--r--modules/services/matrix-bridge.nix200
-rw-r--r--modules/services/matrix-moderation.nix52
-rw-r--r--modules/services/metrics.nix165
-rw-r--r--modules/services/misskey/config/default.yml156
-rw-r--r--modules/services/misskey/default.nix88
-rw-r--r--modules/services/nginx.nix37
-rw-r--r--modules/services/nixos-mailserver.nix106
-rw-r--r--modules/services/postgresql.nix34
-rw-r--r--modules/services/pubnix.nix20
-rw-r--r--modules/services/sefidel-web.nix26
-rw-r--r--modules/services/soju.nix48
-rw-r--r--modules/services/userweb.nix36
-rw-r--r--modules/services/vikunja.nix50
36 files changed, 2268 insertions, 0 deletions
diff --git a/modules/services/acme.nix b/modules/services/acme.nix
new file mode 100644
index 0000000..6f6e33e
--- /dev/null
+++ b/modules/services/acme.nix
@@ -0,0 +1,52 @@
+{ config, lib, ... }:
+
+with lib;
+let
+ cfg = config.modules.services.acme;
+in
+{
+ options.modules.services.acme = {
+ enable = mkEnableOption "ACME certificate manager";
+ email = mkOption {
+ type = types.str;
+ description = mdDoc ''
+ The postmaster email address to use.
+ '';
+ };
+ certs = mkOption {
+ type = types.attrsOf
+ (types.submodule {
+ options = {
+ domain = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ };
+ subDomains = mkOption { type = types.listOf types.str; };
+ };
+ });
+ };
+ secrets.acme-credentials = mkOption { type = types.str; description = "path to the acme environment file"; };
+ };
+
+ config = mkIf cfg.enable {
+ security.acme = {
+ acceptTerms = true;
+ defaults.email = cfg.email;
+ certs = mapAttrs
+ (name: { domain, subDomains }: {
+ extraDomainNames = lists.forEach subDomains (elem: elem + ".${name}");
+ } // {
+ dnsProvider = "hetzner";
+ dnsPropagationCheck = true;
+ credentialsFile = cfg.secrets.acme-credentials;
+ } // optionalAttrs (domain != null) {
+ domain = domain;
+ })
+ cfg.certs;
+ };
+
+ environment.persistence."/persist".directories = [
+ "/var/lib/acme"
+ ];
+ };
+}
diff --git a/modules/services/akkoma/blocklist.toml b/modules/services/akkoma/blocklist.toml
new file mode 100644
index 0000000..e5eac7a
--- /dev/null
+++ b/modules/services/akkoma/blocklist.toml
@@ -0,0 +1,163 @@
+[followers_only]
+
+[media_nsfw]
+
+[reject]
+"*.tk" = "Free TLD"
+"*.ml" = "Free TLD"
+"*.ga" = "Free TLD"
+"*.cf" = "Free TLD"
+"*.gq" = "Free TLD"
+# Reject list from chaos.social at 2023-02-06
+"activitypub-proxy.cf" = "Only exists to evade instance blocks, details"
+"activitypub-troll.cf" = "Spam"
+"aethy.com" = "Lolicon"
+"bae.st" = "Discrimination, racism, “free speech zone”"
+"baraag.net" = "Lolicon"
+"banepo.st" = "Homophobia"
+"beefyboys.club" = "Discrimination, racism, “free speech zone”"
+"beefyboys.win" = "Discrimination, racism, “free speech zone”"
+"beta.birdsite.live" = "Twitter crossposter"
+"birb.elfenban.de" = "Twitter crossposter"
+"bird.evilcyberhacker.net" = "Twitter crossposter"
+"bird.froth.zone" = "Twitter crossposter"
+"bird.geiger.ee" = "Twitter crossposter"
+"bird.im-in.space" = "Twitter crossposter"
+"bird.istheguy.com" = "Twitter crossposter"
+"bird.karatek.net" = "Twitter crossposter"
+"bird.makeup" = "Twitter crossposter"
+"bird.nzbr.de" = "Twitter crossposter"
+"bird.r669.live" = "Twitter crossposter"
+"bird.seafoam.space" = "Twitter crossposter"
+"birdbots.leptonics.com" = "Twitter crossposter"
+"birdsite.b93.dece.space" = "Twitter crossposter"
+"birdsite.blazelights.dev" = "Twitter crossposter"
+"birdsite.frog.fashion" = "Twitter crossposter"
+"birdsite.gabeappleton.me" = "Twitter crossposter"
+"birdsite.james.moody.name" = "Twitter crossposter"
+"birdsite.koyu.space" = "Twitter crossposter"
+"birdsite.lakedrops.com" = "Twitter crossposter"
+"birdsite.link" = "Twitter crossposter"
+"birdsite.monster" = "Twitter crossposter"
+"birdsite.oliviaappleton.com" = "Twitter crossposter"
+"birdsite.platypush.tech" = "Twitter crossposter"
+"birdsite.slashdev.space" = "Twitter crossposter"
+"birdsite.tcjc.uk" = "Twitter crossposter"
+"birdsite.thorlaksson.com" = "Twitter crossposter"
+"birdsite.toot.si" = "Twitter crossposter"
+"birdsite.wilde.cloud" = "Twitter crossposter"
+"birdsitelive.ffvo.dev" = "Twitter crossposter"
+"birdsitelive.kevinyank.com" = "Twitter crossposter"
+"birdsitelive.peanutlasko.com" = "Twitter crossposter"
+"birdsitelive.treffler.cloud" = "Twitter crossposter"
+"bridge.birb.space" = "Twitter crossposter"
+"brighteon.social" = "“free speech zone”"
+"cawfee.club" = "Discrimination, racism, “free speech zone”"
+"childpawn.shop" = "Pedophilia"
+"chudbuds.lol" = "Discrimination, racism, “free speech zone”"
+"club.darknight-coffee.eu" = "“free speech zone”"
+"clubcyberia.co" = "Homophobia"
+"clube.social" = "Harassment"
+"comfyboy.club" = "Discrimination, racism"
+"cum.camp" = "Harassment"
+"cum.salon" = "Misogynic, pedophilia"
+"daishouri.moe" = "Fascism, openly advertises with swastika"
+"detroitriotcity.com" = "Discrimination, racism, “free speech zone”"
+"eientei.org" = "Racism, antisemitism"
+"eveningzoo.club" = "Discrimination, racism, “free speech zone”"
+"f.haeder.net" = "Discrimination"
+"freak.university" = "Pedophilia"
+"freeatlantis.com" = "Conspiracy theory instance"
+"freecumextremist.com" = "Discrimination, racism, “free speech zone”"
+"freefedifollowers.ga" = "Follower spam"
+"freespeechextremist.com" = "Discrimination, racism, “free speech zone”"
+"frennet.link" = "Discrimination, racism, “free speech zone”"
+"froth.zone" = "Calls freespeechextremist their local bubble"
+"gab.com/.ai, develop.gab.com" = "Discrimination, racism, “free speech zone”"
+"gameliberty.club" = "“free speech zone”"
+"gegenstimme.tv" = "“free speech zone”"
+"genderheretics.xyz" = "Tagline “Now With 41% More Misgendering!”"
+"gitmo.life" = "“free speech zone”"
+"gleasonator.com" = "Transphobia, TERFs"
+"glindr.org" = "Discrimination"
+"glowers.club" = "Discrimination, racism, “free speech zone”"
+"honkwerx.tech" = "Racism"
+"iamterminally.online" = "Discrimination, racism, “free speech zone”"
+"iddqd.social" = "Discrimination, racism, “free speech zone”"
+"itmslaves.com" = "“free speech zone”, noagenda affiliated"
+"jaeger.website" = "Discrimination, racism, “free speech zone”"
+"kenfm.quadplay.tv" = "Conspiracy videos"
+"kiwifarms.cc" = "Discrimination"
+"lgbtfree.zone" = "Racism, transphobia, all that"
+"liberdon.com" = "Conspiracy theories, transphobia, racism"
+"libre.tube" = "Promotion of violence and murder, multiple other violations of our rules"
+"lolicon.rocks" = "Lolicon"
+"lolison.top" = "Lolicon, paedophilia"
+"mastinator.com" = "Block evasion, unwanted profile mirroring, and more"
+"mastodon.network" = "Instance went down, now porn spam"
+"mastodon.popps.org" = "Homophobia"
+"mastodong.lol" = "Admin maintains and runs activitypub-proxy.cf"
+"meta-tube.de" = "Conspiracy, CoVid19 denier videos https://fediblock.org/blocklist/#meta-tube.de"
+"midnightride.rs" = "Discrimination"
+"misskey-forkbomb.cf" = "Spam"
+"morale.ch" = "Antisemitism and more"
+"mstdn.foxfam.club" = "Right wing twitter mirror"
+"natehiggers.online" = "Racism"
+"newjack.city" = "Exclusive to unwanted follow bots"
+"nicecrew.digital" = "Discrimination, racism, “free speech zone”"
+"noagendasocial.com" = "“free speech zone”, harassment"
+"noagendasocial.nl" = "“free speech zone”, harassment"
+"noagendatube.com" = "“free speech zone”, harassment"
+"ns.auction" = "Racism etc"
+"ohai.su" = "Offline"
+"pawoo.net" = "Untagged nfsw content, unwanted follow bots, lolicon"
+"paypig.org" = "Racism"
+"pieville.net" = "Racism, antisemitism"
+"pl.serialmay.link" = "Racism, transphobia"
+"pl.tkammer.de" = "Transphobia"
+"play.xmr.101010.pl" = "Cryptomining"
+"pleroma.kitsunemimi.club" = "Discrimination"
+"pleroma.narrativerry.xyz" = "Discrimination, racism, “free speech zone”"
+"pleroma.nobodyhasthe.biz" = "Doxxing and discrimination"
+"pleroma.rareome.ga" = "Doesn’t respect blocks or status privacy, lolicons"
+"poa.st" = "Discrimination"
+"podcastindex.social" = "noagenda affiliated"
+"poster.place" = "Discrimination, racism, “free speech zone”, harassment in response to blocks"
+"qoto.org" = "“free speech zone”, harassment"
+"rapemeat.solutions" = "Lolicon and also, like, the domain name"
+"rdrama.cc" = "Discrimination, “free speech zone”, racism"
+"repl.co" = "Spam"
+"rojogato.com" = "Harassment, “free speech zone”"
+"ryona.agency" = "Alt-right trolls, harassment"
+"seal.cafe" = "Discrimination, racism, “free speech zone”"
+"shitpost.cloud" = "“Free speech zone”, antisemitism"
+"shitposter.club" = "“Free speech zone”"
+"shortstackran.ch" = "Racism, homophobia, “free speech zone”"
+"shota.house" = "Lolicon"
+"skippers-bin.com" = "Same admin as neckbeard.xyz, same behaviour"
+"sleepy.cafe" = "Racism, harassment"
+"sneak.berlin" = "privacy violation"
+"sneed.social" = "Discrimination, racism, “free speech zone”, nationalism, hate speech, completely unmoderated"
+"soc.ua-fediland.de" = "Spam"
+"social.ancreport.com" = "Discrimination, racism, “free speech zone”"
+"social.lovingexpressions.net" = "Transphobia"
+"social.teci.world" = "Discrimination, racism, “free speech zone”"
+"social.urspringer.de" = "Conspiracy, CoVid19 denier"
+"socnet.supes.com" = "Right wing “free speech zone”"
+"solagg.com" = "Scammers"
+"spinster.xyz" = "Discrimination, TERFs"
+"tastingtraffic.net" = "Homophobia"
+"truthsocial.co.in" = "Alt-right trolls"
+"tube.kenfm.de" = "Right-wing conspiracy videos"
+"tube.querdenken-711.de" = "Right-wing onspiracy videos"
+"tweet.pasture.moe" = "Twitter crossposter"
+"tweetbridge.kogasa.de" = "Twitter crossposter"
+"tweets.icu" = "Twitter crossposter"
+"twitter.activitypub.actor" = "Twitter crossposter"
+"twitter.doesnotexist.club" = "Twitter crossposter"
+"twitterbridge.jannis.rocks" = "Twitter crossposter"
+"twtr.plus" = "Twitter crossposter"
+"varishangout.net" = "Transphobia and racism go unmoderated, aggressive trolling, lolicon permitted in rules"
+"wiki-tube.de" = "Right-wing conspiracy videos (initial video welcomes Querdenken and KenFM)"
+"wolfgirl.bar" = "Discrimination, homophobia, unmoderated trolling"
+"yggdrasil.social" = "Instance rules: “No LGBTQ. Period. No homosexuality. No men who think they’re women or women who think they’re men. No made up genders.”"
diff --git a/modules/services/akkoma/default.nix b/modules/services/akkoma/default.nix
new file mode 100644
index 0000000..a0cd42c
--- /dev/null
+++ b/modules/services/akkoma/default.nix
@@ -0,0 +1,95 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+ cfg = config.modules.services.akkoma;
+
+ poorObfuscation = y: x: "${x}@${y}";
+ federation-blocklist = lib.importTOML ./blocklist.toml;
+
+ inherit (lib.my) wrapFile;
+in
+{
+ options.modules.services.akkoma = {
+ enable = mkEnableOption "Akkoma instance";
+ domain = mkOption { type = types.str; };
+ realHost = mkOption { type = types.str; };
+ instanceName = mkOption { type = types.str; default = "Akkoma on ${cfg.domain}"; };
+ };
+
+ config = mkIf cfg.enable {
+ modules.services.postgresql.enable = true;
+
+ services.akkoma = {
+ enable = true;
+ initDb.enable = true;
+
+ extraStatic = {
+ "static/terms-of-service.html" = wrapFile "terms-of-service.html" ./terms-of-service.html;
+ "static/logo.svg" = wrapFile "logo.svg" ./logo.svg;
+ "static/logo.png" = wrapFile "logo.png" ./logo.png;
+ "static/logo-512.png" = wrapFile "logo-512.png" ./favicon-withbg.png; # Intentional, for PWA favicon.
+ "static/icon.png" = wrapFile "icon.png" ./favicon.png;
+ "favicon.png" = wrapFile "favicon.png" ./favicon.png;
+ };
+ config =
+ let inherit ((pkgs.formats.elixirConf { }).lib) mkRaw mkMap;
+ in {
+ ":pleroma"."Pleroma.Web.Endpoint".url.host = cfg.realHost;
+ ":pleroma"."Pleroma.Web.WebFinger".domain = cfg.domain;
+ ":pleroma".":media_proxy".enabled = false;
+ ":pleroma".":instance" = {
+ name = cfg.instanceName;
+
+ description = "Private akkoma instance";
+ email = poorObfuscation cfg.domain "postmaster";
+ notify_email = poorObfuscation cfg.domain "postmaster";
+
+ registrations_open = false;
+ invites_enabled = true;
+
+ limit = 5000;
+ };
+ ":pleroma".":frontend_configurations" = {
+ pleroma_fe = mkMap {
+ logo = "/static/logo.png";
+ };
+ };
+ ":pleroma".":mrf" = {
+ policies = map mkRaw [ "Pleroma.Web.ActivityPub.MRF.SimplePolicy" ];
+ };
+ ":pleroma".":mrf_simple" = {
+ followers_only = mkMap federation-blocklist.followers_only;
+ media_nsfw = mkMap federation-blocklist.media_nsfw;
+ reject = mkMap federation-blocklist.reject;
+ };
+ };
+
+ nginx = {
+ forceSSL = true;
+ useACMEHost = cfg.domain;
+
+ locations."~ \\.(js|css|woff|woff2?|png|jpe?g|svg)$" = {
+ extraConfig = ''
+ add_header Cache-Control "public, max-age=14400, must-revalidate";
+ '';
+
+ proxyPass = "http://unix:${config.services.akkoma.config.":pleroma"."Pleroma.Web.Endpoint".http.ip}";
+ proxyWebsockets = true;
+ recommendedProxySettings = true;
+ };
+ };
+ };
+
+ services.nginx.virtualHosts.${cfg.domain} = {
+ forceSSL = true;
+ useACMEHost = cfg.domain;
+
+ locations."/.well-known/host-meta" = {
+ extraConfig = ''
+ return 301 https://${cfg.realHost}$request_uri;
+ '';
+ };
+ };
+ };
+ }
diff --git a/modules/services/akkoma/favicon-withbg.png b/modules/services/akkoma/favicon-withbg.png
new file mode 100644
index 0000000..7d15954
--- /dev/null
+++ b/modules/services/akkoma/favicon-withbg.png
Binary files differ
diff --git a/modules/services/akkoma/favicon.png b/modules/services/akkoma/favicon.png
new file mode 100644
index 0000000..d8cbce3
--- /dev/null
+++ b/modules/services/akkoma/favicon.png
Binary files differ
diff --git a/modules/services/akkoma/logo.png b/modules/services/akkoma/logo.png
new file mode 100644
index 0000000..7744b1a
--- /dev/null
+++ b/modules/services/akkoma/logo.png
Binary files differ
diff --git a/modules/services/akkoma/logo.svg b/modules/services/akkoma/logo.svg
new file mode 100644
index 0000000..68e647e
--- /dev/null
+++ b/modules/services/akkoma/logo.svg
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="svg4485"
+ width="512"
+ height="512"
+ viewBox="0 0 512 512"
+ sodipodi:docname="logo.svg"
+ inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
+ <metadata
+ id="metadata4491">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs4489" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1274"
+ inkscape:window-height="1410"
+ id="namedview4487"
+ showgrid="false"
+ inkscape:zoom="1.2636719"
+ inkscape:cx="305.99333"
+ inkscape:cy="304.30809"
+ inkscape:window-x="1280"
+ inkscape:window-y="22"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="g4612"
+ inkscape:document-rotation="0" />
+ <g
+ id="g4612">
+ <g
+ id="g850"
+ transform="matrix(0.99659595,0,0,0.99659595,0.37313949,0.87143746)">
+ <path
+ style="opacity:1;fill:#fba457;fill-opacity:1;stroke:#009bff;stroke-width:0;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.175879"
+ d="m 194.75841,124.65165 a 20.449443,20.449443 0 0 0 -20.44944,20.44945 v 242.24725 h 65.28091 v -262.6967 z"
+ id="path4497" />
+ <path
+ style="fill:#fba457;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="M 272.6236,124.65165 V 256 h 45.61799 a 20.449443,20.449443 0 0 0 20.44944,-20.44945 v -110.8989 z"
+ id="path4516" />
+ <path
+ style="opacity:1;fill:#fba457;fill-opacity:1;stroke:#000000;stroke-width:0;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 272.6236,322.06744 v 65.28091 h 45.61799 a 20.449443,20.449443 0 0 0 20.44944,-20.44945 v -44.83146 z"
+ id="path4516-5" />
+ </g>
+ </g>
+</svg>
diff --git a/modules/services/akkoma/robots.txt b/modules/services/akkoma/robots.txt
new file mode 100644
index 0000000..1f53798
--- /dev/null
+++ b/modules/services/akkoma/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow: /
diff --git a/modules/services/akkoma/terms-of-service.html b/modules/services/akkoma/terms-of-service.html
new file mode 100644
index 0000000..b954760
--- /dev/null
+++ b/modules/services/akkoma/terms-of-service.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head></head>
+ <body>
+ <h2>Terms of Service</h2>
+ <p>This is a personal instance with only one user. Therefore, I'll write rules that I'll abide:</p>
+ <ol>
+ <li>
+ <p>No discrimination based on race, gender, sexual orientation, disabilities, or any other characteristic.</p>
+ </li>
+ <li>
+ <p>No harassment or doxxing towards others.</p>
+ </li>
+ <li>
+ <p>No promotion of violence.</p>
+ </li>
+ <li>
+ <p>No content that is illegal in United Kingdom, Japan, Finland, Germany, and South Korea.</p>
+ </li>
+ <li>
+ <p>Use content warnings for explicit or controversial content.</p>
+ </li>
+ </ol>
+ <p>Since I'm the only user here, I try to moderate myself best as I can. But I might sometimes fail to do so. If that ever happens, please do let me know. I'll make sure it never happens again!</p>
+ </body>
+</html>
diff --git a/modules/services/cgit.nix b/modules/services/cgit.nix
new file mode 100644
index 0000000..418312b
--- /dev/null
+++ b/modules/services/cgit.nix
@@ -0,0 +1,121 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+ cfg = config.modules.services.cgit;
+in
+{
+ options.modules.services.cgit = {
+ enable = mkEnableOption "cgit with uwsgi";
+
+ domain = mkOption { type = types.str; };
+ realHost = mkOption { type = types.str; };
+ # TODO: use generators & submodules
+ settings = {
+ title = mkOption { type = types.str; default = "${cfg.domain} git"; };
+ description = mkOption { type = types.str; default = "cgit, hyperfast web frontend for Git"; };
+ };
+ };
+ config = mkIf cfg.enable {
+
+ modules.services.nginx.enable = true;
+
+ services.uwsgi = {
+ enable = true;
+ user = "nginx";
+ group = "nginx";
+ plugins = [ "cgi" ];
+
+ instance = {
+ type = "emperor";
+ vassals = {
+ cgit = {
+ type = "normal";
+ master = true;
+ socket = "/run/uwsgi/cgit.sock";
+ procname-master = "uwsgi cgit";
+ plugins = [ "cgi" ];
+ cgi = "${pkgs.cgit-pink}/cgit/cgit.cgi";
+ };
+ };
+ };
+ };
+
+ users.extraUsers.nginx.extraGroups = [ "git" ];
+
+ services.nginx.virtualHosts.${cfg.realHost} = {
+ forceSSL = true;
+ useACMEHost = cfg.domain;
+ root = "${pkgs.cgit-pink}/cgit";
+ locations = {
+ "/" = {
+ extraConfig = ''
+ try_files $uri @cgit;
+ '';
+ };
+ "@cgit" = {
+ extraConfig = ''
+ uwsgi_pass unix:/run/uwsgi/cgit.sock;
+ include ${pkgs.nginx}/conf/uwsgi_params;
+ uwsgi_modifier1 9;
+ '';
+ };
+ };
+ };
+
+ networking.firewall.allowedTCPPorts = [ 80 443 ];
+
+ systemd.services.create-cgit-cache = {
+ description = "Create cache directory for cgit";
+ enable = true;
+
+ script = ''
+ mkdir -p /run/cgit
+ chown -R nginx:nginx /run/cgit
+ '';
+
+ wantedBy = [ "uwsgi.service" ];
+ serviceConfig = {
+ Type = "oneshot";
+ };
+ };
+
+ environment.etc."cgitrc".text = ''
+ virtual-root=/
+
+ cache-size=1000
+ cache-root=/run/cgit
+
+ root-title=${cfg.domain} git
+ root-desc=Exotic place.
+
+ snapshots=tar.gz zip
+
+ enable-git-config=1
+ remove-suffix=1
+
+ enable-git-clone=1
+ enable-index-links=1
+ enable-commit-graph=1
+ enable-log-filecount=1
+ enable-log-linecount=1
+
+ branch-sort=age
+
+ readme=:README
+ readme=:readme
+ readme=:README.md
+ readme=:readme.md
+ readme=:README.org
+ readme=:readme.org
+
+ source-filter=${pkgs.cgit-pink}/lib/cgit/filters/syntax-highlighting.py
+ about-filter=${pkgs.cgit-pink}/lib/cgit/filters/about-formatting.sh
+
+ section-from-path=2
+
+ project-list=${config.services.gitolite.dataDir}/projects.list
+ scan-path=${config.services.gitolite.dataDir}/repositories
+ '';
+ };
+}
diff --git a/modules/services/coredns/_corefile.nix b/modules/services/coredns/_corefile.nix
new file mode 100644
index 0000000..8d0ec66
--- /dev/null
+++ b/modules/services/coredns/_corefile.nix
@@ -0,0 +1,3 @@
+''
+Add content here
+''
diff --git a/modules/services/coredns/default.nix b/modules/services/coredns/default.nix
new file mode 100644
index 0000000..52d8570
--- /dev/null
+++ b/modules/services/coredns/default.nix
@@ -0,0 +1,18 @@
+{ config, lib, ... }:
+
+with lib;
+let
+ cfg = config.modules.services.coredns;
+in
+{
+ options.modules.services.coredns = {
+ enable = mkEnableOption "coredns";
+ };
+
+ config = mkIf cfg.enable {
+ services.coredns = {
+ enable = true;
+ config = import ./_corefile.nix;
+ };
+ };
+}
diff --git a/modules/services/coturn.nix b/modules/services/coturn.nix
new file mode 100644
index 0000000..967ba60
--- /dev/null
+++ b/modules/services/coturn.nix
@@ -0,0 +1,64 @@
+{ config, lib, ... }:
+
+with lib;
+let
+ turnRange = with config.services.coturn; [{
+ from = min-port;
+ to = max-port;
+ }];
+
+ cfg = config.modules.services.coturn;
+in
+{
+ options.modules.services.coturn = {
+ enable = mkEnableOption "coturn";
+ domain = mkOption { type = types.str; default = config.networking.hostName; };
+ shared_secret = mkOption { type = types.str; };
+ tls.acmeHost = mkOption { type = types.str; default = cfg.domain; };
+ };
+
+ config = mkIf cfg.enable {
+ services.coturn = {
+ enable = true;
+ use-auth-secret = true;
+ static-auth-secret = cfg.shared_secret;
+ realm = cfg.domain;
+ cert = "${config.security.acme.certs.${cfg.tls.acmeHost}.directory}/fullchain.pem";
+ pkey = "${config.security.acme.certs.${cfg.tls.acmeHost}.directory}/key.pem";
+
+ no-tcp-relay = true;
+ no-cli = true;
+
+ extraConfig = ''
+ user-quota=12
+ total-quota=1200
+
+ no-loopback-peers
+ no-multicast-peers
+ denied-peer-ip=0.0.0.0-0.255.255.255
+ denied-peer-ip=10.0.0.0-10.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=172.16.0.0-172.31.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=192.168.0.0-192.168.255.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
+ '';
+ };
+
+ systemd.services.coturn = {
+ serviceConfig.SupplementaryGroups = [ "acme" ];
+ };
+
+ networking.firewall.allowedUDPPortRanges = turnRange;
+ networking.firewall.allowedTCPPortRanges = turnRange;
+ networking.firewall.allowedTCPPorts = [ 3478 3479 5349 5350 ];
+ networking.firewall.allowedUDPPorts = [ 3478 3479 5349 5350 ];
+ };
+}
diff --git a/modules/services/dendrite.nix b/modules/services/dendrite.nix
new file mode 100644
index 0000000..70f9db8
--- /dev/null
+++ b/modules/services/dendrite.nix
@@ -0,0 +1,230 @@
+{ config, lib, ... }:
+
+with lib;
+let
+ cfg = config.modules.services.dendrite;
+
+ database = {
+ connection_string = "postgres:///dendrite?host=/run/postgresql";
+ max_open_conns = 100;
+ max_idle_conns = 5;
+ conn_max_lifetime = -1;
+ };
+in
+{
+ imports = [
+ ../../overlays/sliding-sync-module.nix
+ ];
+
+ options.modules.services.dendrite = {
+ enable = mkEnableOption "dendrite instance";
+ domain = mkOption { type = types.str; };
+ realHost = mkOption { type = types.str; default = "matrix.${cfg.domain}"; };
+ slidingSyncHost = mkOption { type = types.str; default = "slidingsync.${cfg.domain}"; };
+ turn = {
+ enable = mkEnableOption "VOIP suing TURN";
+ domain = mkOption { type = types.str; default = "turn.${cfg.domain}"; };
+ shared_secret = mkOption { type = types.str; };
+ };
+ secrets = {
+ matrix-server-key = mkOption { type = types.str; description = "path to the server key"; };
+ dendrite-envs = mkOption { type = types.nullOr types.str; description = "path for the environment file to source"; };
+ sliding-sync-secret = mkOption { type = types.nullOr types.str; description = "path to the sliding sync secret"; };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ # Adapted from Mic92/dotfiles, (C) 2021 Jörg Thalheim (MIT)
+ services.dendrite = {
+ enable = true;
+ settings = {
+ global = {
+ server_name = cfg.domain;
+ # `private_key` has the type `path`
+ # prefix a `/` to make `path` happy
+ private_key = "/$CREDENTIALS_DIRECTORY/matrix-server-key";
+ jetstream.storage_path = "/var/lib/dendrite/jetstream";
+ trusted_third_party_id_servers = [
+ "matrix.org"
+ "vector.im"
+ ];
+ metrics.enabled = true;
+ };
+ logging = [
+ {
+ type = "std";
+ level = "info"; # "warn" on public release
+ }
+ ];
+ app_service_api = {
+ inherit database;
+ config_files = [ ];
+ };
+ client_api = {
+ registration_disabled = true;
+ rate_limiting.enabled = false;
+ rate_limiting.exempt_user_ids = [
+ "@abuse:${cfg.domain}"
+ ];
+ # registration_shared_secret = ""; # Initially set this option to configure the admin user.
+ } // optionalAttrs cfg.turn.enable {
+ turn = {
+ turn_user_lifetime = "24h";
+ turn_uris = [
+ "turns:${cfg.turn.domain}?transport=udp"
+ "turns:${cfg.turn.domain}?transport=tcp"
+ "turn:${cfg.turn.domain}?transport=udp"
+ "turn:${cfg.turn.domain}?transport=tcp"
+ ];
+ turn_shared_secret = cfg.turn.shared_secret;
+ };
+ };
+ media_api = {
+ inherit database;
+ dynamic_thumbnails = true;
+ };
+ room_server = {
+ inherit database;
+ };
+ push_server = {
+ inherit database;
+ };
+ mscs = {
+ inherit database;
+ mscs = [ "msc2836" "msc2946" ];
+ };
+ sync_api = {
+ inherit database;
+ real_ip_header = "X-Real-IP";
+ # The NixOS option is 'enable', which doesn't exist in Dendrite.
+ search.enabled = true;
+ };