summaryrefslogtreecommitdiffstats
path: root/lass/2configs/services
diff options
context:
space:
mode:
Diffstat (limited to 'lass/2configs/services')
-rw-r--r--lass/2configs/services/coms/default.nix6
-rw-r--r--lass/2configs/services/coms/jitsi.nix43
-rw-r--r--lass/2configs/services/coms/murmur.nix47
-rw-r--r--lass/2configs/services/coms/proxy.nix41
-rw-r--r--lass/2configs/services/flix/container-host.nix40
-rw-r--r--lass/2configs/services/flix/default.nix316
-rw-r--r--lass/2configs/services/flix/proxy.nix12
-rw-r--r--lass/2configs/services/radio/container-host.nix23
-rw-r--r--lass/2configs/services/radio/controls.html83
-rw-r--r--lass/2configs/services/radio/default.nix328
-rw-r--r--lass/2configs/services/radio/news.nix106
-rw-r--r--lass/2configs/services/radio/proxy.nix17
-rw-r--r--lass/2configs/services/radio/radio.liq112
-rw-r--r--lass/2configs/services/radio/shell.nix7
-rw-r--r--lass/2configs/services/radio/weather.nix60
-rw-r--r--lass/2configs/services/radio/weather_for_ips.py48
16 files changed, 1289 insertions, 0 deletions
diff --git a/lass/2configs/services/coms/default.nix b/lass/2configs/services/coms/default.nix
new file mode 100644
index 00000000..4bc5f744
--- /dev/null
+++ b/lass/2configs/services/coms/default.nix
@@ -0,0 +1,6 @@
+{
+ imports = [
+ ./jitsi.nix
+ ./murmur.nix
+ ];
+}
diff --git a/lass/2configs/services/coms/jitsi.nix b/lass/2configs/services/coms/jitsi.nix
new file mode 100644
index 00000000..bbcb3616
--- /dev/null
+++ b/lass/2configs/services/coms/jitsi.nix
@@ -0,0 +1,43 @@
+{ config, lib, pkgs, ... }:
+{
+
+ services.jitsi-meet = {
+ enable = true;
+ hostName = "jitsi.lassul.us";
+ config = {
+ enableWelcomePage = true;
+ requireDisplayName = true;
+ analytics.disabled = true;
+ startAudioOnly = true;
+ channelLastN = 4;
+ stunServers = [
+ # - https://www.kuketz-blog.de/jitsi-meet-server-einstellungen-fuer-einen-datenschutzfreundlichen-betrieb/
+ { urls = "turn:turn.matrix.org:3478?transport=udp"; }
+ { urls = "turn:turn.matrix.org:3478?transport=tcp"; }
+ # - services.coturn:
+ #{ urls = "turn:turn.${domainName}:3479?transport=udp"; }
+ #{ urls = "turn:turn.${domainName}:3479?transport=tcp"; }
+ ];
+ constraints.video.height = {
+ ideal = 720;
+ max = 1080;
+ min = 240;
+ };
+ };
+ interfaceConfig = {
+ SHOW_JITSI_WATERMARK = false;
+ SHOW_WATERMARK_FOR_GUESTS = false;
+ DISABLE_PRESENCE_STATUS = true;
+ GENERATE_ROOMNAMES_ON_WELCOME_PAGE = false;
+ };
+ };
+
+ services.jitsi-videobridge.config = {
+ org.jitsi.videobridge.TRUST_BWE = false;
+ };
+
+ krebs.iptables.tables.filter.INPUT.rules = [
+ { predicate = "-p tcp --dport 4443"; target = "ACCEPT"; }
+ { predicate = "-p udp --dport 10000"; target = "ACCEPT"; }
+ ];
+}
diff --git a/lass/2configs/services/coms/murmur.nix b/lass/2configs/services/coms/murmur.nix
new file mode 100644
index 00000000..40c53da3
--- /dev/null
+++ b/lass/2configs/services/coms/murmur.nix
@@ -0,0 +1,47 @@
+{ config, lib, pkgs, ... }:
+{
+ services.murmur = {
+ enable = true;
+ # allowHtml = false;
+ bandwidth = 10000000;
+ registerName = "lassul.us";
+ autobanTime = 30;
+ sslCert = "/var/lib/acme/lassul.us/cert.pem";
+ sslKey = "/var/lib/acme/lassul.us/key.pem";
+ extraConfig = ''
+ opusthreshold=0
+ # rememberchannelduration=10000
+ '';
+ };
+ krebs.iptables.tables.filter.INPUT.rules = [
+ { predicate = "-p tcp --dport 64738"; target = "ACCEPT";}
+ { predicate = "-p udp --dport 64738"; target = "ACCEPT";}
+ ];
+
+ # services.botamusique = {
+ # enable = true;
+ # settings = {
+ # server.host = "lassul.us";
+ # bot.auto_check_updates = false;
+ # bot.max_track_duration = 360;
+ # webinterface.enabled = true;
+ # };
+ # };
+
+ services.nginx.virtualHosts."lassul.us" = {
+ enableACME = true;
+ };
+ security.acme.certs."lassul.us" = {
+ group = "lasscert";
+ };
+ users.groups.lasscert.members = [
+ "nginx"
+ "murmur"
+ ];
+
+ # services.nginx.virtualHosts."bota.r" = {
+ # locations."/" = {
+ # proxyPass = "http://localhost:8181";
+ # };
+ # };
+}
diff --git a/lass/2configs/services/coms/proxy.nix b/lass/2configs/services/coms/proxy.nix
new file mode 100644
index 00000000..57e13215
--- /dev/null
+++ b/lass/2configs/services/coms/proxy.nix
@@ -0,0 +1,41 @@
+{ config, lib, pkgs, ... }:
+let
+ tcpports = [
+ 4443 # jitsi
+ 64738 # murmur
+ ];
+ udpports = [
+ 10000 # jitsi
+ 64738 # murmur
+ ];
+ target = "orange.r";
+in
+{
+ networking.firewall.allowedTCPPorts = tcpports;
+ networking.firewall.allowedUDPPorts = udpports;
+ services.nginx.streamConfig = ''
+ ${lib.concatMapStringsSep "\n" (port: ''
+ server {
+ listen ${toString port};
+ proxy_pass ${target}:${toString port};
+ }
+ '') tcpports}
+ ${lib.concatMapStringsSep "\n" (port: ''
+ server {
+ listen ${toString port} udp;
+ proxy_pass ${target}:${toString port};
+ }
+ '') udpports}
+ '';
+
+ services.nginx.virtualHosts."jitsi.lassul.us" = {
+ enableACME = true;
+ acmeFallbackHost = "${target}";
+ addSSL = true;
+ locations."/" = {
+ recommendedProxySettings = true;
+ proxyWebsockets = true;
+ proxyPass = "http://${target}";
+ };
+ };
+}
diff --git a/lass/2configs/services/flix/container-host.nix b/lass/2configs/services/flix/container-host.nix
new file mode 100644
index 00000000..1c5b8112
--- /dev/null
+++ b/lass/2configs/services/flix/container-host.nix
@@ -0,0 +1,40 @@
+{ config, pkgs, ... }:
+{
+ krebs.sync-containers3.containers.yellow = {
+ sshKey = "${toString <secrets>}/yellow.sync.key";
+ };
+ containers.yellow.bindMounts."/var/lib" = {
+ hostPath = "/var/lib/sync-containers3/yellow/state";
+ isReadOnly = false;
+ };
+ containers.yellow.bindMounts."/var/download" = {
+ hostPath = "/var/download";
+ isReadOnly = false;
+ };
+ # krebs.iptables.tables.filter.FORWARD.rules = [
+ # { predicate = "-d ${config.krebs.hosts.yellow.nets.retiolum.ip4.addr} -p tcp --dport 8000 -m state --state NEW,ESTABLISHED,RELATED"; target = "ACCEPT"; v6 = false; }
+ # { predicate = "-d ${config.krebs.hosts.yellow.nets.retiolum.ip6.addr} -p tcp --dport 8000 -m state --state NEW,ESTABLISHED,RELATED"; target = "ACCEPT"; v4 = false; }
+ # ];
+ # krebs.iptables.tables.nat.PREROUTING.rules = [
+ # { predicate = "-p tcp --dport 2"; target = "DNAT --to-destination ${config.krebs.hosts.radio.nets.retiolum.ip4.addr}:8000"; v6 = false; }
+ # { predicate = "-p tcp --dport 2"; target = "DNAT --to-destination ${config.krebs.hosts.radio.nets.retiolum.ip6.addr}:8000"; v4 = false; }
+ # ];
+ networking.firewall.allowedTCPPorts = [ 8096 8920 ];
+ networking.firewall.allowedUDPPorts = [ 1900 7359 ];
+ containers.yellow.forwardPorts = [
+ { hostPort = 8096; containerPort = 8096; protocol = "tcp"; }
+ { hostPort = 8920; containerPort = 8920; protocol = "tcp"; }
+ { hostPort = 1900; containerPort = 1900; protocol = "udp"; }
+ { hostPort = 7359; containerPort = 7359; protocol = "udp"; }
+ ];
+
+ services.nginx.virtualHosts."flix.lassul.us" = {
+ # forceSSL = true;
+ # enableACME = true;
+ locations."/" = {
+ proxyPass = "http://yellow.r:8096";
+ proxyWebsockets = true;
+ recommendedProxySettings = true;
+ };
+ };
+}
diff --git a/lass/2configs/services/flix/default.nix b/lass/2configs/services/flix/default.nix
new file mode 100644
index 00000000..e6be394c
--- /dev/null
+++ b/lass/2configs/services/flix/default.nix
@@ -0,0 +1,316 @@
+{ config, lib, pkgs, ... }:
+{
+ users.groups.download.members = [ "transmission" ];
+ services.transmission = {
+ enable = true;
+ home = "/var/state/transmission";
+ group = "download";
+ downloadDirPermissions = "775";
+ settings = {
+ download-dir = "/var/download/transmission";
+ incomplete-dir-enabled = false;
+ rpc-bind-address = "::";
+ message-level = 1;
+ umask = 18;
+ rpc-whitelist-enabled = false;
+ rpc-host-whitelist-enabled = false;
+ };
+ };
+
+ security.acme.defaults.email = "spam@krebsco.de";
+ security.acme.acceptTerms = true;
+ security.acme.certs."yellow.r".server = config.krebs.ssl.acmeURL;
+ security.acme.certs."jelly.r".server = config.krebs.ssl.acmeURL;
+ security.acme.certs."radar.r".server = config.krebs.ssl.acmeURL;
+ security.acme.certs."sonar.r".server = config.krebs.ssl.acmeURL;
+ security.acme.certs."transmission.r".server = config.krebs.ssl.acmeURL;
+ services.nginx = {
+ enable = true;
+ package = pkgs.nginx.override {
+ modules = with pkgs.nginxModules; [
+ fancyindex
+ ];
+ };
+ virtualHosts."yellow.r" = {
+ default = true;
+ enableACME = true;
+ addSSL = true;
+ locations."/" = {
+ root = "/var/download";
+ extraConfig = ''
+ fancyindex on;
+ fancyindex_footer "/fancy.html";
+ include ${pkgs.nginx}/conf/mime.types;
+ include ${pkgs.writeText "extrMime" ''
+ types {
+ video/webm mkv;
+ }
+ ''};
+ create_full_put_path on;
+ '';
+ };
+ locations."/chatty" = {
+ proxyPass = "http://localhost:3000";
+ extraConfig = ''
+ rewrite /chatty/(.*) /$1 break;
+ proxy_set_header Host $host;
+ '';
+ };
+ locations."= /fancy.html".extraConfig = ''
+ alias ${pkgs.writeText "nginx_footer" ''
+ <div id="mydiv">
+ <!-- Include a header DIV with the same name as the draggable DIV, followed by "header" -->
+ <div id="mydivheader">Click here to move</div>
+ <iframe src="/chatty/index.html"></iframe>
+ </div>
+ <style>
+ #mydiv {
+ position: absolute;
+ z-index: 9;
+ background-color: #f1f1f1;
+ border: 1px solid #d3d3d3;
+ text-align: center;
+ }
+
+ #mydivheader {
+ padding: 10px;
+ cursor: move;
+ z-index: 10;
+ background-color: #2196F3;
+ color: #fff;
+ }
+ </style>
+ <script>
+ // Make the DIV element draggable:
+ dragElement(document.getElementById("mydiv"));
+
+ function dragElement(elmnt) {
+ var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
+ if (document.getElementById(elmnt.id + "header")) {
+ // if present, the header is where you move the DIV from:
+ document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
+ } else {
+ // otherwise, move the DIV from anywhere inside the DIV:
+ elmnt.onmousedown = dragMouseDown;
+ }
+
+ function dragMouseDown(e) {
+ e = e || window.event;
+ e.preventDefault();
+ // get the mouse cursor position at startup:
+ pos3 = e.clientX;
+ pos4 = e.clientY;
+ document.onmouseup = closeDragElement;
+ // call a function whenever the cursor moves:
+ document.onmousemove = elementDrag;
+ }
+
+ function elementDrag(e) {
+ e = e || window.event;
+ e.preventDefault();
+ // calculate the new cursor position:
+ pos1 = pos3 - e.clientX;
+ pos2 = pos4 - e.clientY;
+ pos3 = e.clientX;
+ pos4 = e.clientY;
+ // set the element's new position:
+ elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
+ elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
+ }
+
+ function closeDragElement() {
+ // stop moving when mouse button is released:
+ document.onmouseup = null;
+ document.onmousemove = null;
+ }
+ }
+ </script>
+ ''};
+ '';
+ };
+ virtualHosts."jelly.r" = {
+ enableACME = true;
+ addSSL = true;
+ locations."/".extraConfig = ''
+ proxy_pass http://localhost:8096/;
+ proxy_set_header Accept-Encoding "";
+ '';
+ };
+ virtualHosts."transmission.r" = {
+ enableACME = true;
+ addSSL = true;
+ locations."/" = {
+ proxyWebsockets = true;
+ proxyPass = "http://localhost:9091";
+ };
+ };
+ virtualHosts."radar.r" = {
+ enableACME = true;
+ addSSL = true;
+ locations."/" = {
+ proxyWebsockets = true;
+ proxyPass = "http://localhost:7878";
+ };
+ };
+ virtualHosts."sonar.r" = {
+ enableACME = true;
+ addSSL = true;
+ locations."/" = {
+ proxyWebsockets = true;
+ proxyPass = "http://localhost:8989";
+ };
+ };
+ };
+
+ services.samba = {
+ enable = true;
+ enableNmbd = false;
+ extraConfig = ''
+ workgroup = WORKGROUP
+ server string = ${config.networking.hostName}
+ # only allow retiolum addresses
+ hosts allow = 42::/16 10.243.0.0/16 10.244.0.0/16
+
+ # Use sendfile() for performance gain
+ use sendfile = true
+
+ # No NetBIOS is needed
+ disable netbios = true
+
+ # Only mangle non-valid NTFS names, don't care about DOS support
+ mangled names = illegal
+
+ # Performance optimizations
+ socket options = TCP_NODELAY IPTOS_LOWDELAY SO_RCVBUF=65536 SO_SNDBUF=65536
+
+ # Disable all printing
+ load printers = false
+ disable spoolss = true
+ printcap name = /dev/null
+
+ map to guest = Bad User
+ max log size = 50
+ dns proxy = no
+ security = user
+
+ [global]
+ syslog only = yes
+ '';
+ shares.public = {
+ comment = "Warez";
+ path = "/var/download";
+ public = "yes";
+ "only guest" = "yes";
+ "create mask" = "0644";
+ "directory mask" = "2777";
+ writable = "no";
+ printable = "no";
+ };
+ };
+
+ systemd.services.bruellwuerfel =
+ let
+ bruellwuerfelSrc = pkgs.fetchFromGitHub {
+ owner = "krebs";
+ repo = "bruellwuerfel";
+ rev = "dc73adf69249fb63a4b024f1f3fbc9e541b27015";
+ sha256 = "078jp1gbavdp8lnwa09xa5m6bbbd05fi4x5ldkkgin5z04hwlhmd";
+ };
+ in {
+ wantedBy = [ "multi-user.target" ];
+ environment = {
+ IRC_CHANNEL = "#flix";
+ IRC_NICK = "bruelli";
+ IRC_SERVER = "irc.r";
+ IRC_HISTORY_FILE = "/tmp/bruelli.history";
+ };
+ serviceConfig = {
+ ExecStart = "${pkgs.deno}/bin/deno run -A ${bruellwuerfelSrc}/src/index.ts";
+ };
+ };
+
+ krebs.iptables = {
+ enable = true;
+ tables.filter.INPUT.rules = [
+ { predicate = "-p tcp --dport 80"; target = "ACCEPT"; } # nginx web dir
+ { predicate = "-p tcp --dport 443"; target = "ACCEPT"; } # nginx web dir
+ { predicate = "-p tcp --dport 9091"; target = "ACCEPT"; } # transmission-web
+ { predicate = "-p tcp --dport 51413"; target = "ACCEPT"; } # transmission-traffic
+ { predicate = "-p udp --dport 51413"; target = "ACCEPT"; } # transmission-traffic
+ { predicate = "-p tcp --dport 8096"; target = "ACCEPT"; } # jellyfin
+ { predicate = "-p tcp --dport 8920"; target = "ACCEPT"; } # jellyfin
+ { predicate = "-p udp --dport 1900"; target = "ACCEPT"; } # jellyfin
+ { predicate = "-p udp --dport 7359"; target = "ACCEPT"; } # jellyfin
+ { predicate = "-p tcp --dport 9696"; target = "ACCEPT"; } # prowlarr
+ { predicate = "-p tcp --dport 8989"; target = "ACCEPT"; } # sonarr
+ { predicate = "-p tcp --dport 7878"; target = "ACCEPT"; } # radarr
+ { predicate = "-p tcp --dport 6767"; target = "ACCEPT"; } # bazarr
+
+ # smbd
+ { predicate = "-i retiolum -p tcp --dport 445"; target = "ACCEPT"; }
+ { predicate = "-i retiolum -p tcp --dport 111"; target = "ACCEPT"; }
+ { predicate = "-i retiolum -p udp --dport 111"; target = "ACCEPT"; }
+ { predicate = "-i retiolum -p tcp --dport 2049"; target = "ACCEPT"; }
+ { predicate = "-i retiolum -p udp --dport 2049"; target = "ACCEPT"; }
+ { predicate = "-i retiolum -p tcp --dport 4000:4002"; target = "ACCEPT"; }
+ { predicate = "-i retiolum -p udp --dport 4000:4002"; target = "ACCEPT"; }
+ { predicate = "-i wiregrill -p tcp --dport 445"; target = "ACCEPT"; }
+ { predicate = "-i wiregrill -p tcp --dport 111"; target = "ACCEPT"; }
+ { predicate = "-i wiregrill -p udp --dport 111"; target = "ACCEPT"; }
+ { predicate = "-i wiregrill -p tcp --dport 2049"; target = "ACCEPT"; }
+ { predicate = "-i wiregrill -p udp --dport 2049"; target = "ACCEPT"; }
+ { predicate = "-i wiregrill -p tcp --dport 4000:4002"; target = "ACCEPT"; }
+ { predicate = "-i wiregrill -p udp --dport 4000:4002"; target = "ACCEPT"; }
+ ];
+ };
+
+ systemd.services.flix-index = {
+ wantedBy = [ "multi-user.target" ];
+ path = [
+ pkgs.coreutils
+ pkgs.findutils
+ pkgs.inotify-tools
+ ];
+ serviceConfig = {
+ Restart = "always";
+ ExecStart = pkgs.writers.writeDash "flix-index" ''
+ set -efu
+
+ DIR=/var/download
+ cd "$DIR"
+ while inotifywait -rq -e create -e move -e delete "$DIR"; do
+ find . -type f > "$DIR"/index.tmp
+ mv "$DIR"/index.tmp "$DIR"/index
+ done
+ '';
+ };
+ };
+
+ services.jellyfin = {
+ enable = true;
+ group = "download";
+ };
+
+ # movies
+ services.radarr = {
+ enable = true;
+ group = "download";
+ };
+
+ # shows
+ services.sonarr = {
+ enable = true;
+ group = "download";
+ };
+
+ # indexers
+ services.prowlarr = {
+ enable = true;
+ };
+
+ # subtitles
+ services.bazarr = {
+ enable = true;
+ group = "download";
+ };
+}
diff --git a/lass/2configs/services/flix/proxy.nix b/lass/2configs/services/flix/proxy.nix
new file mode 100644
index 00000000..c16c6def
--- /dev/null
+++ b/lass/2configs/services/flix/proxy.nix
@@ -0,0 +1,12 @@
+{ config, pkgs, ... }:
+{
+ services.nginx.virtualHosts."flix.lassul.us" = {
+ forceSSL = true;
+ enableACME = true;
+ locations."/" = {
+ proxyPass = "http://yellow.r:8096";
+ proxyWebsockets = true;
+ recommendedProxySettings = true;
+ };
+ };
+}
diff --git a/lass/2configs/services/radio/container-host.nix b/lass/2configs/services/radio/container-host.nix
new file mode 100644
index 00000000..de0ea9af
--- /dev/null
+++ b/lass/2configs/services/radio/container-host.nix
@@ -0,0 +1,23 @@
+{ config, pkgs, ... }:
+{
+ krebs.sync-containers3.containers.radio = {
+ sshKey = "${toString <secrets>}/radio.sync.key";
+ };
+ containers.radio = {
+ bindMounts."/var/music" = {
+ hostPath = "/var/music";
+ isReadOnly = false;
+ };
+ };
+ krebs.iptables.tables.filter.INPUT.rules = [
+ { predicate = "-p tcp --dport 8000"; target = "ACCEPT"; }
+ ];
+ krebs.htgen.radio-redirect = {
+ port = 8000;
+ scriptFile = pkgs.writers.writeDash "redir" ''
+ printf 'HTTP/1.1 301 Moved Permanently\r\n'
+ printf "Location: http://radio.lassul.us''${Request_URI}\r\n"
+ printf '\r\n'
+ '';
+ };
+}
diff --git a/lass/2configs/services/radio/controls.html b/lass/2configs/services/radio/controls.html
new file mode 100644
index 00000000..858dc365
--- /dev/null
+++ b/lass/2configs/services/radio/controls.html
@@ -0,0 +1,83 @@
+<!doctype html>
+
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
+ <title>The_Playlist Voting!</title>
+<style>
+#good {
+ display: block;
+ width: 100%;
+ border: none;
+ background-color: #04AA6D;
+ padding: 14px;
+ margin: 14px 0 0 0;
+ height: 100px;
+ font-size: 16px;
+ cursor: pointer;
+ text-align: center;
+}
+#bad {
+ display: block;
+ width: 100%;
+ border: none;
+ background-color: red;
+ padding: 14px;
+ height: 100px;
+
+ margin: 14px 0 0 0;
+ font-size: 16px;
+ cursor: pointer;
+ text-align: center;
+}
+</style>
+
+</head>
+
+<body>
+ <div id=votenote></div>
+ <button id=good type="button"> GUT </button>
+
+ <button id=bad type="button"> SCHLECHT </button>
+ <center>
+ Currently Running: <br/><div>
+ <b id=current></b>
+ </div>
+ <div id=vote>
+ </div>
+ <audio controls autoplay="autoplay">
+ <source src="https://radio.lassul.us/radio.ogg" type="audio/ogg">
+ Your browser does not support the audio element.
+ </audio>
+ </center>
+
+ <script>
+ document.getElementById("good").onclick=async ()=>{
+ let result = await fetch("https://radio.lassul.us/good", {"method": "POST"})
+ document.getElementById("vote").textContent = "Dieses Lied findest du gut"
+ };
+ document.getElementById("bad").onclick=async ()=>{
+ let result = await fetch("https://radio.lassul.us/skip", {"method": "POST"})
+ document.getElementById("vote").textContent = "Dieses Lied findest du schlecht"
+ document.getElementById("bad").disabled = true
+ window.setTimeout(function(){
+ document.getElementById("bad").disabled = false
+ }, 100000)
+
+ };
+
+ async function current() {
+ let result = await fetch("https://radio.lassul.us/current", {"method": "GET"})
+ let data = await result.json()
+ document.getElementById("current").textContent = data.name
+ }
+ window.onload = function() {
+ window.setInterval('current()', 10000)
+ current()
+ }
+
+ </script>
+</body>
+</html>
diff --git a/lass/2configs/services/radio/default.nix b/lass/2configs/services/radio/default.nix
new file mode 100644
index 00000000..a511196f
--- /dev/null
+++ b/lass/2configs/services/radio/default.nix
@@ -0,0 +1,328 @@
+{ config, pkgs, lib, ... }:
+
+let
+ name = "radio";
+
+ music_dir = "/var/music";
+
+ skip_track = pkgs.writers.writeBashBin "skip_track" ''
+ set -eu
+
+ # TODO come up with new rating, without moving files
+ # current_track=$(${pkgs.curl}/bin/curl -fSs http://localhost:8002/current | ${pkgs.jq}/bin/jq -r .filename)
+ # track_infos=$(${print_current}/bin/print_current)
+ # skip_count=$(${pkgs.attr}/bin/getfattr -n user.skip_count --only-values "$current_track" || echo 0)
+ # if [[ "$current_track" =~ .*/the_playlist/music/.* ]] && [ "$skip_count" -le 2 ]; then
+ # skip_count=$((skip_count+1))
+ # ${pkgs.attr}/bin/setfattr -n user.skip_count -v "$skip_count" "$current_track"
+ # echo skipping: "$track_infos" skip_count: "$skip_count"
+ # else
+ # mkdir -p "$music_dir"/the_playlist/.graveyard/
+ # mv "$current_track" "$music_dir"/the_playlist/.graveyard/
+ # echo killing: "$track_infos"
+ # fi
+ ${pkgs.curl}/bin/curl -fSs -X POST http://localhost:8002/skip |
+ ${pkgs.jq}/bin/jq -r '.filename'
+ '';
+
+ good_track = pkgs.writeBashBin "good_track" ''
+ set -eu
+
+ current_track=$(${pkgs.curl}/bin/curl -fSs http://localhost:8002/current | ${pkgs.jq}/bin/jq -r .filename)
+ track_infos=$(${print_current}/bin/print_current)
+ # TODO come up with new rating, without moving files
+ # if [[ "$current_track" =~ .*/the_playlist/music/.* ]]; then
+ # ${pkgs.attr}/bin/setfattr -n user.skip_count -v 0 "$current_track"
+ # else
+ # mv "$current_track" "$music_dir"/the_playlist/music/ || :
+ # fi
+ echo good: "$track_infos"
+ '';
+
+ print_current = pkgs.writeDashBin "print_current" ''
+ file=$(${pkgs.curl}/bin/curl -fSs http://localhost:8002/current |
+ ${pkgs.jq}/bin/jq -r '.filename' |
+ ${pkgs.gnused}/bin/sed 's,^${music_dir},,'
+ )
+ link=$(${pkgs.curl}/bin/curl http://localhost:8002/current |
+ ${pkgs.jq}/bin/jq -r '.filename' |
+ ${pkgs.gnused}/bin/sed 's@.*\(.\{11\}\)\.ogg@https://youtu.be/\1@'
+ )
+ echo "$file": "$link"
+ '';
+
+ set_irc_topic = pkgs.writeDash "set_irc_topic" ''
+ ${pkgs.curl}/bin/curl -fsS --unix-socket /home/radio/reaktor.sock http://z/ \
+ -H content-type:application/json \
+ -d "$(${pkgs.jq}/bin/jq -n \
+ --arg text "$1" '{
+ command:"TOPIC",
+ params:["#the_playlist",$text]
+ }'
+ )"
+ '';
+
+ write_to_irc = pkgs.writeDash "write_to_irc" ''
+ ${pkgs.curl}/bin/curl -fsSv --unix-socket /home/radio/reaktor.sock http://z/ \
+ -H content-type:application/json \
+ -d "$(${pkgs.jq}/bin/jq -n \
+ --arg text "$1" '{
+ command:"PRIVMSG",
+ params:["#the_playlist",$text]
+ }'
+ )"
+ '';
+
+in {
+ imports = [
+ ./news.nix
+ ./weather.nix
+ ];
+
+ users.users = {
+ "${name}" = rec {
+ inherit name;
+ createHome = lib.mkForce false;
+ group = name;
+ uid = pkgs.stockholm.lib.genid_uint31 name;
+ description = "radio manager";
+ home = "/home/${name}";
+ useDefaultShell = true;
+ openssh.authorizedKeys.keys = with config.krebs.users; [
+ lass.pubkey
+ ];
+ };
+ };
+
+ users.groups = {
+ "radio" = {};
+ };
+
+ krebs.per-user.${name}.packages = with pkgs; [
+ good_track
+ skip_track
+ print_current
+ ];
+
+ services.liquidsoap.streams.radio = ./radio.liq;
+ systemd.services.radio = {
+ environment = {
+ RADIO_PORT = "8002";
+ HOOK_TRACK_CHANGE = pkgs.writers.writeDash "on_change" ''
+ set -xefu
+ LIMIT=1000 #how many tracks to keep in the history
+ HISTORY_FILE=/var/lib/radio/recent
+
+ listeners=$(${pkgs.curl}/bin/curl -fSs http://localhost:8000/status-json.xsl |
+ ${pkgs.jq}/bin/jq '[.icestats.source[].listeners] | add' || echo 0)
+ echo "$(${pkgs.coreutils}/bin/date -Is)" "$filename" | ${pkgs.coreutils}/bin/tee -a "$HISTORY_FILE"
+ echo "$(${pkgs.coreutils}/bin/tail -$LIMIT "$HISTORY_FILE")" > "$HISTORY_FILE"
+ ${set_irc_topic} "playing: $filename listeners: $listeners"
+ '';
+ MUSIC = "${music_dir}/the_playlist";
+ ICECAST_HOST = "localhost";
+ };
+ path = [
+ pkgs.yt-dlp
+ ];
+ serviceConfig.User = lib.mkForce "radio";
+ };
+
+ nixpkgs.config.packageOverrides = opkgs: {
+ icecast = opkgs.icecast.overrideAttrs (old: rec {
+ version = "2.5-beta3";
+
+ src = pkgs.fetchurl {
+ url = "http://downloads.xiph.org/releases/icecast/icecast-${version}.tar.gz";
+ sha256 = "sha256-4FDokoA9zBDYj8RAO/kuTHaZ6jZYBLSJZiX/IYFaCW8=";
+ };
+
+ buildInputs = old.buildInputs ++ [ pkgs.pkg-config ];
+ });
+ };
+ services.icecast = {
+ enable = true;
+ hostname = "radio.lassul.us";
+ admin.password = "hackme";
+ extraConf = ''
+ <authentication>
+ <source-password>hackme</source-password>
+ <admin-user>admin</admin-user>
+ <admin-password>hackme</admin-password>
+ </authentication>
+ <logging>
+ <accesslog>-</accesslog>
+ <errorlog>-</errorlog>
+ <loglevel>3</loglevel>
+ </logging>
+ '';
+ };
+
+ krebs.iptables = {
+ tables = {
+ filter.INPUT.rules = [
+ { predicate = "-p tcp --dport 8000"; target = "ACCEPT"; }
+ { predicate = "-i retiolum -p tcp --dport 8001"; target = "ACCEPT"; }
+ ];
+ };
+ };
+
+ # allow reaktor2 to modify files
+ systemd.services."reaktor2-the_playlist".serviceConfig.DynamicUser = lib.mkForce false;
+
+ krebs.reaktor2.the_playlist = {
+ hostname = "irc.hackint.org";
+ port = "6697";
+ useTLS = true;
+ nick = "the_playlist";
+ username = "radio";
+ API.listen = "unix:/home/radio/reaktor.sock";
+ plugins = [
+ {
+ plugin = "register";
+ config = {
+ channels = [
+ "#the_playlist"
+ "#krebs"
+ ];
+ };
+ }
+ {
+ plugin = "system";
+ config = {
+ workdir = config.krebs.reaktor2.the_playlist.stateDir;
+ hooks.PRIVMSG = [
+ {
+ activate = "match";
+ pattern = "^(?:.*\\s)?\\s*the_playlist:\\s*([0-9A-Za-z._][0-9A-Za-z._-]*)(?:\\s+(.*\\S))?\\s*$";
+ command = 1;
+ arguments = [2];
+ commands = {
+ skip.filename = "${skip_track}/bin/skip_track";
+ next.filename = "${skip_track}/bin/skip_track";
+ bad.filename = "${skip_track}/bin/skip_track";
+
+ good.filename = "${good_track}/bin/good_track";
+ nice.filename = "${good_track}/bin/good_track";
+ like.filename = "${good_track}/bin/good_track";
+
+ current.filename = "${print_current}/bin/print_current";
+ wish.filename = pkgs.writeDash "wish" ''
+ echo "youtube-dl:$1" | ${pkgs.curl}/bin/curl -fSs http://localhost:8002/wish -d @- > /dev/null
+ '';
+ wishlist.filename = pkgs.writeDash "wishlist" ''
+ ${pkgs.curl}/bin/curl -fSs http://localhost:8002/wish | ${pkgs.jq}/bin/jq -r '.[]'
+ '';
+ suggest.filename = pkgs.writeDash "suggest" ''
+ echo "$@" >> playlist_suggest
+ '';
+ };
+ }
+ ];
+ };
+ }
+ ];
+ };
+
+ krebs.htgen.radio = {
+ port = 8001;
+ user = {
+ name = "radio";
+ };
+ scriptFile = pkgs.writeDash "radio" ''
+ case "$Method $Request_URI" in
+ "POST /skip")
+ printf 'HTTP/1.1 200 OK\r\n'
+ printf 'Connection: close\r\n'
+ printf '\r\n'
+ msg=$(${skip_track}/bin/skip_track)
+ ${write_to_irc} "$msg"
+ echo "$msg"
+ exit
+ ;;
+ "POST /good")
+ printf 'HTTP/1.1 200 OK\r\n'
+ printf 'Connection: close\r\n'
+ printf '\r\n'
+ msg=$(${good_track}/bin/good_track)
+ ${write_to_irc} "$msg"
+ echo "$msg"
+ exit
+ ;;
+ esac
+ '';
+ };
+
+ networking.firewall.allowedTCPPorts = [ 80 ];
+ services.nginx = {
+ enable = true;
+ virtualHosts."radio.r" = {
+ locations."/".extraConfig = ''
+ # https://github.com/aswild/icecast-notes#core-nginx-config
+ proxy_pass http://localhost:8000;
+ # Disable request size limit, very important for uploading large files
+ client_max_body_size 0;
+
+ # Enable support `Transfer-Encoding: chunked`
+ chunked_transfer_encoding on;
+
+ # Disable request and response buffering, minimize latency to/from Icecast
+ proxy_buffering off;
+ proxy_request_buffering off;
+
+ # Icecast needs HTTP/1.1, not 1.0 or 2
+ proxy_http_version 1.1;
+
+ # Forward all original request headers
+ proxy_pass_request_headers on;
+
+ # Set some standard reverse proxy headers. Icecast server currently ignores these,
+ # but may support them in a future version so that access logs are more useful.
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ # get source ip for weather reports
+ proxy_set_header user-agent "$http_user_agent; client-ip=$remote_addr";
+ '';
+ locations."= /recent".extraConfig = ''
+ default_type "text/plain";
+ alias /var/lib/radio/recent;
+ '';
+ locations."= /curr