{ pkgs, lib, config, ... }: let domain = "autogeree.net"; srv = "pleroma"; owner = "${srv}-${domain}"; db = "${srv}-${domain}"; port = 4000; inherit (config.services) postgresql; inherit (config.users) groups; # pleroma_ctl instance gen # https://git.pleroma.social/pleroma/pleroma/blob/develop/config/config.exs pleroma-conf = '' import Config config :pleroma, Pleroma.Web.Endpoint, url: [host: "${srv}.${domain}", scheme: "https", port: 443], http: [ip: {127, 0, 0, 1}, port: ${toString port}] config :pleroma, :http_security, sts: true config :pleroma, Pleroma.Web.WebFinger, domain: "${domain}" # RELEASE_COOKIE="/var/lib/pleroma/.cookie" \ # pleroma_ctl user new $user $user+pleroma@autogeree.net --password "$password" --moderator --admin -y config :pleroma, :instance, name: "${domain}", email: "root+${srv}@${domain}", notify_email: "root+${srv}@${domain}", limit: 5000, registrations_open: false, invites_enabled: true, description: "Pleroma: An efficient and flexible fediverse server", short_description: "", background_image: "/images/city.jpg", instance_thumbnail: "/instance/thumbnail.jpeg", max_pinned_statuses: 4 config :pleroma, :media_proxy, enabled: false, redirect_on_failure: true #base_url: "https://cache.pleroma.social" config :pleroma, :markup, allow_inline_images: true, allow_headings: true, allow_tables: true # pleroma_ctl email test --to julm+pleroma@autogeree.net config :pleroma, Pleroma.Emails.Mailer, [ adapter: Swoosh.Adapters.Sendmail, enabled: true, cmd_path: "/run/wrappers/bin/sendmail", cmd_args: "" ] config :pleroma, :dangerzone, override_repo_pool_size: true config :pleroma, Pleroma.Repo, adapter: Ecto.Adapters.Postgres, username: "${owner}", socket_dir: "/run/postgresql", database: "${db}", migration_lock: :pg_advisory_lock, pool_size: 5, # Database task queue timeout to avoid timeouts on the front end # due to a slow postgresql, eg. because of a CPUQuota= hardening. queue_target: 20_000, queue_interval: 1_000, ownership_timeout: 20_000, timeout: 40_000, prepare: :named, # https://docs-develop.pleroma.social/backend/configuration/postgresql/#disable-generic-query-plans parameters: [ plan_cache_mode: "force_custom_plan" ] config :pleroma, :database, rum_enabled: false config :pleroma, :instance, static_dir: "/var/lib/${srv}/static" config :pleroma, Pleroma.Uploaders.Local, uploads: "/var/lib/${srv}/uploads" config :pleroma, configurable_from_database: false config :pleroma, Pleroma.Upload, filters: [ Pleroma.Upload.Filter.Exiftool.StripLocation, Pleroma.Upload.Filter.Exiftool.ReadDescription ] # https://docs-develop.pleroma.social/backend/configuration/howto_proxy/ #config :pleroma, :http, proxy_url: {:socks5, :localhost, 9050} config :pleroma, :mrf, policies: [ Pleroma.Web.ActivityPub.MRF.ObjectAgePolicy, Pleroma.Web.ActivityPub.MRF.TagPolicy, Pleroma.Web.ActivityPub.MRF.SimplePolicy ] config :pleroma, :media_proxy, enabled: true, proxy_opts: [ redirect_on_failure: true ]; ''; in { services = { pleroma = { enable = true; configs = [ pleroma-conf # Use $CREDENTIALS_DIRECTORY to work with both pleroma.service and pleroma-migrations.service '' import Config cred_dir = System.get_env("CREDENTIALS_DIRECTORY") import_config "#{cred_dir}/config.exs" '' ]; secretConfigFile = "/dev/null"; }; nginx = { enable = true; upstreams.${srv} = { servers."127.0.0.1:${toString port}" = { max_fails = 5; fail_timeout = "60s"; }; extraConfig = '' ''; }; proxyCachePath."${domain}/${srv}/proxy" = { enable = true; inactive = "720m"; keysZoneName = "${domain}/${srv}/proxy"; keysZoneSize = "10m"; levels = "1:2"; maxSize = "10g"; useTempPath = false; }; virtualHosts.${domain} = { locations."/.well-known/host-meta" = { return = "301 https://${srv}.${domain}$request_uri"; }; }; virtualHosts."${srv}.${domain}" = { forceSSL = true; useACMEHost = domain; extraConfig = '' access_log /var/log/nginx/${domain}/${srv}/access.log json buffer=32k; error_log /var/log/nginx/${domain}/${srv}/error.log; ''; locations."/" = { proxyPass = "http://${srv}"; 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 Referrer-Policy same-origin; add_header X-Content-Type-Options nosniff; add_header X-Download-Options noopen; add_header X-Frame-Options DENY; add_header X-Permitted-Cross-Domain-Policies none; add_header X-XSS-Protection "1; mode=block"; client_max_body_size 16m; proxy_connect_timeout 90; proxy_http_version 1.1; proxy_read_timeout 90; proxy_redirect off; proxy_send_timeout 90; proxy_set_header Connection "upgrade"; proxy_set_header Upgrade $http_upgrade; ''; }; locations."/proxy" = { proxyPass = "http://${srv}"; extraConfig = '' proxy_cache ${domain}/${srv}/proxy; proxy_cache_lock on; proxy_ignore_client_abort on; ''; }; }; }; postgresql = { identMap = '' # MAPNAME SYSTEM-USERNAME PG-USERNAME user root ${owner} user ${srv} ${owner} ''; }; sanoid.datasets."rpool/var/lib/${srv}" = { use_template = [ "snap" ]; daily = 31; monthly = 3; recursive = true; }; }; systemd.services = { nginx = { serviceConfig = { LogsDirectory = lib.mkForce [ "nginx/${domain}/${srv}" ]; }; }; pleroma-migrations = { serviceConfig = { LoadCredentialEncrypted = [ "config.exs:${./pleroma/config.exs.cred}" ]; SupplementaryGroups = [ groups."postgres".name ]; }; }; pleroma = { path = [ pkgs.exiftool # For RELEASE_COOKIE pkgs.hexdump # For rand() pkgs.gawk ]; environment.RELEASE_VM_ARGS = pkgs.writeText "vm.args" '' # Disable the busy-waiting. # https://docs-develop.pleroma.social/backend/configuration/optimizing_beam/#virtual-machine-andor-few-cpu-cores +sbwt none +sbwtdcpu none +sbwtdio none ''; unitConfig = { StartLimitBurst = 5; StartLimitIntervalSec = "600s"; }; serviceConfig = { LoadCredentialEncrypted = [ "config.exs:${./pleroma/config.exs.cred}" ]; SupplementaryGroups = [ groups."postgres".name ]; TimeoutStopSec = "10s"; Restart = "on-failure"; RestartSec = "10s"; MemoryAccounting = true; MemoryHigh = "500M"; MemoryMax = "600M"; # For sendmail NoNewPrivileges = lib.mkForce false; }; }; postgresql = { postStart = lib.mkAfter '' connection_limit=64 \ encoding=UTF8 \ lc_collate=fr_FR.UTF-8 \ lc_type=fr_FR.UTF-8 \ owner="${owner}" \ pass="" \ pg_createdb "${db}" >/dev/null pg_adduser "${db}" "${owner}" >/dev/null $PSQL -d "${db}" -AqtX --set ON_ERROR_STOP=1 -f - <