Oracle CloudのVMインスタンスにnginxでwebサーバを建ててプロキシする。SSL化もする。
備忘録。
内容はタイトルの通りで、
- Oracle CloudのVMインスタンス上でnginxをインストールしてWebサーバをたてる。
- nginxの後ろに控えているアプリにプロキシする
- ついでにLet's Encryptを用いてSSL化もする(httpsでアクセスできるようにする)
という内容です。
目次
Oracle Linux上にnginxをインストールして動かす
公式ドキュメントを参考にする
まずはnginxのインストール
sudo dnf install -y nginx
nginxサービスの有効化
sudo systemctl enable --now nginx.service
このサービスはデフォルトで80ポートでリクエストを受け付けるwebサーバを起動する。 ただ現状はファイアウォールで弾かれると思うので、public IPを叩いてもwebサーバの画面は表示されない。
正常に動いているのかサービスの状態を確認するには下記のコマンドを実行する。
(正常に起動していれば、それっぽいログが表示されているはず)
sudo systemctl status nginx
Oracle cloud側で設定できる custom firewall profile
や Oracle Cloud Infrastructure instance
を利用している場合、80ポートを開く必要がある。
今回の場合OCI(Oracle Cloud Infrastructure)のVMインスタンス上で作業しているので、これに該当する。
よって、下記のコマンドを実行して、nginxサービスのファイアウォールポートを有効にしてやる。
# httpトラフィックを許可 sudo firewall-cmd --add-service=http --permanent # リロード sudo firewall-cmd --reload
そして http://<IP_address>/
にアクセスしてみる。...が、私の環境ではこれでも開かない。
何かを忘れている気がしたが、そうだ、そもそもVMインスタンス自体のIngress Rules
上で80ポートを許可していなかった。
というわけで Ingress Rules
に80ポートのアクセスを受け付けるようにする。
これで再びアクセスすると、nginxが表示される。
nginxを使って後ろで動くアプリをプロキシする
nginxの後ろでは3000ポートでリッスンしているサーバがいる。こいつにリクエストを流したい。
nginxを触るのは久しぶりでもう忘れてきてしまっているが、とりあえず調べながら必要最低限の設定だけ書きます。
設定ファイル作成
/etc/nginx/conf.d/default.conf
というファイルを作成して、ここにプロキシの設定を記載する。
ちなみにこれは /etc/nginx/nginx.conf
内の設定ファイルで下記のように記述されているため、conf.d
ディレクトリ内に設定ファイルを置くことで読み込まれている。
(デフォルトでこの記述はあるので、特にこちら側で記述を追加する必要はない)
include /etc/nginx/conf.d/*.conf;
プロキシの設定を書く
次にプロキシ設定。
sudo vim /etc/nginx/conf.d/default.conf
Vimで開き下記の内容を記述する。
server{ listen 80; server_name test.example.com(実際のURLは異なりますが、便宜上これを入れています); proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location / { proxy_pass http://localhost:3000; } }
これでnginxを再起動する。
sudo systemctl restart nginx
nginxで13: Permission deniedのエラーが出てしまう
指定したアドレスにアクセスすると、502エラーになる
下記のように権限周りを変更してみたが、だめだった。
sudo usermod -a -G opc nginx chmod 710 /home/opc
一度落ち着いてログを見てみる。
sudo tail /var/log/nginx/error.log
すると下記のようなログが出ている。
connect() to 127.0.0.1:3000 failed (13: Permission denied) while connecting to upstream...
権限周り?と思い、いろいろしらべていたところ、下記のブログに辿り着く。
どうやらSELinuxの機能によりこの問題が発生しているよう。
sudo setsebool httpd_can_network_connect on -P sudo systemctl restart nginx
これで無事に行けました。
httpsで通信できるようにする
実運用では https
通信を行うことになるので、次はhttps通信ができるようにする。
最初に打った firewall-cmd
で https
通信も許可するようにまずは設定する。
# httpsトラフィックを許可 sudo firewall-cmd --permanent --zone=public --add-service=https # リロード sudo firewall-cmd --reload
今回SSL化するのに無料で利用できるLet’s Encryptを使う。
certbotのインストール
Let's Encryptのクライアントであるcertbotをインストールしていく。
ぐぐると色々と情報が出てくるが、どうやら現在certbotはsnapでインストールすることを強く推奨されているらしい。
(古い情報を参照して設定しようとすると、以前は存在していたコマンドがなくなっていたりして結局うまく行かないので注意)
下記の公式情報を参照して、Oracle Linuxにインストールしていく。
ここで余談だが、Oracle LinuxはOracleによるRed Hat Enterprise Linux (RHEL) をベースとしたLinuxディストリビューションである。そのため snapd
をインストールする際に参照するページはRed Hat Enterprise Linux 向けのページを見ていくことになる。
あと一応実行した自身のversionも下記に記載しておく。
(最初、CentOSのドキュメントを参考にしていて、うまく snapd
がインストールできなかったので注意。snapdのドキュメントで見るべきはRed Hat Enterprise Linux のほう)
# 自身のOracle Linuxの環境 $ cat /etc/redhat-release Red Hat Enterprise Linux release 8.5 (Ootpa)
※参照したsnapdのインストールドキュメント
まずは epel
のインストール。
sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
sudo dnf upgrade
次に snapd
のインストール
sudo dnf install snapd # スナップ通信ソケットを管理するsystemdユニットを有効化 sudo systemctl enable --now snapd.socket # 従来のsnapをサポートするには以下のようにシンボリックリンクを貼る。 # 従来のsnapサポートが必須なのかよく分からないが、ドキュメントに書かれているのでとりあえずやったという感じです... sudo ln -s /var/lib/snapd/snap /snap
一旦ここでログアウトする必要がある。
Oracle Cloud上で行っている場合は、一旦接続を切って再度sshで接続してログインする。
再度ログイン後、下記のコマンドを実施。
# snapの最新バージョンを取得 # 上で最新が入っているので不要かと思ったけど実行すると何やら取得しているっぽい sudo snap install core; sudo snap refresh core
なお、apt、dnf、yum などの OS パッケージマネージャを使用して Certbot パッケージをインストールしている場合は、Certbot スナップをインストールする前にそれらを削除して、certbot コマンドを実行するときに OS パッケージマネージャからのインストールではなく、スナップが使用されるようにする必要があるとのことだが、ここについては今回インストール自体が初めてなので気にしていない。
そしてようやく certbot
のインストール
sudo snap install --classic certbot
下記のコマンドを叩いて実行されることを確認。これで完了。
sudo ln -s /snap/bin/certbot /usr/bin/certbot certbot --help
nginxで使うためのSSL証明書を発行する
というわけで、ようやくSSL証明書の発行に移る。
sudo certbot --nginx
これをやるとCLIがインタラクティブな状態になって色々聞かれる。
- 緊急連絡用のメールアドレスを聞かれる(証明書の更新が迫るとメールが来るらしいので、管理者のアドレスを入力)
- 利用規約を承諾するか?(内容をチェックしてからYes)
- 電子フロンティア財団にメールアドレスを提供するか?(これは別に提供しなくて問題ない)
- どのドメインをhttpsにするか?(nginxで既に設定済みの場合は、そのURLが表示されている)
これらに対して回答を行うことでSSL証明書が生成される。
ここまでやるとnginx側の設定ファイルにもSSL設定に関する内容が追記されている。
(該当箇所にはmanaged by Certbot
とコメントあり。)
ちなみにこの時点で実際にアクセスしてみると https
化されている。
あとは443でアクセスできるように、VMインスタンス自体のIngress Rules
上で443ポートを許可してやる。
ちなみにhttp
でアクセスしても https
にリダイレクトされるように設定してくれている。
なお、もっと手作業でやりたい人は下記のコマンドを使うらしい。
(例えば今回のようにインタラクティブに設定したくない人、スクリプトで自動化している人などはこういうのを使うのか?あまり中身を見ていないのでここについては想像です)
sudo certbot certonly --nginx
自動更新をONにする
Certbotには、証明書が期限切れになる前に自動的に更新するcronジョブまたはsystemdタイマーが付属している。
設定を変更しない限り、Certbot を再度実行する必要はないらしい。
このコマンドを実行することで、証明書の自動更新をテストすることができる。
sudo certbot renew --dry-run
結果が問題なさそうであればOK。
なお、certbot
の renew
コマンドは以下のいずれかに格納されているらしい。
/etc/crontab/ /etc/cron.*/* systemctl list-timers
というわけで、Let's Encryptを用いたhttps化については以上。
振り返ってみるとそこまでの量はないものの、意外と最初躓いたりして思った以上に疲れました。