Finalized first version of docker-tcp post
continuous-integration/drone the build was successful Details

master
Jef Roosens 2021-05-17 12:29:56 +02:00
parent 87c5b2eca9
commit 9e22b69ecb
Signed by: Jef Roosens
GPG Key ID: B580B976584B5F30
1 changed files with 20 additions and 20 deletions

View File

@ -1,7 +1,6 @@
--- ---
draft: true
title: "Encrypting a Docker API for Remote Access Using Portainer" title: "Encrypting a Docker API for Remote Access Using Portainer"
date: "2021-05-16" date: "2021-05-17"
--- ---
tl;dr [This script](/scripts/docker-tcp.sh) has everything you need, just run tl;dr [This script](/scripts/docker-tcp.sh) has everything you need, just run
@ -12,23 +11,23 @@ tl;dr [This script](/scripts/docker-tcp.sh) has everything you need, just run
To manage my little army of servers, I use To manage my little army of servers, I use
[Portainer CE](https://www.portainer.io/). It's an open-source management tool [Portainer CE](https://www.portainer.io/). It's an open-source management tool
for controlling Dockerized applications across multiple hosts. It can handle for controlling Dockerized applications across multiple hosts. It can handle
regular Docker containers, compose stacks, Kubernetes clusters or Docker swarm regular Docker containers, compose stacks, Kubernetes clusters and Docker swarm
mode. It's a really useful tool to keep track of everything, and nowadays, I mode. It's a really useful tool to keep track of everything, and nowadays, I
really can't miss it. really can't miss it.
Before we can add a host to Portainer, its Docker API has to be exposed to the Before we can add a host to Portainer, its Docker API has to be exposed to the
public, and in order to do this, we need to protect it using encryption (unless public, and in order to do this, we need to protect it using encryption (unless
of course you like random people controlling your server). This post will of course you like random people controlling your server). This post will
explain how this can be done, and I've also written a script that can automate explain how this can be done, and I've also written
the "heavy" lifting. [a script](/scripts/docker-tcp.sh) that can automate the "heavy" lifting.
**Note**: This tutorial is only for Linux. I have no experience with managing a **Note**: This tutorial is only for Linux distributions that use systemctl. I
Windows server and therefore can't confirm these steps will also work on a have no experience with managing a Windows server and therefore can't confirm
Windows machine. these steps will also work on a Windows machine, or using another init system.
I recommend running these commands on your local Linux machine and just copying I recommend running these commands on your local Linux machine and just copying
the certificates to the server later, as you'll need all the files in order to the certificates to the server later, as you'll need the files in order to add
add the host to Portainer later. the host to Portainer later.
## Server-side ## Server-side
@ -45,32 +44,33 @@ These first two commands generate the
[CA](https://en.wikipedia.org/wiki/Certificate_authority) key. You'll be asked [CA](https://en.wikipedia.org/wiki/Certificate_authority) key. You'll be asked
for some basic information, e.g. your country, state, city, organization, etc. for some basic information, e.g. your country, state, city, organization, etc.
The most important one is the password. Keep this one safe, as you'll be asked The most important one is the password. Keep this one safe, as you'll be asked
for it later when creating the client key. for it multiple times when generating the other keys.
One thing to note here is the `-days 365` flag. This defines after how many One thing to note here is the `-days 365` flag. This defines after how many
days this certificate will expire (but only when the `-x509` flag is days the certificate will expire (but only when the `-x509` flag is
specified). By default, its value is set at 30 days, but I find this to be specified). By default, its value is set at 30 days, but I find this to be
rather short. After this time, you'll have to repeat these steps and generate a rather short. After this time, you'll have to repeat these steps and generate a
new certificate. You'll have to figure out for yourself how long you'd like new certificate. You'll have to figure out for yourself how long you'd like
your certificate to be valid for. your certificate to be valid for. It's a trade-off between convenience and
security.
Now we can generate the server key: Now we can generate the server key:
```shell ```shell
openssl genrsa -out server-key.pem 4096 openssl genrsa -out server-key.pem 4096
openssl req -subj "/CN=<HOST>" -sha256 -new -key server-key.pem -out server.csr openssl req -subj '/CN=<HOST>' -sha256 -new -key server-key.pem -out server.csr
``` ```
In the above snippet, replace `<HOST>` with the hostname of the machine who's In the above snippet, replace `<HOST>` with the domain name of the machine
API you want to expose. With hostname, I mean the domain from which your server who's API you want to expose. With domain name, I mean the domain from which
is accessible, e.g. `server.example.com`. Now we've created `server-key.pem` your server is accessible, e.g. `server.example.com`. Now we've created
and `server.csr`. `server-key.pem` and `server.csr`.
After this, we need to create a file named `extfile.cnf` with the After this, we need to create a file named `extfile.cnf` with the
following content: following content:
``` ```
subjectAltName = DNS:<HOST>,IP:<IP>,IP:127.0.0.1 >> extfile.cnf subjectAltName = DNS:<HOST>,IP:<IP>,IP:127.0.0.1
extendedKeyUsage = serverAuth extendedKeyUsage = serverAuth
``` ```
@ -134,7 +134,7 @@ ExecStart=
ExecStart=/usr/sbin/dockerd --tlsverify --tlscacert='<DIR>/ca.pem' --tlscert='<DIR>/server-cert.pem' --tlskey='<DIR>/server-key.pem' -H fd:// -H tcp://0.0.0.0:2376 ExecStart=/usr/sbin/dockerd --tlsverify --tlscacert='<DIR>/ca.pem' --tlscert='<DIR>/server-cert.pem' --tlskey='<DIR>/server-key.pem' -H fd:// -H tcp://0.0.0.0:2376
``` ```
Don't forget the replace `<PATH>` with the path to your actual directory. Don't forget to replace `<DIR>` with the path to your actual directory.
The final step is restarting the Docker engine: The final step is restarting the Docker engine: