Deployment & Production
html2rss-web ships on Docker Hub. Start with the Getting Started guide, which uses docker-compose.quickstart.yml. Make sure the one-file demo works first, 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:
- Automatic generation enabled: primary self-hosted workflow, requires
AUTO_SOURCE_ENABLED=trueandHTML2RSS_ACCESS_TOKEN - Included feeds fallback only: lower-maintenance path when the Feed Directory already covers your needs
If you do not need page-URL generation yet, keep AUTO_SOURCE_ENABLED off and ship the fallback mode only.
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
HTML2RSS_ACCESS_TOKEN
If you plan to enable automatic feed generation, also prepare:
- a clear way to give users the same
HTML2RSS_ACCESS_TOKENyour instance expects - optional advanced-rendering infrastructure only if harder sites later prove they need it
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} 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:Create a .env file beside your compose file:
CADDY_HOST=yourdomain.comHTML2RSS_SECRET_KEY=<openssl rand -hex 32>HTML2RSS_ACCESS_TOKEN=<strong access token># Optional only if you want authenticated GET /api/v1/health# HEALTH_CHECK_TOKEN=<strong health token>Before starting the stack:
- Set
CADDY_HOSTfor your domain. - Generate
HTML2RSS_SECRET_KEYwithopenssl rand -hex 32. - Set a strong
HTML2RSS_ACCESS_TOKEN. This is the token users paste into the web UI. - Leave
HEALTH_CHECK_TOKENunset unless you intentionally use authenticatedGET /api/v1/health. - 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
HTML2RSS_ACCESS_TOKENand rotate it when needed - Prefer environment files (
.env) stored outside version control for secrets - Keep token sharing/distribution outside public docs and outside version control
- Give trusted users the same current
HTML2RSS_ACCESS_TOKENthrough your normal operator channel - If you use authenticated
GET /api/v1/health, set a strongHEALTH_CHECK_TOKEN; do not leaveCHANGE_ME_HEALTH_CHECK_TOKENanywhere in production
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} 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-stoppedStore 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:
- 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
- Use
GET /api/v1/health/readyfor standard readiness checks - Add authenticated
GET /api/v1/healthonly when your operator tooling needs it
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 caddyThis Watchtower shape scopes updates to html2rss-web, botasaurus, 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