Developer Tools Azure

ByteStash on Ubuntu 24.04 on Azure User Guide

| Product: ByteStash on Ubuntu 24.04 LTS on Azure

Overview

ByteStash is an open source, self hosted code snippet manager for developers and teams. Store, organise, tag and search reusable code snippets with syntax highlighting through the Monaco editor, render Markdown and Mermaid diagrams, keep multi file snippets, and share snippets publicly with optional expiry. Authentication is username and password with JSON Web Tokens, and per user API keys, optional OIDC single sign on and a remote MCP endpoint for AI assistants are available.

The cloudimg image builds ByteStash from source under /opt/bytestash, runs the Node.js server as the dedicated bytestash system user bound to loopback 127.0.0.1:5000, and fronts it with nginx on port 80, ready for your TLS certificate.

Secure by default: there is no known bootstrap credential. The image ships with an empty database and a placeholder secret. On the first boot of every instance, bytestash-firstboot.service generates a unique JWT signing secret, seeds the initial administrator account with its own random password, and writes both to /root/bytestash-credentials.txt (readable only by root). Open self registration is disabled, so no world open sign up window is ever exposed.

What is included:

  • ByteStash built from source under /opt/bytestash (Node.js server + React client)
  • Embedded SQLite database at /opt/bytestash/data/snippets/snippets.db (no separate database to run)
  • bytestash.service running as bytestash, bound to 127.0.0.1:5000
  • nginx reverse proxy on port 80, ready for TLS
  • bytestash-firstboot.service for the per VM JWT secret + seeded admin
  • Node.js 22 LTS runtime
  • Ubuntu 24.04 LTS base, fully patched
  • 24/7 cloudimg support, 24h response SLA

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet with a subnet. Recommended VM size: Standard_B2s (ByteStash is lightweight; 4 GB RAM is comfortable).

Step 1: Deploy from the Azure Portal

Search the Marketplace for ByteStash on Ubuntu 24.04, choose your VM size, and attach an NSG that allows TCP 22 (SSH) from your management network and TCP 80 / 443 (the web app) from the networks that need it. Front port 80 with TLS in production (see the HTTPS section below).

Step 2: Deploy from the Azure CLI

RG="bytestash-prod"; LOCATION="eastus"; VM_NAME="bytestash-01"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/bytestash-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az network vnet create -g "$RG" --name bs-vnet --address-prefix 10.90.0.0/16 --subnet-name bs-subnet --subnet-prefix 10.90.1.0/24
az network nsg create -g "$RG" --name bs-nsg
az network nsg rule create -g "$RG" --nsg-name bs-nsg --name allow-ssh --priority 100 \
  --source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 22 --access Allow --protocol Tcp
az network nsg rule create -g "$RG" --nsg-name bs-nsg --name allow-web --priority 110 \
  --source-address-prefixes "<your-mgmt-cidr>" --destination-port-ranges 80 443 --access Allow --protocol Tcp
az vm create -g "$RG" --name "$VM_NAME" --image "$GALLERY_IMAGE_ID" \
  --size Standard_B2s --storage-sku StandardSSD_LRS \
  --admin-username azureuser --ssh-key-values "$SSH_KEY" \
  --vnet-name bs-vnet --subnet bs-subnet --nsg bs-nsg --public-ip-sku Standard

Step 3: Connect via SSH

ssh azureuser@<vm-ip>

Step 4: Verify the services are running

ByteStash listens on loopback 127.0.0.1:5000; nginx fronts the web app on port 80.

sudo systemctl is-active bytestash nginx
ss -tln | grep -E ':80 |127.0.0.1:5000'
curl -s -o /dev/null -w 'GET /api/auth/config -> HTTP %{http_code}\n' http://127.0.0.1/api/auth/config

Both services report active, the Node server is bound to 127.0.0.1:5000, nginx is bound to :80, and the auth config API returns HTTP 200 through nginx.

bytestash.service and nginx.service active, the Node server bound to 127.0.0.1:5000, nginx on port 80, and the auth config API returning HTTP 200

Step 5: Read your per VM administrator credentials

There is no default login. On first boot a unique administrator password and JWT secret were generated for this instance and written to a root only file. Open self registration is disabled, so the seeded admin is the only account until you create more.

sudo stat -c '%n perms=%a owner=%U:%G' /root/bytestash-credentials.txt
sudo grep -E '^BYTESTASH_URL|^BYTESTASH_USERNAME' /root/bytestash-credentials.txt
curl -s http://127.0.0.1/api/auth/config
echo
curl -s -o /dev/null -w 'unauthenticated GET /api/snippets -> HTTP %{http_code}\n' http://127.0.0.1/api/snippets

The credentials file is 600 root:root, the auth config reports "allowNewAccounts":false (self registration disabled) with "hasUsers":true, and an unauthenticated API call is refused with HTTP 401. Read your admin password with sudo grep '^BYTESTASH_ADMIN_PASSWORD' /root/bytestash-credentials.txt.

The root only per VM credentials file, the auth config reporting allowNewAccounts false, and an unauthenticated API call refused with HTTP 401

Step 6: Log in to the web UI

Open http://<vm-ip>/ in your browser. ByteStash shows its sign in page. Enter the username admin and the password from /root/bytestash-credentials.txt, then click Login.

The ByteStash sign in page where you log in with the seeded admin username and the per VM password from the credentials file

After logging in you land on your snippet library. It starts empty; click New Snippet to add your first snippet.

The ByteStash snippet library after logging in, ready for your first snippet

Step 7: Create a snippet

Give the snippet a title and description, add one or more code fragments with a language for syntax highlighting, tag it for search, then save. The snippet appears in your library with Monaco syntax highlighting and is instantly searchable by title, content or tag.

Creating a ByteStash snippet with a title, a code fragment with language syntax highlighting, and tags for search

Step 8: The runtime stack

node -v
nginx -v
test -f /opt/bytestash/client/build/index.html && echo "client build present"
test -f /opt/bytestash/server/src/app.js && echo "server present"

Node.js 22 LTS runs the server, nginx 1.24 fronts it, and both the built React client and the Node server are present on disk.

Node.js 22 LTS, nginx 1.24, and the built ByteStash client and server present on disk

Step 9: Data and persistence

All snippets, users and settings live in the embedded SQLite database under /opt/bytestash/data/snippets, captured into the image and carried onto every instance.

sudo ls -lh /opt/bytestash/data/snippets/snippets.db
test -f /var/lib/cloudimg/bytestash-firstboot.done && echo "firstboot: completed"
apt-mark showhold

The database file is present, the first boot marker confirms the per VM secret and admin were provisioned, and there are no held packages, so the OS security baseline is intact.

The ByteStash SQLite database on disk, the first boot completion marker, and an intact OS patch baseline with no held packages

Step 10: Enable HTTPS

nginx already fronts ByteStash on port 80 and is ready for TLS. Point a DNS record at your VM, then obtain a certificate with certbot:

sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain> --agree-tos -m <your-email> --redirect

certbot installs the certificate, rewrites the nginx server block for TLS, and sets up automatic renewal. Your snippet library is then served over HTTPS.

Optional: enable OIDC single sign on

ByteStash supports OIDC single sign on. Set the OIDC variables in /etc/bytestash/bytestash.env and restart the service:

if sudo grep -q '^OIDC_ENABLED=' /etc/bytestash/bytestash.env; then
  sudo sed -i 's/^OIDC_ENABLED=.*/OIDC_ENABLED=true/' /etc/bytestash/bytestash.env
else
  echo 'OIDC_ENABLED=true' | sudo tee -a /etc/bytestash/bytestash.env
fi
# then add OIDC_ISSUER_URL, OIDC_CLIENT_ID and OIDC_CLIENT_SECRET for your provider
sudo systemctl restart bytestash

Consult your identity provider for the issuer URL and client credentials. Internal username and password accounts continue to work alongside OIDC unless you disable them.

Managing the service

sudo systemctl status bytestash
sudo systemctl restart bytestash
sudo journalctl -u bytestash -f

The Node server logs to the journal. nginx logs are under /var/log/nginx/. Back up the instance by snapshotting the OS disk or copying /opt/bytestash/data/snippets while the service is stopped.

Support

cloudimg provides 24/7 support for this image via email and live chat: deployment, nginx TLS termination, upgrades, OIDC integration, and performance tuning. Email support@cloudimg.co.uk.

This is a repackaged open source software product with additional charges for cloudimg support services. ByteStash is a trademark of its respective owner. All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.