btw i use nix
1{
2 nixpkgs-unstable,
3 config,
4 pkgs,
5 lib,
6 nixpkgs-chromedriver,
7 ...
8}:
9
10{
11 custom.nix-cache.enable = true;
12
13 age.secrets."eon-freumh.org.cap" = {
14 file = ../../secrets/eon-freumh.org.cap.age;
15 mode = "770";
16 owner = "acme-eon";
17 group = "acme-eon";
18 };
19 security.acme-eon = {
20 acceptTerms = true;
21 defaults.email = "${config.custom.username}@${config.networking.domain}";
22 defaults.capFile = config.age.secrets."eon-freumh.org.cap".path;
23 nginxCerts = [
24 "nix-cache.vpn.freumh.org"
25 "jellyfin.vpn.freumh.org"
26 "jellyfin.freumh.org"
27 "jellyseerr.freumh.org"
28 "transmission.vpn.freumh.org"
29 "nextcloud.vpn.freumh.org"
30 "owntracks.vpn.freumh.org"
31 "immich.vpn.freumh.org"
32 "calibre.freumh.org"
33 "audiobookshelf.vpn.freumh.org"
34 ];
35 };
36
37 services.nginx = {
38 #requires = [ "tailscaled.service" ];
39 clientMaxBodySize = "1g";
40 virtualHosts = {
41 "nix-cache.vpn.freumh.org" = {
42 listenAddresses = [ "100.64.0.9" ];
43 };
44 "jellyfin.vpn.freumh.org" = {
45 onlySSL = true;
46 listenAddresses = [ "100.64.0.9" ];
47 locations."/" = {
48 proxyPass = ''
49 http://localhost:8096
50 '';
51 proxyWebsockets = true;
52 };
53 };
54 "jellyfin.freumh.org" = {
55 onlySSL = true;
56 locations."/" = {
57 recommendedProxySettings = true;
58 proxyPass = ''
59 http://localhost:8096
60 '';
61 proxyWebsockets = true;
62 };
63 };
64 "jellyseerr.freumh.org" = {
65 onlySSL = true;
66 locations."/" = {
67 recommendedProxySettings = true;
68 proxyPass = ''
69 http://localhost:${builtins.toString config.services.jellyseerr.port}
70 '';
71 proxyWebsockets = true;
72 };
73 };
74 "transmission.vpn.freumh.org" = {
75 onlySSL = true;
76 listenAddresses = [ "100.64.0.9" ];
77 locations."/" = {
78 proxyPass = with config.services.transmission.settings; ''
79 http://localhost:${builtins.toString rpc-port}
80 '';
81 };
82 };
83 "nextcloud.vpn.freumh.org" = {
84 onlySSL = true;
85 listenAddresses = [ "100.64.0.9" ];
86 };
87 "owntracks.vpn.freumh.org" = {
88 onlySSL = true;
89 listenAddresses = [ "100.64.0.9" ];
90 };
91 "immich.vpn.freumh.org" = {
92 onlySSL = true;
93 listenAddresses = [ "100.64.0.9" ];
94 locations."/" = {
95 proxyPass = with config.services.immich; ''
96 http://${host}:${builtins.toString port}
97 '';
98 };
99 };
100 "calibre.freumh.org" = {
101 addSSL = true;
102 locations."/" = {
103 recommendedProxySettings = true;
104 proxyPass = ''
105 http://127.0.0.1:${builtins.toString config.services.calibre-web.listen.port}
106 '';
107 proxyWebsockets = true;
108 extraConfig = ''
109 proxy_buffer_size 128k;
110 proxy_buffers 4 256k;
111 proxy_busy_buffers_size 256k;
112 '';
113 };
114 };
115 "audiobookshelf.vpn.freumh.org" = {
116 onlySSL = true;
117 listenAddresses = [ "100.64.0.9" ];
118 locations."/" = {
119 proxyPass = ''
120 http://localhost:${builtins.toString config.services.audiobookshelf.port}
121 '';
122 proxyWebsockets = true;
123 };
124 };
125 };
126 };
127
128 services.avahi = {
129 enable = true;
130 nssmdns4 = true;
131 publish = {
132 enable = true;
133 addresses = true;
134 workstation = true;
135 };
136 };
137
138 services.minidlna = {
139 enable = true;
140 openFirewall = true;
141 settings = {
142 media_dir = [ "/tank/" ];
143 notify_interval = 60;
144 inofity = true;
145 };
146 };
147
148 services.jellyfin = {
149 enable = true;
150 openFirewall = true;
151 };
152 users.users.${config.services.jellyfin.user}.extraGroups = [
153 config.services.transmission.user
154 config.services.sonarr.user
155 config.services.radarr.user
156 config.services.bazarr.user
157 config.services.lidarr.user
158 config.services.readarr.user
159 ];
160
161 services.samba = {
162 enable = true;
163 openFirewall = true;
164 settings = {
165 global = {
166 workgroup = "WORKGROUP";
167 "server string" = "${config.networking.hostName}";
168 "netbios name" = "${config.networking.hostName}";
169 "security" = "user";
170 #"use sendfile" = "yes";
171 #"max protocol" = "smb2";
172 # note: localhost is the ipv6 localhost ::1
173 "hosts allow" = "192.168.1. 192.168.0. 127.0.0.1 localhost 100.64.0.0/10";
174 "hosts deny" = "0.0.0.0/0";
175 "guest account" = "nobody";
176 "map to guest" = "bad user";
177 };
178 tank = {
179 path = "/tank/";
180 browseable = "yes";
181 "read only" = "no";
182 "guest ok" = "no";
183 "create mask" = "0644";
184 "directory mask" = "0755";
185 };
186 };
187 };
188 users.mutableUsers = lib.mkForce true;
189
190 age.secrets.nextcloud = {
191 file = ../../secrets/nextcloud.age;
192 mode = "770";
193 owner = "nextcloud";
194 group = "nextcloud";
195 };
196 services.nextcloud = {
197 enable = true;
198 package = pkgs.nextcloud29;
199 hostName = "nextcloud.vpn.freumh.org";
200 config.adminpassFile = config.age.secrets.nextcloud.path;
201 };
202
203 services.transmission = {
204 enable = true;
205 openRPCPort = true;
206 package = pkgs.transmission_3;
207 settings = {
208 download-dir = "/tank/transmission";
209 incomplete-dir-enabled = false;
210 rpc-whitelist = "127.0.0.1,100.64.*.*,192.168.1.*";
211 rpc-bind-address = "0.0.0.0";
212 rpc-host-whitelist-enabled = false;
213 ratio-limit-enabled = true;
214 download-queue-size = 20;
215 };
216 };
217
218 services.prowlarr.enable = true;
219 services.flaresolverr.enable = true;
220 services.sonarr.enable = true;
221 services.radarr.enable = true;
222 services.bazarr.enable = true;
223 services.lidarr.enable = true;
224 services.readarr.enable = true;
225 services.nzbget.enable = true;
226 services.jellyseerr.enable = true;
227 users.users.${config.services.sonarr.user}.extraGroups = [
228 config.services.transmission.user
229 config.services.nzbget.user
230 ];
231 users.users.${config.services.radarr.user}.extraGroups = [
232 config.services.transmission.user
233 config.services.nzbget.user
234 ];
235 users.users.${config.services.bazarr.user}.extraGroups = [
236 config.services.sonarr.user
237 config.services.radarr.user
238 ];
239 users.users.${config.services.lidarr.user}.extraGroups = [
240 config.services.transmission.user
241 config.services.nzbget.user
242 ];
243 users.users.${config.services.readarr.user}.extraGroups = [
244 config.services.transmission.user
245 config.services.nzbget.user
246 ];
247
248 services.calibre-web = {
249 enable = true;
250 listen = {
251 port = 8084;
252 ip = "127.0.0.1";
253 };
254 options = {
255 enableBookConversion = true;
256 enableBookUploading = true;
257 enableKepubify = true;
258 };
259 };
260 users.users.${config.services.calibre-web.user}.extraGroups = [
261 config.services.readarr.user
262 ];
263
264 age.secrets.restic-owl.file = ../../secrets/restic-owl.age;
265 age.secrets.restic-gecko.file = ../../secrets/restic-gecko.age;
266 age.secrets.restic-shrew.file = ../../secrets/restic-shrew.age;
267 services.restic = {
268 #backups.owl = {
269 # repository = "${config.services.restic.server.dataDir}/owl";
270 # passwordFile = "${config.custom.secretsDir}/restic-password-owl";
271 # timerConfig = {
272 # OnCalendar = "02:00";
273 # };
274 # pruneOpts = [
275 # "--keep-daily 7"
276 # "--keep-weekly 5"
277 # "--keep-monthly 12"
278 # "--keep-yearly 5"
279 # ];
280 #};
281 #backups.gecko = {
282 # repository = "${config.services.restic.server.dataDir}/gecko";
283 # passwordFile = "${config.custom.secretsDir}/restic-password-gecko";
284 # timerConfig = {
285 # OnCalendar = "02:00";
286 # };
287 # pruneOpts = [
288 # "--keep-daily 7"
289 # "--keep-weekly 5"
290 # "--keep-monthly 12"
291 # "--keep-yearly 5"
292 # ];
293 #};
294 server = {
295 enable = true;
296 listenAddress = "100.64.0.9:8000";
297 dataDir = "/tank/backups/restic";
298 appendOnly = true;
299 extraFlags = [ "--no-auth" ];
300 };
301 };
302 systemd.services.restic-rest-server = {
303 after = [ "tailscaled.service" ];
304 requires = [ "tailscaled.service" ];
305 };
306
307 services.owntracks-recorder = {
308 enable = true;
309 host = "100.64.0.9";
310 domain = "owntracks.vpn.freumh.org";
311 };
312
313 services.immich = {
314 enable = true;
315 openFirewall = true;
316 host = "100.64.0.9";
317 mediaLocation = "/tank/immich";
318 };
319
320 services.audiobookshelf = {
321 enable = true;
322 port = 8001;
323 };
324 users.users.${config.services.audiobookshelf.user}.extraGroups = [
325 config.services.readarr.user
326 ];
327
328 services.fail2ban = {
329 enable = true;
330 bantime = "24h";
331 bantime-increment = {
332 enable = true;
333 multipliers = "1 2 4 8 16 32 64";
334 maxtime = "168h";
335 overalljails = true;
336 };
337 jails."jellyfin".settings = {
338 backend = "auto";
339 port = "80,443";
340 protocol = "tcp";
341 filter = "jellyfin";
342 maxRetry = 3;
343 bantime = "86400";
344 findTime = "43200";
345 logPath = "/var/lib/jellyfin/log/*.log";
346 };
347 # requires 'Enable Proxy Support' for jellyseerr
348 jails."jellyseerr".settings = {
349 backend = "auto";
350 port = "80,443";
351 protocol = "tcp";
352 filter = "jellyseerr";
353 maxRetry = 3;
354 bantime = "86400";
355 findTime = "43200";
356 logPath = "/var/lib/jellyseerr/logs/overseerr.log";
357 };
358 # requires 'Enable Proxy Support' for jellyseerr
359 jails."calibre-web".settings = {
360 backend = "auto";
361 port = "80,443";
362 protocol = "tcp";
363 filter = "calibre-web";
364 maxRetry = 3;
365 bantime = "86400";
366 findTime = "43200";
367 logPath = "/var/lib/calibre-web/log";
368 };
369 };
370 environment.etc = {
371 "fail2ban/filter.d/jellyfin.local".text = ''
372 [Definition]
373 failregex = ^.*Authentication request for .* has been denied \(IP: "<ADDR>"\)\.
374 '';
375 "fail2ban/filter.d/jellyseerr.local".text = ''
376 [Definition]
377 failregex = ^.*\[warn\]\[Auth\]: Failed login attempt from user with incorrect Jellyfin credentials {"account":{"ip":"<HOST>","email":
378 '';
379 "fail2ban/filter.d/calibre-web.local".text = ''
380 [Definition]
381 failregex = ^(?:\[\])?\s*WARN \{[^\}]*\} Login failed for user "<F-USER>[^"]*</F-USER>" IP-address: <ADDR>
382 '';
383 };
384
385 systemd.services.ddns = {
386 description = "Dynamic DNS";
387 wantedBy = [ "multi-user.target" ];
388 after = [ "network-online.target" ];
389 wants = [ "network-online.target" ];
390 serviceConfig = {
391 ExecStart = pkgs.writeShellScript "update-dns" ''
392 while true; do
393 IP="$(${pkgs.curl}/bin/curl https://ipinfo.io/ip 2> /dev/null)"
394 echo $IP
395 ${config.services.eon.package}/bin/capc update /run/agenix/eon-freumh.org.cap \
396 -u "remove|jellyfin.freumh.org|A" \
397 -u "remove|jellyseerr.freumh.org|A" \
398 -u "remove|calibre.freumh.org|A" \
399 -u "add|jellyfin.freumh.org|A|$IP|60" \
400 -u "add|jellyseerr.freumh.org|A|$IP|60" \
401 -u "add|calibre.freumh.org|A|$IP|60" \
402 ;
403 sleep 3600
404 done
405 '';
406 Restart = "always";
407 RestartSec = 5;
408 User = "root";
409 };
410 };
411}