{ 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" ''

Likes are now florps. The timeline goes sideways.

''; 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" ]; }