Deploying Coder with Docker and HTTPS
Encrypting network traffic with TLS has become a standard practice with more applications moving to the cloud. It is how many organizations secure their Coder instance when deploying on top of Kubernetes. This is usually accomplished by terminating TLS at the load balancer level.
However, with the release of Coder for Docker, the process to enable TLS is quite different, but just as important nonetheless. In this post, we’ll discuss how you can access your Coder for Docker deployment over HTTPS with a reverse proxy.
Understanding a reverse proxy
In some ways, a reverse proxy acts just like a regular proxy. It acts as a middleman, communicating with web servers on behalf of client machines. Yet, it comes with a few important caveats.
First, instead of masking outgoing connections, a reverse proxy masks the incoming traffic. When provided with a URL, such as coder.com, the reverse proxy will handle where the request is taken, even with a multi-server configuration.
Second, a reverse proxy enables you to run services on a variety of ports, without having to expose those ports to a user-facing network. In this case, Coder for Docker runs on port 7080. By using a reverse proxy, you only need to open ports 80 (HTTP) and 443 (HTTPS) to have traffic routed to Coder.
How it works
In this example, we’ll make use of an nginx
container to serve as the reverse proxy alongside the Coder container. We’ll also need to include our SSL certificate and key files in the nginx
configuration file to enable TLS.
To get started, you'll need - A machine with Docker Engine and Docker Compose installed - A domain name - An SSL/TLS certificate
If you don’t have a certificate, our documentation covers how to procure one via LetsEncrypt.
Running an nginx
container requires you to have an nginx.conf
file on the host machine. To account for this, we’ll create one locally and define the server name, ports, and headers. See an example below:
worker_processes 1;
events {
worker_connections 1024;
}
http {
default_type application/octet-stream;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
server_name <your-domain.com>;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
location / {
proxy_pass http://coder:7080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 443 ssl;
server_name <your-domain.com>;
ssl_certificate /letsencrypt/etc/letsencrypt/live/<your-domain.com>/cert.pem;
ssl_certificate_key /letsencrypt/etc/letsencrypt/live/<your-domain.com>/privkey.pem;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://coder:7080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
sendfile on;
keepalive_timeout 65;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
}
Once the server configuration is set, we can define our multi-container application with Docker Compose. All that’s needed is a single .yaml
file. Example below:
version: ‘3’
services:
nginx:
container_name: nginx
hostname: reverse
image: nginx
ports:
- 80:80
- 443:443
volumes:
- "/nginx:/etc/nginx"
- "~/letsencrypt:/letsencrypt/"
coder:
hostname: coder
image: codercom/coder:1.27
container_name: coder
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ~/.coder:/var/run/coder
ports:
- 7080:7080
environment:
- DEVURL_HOST=*.your-domain.com
A few things to note: first, we’ve defined the ports
key to publish ports 80 and 443 on the host network. Second, we’ve added the volumes
key to create a bind mount volume. This will mount our local directories of /nginx
and ~/letsencrypt
into the nginx container. Both directories contain the nginx configuration and certificate files, respectively.
Now that we have our Docker Compose and nginx
configuration files in place, we can start the containers! You’ll simply need to run docker-compose up -d
to run both containers simultaneously. You should now be able to access your Coder instance from your domain.
For more detailed information on the steps above, see our documented guide.
Subscribe to our Newsletter
Want to stay up to date on all things Coder? Subscribe to our monthly newsletter and be the first to know when we release new things!