No description
  • Go 92.7%
  • Dockerfile 4.4%
  • Shell 2.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
pika 1210af6e41
Some checks failed
Build and Push to Forgejo Registry / checkout (push) Failing after 30s
testing hetzner
2026-09-09 15:28:14 +02:00
.forgejo/workflows testing hetzner 2026-09-09 15:28:14 +02:00
scripts adding sample scripts 2026-09-09 13:31:42 +02:00
.gitignore renaming stuff + adding dns instead of URLs 2026-09-09 14:11:17 +02:00
compose.yml adding ci/cd + fixing sorts 2026-09-09 14:26:01 +02:00
config.toml adding dns resolution to the pages 2026-09-09 13:51:22 +02:00
Dockerfile adding ci/cd + fixing sorts 2026-09-09 14:26:01 +02:00
go.mod adding ci/cd + fixing sorts 2026-09-09 14:26:01 +02:00
go.sum batman2 2026-09-09 13:01:24 +02:00
README.md adding ci/cd + fixing sorts 2026-09-09 14:26:01 +02:00
server.go adding ci/cd + fixing sorts 2026-09-09 14:26:01 +02:00

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 .sh in /app/input runs on a schedule and writes its result to /tmp/pfbl/<path>.txt, served at /<path>.
  • Every [services.<path>] entry with urls resolves 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 → URL http://<container-ip>:8080/github
  • Name github-actions → URL http://<container-ip>:8080/github/actions
  • Name github-dns → URL http://<container-ip>:8080/github.dns

Add a service

Just drop a script in scripts/ and restart:

  1. Write scripts/foo.sh (bash; output goes to stdout, exit nonzero on failure).
  2. /foo serves it at the default interval.
  3. Optional: add [services.foo] + every in config.toml for a custom schedule.
  4. 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/pfbl inside 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 via ADDR/SCRIPTS_DIR/DATA_DIR/CONFIG env 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"]