# Self-hosted IPTVnator The self-hosted image contains both pieces required for the browser PWA: - Angular PWA static files served by nginx - The monorepo `web-backend` Express app proxied under `/api` The historical standalone `4gray/iptvnator-backend` image is no longer needed for the default Docker deployment. ## Run With Docker Compose From the repository root: ```bash docker compose -f docker/docker-compose.yml up --build -d ``` The ready-to-run compose file is [`docker-compose.yml`](./docker-compose.yml). By default the app is available at . No additional environment variables, backend repository checkout, or separate backend container are required for the default local deployment. ## Build The Image ```bash docker build -t 4gray/iptvnator -f docker/Dockerfile . ``` The image build runs: ```bash pnpm nx build web --configuration=pwa pnpm nx build web-backend ``` ## Published Docker Tags Pull request builds validate the Dockerfile without pushing an image. Docker Hub publishing happens only from trusted repository events. Publishing requires the repository secrets `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN`; pull request builds and default manual runs do not use those secrets. | Tag pattern | Published from | Use case | | -------------------------- | ------------------------ | ------------------------------------------------------------------------- | | `latest` | `master` pushes | Default self-hosted image for users who want the newest merged PWA build. | | `-pwa` | `master` pushes | Latest PWA image for the current `package.json` version. | | `-pwa-` | `master` pushes | Immutable PWA image for a specific merged commit within a version. | | `sha-` | `master` pushes | Commit-addressable image, useful for rollback and support diagnostics. | | `` / `v` | `v*` release tags | Release image aligned with a repository release tag. | | `stable` | Stable `v*` release tags | Most recent non-prerelease tagged release image. | | `manual-` | Manual runs with `push` | Explicit maintainer-triggered rebuilds outside normal publish events. | Use `latest` for the simplest self-hosted setup. Pin `sha-` or `-pwa-` when you need reproducible deployments. Use release tags when you want the Docker image to track a tagged IPTVnator release rather than every merge to `master`. ## Runtime Configuration The container writes `/usr/share/nginx/html/assets/app-config.js` on startup. That file sets `window.__IPTVNATOR_CONFIG__.BACKEND_URL`, which the PWA reads before it creates `PwaService`. These variables are supported by the Docker image. The compose file sets the safe local defaults shown below. | Variable | Default | Purpose | | ---------------------------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | `BACKEND_URL` | `/api` | Browser-facing backend URL used by the PWA. Keep `/api` for the bundled nginx proxy. | | `CLIENT_URL` | `http://localhost:4333` | Allowed browser origin for backend CORS. Use the public URL when hosting behind a reverse proxy. Multiple origins can be comma-separated. | | `PORT` | `3000` | Internal Express backend port. nginx proxy config is rendered from the template to match it at startup. | | `IPTVNATOR_PROXY_ALLOW_PRIVATE_NETWORKS` | `0` | Set to `1` or `true` only for trusted local/LAN deployments that intentionally proxy private network IPTV or mock endpoints. | | `NODE_EXTRA_CA_CERTS` | unset | Optional Node.js CA bundle path for providers using private certificate authorities. Mount the CA file into the container and set this path. | The web backend proxy accepts only `http` and `https` provider URLs. The PWA first registers provider URLs through `/provider-targets`, then uses the returned `targetId` for playlist, Xtream, and Stalker proxy calls. The backend blocks loopback, private, link-local, and reserved network targets by default so a publicly exposed instance cannot be used as a generic internal-network fetcher. If you enable `IPTVNATOR_PROXY_ALLOW_PRIVATE_NETWORKS=1`, keep the instance restricted to trusted users. For providers that use private certificate authorities, keep TLS validation enabled and pass the CA bundle to Node: ```yaml services: iptvnator: volumes: - ./ca.pem:/etc/ssl/private/provider-ca.pem:ro environment: NODE_EXTRA_CA_CERTS: /etc/ssl/private/provider-ca.pem ``` The entrypoint renders the nginx config from `docker/nginx.conf`, starts the backend, waits for `/health`, and only then starts nginx. The nginx config serves the PWA with SPA fallback, avoids caching `assets/app-config.js`, and proxies `/api/*` to the internal backend. The Dockerfile and compose file both define a health check against `/api/health`. If nginx or the backend exits after startup, the entrypoint exits the container so Docker Compose can apply the `restart: unless-stopped` policy. ## Local Validation ```bash pnpm nx test web-backend pnpm nx build web --configuration=pwa --skip-nx-cache pnpm nx build web-backend pnpm nx run web-e2e:e2e -- --project=chromium --grep @self-hosted docker compose -f docker/docker-compose.yml config ```