From 45ffb33514488fd27b9355081a687db8312d97f4 Mon Sep 17 00:00:00 2001 From: misuzu Date: Fri, 19 May 2023 21:18:17 +0300 Subject: [PATCH] nixos/gotosocial: init Co-authored-by: Peder Bergebakken Sundt --- .../manual/release-notes/rl-2311.section.md | 2 + nixos/modules/module-list.nix | 1 + nixos/modules/services/web-apps/gotosocial.md | 64 +++++++ .../modules/services/web-apps/gotosocial.nix | 173 ++++++++++++++++++ nixos/tests/all-tests.nix | 1 + nixos/tests/web-apps/gotosocial.nix | 28 +++ pkgs/servers/gotosocial/default.nix | 3 + 7 files changed, 272 insertions(+) create mode 100644 nixos/modules/services/web-apps/gotosocial.md create mode 100644 nixos/modules/services/web-apps/gotosocial.nix create mode 100644 nixos/tests/web-apps/gotosocial.nix diff --git a/nixos/doc/manual/release-notes/rl-2311.section.md b/nixos/doc/manual/release-notes/rl-2311.section.md index 6f770757edba..8f67999433f0 100644 --- a/nixos/doc/manual/release-notes/rl-2311.section.md +++ b/nixos/doc/manual/release-notes/rl-2311.section.md @@ -14,6 +14,8 @@ - [river](https://github.com/riverwm/river), A dynamic tiling wayland compositor. Available as [programs.river](#opt-programs.river.enable). +- [GoToSocial](https://gotosocial.org/), an ActivityPub social network server, written in Golang. Available as [services.gotosocial](#opt-services.gotosocial.enable). + - [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). ## Backward Incompatibilities {#sec-release-23.11-incompatibilities} diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 83b2a45dbd3b..42230f4524c5 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1188,6 +1188,7 @@ ./services/web-apps/galene.nix ./services/web-apps/gerrit.nix ./services/web-apps/gotify-server.nix + ./services/web-apps/gotosocial.nix ./services/web-apps/grocy.nix ./services/web-apps/pixelfed.nix ./services/web-apps/healthchecks.nix diff --git a/nixos/modules/services/web-apps/gotosocial.md b/nixos/modules/services/web-apps/gotosocial.md new file mode 100644 index 000000000000..a290d7d1893a --- /dev/null +++ b/nixos/modules/services/web-apps/gotosocial.md @@ -0,0 +1,64 @@ +# GoToSocial {#module-services-gotosocial} + +[GoToSocial](https://gotosocial.org/) is an ActivityPub social network server, written in Golang. + +## Service configuration {#modules-services-gotosocial-service-configuration} + +The following configuration sets up the PostgreSQL as database backend and binds +GoToSocial to `127.0.0.1:8080`, expecting to be run behind a HTTP proxy on `gotosocial.example.com`. + +```nix +services.gotosocial = { + enable = true; + setupPostgresqlDB = true; + settings = { + application-name = "My GoToSocial"; + host = "gotosocial.example.com"; + protocol = "https"; + bind-address = "127.0.0.1"; + port = 8080; + }; +}; +``` + +Please refer to the [GoToSocial Documentation](https://docs.gotosocial.org/en/latest/configuration/general/) +for additional configuration options. + +## Proxy configuration {#modules-services-gotosocial-proxy-configuration} + +Although it is possible to expose GoToSocial directly, it is common practice to operate it behind an +HTTP reverse proxy such as nginx. + +```nix +networking.firewall.allowedTCPPorts = [ 80 443 ]; +services.nginx = { + enable = true; + clientMaxBodySize = "40M"; + virtualHosts = with config.services.gotosocial.settings; { + "${host}" = { + enableACME = true; + forceSSL = true; + locations = { + "/" = { + recommendedProxySettings = true; + proxyWebsockets = true; + proxyPass = "http://${bind-address}:${toString port}"; + }; + }; + }; + }; +}; +``` + +Please refer to [](#module-security-acme) for details on how to provision an SSL/TLS certificate. + +## User management {#modules-services-gotosocial-user-management} + +After the GoToSocial service is running, the `gotosocial-admin` utility can be used to manage users. In particular an +administrative user can be created with + +```ShellSession +$ sudo gotosocial-admin account create --username --email --password +$ sudo gotosocial-admin account confirm --username +$ sudo gotosocial-admin account promote --username +``` diff --git a/nixos/modules/services/web-apps/gotosocial.nix b/nixos/modules/services/web-apps/gotosocial.nix new file mode 100644 index 000000000000..f7ae018d5b7c --- /dev/null +++ b/nixos/modules/services/web-apps/gotosocial.nix @@ -0,0 +1,173 @@ +{ config, lib, pkgs, ... }: +let + cfg = config.services.gotosocial; + settingsFormat = pkgs.formats.yaml { }; + configFile = settingsFormat.generate "config.yml" cfg.settings; + defaultSettings = { + application-name = "gotosocial"; + + protocol = "https"; + + bind-address = "127.0.0.1"; + port = 8080; + + storage-local-base-path = "/var/lib/gotosocial/storage"; + + db-type = "sqlite"; + db-address = "/var/lib/gotosocial/database.sqlite"; + }; + gotosocial-admin = pkgs.writeShellScriptBin "gotosocial-admin" '' + exec systemd-run \ + -u gotosocial-admin.service \ + -p Group=gotosocial \ + -p User=gotosocial \ + -q -t -G --wait --service-type=exec \ + ${cfg.package}/bin/gotosocial --config-path ${configFile} admin "$@" + ''; +in +{ + meta.doc = ./gotosocial.md; + meta.maintainers = with lib.maintainers; [ misuzu ]; + + options.services.gotosocial = { + enable = lib.mkEnableOption (lib.mdDoc "ActivityPub social network server"); + + package = lib.mkPackageOptionMD pkgs "gotosocial" { }; + + openFirewall = lib.mkOption { + type = lib.types.bool; + default = false; + description = lib.mdDoc '' + Open the configured port in the firewall. + Using a reverse proxy instead is highly recommended. + ''; + }; + + setupPostgresqlDB = lib.mkOption { + type = lib.types.bool; + default = false; + description = lib.mdDoc '' + Whether to setup a local postgres database and populate the + `db-type` fields in `services.gotosocial.settings`. + ''; + }; + + settings = lib.mkOption { + type = settingsFormat.type; + default = defaultSettings; + example = { + application-name = "My GoToSocial"; + host = "gotosocial.example.com"; + }; + description = lib.mdDoc '' + Contents of the GoToSocial YAML config. + + Please refer to the + [documentation](https://docs.gotosocial.org/en/latest/configuration/) + and + [example config](https://github.com/superseriousbusiness/gotosocial/blob/main/example/config.yaml). + + Please note that the `host` option cannot be changed later so it is important to configure this correctly before you start GoToSocial. + ''; + }; + + environmentFile = lib.mkOption { + type = lib.types.nullOr lib.types.path; + description = lib.mdDoc '' + File path containing environment variables for configuring the GoToSocial service + in the format of an EnvironmentFile as described by systemd.exec(5). + + This option could be used to pass sensitive configuration to the GoToSocial daemon. + + Please refer to the Environment Variables section in the + [documentation](https://docs.gotosocial.org/en/latest/configuration/). + ''; + default = null; + example = "/root/nixos/secrets/gotosocial.env"; + }; + + }; + + config = lib.mkIf cfg.enable { + assertions = [ + { + assertion = cfg.settings.host or null != null; + message = '' + You have to define a hostname for GoToSocial (`services.gotosocial.settings.host`), it cannot be changed later without starting over! + ''; + } + ]; + + services.gotosocial.settings = (lib.mapAttrs (name: lib.mkDefault) ( + defaultSettings // { + web-asset-base-dir = "${cfg.package}/share/gotosocial/web/assets/"; + web-template-base-dir = "${cfg.package}/share/gotosocial/web/template/"; + } + )) // (lib.optionalAttrs cfg.setupPostgresqlDB { + db-type = "postgres"; + db-address = "/run/postgresql"; + db-database = "gotosocial"; + db-user = "gotosocial"; + }); + + environment.systemPackages = [ gotosocial-admin ]; + + users.groups.gotosocial = { }; + users.users.gotosocial = { + group = "gotosocial"; + isSystemUser = true; + }; + + networking.firewall = lib.mkIf cfg.openFirewall { + allowedTCPPorts = [ cfg.settings.port ]; + }; + + services.postgresql = lib.mkIf cfg.setupPostgresqlDB { + enable = true; + ensureDatabases = [ "gotosocial" ]; + ensureUsers = [ + { + name = "gotosocial"; + ensurePermissions = { + "DATABASE gotosocial" = "ALL PRIVILEGES"; + }; + } + ]; + }; + + systemd.services.gotosocial = { + description = "ActivityPub social network server"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ] + ++ lib.optional cfg.setupPostgresqlDB "postgresql.service"; + requires = lib.optional cfg.setupPostgresqlDB "postgresql.service"; + restartTriggers = [ configFile ]; + + serviceConfig = { + EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile; + ExecStart = "${cfg.package}/bin/gotosocial --config-path ${configFile} server start"; + Restart = "on-failure"; + Group = "gotosocial"; + User = "gotosocial"; + StateDirectory = "gotosocial"; + WorkingDirectory = "/var/lib/gotosocial"; + + # Security options: + # Based on https://github.com/superseriousbusiness/gotosocial/blob/v0.8.1/example/gotosocial.service + AmbientCapabilities = lib.optional (cfg.settings.port < 1024) "CAP_NET_BIND_SERVICE"; + NoNewPrivileges = true; + PrivateTmp = true; + PrivateDevices = true; + RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; + RestrictNamespaces = true; + RestrictRealtime = true; + DevicePolicy = "closed"; + ProtectSystem = "full"; + ProtectControlGroups = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + LockPersonality = true; + }; + }; + }; +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index e597a26f31bb..7937e1e15b20 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -306,6 +306,7 @@ in { gonic = handleTest ./gonic.nix {}; google-oslogin = handleTest ./google-oslogin {}; gotify-server = handleTest ./gotify-server.nix {}; + gotosocial = runTest ./web-apps/gotosocial.nix; grafana = handleTest ./grafana {}; grafana-agent = handleTest ./grafana-agent.nix {}; graphite = handleTest ./graphite.nix {}; diff --git a/nixos/tests/web-apps/gotosocial.nix b/nixos/tests/web-apps/gotosocial.nix new file mode 100644 index 000000000000..6d279ab63a79 --- /dev/null +++ b/nixos/tests/web-apps/gotosocial.nix @@ -0,0 +1,28 @@ +{ lib, ... }: +{ + name = "gotosocial"; + meta.maintainers = with lib.maintainers; [ misuzu ]; + + nodes.machine = { pkgs, ... }: { + environment.systemPackages = [ pkgs.jq ]; + services.gotosocial = { + enable = true; + setupPostgresqlDB = true; + settings = { + host = "localhost:8081"; + port = 8081; + }; + }; + }; + + testScript = '' + machine.wait_for_unit("gotosocial.service") + machine.wait_for_unit("postgresql.service") + machine.wait_for_open_port(8081) + + # check user registration via cli + machine.succeed("curl -sS -f http://localhost:8081/nodeinfo/2.0 | jq '.usage.users.total' | grep -q '^0$'") + machine.succeed("gotosocial-admin account create --username nickname --email email@example.com --password kurtz575VPeBgjVm") + machine.succeed("curl -sS -f http://localhost:8081/nodeinfo/2.0 | jq '.usage.users.total' | grep -q '^1$'") + ''; +} diff --git a/pkgs/servers/gotosocial/default.nix b/pkgs/servers/gotosocial/default.nix index 057fbbfb08ea..f0c104f619ab 100644 --- a/pkgs/servers/gotosocial/default.nix +++ b/pkgs/servers/gotosocial/default.nix @@ -3,6 +3,7 @@ , fetchurl , fetchFromGitHub , buildGoModule +, nixosTests }: let owner = "superseriousbusiness"; @@ -44,6 +45,8 @@ buildGoModule rec { # tests are working only on x86_64-linux doCheck = stdenv.isLinux && stdenv.isx86_64; + passthru.tests.gotosocial = nixosTests.gotosocial; + meta = with lib; { homepage = "https://gotosocial.org"; changelog = "https://github.com/superseriousbusiness/gotosocial/releases/tag/v${version}";