Skip to content

Setup Guide

This guide covers everything you need to self-host or deploy CloakMetric, from local development to production.

Before you begin, make sure you have:

  • Node.js 18+ and pnpm installed
  • PostgreSQL 15+ (local or hosted via Neon)
  • AWS Account with SES, S3, Lambda, and SNS access
  • Resend Account for transactional emails
  • GitHub Account for CI/CD
  • Vercel Account for deployment (recommended)
  1. Clone the repository

    Terminal window
    git clone https://github.com/cloakmetric/cloakmetric.git
    cd cloakmetric
  2. Install dependencies

    Terminal window
    pnpm install
  3. Set up environment variables

    Terminal window
    cp .env.example .env

    Edit .env with your configuration (see Environment Variables below).

  4. Set up the database

    Terminal window
    pnpm db:push
  5. Start the development server

    Terminal window
    pnpm dev

    Open http://localhost:3000 in your browser.

Create a .env file in the project root with the following variables:

VariableDescriptionExample
DATABASE_URLPostgreSQL connection stringpostgresql://user:pass@localhost:5432/cloakmetric
NEXTAUTH_URLYour app URLhttp://localhost:3000
NEXTAUTH_SECRETRandom secret for NextAuthopenssl rand -base64 32
VariableDescriptionExample
AWS_ACCESS_KEY_IDAWS IAM access keyAKIA...
AWS_SECRET_ACCESS_KEYAWS IAM secret keywJalr...
AWS_REGIONAWS region for SESus-east-1
AWS_S3_BUCKETS3 bucket for email storagecloakmetric-emails
AWS_SNS_TOPIC_ARNSNS topic for email eventsarn:aws:sns:us-east-1:...
VariableDescriptionExample
RESEND_API_KEYResend API key for transactional emailsre_...
VariableDescriptionExample
POLAR_ACCESS_TOKENPolar access tokenpolar_...
POLAR_WEBHOOK_SECRETPolar webhook signing secretwhsec_...
POLAR_ORGANIZATION_IDYour Polar organization IDorg_...
VariableDescriptionExample
UPSTASH_REDIS_REST_URLUpstash Redis REST URLhttps://...upstash.io
UPSTASH_REDIS_REST_TOKENUpstash Redis REST tokenAX...
  1. Install PostgreSQL (if not already installed)

    Terminal window
    brew install postgresql@15
    brew services start postgresql@15
  2. Create the database

    Terminal window
    createdb cloakmetric
  3. Set your DATABASE_URL

    DATABASE_URL="postgresql://your_user:your_password@localhost:5432/cloakmetric"
  4. Run migrations

    Terminal window
    pnpm db:push

Neon is the recommended hosted PostgreSQL for production deployments.

  1. Create a Neon account and project at console.neon.tech

  2. Copy the connection string from the dashboard

  3. Set it as your DATABASE_URL

    DATABASE_URL="postgresql://user:pass@ep-cool-name-123456.us-east-1.aws.neon.tech/cloakmetric?sslmode=require"
  4. Run migrations against the remote database

    Terminal window
    pnpm db:push

CloakMetric uses AWS SES for sending and receiving emails. This section covers the full setup.

  1. Go to AWS Console → SES → Verified Identities
  2. Click Create Identity and select Domain
  3. Enter your domain (e.g., yourdomain.com)
  4. AWS will provide DNS records to add

Add these records to your domain’s DNS:

TypeNameValuePurpose
TXT_amazonses.yourdomain.com(provided by AWS)Domain verification
CNAMEselector1._domainkey.yourdomain.com(provided by AWS)DKIM signing
CNAMEselector2._domainkey.yourdomain.com(provided by AWS)DKIM signing
CNAMEselector3._domainkey.yourdomain.com(provided by AWS)DKIM signing
MXyourdomain.com10 inbound-smtp.us-east-1.amazonaws.comInbound email
TXTyourdomain.comv=spf1 include:amazonses.com ~allSPF record
  1. Create an S3 bucket (e.g., cloakmetric-emails)

  2. Add a bucket policy to allow SES to write:

    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Effect": "Allow",
    "Principal": {
    "Service": "ses.amazonaws.com"
    },
    "Action": "s3:PutObject",
    "Resource": "arn:aws:s3:::cloakmetric-emails/*",
    "Condition": {
    "StringEquals": {
    "AWS:SourceAccount": "YOUR_AWS_ACCOUNT_ID"
    }
    }
    }
    ]
    }
  3. Set AWS_S3_BUCKET in your .env

Receipt rules tell SES what to do with incoming emails.

  1. Go to SES → Email Receiving → Rule Sets
  2. Create a new rule set (or use the default)
  3. Create a rule with these actions:
    • S3 action — Store email in your S3 bucket
    • Lambda action — Invoke your email processing Lambda
  4. Set the recipient condition to your domain

The Lambda function processes incoming emails stored in S3.

  1. Create a new Lambda function (Node.js 18+ runtime)
  2. Set the handler to process S3 events from SES
  3. Add environment variables: DATABASE_URL, AWS_S3_BUCKET
  4. Grant the Lambda role permissions to read from S3 and write to your database
  5. Connect it to the SES receipt rule

SNS topics handle email event notifications (bounces, complaints, deliveries).

  1. Create an SNS topic (e.g., cloakmetric-email-events)

  2. In SES, go to Configuration Sets

  3. Create a configuration set and add an SNS event destination

  4. Subscribe your API endpoint to the SNS topic:

    https://yourdomain.com/api/webhooks/ses
  5. Set AWS_SNS_TOPIC_ARN in your .env

  1. Go to SES → Configuration Sets
  2. Create a new configuration set (e.g., cloakmetric)
  3. Add event destinations:
    • Bounce → SNS topic
    • Complaint → SNS topic
    • Delivery → SNS topic
  4. The application will use this configuration set when sending emails
  1. Go to SES → Account Dashboard
  2. Click Request Production Access
  3. Fill out the form with your use case, expected volume, and bounce/complaint handling procedures
  4. AWS typically reviews within 24 hours

Resend handles transactional emails (account verification, password resets, notifications).

  1. Create a Resend account at resend.com
  2. Go to API Keys and create a new key
  3. Set RESEND_API_KEY in your .env
  1. Go to Domains in the Resend dashboard
  2. Add your domain
  3. Add the DNS records Resend provides (DKIM, SPF)
  4. Wait for verification (usually a few minutes)

Polar handles payments and subscription management.

  1. Create a Polar organization at polar.sh

  2. Create subscription products matching your plans:

    • Free — $0/month
    • Pro — $29/month
    • Business — $79/month
  3. Go to Settings → Developers and create an access token

  4. Set up a webhook endpoint:

    https://yourdomain.com/api/webhooks/polar
  5. Add to your .env:

    POLAR_ACCESS_TOKEN=polar_...
    POLAR_WEBHOOK_SECRET=whsec_...
    POLAR_ORGANIZATION_ID=org_...

Upstash provides serverless Redis for rate limiting and caching.

  1. Create an Upstash account at upstash.com

  2. Create a new Redis database

  3. Copy the REST URL and token from the dashboard

  4. Add to your .env:

    UPSTASH_REDIS_REST_URL=https://...upstash.io
    UPSTASH_REDIS_REST_TOKEN=AX...
  1. Connect your repository to Vercel

    Import your GitHub repository at vercel.com/new.

  2. Set environment variables

    Add all environment variables from your .env to the Vercel project settings under Settings → Environment Variables.

  3. Configure the build

    Vercel auto-detects Next.js. The default settings should work:

    • Build Command: pnpm build
    • Output Directory: .next
  4. Set up the production database

    Use your Neon production connection string as DATABASE_URL.

  5. Deploy

    Push to main to trigger automatic deployment.

For Pro+ plans, users can connect custom domains for their aliases.

  1. In Vercel, go to Settings → Domains
  2. Add your custom domain (e.g., docs.cloakmetric.com)
  3. Update DNS records as instructed by Vercel
  4. SSL is provisioned automatically

The repository includes two GitHub Actions workflows:

Runs on every pull request:

name: CI
on:
pull_request:
branches: [main]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm type-check
- run: pnpm test

Deploy Workflow (.github/workflows/deploy.yml)

Section titled “Deploy Workflow (.github/workflows/deploy.yml)”

Runs on push to main:

name: Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfile
# Run database migrations
- name: Run migrations
run: pnpm db:push
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
# Vercel handles the actual deployment via its GitHub integration
# This step runs migrations before the deploy completes

Emails not being received

  • Check MX records point to SES inbound SMTP
  • Verify the SES receipt rule is active
  • Check Lambda function logs in CloudWatch
  • Ensure the S3 bucket policy allows SES writes

Bounces increasing suddenly

  • Check SES sending quotas
  • Verify domain DNS records haven’t changed
  • Review SES reputation dashboard
  • Check if your domain was added to any blocklists

Authentication errors

  • Verify NEXTAUTH_SECRET is set
  • Check NEXTAUTH_URL matches your deployment URL
  • Ensure database is accessible and migrations are current

Rate limiting issues

  • Check Upstash Redis connection
  • Verify UPSTASH_REDIS_REST_URL and token are correct
  • Monitor rate limit usage in the Upstash dashboard

Payment webhook failures

  • Verify POLAR_WEBHOOK_SECRET matches your Polar config
  • Check that the webhook URL is publicly accessible
  • Review webhook delivery logs in the Polar dashboard

Database connection errors

  • For Neon: ensure ?sslmode=require is in your connection string
  • Check that your IP is allowed (if using IP allowlists)
  • Verify credentials haven’t expired

Before going live, verify everything on this list:

Infrastructure

  • PostgreSQL database provisioned (Neon recommended)
  • AWS SES domain verified and out of sandbox
  • S3 bucket created with correct policy
  • Lambda function deployed and connected
  • SNS topics created and subscribed
  • SES configuration set active
  • Upstash Redis database created

DNS

  • MX records pointing to SES
  • SPF record includes amazonses.com
  • DKIM records configured
  • Domain verified in SES
  • Domain verified in Resend
  • Custom domain configured in Vercel

Services

  • Resend API key configured
  • Polar products and webhooks set up
  • All environment variables set in Vercel
  • GitHub Actions secrets configured

Testing

  • Send a test email through an alias
  • Receive an inbound email and verify forwarding
  • Test bounce and complaint handling
  • Complete a subscription flow
  • Verify rate limiting works
  • Run the full test suite