Skip to main content

Overview

Sptfy.in requires configuration in two places:
  1. Backend (VPS): .env file for PocketBase environment variables
  2. Frontend (Cloudflare Pages): Build environment variables

Backend Configuration (PocketBase)

Environment Variables

The .env file in your ~/pb-docker directory configures the PocketBase backend.

Required Variables

# Cloudflare Turnstile secret key (REQUIRED)
CF_SECRET_KEY=your_cloudflare_turnstile_secret_here
Production secret: Get this from Cloudflare Dashboard → Turnstile → Your Site → Secret KeyDevelopment secret: The test key 1x0000000000000000000000000000000AA always passes validation (useful for local dev).

Optional Maintenance Mode Variables

These are frontend environment variables (set in Cloudflare Pages, not in .env):
# Maintenance mode settings
PUBLIC_MAINTENANCE_MODE=false
PUBLIC_MAINTENANCE_TYPE=migration
PUBLIC_MAINTENANCE_NOTE=link creation and dashboard edits may be temporarily unavailable.
PUBLIC_MAINTENANCE_SCHEDULED=2026-02-25T10:00:00Z
PUBLIC_MAINTENANCE_END=2026-02-25T11:00:00Z
PUBLIC_STATUS_PAGE_URL=https://status.sptfy.in
How it works:
  • PUBLIC_MAINTENANCE_MODE=true → Force maintenance mode ON
  • PUBLIC_MAINTENANCE_MODE=false → Follow scheduled window (auto-activates between SCHEDULED and END)
  • PUBLIC_MAINTENANCE_MODE=off → Force maintenance mode OFF

Docker Compose Configuration

The docker-compose.yml file defines the PocketBase container setup.
services:
  pocketbase:
    image: ghcr.io/muchobien/pocketbase:0.23.12
    tty: true
    container_name: pocketbase
    restart: unless-stopped
    ports:
      - '8091:8090'
    volumes:
      - ./pb_data:/pb_data
      - ./pb_public:/pb_public
      - ./pocketbase/pb_hooks:/pb_hooks
      - ./pocketbase/pb_migrations:/pb_migrations
      - '/etc/localtime:/etc/localtime:ro'
      - '/etc/timezone:/etc/timezone:ro'
    healthcheck:
      test: wget --no-verbose --tries=1 --spider http://localhost:8090/api/health || exit 1
      interval: 60s
      timeout: 10s
      retries: 2
    environment:
      TZ: 'Asia/Jakarta'
      CF_SECRET_KEY: '${CF_SECRET_KEY}'

Key Configuration Options

ports
string
8091:8090 - Maps host port 8091 to container port 8090. Change if port 8091 is already in use.
volumes
array
Persistent data directories:
  • ./pb_data - Database files (SQLite)
  • ./pb_public - Public file storage
  • ./pocketbase/pb_hooks - Custom API hooks (JavaScript)
  • ./pocketbase/pb_migrations - Database migrations
healthcheck
object
Checks /api/health every 60 seconds. Container marked unhealthy after 2 failed retries.
TZ
string
default:"Asia/Jakarta"
Timezone for container. Change to your preferred timezone (e.g., America/New_York, Europe/London).
CF_SECRET_KEY
string
required
Cloudflare Turnstile secret key (loaded from .env file).

Changing the Port

If port 8091 conflicts with another service:
  1. Edit docker-compose.yml:
    ports:
      - '8092:8090'  # Use port 8092 instead
    
  2. Restart the container:
    docker compose down
    docker compose up -d
    
  3. Update your Nginx reverse proxy to use the new port (see Deployment).

Changing the Timezone

  1. Edit docker-compose.yml:
    environment:
      TZ: 'America/New_York'  # Your timezone
    
  2. Restart the container:
    docker compose restart
    
Find your timezone: List of tz database time zones

Frontend Configuration (Cloudflare Pages)

Required Environment Variables

Set these in Cloudflare Pages → Your Project → Settings → Environment Variables.
# Cloudflare Turnstile site key (public)
PUBLIC_TURNSTILE_SITE_KEY=your_turnstile_site_key

# PocketBase API URL (your VPS backend)
PUBLIC_POCKETBASE_URL=https://pbbase.sptfy.in
PUBLIC_TURNSTILE_SITE_KEY
string
required
Get this from Cloudflare Dashboard → Turnstile → Your Site → Site Key. This is the public key (safe to expose).
PUBLIC_POCKETBASE_URL
string
required
The public URL of your PocketBase instance. Must be HTTPS in production (set up via Nginx reverse proxy).

Build Configuration

Cloudflare Pages auto-detects SvelteKit. Default settings work, but you can customize:
# Build command
npm run build

# Build output directory
.svelte-kit/cloudflare

# Node.js version
20

# Install command
npm install
Sptfy.in uses pnpm for package management. If Cloudflare Pages doesn’t auto-detect pnpm, you may need to:
  1. Add a .nvmrc file with 20 (Node.js version)
  2. Use build command: npx pnpm install && npx pnpm build

PocketBase Admin Configuration

Admin Panel Access

Access the PocketBase admin panel at:
  • Local development: http://127.0.0.1:8090/_/
  • Production: https://pbbase.sptfy.in/_/
Security: Restrict admin panel access in production. Use Nginx to:
  • Require IP whitelist for /_/ path
  • Use strong admin password (16+ characters)
  • Enable 2FA if PocketBase supports it in your version

Collections Configuration

Key collections in the database:
  • users - User accounts (OAuth via Spotify)
  • random_short - Short links (both random and custom slugs)
  • analytics - Click analytics and tracking
  • blocks - Blocked users/IPs
See Database Setup for detailed collection schemas.

API Rules

PocketBase uses collection-level API rules. Important settings:
  • List/View Rules: Control who can read records
  • Create Rules: Control who can create records
  • Update Rules: Control who can modify records
  • Delete Rules: Control who can delete records
The schema is defined in pocketbase/pb_migrations/. Migrations run automatically on container start.

Backup Configuration

PocketBase Built-in Backups

PocketBase supports automated backups to S3-compatible storage. Production setup uses Cloudflare R2 for backups:
  1. Go to PocketBase Admin → Settings → Backups
  2. Configure S3 settings:
    • Endpoint: https://<account-id>.r2.cloudflarestorage.com
    • Bucket: Your R2 bucket name
    • Region: auto
    • Access Key: R2 access key ID
    • Secret Key: R2 secret access key
  3. Set backup schedule (e.g., daily at 3 AM)
Test your backup restoration process regularly. A backup you can’t restore is useless.

Manual Backups

Create a manual backup:
# Stop the container
cd ~/pb-docker
docker compose down

# Backup pb_data directory
tar -czf pb_data_backup_$(date +%Y%m%d).tar.gz pb_data/

# Restart the container
docker compose up -d
Restore from backup:
# Stop the container
docker compose down

# Remove current data
rm -rf pb_data/

# Extract backup
tar -xzf pb_data_backup_20260302.tar.gz

# Restart container
docker compose up -d

Security Best Practices

1

Secure your .env file

# Set proper permissions (only owner can read)
chmod 600 ~/pb-docker/.env
2

Use strong secrets

  • Use production Cloudflare Turnstile keys (not test keys)
  • Set a strong PocketBase admin password
  • Rotate secrets periodically
3

Restrict admin access

Configure Nginx to whitelist IPs for /_/ path (admin panel)
4

Enable HTTPS

Use Nginx with Let’s Encrypt SSL certificates (see Deployment)
5

Monitor logs

# Check container logs regularly
docker compose logs -f --tail=100

Next Steps

  • Database Setup - Configure PocketBase collections and data
  • Deployment - Set up Nginx reverse proxy and Cloudflare Pages

Build docs developers (and LLMs) love