{config, pkgs, ...}: let sources = import ../../../nix/sources.nix; domain = "pleroma.stuebinm.eu"; in { containers.pleroma = { autoStart = true; privateNetwork = true; hostAddress = "192.168.42.30"; localAddress = "192.168.42.31"; hostAddress6 = "fd00::42:30"; localAddress6 = "fd00::42:31"; config = {pkgs, config, ...}: { # pleroma is only on unstable for now, so import it here imports = [ "${sources.nixpkgs-unstable}/nixos/modules/services/networking/pleroma.nix" ]; # generating the manual will fail when mixing nixos channels, # so disable it here or this won't build at all. documentation.enable = false; # pleroma has a cli tool for configuration environment.systemPackages = [ pkgs.pleroma-otp pkgs.dnsutils ]; services.pleroma = { enable = true; # this is barely necessary at this point — all that's # set in here is the default_signer for joken, and the # secret_key_base and signing_salt for phoenix. secretConfigFile = "/var/lib/pleroma/secrets.exs"; # for a list of available config options, see # https://docs-develop.pleroma.social/backend/configuration/cheatsheet/ # # Additionally, some parts of pleroma's config (e.g. Pleroma.Repo) # are better documented in their respective libraries (in this # case, see the documentation for Ecto on Adapters). configs = [ '' import Config config :pleroma, Pleroma.Web.Endpoint, url: [host: "${domain}", scheme: "https", port: 443], http: [ip: {0, 0, 0, 0, 0, 0, 0, 0}, port: 4000] config :pleroma, :instance, name: "Pleroma", limit: 5000, registrations_open: false, federating: true, healthcheck: true, allow_relay: true config :pleroma, :media_proxy, enabled: false, redirect_on_failure: true config :pleroma, Pleroma.Upload, filters: [ Pleroma.Upload.Filter.Exiftool, Pleroma.Upload.Filter.AnonymizeFilename, Pleroma.Upload.Filter.Dedupe ] config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/pleroma/uploads" config :pleroma, Pleroma.Repo, adapter: Ecto.Adapters.Postgres, username: "pleroma", database: "pleroma", socket_dir: "/run/postgresql", pool_size: 10, prepare: :named, parameters: [ plan_cache_mode: "force_custom_plan" ] config :pleroma, :database, rum_enabled: false config :pleroma, configurable_from_database: false config :pleroma, :instance, static_dir: "/var/lib/pleroma/static" '' ]; }; services.postgresql = { enable = true; package = pkgs.postgresql_12; ensureDatabases = [ "pleroma" ]; ensureUsers = [ { name = "pleroma"; ensurePermissions."DATABASE pleroma" = "ALL PRIVILEGES"; } ]; # give pleroma access. must be done with lib.mkForce, for some reason authentication = pkgs.lib.mkForce '' # Generated file; do not edit! local all all trust host pleroma pleroma ::1/128 trust ''; # pleroma wants to do some initial config on startup, which it # can't do by itself since those needs superuser access # # unfortunatly, this is executed /before/ the database is created, # i.e. we have to create user and database by hand, even though # they would otherwise created by ensureUsers / ensureDatabse. # Using those does still prevent us from accidentally deleting # them, though (but not from deleting the database's content!) initialScript = pkgs.writeScript "postgres-pleroma-initial" '' CREATE USER pleroma; CREATE DATABASE pleroma OWNER pleroma; \c pleroma; --Extensions made by ecto.migrate that need superuser access CREATE EXTENSION IF NOT EXISTS citext; CREATE EXTENSION IF NOT EXISTS pg_trgm; CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; ''; }; networking.firewall.allowedTCPPorts = [ 4000 10022 ]; }; }; # give the container access to the external internet (necessary for # fetching content from other instances). Doesn't appear to work with # IPv6, though ... networking.nat = { enable = true; internalInterfaces = [ "ve-pleroma" ]; externalInterface = "ens3"; }; networking.firewall.allowedTCPPorts = [ 10022 ]; services.nginx.virtualHosts."${domain}" = { forceSSL = true; enableACME = true; locations."/" = { proxyPass = "http://[${config.containers.pleroma.localAddress6}]:4000"; proxyWebsockets = true; # these headers are in the example config in the NixOS manual. # take some time to figure out what they all do, and if these # are necessary extraConfig = '' add_header 'Access-Control-Allow-Origin' '*' always; add_header 'Access-Control-Allow-Methods' 'POST, PUT, DELETE, GET, PATCH, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Idempotency-Key' always; add_header 'Access-Control-Expose-Headers' 'Link, X-RateLimit-Reset, X-RateLimit-Limit, X-RateLimit-Remaining, X-Request-Id' always; if ($request_method = OPTIONS) { return 204; } add_header X-XSS-Protection "1; mode=block"; add_header X-Permitted-Cross-Domain-Policies none; add_header X-Frame-Options DENY; add_header X-Content-Type-Options nosniff; add_header Referrer-Policy same-origin; add_header X-Download-Options noopen; client_max_body_size 16m; ''; }; }; }