1# Akkoma {#module-services-akkoma} 2 3[Akkoma](https://akkoma.dev/) is a lightweight ActivityPub microblogging server forked from Pleroma. 4 5## Service configuration {#modules-services-akkoma-service-configuration} 6 7The Elixir configuration file required by Akkoma is generated automatically from 8[{option}`services.akkoma.config`](options.html#opt-services.akkoma.config). Secrets must be 9included from external files outside of the Nix store by setting the configuration option to 10an attribute set containing the attribute {option}`_secret` – a string pointing to the file 11containing the actual value of the option. 12 13For the mandatory configuration settings these secrets will be generated automatically if the 14referenced file does not exist during startup, unless disabled through 15[{option}`services.akkoma.initSecrets`](options.html#opt-services.akkoma.initSecrets). 16 17The following configuration binds Akkoma to the Unix socket `/run/akkoma/socket`, expecting to 18be run behind a HTTP proxy on `fediverse.example.com`. 19 20 21```nix 22{ 23 services.akkoma.enable = true; 24 services.akkoma.config = { 25 ":pleroma" = { 26 ":instance" = { 27 name = "My Akkoma instance"; 28 description = "More detailed description"; 29 email = "admin@example.com"; 30 registration_open = false; 31 }; 32 33 "Pleroma.Web.Endpoint" = { 34 url.host = "fediverse.example.com"; 35 }; 36 }; 37 }; 38} 39``` 40 41Please refer to the [configuration cheat sheet](https://docs.akkoma.dev/stable/configuration/cheatsheet/) 42for additional configuration options. 43 44## User management {#modules-services-akkoma-user-management} 45 46After the Akkoma service is running, the administration utility can be used to 47[manage users](https://docs.akkoma.dev/stable/administration/CLI_tasks/user/). In particular an 48administrative user can be created with 49 50```ShellSession 51$ pleroma_ctl user new <nickname> <email> --admin --moderator --password <password> 52``` 53 54## Proxy configuration {#modules-services-akkoma-proxy-configuration} 55 56Although it is possible to expose Akkoma directly, it is common practice to operate it behind an 57HTTP reverse proxy such as nginx. 58 59```nix 60{ 61 services.akkoma.nginx = { 62 enableACME = true; 63 forceSSL = true; 64 }; 65 66 services.nginx = { 67 enable = true; 68 69 clientMaxBodySize = "16m"; 70 recommendedTlsSettings = true; 71 recommendedOptimisation = true; 72 recommendedGzipSettings = true; 73 }; 74} 75``` 76 77Please refer to [](#module-security-acme) for details on how to provision an SSL/TLS certificate. 78 79### Media proxy {#modules-services-akkoma-media-proxy} 80 81Without the media proxy function, Akkoma does not store any remote media like pictures or video 82locally, and clients have to fetch them directly from the source server. 83 84```nix 85{ 86 # Enable nginx slice module distributed with Tengine 87 services.nginx.package = pkgs.tengine; 88 89 # Enable media proxy 90 services.akkoma.config.":pleroma".":media_proxy" = { 91 enabled = true; 92 proxy_opts.redirect_on_failure = true; 93 }; 94 95 # Adjust the persistent cache size as needed: 96 # Assuming an average object size of 128 KiB, around 1 MiB 97 # of memory is required for the key zone per GiB of cache. 98 # Ensure that the cache directory exists and is writable by nginx. 99 services.nginx.commonHttpConfig = '' 100 proxy_cache_path /var/cache/nginx/cache/akkoma-media-cache 101 levels= keys_zone=akkoma_media_cache:16m max_size=16g 102 inactive=1y use_temp_path=off; 103 ''; 104 105 services.akkoma.nginx = { 106 locations."/proxy" = { 107 proxyPass = "http://unix:/run/akkoma/socket"; 108 109 extraConfig = '' 110 proxy_cache akkoma_media_cache; 111 112 # Cache objects in slices of 1 MiB 113 slice 1m; 114 proxy_cache_key $host$uri$is_args$args$slice_range; 115 proxy_set_header Range $slice_range; 116 117 # Decouple proxy and upstream responses 118 proxy_buffering on; 119 proxy_cache_lock on; 120 proxy_ignore_client_abort on; 121 122 # Default cache times for various responses 123 proxy_cache_valid 200 1y; 124 proxy_cache_valid 206 301 304 1h; 125 126 # Allow serving of stale items 127 proxy_cache_use_stale error timeout invalid_header updating; 128 ''; 129 }; 130 }; 131} 132``` 133 134#### Prefetch remote media {#modules-services-akkoma-prefetch-remote-media} 135 136The following example enables the `MediaProxyWarmingPolicy` MRF policy which automatically 137fetches all media associated with a post through the media proxy, as soon as the post is 138received by the instance. 139 140```nix 141{ 142 services.akkoma.config.":pleroma".":mrf".policies = 143 map (pkgs.formats.elixirConf { }).lib.mkRaw [ 144 "Pleroma.Web.ActivityPub.MRF.MediaProxyWarmingPolicy" 145 ]; 146} 147``` 148 149#### Media previews {#modules-services-akkoma-media-previews} 150 151Akkoma can generate previews for media. 152 153```nix 154{ 155 services.akkoma.config.":pleroma".":media_preview_proxy" = { 156 enabled = true; 157 thumbnail_max_width = 1920; 158 thumbnail_max_height = 1080; 159 }; 160} 161``` 162 163## Frontend management {#modules-services-akkoma-frontend-management} 164 165Akkoma will be deployed with the `akkoma-fe` and `admin-fe` frontends by default. These can be 166modified by setting 167[{option}`services.akkoma.frontends`](options.html#opt-services.akkoma.frontends). 168 169The following example overrides the primary frontend’s default configuration using a custom 170derivation. 171 172```nix 173{ 174 services.akkoma.frontends.primary.package = pkgs.runCommand "akkoma-fe" { 175 config = builtins.toJSON { 176 expertLevel = 1; 177 collapseMessageWithSubject = false; 178 stopGifs = false; 179 replyVisibility = "following"; 180 webPushHideIfCW = true; 181 hideScopeNotice = true; 182 renderMisskeyMarkdown = false; 183 hideSiteFavicon = true; 184 postContentType = "text/markdown"; 185 showNavShortcuts = false; 186 }; 187 nativeBuildInputs = with pkgs; [ jq xorg.lndir ]; 188 passAsFile = [ "config" ]; 189 } '' 190 mkdir $out 191 lndir ${pkgs.akkoma-frontends.akkoma-fe} $out 192 193 rm $out/static/config.json 194 jq -s add ${pkgs.akkoma-frontends.akkoma-fe}/static/config.json ${config} \ 195 >$out/static/config.json 196 ''; 197} 198``` 199 200## Federation policies {#modules-services-akkoma-federation-policies} 201 202Akkoma comes with a number of modules to police federation with other ActivityPub instances. 203The most valuable for typical users is the 204[`:mrf_simple`](https://docs.akkoma.dev/stable/configuration/cheatsheet/#mrf_simple) module 205which allows limiting federation based on instance hostnames. 206 207This configuration snippet provides an example on how these can be used. Choosing an adequate 208federation policy is not trivial and entails finding a balance between connectivity to the rest 209of the fediverse and providing a pleasant experience to the users of an instance. 210 211 212```nix 213{ 214 services.akkoma.config.":pleroma" = with (pkgs.formats.elixirConf { }).lib; { 215 ":mrf".policies = map mkRaw [ 216 "Pleroma.Web.ActivityPub.MRF.SimplePolicy" 217 ]; 218 219 ":mrf_simple" = { 220 # Tag all media as sensitive 221 media_nsfw = mkMap { 222 "nsfw.weird.kinky" = "Untagged NSFW content"; 223 }; 224 225 # Reject all activities except deletes 226 reject = mkMap { 227 "kiwifarms.cc" = "Persistent harassment of users, no moderation"; 228 }; 229 230 # Force posts to be visible by followers only 231 followers_only = mkMap { 232 "beta.birdsite.live" = "Avoid polluting timelines with Twitter posts"; 233 }; 234 }; 235 }; 236} 237``` 238 239## Upload filters {#modules-services-akkoma-upload-filters} 240 241This example strips GPS and location metadata from uploads, deduplicates them and anonymises the 242the file name. 243 244```nix 245{ 246 services.akkoma.config.":pleroma"."Pleroma.Upload".filters = 247 map (pkgs.formats.elixirConf { }).lib.mkRaw [ 248 "Pleroma.Upload.Filter.Exiftool" 249 "Pleroma.Upload.Filter.Dedupe" 250 "Pleroma.Upload.Filter.AnonymizeFilename" 251 ]; 252} 253``` 254 255## Migration from Pleroma {#modules-services-akkoma-migration-pleroma} 256 257Pleroma instances can be migrated to Akkoma either by copying the database and upload data or by 258pointing Akkoma to the existing data. The necessary database migrations are run automatically 259during startup of the service. 260 261The configuration has to be copy‐edited manually. 262 263Depending on the size of the database, the initial migration may take a long time and exceed the 264startup timeout of the system manager. To work around this issue one may adjust the startup timeout 265{option}`systemd.services.akkoma.serviceConfig.TimeoutStartSec` or simply run the migrations 266manually: 267 268```ShellSession 269pleroma_ctl migrate 270``` 271 272### Copying data {#modules-services-akkoma-migration-pleroma-copy} 273 274Copying the Pleroma data instead of re‐using it in place may permit easier reversion to Pleroma, 275but allows the two data sets to diverge. 276 277First disable Pleroma and then copy its database and upload data: 278 279```ShellSession 280# Create a copy of the database 281nix-shell -p postgresql --run 'createdb -T pleroma akkoma' 282 283# Copy upload data 284mkdir /var/lib/akkoma 285cp -R --reflink=auto /var/lib/pleroma/uploads /var/lib/akkoma/ 286``` 287 288After the data has been copied, enable the Akkoma service and verify that the migration has been 289successful. If no longer required, the original data may then be deleted: 290 291```ShellSession 292# Delete original database 293nix-shell -p postgresql --run 'dropdb pleroma' 294 295# Delete original Pleroma state 296rm -r /var/lib/pleroma 297``` 298 299### Re‐using data {#modules-services-akkoma-migration-pleroma-reuse} 300 301To re‐use the Pleroma data in place, disable Pleroma and enable Akkoma, pointing it to the 302Pleroma database and upload directory. 303 304```nix 305{ 306 # Adjust these settings according to the database name and upload directory path used by Pleroma 307 services.akkoma.config.":pleroma"."Pleroma.Repo".database = "pleroma"; 308 services.akkoma.config.":pleroma".":instance".upload_dir = "/var/lib/pleroma/uploads"; 309} 310``` 311 312Please keep in mind that after the Akkoma service has been started, any migrations applied by 313Akkoma have to be rolled back before the database can be used again with Pleroma. This can be 314achieved through `pleroma_ctl ecto.rollback`. Refer to the 315[Ecto SQL documentation](https://hexdocs.pm/ecto_sql/Mix.Tasks.Ecto.Rollback.html) for 316details. 317 318## Advanced deployment options {#modules-services-akkoma-advanced-deployment} 319 320### Confinement {#modules-services-akkoma-confinement} 321 322The Akkoma systemd service may be confined to a chroot with 323 324```nix 325{ 326 services.systemd.akkoma.confinement.enable = true; 327} 328``` 329 330Confinement of services is not generally supported in NixOS and therefore disabled by default. 331Depending on the Akkoma configuration, the default confinement settings may be insufficient and 332lead to subtle errors at run time, requiring adjustment: 333 334Use 335[{option}`services.systemd.akkoma.confinement.packages`](options.html#opt-systemd.services._name_.confinement.packages) 336to make packages available in the chroot. 337 338{option}`services.systemd.akkoma.serviceConfig.BindPaths` and 339{option}`services.systemd.akkoma.serviceConfig.BindReadOnlyPaths` permit access to outside paths 340through bind mounts. Refer to 341[`BindPaths=`](https://www.freedesktop.org/software/systemd/man/systemd.exec.html#BindPaths=) 342of {manpage}`systemd.exec(5)` for details. 343 344### Distributed deployment {#modules-services-akkoma-distributed-deployment} 345 346Being an Elixir application, Akkoma can be deployed in a distributed fashion. 347 348This requires setting 349[{option}`services.akkoma.dist.address`](options.html#opt-services.akkoma.dist.address) and 350[{option}`services.akkoma.dist.cookie`](options.html#opt-services.akkoma.dist.cookie). The 351specifics depend strongly on the deployment environment. For more information please check the 352relevant [Erlang documentation](https://www.erlang.org/doc/reference_manual/distributed.html).