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