Owlmetry
Self-Hosting

Installation

Step-by-step VPS setup — clone the repo, install dependencies, configure the database, and build.

Step-by-step guide to installing Owlmetry on a fresh Ubuntu 24.04 VPS. Estimated time: 15-20 minutes.

1. Run the setup script

SSH into your VPS as root and run the setup script. It installs Node.js 22, PostgreSQL 16, nginx, pm2, pnpm, and creates the database.

curl -fsSL https://raw.githubusercontent.com/owlmetry/owlmetry/main/deploy/setup-ubuntu-vps.sh -o setup-ubuntu-vps.sh
bash setup-ubuntu-vps.sh

Save the DATABASE_URL printed at the end. You will need it in step 3.

The script is idempotent and safe to run again if interrupted.

2. Clone and build

The setup script creates /opt/owlmetry as an empty directory. Clone the repo into it:

cd /opt/owlmetry
git clone https://github.com/owlmetry/owlmetry.git .
pnpm install
pnpm build

The build compiles all packages in dependency order: shared then db then server, plus the Next.js web dashboard.

3. Configure environment

cp .env.example .env

Edit .env with your values:

NODE_ENV=production
DATABASE_URL=postgresql://owlmetry:<password>@localhost:5432/owlmetry
JWT_SECRET=<random-64-char-string>
PORT=4000
HOST=0.0.0.0
CORS_ORIGINS=https://yourdomain.com
WEB_APP_URL=https://yourdomain.com
API_PUBLIC_URL=https://api.yourdomain.com
COOKIE_DOMAIN=.yourdomain.com
MAX_DATABASE_SIZE_GB=8
RESEND_API_KEY=<your-resend-key>
EMAIL_FROM=[email protected]

# Event attachments (required in production — server refuses to start without the signing secret)
OWLMETRY_ATTACHMENTS_PATH=/opt/owlmetry-attachments
OWLMETRY_ATTACHMENTS_SIGNING_SECRET=<random-hex-string, must differ from JWT_SECRET>
OWLMETRY_ATTACHMENTS_INTERNAL_URI=/_attachments/

Generate the secrets:

openssl rand -base64 48    # JWT_SECRET
openssl rand -hex 32       # OWLMETRY_ATTACHMENTS_SIGNING_SECRET (must NOT equal JWT_SECRET)

Create the attachments directory so the API server can write to it:

mkdir -p /opt/owlmetry-attachments

See Configuration for a full reference of all environment variables.

4. Run migrations

Migrations run from packages/db and do not auto-load the root .env, so prefix the command with DATABASE_URL:

DATABASE_URL='postgresql://owlmetry:<password>@localhost:5432/owlmetry' pnpm db:migrate

This creates all database tables and sets up monthly event partitions. The events, metric_events, and funnel_events tables use PARTITION BY RANGE on the timestamp column. Partitions for the current month plus the next 2 months are created automatically.

Your first user account will be auto-created when you log in through the dashboard or CLI.

5. Verify the server starts

Test that the API server runs:

node apps/server/dist/index.js

You should see output indicating the server is listening on port 4000. Press Ctrl+C to stop.

Test the health endpoint:

curl -s http://localhost:4000/health
# {"status":"ok"}

Next steps

Continue to Deployment to configure nginx, pm2, SSL, and firewall for production use.

Development seed data

For development or testing only, you can populate the database with sample data:

pnpm dev:seed         # Creates admin user, team, project, app, and API keys
pnpm dev:seed-events  # Generates 200 random test events across 24 hours

Do not run the seed commands in production. The seed API keys are committed to the repository and publicly known.

Ready to get started?

Connect your agent via MCP or CLI and start tracking.