Deployment & Production
html2rss-web ships on Docker Hub. Start with the Getting Started guide, then add the production pieces below.
The examples use html2rss/web:1, the recommended major-version tag. Pin an exact release if your deployment process requires it.
Choose Your Production Scope First
Section titled “Choose Your Production Scope First”There are two materially different deployment modes:
- Included feeds only: lowest-maintenance path, suitable when the packaged feed set already covers your needs
- Included feeds plus automatic generation: requires
AUTO_SOURCE_ENABLED=true, bearer-token distribution, and Browserless capacity planning
If you do not need page-URL generation yet, keep AUTO_SOURCE_ENABLED off and ship the simpler mode first.
Prepare for Production
Section titled “Prepare for Production”Before exposing html2rss-web, ensure:
- Your domain (for example
yourdomain.com) resolves to the host running Docker - Inbound TCP ports 80 and 443 reach the host (check firewalls and cloud security groups)
- You are ready to watch the first deployment logs for certificate issuance
- You have a value ready for
HTML2RSS_SECRET_KEY - You have a value ready for
HEALTH_CHECK_TOKENif you plan to monitor authenticatedGET /api/v1/health(the documented Compose stack uses it;/api/v1/health/liveand/api/v1/health/readydo not require it)
If you plan to enable automatic feed generation, also prepare:
BROWSERLESS_IO_API_TOKEN- Browserless capacity appropriate for the sites you expect to render
- an operator plan for how users obtain valid bearer tokens
Why a Reverse Proxy?
Section titled “Why a Reverse Proxy?”A reverse proxy terminates public HTTPS traffic and forwards requests to html2rss-web on your private Docker network.
Option A: Caddy (Automatic HTTPS)
Section titled “Option A: Caddy (Automatic HTTPS)”Caddy handles certificates and redirects.
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} HEALTH_CHECK_TOKEN: ${HEALTH_CHECK_TOKEN:?set HEALTH_CHECK_TOKEN} SENTRY_DSN: ${SENTRY_DSN:-} BROWSERLESS_IO_WEBSOCKET_URL: ws://browserless:4002 BROWSERLESS_IO_API_TOKEN: ${BROWSERLESS_IO_API_TOKEN:?set BROWSERLESS_IO_API_TOKEN} BOTASAURUS_SCRAPER_URL: http://botasaurus:4010
botasaurus: image: html2rss/botasaurus-scrape-api:latest restart: unless-stopped
browserless: image: "ghcr.io/browserless/chromium" restart: unless-stopped environment: PORT: 4002 CONCURRENT: 10 TOKEN: ${BROWSERLESS_IO_API_TOKEN:?set BROWSERLESS_IO_API_TOKEN}
volumes: caddy_data:Create a .env file beside your compose file:
CADDY_HOST=yourdomain.comHTML2RSS_SECRET_KEY=<openssl rand -hex 32>HEALTH_CHECK_TOKEN=<strong bearer token>BROWSERLESS_IO_API_TOKEN=<browserless token>Before starting the stack:
- Set
CADDY_HOSTfor your domain. - Generate
HTML2RSS_SECRET_KEYwithopenssl rand -hex 32. - Set a strong
HEALTH_CHECK_TOKENwhen you use authenticatedGET /api/v1/health; liveness/readiness probes can use/api/v1/health/liveand/api/v1/health/readywithout it. - Leave
BUILD_TAGandGIT_SHAunset unless you intentionally override image metadata in logs. - Adjust optional knobs such as
AUTO_SOURCE_ENABLEDandSENTRY_DSNas needed; refer to the environment reference for details.
After docker compose up -d, run docker compose logs caddy --tail 20; look for certificate obtained.
Re-test after DNS changes with SSL Labs.
Secure Your Instance
Section titled “Secure Your Instance”Harden the application before inviting other users:
- Set a strong
HEALTH_CHECK_TOKENfor authenticatedGET /api/v1/health, and separate strong bearer tokens for any protected feeds - Prefer environment files (
.env) stored outside version control for secrets - Keep any operator-only token distribution flow outside public docs and outside version control
services: 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} HEALTH_CHECK_TOKEN: ${HEALTH_CHECK_TOKEN:?set HEALTH_CHECK_TOKEN} SENTRY_DSN: ${SENTRY_DSN:-} BROWSERLESS_IO_WEBSOCKET_URL: ws://browserless:4002 BROWSERLESS_IO_API_TOKEN: ${BROWSERLESS_IO_API_TOKEN:?set BROWSERLESS_IO_API_TOKEN} BOTASAURUS_SCRAPER_URL: http://botasaurus:4010
botasaurus: image: html2rss/botasaurus-scrape-api:latest restart: unless-stopped
browserless: image: "ghcr.io/browserless/chromium" restart: unless-stopped environment: PORT: 4002 CONCURRENT: 10 TOKEN: ${BROWSERLESS_IO_API_TOKEN:?set BROWSERLESS_IO_API_TOKEN}Store these variables in a .env file and reference it with env_file: as demonstrated in the Caddy example.
Operate & Monitor
Section titled “Operate & Monitor”Keep the instance healthy once it is in production:
- Monitor
https://yourdomain.com/api/v1/healthwith the configured bearer token for authenticated health checks - Review
docker compose logsregularly for feed errors or certificate renewals - Enable automatic image updates for the Docker tag you selected
- Right-size CPU and memory to avoid starvation when parsing large feeds
Auto-update with Watchtower
Section titled “Auto-update with Watchtower”services: watchtower: image: containrrr/watchtower restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock:ro # Optional for private registries only: # - "${HOME}/.docker/config.json:/config.json:ro" command: --cleanup --interval 7200 html2rss-web botasaurus browserless caddyThis Watchtower shape scopes updates to html2rss-web, browserless, and caddy; change the service names if your stack differs.
Check docker compose logs watchtower occasionally to confirm updates are applied.
Resource Guardrails
Section titled “Resource Guardrails”services: html2rss-web: image: html2rss/web:1 deploy: resources: limits: memory: 512M cpus: "0.5" reservations: memory: 256M cpus: "0.25"Adjust limits to match host capacity. Increase memory for large feeds.
Share & Support
Section titled “Share & Support”- Test different feed sources before inviting external users
- Publish
/openapi.yamlfrom the running instance if you expect agents or integrations to call the API directly - Add your instance to the community wiki if you want it listed publicly
- Visit the troubleshooting guide or join the community discussions when you need help
- Ready to contribute fixes or docs? See the contributing guide