Node.js サーバーをセットアップし、Apache で Let's Encrypt 証明書を使用して HTTPS を使用しようとしています。セットアップした関連コードは次のとおりです。
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'
これは、現在 Apache 上の 30 を超える通常の Web サイトで使用されている SSL 用の Let's Encrypt ディレクトリとファイルを所有しているのはルート所有者のみであるためです。1 つの Web サイトに Node App を設定しようとしています。私の node app.js プロジェクト ファイルは mysite1:mysite1 によって所有されており、非ルート ユーザー (「mysite1」など) として node app を実行する方が安全であることはわかっています。
/etc/letsencrypt ディレクトリに 755 権限を与えずに、Let's Encrypt HTTPS を Node.js アプリ (Apache 上) で安全に動作させる適切な方法は何ですか?
編集 - 明確化:
Node.js と Apache は並行して実行されています。Web サイトの virtualHost .conf ファイルでは、443 DocumentRoot は /home/mysite1/mysite1.com であり、これは Let's Encrypt SSL がインストールされた場所です。
私の Node.js アプリは /home/mysite1/app に設定されています。Web サイトでは、サイト全体のチャット ルームとして socket.io を使用しており、次のように接続/正常に動作します (アプリがルート ユーザーとして起動されている場合)。ProxyPass は必要ありません。
<script src="//www.mysite1.com:3000/socket.io/socket.io.js"></script>
<script>var socket = io('https://www.mysite1.com:3000');</script>
セキュリティ上の理由から、非ルート ユーザーとしてアプリを実行すると、ノード アプリが SSL ファイルにアクセス/構成しようとしているときに権限エラーが発生するというエラーのみが表示されます。具体的に何をすればよいのでしょうか。Apache の背後でこれを実行するにはどうすればよいですか。または、もっと簡単な解決策はありますか。
もっと簡単な解決策があるように思えます。Apache のように、node.js を root として実行して SSL データを取得し、サーバーを実行してからユーザーに渡すというのはどうでしょうか?
編集2:
Michael と 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') と証明書オプションを削除し、それを "http" パッケージに置き換えて、スクリプトの初期化を試みました。
私の Web サイトのページには、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 で何を変更すればよいですか? これまでノードでプロキシを使用したことはありません。これが初めてのノード アプリです。
解決:
私はそれを理解しました。それは、Web ソケットと JavaScript に関連して実行する必要のある他のことの組み合わせでした。
1) Webソケットを扱うためのApache Confighttps://stackoverflow.com/a/41685748/2317571
2) クライアントのJavaScriptソケット接続設定https://stackoverflow.com/questions/22919276/how-to-connect-socket-io-through-a-reverse-proxy
3) (ボーナス ヒント): Michael と ezra-s のアドバイスのおかげで、Apache の背後にノード アプリを配置できるようになりました。これにより、ufw ファイアウォールを使用して、node/socket.io ポート 3000 を localhost にロックダウンできるようになりました。これにより、世界に公開されるポート (およびセキュリティ ホール) が 1 つ減ります。この情報が他の誰かの役に立つことを願っています。
答え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>