#+title: musicfs * Incus server VM ~musicfs-server~ (gRPC) runs inside an Incus VM, live-sharing the host's ~~/Music~ as a readonly virtiofs mount. =scripts/vm.sh= builds the binary on the host, bundles its nix ~glibc~ so it runs unmodified in the VM, ships it in, and runs it under systemd. ** Setup #+begin_src bash devenv shell # cargo, incus, patchelf, grpcurl scripts/vm.sh up # create VM, share ~/Music, build, ship, start server #+end_src Options (env): =VM_NAME=, =IMAGE=, =MUSIC_SOURCE=, =LISTEN_PORT=, =RUST_LOG=. | Command | Action | |--------------------------+-------------------------------| | =scripts/vm.sh up= | create + build + ship + start | | =scripts/vm.sh redeploy= | rebuild after a code change | | =scripts/vm.sh logs= | tail server logs | | =scripts/vm.sh status= | VM + service status | | =scripts/vm.sh shell= | shell inside the VM | | =scripts/vm.sh down= | stop the VM | | =scripts/vm.sh destroy= | delete the VM | ** Test it (Nushell) #+begin_src nushell let VMIP = (incus list musicfs -f csv -c 4 | lines | first | split row " " | first) let ADDR = $"($VMIP):50051" # liveness ^nc -z -w 3 $VMIP 50051 if $env.LAST_EXIT_CODE == 0 { print "alive" } else { print "dead" } # gRPC: stream the manifest, count entries grpcurl -plaintext -import-path proto -proto musicfs.proto -d "{}" $ADDR musicfs.MusicFs/GetManifest | lines | find relPath | length # files the server scans incus exec musicfs -- find /music -type f | lines | length # play a track straight out of the VM's shared /music incus exec musicfs -- cat "/music/DDT/ДДТ - Творчество в пустоте – 2 - 01 Intro.flac" | ^mpv - #+end_src Reach the server at the VM's bridge IP (=scripts/vm.sh status= prints it). Install mpv with =nix profile install nixpkgs#mpv=, or use =^ffplay -= instead. In Nushell, always put =| lines= between an external command's stdout and a builtin (=find=, =first=, =length=, ...); external-to-external pipes (=cat | mpv=) are byte-stable and don't need it.