aboutsummaryrefslogtreecommitdiff
path: root/modules/webapps
diff options
context:
space:
mode:
Diffstat (limited to 'modules/webapps')
-rw-r--r--modules/webapps/diaspora.nix173
-rw-r--r--modules/webapps/etherpad-lite.nix162
-rw-r--r--modules/webapps/mastodon.nix265
-rw-r--r--modules/webapps/mediagoblin.nix231
-rw-r--r--modules/webapps/webstats/default.nix80
-rw-r--r--modules/webapps/webstats/goaccess.conf100
6 files changed, 0 insertions, 1011 deletions
diff --git a/modules/webapps/diaspora.nix b/modules/webapps/diaspora.nix
deleted file mode 100644
index d9e9989..0000000
--- a/modules/webapps/diaspora.nix
+++ /dev/null
@@ -1,173 +0,0 @@
1{ lib, pkgs, config, ... }:
2let
3 name = "diaspora";
4 cfg = config.services.diaspora;
5
6 uid = config.ids.uids.diaspora;
7 gid = config.ids.gids.diaspora;
8in
9{
10 options.services.diaspora = {
11 enable = lib.mkEnableOption "Enable Diaspora’s service";
12 user = lib.mkOption {
13 type = lib.types.str;
14 default = name;
15 description = "User account under which Diaspora runs";
16 };
17 group = lib.mkOption {
18 type = lib.types.str;
19 default = name;
20 description = "Group under which Diaspora runs";
21 };
22 adminEmail = lib.mkOption {
23 type = lib.types.str;
24 example = "admin@example.com";
25 description = "Admin e-mail for Diaspora";
26 };
27 dataDir = lib.mkOption {
28 type = lib.types.path;
29 default = "/var/lib/${name}";
30 description = ''
31 The directory where Diaspora stores its data.
32 '';
33 };
34 socketsDir = lib.mkOption {
35 type = lib.types.path;
36 default = "/run/${name}";
37 description = ''
38 The directory where Diaspora puts runtime files and sockets.
39 '';
40 };
41 configDir = lib.mkOption {
42 type = lib.types.path;
43 description = ''
44 The configuration path for Diaspora.
45 '';
46 };
47 package = lib.mkOption {
48 type = lib.types.package;
49 default = pkgs.webapps.diaspora;
50 description = ''
51 Diaspora package to use.
52 '';
53 };
54 # Output variables
55 systemdStateDirectory = lib.mkOption {
56 type = lib.types.str;
57 # Use ReadWritePaths= instead if varDir is outside of /var/lib
58 default = assert lib.strings.hasPrefix "/var/lib/" cfg.dataDir;
59 lib.strings.removePrefix "/var/lib/" cfg.dataDir;
60 description = ''
61 Adjusted Diaspora data directory for systemd
62 '';
63 readOnly = true;
64 };
65 systemdRuntimeDirectory = lib.mkOption {
66 type = lib.types.str;
67 # Use ReadWritePaths= instead if socketsDir is outside of /run
68 default = assert lib.strings.hasPrefix "/run/" cfg.socketsDir;
69 lib.strings.removePrefix "/run/" cfg.socketsDir;
70 description = ''
71 Adjusted Diaspora sockets directory for systemd
72 '';
73 readOnly = true;
74 };
75 workdir = lib.mkOption {
76 type = lib.types.package;
77 default = cfg.package.override {
78 varDir = cfg.dataDir;
79 podmin_email = cfg.adminEmail;
80 config_dir = cfg.configDir;
81 };
82 description = ''
83 Adjusted diaspora package with overriden values
84 '';
85 readOnly = true;
86 };
87 sockets = lib.mkOption {
88 type = lib.types.attrsOf lib.types.path;
89 default = {
90 rails = "${cfg.socketsDir}/diaspora.sock";
91 eye = "${cfg.socketsDir}/eye.sock";
92 };
93 readOnly = true;
94 description = ''
95 Diaspora sockets
96 '';
97 };
98 pids = lib.mkOption {
99 type = lib.types.attrsOf lib.types.path;
100 default = {
101 eye = "${cfg.socketsDir}/eye.pid";
102 };
103 readOnly = true;
104 description = ''
105 Diaspora pids
106 '';
107 };
108 };
109
110 config = lib.mkIf cfg.enable {
111 users.users = lib.optionalAttrs (cfg.user == name) {
112 "${name}" = {
113 inherit uid;
114 group = cfg.group;
115 description = "Diaspora user";
116 home = cfg.dataDir;
117 packages = [ cfg.workdir.gems pkgs.nodejs cfg.workdir.gems.ruby ];
118 useDefaultShell = true;
119 };
120 };
121 users.groups = lib.optionalAttrs (cfg.group == name) {
122 "${name}" = {
123 inherit gid;
124 };
125 };
126
127 systemd.services.diaspora = {
128 description = "Diaspora";
129 wantedBy = [ "multi-user.target" ];
130 after = [
131 "network.target" "redis.service" "postgresql.service"
132 ];
133 wants = [
134 "redis.service" "postgresql.service"
135 ];
136
137 environment.RAILS_ENV = "production";
138 environment.BUNDLE_PATH = "${cfg.workdir.gems}/${cfg.workdir.gems.ruby.gemPath}";
139 environment.BUNDLE_GEMFILE = "${cfg.workdir.gems.confFiles}/Gemfile";
140 environment.EYE_SOCK = cfg.sockets.eye;
141 environment.EYE_PID = cfg.pids.eye;
142
143 path = [ cfg.workdir.gems pkgs.nodejs cfg.workdir.gems.ruby pkgs.curl pkgs.which pkgs.gawk ];
144
145 preStart = ''
146 install -m 0755 -d ${cfg.dataDir}/uploads ${cfg.dataDir}/tmp ${cfg.dataDir}/log
147 install -m 0700 -d ${cfg.dataDir}/tmp/pids
148 if [ ! -f ${cfg.dataDir}/schedule.yml ]; then
149 echo "{}" > ${cfg.dataDir}/schedule.yml
150 fi
151 ./bin/bundle exec rails db:migrate
152 '';
153
154 script = ''
155 exec ${cfg.workdir}/script/server
156 '';
157
158 serviceConfig = {
159 User = cfg.user;
160 PrivateTmp = true;
161 Restart = "always";
162 Type = "simple";
163 WorkingDirectory = cfg.workdir;
164 StateDirectory = cfg.systemdStateDirectory;
165 RuntimeDirectory = cfg.systemdRuntimeDirectory;
166 StandardInput = "null";
167 KillMode = "control-group";
168 };
169
170 unitConfig.RequiresMountsFor = cfg.dataDir;
171 };
172 };
173}
diff --git a/modules/webapps/etherpad-lite.nix b/modules/webapps/etherpad-lite.nix
deleted file mode 100644
index 2e09952..0000000
--- a/modules/webapps/etherpad-lite.nix
+++ /dev/null
@@ -1,162 +0,0 @@
1{ lib, pkgs, config, ... }:
2let
3 name = "etherpad-lite";
4 cfg = config.services.etherpad-lite;
5
6 uid = config.ids.uids.etherpad-lite;
7 gid = config.ids.gids.etherpad-lite;
8in
9{
10 options.services.etherpad-lite = {
11 enable = lib.mkEnableOption "Enable Etherpad lite’s service";
12 user = lib.mkOption {
13 type = lib.types.str;
14 default = name;
15 description = "User account under which Etherpad lite runs";
16 };
17 group = lib.mkOption {
18 type = lib.types.str;
19 default = name;
20 description = "Group under which Etherpad lite runs";
21 };
22 dataDir = lib.mkOption {
23 type = lib.types.path;
24 default = "/var/lib/${name}";
25 description = ''
26 The directory where Etherpad lite stores its data.
27 '';
28 };
29 socketsDir = lib.mkOption {
30 type = lib.types.path;
31 default = "/run/${name}";
32 description = ''
33 The directory where Etherpad lite stores its sockets.
34 '';
35 };
36 configFile = lib.mkOption {
37 type = lib.types.path;
38 description = ''
39 The config file path for Etherpad lite.
40 '';
41 };
42 sessionKeyFile = lib.mkOption {
43 type = lib.types.path;
44 description = ''
45 The Session key file path for Etherpad lite.
46 '';
47 };
48 apiKeyFile = lib.mkOption {
49 type = lib.types.path;
50 description = ''
51 The API key file path for Etherpad lite.
52 '';
53 };
54 package = lib.mkOption {
55 type = lib.types.package;
56 default = pkgs.webapps.etherpad-lite;
57 description = ''
58 Etherpad lite package to use.
59 '';
60 example = lib.literalExample ''
61 pkgs.webapps.etherpad-lite.withModules (p: [ p.ep_align ]);
62 '';
63 };
64 modules = lib.mkOption {
65 type = lib.types.listOf lib.types.package;
66 default = [];
67 description = ''
68 Etherpad lite modules to use.
69 DEPRECATED: use package directly
70 '';
71 };
72 # Output variables
73 workdir = lib.mkOption {
74 type = lib.types.package;
75 default = cfg.package.withModules (_: cfg.modules);
76 description = ''
77 Adjusted Etherpad lite package with plugins
78 '';
79 readOnly = true;
80 };
81 systemdStateDirectory = lib.mkOption {
82 type = lib.types.str;
83 # Use ReadWritePaths= instead if varDir is outside of /var/lib
84 default = assert lib.strings.hasPrefix "/var/lib/" cfg.dataDir;
85 lib.strings.removePrefix "/var/lib/" cfg.dataDir;
86 description = ''
87 Adjusted Etherpad lite data directory for systemd
88 '';
89 readOnly = true;
90 };
91 systemdRuntimeDirectory = lib.mkOption {
92 type = lib.types.str;
93 # Use ReadWritePaths= instead if socketsDir is outside of /run
94 default = assert lib.strings.hasPrefix "/run/" cfg.socketsDir;
95 lib.strings.removePrefix "/run/" cfg.socketsDir;
96 description = ''
97 Adjusted Etherpad lite sockets directory for systemd
98 '';
99 readOnly = true;
100 };
101 sockets = lib.mkOption {
102 type = lib.types.attrsOf lib.types.path;
103 default = {
104 node = "${cfg.socketsDir}/etherpad-lite.sock";
105 };
106 readOnly = true;
107 description = ''
108 Etherpad lite sockets
109 '';
110 };
111 };
112
113 config = lib.mkIf cfg.enable {
114 systemd.services.etherpad-lite = {
115 description = "Etherpad-lite";
116 wantedBy = [ "multi-user.target" ];
117 after = [ "network.target" "postgresql.service" ];
118 wants = [ "postgresql.service" ];
119
120 environment.NODE_ENV = "production";
121 environment.HOME = cfg.workdir;
122
123 path = [ pkgs.nodejs ];
124
125 script = ''
126 exec ${pkgs.nodejs}/bin/node ${cfg.workdir}/src/node/server.js \
127 --sessionkey ${cfg.sessionKeyFile} \
128 --apikey ${cfg.apiKeyFile} \
129 --settings ${cfg.configFile}
130 '';
131
132 postStart = ''
133 while [ ! -S ${cfg.sockets.node} ]; do
134 sleep 0.5
135 done
136 chmod a+w ${cfg.sockets.node}
137 '';
138 serviceConfig = {
139 DynamicUser = true;
140 User = cfg.user;
141 Group = cfg.group;
142 WorkingDirectory = cfg.workdir;
143 PrivateTmp = true;
144 NoNewPrivileges = true;
145 PrivateDevices = true;
146 ProtectHome = true;
147 ProtectControlGroups = true;
148 ProtectKernelModules = true;
149 Restart = "always";
150 Type = "simple";
151 TimeoutSec = 60;
152 RuntimeDirectory = cfg.systemdRuntimeDirectory;
153 StateDirectory= cfg.systemdStateDirectory;
154 ExecStartPre = [
155 "+${pkgs.coreutils}/bin/install -d -m 0755 -o ${cfg.user} -g ${cfg.group} ${cfg.dataDir}/ep_initialized"
156 "+${pkgs.coreutils}/bin/chown -R ${cfg.user}:${cfg.group} ${cfg.dataDir} ${cfg.configFile} ${cfg.sessionKeyFile} ${cfg.apiKeyFile}"
157 ];
158 };
159 };
160
161 };
162}
diff --git a/modules/webapps/mastodon.nix b/modules/webapps/mastodon.nix
deleted file mode 100644
index df2dbb2..0000000
--- a/modules/webapps/mastodon.nix
+++ /dev/null
@@ -1,265 +0,0 @@
1{ lib, pkgs, config, ... }:
2let
3 name = "mastodon";
4 cfg = config.services.mastodon;
5
6 uid = config.ids.uids.mastodon;
7 gid = config.ids.gids.mastodon;
8in
9{
10 options.services.mastodon = {
11 enable = lib.mkEnableOption "Enable Mastodon’s service";
12 user = lib.mkOption {
13 type = lib.types.str;
14 default = name;
15 description = "User account under which Mastodon runs";
16 };
17 group = lib.mkOption {
18 type = lib.types.str;
19 default = name;
20 description = "Group under which Mastodon runs";
21 };
22 dataDir = lib.mkOption {
23 type = lib.types.path;
24 default = "/var/lib/${name}";
25 description = ''
26 The directory where Mastodon stores its data.
27 '';
28 };
29 socketsPrefix = lib.mkOption {
30 type = lib.types.str;
31 default = "live";
32 description = ''
33 The prefix to use for Mastodon sockets.
34 '';
35 };
36 socketsDir = lib.mkOption {
37 type = lib.types.path;
38 default = "/run/${name}";
39 description = ''
40 The directory where Mastodon puts runtime files and sockets.
41 '';
42 };
43 configFile = lib.mkOption {
44 type = lib.types.path;
45 description = ''
46 The configuration file path for Mastodon.
47 '';
48 };
49 package = lib.mkOption {
50 type = lib.types.package;
51 default = pkgs.webapps.mastodon;
52 description = ''
53 Mastodon package to use.
54 '';
55 };
56 # Output variables
57 workdir = lib.mkOption {
58 type = lib.types.package;
59 default = cfg.package.override { varDir = cfg.dataDir; };
60 description = ''
61 Adjusted mastodon package with overriden varDir
62 '';
63 readOnly = true;
64 };
65 systemdStateDirectory = lib.mkOption {
66 type = lib.types.str;
67 # Use ReadWritePaths= instead if varDir is outside of /var/lib
68 default = assert lib.strings.hasPrefix "/var/lib/" cfg.dataDir;
69 lib.strings.removePrefix "/var/lib/" cfg.dataDir;
70 description = ''
71 Adjusted Mastodon data directory for systemd
72 '';
73 readOnly = true;
74 };
75 systemdRuntimeDirectory = lib.mkOption {
76 type = lib.types.str;
77 # Use ReadWritePaths= instead if socketsDir is outside of /run
78 default = assert lib.strings.hasPrefix "/run/" cfg.socketsDir;
79 lib.strings.removePrefix "/run/" cfg.socketsDir;
80 description = ''
81 Adjusted Mastodon sockets directory for systemd
82 '';
83 readOnly = true;
84 };
85 sockets = lib.mkOption {
86 type = lib.types.attrsOf lib.types.path;
87 default = {
88 node = "${cfg.socketsDir}/${cfg.socketsPrefix}_node.sock";
89 rails = "${cfg.socketsDir}/${cfg.socketsPrefix}_puma.sock";
90 };
91 readOnly = true;
92 description = ''
93 Mastodon sockets
94 '';
95 };
96 };
97
98 config = lib.mkIf cfg.enable {
99 users.users = lib.optionalAttrs (cfg.user == name) {
100 "${name}" = {
101 inherit uid;
102 group = cfg.group;
103 description = "Mastodon user";
104 home = cfg.dataDir;
105 useDefaultShell = true;
106 };
107 };
108 users.groups = lib.optionalAttrs (cfg.group == name) {
109 "${name}" = {
110 inherit gid;
111 };
112 };
113
114 systemd.slices.mastodon = {
115 description = "Mastodon slice";
116 };
117
118 systemd.services.mastodon-streaming = {
119 description = "Mastodon Streaming";
120 wantedBy = [ "multi-user.target" ];
121 after = [ "network.target" "mastodon-web.service" ];
122
123 environment.NODE_ENV = "production";
124 environment.SOCKET = cfg.sockets.node;
125
126 path = [ pkgs.nodejs pkgs.bashInteractive ];
127
128 script = ''
129 exec npm run start
130 '';
131
132 postStart = ''
133 while [ ! -S $SOCKET ]; do
134 sleep 0.5
135 done
136 chmod a+w $SOCKET
137 '';
138
139 postStop = ''
140 rm $SOCKET
141 '';
142
143 serviceConfig = {
144 Slice = "mastodon.slice";
145 User = cfg.user;
146 EnvironmentFile = cfg.configFile;
147 PrivateTmp = true;
148 Restart = "always";
149 TimeoutSec = 15;
150 Type = "simple";
151 WorkingDirectory = cfg.workdir;
152 StateDirectory = cfg.systemdStateDirectory;
153 RuntimeDirectory = cfg.systemdRuntimeDirectory;
154 RuntimeDirectoryPreserve = "yes";
155 };
156
157 unitConfig.RequiresMountsFor = cfg.dataDir;
158 };
159
160 systemd.services.mastodon-web = {
161 description = "Mastodon Web app";
162 wantedBy = [ "multi-user.target" ];
163 after = [ "network.target" ];
164
165 environment.RAILS_ENV = "production";
166 environment.BUNDLE_PATH = "${cfg.workdir.gems}/${cfg.workdir.gems.ruby.gemPath}";
167 environment.BUNDLE_GEMFILE = "${cfg.workdir.gems.confFiles}/Gemfile";
168 environment.SOCKET = cfg.sockets.rails;
169
170 path = [ cfg.workdir.gems cfg.workdir.gems.ruby pkgs.file pkgs.imagemagick ];
171
172 preStart = ''
173 install -m 0755 -d ${cfg.dataDir}/tmp/cache
174 ./bin/bundle exec rails db:migrate
175 '';
176
177 script = ''
178 exec ./bin/bundle exec puma -C config/puma.rb
179 '';
180
181 postStart = ''
182 exec ./bin/tootctl cache clear
183 '';
184 serviceConfig = {
185 Slice = "mastodon.slice";
186 User = cfg.user;
187 EnvironmentFile = cfg.configFile;
188 PrivateTmp = true;
189 Restart = "always";
190 TimeoutSec = 60;
191 Type = "simple";
192 WorkingDirectory = cfg.workdir;
193 StateDirectory = cfg.systemdStateDirectory;
194 RuntimeDirectory = cfg.systemdRuntimeDirectory;
195 RuntimeDirectoryPreserve = "yes";
196 };
197
198 unitConfig.RequiresMountsFor = cfg.dataDir;
199 };
200
201 systemd.services.mastodon-cleanup = {
202 description = "Cleanup mastodon";
203 startAt = "daily";
204 restartIfChanged = false;
205
206 environment.RAILS_ENV = "production";
207 environment.BUNDLE_PATH = "${cfg.workdir.gems}/${cfg.workdir.gems.ruby.gemPath}";
208 environment.BUNDLE_GEMFILE = "${cfg.workdir.gems.confFiles}/Gemfile";
209 environment.SOCKET = cfg.sockets.rails;
210
211 path = [ cfg.workdir.gems cfg.workdir.gems.ruby pkgs.file ];
212
213 script = ''
214 exec ./bin/tootctl media remove --days 30
215 '';
216
217 serviceConfig = {
218 User = cfg.user;
219 EnvironmentFile = cfg.configFile;
220 PrivateTmp = true;
221 Type = "oneshot";
222 WorkingDirectory = cfg.workdir;
223 StateDirectory = cfg.systemdStateDirectory;
224 RuntimeDirectory = cfg.systemdRuntimeDirectory;
225 RuntimeDirectoryPreserve = "yes";
226 };
227
228 unitConfig.RequiresMountsFor = cfg.dataDir;
229 };
230
231 systemd.services.mastodon-sidekiq = {
232 description = "Mastodon Sidekiq";
233 wantedBy = [ "multi-user.target" ];
234 after = [ "network.target" "mastodon-web.service" ];
235
236 environment.RAILS_ENV="production";
237 environment.BUNDLE_PATH = "${cfg.workdir.gems}/${cfg.workdir.gems.ruby.gemPath}";
238 environment.BUNDLE_GEMFILE = "${cfg.workdir.gems.confFiles}/Gemfile";
239 environment.DB_POOL="5";
240
241 path = [ cfg.workdir.gems cfg.workdir.gems.ruby pkgs.imagemagick pkgs.ffmpeg pkgs.file ];
242
243 script = ''
244 exec ./bin/bundle exec sidekiq -c 5 -q default -q mailers -q pull -q push
245 '';
246
247 serviceConfig = {
248 Slice = "mastodon.slice";
249 User = cfg.user;
250 EnvironmentFile = cfg.configFile;
251 PrivateTmp = true;
252 Restart = "always";
253 TimeoutSec = 15;
254 Type = "simple";
255 WorkingDirectory = cfg.workdir;
256 StateDirectory = cfg.systemdStateDirectory;
257 RuntimeDirectory = cfg.systemdRuntimeDirectory;
258 RuntimeDirectoryPreserve = "yes";
259 };
260
261 unitConfig.RequiresMountsFor = cfg.dataDir;
262 };
263
264 };
265}
diff --git a/modules/webapps/mediagoblin.nix b/modules/webapps/mediagoblin.nix
deleted file mode 100644
index 3fe5e38..0000000
--- a/modules/webapps/mediagoblin.nix
+++ /dev/null
@@ -1,231 +0,0 @@
1{ lib, pkgs, config, ... }:
2let
3 name = "mediagoblin";
4 cfg = config.services.mediagoblin;
5
6 uid = config.ids.uids.mediagoblin;
7 gid = config.ids.gids.mediagoblin;
8
9 paste_local = pkgs.writeText "paste_local.ini" ''
10 [DEFAULT]
11 debug = false
12
13 [pipeline:main]
14 pipeline = mediagoblin
15
16 [app:mediagoblin]
17 use = egg:mediagoblin#app
18 config = ${cfg.configFile} ${cfg.package}/mediagoblin.ini
19 /mgoblin_static = ${cfg.package}/mediagoblin/static
20
21 [loggers]
22 keys = root
23
24 [handlers]
25 keys = console
26
27 [formatters]
28 keys = generic
29
30 [logger_root]
31 level = INFO
32 handlers = console
33
34 [handler_console]
35 class = StreamHandler
36 args = (sys.stderr,)
37 level = NOTSET
38 formatter = generic
39
40 [formatter_generic]
41 format = %(levelname)-7.7s [%(name)s] %(message)s
42
43 [filter:errors]
44 use = egg:mediagoblin#errors
45 debug = false
46
47 [server:main]
48 use = egg:waitress#main
49 unix_socket = ${cfg.sockets.paster}
50 unix_socket_perms = 777
51 url_scheme = https
52 '';
53in
54{
55 options.services.mediagoblin = {
56 enable = lib.mkEnableOption "Enable Mediagoblin’s service";
57 user = lib.mkOption {
58 type = lib.types.str;
59 default = name;
60 description = "User account under which Mediagoblin runs";
61 };
62 group = lib.mkOption {
63 type = lib.types.str;
64 default = name;
65 description = "Group under which Mediagoblin runs";
66 };
67 dataDir = lib.mkOption {
68 type = lib.types.path;
69 default = "/var/lib/${name}";
70 description = ''
71 The directory where Mediagoblin stores its data.
72 '';
73 };
74 socketsDir = lib.mkOption {
75 type = lib.types.path;
76 default = "/run/${name}";
77 description = ''
78 The directory where Mediagoblin puts runtime files and sockets.
79 '';
80 };
81 configFile = lib.mkOption {
82 type = lib.types.path;
83 description = ''
84 The configuration file path for Mediagoblin.
85 '';
86 };
87 package = lib.mkOption {
88 type = lib.types.package;
89 default = pkgs.webapps.mediagoblin;
90 example = lib.literalExample ''
91 pkgs.webapps.mediagoblin.withPlugins (p: [p.basicsearch])
92 '';
93 description = ''
94 Mediagoblin package to use.
95 '';
96 };
97 systemdStateDirectory = lib.mkOption {
98 type = lib.types.str;
99 # Use ReadWritePaths= instead if varDir is outside of /var/lib
100 default = assert lib.strings.hasPrefix "/var/lib/" cfg.dataDir;
101 lib.strings.removePrefix "/var/lib/" cfg.dataDir;
102 description = ''
103 Adjusted Mediagoblin data directory for systemd
104 '';
105 readOnly = true;
106 };
107 systemdRuntimeDirectory = lib.mkOption {
108 type = lib.types.str;
109 # Use ReadWritePaths= instead if socketsDir is outside of /run
110 default = assert lib.strings.hasPrefix "/run/" cfg.socketsDir;
111 lib.strings.removePrefix "/run/" cfg.socketsDir;
112 description = ''
113 Adjusted Mediagoblin sockets directory for systemd
114 '';
115 readOnly = true;
116 };
117 sockets = lib.mkOption {
118 type = lib.types.attrsOf lib.types.path;
119 default = {
120 paster = "${cfg.socketsDir}/mediagoblin.sock";
121 };
122 readOnly = true;
123 description = ''
124 Mediagoblin sockets
125 '';
126 };
127 pids = lib.mkOption {
128 type = lib.types.attrsOf lib.types.path;
129 default = {
130 paster = "${cfg.socketsDir}/mediagoblin.pid";
131 celery = "${cfg.socketsDir}/mediagoblin-celeryd.pid";
132 };
133 readOnly = true;
134 description = ''
135 Mediagoblin pid files
136 '';
137 };
138 };
139
140 config = lib.mkIf cfg.enable {
141 users.users = lib.optionalAttrs (cfg.user == name) {
142 "${name}" = {
143 inherit uid;
144 group = cfg.group;
145 description = "Mediagoblin user";
146 home = cfg.dataDir;
147 useDefaultShell = true;
148 };
149 };
150 users.groups = lib.optionalAttrs (cfg.group == name) {
151 "${name}" = {
152 inherit gid;
153 };
154 };
155
156 systemd.slices.mediagoblin = {
157 description = "Mediagoblin slice";
158 };
159 systemd.services.mediagoblin-web = {
160 description = "Mediagoblin service";
161 wantedBy = [ "multi-user.target" ];
162 after = [ "network.target" ];
163 wants = [ "postgresql.service" "redis.service" ];
164
165 environment.SCRIPT_NAME = "/mediagoblin/";
166
167 script = ''
168 exec ./bin/paster serve \
169 ${paste_local} \
170 --pid-file=${cfg.pids.paster}
171 '';
172 preStop = ''
173 exec ./bin/paster serve \
174 --pid-file=${cfg.pids.paster} \
175 ${paste_local} stop
176 '';
177 preStart = ''
178 if [ -d ${cfg.dataDir}/plugin_static/ ]; then
179 rm ${cfg.dataDir}/plugin_static/coreplugin_basic_auth
180 ln -sf ${cfg.package}/mediagoblin/plugins/basic_auth/static ${cfg.dataDir}/plugin_static/coreplugin_basic_auth
181 fi
182 ./bin/gmg -cf ${cfg.configFile} dbupdate
183 '';
184
185 serviceConfig = {
186 Slice = "mediagoblin.slice";
187 User = cfg.user;
188 PrivateTmp = true;
189 Restart = "always";
190 TimeoutSec = 15;
191 Type = "simple";
192 WorkingDirectory = cfg.package;
193 RuntimeDirectory = cfg.systemdRuntimeDirectory;
194 StateDirectory= cfg.systemdStateDirectory;
195 PIDFile = cfg.pids.paster;
196 };
197
198 unitConfig.RequiresMountsFor = cfg.dataDir;
199 };
200
201 systemd.services.mediagoblin-celeryd = {
202 description = "Mediagoblin service";
203 wantedBy = [ "multi-user.target" ];
204 after = [ "network.target" "mediagoblin-web.service" ];
205
206 environment.MEDIAGOBLIN_CONFIG = cfg.configFile;
207 environment.CELERY_CONFIG_MODULE = "mediagoblin.init.celery.from_celery";
208
209 script = ''
210 exec ./bin/celery worker \
211 --logfile=${cfg.dataDir}/celery.log \
212 --loglevel=INFO
213 '';
214
215 serviceConfig = {
216 Slice = "mediagoblin.slice";
217 User = cfg.user;
218 PrivateTmp = true;
219 Restart = "always";
220 TimeoutSec = 60;
221 Type = "simple";
222 WorkingDirectory = cfg.package;
223 RuntimeDirectory = cfg.systemdRuntimeDirectory;
224 StateDirectory= cfg.systemdStateDirectory;
225 PIDFile = cfg.pids.celery;
226 };
227
228 unitConfig.RequiresMountsFor = cfg.dataDir;
229 };
230 };
231}
diff --git a/modules/webapps/webstats/default.nix b/modules/webapps/webstats/default.nix
deleted file mode 100644
index e873af2..0000000
--- a/modules/webapps/webstats/default.nix
+++ /dev/null
@@ -1,80 +0,0 @@
1{ lib, pkgs, config, ... }:
2let
3 name = "goaccess";
4 cfg = config.services.webstats;
5in {
6 options.services.webstats = {
7 dataDir = lib.mkOption {
8 type = lib.types.path;
9 default = "/var/lib/${name}";
10 description = ''
11 The directory where Goaccess stores its data.
12 '';
13 };
14 sites = lib.mkOption {
15 type = lib.types.listOf (lib.types.submodule {
16 options = {
17 conf = lib.mkOption {
18 type = lib.types.nullOr lib.types.path;
19 default = null;
20 description = ''
21 use custom goaccess configuration file instead of the
22 default one.
23 '';
24 };
25 name = lib.mkOption {
26 type = lib.types.str;
27 description = ''
28 Domain name. Corresponds to the Apache file name and the
29 folder name in which the state will be saved.
30 '';
31 };
32 };
33 });
34 default = [];
35 description = "Sites to generate stats";
36 };
37 };
38
39 config = lib.mkIf (builtins.length cfg.sites > 0) {
40 users.users.root.packages = [
41 pkgs.goaccess
42 ];
43
44 services.cron = {
45 enable = true;
46 systemCronJobs = let
47 stats = domain: conf: let
48 config = if builtins.isNull conf
49 then pkgs.runCommand "goaccess.conf" {
50 dbPath = "${cfg.dataDir}/${domain}";
51 } "substituteAll ${./goaccess.conf} $out"
52 else conf;
53 d = pkgs.writeScriptBin "stats-${domain}" ''
54 #!${pkgs.stdenv.shell}
55 set -e
56 shopt -s nullglob
57 TMPFILE=$(mktemp)
58 trap "rm -f $TMPFILE" EXIT
59
60 mkdir -p ${cfg.dataDir}/${domain}
61 for i in /var/log/httpd/access-${domain}*.gz; do
62 zcat "$i" >> $TMPFILE
63 done
64 cat /var/log/httpd/access-${domain}.log > $TMPFILE
65 ${pkgs.goaccess}/bin/goaccess $TMPFILE --no-progress -o ${cfg.dataDir}/${domain}/index.html -p ${config}
66 '';
67 in "${d}/bin/stats-${domain}";
68 allStats = sites: pkgs.writeScript "stats" ''
69 #!${pkgs.stdenv.shell}
70
71 mkdir -p ${cfg.dataDir}
72 ${builtins.concatStringsSep "\n" (map (v: stats v.name v.conf) sites)}
73 '';
74 in
75 [
76 "5 0 * * * root ${allStats cfg.sites}"
77 ];
78 };
79 };
80}
diff --git a/modules/webapps/webstats/goaccess.conf b/modules/webapps/webstats/goaccess.conf
deleted file mode 100644
index c6c244a..0000000
--- a/modules/webapps/webstats/goaccess.conf
+++ /dev/null
@@ -1,100 +0,0 @@
1time-format %H:%M:%S
2date-format %d/%b/%Y
3
4log-format VCOMBINED
5#= %v:%^ %h %^[%d:%t %^] "%r" %s %b "%R" "%u"
6
7html-prefs {"theme":"bright","layout":"vertical"}
8
9# old
10exclude-ip 188.165.209.148
11exclude-ip 178.33.252.96
12exclude-ip 2001:41d0:2:9c94::1
13exclude-ip 2001:41d0:2:9c94::
14# eldiron
15exclude-ip 176.9.151.89
16exclude-ip 2a01:4f8:160:3445::
17# monitoring-1
18exclude-ip 95.216.164.150
19exclude-ip 2a01:4f9:c010:1c95::
20
21no-query-string true
22
23persist true
24restore true
25db-path @dbPath@
26
27ignore-panel REFERRERS
28ignore-panel KEYPHRASES
29
30static-file .css
31static-file .js
32static-file .jpg
33static-file .png
34static-file .gif
35static-file .ico
36static-file .jpeg
37static-file .pdf
38static-file .csv
39static-file .mpeg
40static-file .mpg
41static-file .swf
42static-file .woff
43static-file .woff2
44static-file .xls
45static-file .xlsx
46static-file .doc
47static-file .docx
48static-file .ppt
49static-file .pptx
50static-file .txt
51static-file .zip
52static-file .ogg
53static-file .mp3
54static-file .mp4
55static-file .exe
56static-file .iso
57static-file .gz
58static-file .rar
59static-file .svg
60static-file .bmp
61static-file .tar
62static-file .tgz
63static-file .tiff
64static-file .tif
65static-file .ttf
66static-file .flv
67#static-file .less
68#static-file .ac3
69#static-file .avi
70#static-file .bz2
71#static-file .class
72#static-file .cue
73#static-file .dae
74#static-file .dat
75#static-file .dts
76#static-file .ejs
77#static-file .eot
78#static-file .eps
79#static-file .img
80#static-file .jar
81#static-file .map
82#static-file .mid
83#static-file .midi
84#static-file .ogv
85#static-file .webm
86#static-file .mkv
87#static-file .odp
88#static-file .ods
89#static-file .odt
90#static-file .otf
91#static-file .pict
92#static-file .pls
93#static-file .ps
94#static-file .qt
95#static-file .rm
96#static-file .svgz
97#static-file .wav
98#static-file .webp
99
100