- Notifications
You must be signed in to change notification settings - Fork1
Simple Application server with Let's Encrypt and Certbot
License
morgangraphics/simple-webapp-or-service-with-lets-encrypt
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
██╗ ███████╗████████╗███████╗ ███████╗███╗ ██╗ ██████╗██████╗ ██╗ ██╗██████╗ ████████╗ ██║ ██╔════╝╚══██╔══╝██╔════╝ ██╔════╝████╗ ██║██╔════╝██╔══██╗╚██╗ ██╔╝██╔══██╗╚══██╔══╝ ██║ █████╗ ██║ ███████╗ █████╗ ██╔██╗ ██║██║ ██████╔╝ ╚████╔╝ ██████╔╝ ██║ ██║ ██╔══╝ ██║ ╚════██║ ██╔══╝ ██║╚██╗██║██║ ██╔══██╗ ╚██╔╝ ██╔═══╝ ██║ ███████╗███████╗ ██║ ███████║ ███████╗██║ ╚████║╚██████╗██║ ██║ ██║ ██║ ██║ ╚══════╝╚══════╝ ╚═╝ ╚══════╝ ╚══════╝╚═╝ ╚═══╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ██╗ ██║ ████████╗ ██╔═██╔═╝ ██████║ ╚═════╝ ██████╗███████╗██████╗ ████████╗██████╗ ██████╗ ████████╗ ██╔════╝██╔════╝██╔══██╗╚══██╔══╝██╔══██╗██╔═══██╗╚══██╔══╝ ██║ █████╗ ██████╔╝ ██║ ██████╔╝██║ ██║ ██║ ██║ ██╔══╝ ██╔══██╗ ██║ ██╔══██╗██║ ██║ ██║ ╚██████╗███████╗██║ ██║ ██║ ██████╔╝╚██████╔╝ ██║ ╚═════╝╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ▄▄██ ██▄▄ ░▄▄▓██████▌ ▐██████▓▄▄░ ▀██▓░▀███ ▄▄▄▄ ▄▄▄▄▄█░ ░█▄▄▄▄▄ ▄▄▄▄ ███▀░▓██▀ ░ ▀██▄ ▀█▓ ▄▄███████▄ ▀▓▀ ▓█▄ ▄█▓ ▀▓▀ ▄███████▄▄ ▓█▀ ▄██▀ ░ █▄▄ ▀█▓ ▀██▀▀░ ▀▀▓█▒ ░▄▄▄▓███ ░ ░ ███▓▄▄▄░ ▒█▓▀▀ ░▀▀██▀ ▓█▀ ▄▄█ ▒███▓▄▄ ▀█▄ ▀███▓▀▀▀░ ░▀▀▀▓███▀ ▄█▀ ▄▄▓███▒ ▓███▀▀▓█▄███▄ ▀ ▀ ▄███▄█▓▀▀███▓ ██▓██▄▄ ▀▀▓▓ ▓▓▀▀ ▄▄██▓██ ░▀▀▀███▄ ▄███▀▀▀░ ██████▄██▓ .:: W E L C O M E ::. ▓██▄██████ ▓██ ██▓ ░█▓ While the examples here are largely Node based, the concepts are applicable to any ██░ ██ application based web server where you want to securely deploy any application or ██ █▓ service with HTTPS using Let's Encrypt and Certbot ▓█ █▓ ▓█ █▓ ▓█ █▓ ▓█ ▐███▓▄▄▄▄ ▄▌ ▐▄ ▄▄▄▄▓███▌ ▀ ▄██▓ ░▄▄▄▄▄██ ██░ ▄▄█ █▄▄ ░██ ██▄▄▄▄▄░ ▓██▄ ▀ ▄█████▓██▓▀▀▀██▌▐███▄ ▐▓▓█▄░▄█▄ ▄█▄░▄█▓▓▌ ▄███▌▐██▀▀▀▓██▓█████▄ ▄█▓▀▀▀▀▀ ▓██ ██▓▐█▓ ██ ▀█▀ ▀■ ■▀ ▀█▀ ██ ▓█▌▓██ ██▓ ▀▀▀▀▀▓█▄ ███▓███ ▀████▌ ▐████▀ ███▓███ ░▀ ▀▌ █▀ ▀█ ▐▀ ▀░
Let's Encrypt is afree,automated, and open certificate authority brought to you by the nonprofitInternet Security Research Group (ISRG).
Certbot is afree, open source software tool for automatically using Let’s Encrypt certificates onmanually-administrated (emphasis mine) websites to enable HTTPS.Certbot is made by the Electronic Frontier Foundation (EFF), a 501(c)3 nonprofit based in San Francisco, CA, that defends digital privacy, free speech, and innovation
██╗ ██╗██╗ ██╗██╗ ██╗ ██╗ ██╗████████╗████████╗██████╗ ███████╗██████╗██║ ██║██║ ██║╚██╗ ██╔╝ ██║ ██║╚══██╔══╝╚══██╔══╝██╔══██╗██╔════╝╚════██╗██║ █╗ ██║███████║ ╚████╔╝ ███████║ ██║ ██║ ██████╔╝███████╗ ▄███╔╝██║███╗██║██╔══██║ ╚██╔╝ ██╔══██║ ██║ ██║ ██╔═══╝ ╚════██║ ▀▀══╝╚███╔███╔╝██║ ██║ ██║ ██║ ██║ ██║ ██║ ██║ ███████║ ██╗ ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚══════╝ ╚═╝
HTTPS is part of theTransport Layer Security (TLS) protocol, the successor of the now-deprecated Secure Sockets Layer (SSL), and is the main technology backing HTTPS (HTTP over TLS). HTTPS provides a secure, encrypted communications channel between the end user (browser) and the website or service it is communicating with. Secure communications become more important when you are exchanging information with users.
Unless you are specifically trying tocreate a way to get around captive portals, HTTPS is important for a few reasons:
It's free, and it's automated. It will cost you nothing other than your time. Set it up once, you won't have to touch it again. This article should help reduce your time adding HTTPS to your app/service easier.
An oft told tale ofman-in-the-middle attack is touted as a primary reason behind securing your app/service.The basic idea being that some bad actor takes the time to impersonate, and/or alter, or steal your data while in flight. While this may still be true, it's considerably easier, and far more likely, that someone would look for your unencrypted data in the numerous log files of all the devices between the end users browser and the server, including wireless access points, routers, switches, modems, and firewalls. When seen in this is context, and the potential for exposure of your unencrypted data, HTTPS seems like a better approach to secure what is important.
In August 2014 Google HTTPS Everywhere initiative began usingHTTPS as a ranking signal to give HTTPS related sites priority over HTTP websites. While not a primary signal of rank, it is a factor, and if your web app/service is public, having HTTPS in place legitimizes your hard work. People are far likelier to use your stuff if they don't seen warnings like:
Secure | Insecure |
---|---|
![]() | ![]() |
██████╗ ██████╗ █████╗ ██╗ ███████╗██╔════╝ ██╔═══██╗██╔══██╗██║ ██╔════╝██║ ███╗██║ ██║███████║██║ ███████╗██║ ██║██║ ██║██╔══██║██║ ╚════██║╚██████╔╝╚██████╔╝██║ ██║███████╗███████║ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚══════╝
- It should be easy to set up
- It should be easy to maintain
- It should run with least privilege
- It should not compromise security of the app or the operating system
What we know:
Node App | Let's Encrypt |
---|---|
Usually run in the context of the login user | Run as sudo to register, setup, and renew |
Login user usually has sudoers access | Saves certificates as root:root with permissions of 700 |
SHOULDNOT BE RUN AS ROOT | Saves files to /etc/letsencrypt/archive/ and symlinks /etc/letsencrypt/live/ back to /etc/letsencrypt/archive/ |
May have to access assets on the file system with different users/groups/permissions | Documentation recommends creating a publicly accessible key file for validation |
Usually runs on some port other than 80 or 443 | Certificates expire every 90 days |
████████╗██╗ ██╗███████╗ ██████╗ ██████╗ ██████╗ ██████╗ ██╗ ███████╗███╗ ███╗╚══██╔══╝██║ ██║██╔════╝ ██╔══██╗██╔══██╗██╔═══██╗██╔══██╗██║ ██╔════╝████╗ ████║ ██║ ███████║█████╗ ██████╔╝██████╔╝██║ ██║██████╔╝██║ █████╗ ██╔████╔██║ ██║ ██╔══██║██╔══╝ ██╔═══╝ ██╔══██╗██║ ██║██╔══██╗██║ ██╔══╝ ██║╚██╔╝██║ ██║ ██║ ██║███████╗ ██║ ██║ ██║╚██████╔╝██████╔╝███████╗███████╗██║ ╚═╝ ██║ ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚══════╝╚══════╝╚═╝ ╚═╝
Node running as a non root-user trying to access the Let's Encrypt certificate files that are only available to the root-user causing anEACCES: permission denied
error like:
Error: EACCES:permissiondenied,open'/etc/letsencrypt/live/some_domain_name/privcert.pem'atObject.openSync(fs.js:438:3)atObject.readFileSync(fs.js:343:35)atObject.<anonymous>(/some_path/server.js:26:12)atModule._compile(internal/modules/cjs/loader.js:701:30)atObject.Module._extensions..js(internal/modules/cjs/loader.js:712:10)atModule.load(internal/modules/cjs/loader.js:600:32)attryModuleLoad(internal/modules/cjs/loader.js:539:12)atFunction.Module._load(internal/modules/cjs/loader.js:531:3)atFunction.Module.runMain(internal/modules/cjs/loader.js:754:12)atstartup(internal/bootstrap/node.js:283:19)
███████╗ ██████╗ ██╗ ██╗ ██╗████████╗██╗ ██████╗ ███╗ ██╗███████╗██████╗██╔════╝██╔═══██╗██║ ██║ ██║╚══██╔══╝██║██╔═══██╗████╗ ██║██╔════╝╚════██╗███████╗██║ ██║██║ ██║ ██║ ██║ ██║██║ ██║██╔██╗ ██║███████╗ ▄███╔╝╚════██║██║ ██║██║ ██║ ██║ ██║ ██║██║ ██║██║╚██╗██║╚════██║ ▀▀══╝███████║╚██████╔╝███████╗╚██████╔╝ ██║ ██║╚██████╔╝██║ ╚████║███████║ ██╗ ╚══════╝ ╚═════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝ ╚═╝
There are some creative, disturbing, wrong, or relatively complicated advice on Stack Overflow to get this setup to work.Some of the potential solutions below are perfectly valid ways to go about achieving the goal of deploying a Node app/service with Let's Encrypt, but adds a level of complexity thatmay be overkill for the task at hand. The goal is a simple server to run a app/service, We don't want to be fighting with a lot infrastructure.
Some of the proposed solutions fell into these 4 main categories:
- changing public key, private key, and certificate authority file permissions
- moving public key, private key, and certificate authority files directly into the node application directory
- spin up another web server like Apache or NGiИX for reverse proxying traffic
- using Docker for reverse proxying traffic
e.g.chmod 755 /etc/letsencrypt/live/some_domain_name/*.pem
Pros
- It works
Cons
- It's inherently less secure than other options(read and execute permission for non root users on the file)
- It messes with the default, secure permissions set up by CertBot for the files and directory structure
- It can potentially interfere with the CertBot script functionality (now or in the future) if there are permissions checks in place
- Any user on the system can now access the files
Private keys usually have the permissions of 600 (owner: read+write), Certificates permissions of 700 (owner: read+write+execute) for a reason. They should only be accessible to the root-user and not anyone else, the same logic applies with the Let's Encrypt files. We want to keep the private stuff private and secure.
- ✔️ It should be easy to set up
- ✔️ It should be easy to maintain
- ❌ It should run with least privilege
- ❌ It should not compromise security of the app or the operating system
Potential Solution 2: Moving pubkey.pem, privkey.pem, and ca.pem files directly into the node application directory
e.g.cp /etc/letsencrypt/archive/some_domain_name/* some_path/ && chmod 755 some_path/*.pem
Pros
- It works
Cons
- It's inherently less secure than other options
- This is the equivalent to moving the combination closer to the safe. If your application code, a dependency you rely on, or the web server itself are compromised your keys potentially could be as well
- It introduces another step in a process that should be automated. You may need to manually move the files after the updates, write a script to do so, update the synlinks, etc.
- It messes with the default secure permissions set up by CertBot for the files and directory structure
- It can potentially interfere with the CertBot script functionality (now or in the future) it there are permissions checks in place
- Any user on the system can now access the files
We want to take advantage of what CertBot does and then leave it be. We do not want to introduce any fragility to the process where a script could fail, a symlink disappears etc.
- ✔️ It should be easy to set up
⚠️ It should be easy to maintain- ❌ It should run with least privilege
- ❌ It should not compromise security of the app or the operating system
Potential Solution 3: Spin up an Apache or NGiИX webs erver and reverse proxy requests to the back end Node app server
Pros
- It works
- It scales if you have multiple apps and/or services
- It can be more secure (if Apache or NGiИX are configured correctly)
- Apache and NGiИX run in different contexts (users) than Node
- TLS (HTTPS) termination at this level can reduce the number certificates for individual apps/services
Cons
- This could be overkill for the task at hand
- It's an added layer that can make things harder to diagnose, debug, and maintain
- It requires knowledge of Apache or NGiИX configuration which can a high bar for entry
This is an attractive option, albeit an advanced one, if you need to maintain multiple Node apps and/or services or maintain different apps and/or services written in different languages. One possibility is that Apache or NGiИX can act as a load balancer and handle the HTTPS termination in one place rather than each app and/or service doing so individually
- ❌ It should be easy to set up
⚠️ It should be easy to maintain- ✔️ It should run with least privilege
- ✔️ It should not compromise security of the app or the operating system
Pros
- It works
- It scales (up to a point) if you have multiple apps and/or services
- It can be more secure (if the orchestration platform e.g. Docker Server, Kubernetes and the container are configured correctly)
- Docker runs in different contexts (users) than Node
Cons
- This could be overkill for the task at hand
- It requires existing infrastructure to be in place and secured (e.g. Kubernetes, EKS, GKS, Rancher) Running Docker in production isvery different than Docker locally
- Some official Docker images are outdated and insecure
- It's an added layer that can make things harder to diagnose, debug, and maintain
- It requires some knowledge of Docker configuration which may be a high bar for entry
docker run container_name
is inherently more insecure then other options unless limits are added
This is an attractive option, albeit an advanced one, if you need to maintain multiple Node apps and/or services or maintain different apps and/or services written in different languages. If you already have infrastructure in place to support this option, great. If not, then getting something up quickly, securely and cheaply might be an issue. It's important to know that some official Node images can bevery insecure. There are many secure options available depending on your needs.
- ❌ It should be easy to set up
- ❌ It should be easy to maintain
⚠️ It should run with least privilege⚠️ It should not compromise security of the app or the operating system
█████╗ ██████╗ ███████╗████████╗████████╗███████╗██████╗ ██╗ ██╗ █████╗ ██╗ ██╗██╔══██╗ ██╔══██╗██╔════╝╚══██╔══╝╚══██╔══╝██╔════╝██╔══██╗ ██║ ██║██╔══██╗╚██╗ ██╔╝███████║ ██████╔╝█████╗ ██║ ██║ █████╗ ██████╔╝ ██║ █╗ ██║███████║ ╚████╔╝██╔══██║ ██╔══██╗██╔══╝ ██║ ██║ ██╔══╝ ██╔══██╗ ██║███╗██║██╔══██║ ╚██╔╝ ██║ ██║ ██████╔╝███████╗ ██║ ██║ ███████╗██║ ██║ ╚███╔███╔╝██║ ██║ ██║ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ ╚══╝╚══╝ ╚═╝ ╚═╝ ╚═╝
You must have a valid domain and that domain must be available via DNS. Lets Encrypt Certificates do not support IP Addresses
Your domain needs to be pointing to a VM, Container, or Load Balancer etc. and that VM, Container, or Load Balancer must be reachable on the INTERNET
Your VM, Container, or Load Balancer must have SSH access
The user must have sudoer access
██╗ ███████╗████████╗███████╗ ██████╗ ██████╗ ██╗██║ ██╔════╝╚══██╔══╝██╔════╝ ██╔════╝ ██╔═══██╗██║██║ █████╗ ██║ ███████╗ ██║ ███╗██║ ██║██║██║ ██╔══╝ ██║ ╚════██║ ██║ ██║██║ ██║╚═╝███████╗███████╗ ██║ ███████║ ╚██████╔╝╚██████╔╝██╗╚══════╝╚══════╝ ╚═╝ ╚══════╝ ╚═════╝ ╚═════╝ ╚═╝
Install CertBot by openinghttps://certbot.eff.org/lets-encrypt/sharedhost-other in a new tab. Select My HTTP website is runningNone of the above on<YOUR_OPERATING_SYSTEM>
Follow the instructions for installing Certbot for your OS. Once you have installed proceed to the next step
If this is your first time running Certbot. Register your account by replacing
<MY_EMAIL_ADDRESS@MAIL.COM>
below with your real email addresssudo certbot register --agree-tos -m<MY_EMAIL_ADDRESS@MAIL.COM>
Successful output will look like:
Saving debug log to /var/log/letsencrypt/letsencrypt.log- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Would you be willing, once your first certificate is successfully issued, toshare your email address with the Electronic Frontier Foundation, a foundingpartner of the Let's Encrypt project and the non-profit organization thatdevelops Certbot? We'd like to send you email about our work encrypting the web,EFF news, campaigns, and ways to support digital freedom.- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -(Y)es/(N)o: YAccount registered.
Accepting the offer for the EFF to have your email is up to you.
It is likely that your app/service is running on some port other than 80. Before we attempt installing the certificates, your app/service needs to be available on the Web. To do this, we will add a temporaryiptables rule to route traffic from port 80 => to whatever port your app/service is running on
sudo iptables --table nat --append PREROUTING --in-interface<YOUR_NETWORK_INTERFACE> --protocol tcp --dport 80 --jump REDIRECT --to-port<YOUR_APPLICATION_PORT>
e.g.
sudo iptables --table nat --append PREROUTING --in-interface eth0 --protocol tcp --dport 80 --jump REDIRECT --to-port 3000
By default many network interfaces are
eth0
, however, this really depends on your Operating System and Version of Operating System. If you don't know what your network interface is, or want to confirm typeip addr
(Newer *Nix Distros) orifconfig
(Older *Nix Distros) into your terminal. In the example output below, the interface isens33
e.g.
user@ubuntu: ip addr 1: lo:<LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: ens33:<BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:a4:f1:4a brd ff:ff:ff:ff:ff:ff inet 192.168.0.1/24 brd 192.168.0.255 scope global dynamic ens33 valid_lft 1138sec preferred_lft 1138sec inet6 fe80::f53e:89e:b44a:c634/64 scope link valid_lft forever preferred_lft forever 3: docker0:<NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default link/ether 02:42:bc:d3:df:97 brd ff:ff:ff:ff:ff:ff inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0 valid_lft forever preferred_lft forever
The iptables rules are temporary and will go away on a VM reboot (we'll address this later). This previous rule states
- Intercept any traffic coming across the eth0 network interface on port 80 and redirect that traffic to port 3000
Optional: Check to see if the rule is there
sudo iptables --list --table nat
To ensure that our VM and app/service is secure, we're going to create a new non-root user to handle just the app/service stuff andonly the app/service stuff
sudo useradd -m node-user -s /usr/bin/bash
We are setting the default users login shell to bash, it can be any shell you want bash, rbash, bash, dash, tmux, screen etc.
Give the new
non-root
node-user a passwordsudo passwd node-user
⚠️ The app/service should run as thenode-user
after setup for the best security profile. If you will be regularly pulling code from some Source Code Management tool like GitHub, GitLab, or BitBucketit is highly recommended that you create ssh keys for thenode-user
before moving to the next step.GitHub SSH Key generation instructions
GitLab SSH Key generation instructions
Bitbucket SSH Key generation instructions
If this is a one-off set up, you can install the app/service under the
root-user
home directory, complete all of the necessary steps to set up Certbot and then move the app/service to the new user home directory and change the owner/group permissions accordinglysudo mv<YOUR_APP_DIRECTORY>~/node-user/&& chmod -R node_user:node_user~/node-user/<YOUR_APP_DIRECTORY>
Yourproduction version Node app/service needs to be running (Without HTTPS) while we install the certificates with Certbot.
Log in as your new non-root user, enter password when prompted:
su --login node-user
Build your app/service:
npm run build
Run your prod app/service:
npm run prod
Exit out of
node-user
exit
Next we are going to install the certificates.
webroot-path
needs to be apublicly available folder in your app directory structure after your build process. Certbot requires this for installation and validation, but will not store the certificate files in this folder.💥 You must be logged in as your root user 💥
sudo certbot certonly -d<MY_DOMAIN_NAME> --webroot --webroot-path<ABSOLUTE_PATH_TO>/<MY_APP_NAME>/public
e.g.
sudo certbot certonly -d mydomain.com --webroot --webroot-path /home/node-user/my_web_app/public
⚠️ There arerate limits for running the above command. If your command fails for any reason, add--dry-run
to the end of the command until you get the correct setup. This moves the registration attempt to Let's Encrypt staging environment where the rate limits are highere.g.
sudo certbot certonly -d mydomain.com --webroot --webroot-path /home/ubuntu/my_web_app/public --dry-run
Successful output will look like
Saving debug log to /var/log/letsencrypt/letsencrypt.logRequesting a certificate for mydomain.comSuccessfully received certificate.Certificate is saved at: /etc/letsencrypt/live/mydomain.com/fullchain.pemKey is saved at: /etc/letsencrypt/live/mydomain.com/privkey.pemThis certificate expires on 2021-11-05.These files will be updated when the certificate renews.Certbot has set up a scheduled task to automatically renew this certificate in the background.- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -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- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Doing it this way prevents having to manually add a file with the validation key to the public folder of your app/service
Next, stop your app/service and update the HTTPS/TLS configuration paths in your app/service
Log in as your new non-root user, enter password when prompted:
su --login node-user
Make your edits
consttls_svr=http2.createSecureServer({ca:fs.readFileSync('/etc/letsencrypt/live/<MY_DOMAIN_NAME>/ca.pem'),cert:fs.readFileSync('/etc/letsencrypt/live/<MY_DOMAIN_NAME>/cert.pem'),key:fs.readFileSync('/etc/letsencrypt/live/<MY_DOMAIN_NAME>/privkey.pem'),});
e.g.
consttls_svr=http2.createSecureServer({ca:fs.readFileSync('/etc/letsencrypt/live/mydomain.com/ca.pem'),cert:fs.readFileSync('/etc/letsencrypt/live/mydomain.com/cert.pem'),key:fs.readFileSync('/etc/letsencrypt/live/mydomain.com/privkey.pem'),});
As these paths SHOULD NOT change. You can commit file containing these paths in your Source Code Management tool, environment configuration files, AWS Secrets Manager etc.
Exit out of
node-user
exit
Now that we have gotten our certificates installed, lets correct our iptables rules to reflect the right configuration To do this, we need to delete our old temporary rule and add an iptables rule to route traffic from port 80 => 443 and another rule to route traffic from port 443 to whatever port your app is running on. Whether the end user goes to
http://mydomain.com
orhttps://mydomain.com
they will got to the secure version of the site💥 You must be logged in as your root user 💥
DELETE:
sudo iptables -t nat -D PREROUTING -i<YOUR_NETWORK_INTERFACE> -p tcp --dport 443 -j REDIRECT --to-port<YOUR_APPLICATION_PORT>
ADD:
sudo iptables -t nat -A PREROUTING -i<YOUR_NETWORK_INTERFACE> -p tcp --dport 80 -j REDIRECT --to-port 443sudo iptables -t nat -A PREROUTING -i<YOUR_NETWORK_INTERFACE> -p tcp --dport 443 -j REDIRECT --to-port<YOUR_APPLICATION_PORT>
e.g.
DELETE:
sudo iptables -t nat -D PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000
ADD:
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 443sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 3000
By default many network interfaces are
eth0
, however, this really depends on your Operating System and version of Operating System. If you don't know what your network interface is, or want to confirm that it is eth0 typeip addr
(Newer *Nix Distros) orifconfig
(Older *Nix Distros) into your terminal.The iptables rules are temporary and will go away on a VM reboot. The rules above state
Intercept any traffic coming across the eth0 network interface on port 80 and redirect that traffic to port 443
Intercept any traffic coming across the eth0 network interface on port 443 and redirect that traffic to port 3000
Optonal: Verify iptables rules have been updated as expected
sudo iptables --list --table nat
If the iptables rules do not look like:
Chain PREROUTING (policy ACCEPT)target prot optsource destination REDIRECT tcp -- anywhere anywhere tcp dpt:https redir ports 3000REDIRECT tcp -- anywhere anywhere tcp dpt:http redir ports 443
or an old rule is still present, you can delete a rule by replacing the -A with a -D on the original rule
e.g.
sudo iptables -t nat -D PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000
We're going to limit who has access to our new certificate files by creating a FACL (File Access Control List). By doing so we only allow the root-user and our new node-user access to the files without exposing the files to anyone else.
sudo setfacl --recursive --modify"u:user:permissions"<file/dir>
e.g.
sudo setfacl --recursive --modify u:node-user:rX /etc/letsencrypt/{live,archive}
This FACL states: recursively (--recursive) set access for node-user with Read+Execute permissions (--modify "u:user:permissions"* on all letsencrypt directories (/etc/letsencrypt/{live,archive}) for mydomain
* The capital "X" in the ACL specification means "add execute permission for directories only" and is convenient for situations where you don't know whether the ACL will be applied to a directory or a file
login as the new node-user, enter the password when prompted
su --login node-user
Rerun your application build script to reflect the newest changes
npm run build
Run your prod app/service:
npm run prod
Exit out of
node-user
exit
██████╗ ██████╗ ███╗ ██╗ ██████╗██╗ ██╗ ██╗███████╗██╗ ██████╗ ███╗ ██╗██╔════╝██╔═══██╗████╗ ██║██╔════╝██║ ██║ ██║██╔════╝██║██╔═══██╗████╗ ██║██║ ██║ ██║██╔██╗ ██║██║ ██║ ██║ ██║███████╗██║██║ ██║██╔██╗ ██║██║ ██║ ██║██║╚██╗██║██║ ██║ ██║ ██║╚════██║██║██║ ██║██║╚██╗██║╚██████╗╚██████╔╝██║ ╚████║╚██████╗███████╗╚██████╔╝███████║██║╚██████╔╝██║ ╚████║ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝ ╚═════╝╚══════╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝
If everything went as planned, you should now have a web application running or service with HTTPS enabled which will automatically renew every 90 days with the help of Certbot's auto-renewal script. The entire process accomplished the 4 goals we laid out at the beginning of this article
✔️ It should be easy to set up
Hopefully, the most tedious portion of this setup was reading the article and all the copying and pasting
✔️ It should be easy to maintain
Certbot's auto renewal script should be worry free.
Set it and forget it
✔️ It should run with least privilege
We created a new, non-root user with password, whose sole purpose is to run the app/service. We've then set up a FACL (File Access Control List) allowing only the root-user and the new, non-root user access
✔️ It should not compromise security of the app or the operating system
We haven't changed permission on any files or directories to get this to work
If things didn't go smoothly, checkout theCommon Issues file
About
Simple Application server with Let's Encrypt and Certbot
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.