Turn GitHub repositories into RSS feeds. Add a repo, pick what to follow, and subscribe to the generated feed URL in any reader.
Built for tracking projects that ship via CI artifacts (where a green workflow run is the update) as well as the usual releases/commits/tags/issues.
- Feed types: Releases, Actions (successful runs of one workflow, with an optional branch filter), Commits (branch-aware), Tags, Issues (PRs filtered out).
- Workflow picker auto-populates from the repo — no need to know the filename.
- Optional GitHub token for a 5000 req/hr limit and private-repo access, with a deep link that pre-fills GitHub's token page with the minimal scope.
- OPML export to bulk-import every feed into your reader at once.
- Server-side caching so reader polling doesn't burn your rate limit.
- Reverse-proxy aware (honours
X-Forwarded-*),/healthzendpoint, multi-arch image (amd64 + arm64).
The template lives at unraid/gitfeed.xml. Until/unless it's in Community Apps,
add it manually: Docker → Add Container → Template field, paste
https://raw.githubusercontent.com/websterwh/gitfeed/main/unraid/gitfeed.xml.
Default WebUI port is 8579; data persists to /mnt/user/appdata/gitfeed.
services:
gitfeed:
image: ghcr.io/websterwh/gitfeed:latest
container_name: gitfeed
restart: unless-stopped
ports:
- "8579:8080" # admin UI + API (put behind auth)
- "8580:8081" # public feeds + healthz (safe to expose)
volumes:
- ./data:/datadocker compose up -ddocker run -d --name gitfeed --restart unless-stopped \
-p 8579:8080 -p 8580:8081 -v gitfeed_data:/data \
ghcr.io/websterwh/gitfeed:latestThen open http://<host>:8579 (admin). Feeds are served on http://<host>:8580.
Without a token you share GitHub's anonymous 60 requests/hour limit and feeds will start failing once you add a few. A token raises that to 5000/hour.
In the app's Settings, click Create a token on GitHub — it opens the token
page pre-filled. For public repos, leave all scopes unchecked: a scopeless
classic token already gets the higher rate limit and can read public data (this is
the most secure option). Tick "I need to track private repos" before clicking
the link to add the repo scope. Generate, paste, Save.
| Type | Source | Branch filter | Best for |
|---|---|---|---|
| Releases | /releases |
no | repos that cut formal releases |
| Actions | /actions/workflows/{wf}/runs?status=success |
yes | CI-artifact projects |
| Commits | /commits |
yes | tracking a branch closely |
| Tags | /tags |
no | version tags without formal releases |
| Issues | /issues?state=open (PRs removed) |
no | bug/discussion tracking |
Each feed gets a stable URL like http://<host>:8579/feed/<id>.xml.
The container exposes two listeners:
| Container port | Default host port | Serves | Expose how |
|---|---|---|---|
| 8080 | 8579 | full UI + API + feeds | behind auth (Cloudflare Access, proxy basic-auth, or LAN-only) |
| 8081 | 8580 | /feed/<id>.xml and /healthz only |
public — safe to leave unauthenticated |
The public listener has no UI, no /api, no token handling, and no add/delete —
it physically cannot read or change config, so an RSS reader can pull feeds without
ever touching the admin surface.
Point a gated hostname at the admin port and a public hostname at the feeds port.
Both honour X-Forwarded-*, so feed URLs render with whichever hostname you used.
Caddy:
# admin — protect this (e.g. Cloudflare Access in front, or forward_auth)
gitfeed.example.com {
reverse_proxy webby:8579
}
# public — your reader hits this, no auth
feeds.example.com {
reverse_proxy webby:8580
}
RSS readers can't log in through an Access page. With the split above you simply
don't put Access on feeds.example.com — only on gitfeed.example.com. No
path bypass rules needed. Add feeds via the admin UI, then hand the
https://feeds.example.com/feed/<id>.xml URLs to your reader.
| Env var | Default | Purpose |
|---|---|---|
GITFEED_DATA |
/data |
Where config.json is stored |
GITFEED_CACHE_TTL |
600 |
Seconds a feed is cached before re-fetching |
GITFEED_ITEM_LIMIT |
25 |
Max items per feed |
PORT |
8080 |
In-container listen port |
The GitHub token is not an env var — it's entered in the UI and stored in
config.json so it survives restarts and isn't visible in docker inspect.
Pushing to main (or a v* tag) runs .github/workflows/docker-publish.yml,
which builds amd64 + arm64 and pushes to ghcr.io/<you>/gitfeed. After the first
successful run, open the package on GitHub and set its visibility to Public so
Unraid and docker pull work without auth.
MIT — see LICENSE.