У меня настроен сервер Node.js, и я пытаюсь использовать HTTPS с моим сертификатом Let's Encrypt на Apache. Вот соответствующий код, который я настроил:
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')
}, ...
При попытке запустить скрипт возникает следующая ошибка:
Error: EACCES: permission denied, open '/etc/letsencrypt/live/www.mysite.com/privkey.pem'
Это потому, что только владелец root владеет каталогами и файлами Let's Encrypt для SSL, который в настоящее время используется с моими 30+ обычными веб-сайтами на Apache. Я пытаюсь настроить приложение Node для одного веб-сайта. Мои файлы проекта node app.js принадлежат mysite1:mysite1, и я знаю, что должно быть безопаснее запускать приложение node как не-root пользователь (например, "mysite1").
Как правильно обеспечить безопасную работу моего Let's Encrypt HTTPS с приложением Node.js (на Apache) без предоставления моему каталогу /etc/letsencrypt прав 755?
ПРАВКА - УТОЧНЕНИЕ:
Node.js и Apache работают бок о бок. В моем файле virtualHost .conf для веб-сайта 443 DocumentRoot — это /home/mysite1/mysite1.com , для которого был установлен мой Let's Encrypt SSL.
Мое приложение Node.js настроено в /home/mysite1/app . На сайте я использую socket.io как чат-комнату для всего сайта, и он прекрасно подключается/работает со следующими (если приложение запущено как пользователь root), ProxyPass не требуется:
<script src="//www.mysite1.com:3000/socket.io/socket.io.js"></script>
<script>var socket = io('https://www.mysite1.com:3000');</script>
Когда я запускаю приложение как не-root пользователь (в целях безопасности), единственная ошибка, которую я вижу, это то, что у моего node app есть ошибка разрешения при попытке доступа/настройки файлов SSL. Что конкретно мне делать, я не очень понимаю, как запустить это "позади" Apache, или есть более простое решение?
Кажется, должно быть более простое решение, может быть, node.js запускается от имени root, чтобы получить данные SSL и запустить сервер, прежде чем передать их пользователю, как это делает Apache?
ПРАВКА 2:
Основываясь на предложении Майкла и ezra-s, я некоторое время искал в Google и изменил несколько вещей, но не могу заставить это работать. В Apache я сделал что-то вроде этого:
<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>
В моем файле проекта node app.js я удалил параметры require('https') и certificate и заменил их пакетом "http" и попытался инициализировать скрипт.
На странице моего веб-сайта есть скрипты, которые пытаются загрузить socket.io и подключиться к приложению Node:
<script src="https://www.mysite1.com/node/socket.io/socket.io.js"></script>
<script>var socket = io('https://www.mysite1.com/node/');</script>
При загрузке страницы возникает ошибка 500, и скрипт не загружается. Что мне следует изменить в конфигурации Apache или URL-адресах скрипта? Я никогда раньше не использовал прокси с node, это мое первое приложение node.
РЕШЕНИЕ:
Я понял, что это была комбинация других вещей, которые нужно было сделать, с использованием веб-сокетов и JavaScript:
1) Apache Config для работы с веб-сокетамиhttps://stackoverflow.com/a/41685748/2317571
2) Конфигурация соединения сокета JavaScript для клиентаhttps://stackoverflow.com/questions/22919276/how-to-connect-socket-io-through-a-reverse-proxy
3) (бонусный совет): Благодаря совету Майкла и ezra-s о том, как разместить приложение node за Apache, я могу использовать брандмауэр ufw и заблокировать порт node/socket.io 3000 на localhost — на один порт (и дыру в безопасности) меньше, открытый миру. Надеюсь, эта информация поможет кому-то еще.
решение1
1. Запустите приложение Node.js на отдельном порту.
2. Обратные прокси к нему.
Примечание:Соединение между приложением Node.js и Apache будет осуществляться по протоколу HTTP. Однако оно будет происходить только на уровне "localhost". Поэтому все будет в порядке.
Конфигурация виртуального хоста:
<VirtualHost *:443>
ServerName nodeapp.com
ServerAdmin webmas@localhost
DocumentRoot /var/www/nodeapp
SSLEngine on
SSLCertificateFile /path/to/cert
SSLCertificateKeyFile /path/to/key
ProxyRequests off
ProxyPass "/" "http://127.0.0.1:node_app_port/"
ProxyPassReverse "/" "http://127.0.0.1:node_app_port/"
ErrorLog ${APACHE_LOG_DIR}/nodeapp_error.log
CustomLog ${APACHE_LOG_DIR}/nodeapp_access.log combined
</VirtualHost>