What I’m trying to do shouldn’t be too bad, but I’m having a hell of a time. Spent about 4.5 hours now, and every set of instructions online (docker forums, stackoverflow, stackexchange, you name it) have all led me to something not quite fully working. I’m hoping one of you kind people can help me get to the finish line.
The goal
- Build some docker containers on an Ubuntu server (easy)
- Upload those containers to another Ubuntu server
- Preferably only a server cert used (no idea how to disable requiring client cert - I keep getting deprecation failures)
Environment
- These are both Ubuntu 22 machines (EC2s in AWS).
- Docker was installed through these instructions: Ubuntu | Docker Docs
- The EC2s connect to each other via private IPs.
- We have a private CA server if we need it (I really think it shouldn’t be needed though)
- The machines security groups give full network access to each other
- ufw disabled - so no firewall
Other Thoughts
- For these machines, a simple self-signed cert is preferred to make the setup easier, but if it’s a hard requirement, I can create signed certs for both servers.
- No TLS is acceptable, but as I understand it, Docker wants to hard force SSL in ALL situations everywhere soon. I also tried no SSL for about an hour and gave up - Kept getting different errors (usually along the lines of bad HTTP request with HTTPS server, even though both sides configured for non TLS).
- P.S. Why on earth is a client cert required?? Can that be disabled? If I docker login to dockerhub, I don’t have to generate a cert and give it to dockerhub
Latest Error
- Client side: “remote error: tls: bad certificate”
- Server side: “certificate specifies an incompatible key usage”
Reproduction Steps
-
Create a server cert
1.a. openssl req -newkey rsa:4096 -nodes -keyout server.com.key -out server.com.csr -addext “subjectAltName = DNS:server.com,IP:10.0.0.53”
1.b. Signed it with our CA server -
Create a client cert
2.a. openssl req -newkey rsa:4096 -nodes -keyout client.com.key -out client.com.csr -addext “subjectAltName = DNS:client.com,IP:10.0.0.76”
2.b. Signed it with our CA server -
Installed certs on the server
3.a. Put root ca cert at /usr/loca/share/ca-certificates/root-ca.crt
3.b. sudo update-ca-certificates --fresh # The fresh to really make sure it’s clean
3.c. mkdir -p /etc/docker/certs.d/server.com:2376
3.d. In the above /etc/docker/certs.d/server.com:2376 directory, I put ALL certs: client.com.crt, client.com.key, server.com.crt, server.com.key, and a symlink to the root-ca.crt cert
3.e. sudo systemctl restart docker -
Installed certs on the client
4.a. Basically did the exact same thing on the server as the client. It’s really not clear anywhere what files go where, so the server and client both have both client certs and keys in /etc/docker/certs.d/server.com:2376
4.b. Root cert installed, with update-ca-certificates
4.c. Also did systemctl restart docker on client -
How the server is configured
5.a. Eventually I found out the server runs a docker daemon, with configuration at /lib/systemd/system/docker.service
5.b. I modified this docker.service file to remove the “-H” option from the ExecStart command. This was causing failures with similar options in the daemon.json file
5.c. Created a file at /etc/docker/daemon.json with these contents:
{
"tlsverify": true,
"tlscacert": "/etc/docker/certs.d/server.com:2376/ca.crt",
"tlscert": "/etc/docker/certs.d/server.com:2376/server.com.crt",
"tlskey": "/etc/docker/certs.d/server.com:2376/server.com.key",
"hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"]
}
5.d. P.S. I assume this file is where I can disable requiring client certs? But if I set tlsverify to false, I get deprecation failures, so that’s very clearly the wrong way to do it. But it really doesn’t make sense to require an additional client cert, so I’m confused here.
- The client
6.a. I’ve tried creating a daemon.json file, setting the server to insecure, but that just gave lots more failures. There’s currently no daemon.json right now.
6.b.docker login server.com:2376
# I’ve tried loads of other things… adding http://, https://, changing port to 2375, 443, 80, etc. Ensuring port matched server of course.