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