- Go 92.7%
- Dockerfile 4.4%
- Shell 2.9%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
Some checks failed
Build and Push to Forgejo Registry / checkout (push) Failing after 30s
|
||
| .forgejo/workflows | ||
| scripts | ||
| .gitignore | ||
| compose.yml | ||
| config.toml | ||
| Dockerfile | ||
| go.mod | ||
| go.sum | ||
| README.md | ||
| server.go | ||
urip
Serve plain-text IP/CIDR lists for pfSense URL aliases. A Go server runs scheduled tasks (bash scripts and/or DNS resolution) and exposes each result as an HTTP endpoint.
How it works
- Every
.shin/app/inputruns on a schedule and writes its result to/tmp/pfbl/<path>.txt, served at/<path>. - Every
[services.<path>]entry withurlsresolves those hosts and serves the IPs at/<path>.dns. - A failed task writes
<path>.error; the endpoint returns that error with HTTP 503 so you can inspect it. GET /lists all available endpoints, sorted and grouped into Scripts and DNS sections.- Restart the container to load new scripts or config.
Inputs (scripts, config) are read-only; the only writable path is /tmp/pfbl inside the container. Nothing is written to the host.
DNS resolution
[services.github]
urls = ["github.com", "api.github.com", "objects.githubusercontent.com"]
Serves /github (from github.sh, if present) and /github.dns (host lookups). Output is one block per host with a # host comment header (pfSense ignores # comment lines in alias lists). Same every interval applies; failed lookups → .dns.error, endpoint returns it with HTTP 503.
# example.com
104.20.23.154
172.66.147.243
# github.com
140.82.121.3
Endpoint auto-discovery
Any *.sh file in scripts/ becomes an endpoint automatically — no config needed. _ in the filename is the path separator, - stays literal:
| Script | Endpoint |
|---|---|
scripts/foo.sh |
/foo |
scripts/foo_bar.sh |
/foo/bar |
scripts/foo-bar_biz.sh |
/foo-bar/biz |
scripts/github/actions.sh |
/github/actions |
Colliding endpoints (e.g. foo_bar.sh and foo/bar.sh): only the first registers, the rest are skipped with a warning.
Config only needed to set a custom interval:
[services.foo]
every = "30m"
The service key is the derived endpoint with . instead of / ([services.github.actions] for github_actions.sh). Only every and urls are read.
pfSense
Firewall → Aliases → URL. One alias per endpoint:
- Name
github→ URLhttp://<container-ip>:8080/github - Name
github-actions→ URLhttp://<container-ip>:8080/github/actions - Name
github-dns→ URLhttp://<container-ip>:8080/github.dns
Add a service
Just drop a script in scripts/ and restart:
- Write
scripts/foo.sh(bash; output goes to stdout, exit nonzero on failure). /fooserves it at the default interval.- Optional: add
[services.foo]+everyinconfig.tomlfor a custom schedule. - Restart container.
Example script:
#!/usr/bin/env bash
set -euo pipefail
curl -fsSL https://api.github.com/meta | jq -r '.git[]'
Run
docker compose up --build -d
docker compose logs -f
curl localhost:8080/github
curl localhost:8080/github.dns
Container model
- Runs as unprivileged user
app(uid 10000). Scripts and config are mounted read-only. - Data lives in
/tmp/pfblinside the container only — ephemeral, regenerated on start. - Rootless Docker works out of the box: no host bind for write access, no privileged operations. The daemon itself runs rootless (dockerd-rootless-setuptool.sh); the image needs nothing special.
- Internal paths (
/app/input,/tmp/pfbl,/app/config.toml,:8080) are hardcoded in the image; overridable viaADDR/SCRIPTS_DIR/DATA_DIR/CONFIGenv vars for local testing only.
Config
[server]
interval = "1h" # default interval for all services
timeout = "60s" # per-script timeout
[services]
# optional; only for custom intervals and DNS urls
[services.github]
every = "1h"
urls = ["github.com"]