Installation guide

Install CrateSphere on a cloud server

Run a permanently available portal on a rented Linux server, with your own database, storage and public address.

This guide puts the portal on a rented Linux server with a proper https:// address, so artists and engineers can sign in from anywhere.

You do not need to know Linux. You will type commands into a black window, but every one of them is written out for you, and each is explained in plain English before you run it. You are copying and pasting, not programming.

Set aside about two hours the first time. Most of it is waiting.

What you are building

Six programs run on your server, and you never interact with them directly:

What it does
Web serverThe website people sign in to
Media workerAnalyses audio, draws waveforms, converts files
SchedulerTidies up on a timer
PostgreSQLThe database — accounts, projects, comments
RedisA to-do list the worker reads from
Cloudflare TunnelCarries traffic from the internet to your server

Your music does not live on the server. It lives in cloud storage, and the server fetches pieces as needed. This is why a small, cheap server is enough for a large catalogue.

Part 1: Choose and buy

The storage

Use Cloudflare R2. The reason is not that it is the cheapest per gigabyte — it is not — but that downloads are free, always.

Storage, 100 GBDownloads
Cloudflare R2about $1.50/month$0, unlimited
Backblaze B2about $0.60/monthfree to 3× what you store, then $0.01/GB

A record label's portal exists to let people download masters. That download figure is the one you cannot predict — a busy month with a big release could be hundreds of gigabytes. R2 makes it structurally zero, so your bill is the storage line and nothing else. B2's cheaper storage is exactly right for a backup copy, which is rarely read, and that is covered at the end.

R2 includes 10 GB free.

The server

Two providers worth your time:

Contabo — most memory and disk for the money. Current Cloud VPS tiers:

vCPUMemoryDiskPrice
Cloud VPS 448 GB100 GB€5.40/month
Cloud VPS 6612 GB200 GB€7.00/month
Cloud VPS 8824 GB300 GB€14.00/month

Hetzner — faster disks and a better network, for more money.

Cloud VPS 4 is enough, including a demo portal alongside your real one. The six programs use roughly 1 GB of memory per portal at rest; audio processing is handled one file at a time, so it spikes briefly rather than piling up. Your catalogue is in R2, so the 100 GB disk only holds the programs and temporary working files.

The one thing that could outgrow it is temporary space: when someone asks the portal to zip up a whole release, it builds that zip on the server's disk first. If you routinely package very large releases, Cloud VPS 6 doubles the disk for €1.60 more. Do not pre-buy it — you can move up later.

Choose Ubuntu 24.04 LTS as the operating system when you order.

The domain name

You need a domain (like glitchpulser.com) with its DNS managed by Cloudflare. If your domain is somewhere else, move its nameservers to Cloudflare first — Cloudflare's dashboard walks you through it and it is free.

Decide now what address the portal will have, for example portal.glitchpulser.com. You will type it in exactly, twice.

Part 2: Set up storage

Do this in a web browser before touching the server.

Create the bucket

  1. Sign in to Cloudflare and open R2.
  2. Create a bucket. Name it something plain, like glitchpulse-catalogue.
  3. Do not enable public access. Do not attach a public URL. People will reach your music by signing in to the portal; the bucket itself stays shut.

Create the portal's key

The portal needs its own login to that bucket. Cloudflare calls this an API token, and it produces two halves that only work together.

  1. In R2, open Manage in the API Tokens area.
  2. Choose Create Account API Token.
  3. Name it cratesphere-portal. This name is just for your own reference.
  4. Permission: Object Read & Write.
  5. Scope: Apply to specific buckets only, and pick the one bucket you just made. Do not give it access to everything.
  6. TTL: choose Forever. If you set an expiry, the portal stops working on that date with no warning and no automatic renewal.
  7. Client IP Filtering: leave it unrestricted for now. You can tighten it once everything works.
  8. Click Create API Token.

Cloudflare now shows you a page with the secrets on it. This page appears once. Copy all four of these into your password manager before you leave it:

What to copyLooks like
Bucket nameglitchpulse-catalogue
Access Key IDa long string of letters and numbers
Secret Access Keya longer one — shown once, never again
S3 API endpointhttps://<account-id>.r2.cloudflarestorage.com

If you lose the Secret Access Key, Cloudflare cannot show it again. Create a new token and delete the old one; you cannot mix halves from two tokens.

The endpoint is the account address. It does not contain your bucket name and has nothing after .com.

Part 3: Connect to the server

SSH is a secure text connection from your PC to your server. Windows has it built in.

Open Windows Terminal or PowerShell and check:

ssh -V

If Windows does not recognise ssh, install the optional feature OpenSSH Client from Settings, then open a new window.

Find your server's IP address in your provider's control panel. It looks like 203.0.113.10. Then connect, replacing the example address with yours:

ssh root@203.0.113.10

The first time, it asks whether you trust this server. Because you just created it yourself, type yes and press Enter.

Then it asks for the root password from your provider's welcome email. Nothing appears on screen while you type a password on Linux — no dots, no stars. That is normal. Type it carefully and press Enter.

You are in when the prompt looks like:

root@your-server:~#

Check the connection is behaving before you paste anything longer:

echo "SSH works"

It must print SSH works. If it prints nothing, stop and fix that first — something is wrong with your terminal, and later steps will be impossible to follow.

To leave at any time, type exit.

About the code boxes below. Copy only the text inside them. Do not copy the bash label, the box borders, or the root@your-server:~# prompt.

Part 4: Copy CrateSphere to the server

CrateSphere is private, so you do not download it on the server. You send it from your PC as a single file called a bundle, which contains the code and nothing else — no passwords, no database, no music.

Open a second PowerShell window on your PC (leave the server one open). Run these, replacing the folder path with wherever your CrateSphere is and the IP with your server's:

Set-Location C:\Users\nickm\Documents\GitHub\CrateSphere
git bundle create "$env:USERPROFILE\Downloads\cratesphere.bundle" HEAD
git bundle verify "$env:USERPROFILE\Downloads\cratesphere.bundle"
scp "$env:USERPROFILE\Downloads\cratesphere.bundle" root@203.0.113.10:/root/

In plain English: package the current version of the code into one file, check the file is not damaged, then copy it to the server. git bundle verify must say the bundle is okay before you run scp.

Now back in the server window, unpack it:

git clone /root/cratesphere.bundle /root/cratesphere-source
cd /root/cratesphere-source

In plain English: unpack the code into a folder, then move into it.

If it says git: command not found, install it first with apt update && apt install -y git, then run the two lines again. In plain English: refresh the list of available software, then install the tool for unpacking code.

Part 5: Run the installer

This is the one command that does the work. Before running it, have ready:

  • the four R2 values from Part 2, and
  • the exact web address you chose, e.g. https://portal.glitchpulser.com.

The address does not need to be live yet, but it must be the one you will set up in Part 6, typed identically.

sudo bash apps/submission-portal/scripts/bootstrap-self-hosted-linux.sh --instance demo --bind-port 3000

In plain English: install and start the portal. With administrator rights, this single command installs Docker (the program that runs everything else), creates locked-down folders for the portal's private files, generates a database password and a one-time setup key that even you never see, asks you for the address and the four R2 values, builds the portal, starts the database, creates the tables, starts the portal, and waits until it answers a health check.

It will ask you, one at a time:

  1. The public address. Type it with https:// and nothing after the domain.
  2. The R2 endpoint, then the bucket name.
  3. The Access Key ID, then the Secret Access Key. Nothing appears while you paste these. That is deliberate — they are secrets. Paste and press Enter.

Then it runs for five to fifteen minutes, printing a lot of build output.

You are done with this part when it says:

Installation complete: the portal is healthy on the VPS at http://127.0.0.1:3000.

That address only works on the server itself. Part 6 gives it a public one.

If it stops with an error, read the last few lines — they name the problem. Nothing is half-installed: fix what it names and run the same command again. It keeps anything it already made correctly, and it will not ask for your R2 details twice.

Part 6: Put it on the internet

Cloudflare Tunnel connects your server to Cloudflare without opening any ports on the server. Three commands, then a small file.

sudo install -d -o root -g root -m 0700 /srv/cratesphere/cloudflared
sudo docker run --rm -it --user 0:0 -v /srv/cratesphere/cloudflared:/root/.cloudflared cloudflare/cloudflared:latest tunnel login

In plain English: make a private folder for Cloudflare's credentials, then sign in to Cloudflare. The second command prints a link. Copy it into your browser, sign in, and pick your domain. The window then confirms it saved a certificate.

sudo docker run --rm --user 0:0 -v /srv/cratesphere/cloudflared:/root/.cloudflared cloudflare/cloudflared:latest tunnel create cratesphere-portal

In plain English: create the tunnel. It prints an ID that looks like 6ff42ae2-765d-4adf-8d05-196c6c9b67eb. Copy that ID — you need it twice.

Now create the tunnel's settings file:

sudo nano /srv/cratesphere/cloudflared/config.yml

In plain English: open a simple text editor. Type the following, replacing both YOUR-TUNNEL-ID with the ID you copied and the hostname with your address:

tunnel: YOUR-TUNNEL-ID
credentials-file: /etc/cloudflared/YOUR-TUNNEL-ID.json

ingress:
  - hostname: portal.glitchpulser.com
    service: http://portal-web:3000
  - service: http_status:404

Keep the indentation exactly as shown. The last two lines are required by Cloudflare even though they look odd.

Save and close: press Ctrl+O, then Enter, then Ctrl+X.

Point your web address at the tunnel, replacing both values:

sudo docker run --rm --user 0:0 -v /srv/cratesphere/cloudflared:/root/.cloudflared cloudflare/cloudflared:latest tunnel route dns YOUR-TUNNEL-ID portal.glitchpulser.com

In plain English: tell Cloudflare that this web address should reach this tunnel. This creates the DNS record for you — do not add one by hand.

Start everything:

cd /srv/cratesphere
sudo docker compose --env-file /etc/cratesphere/portal.env up -d

In plain English: start all the portal's programs, including the tunnel, and leave them running in the background.

Wait a minute, then open your address in a browser. You should see the portal's sign-in page over https://.

Part 7: Create your administrator account

Go to https://portal.glitchpulser.com/login.

You will see Initial administrator, with the Bootstrap token box empty. That is correct and deliberate: on a public server the portal refuses to print its own setup key into a web page. You fetch it from the server yourself.

In the server window:

sudo grep '^BOOTSTRAP_ADMIN_TOKEN=' /etc/cratesphere/portal.env

In plain English: show me the one-time setup key.

Copy only the part after the `=` into the browser box. Fill in your name, email and a password of at least 12 characters, accept the Terms, and click Create administrator.

Moving an existing portal? Do not create a new administrator. Use the link reading "Moving an existing portal? Restore from a backup instead" and follow Move to a cloud server.

Once the account exists, remove the used key:

sudo sed -i '/^BOOTSTRAP_ADMIN_TOKEN=/d' /etc/cratesphere/portal.env
cd /srv/cratesphere && sudo docker compose --env-file /etc/cratesphere/portal.env up -d --force-recreate portal-web portal-worker portal-scheduler

In plain English: delete the used setup key from the settings file, then restart the portal so it forgets it. The portal already refuses to create a second administrator, but a used secret should not linger.

Finally, in the portal: open Settings → Storage and confirm it reports the r2 adapter as reachable. Then open Settings → Email, enter your SMTP sender details and use Verify SMTP for invitations. Until that verification passes, the portal will not let you invite anyone — a saved but untested sender is deliberately not enough.

Part 8: A second portal for demos

One server can run two completely separate portals. They share nothing: not the database, not the storage, not the accounts.

cd /root/cratesphere-source
sudo bash apps/submission-portal/scripts/bootstrap-self-hosted-linux.sh --instance gpr --bind-port 3001

In plain English: install a second, independent portal, with its own folders, its own database and its own internal address.

It asks the same questions again. Give it a different web address and a different R2 bucket. Do not reuse the first portal's bucket — two portals writing to one bucket will overwrite each other's music.

First portalSecond portal
Instance namedemogpr
Settings file/etc/cratesphere/portal.env/etc/cratesphere-gpr/portal.env
Folders/srv/cratesphere/srv/cratesphere-gpr
Internal address127.0.0.1:3000127.0.0.1:3001

Then repeat Part 6 for the second portal, using its own folder (/srv/cratesphere-gpr/cloudflared), its own tunnel name and its own web address.

One thing catches people out here. In the second portal's config.yml, the service line is still:

    service: http://portal-web:3000

Not `3001`. Each portal runs on its own private network, and inside that network its web server is always on port 3000. The 3001 you gave the installer is only how the server itself reaches the second portal from outside that network, which is what the health check below uses. It never appears in config.yml.

To check the second portal directly on the server:

curl http://127.0.0.1:3001/api/health

In plain English: ask the second portal whether it is healthy.

Before adding the second portal, check you have room:

free -h; df -h /srv

In plain English: show memory and disk space. You want at least 2 GB of memory free and 20 GB of disk.

Keeping it running

Updating

Make a fresh bundle on your PC exactly as in Part 4, copy it over, then:

sudo bash /root/cratesphere-source/apps/submission-portal/scripts/update-self-hosted-linux.sh --instance demo /root/cratesphere.bundle

In plain English: update the portal to the new code. It checks the bundle, builds the new version, makes a rollback copy of the database, asks you to type UPDATE to confirm, then swaps over during a short outage and waits for the health check.

It never touches your settings, database, keys or music.

Backing up

Two things need backing up, separately.

The database, which holds accounts, projects and comments:

sudo install -d -o root -g root -m 0700 /srv/cratesphere/backups/postgres
cd /srv/cratesphere && sudo sh -c 'docker compose --env-file /etc/cratesphere/portal.env exec -T postgres pg_dump -U cratesphere -d cratesphere --format=custom > /srv/cratesphere/backups/postgres/portal-$(date -u +%Y%m%dT%H%M%SZ).dump'

In plain English: make a dated copy of the database into a private folder. Copy that file off the server afterwards — a backup that only exists on the server does not survive losing the server.

The music, by copying R2 to Backblaze B2. This is where B2's cheaper storage earns its place: it is written often and read almost never. Full instructions are in the technical runbook.

A provider snapshot of the whole server is not a substitute. It is a way to rebuild the machine, not a consistent copy of your database or your music.

When something goes wrong

What you seeWhat to do
The installer stops with an errorRead the last few lines; they name the problem. Fix it and run the same command again — it keeps what it already did correctly.
The web address does not load, but the installer said healthyThe tunnel, not the portal. Check sudo docker compose --env-file /etc/cratesphere/portal.env logs cloudflared, and check the address in config.yml matches the one you routed exactly.
"Production configuration invalid" in the logsA setting is missing or malformed in /etc/cratesphere/portal.env. The log names which one.
The setup screen does not appearAn account already exists. Go to /login and sign in.
Storage shows unavailableCheck the R2 endpoint has nothing after .com, and that the token has Object Read & Write on that bucket.
Invitations fail with SMTP_NOT_READYSave the sender in Settings → Email, then use Verify SMTP for invitations. Saving alone is not enough.
Audio uploads but never finishes processingThe worker or Redis is down. Check sudo docker compose --env-file /etc/cratesphere/portal.env ps — all services should say running.

For anything deeper, the technical runbook documents every setting and the reasoning behind it.

This guide is generated from the maintained source that ships with the software, so it matches the release it documents.

Back to CrateSphere