This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

superconfig / 2configs / services / radio / default.nix
9.7 kB 314 lines
1{ 2 self, 3 config, 4 pkgs, 5 lib, 6 ... 7}: 8 9let 10 name = "radio"; 11 12 music_dir = "/var/music"; 13 14 # dash 0.5.13 has a regression where `read` builtin discards input when stdin is a socket 15 # This breaks htgen which uses tcpserver. Pin htgen's dash to 0.5.12 until upstream fixes it. 16 # See: https://git.kernel.org/pub/scm/utils/dash/dash.git/commit/?id=1d072e9c3292281a7eee54c41fec117ff22723e5 17 dash-0_5_12 = pkgs.dash.overrideAttrs (old: rec { 18 version = "0.5.12"; 19 src = pkgs.fetchurl { 20 url = "http://gondor.apana.org.au/~herbert/dash/files/dash-${version}.tar.gz"; 21 hash = "sha256-akdKxG6LCzKRbExg32lMggWNMpfYs4W3RQgDDKSo8oo="; 22 }; 23 }); 24 25 htgen-fixed = pkgs.htgen.override { 26 pkgs = pkgs // { dash = dash-0_5_12; }; 27 }; 28 29 skip_track = pkgs.writers.writeBashBin "skip_track" '' 30 set -eu 31 32 # TODO come up with new rating, without moving files 33 # current_track=$(${pkgs.curl}/bin/curl -fSs http://localhost:8002/current | ${pkgs.jq}/bin/jq -r .filename) 34 # track_infos=$(${print_current}/bin/print_current) 35 # skip_count=$(${pkgs.attr}/bin/getfattr -n user.skip_count --only-values "$current_track" || echo 0) 36 # if [[ "$current_track" =~ .*/the_playlist/music/.* ]] && [ "$skip_count" -le 2 ]; then 37 # skip_count=$((skip_count+1)) 38 # ${pkgs.attr}/bin/setfattr -n user.skip_count -v "$skip_count" "$current_track" 39 # echo skipping: "$track_infos" skip_count: "$skip_count" 40 # else 41 # mkdir -p "$music_dir"/the_playlist/.graveyard/ 42 # mv "$current_track" "$music_dir"/the_playlist/.graveyard/ 43 # echo killing: "$track_infos" 44 # fi 45 ${pkgs.curl}/bin/curl -fSs -X POST http://localhost:8002/skip | 46 ${pkgs.jq}/bin/jq -r '.filename' 47 ''; 48 49 good_track = pkgs.writeBashBin "good_track" '' 50 set -eu 51 52 current_track=$(${pkgs.curl}/bin/curl -fSs http://localhost:8002/current | ${pkgs.jq}/bin/jq -r .filename) 53 track_infos=$(${print_current}/bin/print_current) 54 # TODO come up with new rating, without moving files 55 # if [[ "$current_track" =~ .*/the_playlist/music/.* ]]; then 56 # ${pkgs.attr}/bin/setfattr -n user.skip_count -v 0 "$current_track" 57 # else 58 # mv "$current_track" "$music_dir"/the_playlist/music/ || : 59 # fi 60 echo good: "$track_infos" 61 ''; 62 63 print_current = pkgs.writeDashBin "print_current" '' 64 file=$(${pkgs.curl}/bin/curl -fSs http://localhost:8002/current | 65 ${pkgs.jq}/bin/jq -r '.filename' | 66 ${pkgs.gnused}/bin/sed 's,^${music_dir},,' 67 ) 68 link=$(${pkgs.curl}/bin/curl http://localhost:8002/current | 69 ${pkgs.jq}/bin/jq -r '.filename' | 70 ${pkgs.gnused}/bin/sed 's@.*\(.\{11\}\)\.ogg@https://youtu.be/\1@' 71 ) 72 echo "$file": "$link" 73 ''; 74 75in 76{ 77 imports = [ 78 ./news.nix 79 ./weather.nix 80 self.inputs.stockholm.nixosModules.acl 81 # self.inputs.stockholm.nixosModules.reaktor2 82 ]; 83 84 users.users = { 85 "${name}" = rec { 86 inherit name; 87 createHome = true; 88 group = name; 89 uid = pkgs.stockholm.lib.genid_uint31 name; 90 description = "radio manager"; 91 home = "/home/${name}"; 92 useDefaultShell = true; 93 openssh.authorizedKeys.keys = [ 94 self.keys.ssh.barnacle.public 95 self.keys.ssh.yubi_pgp.public 96 self.keys.ssh.yubi1.public 97 self.keys.ssh.yubi2.public 98 self.keys.ssh.solo2.public 99 ]; 100 packages = [ 101 good_track 102 skip_track 103 print_current 104 ]; 105 }; 106 }; 107 108 users.groups = { 109 "radio" = { }; 110 }; 111 112 systemd.services.radio_watcher = { 113 wantedBy = [ "multi-user.target" ]; 114 after = [ "radio.service" ]; 115 serviceConfig = { 116 ExecStart = pkgs.writers.writeDash "radio_watcher" '' 117 set -efux 118 while :; do 119 ${pkgs.curl}/bin/curl -Ss http://localhost:8000/radio.ogg -o /dev/null 120 ${pkgs.systemd}/bin/systemctl restart radio 121 sleep 60 122 done 123 ''; 124 Restart = "on-failure"; 125 }; 126 }; 127 128 services.liquidsoap.streams.radio = ./radio.liq; 129 systemd.services.radio = { 130 environment = { 131 RADIO_PORT = "8002"; 132 HOOK_TRACK_CHANGE = pkgs.writers.writeDash "on_change" '' 133 set -xefu 134 LIMIT=1000 #how many tracks to keep in the history 135 HISTORY_FILE=/var/lib/radio/recent 136 137 listeners=$(${pkgs.curl}/bin/curl -fSs http://localhost:8000/status-json.xsl | 138 ${pkgs.jq}/bin/jq '[.icestats.source[].listeners] | add' || echo 0) 139 echo "$(${pkgs.coreutils}/bin/date -Is)" "$filename" | ${pkgs.coreutils}/bin/tee -a "$HISTORY_FILE" 140 echo "$(${pkgs.coreutils}/bin/tail -$LIMIT "$HISTORY_FILE")" > "$HISTORY_FILE" 141 ''; 142 MUSIC = "${music_dir}/the_playlist"; 143 ICECAST_HOST = "localhost"; 144 }; 145 path = [ 146 pkgs.yt-dlp 147 pkgs.bubblewrap 148 ]; 149 serviceConfig.User = lib.mkForce "radio"; 150 }; 151 152 nixpkgs.config.packageOverrides = opkgs: { 153 liquidsoap = opkgs.liquidsoap.override { 154 runtimePackages = with opkgs; [ 155 bubblewrap 156 curl 157 ffmpeg 158 yt-dlp 159 ]; 160 }; 161 icecast = opkgs.icecast.overrideAttrs (old: rec { 162 version = "2.5-beta3"; 163 164 src = pkgs.fetchurl { 165 url = "http://downloads.xiph.org/releases/icecast/icecast-${version}.tar.gz"; 166 sha256 = "sha256-4FDokoA9zBDYj8RAO/kuTHaZ6jZYBLSJZiX/IYFaCW8="; 167 }; 168 169 NIX_CFLAGS_COMPILE = "-Wno-error=implicit-function-declaration"; 170 171 buildInputs = old.buildInputs ++ [ pkgs.pkg-config ]; 172 }); 173 }; 174 services.icecast = { 175 enable = true; 176 hostname = "radio.lassul.us"; 177 admin.password = "hackme"; 178 extraConf = '' 179 <authentication> 180 <source-password>hackme</source-password> 181 <admin-user>admin</admin-user> 182 <admin-password>hackme</admin-password> 183 </authentication> 184 <logging> 185 <accesslog>-</accesslog> 186 <errorlog>-</errorlog> 187 <loglevel>3</loglevel> 188 </logging> 189 <mount type="normal"> 190 <mount-name>/radio.badge</mount-name> 191 <queue-size>2048000</queue-size> 192 <burst-size>128000</burst-size> 193 </mount> 194 ''; 195 }; 196 197 networking.firewall.interfaces.retiolum.allowedTCPPorts = [ 198 8001 199 8002 200 ]; 201 202 krebs.htgen.radio = { 203 package = htgen-fixed; 204 port = 8001; 205 user = { 206 name = "radio"; 207 }; 208 scriptFile = pkgs.writeDash "radio" '' 209 set -x 210 case "''${Method:-} ''${Request_URI:-}" in 211 "POST /skip") 212 printf 'HTTP/1.1 200 OK\r\n' 213 printf 'Connection: close\r\n' 214 printf '\r\n' 215 msg=$(${skip_track}/bin/skip_track) 216 echo "$msg" 217 exit 218 ;; 219 "POST /good") 220 printf 'HTTP/1.1 200 OK\r\n' 221 printf 'Connection: close\r\n' 222 printf '\r\n' 223 msg=$(${good_track}/bin/good_track) 224 echo "$msg" 225 exit 226 ;; 227 esac 228 ''; 229 }; 230 231 security.acme.certs."radio.r".server = config.krebs.ssl.acmeURL; 232 233 networking.firewall.allowedTCPPorts = [ 234 80 235 8000 236 ]; 237 services.nginx = { 238 enable = true; 239 virtualHosts."radio.r" = { 240 enableACME = true; 241 addSSL = true; 242 locations."/".extraConfig = '' 243 # https://github.com/aswild/icecast-notes#core-nginx-config 244 proxy_pass http://localhost:8000; 245 # Disable request size limit, very important for uploading large files 246 client_max_body_size 0; 247 248 # Enable support `Transfer-Encoding: chunked` 249 chunked_transfer_encoding on; 250 251 # Disable request and response buffering, minimize latency to/from Icecast 252 proxy_buffering off; 253 proxy_request_buffering off; 254 255 # Icecast needs HTTP/1.1, not 1.0 or 2 256 proxy_http_version 1.1; 257 258 # Forward all original request headers 259 proxy_pass_request_headers on; 260 261 # Set some standard reverse proxy headers. Icecast server currently ignores these, 262 # but may support them in a future version so that access logs are more useful. 263 proxy_set_header Host $host; 264 proxy_set_header X-Real-IP $remote_addr; 265 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 266 proxy_set_header X-Forwarded-Proto $scheme; 267 268 # get source ip for weather reports 269 proxy_set_header user-agent "$http_user_agent; client-ip=$remote_addr"; 270 ''; 271 locations."= /recent".extraConfig = '' 272 default_type "text/plain"; 273 alias /var/lib/radio/recent; 274 ''; 275 locations."= /current".extraConfig = '' 276 proxy_pass http://localhost:8002; 277 ''; 278 locations."= /skip".extraConfig = '' 279 proxy_pass http://localhost:8001; 280 ''; 281 locations."= /good".extraConfig = '' 282 proxy_pass http://localhost:8001; 283 ''; 284 locations."= /radio.sh".alias = pkgs.writeScript "radio.sh" '' 285 #!/bin/sh 286 trap 'exit 0' EXIT 287 while sleep 1; do 288 mpv \ 289 --cache-secs=0 --demuxer-readahead-secs=0 --untimed --cache-pause=no \ 290 'http://radio.lassul.us/radio.ogg' 291 done 292 ''; 293 locations."= /controls".extraConfig = '' 294 default_type "text/html"; 295 alias ${./controls.html}; 296 ''; 297 extraConfig = '' 298 add_header 'Access-Control-Allow-Origin' '*'; 299 add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; 300 ''; 301 }; 302 }; 303 services.syncthing.settings.folders."/home/lass/tmp/the_playlist" = { 304 path = lib.mkForce "/var/music/the_playlist"; 305 devices = [ 306 "mors" 307 "prism" 308 "radio" 309 ]; 310 }; 311 krebs.acl."/var/music/the_playlist"."u:lass:X".parents = true; 312 krebs.acl."/var/music/the_playlist"."u:lass:rwX" = { }; 313 krebs.acl."/var/music/the_playlist"."u:radio:rwX" = { }; 314}