This repository has no description
9.8 kB
357 lines
1{ config, pkgs, ... }:
2{
3 users.users.download = {
4 isSystemUser = true;
5 uid = 1001;
6 group = "download";
7 };
8 users.groups.download.members = [ "transmission" ];
9 services.transmission = {
10 enable = true;
11 package = pkgs.transmission_4;
12 home = "/var/state/transmission";
13 group = "download";
14 downloadDirPermissions = "775";
15 settings = {
16 download-dir = "/var/download/transmission";
17 incomplete-dir-enabled = false;
18 rpc-bind-address = "::";
19 message-level = 1;
20 umask = 18;
21 rpc-whitelist-enabled = false;
22 rpc-host-whitelist-enabled = false;
23 };
24 };
25 systemd.services.transmission-watcher = {
26 wantedBy = [ "multi-user.target" ];
27 startAt = "*:0/5";
28 path = [
29 pkgs.curl
30 pkgs.systemdMinimal
31 ];
32 script = ''
33 set -efu -o pipefail
34 if ! curl -SsfL http://transmission.r; then
35 systemctl restart transmission*
36 fi
37 '';
38 };
39
40 security.acme.defaults.email = "spam@krebsco.de";
41 security.acme.acceptTerms = true;
42 security.acme.certs."yellow.r".server = config.krebs.ssl.acmeURL;
43 security.acme.certs."jelly.r".server = config.krebs.ssl.acmeURL;
44 security.acme.certs."radar.r".server = config.krebs.ssl.acmeURL;
45 security.acme.certs."sonar.r".server = config.krebs.ssl.acmeURL;
46 security.acme.certs."transmission.r".server = config.krebs.ssl.acmeURL;
47 services.nginx = {
48 enable = true;
49 package = pkgs.nginx.override {
50 modules = with pkgs.nginxModules; [
51 fancyindex
52 ];
53 };
54 virtualHosts."yellow.r" = {
55 serverAliases = [ "flix.r" ];
56 default = true;
57 enableACME = true;
58 addSSL = true;
59 locations."/" = {
60 root = "/var/download";
61 extraConfig = ''
62 fancyindex on;
63 fancyindex_footer "/fancy.html";
64 include ${pkgs.nginx}/conf/mime.types;
65 include ${pkgs.writeText "extrMime" ''
66 types {
67 video/webm mkv;
68 }
69 ''};
70 create_full_put_path on;
71 '';
72 };
73 locations."/chatty" = {
74 proxyPass = "http://localhost:3000";
75 extraConfig = ''
76 rewrite /chatty/(.*) /$1 break;
77 proxy_set_header Host $host;
78 '';
79 };
80 locations."= /fancy.html".extraConfig = ''
81 alias ${pkgs.writeText "nginx_footer" ''
82 <div id="mydiv">
83 <!-- Include a header DIV with the same name as the draggable DIV, followed by "header" -->
84 <div id="mydivheader">Click here to move</div>
85 <iframe src="/chatty/index.html"></iframe>
86 </div>
87 <style>
88 #mydiv {
89 position: absolute;
90 z-index: 9;
91 background-color: #f1f1f1;
92 border: 1px solid #d3d3d3;
93 text-align: center;
94 }
95
96 #mydivheader {
97 padding: 10px;
98 cursor: move;
99 z-index: 10;
100 background-color: #2196F3;
101 color: #fff;
102 }
103 </style>
104 <script>
105 // Make the DIV element draggable:
106 dragElement(document.getElementById("mydiv"));
107
108 function dragElement(elmnt) {
109 var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
110 if (document.getElementById(elmnt.id + "header")) {
111 // if present, the header is where you move the DIV from:
112 document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
113 } else {
114 // otherwise, move the DIV from anywhere inside the DIV:
115 elmnt.onmousedown = dragMouseDown;
116 }
117
118 function dragMouseDown(e) {
119 e = e || window.event;
120 e.preventDefault();
121 // get the mouse cursor position at startup:
122 pos3 = e.clientX;
123 pos4 = e.clientY;
124 document.onmouseup = closeDragElement;
125 // call a function whenever the cursor moves:
126 document.onmousemove = elementDrag;
127 }
128
129 function elementDrag(e) {
130 e = e || window.event;
131 e.preventDefault();
132 // calculate the new cursor position:
133 pos1 = pos3 - e.clientX;
134 pos2 = pos4 - e.clientY;
135 pos3 = e.clientX;
136 pos4 = e.clientY;
137 // set the element's new position:
138 elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
139 elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
140 }
141
142 function closeDragElement() {
143 // stop moving when mouse button is released:
144 document.onmouseup = null;
145 document.onmousemove = null;
146 }
147 }
148 </script>
149 ''};
150 '';
151 };
152 virtualHosts."jelly.r" = {
153 enableACME = true;
154 addSSL = true;
155 locations."/".extraConfig = ''
156 proxy_pass http://localhost:8096/;
157 proxy_set_header Accept-Encoding "";
158 '';
159 };
160 virtualHosts."transmission.r" = {
161 enableACME = true;
162 addSSL = true;
163 locations."/" = {
164 proxyWebsockets = true;
165 proxyPass = "http://128.0.0.1:9091";
166 };
167 };
168 virtualHosts."radar.r" = {
169 enableACME = true;
170 addSSL = true;
171 locations."/" = {
172 proxyWebsockets = true;
173 proxyPass = "http://localhost:7878";
174 };
175 };
176 virtualHosts."sonar.r" = {
177 enableACME = true;
178 addSSL = true;
179 locations."/" = {
180 proxyWebsockets = true;
181 proxyPass = "http://localhost:8989";
182 # sonar.r now has forced authentication
183 extraConfig = ''
184 proxy_set_header Authorization "Basic a3JlYnM6YWlkc2JhbGxz";
185 '';
186 };
187 };
188 };
189
190 services.samba = {
191 enable = true;
192 enableNmbd = false;
193 settings.global = {
194 "hosts allow" = "42::/16 10.243.0.0/16 10.244.0.0/16 fdcc:c5da:5295:c853:d499::/80";
195 "use sendfile" = "true";
196 "disable netbios" = "true";
197 "mangled names" = "illegal";
198 "socket options" = "TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=65536 SO_SNDBUF=65536";
199 "load printers" = "false";
200 "disable spoolss" = "true";
201 "printcap name" = "/dev/null";
202 "map to guest" = "Bad User";
203 "max log size" = "50";
204 "dns proxy" = "no";
205 "security" = "user";
206 "syslog only" = "yes";
207 };
208 shares.public = {
209 comment = "Warez";
210 path = "/var/download";
211 public = "yes";
212 "only guest" = "yes";
213 "create mask" = "0644";
214 "directory mask" = "2777";
215 writable = "no";
216 printable = "no";
217 };
218 };
219
220 systemd.services.bruellwuerfel =
221 let
222 bruellwuerfelSrc = pkgs.fetchFromGitHub {
223 owner = "krebs";
224 repo = "bruellwuerfel";
225 rev = "dc73adf69249fb63a4b024f1f3fbc9e541b27015";
226 sha256 = "078jp1gbavdp8lnwa09xa5m6bbbd05fi4x5ldkkgin5z04hwlhmd";
227 };
228 in
229 {
230 wantedBy = [ "multi-user.target" ];
231 after = [ "network-online.target" ];
232 environment = {
233 IRC_CHANNEL = "#flix";
234 IRC_NICK = "bruelli";
235 IRC_SERVER = "irc.r";
236 IRC_HISTORY_FILE = "/tmp/bruelli.history";
237 };
238 serviceConfig = {
239 ExecStart = "${pkgs.deno}/bin/deno run -A ${bruellwuerfelSrc}/src/index.ts";
240 };
241 };
242
243 networking.firewall.allowedTCPPorts = [
244 80 # nginx
245 443 # nginx
246 9091 # transmission web
247 8096 # jellyfin
248 8920 # jellyfin
249 51413 # transmission traffic
250 445 # smbd
251 111 # smbd
252 2049 # smbd
253 4000 # smbd
254 4001 # smbd
255 4002 # smbd
256 ];
257 networking.firewall.allowedUDPPorts = [
258 51413 # transmission traffic
259 1900 # jellyfin
260 7359 # jellyfin
261 111 # smbd
262 2049 # smbd
263 4000 # smbd
264 4001 # smbd
265 4002 # smbd
266 ];
267 krebs.iptables = {
268 enable = true;
269 tables.nat.PREROUTING.rules = [
270 # transmission rpc port
271 {
272 predicate = "-i retiolum -p tcp --dport 9091";
273 target = "DNAT --to-destination fdb4:3310:947::2";
274 v4 = false;
275 }
276 ];
277 tables.filter.FORWARD.policy = "ACCEPT"; # we need this so we can forward into the the transmission network namespace
278 };
279
280 systemd.services.flix-index = {
281 wantedBy = [ "multi-user.target" ];
282 path = [
283 pkgs.coreutils
284 pkgs.findutils
285 pkgs.inotify-tools
286 ];
287 startAt = "hourly";
288 serviceConfig = {
289 Type = "oneshot";
290 ExecStart = pkgs.writers.writeDash "flix-index" ''
291 set -efu
292 index(){
293 find . -type f > "$DIR"/index.tmp
294 mv "$DIR"/index.tmp "$DIR"/index
295 }
296
297 DIR=/var/download
298 cd "$DIR"
299 index
300 '';
301 };
302 };
303
304 services.jellyfin = {
305 enable = true;
306 group = "download";
307 };
308
309 # request managment
310 services.jellyseerr = {
311 enable = true;
312 openFirewall = true;
313 };
314
315 # movies
316 services.radarr = {
317 enable = true;
318 openFirewall = true;
319 user = "download";
320 group = "download";
321 };
322
323 # shows
324 services.sonarr = {
325 enable = true;
326 openFirewall = true;
327 user = "download";
328 group = "download";
329 };
330 # sonarr needs unsecure packages
331 nixpkgs.config.permittedInsecurePackages = [
332 "aspnetcore-runtime-wrapped-6.0.36"
333 "aspnetcore-runtime-6.0.36"
334 "dotnet-sdk-wrapped-6.0.428"
335 "dotnet-sdk-6.0.428"
336 ];
337
338 # indexers
339 services.prowlarr = {
340 enable = true;
341 openFirewall = true;
342 };
343
344 # flaresolverr for bypassing cloudflare on some indexers
345 services.flaresolverr = {
346 enable = true;
347 openFirewall = true;
348 };
349
350 # subtitles
351 services.bazarr = {
352 enable = true;
353 openFirewall = true;
354 user = "download";
355 group = "download";
356 };
357}