Speedtest Tracker Common — Shared Application Configuration
SpeedtestTracker_Common is the shared application layer for Speedtest Tracker.
It is not deployed on its own; instead it supplies the Speedtest Tracker-specific
configuration that both SpeedtestTracker_GKE and
SpeedtestTracker_CloudRun build on, so the two
platform variants behave identically where it matters. End users never configure
this layer directly — it has no deployment UI inputs of its own — but understanding
what it provides explains the defaults you see in the platform docs.
For the infrastructure that actually provisions and runs Speedtest Tracker, see the platform guides (SpeedtestTracker_GKE, SpeedtestTracker_CloudRun) and the foundation guides (App_GKE, App_CloudRun, App_Common).
1. What this layer provides
| Area | Provided by SpeedtestTracker_Common | Where it surfaces |
|---|---|---|
| Cryptographic secrets | Generates the Laravel APP_KEY (base64:<44-char base64>) and stores it in Secret Manager | Injected automatically as secret env APP_KEY |
| Container image | Fixes the prebuilt linuxserver/speedtest-tracker image (no custom build) | container_image output of the platform deployment |
| Database engine | Fixes Cloud SQL for MySQL 8.0 as the only supported engine | §Database in the platform guides |
| Database bootstrap | Defines the first-deploy job (db-init) that creates the database, user, and grants | initialization_jobs output |
| Speed test schedule | Sets SPEEDTEST_SCHEDULE and PRUNE_RESULTS_OLDER_THAN — the in-process Laravel scheduler that fires automated speed tests | Application behaviour in the platform guides |
| Core settings | Sets DB_CONNECTION = mysql, DB_PORT = 3306, APP_URL, and the Laravel-native DB env var names | Application behaviour in the platform guides |
| Health checks | Supplies the default startup (TCP) / liveness (HTTP /api/healthcheck) probes | §Observability in the platform guides |
2. Cryptographic secrets in Secret Manager
One secret is generated automatically and stored in Secret Manager — it is never set in plain text and must never be changed after the first deployment:
APP_KEY— the Laravel application key, in the formatbase64:<44-char base64>(32 random bytes, base64-encoded). Generated byrandom_passwordinSpeedtestTracker_Common, stored as secretsecret-<resource_prefix>-speedtesttracker-app-key, and injected as the secret env varAPP_KEY. Speedtest Tracker uses it to encrypt application data stored encrypted. Rotating it after first boot makes those encrypted values permanently undecryptable — it is effectively immutable for the life of the deployment.
Retrieve the secret after deployment:
# List secrets for this deployment (names include the resource prefix):
gcloud secrets list --project "$PROJECT" --filter="name~app-key"
# Read a secret version:
gcloud secrets versions access latest --secret=<secret-name> --project "$PROJECT"
The database password is generated and managed separately by the foundation; its
secret name is reported in the platform deployment outputs (database_password_secret)
and it is injected as DB_PASSWORD. See App_Common for the shared
secret and Workload Identity model.
3. Database engine and bootstrap
Speedtest Tracker requires MySQL 8.0 (database_type = "MYSQL_8_0") in this
module; the engine is fixed and PostgreSQL is not supported (the upstream image's
SQLite default is never reached, since this module always wires MySQL). On the
first deployment a one-shot job (db-init) runs using mysql:8.0-debian and
idempotently:
- Detects the Cloud SQL Auth Proxy Unix socket or the TCP endpoint and selects the
right connection form for the
mysqlclient, - Waits for MySQL to be reachable,
- Creates (or updates) the application user with the generated password,
- Creates the application database,
- Grants full privileges on the database to the application user,
- Verifies the application user can connect,
- Signals the Cloud SQL Auth Proxy sidecar to shut down gracefully
(
POST /quitquitquit).
The job is safe to re-run (max_retries = 3). Inspect the database directly with:
gcloud sql connect <instance-name> --user=speedtesttracker --database=<db-name> --project "$PROJECT"
The instance, database, and user names are in the platform deployment outputs.
Note: db-init provisions only the database, user, and grants — the schema
itself is created by the image's automatic php artisan migrate --force on the
first container start (and re-applied on later boots for upgrades). There is no
separate migration job.
4. Container image
Speedtest Tracker is deployed from the official LinuxServer.io prebuilt image,
linuxserver/speedtest-tracker:<version> — there is no custom Cloud Build. The
Application modules forward container_image_source = "prebuilt" (and
container_build_config.enabled = false), so the platform mirrors the image into
Artifact Registry (enable_image_mirroring = true) and deploys it directly.
Fallback: the LinuxServer image uses s6-overlay as PID 1. If it is ever found
incompatible with a specific runtime (a documented risk class for s6-overlay images
in this repo — confirmed on Prowlarr under Cloud Run's gVisor sandbox, though not
universal; BookStack, also LinuxServer, works fine on Cloud Run), override
container_image to ghcr.io/alexjustesen/speedtest-tracker:<tag> — the
Alpine-based image with no s6-overlay.
Because Speedtest Tracker is a Laravel app, it reads the Laravel-native database
environment variables rather than the image's generic DB_USER/DB_PASS. The
Application modules map the platform's injected DB values onto the Laravel names via
db_*_env_var_name:
db_user_env_var_name = "DB_USERNAME",db_password_env_var_name = "DB_PASSWORD",db_name_env_var_name = "DB_DATABASE".
SpeedtestTracker_Common additionally sets the static DB_CONNECTION = "mysql" and
DB_PORT = "3306". DB_HOST differs by platform:
- Cloud Run connects over the Cloud SQL private IP (
enable_cloudsql_volume = false), soDB_HOSTis the instance private IP; MySQL over private-IP TCP needs no SSL. - GKE connects through the Cloud SQL Auth Proxy sidecar
(
enable_cloudsql_volume = true), so the GKE wiring overridesDB_HOST = "127.0.0.1".
The LinuxServer image runs php artisan migrate --force on start (see §3), so no
custom entrypoint is needed to create the schema.
5. Core application settings
SpeedtestTracker_Common establishes the baseline Speedtest Tracker environment so
the application comes up correctly on first boot:
- Database connection —
DB_CONNECTION = "mysql",DB_PORT = "3306"; the Laravel-nativeDB_USERNAME/DB_PASSWORD/DB_DATABASEandDB_HOSTare injected by the foundation (see §4). - Application URL —
APP_URLis set from the predicted service URL so links, assets, and redirects resolve to the real address. - Speed test schedule —
SPEEDTEST_SCHEDULE(default"0 * * * *", hourly) drives Speedtest Tracker's in-process Laravel scheduler, which fires an automated speed test independent of any inbound HTTP request. This is why the Cloud Run variant defaultscpu_always_allocated = trueandmin_instance_count = 1— the same class of requirement as n8n/Kestra in this catalogue. - Result pruning —
PRUNE_RESULTS_OLDER_THAN(default"0", disabled) automatically deletes speed test results older than the configured number of days. - Redis (optional) — when Redis is enabled via the platform deployment settings,
REDIS_HOSTandREDIS_PORTare injected; otherwise Speedtest Tracker uses its local file/sync cache driver, which is fine for a single-instance deployment. - First-run setup — Speedtest Tracker's web UI walks through account creation on first visit; there is no seeded default admin account.
6. Health probe behaviour
The default probes rely on Speedtest Tracker's public health surface:
- Startup — a TCP check on port
80, which passes as soon as the PHP web server binds its port. - Liveness — an HTTP
GET /api/healthcheck, Speedtest Tracker's unauthenticated JSON health endpoint (returns 200 with a JSON message). A generous first-boot window (300-second initial delay) accommodates the automaticphp artisan migrate --forcethat runs on the first container start.
On the GKE variant, the shipped
liveness_probedefault already points at/api/healthcheck— no override needed for accurate health signalling.
7. Object storage
Speedtest Tracker stores all results and configuration in Cloud SQL (MySQL) and has
no user-file-upload workflow analogous to BookStack's attachments, so no GCS
bucket is provisioned by default (storage_buckets output is an empty list). If
you need to persist /config (e.g. custom SSL certs) across restarts, enable NFS
via the platform's Group 11/13 storage variables.
For the Speedtest Tracker-specific, user-facing configuration (variables by group, outputs, and how to explore each service from the Console and CLI), see the platform guides: SpeedtestTracker_GKE and SpeedtestTracker_CloudRun.