How to Self-Host World Monitor: Vercel, Docker, and Desktop Deployment Guide
I wanted to run my own instance of World Monitor - not just for privacy, but because I needed to customize the data sources and have full control over the deployment. After diving into the codebase, I discovered there are actually three solid options for self-hosting, each with its own trade-offs.
Let me walk through what I learned.
Why Self-Host World Monitor?
Before we get into the how, let’s talk about why you’d want to self-host in the first place.
If you’re running an intelligence dashboard, you might have concerns about:
- API keys - You don’t want your Finnhub, OpenSky, or AISStream keys sitting on someone else’s servers
- Customization - You want to add your own data sources or modify the UI
- Privacy - Your organization requires all tools to run on internal infrastructure
- Reliability - You need guaranteed uptime without dependency on a third-party service
World Monitor is built with self-hosting in mind. The architecture supports everything from a simple static deployment to a full-featured cloud installation.
Option 1: Vercel Edge Functions (Recommended for Most Users)
The easiest path to self-hosting is deploying to Vercel. The entire application is designed around Vercel’s edge runtime.
Getting Started
git clone https://github.com/koala73/worldmonitor.gitcd worldmonitormake installnpm run devThis gets you a local development server. But for production, you’ll want to understand the deployment topology:
| Service | Platform | Role |
|---|---|---|
| SPA + Edge Functions | Vercel | Static files, API endpoints, middleware |
| AIS Relay | Railway | WebSocket proxy, seed loops |
| Redis | Upstash | Cache layer, rate limiting |
| Convex | Convex Cloud | Contact form, waitlist |
Understanding Edge Functions
All API endpoints live in the api/ directory as self-contained JavaScript files. Each file becomes a Vercel Edge Function. The key constraint: you cannot import from ../src/ or ../server/ - they run in a different runtime.
The gateway pipeline for every request:
- Origin check (403 if disallowed)
- CORS headers
- OPTIONS preflight handling
- API key validation
- Rate limiting
- Route matching
- Handler execution
- ETag generation + 304 Not Modified
- Cache header application
Cache Tier Configuration
The system uses five cache tiers, and understanding these is crucial for performance:
| Tier | s-maxage | Use case |
|---|---|---|
| fast | 300s | Live events, flight status |
| medium | 600s | Market quotes |
| slow | 1800s | ACLED events, cyber threats |
| static | 7200s | Humanitarian summaries |
| daily | 86400s | Static reference data |
Build Variants
Here’s something I found interesting - you can build different variants for different audiences:
npm run build # Production buildnpm run build:full # Full variant (geopolitical)npm run build:tech # Tech variantnpm run build:finance # Finance variantThis lets you run focused instances - tech.yourdomain.com for technology intelligence, finance.yourdomain.com for markets, etc.
Option 2: Docker Deployment
For those who prefer containerized deployments or need to run on Kubernetes/Docker Swarm, there’s a multi-arch Docker image.
Pulling and Running
The image is published to GitHub Container Registry (GHCR):
docker pull ghcr.io/koala73/worldmonitor:latestThe container uses nginx to serve the built SPA and proxies API requests to upstream services. This is great when you need:
- Consistent deployment across environments
- Integration with existing container orchestration
- Air-gapped or restricted network deployments
What the Dockerfile Does
Looking at the architecture, the Docker image:
- Builds the SPA during the image build process
- Configures nginx for static file serving
- Sets up proxy rules for API endpoints
- Supports both amd64 and arm64 architectures
The downside of Docker deployment: you lose the edge function benefits. API calls will have higher latency compared to Vercel’s global edge network. But for many use cases, especially internal deployments, this trade-off is acceptable.
Option 3: Desktop App (Fully Local)
If you need complete offline capability or want zero network dependency on external servers, the desktop app is the answer.
Available Platforms
Pre-built binaries are available for:
- Windows (.exe)
- macOS (Apple Silicon and Intel)
- Linux (.AppImage)
Building from Source
npm run desktop:build:full # Build desktop appnpm run desktop:package:macos:fullnpm run desktop:package:windows:fullThe desktop app is built with Tauri 2.x, which wraps the web application in a native shell. This gives you:
- Zero external dependencies - Everything runs locally
- Native performance - Direct filesystem and OS integration
- Offline operation - Works without internet (for cached data)
The trade-off: you lose real-time data updates since there’s no backend processing. But for historical analysis or specific use cases, this is exactly what you need.
The Missing Piece: Railway Relay
Here’s something that tripped me up initially. Some APIs simply don’t work well with Vercel’s edge functions:
- OAuth2 flows require stable endpoints (OpenSky authentication)
- WebSocket streams need persistent connections (AIS vessel tracking)
- Some APIs block Vercel IP ranges entirely
The solution is a Railway relay server. Looking at the architecture, the relay handles:
- AIS WebSocket stream
- OpenSky OAuth2 authentication
- Telegram MTProto (26 OSINT channels)
- OREF rocket alerts
- Polymarket proxy
- ICAO NOTAM proxy
- RSS feeds for blocked domains
If you need real-time AIS data or Telegram monitoring, you’ll need to deploy the relay component. This is a Node.js service that runs persistently and forwards data to your Vercel deployment.
Environment Configuration
The beauty of World Monitor’s design: basic operation works without any environment variables. You can deploy it and it just works.
For enhanced features, you’ll want to configure these optional keys:
# Stock quotesFINNHUB_API_KEY=
# Oil analyticsEIA_API_KEY=
# Internet outagesCLOUDFLARE_API_TOKEN=
# Protest dataACLED_ACCESS_TOKEN=
# Aircraft trackingOPENSKY_CLIENT_ID=OPENSKY_CLIENT_SECRET=
# Vessel trackingAISSTREAM_API_KEY=VITE_WS_RELAY_URL=
# AI SummarizationGROQ_API_KEY=OPENROUTER_API_KEY=OLLAMA_API_URL=OLLAMA_MODEL=The environment variables are well-documented in .env.example, and each is truly optional. The system gracefully degrades when keys are missing.
Redis and Caching Architecture
If you’re deploying at scale, you’ll want Redis. The cache architecture is clever:
Bootstrap seed (Railway writes to Redis) ↓ missIn-memory cache (per Vercel instance) ↓ missRedis (cross-instance) ↓ missUpstream API fetchThis prevents cache stampedes and ensures fresh data. Upstash Redis works well because it’s:
- Serverless (no infrastructure to manage)
- Edge-compatible
- Has built-in rate limiting
Security Considerations
Three areas need attention for secure deployments:
Content Security Policy
The CSP must stay in sync across three locations:
index.htmlmeta tagvercel.jsonHTTP headersrc-tauri/tauri.conf.json(for desktop)
If you modify allowed origins for any feature, update all three.
Bot Protection
The middleware filters known crawlers on API and asset paths, but explicitly allows social preview bots (Twitter, Facebook, LinkedIn) for proper link previews.
Rate Limiting
Per-IP sliding window rate limiting via Upstash, with per-endpoint overrides for high-traffic paths. This prevents abuse while keeping the service responsive for legitimate users.
Monitoring Your Deployment
Health endpoints help you monitor the system:
/api/health- System health check- Per-key staleness detection
- Seed metadata freshness tracking
These are useful for setting up alerts in your monitoring system of choice.
Which Option Should You Choose?
After working through all three options, here’s my recommendation:
Vercel + Railway Relay - Best for most users. You get global edge performance with optional real-time features. Minimal ops burden.
Docker - Choose this if you’re already running Kubernetes/Docker Swarm, or if you have strict compliance requirements around containerized deployments.
Desktop App - Perfect for individual analysts who need offline capability or want to run completely air-gapped.
The codebase architecture makes all three viable because the separation between frontend and API is clean. You can even mix approaches - run the desktop app while pointing it to your own Vercel deployment for API calls.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments