Get Started

Self-host your email in ~20 minutes

This guide walks you through cloning Selfmail, wiring up your services, and deploying a fully functional email client for your custom domain.

Prerequisites

  • Node.js 18+ and pnpm installed locally
  • A custom domain you control (e.g. yourdomain.com)
  • A Resend account — free tier works
  • A Supabase account — free tier works
  • Optional: Vercel account for one-click deployment
Step 1

Clone & Install

Clone the repository and install dependencies.

git clone https://github.com/hasimpk/selfmail.git
cd selfmail
pnpm install
Step 2

Configure Environment Variables

Copy the example environment file and fill in your credentials.

cp .env.example .env.local

Open .env.local and set the following variables:

VariableWhere to find itRequired
NEXT_PUBLIC_SUPABASE_URLSupabase → Settings → API Keys → Project URLYes
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEYSupabase → Settings → API Keys → Publishable keyYes
SUPABASE_SERVICE_ROLE_KEYSupabase → Settings → API Keys → Secret keyYes
RESEND_API_KEYResend → API Keys → Create API KeyYes
RESEND_WEBHOOK_SECRETResend → Inbound → your route → Signing SecretYes
FROM_NAMEYour sender display name (e.g. Your Name)Yes
NEXT_PUBLIC_FROM_ADDRESSESComma-separated sender addresses (e.g. you@yourdomain.com)Yes
NEXT_PUBLIC_APP_DOMAINYour domain shown in the app header (e.g. yourdomain.com)Yes
ALLOWED_EMAILYour email address — restricts who can log inNo
Step 3

Set Up Supabase

  1. 1.Go to supabase.com/dashboard and create a new project.
  2. 2.Once ready, go to Settings → API Keys and copy your Project URL, Publishable key, and Secret key.
  3. 3.In the SQL Editor, run the migration files found in supabase/migrations/ — run them in order.
  4. 4.Under Authentication → Providers, enable Email and disable email confirmation (magic link only).
  5. 5.Set your Site URL under Authentication → URL Configuration to your deployed domain (or http://localhost:3000 for local development).
Step 4

Set Up Resend

  1. 1.Create a Resend account and verify your custom domain under Domains. Add the DNS records Resend provides.
  2. 2.Go to API Keys, create a new key, and add it as RESEND_API_KEY.
  3. 3.Under Inbound, create an inbound route for your domain and set the endpoint to:
https://your-domain.vercel.app/api/inbound

Copy the Signing Secret from the inbound route into RESEND_WEBHOOK_SECRET.

Step 5

Run Locally

Start the development server:

pnpm dev

Open localhost:3000 in your browser. Enter your email address to receive a magic link and log in.

Set ALLOWED_EMAIL to your address to restrict access to your account only.

Step 6

Deploy to Vercel

Deploy using the Vercel CLI:

npx vercel --prod

Or import your GitHub repository from the Vercel dashboard. Add all environment variables under Project → Settings → Environment Variables.

Once deployed, update your Resend inbound route URL and Supabase Site URL to your production domain.

Troubleshooting

Common issues

Emails are not appearing in the inbox

Check that your Resend inbound route URL matches your deployed domain exactly (including https://). Verify the webhook is enabled and the signing secret matches RESEND_WEBHOOK_SECRET in your environment.

Magic link login is not working

Ensure Email Auth is enabled in Supabase under Authentication → Providers. Check that your Site URL in Supabase matches your deployed domain. In development, set it to http://localhost:3000.

Database migration errors on first run

Run migration files in order from the supabase/migrations/ folder via the Supabase SQL Editor. If a migration fails, check the error message — it usually points to a missing extension or a table ordering issue.

Inbound emails not routing to the app

Verify your domain's MX records are set to Resend's inbound servers. DNS propagation can take up to 48 hours. Use Resend's domain verification status page to confirm the records are live.

All done

Your inbox is yours now.

Questions or issues? Open an issue on GitHub — contributions are welcome.