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