Deployment & Production
Start from a working Getting Started demo, then switch to production Compose with your own secrets.
Use image tag html2rss/web:1 (or pin an exact release). Production Compose lives in html2rss-web/docker-compose.yml with .env.example.
Production compose (recommended)
Section titled “Production compose (recommended)”- Download and copy env:
curl -O https://raw.githubusercontent.com/html2rss/html2rss-web/main/docker-compose.ymlcurl -O https://raw.githubusercontent.com/html2rss/html2rss-web/main/.env.examplecp .env.example .env- Set secrets in
.env:
openssl rand -hex 32 # HTML2RSS_SECRET_KEYopenssl rand -hex 32 # HTML2RSS_ACCESS_TOKEN| Variable | Required | Notes |
|---|---|---|
HTML2RSS_SECRET_KEY |
Yes | ≥ 32 characters |
HTML2RSS_ACCESS_TOKEN |
Yes | ≥ 16 characters; paste into the UI |
AUTO_SOURCE_ENABLED |
Default true |
Keep true for URL-to-RSS |
HEALTH_CHECK_TOKEN |
No | Only if you use authenticated GET /api/v1/health |
SENTRY_DSN / BOTASAURUS_SENTRY_DSN |
No | Separate web vs scraper Sentry projects |
- Start:
docker compose up -dWeb listens on host port 4000 (4000:4000). Botasaurus stays on 127.0.0.1:4010 inside the published mapping from Compose. Open http://localhost:4000/ or http://<LAN_IP>:4000/ and paste HTML2RSS_ACCESS_TOKEN.
Port 4000 on all interfaces is intentional for LAN access. Protect the instance with a strong access token; do not expose an unauthenticated demo token on a shared network.
LAN / Tailscale (plain HTTP)
Section titled “LAN / Tailscale (plain HTTP)”No reverse proxy required. The app does not force HTTPS upgrades on plain HTTP, so LAN IPs keep working. HSTS and CSP upgrade-insecure-requests apply only on HTTPS requests.
Public HTTPS (Caddy example)
Section titled “Public HTTPS (Caddy example)”Terminate TLS in front of the app and forward to port 4000:
services: caddy: image: caddy:2-alpine restart: unless-stopped ports: - "80:80" - "443:443" volumes: - caddy_data:/data command: - caddy - reverse-proxy - --from - ${CADDY_HOST} - --to - html2rss-web:4000
html2rss-web: image: html2rss/web:1 restart: unless-stopped env_file: - path: .env required: false environment: RACK_ENV: production PORT: 4000 HTML2RSS_SECRET_KEY: ${HTML2RSS_SECRET_KEY:?set HTML2RSS_SECRET_KEY} HTML2RSS_ACCESS_TOKEN: ${HTML2RSS_ACCESS_TOKEN:?set HTML2RSS_ACCESS_TOKEN} AUTO_SOURCE_ENABLED: "true" SENTRY_DSN: ${SENTRY_DSN:-} BOTASAURUS_SCRAPER_URL: http://botasaurus:4010
botasaurus: image: html2rss/botasaurus-scrape-api:latest restart: unless-stopped
volumes: caddy_data:Example .env beside Compose:
CADDY_HOST=yourdomain.comHTML2RSS_SECRET_KEY=<openssl rand -hex 32>HTML2RSS_ACCESS_TOKEN=<openssl rand -hex 32># Optional:# HEALTH_CHECK_TOKEN=# SENTRY_DSN=# BOTASAURUS_SENTRY_DSN=After docker compose up -d, check docker compose logs caddy --tail 20 for certificate issuance.
Custom feeds mount
Section titled “Custom feeds mount”Auto-source is the default. To add curated YAML feeds, bind-mount feeds.yml (see Advanced Feeds):
volumes: - type: bind source: ./config/feeds.yml target: /app/config/feeds.yml read_only: trueOperate
Section titled “Operate”GET /api/v1/health/readyfor readiness- Authenticated
GET /api/v1/healthonly whenHEALTH_CHECK_TOKENis set - OpenAPI at
/openapi.yamlon the running instance - Monitoring reference for Sentry and probes
- Environment variables for the full table
