Deployment
Deploy Quickslice to production. Railway with one-click deploy is fastest.
#Railway (Recommended)
#1. Deploy
Click the button to deploy Quickslice with SQLite:
Railway prompts you to configure environment variables. Leave the form open while you generate a signing key.
#2. Generate OAuth Signing Key
Quickslice needs a private key to sign OAuth tokens:
brew install goat
goat key generate -t p256
This outputs:
Key Type: P-256 / secp256r1 / ES256 private key
Secret Key (Multibase Syntax): z42tsQ4W...
Public Key (DID Key Syntax): did:key:zDnaek...
Copy only the Secret Key value (starts with z) and paste it into the OAUTH_SIGNING_KEY field in Railway, then click Save Config.
#3. Configure Your Domain
After deployment completes:
- Click on your quickslice service
- Go to Settings
- Click Generate Domain under Networking
Railway creates a public URL like quickslice-production-xxxx.up.railway.app.
Redeploy to apply the domain:
- Go to Deployments
- Click the three-dot menu on the latest deployment
- Select Redeploy
#4. Create Admin Account
Visit your domain. The welcome screen prompts you to create an admin account:
- Enter your AT Protocol handle (e.g.,
yourname.bsky.social) - Click Authenticate
- Authorize Quickslice on your PDS
- You're now the instance admin
#5. Configure Your Instance
From the homepage, go to Settings:
-
Enter your Domain Authority in reverse-domain format (e.g.,
xyz.statusphere) -
Upload your Lexicons as a
.zipfile (JSON format, directory structure doesn't matter). See statusphere lexicons for an example.lexicons.zip └── lexicons/ └── xyz/ └── statusphere/ └── status.json -
Click Trigger Backfill to import existing records from the network. The Quickslice logo enters a loading state during backfill and the page refreshes when complete. Check Railway logs to monitor progress:
INFO [backfill] PDS worker 67/87 done (1898 records) INFO [backfill] PDS worker 68/87 done (1117 records) INFO [backfill] PDS worker 69/87 done (746 records) ...Depending on the lexicon, this could take a few seconds (
xyz.statusphere.*) to days (app.bsky.*) to complete. Be mindful of your available storage and associated cloud provider fees when backfilling large lexicons.
#Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
OAUTH_SIGNING_KEY |
Yes | - | P-256 private key for signing OAuth tokens |
DATABASE_URL |
No | quickslice.db |
Path to SQLite database |
HOST |
No | 127.0.0.1 |
Server bind address (use 0.0.0.0 for containers) |
PORT |
No | 8080 |
Server port |
SECRET_KEY_BASE |
Recommended | Auto-generated | Session encryption key (64+ chars) |
EXTERNAL_BASE_URL |
No | Auto-detected | Public URL for OAuth redirects |
#Fly.io
#1. Create a Volume
fly volumes create app_data --size 10
#2. Configure fly.toml
app = 'your-app-name'
primary_region = 'sjc'
[build]
dockerfile = "Dockerfile"
[env]
DATABASE_URL = 'sqlite:/data/quickslice.db'
EXTERNAL_BASE_URL=https://your-quickslice.fly.dev
HOST = '0.0.0.0'
PORT = '8080'
[http_service]
internal_port = 8080
force_https = true
auto_stop_machines = 'stop'
auto_start_machines = true
min_machines_running = 1
[[mounts]]
source = 'app_data'
destination = '/data'
[[vm]]
memory = '1gb'
cpu_kind = 'shared'
cpus = 1
#3. Set Secrets
fly secrets set SECRET_KEY_BASE=$(openssl rand -base64 48)
Generate a signing key and copy only the Secret Key value (starts with z):
goat key generate -t p256
fly secrets set OAUTH_SIGNING_KEY="z42tsQ4W..." # paste your secret key here
#4. Deploy
fly deploy
#Docker Compose
For self-hosted deployments:
version: "3.8"
services:
quickslice:
image: ghcr.io/bigmoves/quickslice:latest
ports:
- "8080:8080"
volumes:
- quickslice-data:/data
environment:
- HOST=0.0.0.0
- PORT=8080
- DATABASE_URL=sqlite:/data/quickslice.db
- SECRET_KEY_BASE=${SECRET_KEY_BASE}
- OAUTH_SIGNING_KEY=${OAUTH_SIGNING_KEY}
- EXTERNAL_BASE_URL=https://your-quickslice.example.com
restart: unless-stopped
volumes:
quickslice-data:
Create a .env file:
SECRET_KEY_BASE=$(openssl rand -base64 48)
OAUTH_SIGNING_KEY=z42tsQ4W... # paste your secret key here
Start:
docker compose up -d
#Backfill Configuration
NOTE: These configurations are evolving. If your container runs low on memory or crashes, reduce concurrent workers and requests.
Control memory usage during backfill with these variables:
| Variable | Default | Description |
|---|---|---|
BACKFILL_MAX_PDS_WORKERS |
10 | Max concurrent PDS endpoints |
BACKFILL_PDS_CONCURRENCY |
4 | Max concurrent repo fetches per PDS |
BACKFILL_MAX_HTTP_CONCURRENT |
50 | Global HTTP request limit |
1GB RAM:
BACKFILL_MAX_PDS_WORKERS=8
BACKFILL_PDS_CONCURRENCY=2
BACKFILL_MAX_HTTP_CONCURRENT=30
2GB+ RAM: Use defaults or increase values.
#Resource Requirements
Minimum:
- Memory: 1GB
- CPU: 1 shared core
- Disk: 10GB volume
Recommendations:
- Use SSD-backed volumes for SQLite performance
- Monitor database size and scale volume as needed
#PostgreSQL Deployment
For deployments requiring a full database server, use the PostgreSQL template:
This template provisions a PostgreSQL database alongside Quickslice. The DATABASE_URL is automatically configured.