This repository has no description
0

Configure Feed

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

superconfig / configs / services / radio / default.nix
9.4 kB 289 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 skip_track = pkgs.writers.writeBashBin "skip_track" '' 15 set -eu 16 17 # TODO come up with new rating, without moving files 18 # current_track=$(${pkgs.curl}/bin/curl -fSs http://localhost:8002/current | ${pkgs.jq}/bin/jq -r .filename) 19 # track_infos=$(${print_current}/bin/print_current) 20 # skip_count=$(${pkgs.attr}/bin/getfattr -n user.skip_count --only-values "$current_track" || echo 0) 21 # if [[ "$current_track" =~ .*/the_playlist/music/.* ]] && [ "$skip_count" -le 2 ]; then 22 # skip_count=$((skip_count+1)) 23 # ${pkgs.attr}/bin/setfattr -n user.skip_count -v "$skip_count" "$current_track" 24 # echo skipping: "$track_infos" skip_count: "$skip_count" 25 # else 26 # mkdir -p "$music_dir"/the_playlist/.graveyard/ 27 # mv "$current_track" "$music_dir"/the_playlist/.graveyard/ 28 # echo killing: "$track_infos" 29 # fi 30 ${pkgs.curl}/bin/curl -fSs -X POST http://localhost:8002/skip | 31 ${pkgs.jq}/bin/jq -r '.filename' 32 ''; 33 34 good_track = pkgs.writers.writeBashBin "good_track" '' 35 set -eu 36 37 current_track=$(${pkgs.curl}/bin/curl -fSs http://localhost:8002/current | ${pkgs.jq}/bin/jq -r .filename) 38 track_infos=$(${print_current}/bin/print_current) 39 # TODO come up with new rating, without moving files 40 # if [[ "$current_track" =~ .*/the_playlist/music/.* ]]; then 41 # ${pkgs.attr}/bin/setfattr -n user.skip_count -v 0 "$current_track" 42 # else 43 # mv "$current_track" "$music_dir"/the_playlist/music/ || : 44 # fi 45 echo good: "$track_infos" 46 ''; 47 48 print_current = pkgs.writers.writeDashBin "print_current" '' 49 file=$(${pkgs.curl}/bin/curl -fSs http://localhost:8002/current | 50 ${pkgs.jq}/bin/jq -r '.filename' | 51 ${pkgs.gnused}/bin/sed 's,^${music_dir},,' 52 ) 53 link=$(${pkgs.curl}/bin/curl http://localhost:8002/current | 54 ${pkgs.jq}/bin/jq -r '.filename' | 55 ${pkgs.gnused}/bin/sed 's@.*\(.\{11\}\)\.ogg@https://youtu.be/\1@' 56 ) 57 echo "$file": "$link" 58 ''; 59 60 # nginx location running a track script through fcgiwrap 61 trackAction = script: '' 62 limit_except POST { deny all; } 63 include ${config.services.nginx.package}/conf/fastcgi_params; 64 fastcgi_param SCRIPT_FILENAME ${pkgs.writers.writeDash "${script.name}-cgi" '' 65 printf 'Content-Type: text/plain; charset=UTF-8\r\n\r\n' 66 ${script}/bin/${script.name} 67 ''}; 68 fastcgi_pass unix:${config.services.fcgiwrap.instances.radio.socket.address}; 69 ''; 70 71in 72{ 73 imports = [ 74 ./news.nix 75 ./weather.nix 76 ]; 77 78 users.users = { 79 "${name}" = rec { 80 inherit name; 81 isSystemUser = true; 82 createHome = true; 83 group = name; 84 description = "radio manager"; 85 home = "/home/${name}"; 86 useDefaultShell = true; 87 openssh.authorizedKeys.keys = [ 88 self.keys.ssh.barnacle.public 89 self.keys.ssh.yubi_pgp.public 90 self.keys.ssh.termux_massulus.public 91 self.keys.ssh.yubi1.public 92 self.keys.ssh.yubi2.public 93 self.keys.ssh.solo2.public 94 ]; 95 packages = [ 96 good_track 97 skip_track 98 print_current 99 ]; 100 }; 101 }; 102 103 users.groups = { 104 "radio" = { }; 105 }; 106 107 systemd.services.radio_watcher = { 108 wantedBy = [ "multi-user.target" ]; 109 after = [ "radio.service" ]; 110 serviceConfig = { 111 ExecStart = pkgs.writers.writeDash "radio_watcher" '' 112 set -efux 113 while :; do 114 ${pkgs.curl}/bin/curl -Ss http://localhost:8000/radio.ogg -o /dev/null 115 ${pkgs.systemd}/bin/systemctl restart radio 116 sleep 60 117 done 118 ''; 119 Restart = "on-failure"; 120 }; 121 }; 122 123 services.liquidsoap.streams.radio = ./radio.liq; 124 systemd.services.radio = { 125 environment = { 126 RADIO_PORT = "8002"; 127 HOOK_TRACK_CHANGE = pkgs.writers.writeDash "on_change" '' 128 set -xefu 129 LIMIT=100000 #how many tracks to keep in the history 130 HISTORY_FILE=/var/lib/radio/recent 131 132 listeners=$(${pkgs.curl}/bin/curl -fSs http://localhost:8000/status-json.xsl | 133 ${pkgs.jq}/bin/jq '[.icestats.source[].listeners] | add' || echo 0) 134 echo "$(${pkgs.coreutils}/bin/date -Is)" "$filename" | ${pkgs.coreutils}/bin/tee -a "$HISTORY_FILE" 135 echo "$(${pkgs.coreutils}/bin/tail -$LIMIT "$HISTORY_FILE")" > "$HISTORY_FILE" 136 ''; 137 MUSIC = "${music_dir}/the_playlist"; 138 ICECAST_HOST = "localhost"; 139 }; 140 path = [ 141 pkgs.bubblewrap 142 ]; 143 serviceConfig.User = lib.mkForce "radio"; 144 }; 145 146 nixpkgs.config.packageOverrides = opkgs: { 147 liquidsoap = opkgs.liquidsoap.override { 148 runtimePackages = with opkgs; [ 149 bubblewrap 150 curl 151 ffmpeg 152 ]; 153 }; 154 icecast = opkgs.icecast.overrideAttrs (old: rec { 155 version = "2.5-beta3"; 156 157 src = pkgs.fetchurl { 158 url = "http://downloads.xiph.org/releases/icecast/icecast-${version}.tar.gz"; 159 sha256 = "sha256-4FDokoA9zBDYj8RAO/kuTHaZ6jZYBLSJZiX/IYFaCW8="; 160 }; 161 162 NIX_CFLAGS_COMPILE = "-Wno-error=implicit-function-declaration"; 163 164 buildInputs = old.buildInputs ++ [ pkgs.pkg-config ]; 165 }); 166 }; 167 services.icecast = { 168 enable = true; 169 hostname = "radio.lassul.us"; 170 admin.password = "hackme"; 171 extraConf = '' 172 <authentication> 173 <source-password>hackme</source-password> 174 <admin-user>admin</admin-user> 175 <admin-password>hackme</admin-password> 176 </authentication> 177 <logging> 178 <accesslog>-</accesslog> 179 <errorlog>-</errorlog> 180 <loglevel>3</loglevel> 181 </logging> 182 <mount type="normal"> 183 <mount-name>/radio.badge</mount-name> 184 <queue-size>2048000</queue-size> 185 <burst-size>128000</burst-size> 186 </mount> 187 ''; 188 }; 189 # the 2.5 beta has segfaulted before; the module sets no Restart= 190 systemd.services.icecast.serviceConfig.Restart = "on-failure"; 191 192 networking.firewall.interfaces.retiolum.allowedTCPPorts = [ 193 8002 194 ]; 195 196 # POST /skip and /good, run as radio by fcgiwrap 197 services.fcgiwrap.instances.radio = { 198 process.user = name; 199 process.group = name; 200 socket.user = config.services.nginx.user; 201 socket.group = config.services.nginx.group; 202 }; 203 204 networking.firewall.allowedTCPPorts = [ 205 80 206 8000 207 ]; 208 services.nginx = { 209 enable = true; 210 virtualHosts."radio.r" = { 211 locations."/".extraConfig = '' 212 # https://github.com/aswild/icecast-notes#core-nginx-config 213 proxy_pass http://localhost:8000; 214 # Disable request size limit, very important for uploading large files 215 client_max_body_size 0; 216 217 # Enable support `Transfer-Encoding: chunked` 218 chunked_transfer_encoding on; 219 220 # Disable request and response buffering, minimize latency to/from Icecast 221 proxy_buffering off; 222 proxy_request_buffering off; 223 224 # Icecast needs HTTP/1.1, not 1.0 or 2 225 proxy_http_version 1.1; 226 227 # Forward all original request headers 228 proxy_pass_request_headers on; 229 230 # Set some standard reverse proxy headers. Icecast server currently ignores these, 231 # but may support them in a future version so that access logs are more useful. 232 proxy_set_header Host $host; 233 proxy_set_header X-Real-IP $remote_addr; 234 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 235 proxy_set_header X-Forwarded-Proto $scheme; 236 237 # get source ip for weather reports 238 proxy_set_header user-agent "$http_user_agent; client-ip=$remote_addr"; 239 ''; 240 locations."= /recent".extraConfig = '' 241 default_type "text/plain"; 242 alias /var/lib/radio/recent; 243 ''; 244 locations."= /current".extraConfig = '' 245 proxy_pass http://localhost:8002; 246 ''; 247 locations."= /skip".extraConfig = trackAction skip_track; 248 locations."= /good".extraConfig = trackAction good_track; 249 locations."= /radio.sh".alias = pkgs.writeScript "radio.sh" '' 250 #!/bin/sh 251 trap 'exit 0' EXIT 252 while sleep 1; do 253 mpv \ 254 --cache-secs=0 --demuxer-readahead-secs=0 --untimed --cache-pause=no \ 255 'http://radio.lassul.us/radio.ogg' 256 done 257 ''; 258 locations."= /controls".extraConfig = '' 259 default_type "text/html"; 260 alias ${./controls.html}; 261 ''; 262 extraConfig = '' 263 add_header 'Access-Control-Allow-Origin' '*'; 264 add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS'; 265 ''; 266 }; 267 }; 268 services.syncthing.settings.folders."/home/lass/tmp/the_playlist" = { 269 path = lib.mkForce "/var/music/the_playlist"; 270 devices = [ 271 "mors" 272 "radio" 273 ]; 274 }; 275 # lass and radio manage the playlist. The default ACL hands rw on new 276 # files and rwx on new directories to both (files are created without x, 277 # so the mask drops it); existing content keeps the ACLs it already has. 278 # No X: tmpfiles applies it to existing files with an r-- mask. 279 systemd.tmpfiles.settings."10-the-playlist" = { 280 "/var/music/the_playlist" = { 281 d = { }; 282 "a+".argument = "u:lass:rwx,u:radio:rwx"; 283 "A+".argument = "d:u:lass:rwx,d:u:radio:rwx"; 284 }; 285 # traverse down to the playlist 286 "/var/music"."a+".argument = "u:lass:x"; 287 "/var"."a+".argument = "u:lass:x"; 288 }; 289}