Marcel Benders
DE
← Tonregal

Guide ·

Setting up Tonregal on a Mac from scratch

From an empty Mac with an external SSD to a running library with Navidrome, Tailscale, a nightly Nextcloud backup and the iPhone app, also for restoring after a failure.

Tonregal runs as a service on a Mac at home. The music, the database, the app itself and its logs live on an external SSD so the internal disk stays free. Everything is reachable only through Tailscale, so only by your own devices. This guide walks through the setup in the order in which the parts build on each other. If you are restoring after a disk failure or onto a new Mac, step 4 brings the data back from Nextcloud; everything else is the same.

What you need

  • a Mac with Apple Silicon (the app is built for osx-arm64) that stays on, a Mac mini for example
  • an external SSD for the music, large enough for the whole collection
  • a Tailscale account, with Tailscale on the Mac and on the iPhone
  • a Nextcloud with an app password for the backup
  • a free AcoustID key from acoustid.org for recognition by fingerprint
  • for the iPhone app: access to the TestFlight version or an Apple developer account of your own

1. Prepare the Mac

In the Terminal, install the developer tools, Homebrew and what the build needs:

xcode-select --install
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install git node rclone
brew install --cask dotnet-sdk

Tonregal needs the .NET 10 SDK and Node.js 22 or later; dotnet --version and node --version tell you whether that fits. The rest (Chromaprint, rsgain, uv, ffmpeg, Navidrome) is installed by the scripts later on.

Add Tailscale as an app from the App Store or from tailscale.com. Sign the Mac in to your tailnet and switch on HTTPS Certificates under DNS in the Tailscale admin console, otherwise Tailscale cannot issue a certificate later.

So the Mac does not fall asleep: in System Settings → Energy (Energy Saver on some models), prevent sleep and let it start automatically after a power failure.

2. Set up the SSD

Format the SSD as APFS in Disk Utility and name it T7. The scripts expect everything under /Volumes/T7/Musik:

mkdir -p /Volumes/T7/Musik

A disk with another name works too: then run export MUSIC_ROOT=/Volumes/<name>/Musik before every script and read the paths in this guide accordingly. Naming it T7 is simpler.

Over time these folders appear under Musik:

Folder Contents
Inbox/ new music for Tonregal to recognise and file
Library/ the finished library, written only by Tonregal
Altbestand/ old MP3 copies that Tonregal only reads (optional)
app/ the published app, tonregal.db and your settings
navidrome/ Navidrome's settings and database
logs/, update/, tools/, backups/ logs, the state of automatic updates, analysis tools, database copies taken before every update

3. Get the source

git clone https://github.com/Marcel-B/Tonregal.git ~/repos/Tonregal
cd ~/repos/Tonregal

The checkout stays on main; the automatic updates from step 9 only deploy from there.

4. Bring the data back from the backup (only when restoring)

If you are setting Tonregal up for the first time, skip this step.

First give rclone access to Nextcloud as described in step 8 (rclone config create …), then check that the backup is there:

rclone lsd nextcloud:Musik            # shows Library and _state
rclone lsf --dirs-only nextcloud:Musik/_state

_state/ holds one folder per day with tonregal.db and navidrome.db, for the last seven days. Take the newest and bring back the databases and the library:

stand=$(rclone lsf --dirs-only nextcloud:Musik/_state | sort | tail -n1)
mkdir -p /Volumes/T7/Musik/{app,navidrome,Library}
rclone copy "nextcloud:Musik/_state/$stand" /Volumes/T7/Musik/app/ --include tonregal.db
rclone copy "nextcloud:Musik/_state/$stand" /Volumes/T7/Musik/navidrome/ --include navidrome.db
rclone copy nextcloud:Musik/Library /Volumes/T7/Musik/Library --progress

Depending on its size and your connection, the library can take hours; you can stop the command and start it again, and it carries on where it was. The paths must be the same as before (/Volumes/T7/Musik/…), because Navidrome keeps them as absolute paths in its database.

What comes back: every music file with its tags, covers, lyrics (.lrc) and smart playlists; from tonregal.db the import history, the keys for the ingest interface (for Tonwerk-AI, for example) and the smart playlist rules; from navidrome.db your Navidrome account, stars and play counts. Not in the backup are the inbox, the old collection and appsettings.Production.json; keep its values (AcoustID key, Navidrome password) in your password manager.

If tonregal.db is missing altogether, that is no disaster: the database is only an index, and Tonregal reads the library at start and rebuilds it.

5. Set up Navidrome

Navidrome delivers the audio behind the scenes, counts plays and keeps the stars. Tailscale must already be running, because Navidrome listens on the Mac's Tailscale address:

./deploy/navidrome/setup-navidrome.sh

The script installs Navidrome and ffmpeg, creates the folders, writes navidrome.toml and sets up the service org.navidrome.server.

Full Disk Access: The first time, the service usually does not start because macOS denies it the external SSD. The script then names the program that needs access. In System Settings → Privacy & Security → Full Disk Access, add exactly that path with + (in the file dialog, Cmd+Shift+G takes you to a path) and run the script again. After brew upgrade navidrome the path changes; grant access again then.

At the end the script prints Navidrome's address. Open it in a browser and create the admin user on the first visit. After a restore it already exists.

6. Deploy Tonregal

./deploy/deploy-tonregal.sh

The script installs Chromaprint, rsgain, uv and rclone, creates a Python environment for the tempo and key analysis on the SSD, builds Tonregal with its web interface, copies it to Musik/app and sets up the service de.bvelop.tonregal. Tonregal listens only on http://localhost:5100. At the end the script calls /api/health and stops with a message if Tonregal does not answer. Here, too, access to the SSD may be missing the first time; grant it to the path it names (…/Musik/app/Tonregal.Web) as in step 5 and run the script again.

Your own settings go into /Volumes/T7/Musik/app/appsettings.Production.json. The script leaves this file alone on every update, and it never belongs in the repository:

{
  "Tonregal": {
    "Metadata": { "AcoustIdApiKey": "<your AcoustID key>" },
    "Navidrome": { "User": "<Navidrome admin>", "Password": "<password>" }
  }
}

Without the AcoustID key Tonregal recognises no tracks by fingerprint, without the Navidrome account stars and play counts do not work. After a change, restart the service:

launchctl kickstart -k gui/$(id -u)/de.bvelop.tonregal
curl http://localhost:5100/api/health

7. Make it reachable through Tailscale

Tailscale Serve puts Tonregal into the tailnet with HTTPS:

tailscale serve --bg 5100
tailscale serve status

If the Terminal cannot find tailscale, the program lives inside the app at /Applications/Tailscale.app/Contents/MacOS/Tailscale. Tonregal is then reachable on all your devices in the tailnet at https://<mac-name>.<tailnet>.ts.net, without a port. tailscale serve status shows the exact name. Check it from another device:

curl https://<mac-name>.<tailnet>.ts.net/api/health

Do not put Tonregal on the open internet with tailscale funnel, since the interface has no login of its own. On the iPhone you can add the page to the home screen in Safari through Share → Add to Home Screen and use it like an app.

8. Set up the nightly backup

Every night at 03:00 Tonregal mirrors the library to Nextcloud and puts copies of both databases beside it. In Nextcloud, create a user with an app password who sees only the folder Musik, and give rclone the access. It stays in ~/.config/rclone/rclone.conf on the Mac:

rclone config create nextcloud webdav vendor=nextcloud \
  url=https://<your-nextcloud>/remote.php/dav/files/<user>/ user=<user> pass='<app-password>'
rclone lsd nextcloud:Musik    # must answer without an error

Start a first run at once with Jetzt sichern (back up now) on the overview or in the Terminal:

curl -X POST http://localhost:5100/api/backup/run

The overview shows the latest runs; two failures in a row turn red. A run that would delete more than 500 files in Nextcloud stops, so an empty or wrongly mounted disk cannot empty the backup.

9. Switch on automatic updates

From now on the Mac should install new versions by itself. From a Terminal in which brew, dotnet and npm work (the command remembers its PATH):

./deploy/update-tonregal.sh on

A background service looks for new commits on main every five minutes. When there are some, it waits until nothing is being imported, analysed or backed up, copies tonregal.db to Musik/backups/deploy/ and deploys with deploy-tonregal.sh.

The service runs as /bin/bash and needs Full Disk Access for it once: in System Settings as in step 5, with +, Cmd+Shift+G and /bin/bash. Whether it worked is shown by

./deploy/update-tonregal.sh status
cat /Volumes/T7/Musik/update/deployed    # the last deployed commit

If there is no log and no commit after a few minutes, access for /bin/bash is usually missing.

10. Short commands for every day

The shell functions go into ~/.zshrc:

echo 'source ~/repos/Tonregal/deploy/shell/tonregal.zsh' >> ~/.zshrc

Then you have tonregal-status, tonregal-log, tonregal-restart, tonregal-backup-now and tonregal-update. On a second Mac the same commands run over SSH on the Tonregal Mac; set TONREGAL_HOST to its name for that.

11. Connect the iPhone, iPad and Tonwerk-AI

  • App: Install Tonregal through TestFlight. With Tailscale on, enter the address from step 7, https://<mac-name>.<tailnet>.ts.net, on first start. If you want to build the app yourself, the steps are in the app's README.
  • Tonwerk-AI: The page Verbindungen (connections) in Tonregal shows the key for tonwerk-ai and copies the two lines that go into Tonwerk-AI's settings. After a restore with tonregal.db the old key stays valid; without it, create a new one there and enter it in Tonwerk-AI.

Check that everything runs

  • tonregal-status shows both services as running and the answer from /api/health.
  • The interface opens at https://<mac-name>.<tailnet>.ts.net, and the library shows your albums.
  • A track dropped into Musik/Inbox appears on the inbox page after about ten seconds.
  • The next morning the overview shows a successful backup.

If a service does not run, its log almost always helps (tonregal-log or ~/Library/Logs/Tonregal/). "Operation not permitted" there means access to the external SSD is missing. Without the SSD mounted, the service waits until it is back and never creates an empty library on the internal disk. More on the individual features is in Tonregal's README.