# Cal-Funnel Merge multiple iCalendar feeds into one and serve the result over HTTP. Built with [mergecal](https://pypi.org/project/mergecal/) and designed to run behind Traefik. ## Quick start 1. Copy the environment template: ```bash cp .env.example .env ``` 2. Edit `.env` and set your calendar URLs and Traefik host. 3. Start behind Traefik (requires external `proxy` network): ```bash docker compose up -d ``` 4. Subscribe your calendar client to: ``` https:///calendar.ics ``` ## Local testing (without Traefik) Create `docker-compose.override.yml` (gitignored) with a port mapping: ```yaml services: cal-funnel: ports: - "8080:8080" ``` Then run: ```bash docker compose up -d curl http://localhost:8080/health curl http://localhost:8080/calendar.ics ``` ## Configuration | Variable | Default | Description | |----------|---------|-------------| | `CALENDAR_URLS` | *(required)* | Comma-separated iCal feed URLs | | `FETCH_INTERVAL_SECONDS` | `900` | How often feeds are re-fetched | | `PORT` | `8080` | HTTP listen port | | `CALENDAR_PATH` | `/calendar.ics` | Path served to calendar clients | | `HTTP_TIMEOUT_SECONDS` | `30` | Per-feed fetch timeout | | `PRODID` | *(optional)* | RFC5545 PRODID for merged calendar | | `TRAEFIK_HOST` | *(compose only)* | Hostname for Traefik routing | | `TRAEFIK_CERT_RESOLVER` | *(compose only)* | Traefik cert resolver name | ## Endpoints | Path | Description | |------|-------------| | `/calendar.ics` | Merged iCalendar feed | | `/health` | Health check (`200` when ready) | | `/` | Short HTML page with subscription link | ## Build image ```bash docker build -t cal-funnel:latest . ``` ## License note mergecal is licensed under GPL-3.0. This project uses it as a self-hosted calendar merge tool.