Skip to main content
Shipyard is a self-hosted CI/CD engine that listens for GitHub push events and automatically clones, builds, tests, and deploys your project inside isolated Docker containers. This guide walks you through standing up the server locally, pointing GitHub webhooks at it, and running your first build.

Prerequisites

Before you begin, make sure you have the following installed and configured:
  • Node.js 20+ — the runtime for the Shipyard server
  • Docker — used to run the PostgreSQL database and to build and test your projects
  • PostgreSQL — Shipyard stores users, projects, builds, and secrets here (you’ll run it in Docker in the steps below)
  • A GitHub OAuth App — Shipyard uses GitHub OAuth for authentication and the GitHub API to register webhooks on your repositories

Create a GitHub OAuth App

  1. Go to GitHub → Settings → Developer Settings → OAuth Apps and click New OAuth App.
  2. Fill in the fields:
    • Application name: anything you like (e.g., Shipyard Local)
    • Homepage URL: http://localhost:8080
    • Authorization callback URL: your FRONTEND_URL (e.g., http://localhost:3000)
  3. Click Register application.
  4. Copy the Client ID and generate a Client Secret — you’ll need both for your .env file.
Shipyard requests the following GitHub OAuth scopes: read:user, repo, and read:org. These allow it to read your profile and email, register webhooks on repositories, and list your organization memberships.

Set up Shipyard

1

Install dependencies

Clone the repository and install Node.js dependencies:
npm install
2

Start PostgreSQL

Run a PostgreSQL container using Docker. Replace the placeholder values with credentials of your choice — you’ll use these same values in your DATABASE_URL below.
docker run --name pipeline-db \
  -e POSTGRES_USER=<username> \
  -e POSTGRES_PASSWORD=<password> \
  -e POSTGRES_DB=<database> \
  -p 5432:5432 \
  -d postgres:alpine
3

Configure environment variables

Create a .env file in the project root. The ENCRYPTION_KEY must be a cryptographically random 32-byte value encoded as hex — generate one with the command shown below.
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
Then create your .env:
DATABASE_URL=postgresql://<username>:<password>@localhost:5432/<database>
CLIENT_ID=your_github_oauth_client_id
CLIENT_SECRET=your_github_oauth_client_secret
SECRET=your_jwt_signing_secret
ENCRYPTION_KEY=your_generated_32_byte_hex_key
WEBHOOK_SECRET=your_webhook_secret
BASE_DOMAIN=lvh.me:8080
WEBHOOK_CALLBACK=https://your-tunnel-url.ngrok.io
FRONTEND_URL=http://localhost:3000
See the environment variables reference for a full description of each value.
4

Push the database schema

Run Drizzle Kit to create all the required tables in your PostgreSQL database:
npx drizzle-kit push
5

Start the server

Start Shipyard in development mode (with file watching) or in production mode after building:
npm run dev
The server starts on port 8080. You can reach the health check endpoint at http://localhost:8080/health and the API root at http://localhost:8080/api.

Expose webhooks locally

GitHub needs a publicly reachable URL to send push events to. If you’re running Shipyard on your local machine, use a tunneling tool to expose port 8080:
ngrok http 8080
After starting the tunnel, copy the public URL it provides and set it as WEBHOOK_CALLBACK in your .env file, then restart the server. Shipyard will register this URL as the webhook endpoint when you connect a repository.

Verify your setup

Once the server is running, confirm everything is working:
curl http://localhost:8080/health
# {"message":"OK"}
If the database connection fails, the server exits immediately with an error message — check that your PostgreSQL container is running and that DATABASE_URL matches the credentials you used in step 2.

Next steps

Connect a repository

Select a GitHub repo, choose a branch, and configure your build command

Environment variables

Full reference for every configuration variable Shipyard uses

Build pipeline

Understand how Shipyard clones, builds, and tests your project

Local testing

Test subdomain routing and deployed projects on your machine

Build docs developers (and LLMs) love