1{ config, lib, pkgs, ... }:
2let
3 cfg = config.services.gotosocial;
4 settingsFormat = pkgs.formats.yaml { };
5 configFile = settingsFormat.generate "config.yml" cfg.settings;
6 defaultSettings = {
7 application-name = "gotosocial";
8
9 protocol = "https";
10
11 bind-address = "127.0.0.1";
12 port = 8080;
13
14 storage-local-base-path = "/var/lib/gotosocial/storage";
15
16 db-type = "sqlite";
17 db-address = "/var/lib/gotosocial/database.sqlite";
18 };
19 gotosocial-admin = pkgs.writeShellScriptBin "gotosocial-admin" ''
20 exec systemd-run \
21 -u gotosocial-admin.service \
22 -p Group=gotosocial \
23 -p User=gotosocial \
24 -q -t -G --wait --service-type=exec \
25 ${cfg.package}/bin/gotosocial --config-path ${configFile} admin "$@"
26 '';
27in
28{
29 meta.doc = ./gotosocial.md;
30 meta.maintainers = with lib.maintainers; [ blakesmith ];
31
32 options.services.gotosocial = {
33 enable = lib.mkEnableOption "ActivityPub social network server";
34
35 package = lib.mkPackageOption pkgs "gotosocial" { };
36
37 openFirewall = lib.mkOption {
38 type = lib.types.bool;
39 default = false;
40 description = ''
41 Open the configured port in the firewall.
42 Using a reverse proxy instead is highly recommended.
43 '';
44 };
45
46 setupPostgresqlDB = lib.mkOption {
47 type = lib.types.bool;
48 default = false;
49 description = ''
50 Whether to setup a local postgres database and populate the
51 `db-type` fields in `services.gotosocial.settings`.
52 '';
53 };
54
55 settings = lib.mkOption {
56 type = settingsFormat.type;
57 default = defaultSettings;
58 example = {
59 application-name = "My GoToSocial";
60 host = "gotosocial.example.com";
61 };
62 description = ''
63 Contents of the GoToSocial YAML config.
64
65 Please refer to the
66 [documentation](https://docs.gotosocial.org/en/latest/configuration/)
67 and
68 [example config](https://github.com/superseriousbusiness/gotosocial/blob/main/example/config.yaml).
69
70 Please note that the `host` option cannot be changed later so it is important to configure this correctly before you start GoToSocial.
71 '';
72 };
73
74 environmentFile = lib.mkOption {
75 type = lib.types.nullOr lib.types.path;
76 description = ''
77 File path containing environment variables for configuring the GoToSocial service
78 in the format of an EnvironmentFile as described by systemd.exec(5).
79
80 This option could be used to pass sensitive configuration to the GoToSocial daemon.
81
82 Please refer to the Environment Variables section in the
83 [documentation](https://docs.gotosocial.org/en/latest/configuration/).
84 '';
85 default = null;
86 example = "/root/nixos/secrets/gotosocial.env";
87 };
88
89 };
90
91 config = lib.mkIf cfg.enable {
92 assertions = [
93 {
94 assertion = cfg.settings.host or null != null;
95 message = ''
96 You have to define a hostname for GoToSocial (`services.gotosocial.settings.host`), it cannot be changed later without starting over!
97 '';
98 }
99 ];
100
101 services.gotosocial.settings = (lib.mapAttrs (name: lib.mkDefault) (
102 defaultSettings // {
103 web-asset-base-dir = "${cfg.package}/share/gotosocial/web/assets/";
104 web-template-base-dir = "${cfg.package}/share/gotosocial/web/template/";
105 }
106 )) // (lib.optionalAttrs cfg.setupPostgresqlDB {
107 db-type = "postgres";
108 db-address = "/run/postgresql";
109 db-database = "gotosocial";
110 db-user = "gotosocial";
111 });
112
113 environment.systemPackages = [ gotosocial-admin ];
114
115 users.groups.gotosocial = { };
116 users.users.gotosocial = {
117 group = "gotosocial";
118 isSystemUser = true;
119 };
120
121 networking.firewall = lib.mkIf cfg.openFirewall {
122 allowedTCPPorts = [ cfg.settings.port ];
123 };
124
125 services.postgresql = lib.mkIf cfg.setupPostgresqlDB {
126 enable = true;
127 ensureDatabases = [ "gotosocial" ];
128 ensureUsers = [
129 {
130 name = "gotosocial";
131 ensureDBOwnership = true;
132 }
133 ];
134 };
135
136 systemd.services.gotosocial = {
137 description = "ActivityPub social network server";
138 wantedBy = [ "multi-user.target" ];
139 after = [ "network.target" ]
140 ++ lib.optional cfg.setupPostgresqlDB "postgresql.service";
141 requires = lib.optional cfg.setupPostgresqlDB "postgresql.service";
142 restartTriggers = [ configFile ];
143
144 serviceConfig = {
145 EnvironmentFile = lib.mkIf (cfg.environmentFile != null) cfg.environmentFile;
146 ExecStart = "${cfg.package}/bin/gotosocial --config-path ${configFile} server start";
147 Restart = "on-failure";
148 Group = "gotosocial";
149 User = "gotosocial";
150 StateDirectory = "gotosocial";
151 WorkingDirectory = "/var/lib/gotosocial";
152
153 # Security options:
154 # Based on https://github.com/superseriousbusiness/gotosocial/blob/v0.8.1/example/gotosocial.service
155 AmbientCapabilities = lib.optional (cfg.settings.port < 1024) "CAP_NET_BIND_SERVICE";
156 NoNewPrivileges = true;
157 PrivateTmp = true;
158 PrivateDevices = true;
159 RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
160 RestrictNamespaces = true;
161 RestrictRealtime = true;
162 DevicePolicy = "closed";
163 ProtectSystem = "full";
164 ProtectControlGroups = true;
165 ProtectKernelModules = true;
166 ProtectKernelTunables = true;
167 LockPersonality = true;
168 };
169 };
170 };
171}