Started writing Docker TCP post
	
		
			
	
		
	
	
		
			
				
	
				continuous-integration/drone the build was successful
				
					Details
				
			
		
	
				
					
				
			
				
	
				continuous-integration/drone the build was successful
				
					Details
				
			
		
	
							parent
							
								
									282e5f3824
								
							
						
					
					
						commit
						be5b5ba3b1
					
				|  | @ -0,0 +1,77 @@ | |||
| --- | ||||
| draft: true | ||||
| title: "Encrypting a Docker API for Remote Access Using Portainer" | ||||
| date: "2021-05-16" | ||||
| --- | ||||
| 
 | ||||
| tl;dr [This script](/docker-tcp.sh) has everything you need, just run | ||||
| `./docker-tcp.sh -h` (after making it executable) for any help. | ||||
| 
 | ||||
| ## Introduction | ||||
| 
 | ||||
| To manage my little army of servers, I use | ||||
| [Portainer CE](https://www.portainer.io/). It's an open-source management tool | ||||
| for controlling Dockerized applications across multiple hosts. It can handle | ||||
| regular Docker containers, compose stacks, Kubernetes clusters or Docker swarm | ||||
| mode. It's a really useful tool to keep track of everything, and nowadays, I | ||||
| really can't miss it. | ||||
| 
 | ||||
| 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 | ||||
| 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 | ||||
| the "heavy" lifting. | ||||
| 
 | ||||
| **Note**: This tutorial is only for Linux. I have no experience with managing a | ||||
| Windows server and therefore can't confirm these steps will also work on a | ||||
| Windows machine. | ||||
| 
 | ||||
| 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 | ||||
| add the host to Portainer later. | ||||
| 
 | ||||
| ## Server-side | ||||
| 
 | ||||
| To make the connection as secure as possible, we'll use both a server- & a | ||||
| client-side certificate. This first section describes how to generate the | ||||
| former: | ||||
| 
 | ||||
| ```shell | ||||
| openssl genrsa -aes256 -out ca-key.pem 4096 | ||||
| openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem | ||||
| ``` | ||||
| 
 | ||||
| These first two commands generate the | ||||
| [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. | ||||
| The most important one is the password. Keep this one safe, as you'll be asked | ||||
| for it later when creating the client key. | ||||
| 
 | ||||
| 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 | ||||
| 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 | ||||
| new certificate. You'll have to figure out for yourself how long you'd like | ||||
| your certificate to be valid for. | ||||
| 
 | ||||
| Now we can generate the server key: | ||||
| 
 | ||||
| ```shell | ||||
| openssl genrsa -out server-key.pem 4096 | ||||
| openssl req -subj "/CN=<HOST>" -sha256 -new -key server-key.pem -out server.csr | ||||
| ``` | ||||
| 
 | ||||
| In the above snippet, replace `<HOST>` with the hostname (output of the | ||||
| `hostname` command) of the machine who's API you want to expose. Now we've | ||||
| created `server-key.pem` and `server.csr`. | ||||
| 
 | ||||
| As a final step, we need to create a file named `extfile.cnf` with the | ||||
| following content: | ||||
| 
 | ||||
| ``` | ||||
| subjectAltName = DNS:<HOST>,IP:<IP>,IP:127.0.0.1 >> extfile.cnf | ||||
| extendedKeyUsage = serverAuth | ||||
| ``` | ||||
| 
 | ||||
| Here, we once again replace `<HOST>` with the machine's hostname, and `<IP>` | ||||
| with the machine's public IP. | ||||
|  | @ -0,0 +1,6 @@ | |||
| #!/usr/bin/env sh | ||||
| 
 | ||||
| # This script generates an openSSL key pair which can be used to expose a | ||||
| # Docker API over the internet. | ||||
| 
 | ||||
| 
 | ||||
		Reference in New Issue