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