skip to Main Content

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:

  1. running the node server as root so it has the permission to the files (not recommended for node).
  2. Copy the files with sudo cp to a local directory and apply permissions with sudo 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).
  3. running node as root, load the certificate and private key, and then change the uid to a non-root user with process.setgid() and process.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


  1. Chosen as BEST ANSWER

    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.


  2. 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 this

    chgrp -R staff /etc/letsencrypt/live/domain.name.example
    

    Then set the setgid bit of the directory’s permissions like so.

    chmod 02755 staff /etc/letsencrypt/live/domain.name.example
    

    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.

    Login or Signup to reply.
  3. 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:

    If you would like the live certificate files whose symlink location
    Certbot updates on each run to reside in a different location, first
    move them to that location, then specify the full path of each of the
    four files in the renewal configuration file. Since the symlinks are
    relative links, you must follow this with an invocation of certbot
    update_symlinks.

    For example, say that a certificate’s renewal configuration file
    previously contained the following directives:

    archive_dir = /etc/letsencrypt/archive/example.com
    cert = /etc/letsencrypt/live/example.com/cert.pem
    privkey = /etc/letsencrypt/live/example.com/privkey.pem
    chain = /etc/letsencrypt/live/example.com/chain.pem
    fullchain = /etc/letsencrypt/live/example.com/fullchain.pem
    

    The following commands could be used to specify where these files are
    located:

    mv /etc/letsencrypt/archive/example.com /home/user/me/certbot/example_archive
    sed -i 's,/etc/letsencrypt/archive/example.com,/home/user/me/certbot/example_archive,' /etc/letsencrypt/renewal/example.com.conf
    mv /etc/letsencrypt/live/example.com/*.pem /home/user/me/certbot/
    sed -i 's,/etc/letsencrypt/live/example.com,/home/user/me/certbot,g' /etc/letsencrypt/renewal/example.com.conf
    certbot update_symlinks
    

    Quote B (my solution, just because it is the simples -KISS principle)

    Regarding permissions and group ownerships they say the following:

    For historical reasons, the containing directories are created with
    permissions of 0700 meaning that certificates are accessible only to
    servers that run as the root user. If you will never downgrade to an
    older version of Certbot, then you can safely fix this using chmod
    0755 /etc/letsencrypt/{live,archive}.

    For servers that drop root privileges before attempting to read the
    private key file, you will also need to use chgrp and chmod 0640 to
    allow the server to read /etc/letsencrypt/live/$domain/privkey.pem.

    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 pem files in the directory mentioned above, are only symlinks:
    /etc/letsencrypt/archive and /etc/letsencrypt/keys contain all
    previous keys and certificates, while /etc/letsencrypt/live symlinks
    to the latest version

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search