Skip to content

Allow http URLs for all local-network Navidrome and Jellyfin hosts#2331

Merged
theovilardo merged 1 commit into
masterfrom
fix/navidrome-http-local-hosts
Jun 11, 2026
Merged

Allow http URLs for all local-network Navidrome and Jellyfin hosts#2331
theovilardo merged 1 commit into
masterfrom
fix/navidrome-http-local-hosts

Conversation

@lostf1sh

Copy link
Copy Markdown
Collaborator

Fixes #2327

Problem

#2329 relaxed the Navidrome server URL validation to accept http for localhost, 127.0.0.1, *.local, and private IPv4 literals, matching Jellyfin. However, many common local setups are still rejected over http by both integrations:

  • Single-label LAN hostnames (http://mynas:4533) resolved by router DNS
  • Local-only DNS suffixes: .lan, .home, .internal, .home.arpa (RFC 8375)
  • IPv6 loopback / link-local / unique-local literals (http://[::1]:4533, http://[fd00::1]:4533)
  • Carrier-grade NAT addresses, 100.64.0.0/10 (RFC 6598) — what Tailscale assigns, a very common way to reach a self-hosted Navidrome

Changes

  • Add CloudStreamSecurity.isLocalOrPrivateHost(host) covering all of the above host forms in one place.
  • Use it from NavidromeCredentials.connectionValidationError and JellyfinCredentials.connectionValidationError, replacing the duplicated inline checks so the two integrations stay in sync.
  • Remote (public) http URLs are still rejected with the same error message as before.

No changes were needed downstream: NavidromeApiService, the stream proxies, and the Coil image loader all use cleartext-capable OkHttp clients, and the network security config already permits cleartext, so http works end-to-end once validation passes.

Tests

  • CloudStreamSecurityTest: new coverage for isLocalOrPrivateHost (accepts local/private forms, rejects public hosts including 100.32.x.x outside the CGNAT range).
  • NavidromeCredentialsTest: local http acceptance extended to hostname/IPv6/CGNAT forms.
  • JellyfinCredentialsTest (new): parity coverage for the Jellyfin validation.

All 16 tests in the three classes pass via :app:testDebugUnitTest.

The private-host check used during server URL validation only recognized
localhost, 127.0.0.1, .local names, and private IPv4 literals. Local
servers reached via single-label LAN hostnames, router DNS suffixes
(.lan, .home, .internal, .home.arpa), IPv6 loopback/link-local/unique-
local literals, or carrier-grade NAT addresses (100.64.0.0/10, used by
Tailscale) were still rejected over http.

Centralize the check as CloudStreamSecurity.isLocalOrPrivateHost and use
it from both NavidromeCredentials and JellyfinCredentials so the two
integrations stay in sync.
@theovilardo theovilardo merged commit fb10d2b into master Jun 11, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Allow http URLs for local Navidrome servers

2 participants