Skip to main content

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

AreaProvided by SpeedtestTracker_CommonWhere it surfaces
Cryptographic secretsGenerates the Laravel APP_KEY (base64:<44-char base64>) and stores it in Secret ManagerInjected automatically as secret env APP_KEY
Container imageFixes the prebuilt linuxserver/speedtest-tracker image (no custom build)container_image output of the platform deployment
Database engineFixes Cloud SQL for MySQL 8.0 as the only supported engine§Database in the platform guides
Database bootstrapDefines the first-deploy job (db-init) that creates the database, user, and grantsinitialization_jobs output
Speed test scheduleSets SPEEDTEST_SCHEDULE and PRUNE_RESULTS_OLDER_THAN — the in-process Laravel scheduler that fires automated speed testsApplication behaviour in the platform guides
Core settingsSets DB_CONNECTION = mysql, DB_PORT = 3306, APP_URL, and the Laravel-native DB env var namesApplication behaviour in the platform guides
Health checksSupplies 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 format base64:<44-char base64> (32 random bytes, base64-encoded). Generated by random_password in SpeedtestTracker_Common, stored as secret secret-<resource_prefix>-speedtesttracker-app-key, and injected as the secret env var APP_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:

  1. Detects the Cloud SQL Auth Proxy Unix socket or the TCP endpoint and selects the right connection form for the mysql client,
  2. Waits for MySQL to be reachable,
  3. Creates (or updates) the application user with the generated password,
  4. Creates the application database,
  5. Grants full privileges on the database to the application user,
  6. Verifies the application user can connect,
  7. 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), so DB_HOST is 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 overrides DB_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 connectionDB_CONNECTION = "mysql", DB_PORT = "3306"; the Laravel-native DB_USERNAME / DB_PASSWORD / DB_DATABASE and DB_HOST are injected by the foundation (see §4).
  • Application URLAPP_URL is set from the predicted service URL so links, assets, and redirects resolve to the real address.
  • Speed test scheduleSPEEDTEST_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 defaults cpu_always_allocated = true and min_instance_count = 1 — the same class of requirement as n8n/Kestra in this catalogue.
  • Result pruningPRUNE_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_HOST and REDIS_PORT are 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 automatic php artisan migrate --force that runs on the first container start.

On the GKE variant, the shipped liveness_probe default 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.