Note that localhost is an implicitly insecure registry in engine/security/certificates
Nobody has claimed this yet.
- Dominant language
- Markdown
- Stars
- 4.7k
- Forks
- 8.5k
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 108
Description
Is this a docs issue?
- My issue is about the documentation content or website
Type of issue
Information is incorrect
Description
Page: https://docs.docker.com/engine/security/certificates/#understand-the-configuration
Source file: content/manuals/engine/security/certificates.md
Problem: The "Understand the configuration" section uses localhost as the sample registry hostname, and the directory-layout example uses localhost:5000: /etc/docker/certs.d/ <-- Certificate directory localhost:5000 <-- Hostname:port client.cert <-- Client certificate client.key <-- Client key ca.crt <-- Root CA that signed the registry certificate, in PEM
Following this page literally with a localhost test registry does not work. Docker never presents the client certificate, so a registry that requires mutual TLS rejects or never completes the handshake. There is nothing on the page explaining why.
Root cause: The Docker Engine unconditionally treats loopback addresses as insecure registries.
daemon/pkg/registry/config.go: // Localhost is by default considered as an insecure registry. This is a // stop-gap for people who are running a private registry on localhost.registries = append(registries, "::1/128", "127.0.0.0/8")
isSecureIndex() in the same file resolves the registry hostname and matches it against that CIDR list. localhost resolves to 127.0.0.1, matches, and the registry is marked insecure.
That result is passed to newTLSConfig() in daemon/pkg/registry/registry.go, which only calls loadTLSConfig() when the registry is secure. loadTLSConfig() is the function that reads certs.d and attaches the client certificate. So for any loopback registry, the client certificate is silently never loaded and never sent, regardless of what is present in certs.d.
This is documented nowhere on the page. The word "insecure" does not appear in certificates.md at all, and there is no companion insecure-registries page in content/manuals/engine/security/ to cross-reference.
Impact:
The page's own example is the configuration most likely to be used for a first test, and it is the one configuration guaranteed not to exercise the client-certificate path. Users following it conclude their certificates are misconfigured. This came up during an enterprise customer's migration of a large internal registry to mTLS authentication: their engineer got Podman working against the same test setup (Podman has no equivalent implicit-insecure-localhost default) and lost time assuming the Docker-side failure was their own configuration error before locating the behaviour in the Engine source.
Location
https://docs.docker.com/engine/security/certificates/
Suggestion
Suggested fix:
Add a short note in "Understand the configuration", near the localhost:5000 example, along the lines of:
[NOTE]
localhost, 127.0.0.0/8 and ::1/128 are treated as insecure registries by default, and Docker does not send client certificates to insecure registries. If you are testing client-certificate authentication locally, use a non-loopback hostname (for example an /etc/hosts alias resolving to a non-loopback address) so the certificate path is actually exercised.
Ideally also switch the worked example away from localhost to a hostname that works, since the example as written cannot succeed for the feature the page documents. If there is a canonical insecure-registries reference page, linking it from this note would help. I could not find one under content/manuals/engine/ in the current repo beyond release-note mentions.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Open content/manuals/engine/security/certificates.md and review the “Understand the configuration” section around the localhost:5000 directory-layout example. Read daemon/pkg/registry/config.go and daemon/pkg/registry/registry.go to confirm the documented behavior, then update the note and example as appropriate, including a cross-reference if a canonical insecure-registries page exists. Done means the page no longer implies that localhost exercises client-certificate authentication.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 84/100