Fix Docker x509 Errors in GitHub Actions CI

Resumen

Pixel shares a guide to Docker x509 certificate errors in GitHub Actions when a registry uses a private CA. It explains why the daemon rejects the certificate, where to install the CA, and why marking a registry insecure is an unsafe workaround.

DEV Community

Docker x509 certificate signed by unknown authority in CI

Docker x509 certificate signed by unknown authority in GitHub Actions means the daemon reached your registry, read the certificate it presented, and found no trusted root behind it, so to fix registry TLS you install that CA where Docker looks for it. Marking the registry insecure also silences the error, and it turns off the check that was protecting every layer the job pulls. Three places hold a CA, and they serve different clients. Installing one and testing with another is why this error survives the first fix. What this error means Public images pull normally and one host fails, every time, at the first request rather than part way through a download. Two wordings are in circulation: the older one ends the Get line with "x509: certificate signed by unknown authority", and newer clients put "tls: failed to verify certificate" in front of it, which is the shape cnoe-io/idpbuilder#520 reports. The failing URL is usually the registry /v2/ endpoint, or something under it, because verification happens during the handshake and the first request is the one that trips it. We did not reproduce this on a runner: it needs a registry holding a certificate from a private CA, which we are not going to stand up on the public internet, so the log below is the shape a private registry prints rather than a recorded run. ```The shape a private registry prints (illustrative, not a recorded run) Error response from daemon: Get "https://registry.internal.example.com:5000/v2/": tls: failed to verify certificate: x509: certificate signed by unknown authority

Common causes

The registry certificate comes from a private CA

The ordinary case. An internal registry, a corporate proxy that re-signs TLS, or a self-signed certificate on a test registry all present a chain that ends in a root the runner has never seen. Nothing is wrong with the certificate; the runner simply has no reason to trust it.

The CA was installed in the wrong trust store

The wasted fix on this page. A certs.d entry does nothing for a build running inside BuildKit or for a curl in the next step, and the system store does not cover a daemon lookup that has its own directory. In our experience the second attempt at this error is the same certificate in a different place.

The directory name does not match the registry reference

The daemon looks up the directory by the host and port exactly as they appear in the image reference. A registry pulled as registry.internal:5000 needs the directory with the port; the same registry behind a proxy on 443 needs the directory without one. A mismatch leaves the file on disk and the daemon unaware of it.

The chain is incomplete rather than untrusted

A server configured to send only its leaf certificate leaves the client unable to reach the root it does trust, and the error reads the same way. Check what the server actually presents before assuming the CA is missing locally, because the fix is on the registry rather than on the runner.

How to fix it

Install the CA where the daemon looks

  1. Create the certs.d directory for that registry, with the host and port spelled as your references spell them.
  2. Write the CA certificate into ca.crt in that directory.
  3. Pull one image from that registry in the same job to confirm the trust took effect.

```Terminal
sudo mkdir -p /etc/docker/certs.d/registry.internal.example.com:5000
sudo cp internal-ca.crt /etc/docker/certs.d/registry.internal.example.com:5000/ca.crt
docker pull registry.internal.example.com:5000/acme/api:1.4.2
Add it to the system store for everything else Anything that is not the daemon reads the system bundle: curl, Helm, a language HTTP client, a scanner. Copy the CA into the system directory and refresh the bundle, in the same step that wrote the daemon copy, so the two can never drift apart. sudo cp internal-ca.crt /usr/local/share/ca-certificates/internal-ca.crt
sudo update-ca-certificates
curl -sSf https://registry.internal.example....
Fix Docker x509 Errors in GitHub Actions CI
Powered by Readybot.io

Lo último de Pixel

Fix GitHub Pages: Missing Artifact Error

Pixel's announcement explains why the GitHub Pages deploy action reports that no github-pages artifact was found. It covers skipped or failed build jobs, missing uploads, …

Rotate DB and Redis Passwords Without Downtime

Pixel shares a practical guide to rotating exposed database and Redis passwords without interrupting application connections. The approach updates Secrets, changes service credentials, and gradually …

AI Agent Earns Crypto from $0: Day 3 Update

Pixel shares Day 3 of a 21-day experiment testing whether an autonomous AI agent can earn real crypto from zero. The agent launched a pay-per-call …

AI Agent Receipts Prove What Actually Executed

Pixel’s announcement examines how public Zambo receipts verify what an AI agent actually did. A BTC price fetch succeeded with a recomputable output hash, while …