I have a Node.js server set up and I am trying to use HTTPS with my Let's Encrypt certificate on Apache. Here is the relevant code I have set up:
var fs = require('fs'),
https = require('https'),
express = require('express'),
options = {
key: fs.readFileSync('/etc/letsencrypt/live/www.mysite.com/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/www.mysite.com/fullchain.pem'),
ca: fs.readFileSync('/etc/letsencrypt/live/www.mysite.com/chain.pem')
}, ...
When I try starting up the script, I get this error:
Error: EACCES: permission denied, open '/etc/letsencrypt/live/www.mysite.com/privkey.pem'
It is because only the root owner owns the Let's Encrypt directories and files for the SSL, which is currently used with my 30+ regular websites on Apache. I am trying to set up a Node App for one website. My node app.js project files are owned by mysite1:mysite1 and I know it is supposed to be safer to run the node app as a non-root user (like "mysite1").
What is the proper way to make my Let's Encrypt HTTPS work securely with the Node.js App (on Apache) without having to give my /etc/letsencrypt directory 755 permissions?
EDIT - CLARIFICATION:
Node.js and Apache are running side-by-side. In my virtualHost .conf file for the website, 443 DocumentRoot is /home/mysite1/mysite1.com , which is what my Let's Encrypt SSL was installed for.
My Node.js app is set up in /home/mysite1/app . On the website, I use socket.io as a site-wide chat room and it connects/works perfectly fine with the following (if the app is started as a root user), no ProxyPass is required:
<script src="//www.mysite1.com:3000/socket.io/socket.io.js"></script>
<script>var socket = io('https://www.mysite1.com:3000');</script>
When I run the app as a non-root user (for security purposes), the only error that I see is my node app has a permission error trying to access/configure SSL files. What specifically should I do, I'm not very clear how to run this "behind" Apache, or if there is a simpler solution?
It seems like there must be a simpler solution, maybe node.js runs as root to get the SSL data and get the server running before handing it off to the user, like Apache does?
EDIT 2:
Based on Michael's and ezra-s's suggestion, I've searched on Google for awhile and have changed a few things around but can't get it to work. In Apache, I have done something like this:
<VirtualHost *:443>
ServerAlias mysite1.com
DocumentRoot /home/mysite1/mysite1.com
DirectoryIndex index.html index.php
<Directory /home/mysite1/mysite1.com>
.. web config stuff
</Directory>
ProxyRequests Off
ProxyPreserveHost On
ProxyVia Full
<Proxy *>
Require all granted
</Proxy>
<Location /node>
ProxyPass http://127.0.0.1:3000
ProxyPassReverse http://127.0.0.1:3000
</Location>
SSLEngine on
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/www.letshangout.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.letshangout.com/privkey.pem
</VirtualHost>
In my node app.js project file, I've removed the require('https') and certificate options and replaced it with the "http" package and attempt to initialize the script.
On a page on my website, I have scripts that attempt to load socket.io and connect with the node app:
<script src="https://www.mysite1.com/node/socket.io/socket.io.js"></script>
<script>var socket = io('https://www.mysite1.com/node/');</script>
When I load the page, there is a 500 error and the script doesn't load up. What should I change in my Apache config or the script URLs? I've never used proxy with node before, this is my first node app.
SOLUTION:
I figured it out, it was a combination of other things that needed to be done involving web sockets and javascript:
1) Apache Config for dealing with websockets https://stackoverflow.com/a/41685748/2317571
2) JavaScript Socket Connection Config for client https://stackoverflow.com/questions/22919276/how-to-connect-socket-io-through-a-reverse-proxy
3) (bonus tip): Thanks to advice from Michael and ezra-s for getting the node app behind Apache, I can use the ufw firewall and lock down the node/socket.io port 3000 to localhost - one less port (and security hole) open to the world. Hopefully this information can help someone else.