···14141515- [river](https://github.com/riverwm/river), A dynamic tiling wayland compositor. Available as [programs.river](#opt-programs.river.enable).
16161717+- [GoToSocial](https://gotosocial.org/), an ActivityPub social network server, written in Golang. Available as [services.gotosocial](#opt-services.gotosocial.enable).
1818+1719- [sitespeed-io](https://sitespeed.io), a tool that can generate metrics (timings, diagnostics) for websites. Available as [services.sitespeed-io](#opt-services.sitespeed-io.enable).
18201921## Backward Incompatibilities {#sec-release-23.11-incompatibilities}
···11+# GoToSocial {#module-services-gotosocial}
22+33+[GoToSocial](https://gotosocial.org/) is an ActivityPub social network server, written in Golang.
44+55+## Service configuration {#modules-services-gotosocial-service-configuration}
66+77+The following configuration sets up the PostgreSQL as database backend and binds
88+GoToSocial to `127.0.0.1:8080`, expecting to be run behind a HTTP proxy on `gotosocial.example.com`.
99+1010+```nix
1111+services.gotosocial = {
1212+ enable = true;
1313+ setupPostgresqlDB = true;
1414+ settings = {
1515+ application-name = "My GoToSocial";
1616+ host = "gotosocial.example.com";
1717+ protocol = "https";
1818+ bind-address = "127.0.0.1";
1919+ port = 8080;
2020+ };
2121+};
2222+```
2323+2424+Please refer to the [GoToSocial Documentation](https://docs.gotosocial.org/en/latest/configuration/general/)
2525+for additional configuration options.
2626+2727+## Proxy configuration {#modules-services-gotosocial-proxy-configuration}
2828+2929+Although it is possible to expose GoToSocial directly, it is common practice to operate it behind an
3030+HTTP reverse proxy such as nginx.
3131+3232+```nix
3333+networking.firewall.allowedTCPPorts = [ 80 443 ];
3434+services.nginx = {
3535+ enable = true;
3636+ clientMaxBodySize = "40M";
3737+ virtualHosts = with config.services.gotosocial.settings; {
3838+ "${host}" = {
3939+ enableACME = true;
4040+ forceSSL = true;
4141+ locations = {
4242+ "/" = {
4343+ recommendedProxySettings = true;
4444+ proxyWebsockets = true;
4545+ proxyPass = "http://${bind-address}:${toString port}";
4646+ };
4747+ };
4848+ };
4949+ };
5050+};
5151+```
5252+5353+Please refer to [](#module-security-acme) for details on how to provision an SSL/TLS certificate.
5454+5555+## User management {#modules-services-gotosocial-user-management}
5656+5757+After the GoToSocial service is running, the `gotosocial-admin` utility can be used to manage users. In particular an
5858+administrative user can be created with
5959+6060+```ShellSession
6161+$ sudo gotosocial-admin account create --username <nickname> --email <email> --password <password>
6262+$ sudo gotosocial-admin account confirm --username <nickname>
6363+$ sudo gotosocial-admin account promote --username <nickname>
6464+```
+173
nixos/modules/services/web-apps/gotosocial.nix
···11+{ config, lib, pkgs, ... }:
22+let
33+ cfg = config.services.gotosocial;
44+ settingsFormat = pkgs.formats.yaml { };
55+ configFile = settingsFormat.generate "config.yml" cfg.settings;
66+ defaultSettings = {
77+ application-name = "gotosocial";
88+99+ protocol = "https";
1010+1111+ bind-address = "127.0.0.1";
1212+ port = 8080;
1313+1414+ storage-local-base-path = "/var/lib/gotosocial/storage";
1515+1616+ db-type = "sqlite";
1717+ db-address = "/var/lib/gotosocial/database.sqlite";
1818+ };
1919+ gotosocial-admin = pkgs.writeShellScriptBin "gotosocial-admin" ''
2020+ exec systemd-run \
2121+ -u gotosocial-admin.service \
2222+ -p Group=gotosocial \
2323+ -p User=gotosocial \
2424+ -q -t -G --wait --service-type=exec \
2525+ ${cfg.package}/bin/gotosocial --config-path ${configFile} admin "$@"
2626+ '';
2727+in
2828+{
2929+ meta.doc = ./gotosocial.md;
3030+ meta.maintainers = with lib.maintainers; [ misuzu ];
3131+3232+ options.services.gotosocial = {
3333+ enable = lib.mkEnableOption (lib.mdDoc "ActivityPub social network server");
3434+3535+ package = lib.mkPackageOptionMD pkgs "gotosocial" { };
3636+3737+ openFirewall = lib.mkOption {
3838+ type = lib.types.bool;
3939+ default = false;
4040+ description = lib.mdDoc ''
4141+ Open the configured port in the firewall.
4242+ Using a reverse proxy instead is highly recommended.
4343+ '';
4444+ };
4545+4646+ setupPostgresqlDB = lib.mkOption {
4747+ type = lib.types.bool;
4848+ default = false;
4949+ description = lib.mdDoc ''
5050+ Whether to setup a local postgres database and populate the
5151+ `db-type` fields in `services.gotosocial.settings`.
5252+ '';
5353+ };
5454+5555+ settings = lib.mkOption {
5656+ type = settingsFormat.type;
5757+ default = defaultSettings;
5858+ example = {
5959+ application-name = "My GoToSocial";
6060+ host = "gotosocial.example.com";
6161+ };
6262+ description = lib.mdDoc ''
6363+ Contents of the GoToSocial YAML config.
6464+6565+ Please refer to the
6666+ [documentation](https://docs.gotosocial.org/en/latest/configuration/)
6767+ and
6868+ [example config](https://github.com/superseriousbusiness/gotosocial/blob/main/example/config.yaml).
6969+7070+ Please note that the `host` option cannot be changed later so it is important to configure this correctly before you start GoToSocial.
7171+ '';
7272+ };
7373+7474+ environmentFile = lib.mkOption {
7575+ type = lib.types.nullOr lib.types.path;
7676+ description = lib.mdDoc ''
7777+ File path containing environment variables for configuring the GoToSocial service
7878+ in the format of an EnvironmentFile as described by systemd.exec(5).
7979+8080+ This option could be used to pass sensitive configuration to the GoToSocial daemon.
8181+8282+ Please refer to the Environment Variables section in the
8383+ [documentation](https://docs.gotosocial.org/en/latest/configuration/).
8484+ '';
8585+ default = null;
8686+ example = "/root/nixos/secrets/gotosocial.env";
8787+ };
8888+8989+ };
9090+9191+ config = lib.mkIf cfg.enable {
9292+ assertions = [
9393+ {
9494+ assertion = cfg.settings.host or null != null;
9595+ message = ''
9696+ You have to define a hostname for GoToSocial (`services.gotosocial.settings.host`), it cannot be changed later without starting over!
9797+ '';
9898+ }
9999+ ];
100100+101101+ services.gotosocial.settings = (lib.mapAttrs (name: lib.mkDefault) (
102102+ defaultSettings // {
103103+ web-asset-base-dir = "${cfg.package}/share/gotosocial/web/assets/";
104104+ web-template-base-dir = "${cfg.package}/share/gotosocial/web/template/";
105105+ }
106106+ )) // (lib.optionalAttrs cfg.setupPostgresqlDB {
107107+ db-type = "postgres";
108108+ db-address = "/run/postgresql";
109109+ db-database = "gotosocial";
110110+ db-user = "gotosocial";
111111+ });
112112+113113+ environment.systemPackages = [ gotosocial-admin ];
114114+115115+ users.groups.gotosocial = { };
116116+ users.users.gotosocial = {
117117+ group = "gotosocial";
118118+ isSystemUser = true;
119119+ };
120120+121121+ networking.firewall = lib.mkIf cfg.openFirewall {
122122+ allowedTCPPorts = [ cfg.settings.port ];
123123+ };
124124+125125+ services.postgresql = lib.mkIf cfg.setupPostgresqlDB {
126126+ enable = true;
127127+ ensureDatabases = [ "gotosocial" ];
128128+ ensureUsers = [
129129+ {
130130+ name = "gotosocial";
131131+ ensurePermissions = {
132132+ "DATABASE gotosocial" = "ALL PRIVILEGES";
133133+ };
134134+ }
135135+ ];
136136+ };
137137+138138+ systemd.services.gotosocial = {
139139+ description = "ActivityPub social network server";
140140+ wantedBy = [ "multi-user.target" ];
141141+ after = [ "network.target" ]
142142+ ++ lib.optional cfg.setupPostgresqlDB "postgresql.service";
143143+ requires = lib.optional cfg.setupPostgresqlDB "postgresql.service";
144144+ restartTriggers = [ configFile ];
145145+146146+ serviceConfig = {
147147+ EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
148148+ ExecStart = "${cfg.package}/bin/gotosocial --config-path ${configFile} server start";
149149+ Restart = "on-failure";
150150+ Group = "gotosocial";
151151+ User = "gotosocial";
152152+ StateDirectory = "gotosocial";
153153+ WorkingDirectory = "/var/lib/gotosocial";
154154+155155+ # Security options:
156156+ # Based on https://github.com/superseriousbusiness/gotosocial/blob/v0.8.1/example/gotosocial.service
157157+ AmbientCapabilities = lib.optional (cfg.settings.port < 1024) "CAP_NET_BIND_SERVICE";
158158+ NoNewPrivileges = true;
159159+ PrivateTmp = true;
160160+ PrivateDevices = true;
161161+ RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
162162+ RestrictNamespaces = true;
163163+ RestrictRealtime = true;
164164+ DevicePolicy = "closed";
165165+ ProtectSystem = "full";
166166+ ProtectControlGroups = true;
167167+ ProtectKernelModules = true;
168168+ ProtectKernelTunables = true;
169169+ LockPersonality = true;
170170+ };
171171+ };
172172+ };
173173+}