Vercel
Deploy AIOLiveTV on Vercel as a Container Function with PostgreSQL and Redis.
AIOLiveTV can run on Vercel as a Container Function. The Express server and the React frontend stay in the same image; there is no Next.js rewrite.
Public beta (0.1.0-beta). Use this for a personal instance. Breaking
changes are likely before 1.0.
Vercel builds Dockerfile.vercel as a Container service and routes every
request to that image. Scheduled maintenance uses Vercel Cron Jobs against /api/internal/tasks/*.
In Project Settings → General → Framework Settings, set Framework Preset
to Container (or Services). Clear any Build Command and Output
Directory overrides. framework: null plus pnpm run build makes Vercel
look for a public/ folder and fail with No Output Directory named "public".
Keep Root Directory empty (the Git repository root). If it is set to
packages/docs, Vercel builds the documentation site instead of the addon
container.
The instance filesystem is not persistent. SQLite, the data/ directory, and
in-memory caches are not shared between instances. Use PostgreSQL and Redis.
What stays on Vercel
- Dashboard, login, and configuration
- Manifest, catalog, meta, stream, and EPG responses
- Built-in Live TV addons (M3U, XMLTV, Xtream, Vivo TV, Claro TV, Mi.tv)
- Cron-triggered maintenance (inactive users, expired SQL cache, analytics rollup)
What does not run on Vercel
- SQLite
- Stream Probe /
ffprobe(unlessFFPROBE_PATHis provided) - Built-in media proxy (video bytes must go from the provider to Stremio)
- Process-local timers (
setTimeoutbackground tasks)
Required services
- PostgreSQL — Neon, Supabase, or any external Postgres. Prefer a pooler URL.
- Redis / Valkey — Upstash or another Redis compatible with
rediss://.
Environment variables
Set these in the Vercel project settings. Do not set PORT; the platform provides it.
BASE_URL=https://aiolivetv.example.com
SECRET_KEY=<64-character-hex>
DATABASE_URI=postgresql://user:password@host:port/database
DATABASE_POOL_MAX=3
REDIS_URI=rediss://user:password@host:port
REDIS_TIMEOUT=5000
NODE_ENV=production
SYSTEM_LIFECYCLE_ENABLED=false
LOG_LEVEL=info
LOG_FORMAT=json
CRON_SECRET=<long-random-secret>Leave HTTP_ALLOW_PRIVATE_URLS unset (false). The platform must not fetch
user-supplied XMLTV, M3U or addon URLs that point at localhost, private networks
or cloud metadata.
Keep SECRET_KEY stable. Changing it makes existing encrypted configurations
undecryptable.
Optional: ANALYTICS_ENABLED=false for the first deploy. Analytics that remain
enabled are written to PostgreSQL; the in-memory buffer is flushed at the end
of each request.
Deploy
Production deploys run on a published GitHub Release, not on every commit.
vercel.json sets git.deploymentEnabled to false so the Git integration
does not build on push or pull request. The Deploy Vercel workflow
checks out the release tag and runs vercel deploy --prod.
Create a Vercel project from this repository. Set Framework Preset to
Container. Vercel builds Dockerfile.vercel and routes all traffic to
that image.
Attach PostgreSQL and Redis, then set the environment variables above.
In the GitHub repo, add secrets VERCEL_TOKEN, VERCEL_ORG_ID, and
VERCEL_PROJECT_ID. The org and project IDs are in .vercel/project.json
after vercel link. Create the token in the Vercel account tokens
page with Full Account scope. Project-scoped and team-scoped tokens
fail the CLI preflight (GET /v2/user → User not found).
Publish a GitHub Release (or let release-please merge), then open
/api/v1/health on the production URL. To redeploy an existing tag, run
Deploy Vercel with workflow dispatch.
Create a test configuration in the dashboard, install the manifest in Stremio, and verify catalog, meta, stream, and EPG responses.
Confirm that stream URLs point at the original provider, not at the Vercel host.
Raise the Function maxDuration in the Vercel project if large M3U or XMLTV
sources need more than the plan default. Keep the built-in proxy disabled.
Cron jobs
vercel.json registers three daily jobs (Hobby-compatible; more than once per day requires Pro):
| Path | Schedule |
|---|---|
/api/internal/tasks/prune-users | 0 4 * * * |
/api/internal/tasks/clear-expired-cache | 30 4 * * * |
/api/internal/tasks/analytics-rollup | 0 5 * * * |
Each request must include Authorization: Bearer ${CRON_SECRET}. Vercel adds
this header automatically when CRON_SECRET is set.
First-deploy defaults
- PostgreSQL and Redis: required for a healthy production deploy
- M3U, XMLTV/EPG, Xtream, Vivo TV, Claro TV, Mi.tv: enabled from user configuration
- Stream Probe: disabled unless
FFPROBE_PATHis set - Media proxy: disabled
- System lifecycle (restart/stop process): disabled

