Install on a new server
This guide installs the whole stack on one Linux server: Navidrome, Postgres, a local Telegram Bot API server, and the bot. If you already run Navidrome, connect it instead.
Check the requirements first.
Download the installer of the latest release, v0.0.8, and run it on the server:
curl -fL https://github.com/lubaskinc0de/beatstash/releases/download/v0.0.8/install.sh -o install.shcurl -fL https://github.com/lubaskinc0de/beatstash/releases/download/v0.0.8/install.sh.sha256 -o install.sh.sha256sha256sum -c install.sh.sha256bash install.shChoose new when it asks about Navidrome. The installer then:
- walks you through creating a Telegram bot, turning on inline mode, and getting the Telegram credentials;
- generates the database password and the encryption key;
- starts Navidrome and creates its first administrator with the login and password you enter (if Navidrome already has accounts, it checks that this one signs in);
- starts the bot.
On a server reached over SSH, it prints Telegram links for you to open on your computer or phone. If Telegram is blocked on the server, it notices and asks for a proxy; see when Telegram is blocked.
If you enter an https:// public address, the installer offers to set up HTTPS. It can add a site to a Caddy already running on the server, or start its own Caddy when nothing else uses ports 80 and 443. It shows each change and asks first. HTTPS and public access lists what it checks.
Passwords and tokens are hidden as you type them. If you stop partway, run the installer again in the same directory: press Enter at a filled prompt to keep the saved value. It keeps your Compose file, configuration, and generated secrets.
Follow these steps if you’d rather configure the stack yourself.
-
Download the installation files. These commands fetch the Compose and configuration templates of v0.0.8, with the matching Docker image version already set:
Terminal window release_tag="v0.0.8"mkdir -p beatstashcd beatstashcurl --fail --location --remote-name \"https://github.com/lubaskinc0de/beatstash/releases/download/$release_tag/beatstash-$release_tag-deploy.tar.gz"curl --fail --location --remote-name \"https://github.com/lubaskinc0de/beatstash/releases/download/$release_tag/beatstash-$release_tag-deploy.tar.gz.sha256"sha256sum -c "beatstash-$release_tag-deploy.tar.gz.sha256"tar -xzf "beatstash-$release_tag-deploy.tar.gz"cp deploy/.env.example deploy/.envcp deploy/config.example.toml deploy/config.tomlmkdir -p deploy/music/shared deploy/music/users deploy/data/navidromechmod 600 deploy/.env deploy/config.tomlcd deployYou get this layout:
Directorybeatstash/deploy/
- compose.yml services of the stack
- .env secrets and service choices
- config.toml bot settings
Directorymusic/ the bot’s managed folders
Directoryshared/
- …
Directoryusers/
- …
Directorydata/navidrome/
- …
compose.ymlpullsghcr.io/lubaskinc0de/beatstashat the version inBEATSTASH_VERSION. Keep that exact version instead oflatest, so a restart never picks up a different release. Optional services are Compose profiles listed inCOMPOSE_PROFILES: the example turns onnavidrome; addproxyonly for the bundled Caddy described in HTTPS.Keep everything under
music/on one filesystem. The bot moves files between these folders with hardlinks and renames. -
Set up Telegram and secrets. Follow Set up Telegram to create the bot, turn on inline mode, find your numeric user ID, and get
api_idandapi_hash. Then fill in.env:deploy/.env BOT_TOKEN="<token from BotFather>"SECRET_KEY="<output of openssl rand -base64 32>"NAVIDROME_PASSWORD="<password for the Navidrome administrator>"TELEGRAM_API_ID="<your api_id>"TELEGRAM_API_HASH="<your api_hash>"POSTGRES_PASSWORD="<output of openssl rand -hex 32>"Generate the two random values separately:
Terminal window openssl rand -base64 32openssl rand -hex 32Leave
BEATSTASH_VERSIONas the archive set it. Compose setsDB_DSNitself. Before the first start, log the bot out of Telegram’s cloud API as described in Run the local Bot API. -
Configure the bot. Edit these existing sections, keeping the rest of the example:
deploy/config.toml admins = ["telegram:123456789"]admin_contact = "@your_telegram_username"[telegram]bot_api_url = "http://telegram-bot-api:8081"[library]music_dir = "/music"navidrome_music_dir = "/music"[navidrome]url = "http://navidrome:4533"public_url = ""user = "admin"Put your own numeric ID in
admins. Addresses such ashttp://navidrome:4533work only inside the Compose network. Leavepublic_urlempty until you set up HTTPS; uploads work without it. -
Create the first Navidrome administrator. The bot doesn’t create it, so do this before starting the bot:
Terminal window docker compose up -d postgres navidromedocker compose psNavidrome listens only on the server’s loopback interface. Open an SSH tunnel from your computer:
Terminal window ssh -L 4533:127.0.0.1:4533 your_user@your_serverOpen
http://localhost:4533and create an administrator namedadminwith the password fromNAVIDROME_PASSWORD. If you pick another login, changenavidrome.userto match.Without a browser, use Navidrome’s first-run API on the server. It works only while Navidrome has no accounts. Type the password when
readwaits, so it stays out of your shell history:Terminal window read -rs passwordcurl -fsS http://127.0.0.1:4533/auth/createAdmin -H 'Content-Type: application/json' \-d "$(jq -n --arg password "$password" '{username: "admin", password: $password}')" > /dev/null -
Start beatstash.
Terminal window docker compose pull telegram-bot-api botdocker compose up -d telegram-bot-api botdocker compose logs --tail=100 botdocker compose psOpen your bot in Telegram and send
/start. You should see Admin on the home screen; invites are made there. In Settings > Navidrome account, choose Link and sendlogin password. The bot deletes that message.This administrator account sees every Navidrome library. For everyday listening with a private library, link a separate regular account.
Check the installation
Section titled “Check the installation”- Send the bot a tagged audio file and wait for 👍.
- Open Navidrome, let it scan the track, and play it.
- Create an invite and have someone join with a new account.
- Check that they see their personal library and the shared library, but not yours.
- Share the track from Music > Mine. Check that they find it under Shared.
Next, set up HTTPS if you skipped it, so players and listening links work from anywhere. To change limits or intervals later, see configuration. To update, see updates.