Docs/Self-Hosting Guide

Self-Hosting Guide

Run VibeBasket on your own infrastructure with the single-node deployment shape the product is currently optimized for: one app process, one SQLite database, optional OAuth, and optional encrypted backup storage.

Docker (recommended)

The easiest way to self-host VibeBasket. The image is a lean multi-stage build based on Node.js 22 Alpine. The SQLite database file is persisted through a named Docker volume so your data survives container restarts and upgrades.

Step 1 — Clone & configure

git clone https://github.com/mhmtayberk/VibeBasket.git
cd VibeBasket

# Copy the example env file and fill in your values
cp .env.example .env

Step 2 — Start with Docker Compose

docker compose up -d

# View logs
docker compose logs -f web

Step 3 — Seed the catalog

# Run the catalog sync inside the running container
docker compose exec web node scripts/catalog-sync.mjs

Upgrading

git pull
docker compose up -d --build

Helm (Kubernetes)

A fully-featured Helm chart is available in charts/vibebasket/. The chart deploys a single-replica Deployment with a ClusterIP Service, optional Ingress, and a PersistentVolumeClaim for the SQLite database. Non-secret runtime values belong under .Values.env, while secrets such as AUTH_SECRET and OAuth client secrets belong under .Values.secretEnv or an existing Kubernetes Secret.

git clone https://github.com/mhmtayberk/VibeBasket.git
cd VibeBasket

helm install vibebasket ./charts/vibebasket \
  --set env.NEXTAUTH_URL=https://vibebasket.example.com \
  --set secretEnv.AUTH_SECRET=$(openssl rand -base64 32) \
  --set env.AUTH_GITHUB_ID=your-client-id \
  --set secretEnv.AUTH_GITHUB_SECRET=your-client-secret \
  --set env.AUTH_GITHUB_ENABLED=true \
  --set persistence.size=5Gi

# Or install with a custom values file
helm install vibebasket ./charts/vibebasket -f my-values.yaml

Manual Installation

Requires Node.js >=20 and pnpm >=9. Suitable for VMs, bare-metal servers, or platforms that do not run Docker.

git clone https://github.com/mhmtayberk/VibeBasket.git && cd VibeBasket
cp .env.example .env          # fill in values (see below)
pnpm install --frozen-lockfile
pnpm run build
node scripts/catalog-sync.mjs # seed the database
pnpm --filter web start        # production server on :3000

Environment Variables

OAuth Callback URLs

When enabling OAuth authentication, configure the exact redirect callback URL in each provider's developer console:

GitHub
${NEXTAUTH_URL}/api/auth/callback/github
Google
${NEXTAUTH_URL}/api/auth/callback/google
Apple
${NEXTAUTH_URL}/api/auth/callback/apple
Microsoft Entra ID
${NEXTAUTH_URL}/api/auth/callback/microsoft-entra-id

For local development, replace ${NEXTAUTH_URL} with http://localhost:3000.

Never commit your .env file. The .env .gitignore. In Docker deployments, pass secrets as environment variables or use Docker secrets.

If you run VibeBasket behind Cloudflare, keep application security headers enabled and disable script-injecting edge features for this site unless you explicitly plan for them. In practice that means turning off Browser Insights, Rocket Loader, and Speed Brain / speculative prefetch features that inject inline or third-party scripts, otherwise the site will log CSP violations by design.

VariableRequiredDescription
DATABASE_URLRequiredSQLite connection string. Use file:/data/vibebasket.db for Docker (volume mount) or an absolute path for manual installs.
AUTH_SECRETRequiredRandom 32-byte secret used to sign Next-Auth session tokens. Generate with: openssl rand -base64 32
NEXTAUTH_URLRequiredThe public canonical URL of your deployment, e.g. https://vibebasket.example.com. Required for OAuth redirects.
AUTH_TRUST_HOSTOptionalSet to true when running behind a reverse proxy such as Coolify, Nginx, or Cloudflare. Strongly recommended for production OAuth callback reliability.
AUTH_GITHUB_ID / SECRETOptionalGitHub OAuth App credentials. Set AUTH_GITHUB_ENABLED=true to enable.
AUTH_GOOGLE_ID / SECRETOptionalGoogle OAuth credentials. Set AUTH_GOOGLE_ENABLED=true to enable.
AUTH_APPLE_ID / SECRETOptionalApple Sign-In credentials. Set AUTH_APPLE_ENABLED=true to enable.
AUTH_MICROSOFT_ENTRA_ID_ID / SECRETOptionalMicrosoft Entra ID (Azure AD) credentials. Set AUTH_MICROSOFT_ENTRA_ID_ENABLED=true. Uses /common/ endpoint by default.
ADMIN_OAUTH_EMAILSOptionalComma-separated list of admin emails. Access is granted only when the OAuth account email is allowlisted and verified.
TRUST_PROXYOptionalSet to true when running behind Cloudflare, Nginx, or another trusted reverse proxy. Proxy IP headers are ignored otherwise.
CATALOG_REFRESH_TOKENOptionalOptional token required for authenticated production callers that use /api/catalog?refresh=1.
BACKUP_STORAGE_BACKENDOptionalBackup storage backend: local, s3, r2, spaces, azure, or gcs. Defaults to local. Can also be set via admin panel.
BACKUP_S3_* / R2_* / SPACES_*OptionalS3-compatible storage credentials (endpoint, region, bucket, access key, secret key). Covers AWS S3, Cloudflare R2, and DigitalOcean Spaces.
BACKUP_AZURE_CONNECTION_STRING / CONTAINEROptionalAzure Blob Storage connection string and container name.
BACKUP_GCS_BUCKET / PROJECT_IDOptionalGoogle Cloud Storage bucket name and GCP project ID.

Bundle TTL & Cleanup

Anonymous bundles expire after 48 hours. Registered user bundles persist for 365 days. The platform periodically purges expired bundles and stale session tokens. Administrators can trigger a manual force cleanup from the admin dashboard under System Health.

Admin Dashboard

The admin panel at /admin provides catalog sync controls, backup management, FTS5 index health checks, database integrity diagnostics, force cleanup utilities, user overview telemetry, and admin email configuration. Access is gated by the ADMIN_OAUTH_EMAILS environment variable.

Helm Deployment

A Helm chart is available at charts/vibebasket/ for Kubernetes deployments. The chart includes a Deployment, Service, Ingress, and PersistentVolumeClaim for SQLite storage.

$ helm install vibebasket ./charts/vibebasket \
--set env.NEXTAUTH_URL=https://vibebasket.example.com \
--set secretEnv.AUTH_SECRET=<generated-secret>

The deployment uses strategy: Recreate to prevent SQLite corruption during updates. Pod securityContext runs as non-root user 1001 with all capabilities dropped. Production secrets should use existingSecret instead of embedding credentials in values.

Before exposing a public domain, walk through the repository's production readiness checklist in docs/PRODUCTION_READINESS_CHECKLIST.md.

SQLite WAL Mode

VibeBasket enables SQLite WAL (Write-Ahead Logging) mode on startup. This allows concurrent reads during writes and is required for the catalog sync process. Do not mount the database file on a network filesystem (NFS, CIFS) because WAL locking relies on local OS primitives. If you run multiple Node.js replicas, use a load balancer that routes all writes to a single instance, or migrate to a Turso remote database.