I am developing a secure web server on node.js and I am using Let’s Encrypt certificates with the https
module.
I want it to run on Ubuntu/Debian machines.
By default, the certificate and private key are stored in:
/etc/letsencrypt/live/domain.name.example/fullchain.pem
/etc/letsencrypt/live/domain.name.example/privkey.pem
These files permissions only allow the root user to read them, so the problem is that the node.js server can’t load them normally using:
const cert = fs.readFileSync("/etc/letsencrypt/live/domain.name.example/fullchain.pem");
const privKey = fs.readFileSync("/etc/letsencrypt/live/domain.name.example/privkey.pem");
(Which will throw a permission error)
The only solutions to this I know are:
- running the node server as root so it has the permission to the files (not recommended for node).
- Copy the files with
sudo cp
to a local directory and apply permissions withsudo chmod +r
so they can be accessed by the server after every certificate renewal (let’s encrypt does not recommend to copy these files, this is my current solution though). - running node as root, load the certificate and private key, and then change the uid to a non-root user with
process.setgid()
andprocess.setuid()
, which will drop root privileges.
My question is if there is a better solution to achieve this, or maybe one of these methods are just fine?
3
Answers
As per O. Jones comment, I solved this problem by using nginx as a reverse-proxy for my nodejs server. This way nginx handles the SSL without permission issues, and nodejs only needs to run an http server.
Use
setgid
.Set the group ownership of the directory to the group you’re using to run nodejs. If your user and group are
itay:staff
for example, say thisThen set the
setgid
bit of the directory’s permissions like so.Thereafter, any files written to that directory will be owned by that group,
staff
in this example. So, your nodejs program will be able to read them without any further ado.The problem was solved by following the second recommendation here by letsencrypt documentation (Quote B) that doesn’t require me to create any script to move or copy the files whenever the certificate auto renews (I installed mine with the –apache plug-in, as a side note, it you have your redirect from http to https inside your virtual host, when you first run certbot use –no-redirect to avoid an error being reported during the installation of the certificates).
Despite that I found unnecessary to move or copy the pem files. In the certbot documentation here, I don’t find that letsencrypt doesn’t recommend to move the certificates, in their documentation as of now they even tell you how to do it right:
Quote A:
Quote B (my solution, just because it is the simples -KISS principle)
Regarding permissions and group ownerships they say the following:
Which is VERY interesting, they are 700 only for historical reasons. What they don’t clarify is that the /etc/letsencrypt/live and keys folders are 700, and in 20.04 Ubuntu you can’t even see that the folder exists unless you become root, yes sudo doesn’t work, folder not found error.
the -d or domain folders are 755 (/etc/letsencrypt/live.domain.com) and the symlinks themselves to the .pem files are 777.
Letsencrypt documentation says:
The keys themselves have permissions: 600
In my Ubuntu 20.04 system with cerbot –apache certificate and installation I find that the keys folder has 000x_key-certbot.pem files with permissions 600, and the the archive directory has the actual cert1.pem, chain1.pem, fullchain1.pem and privkey1.pem files with permissions: 644, 644, 644 and 600 respectively.
The /etc/letsencrypt/archive/domain.com# folder has permissions 755 and /etc/letsencrypt/archive folder has permissions 700.
So access is blocked by hiding the directory and and blocking the keys themselves.