Appearance
Self-hosting
Atlas can run on your own infrastructure. The same backend (Python/FastAPI) and frontend (React/Vite) you'd run in dev work in production with the right env, a Postgres database, and a Redis instance. This page covers the supported shape; for a single-user dev environment, see Quick Start.
Components
| Component | What it is | How to run |
|---|---|---|
| Backend | Python/FastAPI app | uvicorn behind a reverse proxy |
| Frontend | React/Vite SPA | Static build, served from a CDN or nginx |
| Database | PostgreSQL | Any managed or self-hosted Postgres ≥ 14 |
| Cache | Redis | Any managed or self-hosted Redis ≥ 6 |
| Docs (optional) | VitePress static site | npm run build in apps/docs/ → static deploy |
Required env vars
The minimum to boot:
DATABASE_URL— Postgres connection stringREDIS_URL— Redis connection stringSECRET_KEY— JWT signing key. Long random string. Rotating invalidates all sessions.FINNHUB_API_KEY— equity quotesEODHD_API_KEY,EODHD_BASE_URL— EOD prices and fundamentalsCESIUM_ION_TOKEN,VITE_CESIUM_ION_TOKEN— globe rendering
Optional providers (degrade the relevant features gracefully if absent):
OPENSKY_USERNAME,OPENSKY_PASSWORD— anonymous access works at lower rate limitsMARINETRAFFIC_API_KEY— gates the AIS layerSTRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRET,STRIPE_PRICE_ID_*— only if you're running paid plans
The full list with placeholders lives in .env.example.
What NOT to do
The project's secrets-handling rules apply doubly to self-hosted deployments:
- Never commit
.env. Verify.gitignoreexcludes.env,.env.local,.env.*.local. - Never call EODHD / Finnhub / Stripe directly from the frontend. The frontend talks only to the Atlas backend, which proxies to upstream providers.
- Never put backend-only credentials behind a
VITE_*prefix. Frontend env vars are bundled into the client and become public. - Never log full URLs containing tokens — service modules strip the
api_tokenquery param before logging.
Deployment shapes
Three supported shapes:
Single-host
One VM, everything on it (backend + nginx serving the frontend bundle + Postgres + Redis). Lowest ops complexity, fine for personal use or small teams. ~2 vCPU / 4 GB RAM minimum.
Backend on app platform + managed DB
Backend on Fly.io / Railway / Render / Heroku-style platform; Postgres and Redis managed by the same provider. Frontend static-deployed to Cloudflare Pages or Vercel. This is the recommended shape for production.
Container orchestration
Backend image deployed to Kubernetes / ECS / Cloud Run. Standard 12-factor app — read all configuration from env, log to stdout, single process. Health check at /health.
Health and monitoring
The backend exposes a /health endpoint for liveness checks (backend/routes/health.py). Hook it up to your platform's liveness probe.
For deeper monitoring, instrument the backend with your APM of choice; structured logging is in place via the logging module — every service module uses logger = logging.getLogger(__name__).
Updating
- Pull the latest tag.
- Run database migrations (Alembic —
alembic upgrade head). - Restart the backend.
- Rebuild and redeploy the frontend (
npm run buildthen static deploy). - Smoke-test /health and a few panels.
The backend reads credentials at request time (per the _key() pattern), so credential rotation doesn't strictly require a restart — but a restart is the safe default after a config change.
Limits
- Atlas is not designed for multi-tenant isolation between organizations on a single deployment. If you need org-level isolation, run separate deployments.
- The OSINT data providers (OpenSky, MarineTraffic) impose their own rate limits; high-frequency or large-fleet workloads may exceed free tiers fast.