diff --git a/librespeed/.env.example b/librespeed/.env.example new file mode 100644 index 0000000..372c56d --- /dev/null +++ b/librespeed/.env.example @@ -0,0 +1,50 @@ +# Copy to .env and adjust. .env is git-ignored; this file is not. +# +# NOTE: compose.yaml currently sets these values literally in its +# `environment:` block, so nothing here is read yet. Switch a line to +# ${VAR} in compose.yaml to start using it -- worth doing for the two +# marked SECRET below, which should never sit in a committed file. + +# ─── Basics ───────────────────────────────────────────────────────── +#TITLE=LibreSpeed +#TAGLINE= +# Port on the host; the container always listens on WEBPORT (8080). +#PORT=3011 + +# ─── Telemetry: off by default ────────────────────────────────────── +# Turn this on and results are stored -- which needs a database AND a +# volume, neither of which compose.yaml has today. See the README. +#TELEMETRY=false + +# SECRET. Protects the stats page at /results/stats.php. Required once +# telemetry is on, or anyone can read every result. +#PASSWORD= + +# Shown in the privacy policy as the contact for deletion requests. +# Required for a production install with telemetry. NOTE: the old EMAIL +# variable is deprecated -- this is the current name. +#GDPR_EMAIL=you@example.com + +# Telemetry logs client IPs unless you turn this on. +#REDACT_IP_ADDRESSES=false +#ENABLE_ID_OBFUSCATION=false +# 2-byte hex, e.g. 0x1234abcd. Random if unset -- which means IDs change +# every restart. +#OBFUSCATION_SALT= + +# ─── Database (only when TELEMETRY=true) ──────────────────────────── +# sqlite needs /database mounted or results vanish on recreate. +#DB_TYPE=sqlite +#DB_NAME= +#DB_HOSTNAME= +#DB_PORT= +#DB_USERNAME= +#DB_PASSWORD= + +# ─── ISP name and distance ────────────────────────────────────────── +# SECRET. From ipinfo.io. Without it there is no ISP name, and DISTANCE +# does nothing. +#IPINFO_APIKEY= +#DISABLE_IPINFO=false +# km, mi, or empty to hide it. Needs IPINFO_APIKEY. +#DISTANCE=km diff --git a/librespeed/README.md b/librespeed/README.md new file mode 100644 index 0000000..ad1252c --- /dev/null +++ b/librespeed/README.md @@ -0,0 +1,93 @@ +# LibreSpeed + +A speed test you host yourself. One container, no Flash, no Java, no account — +open the page and it measures the link between the browser and *your* server. + +That last part is the whole point and the whole catch: this does not tell you +how fast your internet is. It tells you how fast the path to this box is, which +is the more useful number when you are debugging your own LAN, your VPN, or a +neighbour's Wi-Fi — and a meaningless one if you point it through a CDN. + +## Quick start + +```bash +docker compose up -d +``` + +Open `http://:3011`. There is nothing to configure and no `.env` needed +for the default read-only setup — see [`.env.example`](.env.example) for what +becomes relevant once you turn telemetry on. + +## Ports + +| Host | Container | Purpose | +|------|-----------|---------| +| 3011 | 8080 | Web UI and the test endpoints | + +The container port follows `WEBPORT`, which defaults to 8080. + +## Why it looks like this + +**`MODE: standalone`** means one container is both the page and the test +endpoint. The alternatives matter only at scale: `backend` is a bare test point, +`frontend` serves a UI that talks to a list of remote backends, and `dual` is +both. For a single box, standalone is the whole story. + +**No volumes, because telemetry is off.** With `TELEMETRY` unset the container +stores nothing and is entirely disposable — `docker compose down` costs you +nothing. The moment you enable it, that stops being true; see the gotchas. + +**Most of the environment block is commented out on purpose.** It is upstream's +menu of options kept close to hand, which is more useful in a file you revisit +once a year than a link to documentation. + +## Gotchas + +- **Turning on telemetry needs a volume that isn't there.** `TELEMETRY: "true"` + stores results in sqlite by default, inside the container, at `/database`. + With no volume mounted the results survive restarts but vanish the moment the + container is recreated — which is to say, on the next `docker compose pull`. + Add `- ./data:/database` before enabling it. +- **Telemetry also wants `PASSWORD`**, which protects the stats page at + `/results/stats.php`. Without it, anyone who finds the URL can read every + result you've recorded, including client IPs. +- **`EMAIL` is deprecated — the current name is `GDPR_EMAIL`.** It is the + address shown in the privacy policy for deletion requests, and upstream + considers it required for a production install with telemetry on. The + commented block in `compose.yaml` still uses the old name. +- **Results log client IP addresses by default.** `REDACT_IP_ADDRESSES: "true"` + turns that off. Worth thinking about before you hand the URL to guests. +- **`DISTANCE` does nothing without `IPINFO_APIKEY`**, and that key is a + credential — it belongs in `.env` and a `${IPINFO_APIKEY}` reference, never in + the committed compose file. +- **A slow result may be your server, not your network.** The test works by + generating and swallowing garbage data, so on a low-power host the CPU can cap + the number before the link does. If you see a suspiciously round ceiling, + check `docker stats` while a test runs — the same trap as + [copyparty on an N100](../copyparty/README.md). +- **`:latest` is unpinned.** Note the Docker tags drop the `v` that the git tags + carry: the release is `v6.3.0`, the image tag is **`6.3.0`** (also `6.3`, `6`, + and `-alpine` variants of each). Pinning `v6.3.0` fails with a manifest error + that looks like a network problem. +- **`restart: always` rather than `unless-stopped`**, so a deliberate stop does + not survive a reboot. The rest of this repo uses the latter. + +## Exposing it + +- [Reverse proxy with Caddy](../docs/reverse-proxy.md) — works, but understand + what you are then measuring: the path to the proxy, shaped by whatever the + proxy does. For a LAN test, reach it directly by IP and skip the proxy. +- [Cloudflare Tunnel](../cloudflare-tunnel/) — **no.** This is a tool whose job + is to move as many gigabytes as it can for as long as you let it. Putting it + behind a tunnel produces a number that measures Cloudflare, while pushing + bulk transfer through a service not meant to carry it. +- [Single sign-on with Authentik](../docs/authentik-sso.md) — forward auth fits + fine; it is a browser-only app with no accounts of its own. Sensible if this + faces the internet, though a public speed test is also a free bandwidth sink + for whoever finds it. + +## Links + +- Upstream: +- Docker options: +- Image: diff --git a/librespeed/compose.yaml b/librespeed/compose.yaml new file mode 100644 index 0000000..81afc08 --- /dev/null +++ b/librespeed/compose.yaml @@ -0,0 +1,19 @@ +services: + speedtest: + container_name: speedtest + image: ghcr.io/librespeed/speedtest:latest + restart: unless-stopped + environment: + MODE: standalone + TITLE: "Gooyban's Speed Meter" + #TELEMETRY: "false" + #ENABLE_ID_OBFUSCATION: "false" + #REDACT_IP_ADDRESSES: "false" + #PASSWORD: + #GDPR_EMAIL:: + #DISABLE_IPINFO: "false" + #IPINFO_APIKEY: "your api key" + #DISTANCE: "km" + #WEBPORT: 8080 + ports: + - "3011:8080" # webport mapping (host:container) \ No newline at end of file