commit 132c5f25ba280389d9eb86e8924e145ca0fdbd99
parent e846889b707d2e03b340de40f519c96fbf21e750
Author: Katja (zaphyra) <git@ctu.cx>
Date: Sat, 24 May 2025 17:59:39 +0200
parent e846889b707d2e03b340de40f519c96fbf21e750
Author: Katja (zaphyra) <git@ctu.cx>
Date: Sat, 24 May 2025 17:59:39 +0200
config/nixos/modules/services: add `gotosocial`
1 file changed, 186 insertions(+), 0 deletions(-)
A
|
186
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/config/nixos/modules/services/gotosocial.nix b/config/nixos/modules/services/gotosocial.nix @@ -0,0 +1,186 @@ +{ + povSelf, + config, + lib, + pkgs, + ... +}: +let + inherit (lib) types; + cfg = lib.getAttrFromPath povSelf config; + settingsFormat = pkgs.formats.json { }; + +in +{ + + options = { + enable = { + type = types.bool; + default = false; + }; + + package = { + type = types.package; + default = pkgs.gotosocial; + }; + + user = { + type = types.str; + default = "gotosocial"; + }; + + group = { + type = types.str; + default = "gotosocial"; + }; + + stateDir = { + type = types.str; + default = "/var/lib/gotosocial"; + readOnly = true; + }; + + environmentFile = { + type = with types; nullOr path; + default = null; + }; + + settings = { + default = { }; + description = '' + Configuration for GoToSocial, see + <link xlink:href="https://docs.gotosocial.org/en/latest/"> + for supported values. + ''; + type = types.submodule { + freeformType = settingsFormat.type; + options = { + host = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + description = '' + Hostname that this server will be reachable at. Defaults to localhost for local testing, + but you should *definitely* change this when running for real, or your server won't work at all. + DO NOT change this after your server has already run once, or you will break things! + ''; + }; + port = lib.mkOption { + type = lib.types.port; + default = 8080; + description = '' + Int. Listen port for the GoToSocial webserver + API. If you're running behind a reverse proxy and/or in a docker, + container, just set this to whatever you like (or leave the default), and make sure it's forwarded properly. + If you are running with built-in letsencrypt enabled, and running GoToSocial directly on a host machine, you will + probably want to set this to 443 (standard https port), unless you have other services already using that port. + This *MUST NOT* be the same as the letsencrypt port specified below, unless letsencrypt is turned off. + ''; + }; + }; + }; + }; + }; + + config = lib.mkIf cfg.enable ( + let + configFile = settingsFormat.generate "gotosocial-config.yaml" cfg.settings; + in + { + assertions = [ + { + assertion = cfg.settings.host != null; + message = "You have to define a hostname for GoToSocial, it cannot be changed later without starting over!"; + } + ]; + + modules.services.gotosocial.settings = { + # Defaults + user = lib.mkDefault cfg.user; + group = lib.mkDefault cfg.group; + + storage-local-base-path = lib.mkDefault cfg.stateDir; + + web-template-base-dir = lib.mkDefault "${cfg.package}/share/web/template/"; + web-asset-base-dir = lib.mkDefault "${cfg.package}/share/web/assets/"; + }; + + users = { + users."${cfg.user}" = { + home = cfg.stateDir; + group = cfg.group; + isSystemUser = true; + }; + groups."${cfg.group}" = { }; + }; + + environment.etc."gotosocial.yaml".source = configFile; + + environment.systemPackages = [ + (pkgs.writeShellScriptBin "gotosocial" '' + exec ${cfg.package}/bin/gotosocial --config-path ${configFile} "$@" + '') + ]; + + systemd.services = { + gotosocial = { + description = "GoToSocial ActivityPub Server"; + wants = [ "network-online.target" ]; + after = [ "network-online.target" ]; + wantedBy = [ "multi-user.target" ]; + environment = { + GTS_WAZERO_COMPILATION_CACHE = "${cfg.stateDir}/.cache"; + }; + + serviceConfig = { + User = cfg.user; + Group = cfg.group; + + Type = "exec"; + WorkingDirectory = "~"; + StateDirectory = lib.mkIf ( + cfg.settings.storage-local-base-path != "/var/lib/gotosocial" + ) "gotosocial"; + ReadOnlyPaths = [ cfg.package ]; + ReadWritePaths = [ cfg.settings.storage-local-base-path ]; + StateDirectoryMode = "750"; + + Restart = "always"; + RestartSec = 3; + + EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile; + ExecStart = "${cfg.package}/bin/gotosocial --config-path ${configFile} server start"; + + NoNewPrivileges = true; + PrivateTmp = true; + PrivateDevices = false; + + RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6"; + RestrictNamespaces = true; + RestrictRealtime = true; + + ProtectSystem = "full"; + ProtectControlGroups = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + + DevicePolicy = "closed"; + LockPersonality = true; + SystemCallFilter = "~@clock @debug @module @mount @obsolete @reboot @setuid @swap"; + + CapabilityBoundingSet = [ + "~CAP_RAWIO CAP_MKNOD" + "~CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE" + "~CAP_SYS_BOOT CAP_SYS_TIME CAP_SYS_MODULE CAP_SYS_PACCT" + "~CAP_LEASE CAP_LINUX_IMMUTABLE CAP_IPC_LOCK" + "~CAP_BLOCK_SUSPEND CAP_WAKE_ALARM" + "~CAP_SYS_TTY_CONFIG" + "~CAP_MAC_ADMIN CAP_MAC_OVERRIDE" + "~CAP_NET_ADMIN CAP_NET_BROADCAST CAP_NET_RAW" + "~CAP_SYS_ADMIN CAP_SYS_PTRACE CAP_SYSLOG" + ]; + }; + }; + }; + } + ); + +}