For the fastest setup, see the Quick Start.
Prerequisites
Requirements
- VPS with Minimum 2GB RAM, 2 CPU cores, 20GB storage and linux distribution with minimum security
- Domain name pointed to your VPS IP
- SSH access to your VPS
Step-by-Step VPS Setup
1. Prepare Your VPS
Connect to your VPS and install:- Docker Engine: Follow the official guide and the Post installation steps
- Node.js: Follow the official guide (required for the setup CLI)
2. Setup and Configure
The easiest way to get started is with the Inbox Zero CLI. You can either use it standalone or from within the cloned repo. Option A: Standalone (no clone needed).env template automatically.
Option B: From the cloned repo
.env.example to .env and set the values yourself.
If doing this manually edit then you’ll need to configure:
- Google OAuth:
GOOGLE_CLIENT_IDandGOOGLE_CLIENT_SECRET - LLM Provider: Uncomment one provider block and add your API key
- Optional: Microsoft OAuth, external Redis, etc.
.env.example variables that are commented out. If you’re using Docker Compose leave them commented - Docker Compose sets these automatically with the correct internal hostnames.
4. Deploy
Pull and start the services with your domain:ghcr.io/elie222/inbox-zero:latest and will be automatically pulled.
Important: The NEXT_PUBLIC_BASE_URL must be set as a shell environment variable when running docker compose up (as shown above). Setting it in apps/web/.env will not work because docker-compose.yml overrides it.
Using External Database Services (Optional)
Thedocker-compose.yml supports different deployment modes using profiles:
| Profile | Description | Use when |
|---|---|---|
--profile all | Includes Postgres and Redis containers | Default, simplest setup |
--profile local-redis | Local Redis only | Using managed Postgres (RDS, Neon, Supabase) |
--profile local-db | Local Postgres only | Using managed Redis (Upstash, ElastiCache) |
| (no profile) | No local databases | Using managed services for both (production recommended) |
apps/web/.env:
- External Postgres: Set
DATABASE_URLandDIRECT_URL - External Redis: Set
UPSTASH_REDIS_URLandUPSTASH_REDIS_TOKEN
5. Check Logs
Wait for the containers to start, then run the database migrations:6. Access Your Application
Your application should now be accessible at:http://your-server-ip:3000(if accessing directly)https://yourdomain.com(if you’ve set up a reverse proxy with SSL)
Scheduled Tasks
The Docker Compose setup includes acron container that handles scheduled tasks automatically:
| Task | Frequency | Endpoint | Cron Expression | Description |
|---|---|---|---|---|
| Scheduled actions | Every minute | /api/cron/scheduled-actions | * * * * * | Executes delayed/scheduled actions when QStash is not configured |
| Email watch renewal | Every 6 hours | /api/watch/all | 0 */6 * * * | Renews Gmail/Outlook push notification subscriptions |
| Meeting briefs | Every 15 minutes | /api/meeting-briefs | */15 * * * * | Sends pre-meeting briefings to users with the feature enabled |
| Follow-up reminders | Every 30 minutes | /api/follow-up-reminders | */30 * * * * | Processes follow-up reminder notifications |
YOUR_CRON_SECRET with the value of CRON_SECRET from your .env file.
Optional: QStash for Advanced Features
Upstash QStash is a serverless message queue that enables scheduled and delayed actions. It’s optional but recommended for the full feature set. When QStash isn’t configured, we fall back to internal API calls and cron for scheduled actions. This works without QStash, but lacks built-in retries/deduping. Features that benefit from QStash:| Feature | Without QStash | With QStash |
|---|---|---|
| Email digest | ✅ Works (sync, no retries) | ✅ Full support |
| Delayed/scheduled email actions | ✅ Works via cron fallback | ✅ Full support |
| AI categorization of senders* | ✅ Works (sync) | ✅ Works (async with retries) |
| Bulk inbox cleaning* | ✅ Works (sync, no throttling) | ✅ Full support |
.env: