-
-
Notifications
You must be signed in to change notification settings - Fork 215
Description
Welcome!
- I have read the documentation and my problem was not listed in the help section.
- I have searched open and closed issues and my problem was not mentioned before.
- I have verified I am using the latest version available. You can check the latest release here.
- I agree to follow this project's Code of Conduct.
What did you do?
I configured Speedtest Tracker with a cron schedule (SPEEDTEST_SCHEDULE="0 */4 * * *") and a fixed server (SPEEDTEST_SERVERS=31448). I also set SPEEDTEST_EXTERNAL_IP_URL=icanhazip.com (without the https:// protocol prefix) and SPEEDTEST_INTERNET_CHECK_HOSTNAME=google.com.
Every scheduled test fails. Running a manual test for the exact same server via the Admin UI succeeds without any issues.
Before the below mentioned workaround:
After the below mentioned workaround:
Root Cause Analysis
After reviewing the source code, AI identified the following:
All speedtests — both scheduled and manual — run through CheckForInternetConnectionJob. This job:
- Attempts to ping the host configured via
SPEEDTEST_INTERNET_CHECK_HOSTNAME. - If the ping fails or is unavailable, it falls back to an HTTP GET request against
SPEEDTEST_EXTERNAL_IP_URL.
The HTTP fallback is implemented as:
$url = config('speedtest.preflight.external_ip_url');
$response = Http::retry(3, 100)->timeout(5)->get(url: $url);When SPEEDTEST_EXTERNAL_IP_URL is set to icanhazip.com without a protocol prefix, the HTTP client cannot resolve it as a valid URL, which causes the repeated timeout and ultimately marks the result as Failed.
Why do manual tests succeed?
A manual test triggered from the UI sets scheduled = false. In SkipSpeedtestJob the skip-IP logic is bypassed for non-scheduled tests, and in SelectSpeedtestServerJob the config-based server selection is also only applied to scheduled results. The CheckForInternetConnectionJob runs for both — however, the connectivity check appears to behave differently in practice, possibly due to race conditions, caching, or the ping succeeding intermittently for manual tests while consistently failing under the scheduler's execution context.
Workaround (confirmed working):
- SPEEDTEST_EXTERNAL_IP_URL=https://icanhazip.com/
- SPEEDTEST_INTERNET_CHECK_HOSTNAME=icanhazip.comNote:
config/speedtest.phpalso references an undocumented variableSPEEDTEST_CHECKINTERNET_URLthat takes precedence over both of the above and sets both values at once. Since it does not appear in the documentation, the workaround above using the documented variables is recommended.
Suggested Fix
The config value speedtest.preflight.external_ip_url (mapped from SPEEDTEST_EXTERNAL_IP_URL) is used directly as a URL in an HTTP request. The application should either:
- Validate and normalize the configured URL at boot time, ensuring it always has a valid protocol prefix (
https://), or - Add a protocol prefix automatically if none is present before passing it to
Http::get(), or - Update the documentation to clearly state that
SPEEDTEST_EXTERNAL_IP_URLmust include the full URL with protocol (e.g.,https://icanhazip.com), since the default value inconfig/speedtest.phpalready includeshttps://:The default is safe, but overriding it without the protocol silently breaks scheduled tests.'external_ip_url' => env('SPEEDTEST_CHECKINTERNET_URL') ?? env('SPEEDTEST_EXTERNAL_IP_URL', 'https://icanhazip.com'),
Expected Behavior
Scheduled speedtests should complete successfully, just like manually triggered tests for the same server.
Steps to Reproduce
- Deploy Speedtest Tracker via Docker Compose with the following environment variables:
SPEEDTEST_SCHEDULE="0 */4 * * *" SPEEDTEST_SERVERS=<any server ID> SPEEDTEST_EXTERNAL_IP_URL=icanhazip.com # ← no protocol prefix! SPEEDTEST_INTERNET_CHECK_HOSTNAME=google.com - Wait for the cron schedule to trigger an automatic speedtest (or trigger it manually via the scheduler).
- Observe that the result is marked as Failed with the message:
Error: [0] Timeout occurred in connect. - Trigger a manual speedtest for the same server via Admin → Results → Run Speedtest.
- Observe that the manual test completes successfully.
Deployment Environment
Docker Compose
What is your environment & configuration?
services:
speedtest-tracker:
image: ghcr.io/linuxserver/speedtest-tracker:1.13.10
container_name: speedtest-tracker
restart: unless-stopped
environment:
- TZ=Europe/Berlin
- APP_KEY=${APP_KEY}
- APP_URL=${APP_URL}
- DB_CONNECTION=sqlite
- SPEEDTEST_SCHEDULE="0 */4 * * *"
- SPEEDTEST_SERVERS=31448
- DISPLAY_TIMEZONE=Europe/Berlin
- PRUNE_RESULTS_OLDER_THAN=180
- SPEEDTEST_EXTERNAL_IP_URL=icanhazip.com # ← root cause
- SPEEDTEST_INTERNET_CHECK_HOSTNAME=google.com
- PUID=99
- PGID=100Add more configuration information here.
Application Information
{
"Laravel": {
"version": "11.x"
},
"Speedtest Tracker": {
"Version": "v1.13.10"
}
}What browser(s) are you seeing the problem on?
N/A — issue is fully reproducible without any browser interaction (it is a server-side scheduling problem).
Logs
.