Speedtest Tracker runs the Ookla speedtest on a schedule and stores the results, so you get a history graph of your connection instead of a number you read once and forget. It's how you settle the argument about whether the line got worse, with data.
What it is
A Laravel app that schedules speedtests against your own connection, records download, upload, ping, jitter and packet loss, and graphs them over time. Scheduled tests can be a several-times-a-day heartbeat or a weekly record.
Before you start
- Speedtest data caps are a real consideration on metered or mobile connections. Set the schedule accordingly, and know that a test can use several hundred megabytes.
- Measure at the router if you can. A test from a laptop on Wi-Fi measures Wi-Fi, not your line.
- The scheduled test container needs more than the web container. The image bundles both; the default compose starts them as a single service with an internal queue.
1 — Write the compose file
services:
speedtest-tracker:
image: alexjustesen/speedtest-tracker:latest
container_name: speedtest-tracker
restart: unless-stopped
ports:
- "127.0.0.1:8000:8000"
environment:
APP_KEY: base64:CHANGE_ME_32_bytes_base64=
APP_URL: https://speed.example.com
DB_CONNECTION: sqlite
QUEUE_CONNECTION: sync
CACHE_DRIVER: file
SCHEDULE_ENABLED: "true"
SCHEDULE_INTERVAL: "0 */6 * * *"
TZ: UTC
volumes:
- ./data:/var/www/html/storage/app
healthcheck:
test: ["CMD", "curl", "-fs", "http://localhost:8000"]
interval: 60s
timeout: 10s
retries: 3
2 — Start it
mkdir -p ~/services/speedtest-tracker/data
cd ~/services/speedtest-tracker
# generate a real app key rather than pasting the placeholder
docker run --rm -e APP_KEY=base64:dummy alexjustesen/speedtest-tracker:latest \
php artisan key:generate --show
# paste the output into APP_KEY above
3 — First-run setup
- Create the admin account at
https://speed.example.comafter generating the app key. Without a validAPP_KEYsessions won't survive a page load. - Under Settings → Schedule, enable scheduled tests and set the cron expression.
0 */6 * * *is every six hours — plenty for a trend line without burning data. - Click Run test once manually and watch the first result land. If it errors, check outbound HTTPS from the container:
docker exec speedtest-tracker curl -sI https://www.speedtest.net | head -1 - Set retention in Settings. Rows accumulate slowly but there's no reason to keep years of samples for a home connection.
- Compare against your ISP's advertised speed. Consistently 80–90% of advertised is normal; consistently under 50% is worth a phone call.
4 — Read the graph
# average the last 30 days straight from the database
docker exec speedtest-tracker sqlite3 /var/www/html/database/database.sqlite3 \
"select date(created_at), round(avg(download_mbps),1), round(avg(ping),1)
from speed_tests
where created_at > date('now','-30 day')
group by 1 order by 1 desc limit 10;"