Euterpe
Overview
Euterpe is a self-hosted music streaming server. It indexes a music library you already own, reads the tags and cover art from your own files, and streams them back through a browser player, a documented REST API and a Subsonic-compatible API that works with many third-party mobile clients. You can browse and search by artist, album or track, play in the browser, build playlists, download a whole album as a zip, and pair devices with a QR code.
This SecureAnyCloud image builds Euterpe v1.6.3 from the pinned upstream release tag against the operating system's own audio tagging and Unicode libraries, and puts it behind an nginx reverse proxy. The image is secure by default. Nothing listens on the public port as shipped, and the server does not start until euterpe-firstboot.service has generated this machine's own administrator password and token signing secret. Only then does the public site open.
The music library ships empty, on purpose. This is a server for music you already own, and no recordings of any kind are included in or distributed with this image. Copy your own files into /var/lib/euterpe/music, or point the configuration at a disk you attach, and Euterpe indexes them automatically.
What you get:
- Euterpe v1.6.3, a single Go binary at
/usr/local/bin/euterpewith the web player, the SQL migrations and the HTML templates embedded inside it - A SQLite library index at
/var/lib/euterpe/euterpe.db, created on first scan, with no separate database to maintain - An empty music library directory at
/var/lib/euterpe/music, ready for your own files euterpe.servicerunning as theeuterpeuser, bound to loopback127.0.0.1:9996nginx.serviceas a reverse proxy on TCP 80, TLS ready, passing Range requests straight through so seeking workseuterpe-firstboot.service, which generates a per-VM administrator password and a per-VM token signing secret on first boot- A REST API with HTTP Basic and bearer token authentication, and a Subsonic-compatible API for third-party mobile players
- The GNU GPL v3 licence, a written offer for the corresponding source and full third-party notices in
/usr/share/doc/euterpe - An Ubuntu 24.04 LTS base with the latest patches and unattended security upgrades enabled
- 24/7 SecureAnyCloud support with a 24-hour response SLA
Prerequisites
You need an active Azure subscription, an SSH key and a VNet with a subnet.
The recommended VM size is Standard_B2s. Euterpe is very light. The size you need depends on how much disk your music library takes, not on CPU or memory.
Deploy from the Azure Portal
Search the Azure Marketplace for Euterpe, choose the plan and create the VM. In the networking step, attach an NSG that allows inbound TCP 22 (SSH) and TCP 80 (the web player) from your client networks only. Put a TLS certificate in front of port 80 before you use the player over the internet (Step 16).
If your library is large, add a data disk when you create the VM and mount it. Then point Euterpe at that mount in Step 6.
Deploy from the Azure CLI
RG="euterpe-prod"; LOCATION="eastus"; VM_NAME="euterpe-01" IMAGE_URN="sac1647283583153:euterpe-ubuntu-24-04:default:latest"
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:euterpe-ubuntu-24-04:default:latest
az vm create \
--resource-group "$RG" --name "$VM_NAME" --location "$LOCATION" \
--image "$IMAGE_URN" --size Standard_B2s \
--admin-username azureuser --generate-ssh-keys \
--public-ip-sku Standard
# then open TCP 80 to your own client network only:
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 80 --priority 900Connect via SSH
ssh azureuser@<vm-ip>On first boot, euterpe-firstboot.service, euterpe.service and nginx.service start automatically, in that order.
Verify the service
Check the units, the first-boot sentinel and the listeners:
sudo systemctl is-active euterpe nginx euterpe-firstboot
sudo test -f /var/lib/sac/data/euterpe-firstboot.done && echo FIRSTBOOT_DONE
sudo ss -tlnH | awk '$4 ~ /:80$|:9996$/ {print $1, $4}' | sortAll three units are active and the first-boot sentinel is present. The listeners show the split that matters. nginx is the only service on the public port 80, while Euterpe itself is reachable only on loopback 127.0.0.1:9996.
active active active FIRSTBOOT_DONE LISTEN 0.0.0.0:80 LISTEN 127.0.0.1:9996 LISTEN [::]:80Get your login credentials
There is no default password. On first boot, this machine generates its own administrator password and token signing secret, writes them into the configuration, and only then opens the public site. Read the instance note:
sudo cat /root/euterpe-info.txtThe note holds the username, the password and the URL. All of them are unique to this VM, and none is baked into the image:
# Euterpe on Ubuntu 24.04 - Per-VM Instance Info
# EUTERPE_ADMIN_USERNAME=admin EUTERPE_ADMIN_PASSWORD=<EUTERPE_ADMIN_PASSWORD> EUTERPE_URL=http://10.0.0.10/ EUTERPE_LIBRARY_PATH=/var/lib/euterpe/musicNext, confirm that every entry point is gated. An anonymous browser request is redirected to the login page, an anonymous API call is refused, and only this machine's own credentials are accepted:
curl -s -o /dev/null -w 'web UI, no credentials -> HTTP %{http_code}\n' -H 'Accept: text/html' http://127.0.0.1/
curl -s -o /dev/null -w 'REST API, no credentials -> HTTP %{http_code}\n' -H 'Accept: application/json' http://127.0.0.1/v1/about
P=$(sudo grep '^EUTERPE_ADMIN_PASSWORD=' /root/euterpe-info.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'REST API, this VM login -> HTTP %{http_code}\n' -u "admin:$P" http://127.0.0.1/v1/aboutweb UI, no credentials -> HTTP 302 REST API, no credentials -> HTTP 401 REST API, this VM login -> HTTP 200The EUTERPE_URL line uses the address the VM sees for itself. To reach the player, browse to your VM's public IP address.
Add your own music
The library directory ships empty. It is owned by the euterpe service user, and it is where Euterpe looks for your files:
ls -ld /var/lib/euterpe/music
sudo -u euterpe test -w /var/lib/euterpe/music && echo "writable by the euterpe service user"drwxr-xr-x 2 euterpe euterpe 4096 Aug 7 13:16 /var/lib/euterpe/music writable by the euterpe service userCopy your own audio from your workstation. Run these commands on your own machine, not on the VM:
# a single album scp -r "/path/to/your/music/Some Album" azureuser@<vm-ip>:/tmp/
# or a whole library, resumable rsync -av --progress "/path/to/your/music/" azureuser@<vm-ip>:/tmp/incoming/Then, on the VM, move the files into the library and give ownership to the service user:
sudo mkdir -p /var/lib/euterpe/music
#
sudo mv /tmp/incoming/* /var/lib/euterpe/music/
sudo chown -R euterpe:euterpe /var/lib/euterpe/music
sudo find /var/lib/euterpe/music -type d -exec chmod 0755 {} +
sudo find /var/lib/euterpe/music -type f -exec chmod 0644 {} +Euterpe watches the library directories, so it picks up new files without a restart. Confirm what is indexed through the API:
P=$(sudo grep '^EUTERPE_ADMIN_PASSWORD=' /root/euterpe-info.txt | cut -d= -f2-)
curl -s -u "admin:$P" 'http://127.0.0.1/v1/browse?by=artist'On a freshly deployed VM, the library is empty, as shipped, and the API reports that:
{"data":null,"next":"","previous":"","pages_count":0}Once your files are in place, the same call lists your artists.
To keep your music somewhere else, for example on a mounted data disk, add that path to the libraries list in /etc/euterpe/config.json and restart the service. Euterpe reads MP3, FLAC, OGG, M4A, WAV and Opus. It takes the artist, album, track number and embedded cover art from the tags in your files.
Sign in to the web player
Open http://<vm-ip>/ in a browser. Anonymous requests are redirected to the login page. Enter the username admin and the password from Step 5.
Browse your library
After you sign in, the player shows a search box across the top, an artist list and an album list, an artwork panel, the transport controls, and the playlist underneath. Choose Load All Music to pull the whole library into the playlist, or filter with the artist and album lists first.
The screenshots in this guide use a library of synthetic audio tones that SecureAnyCloud generated for documentation, so that the interface can be shown populated. Your VM ships with an empty library and shows your own music once you copy it in.
Play a track
Click any track in the playlist to start streaming it immediately. The progress bar fills, the elapsed and total time count along, and the transport switches to a pause button.
Use the previous, next and stop buttons, the volume slider, and the shuffle and repeat toggles to control playback. Because nginx passes Range requests straight through, dragging the progress bar seeks within the track instead of restarting it.
Search and filter
Type into the search box to match across track, album and artist names. Or narrow the playlist by selecting an artist and then an album. The artwork panel shows the cover art embedded in your own files and falls back to a default image when a track has none.
Use the REST API
Euterpe has a documented, stable REST API behind the same login. It accepts HTTP Basic credentials. You can also exchange them once for a bearer token, which suits scripts and long-lived device sign-ins.
P=$(sudo grep '^EUTERPE_ADMIN_PASSWORD=' /root/euterpe-info.txt | cut -d= -f2-)
curl -s -u "admin:$P" http://127.0.0.1/v1/about
TOK=$(curl -s -H 'Content-Type: application/json' \
--data "{\"username\":\"admin\",\"password\":\"$P\"}" \
http://127.0.0.1/v1/login/token/ | python3 -c 'import json,sys;print(json.load(sys.stdin)["token"])')
echo "token length: ${#TOK}" curl -s -o /dev/null -w 'with the token -> HTTP %{http_code}\n' -H "Authorization: Bearer $TOK" http://127.0.0.1/v1/about curl -s -o /dev/null -w 'with a forged token -> HTTP %{http_code}\n' -H 'Accept: application/json' -H 'Authorization: Bearer forged' http://127.0.0.1/v1/aboutA real token is accepted and anything else is refused, because tokens are signed with the secret that this VM generated for itself on first boot:
{"server_version":"v1.6.3"} token length: 128 with the token -> HTTP 200 with a forged token -> HTTP 401The full endpoint reference is on the VM at /usr/share/doc/euterpe/API.md. It covers search, browse, streaming a track, downloading an album as a zip, album artwork, artist images and playlists.
Connect a Subsonic mobile player
Euterpe also speaks the Subsonic API, so most third-party Subsonic clients on phones, tablets and desktops can play your library. Point the client at http://<vm-ip>/rest/ with the username and password from Step 5. First, check the endpoint from the VM:
P=$(sudo grep '^EUTERPE_ADMIN_PASSWORD=' /root/euterpe-info.txt | cut -d= -f2-)
curl -s "http://127.0.0.1/rest/ping.view?v=1.16.1&c=sac&f=json&u=admin&p=$P"{ "subsonic-response": { "status": "ok", "version": "1.16.1", "type": "euterpe", "serverVersion": "v1.6.3", "openSubsonic": true } }This API is authenticated too. Without credentials, or with the wrong ones, the same call returns a failed status. Add TLS (Step 16) before you point a phone at the server over the internet, because Subsonic clients send the credentials with every request.
Server components and configuration
Everything the image installs lives in a handful of predictable paths:
/usr/local/bin/euterpe -v ls -1 /usr/local/bin/euterpe /etc/euterpe/config.json /etc/systemd/system/euterpe.service \
/usr/local/sbin/euterpe-firstboot.sh /etc/nginx/sites-available/sac-euterpe ls -1 /usr/share/doc/euterpe/Euterpe Media Server v1.6.3 Build with go1.24.13 /etc/euterpe/config.json /etc/nginx/sites-available/sac-euterpe /etc/systemd/system/euterpe.service /usr/local/bin/euterpe /usr/local/sbin/euterpe-firstboot.sh API.md CHANGELOG.md LICENSE LICENSE.go-taglib README.md SOURCE-OFFER.txt THIRD-PARTY-NOTICES.txtThe configuration that this VM generated for itself looks like this, with the two secrets redacted:
{ "listen": "127.0.0.1:9996", "ssl": false, "basic_authenticate": true, "authentication": { "user": "admin", "password": "<EUTERPE_ADMIN_PASSWORD>", "secret": "<128-hex-signing-secret-generated-on-this-vm>" }, "libraries": [ "/var/lib/euterpe/music" ], "sqlite_database": "/var/lib/euterpe/euterpe.db", "log_file": "/var/log/euterpe/euterpe.log", "download_artwork": false }basic_authenticate must stay true. This setting puts the login in front of the web player, the REST API and the Subsonic API.
To have Euterpe fetch missing cover art and artist images from the Cover Art Archive and Discogs, set download_artwork to true and optionally add a discogs_auth_token. It is off by default, so a fresh instance makes no outbound requests.
Change the administrator password
The password lives in /etc/euterpe/config.json. Set a new one and restart the service:
sudo python3 - <<'PY' import json, getpass p = "/etc/euterpe/config.json" c = json.load(open(p)) c["authentication"]["password"] = "<new-password>" json.dump(c, open(p, "w"), indent=4) PY
sudo systemctl restart euterpeReplace <new-password> with your own value before you run the command. Update /root/euterpe-info.txt if you rely on that note, and store the new password in your own secret manager.
Existing API tokens keep working, because they are signed with the separate signing secret. To invalidate every issued token, change the secret value in the same file and restart the service.
Manage the service
Check the status, restart the service and read the logs with:
sudo systemctl status euterpe --no-pager sudo systemctl restart euterpe
sudo journalctl -u euterpe -n 50 --no-pagerEuterpe is a simple systemd service with Restart=always, so it restarts automatically after a crash or a reboot. It runs as the unprivileged euterpe user with ProtectSystem=strict and can write only to /var/lib/euterpe and /var/log/euterpe.
If the service refuses to start, check that /etc/euterpe/config.json and /var/lib/euterpe/.bootstrap-ready both exist. The unit deliberately does not run without them, which stops the image from serving before it has generated a credential of its own.
Add TLS
For anything reachable from the internet, terminate TLS in front of port 80. The reverse proxy is already in place at /etc/nginx/sites-available/sac-euterpe. Add a certificate for your own domain name with certbot:
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d music.example.comCertbot edits the existing server block in place and sets up automatic renewal. Then browse to https://music.example.com/, and point any Subsonic client at the same HTTPS URL.
Back up the instance
Two things are worth backing up, and they are separate concerns. Back up the library index and the configuration with:
sudo systemctl stop euterpe
sudo cp /var/lib/euterpe/euterpe.db /var/backups/euterpe.db.$(date +%F)
sudo cp /etc/euterpe/config.json /var/backups/euterpe-config.json.$(date +%F)
sudo systemctl start euterpe ls -1 /var/backups/ | headeuterpe.db holds the library index, your playlists and any artwork you uploaded through the interface. config.json holds your credentials and signing secret.
The music files in /var/lib/euterpe/music are your own master copies. Back them up with whatever you already use for your media, or keep them on a data disk that you snapshot.
Licensing
Euterpe is free software distributed under the GNU General Public License version 3. This image ships an unmodified build of the tagged upstream release. SecureAnyCloud has not patched or forked it. The full licence text is at /usr/share/doc/euterpe/LICENSE. A written offer for the corresponding source, with the exact tag, commit and build settings, is at /usr/share/doc/euterpe/SOURCE-OFFER.txt. Every bundled third-party component is listed in /usr/share/doc/euterpe/THIRD-PARTY-NOTICES.txt.
This is a repackaged open-source software product with additional charges for SecureAnyCloud support services. SecureAnyCloud is not affiliated with, endorsed by or sponsored by the Euterpe project. All product and company names are trademarks or registered trademarks of their respective holders, and their use does not imply any affiliation with or endorsement by them.
No music is included with this image. Euterpe is a server for a library you already own, and nothing in this image grants any rights in any recording. You are responsible for holding the rights to whatever you put in your library.
Support
24/7 support with a 24-hour response SLA is included with this image. Email sales@secureanycloud.com and quote the offer name and your VM's resource ID.
Deploy on Azure
Launch Euterpe on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com