- Why you may want to read this article
- Presetup
- Configuring Nginx
- Generate certificates
- Demo
- Follow up
Why you may want to read this article
Today it is a continuation of my short Infrastructure-related articles.
This article will be about creating and configuring SSL/TLS certificates (https) for your domain and IP.
Presetup
I have my Ubuntu server, domain that points to this server, Nginx reverse proxy in the docker container, and React application in the container as well. Each request that goes to my application is not protected, because it uses http protocol (not https).
I would like to make my application more secure by adding https functionality for free, without any cost.
To do that, we will
- Certbot tool inside the docker container that will generate certificates for domain
- Configure Nginx to use those SSL/TLS certificates
Configuring Nginx
Nginx and certbot docker-compose
docker-compose.yml
version: '3'
services:
nginx:
container_name: nginx
image: nginx:latest
restart: always
volumes:
- ./conf.d:/etc/nginx/conf.d
- ./nginx.conf:/etc/nginx/nginx.conf
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
- ./nginx-logs:/var/log/nginx
ports:
- 80:80
- 443:443
networks:
- nginx-network
- default
certbot:
image: certbot/certbot:latest
volumes:
- ./certbot/conf:/etc/letsencrypt
- ./certbot/www:/var/www/certbot
networks:
- nginx-network
networks:
nginx-network:
external: true
This docker-compose file contains nginx
service specification. We created a volume for the nginx configuration to pass local configurations to the container and a volume for certificates ./certbot/…
.
We have added nginx-network, this is for encapsulation and accessibility. With this setup only containers that are inside nginx-network
network can be accessed from nginx.
On top of that, there is certbot
specification with the certificate volumes.
Nginx.conf file
nginx.conf
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
client_max_body_size 10M;
# **disables nginx version**
server_tokens off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
It is pretty simple nginx.conf file, just regular configurations, and in the last line we are including all the subconfigurations for nginx.
Application nginx subconfiguration
conf.d/symptoms-dev.conf
#frontend dev env
server {
listen 80;
server_name symptom-diary.com;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
proxy_set_header Host $host;
return 301 https://symptom-diary.com$request_uri;
}
}
#server {
# listen 443 ssl;
# server_name symptom-diary.com;
# ssl_certificate /etc/letsencrypt/live/symptom-diary.com/fullchain.pem;
# ssl_certificate_key /etc/letsencrypt/live/symptom-diary.com/privkey.pem;
# location / {
#this needed to resolve host by docker dns, othervise 'set $upstream will' not work
# resolver 127.0.0.11 valid=10s;
#this variable needed to not fail nginx if any of the containers is down
# set $upstream http://symptom-tracker-dev:3000;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header Host $host;
# proxy_pass $upstream;
# }
#}
This is subconfiguration for my react application for demo purpose.
It has 2 parts:
- The first part is for unsecured http connection that listens to 80th port of our domain
symptom-diary.com
. The main purpose for this block is to allow certbot authenticate throught the challenge request. Other than that It just redirects the request to https connection on 443d port. - The second part is specifying secured https connection with SSL/TLS protocols, it directs request to our application docker container
symptom-tracker-dev
on3000
internal docker port. Until we have SSL certificates created by certbot it is unusable.
The SSL certificates are ensured by
ssl_certificate /etc/letsencrypt/live/symptom-diary.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/symptom-diary.com/privkey.pem;
But now there is no fullchain.pem
and privkey.pem
files, let’s generate them. That’s why the second part is commented. Now we need to generate certificates and uncomment the SSL part (second one) of configuration
Generate certificates
Go to our docker-compose.yml location.
Note, that I’m generating the certificates also for 2 subdomains: dev
and blog
. If you would like to have only one domain - specify only one.
Run
docker-compose run --rm certbot certonly --webroot --webroot-path /var/www/certbot/ -d symptom-diary.com -d dev.symptom-diary.com -d blog.symptom-diary.com
You will see this output:
As you can see our certificates were successfully generated by letsencrypt organization, and since we have our docker volumes they are already in our server and inside the nginx container.
Take a look into certificate expiration, by that time - you need to renew the certificate with the same command.
Demo
Now let’s go and try to access our application by domain name symptom-diary.com
As you can see it shows TLS expiration details.
Follow up
Please subscribe to my social media to not miss updates.: Instagram, Telegram
I’m talking about life as a Software Engineer at Microsoft.
Besides that, my projects:
Symptoms Diary: https://symptom-diary.com
Pet4Pet: https://pet-4-pet.com