Publish service with nginx & certbot
In this article, we are going to talk about how to publish a service with nginx and certbot.
prerequisites
Nginx
sudo apt install nginx
Certbot
sudo apt-get install certbot
sudo apt-get install python3-certbot-nginxDomain name We will need a registered domain to have an SSL certificate. In our case, we will use cloudflare to manage the domain name.
A server with a public IP address (In this case, we will use OCI VM instance)
A service running on the server
Project overview
I have an code-server instance running on my OCI VM instance. I want to publish it with a domain name and SSL certificate. See the table below:
address | example value | |
---|---|---|
before | http://${public-ip-addr}:${service-port} | http://129.32.24.11:3001 |
after | https://${domain-name} | https://code-server.my-domain-name.com |
Before starting,
- create an ingress rule to allow the service port.
- make sure you can access the service by the url
http://<public-ip-addr>:<service-port>
Setup nginx
create the domain on Nginx available site list
cd /etc/nginx/sites-available/
touch <domain-name> # in my case, it is code-server.my-domain-name.comEdit the config file with the following content:
server {
server_name code-server.my-domain-name.com;
location / {
proxy_pass http://localhost:3001;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_set_header Accept-Encoding gzip;
}
}Reload nginx server
sudo systemctl reload nginx
- create a symbolic link to the sites-enabled folder
cd /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/<domain-name> <domain-name>
- Restart nginx server
sudo systemctl restart nginx
- Access the service (Cloudflare only). Skip this section if not using cloudflare
If you are also using cloudflare, you should already be able to access the service with https://<domain-name>
now because cloudflare will automatically generate a SSL certificate.
However, you will see that the certificate is only between browser and cloudflare. The connection between cloudflare and the server is still not encrypted.
You will see the following error message when you use Full
encryption mode on cloudflare.
- Create a server certificate with certbot we can generate a SSL Certificate for our server with certbot.
sudo certbot --nginx -d <domain-name>
output
(base) ubuntu@dev-eric:/etc/nginx/sites-available$ sudo certbot --nginx -d code-server.dev-eric.work
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for code-server.dev-eric.work
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/code-server.dev-eric.work/fullchain.pem
Key is saved at: /etc/letsencrypt/live/code-server.dev-eric.work/privkey.pem
This certificate expires on 2024-03-30.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
Deploying certificate
Successfully deployed certificate for code-server.dev-eric.work to /etc/nginx/sites-enabled/code-server.dev-eric.work
Congratulations! You have successfully enabled HTTPS on https://code-server.dev-eric.work
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Auto modified nginx config file
You will see that certbot automatically modified the nginx config file.
server {
server_name code-server.dev-eric.work;
location / {
proxy_pass http://localhost:3001;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection upgrade;
proxy_set_header Accept-Encoding gzip;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/code-server.dev-eric.work/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/code-server.dev-eric.work/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = code-server.dev-eric.work) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name code-server.dev-eric.work;
listen 80;
return 404; # managed by Certbot
}
- Ready to go
Now you should be able to access the service with https://<domain-name>
.
If you are using cloudflare, you will realize that the site is now available with Full
encryption mode.