Installation guide

Move a portal from Windows to a cloud server

The supported procedure for moving an existing Windows installation onto an always-on cloud server.

This is the official procedure for moving an existing Windows installation — its accounts, projects, tracks, comments and music — onto a cloud server.

Nothing is deleted from your Windows PC. If the move goes wrong, your original portal is still there, untouched, and you simply carry on using it.

Read this first: the two halves

A portal is two separate things, and they move by two separate routes.

What it isHow it moves
The databaseAccounts, projects, track listings, comments, submissions, settingsA backup file you upload
The catalogueThe actual audio and artworkCopied straight into cloud storage

Your music is never inside a backup. An 80 GB catalogue would make an 80 GB backup, and it would be pointless — the files already exist on your disk. So a backup stays small and the music travels separately.

The two halves must agree. The database stores each file by its folder path — for example GPR009 - Nosivel - Knowledge & Ignorance/MMM Dynamic (We used this)/01. Nosivel - Knowledge & Ignorance - The AI Awakens.wav. If that exact path exists in your cloud storage, the portal finds the file. If a folder was renamed on the way, the track appears in the portal but will not play.

So the single rule for the whole migration is: copy the catalogue with every folder name exactly as it is.

Which comes first?

Upload the music first, then restore the database. Both orders end up working, but this one means the portal is never showing tracks it cannot play. The music upload is also the slow part, and you can do it days in advance while your Windows portal keeps running normally.

Before you start

You need:

  • Your Windows portal working now.
  • A cloud server already installed and healthy, following Install on a cloud server as far as the end of Part 6. Stop before creating an administrator account — you are restoring one, not making one.
  • The R2 bucket from that install, still empty.
  • Time for the upload. See the table further down.

Step 1: Find your catalogue

On your Windows PC, the catalogue is in one of two places.

If you have never changed storage settings, it is:

%LOCALAPPDATA%\CrateSphere\storage

If you commissioned external storage — Proton Drive, for instance — it is wherever you pointed it. To check, open this file in Notepad:

%LOCALAPPDATA%\CrateSphere\runtime\storage-commission.v1.json

The path is on the line beginning "protonSyncRoot". For example:

"protonSyncRoot": "C:\\Users\\nickm\\Proton Drive\\nickmanton\\My files\\!Glitchpulser"

The double backslashes are how the file is written; the real path has single ones.

Open that folder. You should see your release folders, and possibly Submissions and Rejected. That whole folder is what you are uploading.

Step 2: Upload the catalogue

You will use rclone, a free tool for copying files to cloud storage.

Install rclone

  1. Go to <https://rclone.org/downloads/> and download the Windows AMD64 zip.
  2. Extract it. You will find rclone.exe inside.
  3. Copy rclone.exe into a simple folder such as C:\rclone.

Point it at your bucket

Open PowerShell and run:

C:\rclone\rclone.exe config

Answer its questions:

It asksYou answer
n/s/q>n (new remote)
namer2
Storagetype s3
providerchoose Cloudflare
env_authpress Enter
access_key_idyour R2 Access Key ID
secret_access_keyyour R2 Secret Access Key
regionauto
endpointyour R2 endpoint, https://<account-id>.r2.cloudflarestorage.com
Everything elsepress Enter
Edit advanced config?n
Keep this remote?y
e/n/d/r/c/s/q>q to quit

These are the same four R2 values you gave the installer.

Do a dry run first

This shows what would be copied without copying anything. Replace the folder path with yours and the bucket name with yours:

C:\rclone\rclone.exe copy "C:\Users\nickm\Proton Drive\nickmanton\My files\!Glitchpulser" r2:glitchpulse-catalogue --dry-run --progress

Read the first few lines. The paths listed after your bucket name must start directly with your release folders — GPR001 - ..., Submissions/... — and not with an extra folder like !Glitchpulser/GPR001 - .... If you see that extra level, you have a trailing \ on the source path; remove it and try again.

Getting this right is the whole migration. An extra folder level means every track in the portal is unplayable.

Run it for real

Remove --dry-run:

C:\rclone\rclone.exe copy "C:\Users\nickm\Proton Drive\nickmanton\My files\!Glitchpulser" r2:glitchpulse-catalogue --progress

In plain English: copy everything in that folder up to the bucket, showing progress. copy only ever adds and overwrites; it never deletes anything at either end.

This takes a long time. It depends on your upload speed, not your download speed:

Your upload86 GB takes about
10 Mbit/s19 hours
20 Mbit/s10 hours
50 Mbit/s4 hours
100 Mbit/s2 hours

Leave the PC on and awake. If it is interrupted, run the same command again — it skips files already uploaded and carries on.

Do I need to copy Submissions and Rejected?

Yes, if they contain anything you want to keep.

The portal creates both folders automatically when it first needs them, but it creates them empty. It will not recreate their contents. Every submission and every rejected submission in your database points at a real folder inside them, so if you skip them, those entries survive in the portal with nothing behind them.

Copying the parent folder, as above, includes them automatically. You do not need to do anything special — just do not exclude them.

You may skip them only if you genuinely do not care about past submissions.

Step 3: Take the backup

Do this after the upload finishes, so the backup reflects the same state as the music.

On your Windows portal, sign in as administrator and go to Settings → Maintenance. Click Create portal-state backup.

The file appears in:

%LOCALAPPDATA%\CrateSphere\backups

named like cratesphere-20260814-052408.zip. Take the newest one.

Treat this file as a secret. It contains your accounts and your encrypted service passwords. Do not email it or put it in a shared folder.

Keep using your Windows portal normally after this if you want — but anything you change from now on will not be in the backup, and will not appear on the server.

Step 4: Restore onto the server

Open your new server's address in a browser, at /login. You will see the Initial administrator screen.

Do not create an administrator. Click the link at the bottom:

Moving an existing portal? Restore from a backup instead

The screen changes to Restore from a backup.

You need the server's one-time setup key. In your server terminal:

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 =.

Then on the restore screen:

  1. Backup file — choose the .zip from Step 3.
  2. Bootstrap token — paste the key.
  3. Click Restore this portal.

The upload takes a moment and the copy takes under a minute for a typical label. When it finishes you will see how many records and accounts were restored.

Sign in with the same email and password you used on Windows. Your accounts came across unchanged — passwords included. No one needs a new password, and your artists never notice the move.

If the browser upload will not work

Very large backups, or a slow connection, can make a browser upload impractical. Do it over SSH instead. Copy the file up from your PC:

scp "$env:LOCALAPPDATA\CrateSphere\backups\cratesphere-20260814-052408.zip" root@203.0.113.10:/root/

Then on the server:

sudo bash /root/cratesphere-source/apps/submission-portal/scripts/restore-self-hosted-linux.sh --instance demo --archive /root/cratesphere-20260814-052408.zip

In plain English: load that backup into the portal. It shows what it is about to do, asks you to type RESTORE, briefly stops the portal, copies the data in, and starts it again.

If you are restoring into the second portal, use --instance gpr.

Checking it before you commit

To see what a backup contains without changing anything:

sudo docker run --rm --env-file /etc/cratesphere/portal.env -v /root/cratesphere-20260814-052408.zip:/b.zip:ro cratesphere-portal-migrate:current node scripts/migrate-sqlite-to-postgres.mjs --archive /b.zip --dry-run

In plain English: read the backup and report what it would restore, writing nothing. It prints a row count per table.

Step 5: Finish setting up

Three things do not travel with the backup. All three are quick.

1. Service passwords. Your SMTP details and any distribution logins were deliberately left behind rather than carrying an encryption key between machines. Go to Settings → Email, enter your sender details, and use Verify SMTP for invitations. Until that verification passes, the portal will not let you invite anyone.

2. Storage check. Go to Settings → Storage and confirm it reports the r2 adapter as reachable.

3. Play something. Open a release, play a track, and download the original. This is the real test that the database and the catalogue agree. If a track plays, your folder paths came across correctly.

If a track does not play, it is almost always the extra-folder-level mistake from Step 2. Check in the Cloudflare dashboard: your bucket's top level should show your release folders directly, not one folder containing them.

Step 6: Tidy up

Once you are satisfied — give it a few days of real use — remove the used setup key from the server:

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 and restart the portal so it forgets it. The portal already refuses to restore or create an administrator once accounts exist, but a used secret should not linger.

Keep your Windows installation for a while as a fallback. When you no longer want it, simply stop launching it; the data stays in %LOCALAPPDATA%\CrateSphere until you delete that folder yourself.

Set up backups on the server now — see Keeping it running. Your Windows PC is no longer the copy of record.

What can go wrong

What you seeWhat it means
"This portal already has accounts, so it cannot be restored over"Someone created an administrator on the server. Restore is only possible into a fresh installation. Start the server portal over, or restore into a new instance.
"That backup restored no sign-in accounts"The file is not a portal backup, or is from an installation that never had accounts. Nothing was changed. Check you picked the right .zip.
"The archive is not a CrateSphere portal backup"Wrong file, or a damaged download. Take a fresh backup.
"That backup is larger than this portal accepts"Use the SSH method above instead of the browser.
Tracks are listed but will not playThe catalogue is missing, or is one folder level too deep in the bucket. Compare a track's folder path in the portal against the bucket's top level.
Submissions exist but their files are missingSubmissions was not copied. Run the same rclone command again — it only adds what is absent.
Everything works, but no one can be invitedSMTP is not verified. Settings → Email, then Verify SMTP for invitations.

What the migration actually does

For anyone who wants to know what is happening under the covers.

Windows stores its data in SQLite, a single database file. A cloud server uses PostgreSQL, a database program. They are different systems, so the move is a row-by-row copy rather than a file copy.

That copy is safe to do mechanically because both are generated from the same schema — the two definitions differ only in which database they name. The tool reads the table structure at runtime rather than from a hand-written list, so it stays correct as the portal gains features, and it reports any table in the backup it does not recognise instead of skipping it silently.

Three details it handles that a naive copy would get wrong:

  • Tag links. The connections between tags and tracks live in their own hidden tables. A copy that only walks the visible tables loses every tag.
  • Replies and nested folders. A comment that replies to another comment, or a folder inside a folder, cannot be written before the thing it points at exists. These are filled in on a second pass.
  • Dates, true/false values and settings blobs. SQLite has no real type for any of these and stores them as numbers and text. Each is converted back before PostgreSQL sees it, so a date arrives as the same instant rather than as a large number.

Re-running a restore is harmless: rows that already exist are skipped, so a second run writes nothing rather than duplicating your catalogue.

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

Back to CrateSphere