Skip to main content
This guide walks you through setting up a local Vibe Kanban Cloud instance for development and testing.

Prerequisites

Before you begin, ensure you have:
  • Docker and Docker Compose installed
  • Git to clone the repository
  • Node.js 20+ and pnpm (for running the desktop client)
  • A GitHub or Google OAuth application

Step 1: Clone the Repository

Step 2: Create OAuth Application

You need at least one OAuth provider. Choose GitHub, Google, or both.
  1. Go to GitHub Developer Settings
  2. Click New OAuth App
  3. Fill in the details:
    • Application name: Vibe Kanban Local
    • Homepage URL: http://localhost:3000
    • Authorization callback URL: http://localhost:3000/v1/oauth/github/callback
  4. Click Register application
  5. Copy the Client ID
  6. Click Generate a new client secret and copy it

Step 3: Configure Environment

Create a .env.remote file in crates/remote/:
Copy the output and create your .env.remote:
.env.remote
For production or self-hosting on a server, add PUBLIC_BASE_URL (your public URL, e.g. https://kanban.example.com) and REMOTE_SERVER_PORTS=0.0.0.0:3000:8081 so the server is reachable from other hosts. Defaults keep local dev unchanged.
Never commit .env.remote to version control. It’s already in .gitignore.

Step 4: Start the Stack

From the crates/remote directory, start all services:
Or from the repo root:
This starts:
  • PostgreSQL on port 5433 (external) / 5432 (internal)
  • ElectricSQL on port 3000 (internal only, used by Remote Server for real-time sync)
  • Remote Server on port 3000 (external) / 8081 (internal)
  • Relay Server on port 8082 (external and internal)
The remote server binds to 127.0.0.1:3000 only - it’s not accessible from other machines. For production, use a reverse proxy.
Wait until you see health checks passing:

Step 5: Access the Web Interface

Open http://localhost:3000 in your browser. You should see the Vibe Kanban Cloud login page. Sign in with your configured OAuth provider (GitHub or Google).

Step 6: Connect the Desktop Client (Optional)

To use the desktop client with your local server:
The desktop client will now connect to your local Cloud instance instead of the hosted version. To test relay/tunnel mode end-to-end, add:
This mode requires local HTTPS + Caddy routing (next step).

Step 7: Optional Local HTTPS + Caddy (required for tunnel-mode testing)

Use the checked-in Caddyfile.example in the repository root. It routes:
  • localhost:3001 -> remote server (127.0.0.1:3000)
  • relay.localhost:3001 and *.relay.localhost:3001 -> relay server (127.0.0.1:8082)
If you use this HTTPS setup, update OAuth callback URLs to:
  • GitHub: https://localhost:3001/v1/oauth/github/callback
  • Google: https://localhost:3001/v1/oauth/google/callback

Stopping the Stack

To stop all services:
To stop and remove all data (fresh start):

Troubleshooting

Ensure the database is healthy before the server starts:
Verify your OAuth callback URLs match exactly for your setup:
  • HTTP local stack:
    • GitHub: http://localhost:3000/v1/oauth/github/callback
    • Google: http://localhost:3000/v1/oauth/google/callback
  • HTTPS + Caddy:
    • GitHub: https://localhost:3001/v1/oauth/github/callback
    • Google: https://localhost:3001/v1/oauth/google/callback
ElectricSQL requires the electric_sync database user, which is created automatically by the Remote Server on first startup. If ElectricSQL fails to connect:
  1. Ensure the Remote Server has started successfully and run its migrations
  2. Check that ELECTRIC_ROLE_PASSWORD is set in your .env.remote
  3. Restart the stack — ElectricSQL will retry the connection
If port 3000 is in use, you can change it in docker-compose.yml:
Update your OAuth callback URLs accordingly.
Problem: curl -sk https://relay.localhost:3001/health returns HTML, and relay/tunnel fails.Cause: Caddy routed relay hostnames to the remote app (:3000) instead of relay server (:8082).Solution:
  1. Use host-specific routing for relay.localhost and *.relay.localhost
  2. Verify:
    • curl -sk https://relay.localhost:3001/health returns {"status":"ok"}
    • curl -sk https://localhost:3001/v1/health returns remote server health JSON

Next Steps

Once you have local development working, you can:
  • Deploy to Fly.io for production (coming soon)
  • Deploy with Docker Compose on your own server (coming soon)