aboutsummaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorsefidel <contact@sefidel.net>2023-03-29 20:54:19 +0900
committersefidel <contact@sefidel.net>2023-04-03 18:32:29 +0900
commitce06f43476863da90dc60dcee606d2b6c5a89a8e (patch)
tree5d14946330cb09ff0ebd97bee59407fccee4d860 /modules
downloadinfra-ce06f43476863da90dc60dcee606d2b6c5a89a8e.zip
project: initial commit
Diffstat (limited to 'modules')
-rw-r--r--modules/README.md9
-rw-r--r--modules/cachix/caches/nix-community.nix12
-rw-r--r--modules/cachix/default.nix13
-rw-r--r--modules/flakes.nix36
-rw-r--r--modules/nix.nix34
-rw-r--r--modules/security.nix59
-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
-rw-r--r--modules/sops.nix21
43 files changed, 2452 insertions, 0 deletions
diff --git a/modules/README.md b/modules/README.md
new file mode 100644
index 0000000..25031dc
--- /dev/null
+++ b/modules/README.md
@@ -0,0 +1,9 @@
+infra->modules
+==============
+
+This is all the modules used to configure our systems based on its purposes.
+
+As of now, it doesn't have any clear "naming convention", but generally it's
+`<servicename>` for a module configuring one thing, `<capability>` otherwise.
+
+e.g) `dendrite` -> `dendrite`, `prometheus`, `grafana` -> `metrics`
diff --git a/modules/cachix/caches/nix-community.nix b/modules/cachix/caches/nix-community.nix
new file mode 100644
index 0000000..d323939
--- /dev/null
+++ b/modules/cachix/caches/nix-community.nix
@@ -0,0 +1,12 @@
+{ config, lib, ... }:
+
+{
+ nix.settings = {
+ substituters = [
+ "https://nix-community.cachix.org"
+ ];
+ trusted-public-keys = [
+ "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
+ ];
+ };
+}
diff --git a/modules/cachix/default.nix b/modules/cachix/default.nix
new file mode 100644
index 0000000..9dd55b5
--- /dev/null
+++ b/modules/cachix/default.nix
@@ -0,0 +1,13 @@
+{ config, pkgs, lib, ... }:
+let
+ folder = ./caches;
+ toImport = name: value: folder + ("/" + name);
+ filterCaches = key: value: value == "regular" && lib.hasSuffix ".nix" key;
+ imports = lib.mapAttrsToList toImport (lib.filterAttrs filterCaches (builtins.readDir folder));
+in
+{
+ inherit imports;
+ nix.settings.substituters = [ "https://cache.nixos.org/" ];
+
+ environment.systemPackages = [ pkgs.cachix ];
+}
diff --git a/modules/flakes.nix b/modules/flakes.nix
new file mode 100644
index 0000000..df86369
--- /dev/null
+++ b/modules/flakes.nix
@@ -0,0 +1,36 @@
+{ config, pkgs, unstable, unstable-small, nixpkgs-2111, lib, ... }:
+
+with lib;
+let
+ base = "/etc/nixpkgs/channels";
+ nixpkgsPath = "${base}/nixpkgs";
+ nixpkgsSmallPath = "${base}/nixpkgsSmall";
+ nixpkgs2111Path = "${base}/nixpkgs2111";
+in
+{
+ options.nix.flakes.enable = mkEnableOption "nix flakes";
+
+ config = lib.mkIf config.nix.flakes.enable {
+ nix = {
+ package = pkgs.nixUnstable;
+ experimentalFeatures = "nix-command flakes";
+
+ registry.nixpkgs.flake = unstable;
+ registry.nixpkgsSmall.flake = unstable-small;
+ registry.nixpkgs2111.flake = nixpkgs-2111;
+
+ nixPath = [
+ "nixpkgs=${nixpkgsPath}"
+ "nixpkgsSmall=${nixpkgsSmallPath}"
+ "nixpkgs2111=${nixpkgs2111Path}"
+ "/nix/var/nix/profiles/per-user/root/channels"
+ ];
+ };
+
+ systemd.tmpfiles.rules = [
+ "L+ ${nixpkgsPath} - - - - ${unstable}"
+ "L+ ${nixpkgsSmallPath} - - - - ${unstable-small}"
+ "L+ ${nixpkgs2111Path} - - - - ${nixpkgs-2111}"
+ ];
+ };
+}
diff --git a/modules/nix.nix b/modules/nix.nix
new file mode 100644
index 0000000..1f61d45
--- /dev/null
+++ b/modules/nix.nix
@@ -0,0 +1,34 @@
+{ config, lib, ... }:
+
+let
+ allowed = config.nix.allowedUnfree;
+in
+{
+ options.nix = {
+ experimentalFeatures = lib.mkOption {
+ type = lib.types.separatedString " ";
+ default = "";
+ description = ''
+ Enables experimental features
+ '';
+ };
+
+ allowedUnfree = lib.mkOption {
+ type = lib.types.listOf lib.types.string;
+ default = [ ];
+ description = ''
+ Allows for unfree packages by their name.
+ '';
+ };
+ };
+
+ config = lib.mkMerge [
+ (lib.mkIf (config.nix.experimentalFeatures != "") { nix.extraOptions = "experimental-features = ${config.nix.experimentalFeatures}"; })
+ (lib.mkIf (allowed != [ ]) { nixpkgs.config.allowUnfreePredicate = (pkg: __elem (lib.getName pkg) allowed); })
+ { nix.settings.auto-optimise-store = lib.mkDefault true; }
+ {
+ nix.gc.automatic = lib.mkDefault true;
+ nix.gc.options = lib.mkDefault "--delete-older-than 10d";
+ }
+ ];
+}
diff --git a/modules/security.nix b/modules/security.nix
new file mode 100644
index 0000000..d845393
--- /dev/null
+++ b/modules/security.nix
@@ -0,0 +1,59 @@
+{ config, lib, ... }:
+
+{
+ # Security-related system tweaks
+
+ # Prevent replacing the running kernel without reboot.
+ security.protectKernelImage = true;
+
+ # mount /tmp in ram. This makes temp file management faster
+ # on ssd systems, and volatile! Because it's wiped on reboot.
+ boot.tmpOnTmpfs = false;
+ boot.tmpOnTmpfsSize = "80%";
+
+ # Purge /tmp on boot. (fallback option)
+ boot.cleanTmpDir = lib.mkDefault (!config.boot.tmpOnTmpfs);
+
+ boot.kernel.sysctl = {
+ # The Magic SysRq key is a key combo that allows users connected to the
+ # system console of a Linux kernel to perform some low-level commands.
+ # Disable it, since we don't need it, and is a potential security concern.
+ "kernel.sysrq" = 0;
+
+ ## TCP hardening
+ # Prevent bogus ICMP errors from filling up logs.
+ "net.ipv4.icmp_ignore_bogus_error_responses" = 1;
+ # Reverse path filtering causes the kernel to do source validation of
+ # packets received from all interfaces. This can mitigate IP spoofing.
+ "net.ipv4.conf.default.rp_filter" = 1;
+ "net.ipv4.conf.all.rp_filter" = 1;
+ # Do not accept IP source route packets (we're not a router)
+ "net.ipv4.conf.all.accept_source_route" = 0;
+ "net.ipv6.conf.all.accept_source_route" = 0;
+ # Don't send ICMP redirects (again, we're on a router)
+ "net.ipv4.conf.all.send_redirects" = 0;
+ "net.ipv4.conf.default.send_redirects" = 0;
+ # Refuse ICMP redirects (MITM mitigations)
+ "net.ipv4.conf.all.accept_redirects" = 0;
+ "net.ipv4.conf.default.accept_redirects" = 0;
+ "net.ipv4.conf.all.secure_redirects" = 0;
+ "net.ipv4.conf.default.secure_redirects" = 0;
+ "net.ipv6.conf.all.accept_redirects" = 0;
+ "net.ipv6.conf.default.accept_redirects" = 0;
+ # Protects against SYN flood attacks
+ "net.ipv4.tcp_syncookies" = 1;
+ # Incomplete protection again TIME-WAIT assassination
+ "net.ipv4.tcp_rfc1337" = 1;
+
+ ## TCP optimization
+ # TCP Fast Open is a TCP extension that reduces network latency by packing
+ # data in the sender’s initial TCP SYN. Setting 3 = enable TCP Fast Open for
+ # both incoming and outgoing connections:
+ "net.ipv4.tcp_fastopen" = 3;
+ # Bufferbloat mitigations + slight improvement in throughput & latency
+ "net.ipv4.tcp_congestion_control" = "bbr";
+ "net.core.default_qdisc" = "cake";
+ };
+
+ boot.kernelModules = [ "tcp_bbr" ];
+}
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