nixfiles/config/services/akkoma/default.nix
2024-11-02 17:16:48 +01:00

291 lines
9.5 KiB
Nix

{ config, inputs, pkgs, ... }: {
sops.secrets."services/akkoma/mailerPassword" = {
sopsFile = ../../../secrets/services/akkoma.yaml;
};
sops.secrets."services/akkoma/deepl" = {
sopsFile = ../../../secrets/services/akkoma.yaml;
};
services.akkoma = {
enable = true;
extraPackages = with pkgs; [ exiftool ffmpeg-headless imagemagick ];
extraStatic."emoji/blobs.gg" = pkgs.akkoma-emoji.blobs_gg;
extraStatic."static/styles.json" = pkgs.writeText "styles.json" (builtins.toJSON {
pleroma-dark = "/static/themes/pleroma-dark.json";
pleroma-light = "/static/themes/pleroma-light.json";
pleroma-amoled = [ "Pleroma Dark AMOLED" "#000000" "#111111" "#b0b0b1" "#d8a070" "#aa0000" "#0fa00f" "#0095ff" "#d59500"];
classic-dark = [ "Classic Dark" "#161c20" "#282e32" "#b9b9b9" "#baaa9c" "#d31014" "#0fa00f" "#0095ff" "#ffa500" ];
bird = [ "Bird" "#f8fafd" "#e6ecf0" "#14171a" "#0084b8" "#e0245e" "#17bf63" "#1b95e0" "#fab81e"];
ir-black = [ "Ir Black" "#000000" "#242422" "#b5b3aa" "#ff6c60" "#FF6C60" "#A8FF60" "#96CBFE" "#FFFFB6" ];
monokai = [ "Monokai" "#272822" "#383830" "#f8f8f2" "#f92672" "#F92672" "#a6e22e" "#66d9ef" "#f4bf75" ];
redmond-xx = "/static/themes/redmond-xx.json";
redmond-xx-se = "/static/themes/redmond-xx-se.json";
redmond-xxi = "/static/themes/redmond-xxi.json";
breezy-dark = "/static/themes/breezy-dark.json";
breezy-light = "/static/themes/breezy-light.json";
paper = "/static/themes/paper.json";
thekanata = "/static/themes/thekanata.json";
ihatebeingalive = "/static/themes/ihatebeingalive.json";
elly-mod = "/static/themes/elly-mod.json";
});
extraStatic."static/themes/elly-mod.json" = pkgs.writeText "elly-mod.json" (builtins.readFile ./elly-mod.json);
extraStatic."static/terms-of-service.html" = pkgs.writeText "terms-of-service.html" ''
<h3>Likes are now florps. The timeline goes sideways.</h3>
'';
extraStatic."images/sylvia-ritter-15012323.avif" = inputs.florp-branding.packages.${config.nixpkgs.hostPlatform.system}.wallpaper;
extraStatic."favicon.png" = let
rev = "697a8211b0f427a921e7935a35d14bb3e32d0a2c";
in pkgs.stdenvNoCC.mkDerivation {
name = "favicon.png";
src = pkgs.fetchurl {
url = "https://raw.githubusercontent.com/TilCreator/NixOwO/${rev}/NixOwO_plain.svg";
hash = "sha256-tWhHMfJ3Od58N9H5yOKPMfM56hYWSOnr/TGCBi8bo9E=";
};
nativeBuildInputs = with pkgs; [ librsvg ];
dontUnpack = true;
installPhase = ''
rsvg-convert -o $out -w 96 -h 96 $src
'';
};
frontends = {
primary = {
package = pkgs.akkoma-fe-domi;
name = "akkoma-fe";
ref = "5f0339ce00";
};
admin = {
package = pkgs.akkoma-frontends.admin-fe;
name = "admin-fe";
ref = "stable";
};
};
};
services.akkoma.config = let
inherit ((pkgs.formats.elixirConf { }).lib) mkRaw mkAtom mkMap;
in {
":pleroma" = {
":instance" = {
name = "florp.social";
email = "contact@florp.social";
notify_email = "akkoma@florp.social";
description = "Likes are now florps. The timeline goes sideways.";
instance_thumbnail = "/instance/thumbnail.avif";
limit = 69420;
description_limit = 69420;
remote_limit = 131072;
upload_limit = 160 * 1024 * 1024;
avatar_upload_limit = 16 * 1024 * 1024;
background_upload_limit = 32 * 1024 * 1024;
banner_upload_limit = 32 * 1024 * 1024;
registrations_open = true;
registration_reason_length = 2048;
account_approval_required = true;
account_activation_required = true;
federation = false;
federation_incoming_replies_max_depth = 1024;
max_pinned_statuses = 10;
safe_dm_mentions = true;
remote_post_retention_days = 365;
user_bio_length = 8192;
user_name_length = 64;
max_account_fields = 8;
cleanup_attachments = true;
local_bubble = [
"solitary.social"
"donotsta.re"
"chaos.social"
];
};
"Pleroma.Captcha".method = mkRaw "Pleroma.Captcha.Kocaptcha";
"Pleroma.Web.Endpoint".url.host = "florp.social";
"Pleroma.Emails.Mailer" = {
enabled = true;
adapter = mkRaw "Swoosh.Adapters.SMTP";
relay = "mail.kyouma.net";
username = "akkoma@florp.social";
password._secret = config.sops.secrets."services/akkoma/mailerPassword".path;
port = 465;
ssl = true;
auth = mkRaw ":always";
};
":database".rum_enabled = true;
":media_proxy" = {
enabled = true;
base_url = "https://cache.florp.social";
proxy_opts.redirect_on_failure = true;
proxy_opts.max_body_length = 64 * 1024 * 1024;
};
":media_preview_proxy" = {
enabled = true;
thumbnail_max_width = 1920;
thumbnail_max_height = 1080;
min_content_length = 128 * 1024;
};
"Pleroma.Upload".base_url = "https://media.florp.social";
"Pleroma.Upload".filters = map mkRaw [
"Pleroma.Upload.Filter.Exiftool.ReadDescription"
"Pleroma.Upload.Filter.Exiftool.StripMetadata"
"Pleroma.Upload.Filter.Dedupe"
"Pleroma.Upload.Filter.AnonymizeFilename"
];
":mrf" = {
transparency = true;
policies = map mkRaw [
"Pleroma.Web.ActivityPub.MRF.SimplePolicy"
"Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy"
];
};
":mrf_simple" = {
reject = mkMap {
"bae.st" = "harassment";
"brighteon.social" = "incompatible";
"detroitriotcity.com" = "incompatible";
"freeatlantis.com" = "incompatible";
"freespeechextremist.com" = "incompatible";
"gab.com" = "incompatible";
"gleasonator.com" = "incompatible";
"kitsunemimi.club" = "incompatible";
"poa.st" = "incompatible";
"seal.cafe" = "harassment";
"social.quodverum.com" = "incompatible";
"spinster.xyz" = "incompatible";
"truthsocial.co.in" = "incompatible";
"varishangout.net" = "incompatible";
"activitypub-troll.cf" = "security";
"misskey-forkbomb.cf" = "security";
"repl.co" = "security";
};
followers_only = mkMap {
"bitcoinhackers.org" = "annoying";
};
};
":mrf_object_age".threshold = 180 * 24 * 3600;
":frontend_configurations" = {
pleroma_fe = mkMap {
background = "/images/sylvia-ritter-15012323.avif";
collapseMessageWithSubject = true;
streaming = true;
webPushNotifications = true;
useStreamingApi = true;
scopeCopy = true;
showFeaturesPanel = false;
subjectLineBehavior = "masto";
alwaysShowSubjectInput = true;
postContentType = "text/markdown";
modalOnRepeat = true;
minimalScopesMode = true;
redirectRootNoLogin = "/about";
translationLanguage = "en";
theme = "elly-mod";
};
};
":restrict_unauthenticated" = {
timelines = mkMap {
local = false;
federated = true;
};
};
":translator" = {
enabled = true;
module = mkRaw "Pleroma.Akkoma.Translators.DeepL";
};
":deepl" = {
tier = mkAtom ":free";
api_key._secret = config.sops.secrets."services/akkoma/deepl".path;
};
};
":web_push_encryption".":vapid_details" = {
subject = "mailto:contact@florp.social";
};
":joken".":default_signer"._secret = "/var/lib/secrets/akkoma/jwt-signer";
};
services.postgresql.extraPlugins = [
pkgs.postgresql15Packages.rum
];
services.nginx = {
package = pkgs.tengine;
clientMaxBodySize = "256m";
commonHttpConfig = ''
proxy_cache_path /var/cache/nginx/cache/akkoma-media-cache
levels= keys_zone=akkoma_media_cache:32m max_size=32g
inactive=1y use_temp_path=off;
access_log off;
'';
};
kyouma.nginx.virtualHosts = {
"florp.social" = {
locations."/" = {
proxyPass = "http://unix:/run/akkoma/socket";
proxyWebsockets = true;
};
locations."^/media(/.*)$".return = "308 https://media.florp.social$1";
locations."^/proxy(/.*)$".return = "308 https://cache.florp.social$1";
};
"media.florp.social" = {
useACMEHost = "florp.social";
locations."/" = {
proxyPass = "http://unix:/run/akkoma/socket";
extraConfig = "rewrite ^(?!/media)(.*)$ /media$1;";
};
};
"cache.florp.social" = {
useACMEHost = "florp.social";
locations."/" = {
proxyPass = "http://unix:/run/akkoma/socket";
extraConfig = ''
rewrite ^(?!/proxy)(.*)$ /proxy$1;
proxy_cache akkoma_media_cache;
# Cache objects in slices of 1 MiB
slice 1m;
proxy_cache_key $host$uri$is_args$args$slice_range;
proxy_set_header Range $slice_range;
# Decouple proxy and upstream responses
proxy_buffering on;
proxy_cache_lock on;
proxy_ignore_client_abort on;
# Default cache times for various responses
proxy_cache_valid 200 1y;
proxy_cache_valid 206 301 304 1h;
# Allow serving of stale items
proxy_cache_use_stale error timeout invalid_header updating;
'';
};
};
};
security.acme.certs."florp.social".extraDomainNames = [ "cache.florp.social" "media.florp.social" ];
}