1

I am using docker stack to deploy one service in multiple digital ocean droplets (replica > 1), one container per droplet. This is my app backend service.

I want to have a SSL cert & private key installed (and hopefully automatically renewed) so I can use TLS connection, with SSL termination setting, so data transfer from swarm LB to containers is unencrypted using port 80. I also use docker-machine cmd to setup my digital ocean ubuntu v16.04 droplet.

What is the best way of doing this?

I tried the following, and two issues arised:

  1. I am first generating the cert and private key with let's encrypt somewhere else on a server with nginx installed (messing with my DNS also). After the cert/key generation, I then copy and install them back with docker swarm ca --rotate. But feel this approach is wrong.

  2. With 1. set, I tried curl the backend service. The port 80 is fine, but port 443 seems to be talking http protocol, and I see the following:

    $ curl -vvv https://myurl.com:443/v1/check 
    *   Trying my.ip.address... 
    * Connected to myurl.com (my.ip.address) port 443 (#0) 
    * found 148 certificates in /etc/ssl/certs/ca-certificates.crt 
    * found 593 certificates in /etc/ssl/certs
    * ALPN, offering http/1.1
    * gnutls_handshake() failed: An unexpected TLS packet was received.
    * Closing connection 0
    
    curl: (35) gnutls_handshake() failed: An unexpected TLS packet was received.
    
    $ curl -vvv http://myurl.com:443/v1/check
    *   Trying my.ip.address...
    * Connected to myurl.com (my.ip.address) port 443 (#0)
    > GET /v1/check HTTP/1.1
    > Host: myurl.com:443
    > User-Agent: curl/7.47.0
    > Accept: */*
    >
    < HTTP/1.1 200 OK
    < Server: nginx/1.10.3 (Ubuntu)
    < Date: Sun, 09 Sep 2018 11:06:39 GMT
    < Content-Type: application/json; charset=utf-8
    < Transfer-Encoding: chunked
    < Connection: keep-alive
    < Vary: Accept-Encoding, Origin
    < ETag: W/"843adc298b0b2ef417eabf2f82670fc9"
    < Cache-Control: max-age=0, private, must-revalidate
    < X-Request-Id: b201d205-4c63-4318-b965-cebabc056b29
    < X-Runtime: 0.078911
    < X-Rack-Cache: pass
    <
    * Connection #0 to host myurl.com left intact
    {"status":"ok","container_id":"8bd9981213e7"}
    

Thank you for shedding light on this subject!

I have also asked the question here:

https://forums.docker.com/t/installing-ssl-cert-in-docker-swarm/58073

Jimmy Chu
  • 972
  • 8
  • 27

1 Answers1

2

You can generate certificates manually using the OpenSSL tool and configure Docker daemon to use these certificates.

Generate Server Certificates

  1. Generate CA private and public keys:

    openssl genrsa -aes256 -out ca-key.pem 4096
    openssl req -new -x509 -days 1000 -key ca-key.pem -sha256 -out ca.pem
    
  2. Create a server key and certificate signing request (CSR):

    openssl genrsa -out server-key.pem 4096
    openssl req -subj "/CN=my.company.com" -sha256 -new -key server-key.pem -out server.csr
    
  3. Sign the public key with CA:

    echo subjectAltName = DNS:my.company.com,IP:127.0.0.1 >> extfile.cnf
    echo extendedKeyUsage = serverAuth >> extfile.cnf
    
  4. Generate the key:

    openssl x509 -req -days 1000 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf
    

Generate Client Certificates

  1. Create a client key and certificate signing request:

    openssl genrsa -out key.pem 4096
    openssl req -subj '/CN=client' -new -key key.pem -out client.csr
    
  2. Create an extensions config file:

    echo extendedKeyUsage = clientAuth >> extfile.cnf
    
  3. Sign the private key:
    openssl x509 -req -days 1000 -sha256 -in client.csr -CA ../server/ca.pem -CAkey ../server/ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnf
    
  4. Export cert.pem into PFX format to be added into Trusted Root Certification Authorities
    openssl pkcs12 -export -in cert.pem -inkey key.pem -out cert.pfx
    

Configure Docker daemon with /etc/docker/daemon.json

{
    "debug": false,
    "tls": true,
    "tlsverify": true,
    "tlscacert": "/etc/docker/certificates/server/ca.pem",
    "tlscert": "/etc/docker/certificates/server/server-cert.pem",
    "tlskey": "/etc/docker/certificates/server/server-key.pem",
    "hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"]
}

Start Docker Service

systemctl start docker

Check out this article Building Jenkins Pipelines – Part 1. Setting Up Docker Swarm by Scalified.

It includes a step-by-step guide on how to setup Docker Swarm and generate server and client self-signed certificates. I hope it will help to solve your issue.