Rust
の Web
アプリケーションフレームワークの Rocket
で作成した Hello, world! のプロジェクトを AWS
の EC2
上で Nginx
を使用して公開する手順を説明していきたいと思います。
今回は「 Hello, world! 」を表示するだけのプロジェクトですが、実際に開発されたプロジェクトでも同じ手順で公開できると思います。
前提条件
- EC2 : Amazon Linux release 2
- rustup : 1.24.3
- Rust : 1.61.0-nightly
- Nginx : 1.20.0
今回は HTTP
での通信だけ行うので、 80
番ポートを解放しておく必要があります。
Nginx インストール
まずは Web
サーバなので Nginx
をインストールします。今回は EC2
での Nginx
のインストールなので yum
は使用せず、 amazon-linux-extras
を使用してインストールします。
# amazon-linux-extrasがあるか確認する
$ which amazon-linux-extras
# Nginxがパッケージとして存在するか確認
$ amazon-linux-extras
上記のコマンドを実行し、 nginx1
がリストに存在していれば amazon-linux-extras
から Nginx
をインストールできます。
$ sudo amazon-linux-extras install nginx1
インストール完了したら Nginx
の設定ファイルをバックアップしておきます。
$ sudo cp -a /etc/nginx/nginx.conf /etc/nginx/nginx.conf.back
Nginx
を起動します。
$ sudo systemctl start nginx
再起動時に自動で Nginx
が起動するようにしておきます。
$ sudo systemctl enable nginx
下記のコマンドで Nginx
のステータスを確認することができます。
$ sudo systemctl status nginx
Rust インストール
Rust
のインストール方法は詳しくは下記の記事を参考にしてください。
簡単にコマンドだけ書いておきます。
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
$ source $HOME/.cargo/env
$ rustup install stable
rustup
、 Rust
のバージョンは下記のコマンドで確認できます。
$ rustup --version
rustup 1.24.3 (ce5817a94 2021-05-31)
$ rustc --version
rustc 1.59.0 (9d1b2106e 2022-02-23)
Hello World! プロジェクトを作成する
/home/ec2-user
ディレクトリで新規に Rocket
のプロジェクトを作成します。
プロジェクトの作成方法については下記を参考にしてください。
プロジェクトのビルド時に「 error: linker cc
not found 」というエラーが出るかもしれませんが、その場合、 gcc コンパイラがインストールされていないので、 yum
コマンドを使用して gcc
をインストールします。
$ sudo yum install -y gcc
ビルド時は下記のコマンドを実行することでリリース版としてビルドできます。
$ cargo run --release
nginx.conf を編集する
Nginx
で今回作成したプロジェクトが表示できるように nginx.conf
を編集します。今回の設定では、ブラウザからこのサーバにアクセスがあった場合、 Nginx
がプロキシーサーバーとして動作し、 Nginx
を経由して EC2
の中にある http://localhost:8000
へアクセスさせる仕組みとなっています。
編集した nginx.conf
の全文を載せておきます。
nginx.conf
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
server {
listen 80;
listen [::]:80;
#server_name _;
#root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
location / {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection keep-alive;
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers PROFILE=SYSTEM;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
}
動作確認
Nginx
を再起動します。
$ sudo systemctl restart nginx
Rocket
のプロジェクトをビルドします。
$ cargo run --release
🔧 Configured for production.
=> address: 0.0.0.0
=> port: 8000
=> log: critical
=> workers: 2
=> secret key: generated
=> limits: forms = 32KiB
=> keep-alive: 5s
=> read timeout: 5s
=> write timeout: 5s
=> tls: disabled
Warning: environment is 'production', but no `secret_key` is configured
🚀 Rocket has launched from http://0.0.0.0:8000
この状態で EC2
インスタンスのパブリック IPv4 アドレスへブラウザからアクセスしてみます。
ブラウザから動作確認することができました!
最後に
Nginx
で Rocket
のプロジェクトを公開することができました。あとは HTTPS
化したり、 AWS
の RDS
と繋いで DB
と接続してみたりと色々確認しないといけないこともありますが、なんとか実際の業務にも使えそうな気がします。
コメント
環境変数を使ってポート変更するほうが手間が少ない気がするんですが、Nginxで公開するメリットってなんですか?
Nginxを使用せずRocketのみでWebサーバーを構築し、80番ポートを解放する場合、「cargo run」コマンドをroot権限で実行させる必要がるため、セキュリティ上あまり良い方法ではないと思います。
NginxをプロキシサーバとしてWebアプリを公開することでroot権限でアプリを実行する必要がなくなります。また、SSL化やアクセス制御などNginxで設定した方が実現難易度が低いと思います。
あとは、リプレースなどでRocketからGo言語のEchoなどに切り替えたりする場合に、WebサーバとしてNginxを使用している方がリプレースも簡単だと思います。
回答有り難うございます。
Rocketで TLS/SSL を有効化してみたのですが、公式でも Rocket を生で晒すのは危険であるという文言があり、ご指摘頂いてる Ngnix をプロキシサーバーとする方法が思い浮かび、このページに戻ってきました。。。
参考にさせていただきます。