5つのステップで完成!プロダクションサーバーのセットアップ方法
Webアプリケーションを開発し終えたら、次なるステップはそれを世界に公開することです。その舞台となるのが「プロダクションサーバー」です。しかし、単にコードをサーバーに置くだけでは、安定したサービス提供はできません。セキュリティ、パフォーマンス、そして信頼性を確保するためには、適切にサーバーをセットアップする必要があります。
この記事では、Linuxサーバー(特にUbuntu)をベースに、Webアプリケーションを公開するためのプロダクション環境を構築する手順を、5つの具体的なステップに分けて詳細に解説します。クラウドの自動化ツールが普及した現代でも、その裏側で何が行われているのかを理解することは、トラブルシューティング能力を高め、より堅牢なシステムを設計する上で非常に重要です。
Web開発者、インフラエンジニアを目指す方、あるいは個人プロジェクトを公開したいと考えているすべての方にとって、このガイドが実践的な知識となることを目指します。
この記事で構築する環境の前提
* OS: Ubuntu 22.04 LTS
* Webサーバー: Nginx
* アプリケーション: Node.js, Python, PHPなどを想定
* データベース: PostgreSQL
* クラウドプラットフォーム: AWS EC2, Google Cloud, Vultr, DigitalOceanなど、任意のVPS/クラウドサーバー
それでは、始めましょう。
ステップ1: サーバーの初期設定とセキュリティ強化
プロダクションサーバーを構築する上で最も重要なのが、土台となるサーバーの初期設定とセキュリティです。ここを疎かにすると、不正アクセスやデータ漏洩のリスクに常に晒されることになります。最初に堅牢な基盤を築きましょう。
1.1. サーバーのプロビジョニングと初回ログイン
まず、お好みのクラウドプロバイダーでサーバーインスタンスを作成します。OSには、長期サポート(LTS)が提供され、安定性と豊富な情報量で定評のある「Ubuntu 22.04 LTS」を選択することを強く推奨します。
インスタンスが作成されると、IPアドレスとroot
ユーザーの初期パスワード(またはSSHキー)が提供されます。これを使って、ターミナルからSSHでサーバーに初めてログインします。
“`bash
SSHキーを使用する場合
ssh -i /path/to/your-private-key.pem root@YOUR_SERVER_IP
パスワードを使用する場合
ssh root@YOUR_SERVER_IP
“`
1.2. 一般ユーザーの作成とsudo権限の付与
root
ユーザーは、システム上で何でもできる最高権限を持つユーザーです。日常的な作業をroot
で続けるのは、誤操作によるシステム破壊のリスクが非常に高く、セキュリティ上も危険です。
そのため、管理者権限(sudo
)を持つ一般ユーザーを作成し、今後はそのユーザーで作業を行います。
“`bash
新しいユーザーを作成(例: ‘deploy’というユーザー名)
adduser deploy
“`
adduser
コマンドを実行すると、パスワードの設定やユーザー情報の入力を求められます。パスワードは強力なものを設定してください。
次に、この新しいユーザーをsudo
グループに追加して、管理者権限を与えます。
bash
usermod -aG sudo deploy
これで、deploy
ユーザーはsudo
コマンドを使うことで、root
権限が必要な操作を実行できるようになりました。一度ログアウトし、新しく作成したユーザーで再ログインして確認しましょう。
“`bash
deployユーザーでログイン
ssh deploy@YOUR_SERVER_IP
sudoが使えるかテスト(aptパッケージリストの更新)
sudo apt update
“`
パスワードを求められ、コマンドが正常に実行できれば成功です。
1.3. SSHキー認証の設定(パスワード認証の無効化)
パスワード認証は、総当たり攻撃(ブルートフォースアタック)の標的になりやすいです。より安全な「SSH公開鍵認証」に切り替え、パスワードでのログインを禁止しましょう。
まず、ローカルマシン(あなたのPC)でSSHキーペアをまだ持っていない場合は生成します。
“`bash
ローカルマシンのターミナルで実行
ssh-keygen -t rsa -b 4096
“`
いくつか質問されますが、基本的にはEnterキーを押してデフォルト設定で問題ありません。これにより、~/.ssh/id_rsa
(秘密鍵)と~/.ssh/id_rsa.pub
(公開鍵)が生成されます。
次に、生成した公開鍵(id_rsa.pub
)の内容を、サーバー上のdeploy
ユーザーの~/.ssh/authorized_keys
ファイルにコピーします。ssh-copy-id
コマンドを使うと簡単です。
“`bash
ローカルマシンのターミナルで実行
ssh-copy-id deploy@YOUR_SERVER_IP
“`
最後に、サーバー側でSSHの設定ファイルを編集し、パスワード認証とrootログインを無効化します。
“`bash
サーバーにログインして実行
sudo nano /etc/ssh/sshd_config
“`
エディタで以下の行を見つけて、値を変更(またはコメントアウトを解除)します。
“`ini
/etc/ssh/sshd_config の中の設定例
rootユーザーでのSSHログインを禁止
PermitRootLogin no
パスワードでのログインを禁止
PasswordAuthentication no
``
PubkeyAuthentication yes` になっていることも確認してください(デフォルトでそうなっているはずです)。
設定を保存したら、SSHサービスを再起動して変更を適用します。
bash
sudo systemctl restart sshd
【重要】 このコマンドを実行する前に、別のターミナルウィンドウを開いて、新しいユーザーでSSHキーを使ってログインできることを必ず確認してください。設定ミスでサーバーから締め出されるのを防ぐためです。
1.4. ファイアウォールの設定 (UFW)
サーバーへの不要なアクセスをブロックするため、ファイアウォールを設定します。UbuntuにはUFW
(Uncomplicated Firewall) という使いやすいツールがプリインストールされています。
まず、許可する通信(ポート)を設定します。最低限、SSH(ポート22)、HTTP(ポート80)、HTTPS(ポート443)は必要です。UFWは一般的なアプリケーションの名前で設定できます。
“`bash
SSHの接続を許可
sudo ufw allow ‘OpenSSH’
Nginx用のHTTPとHTTPSをまとめて許可
sudo ufw allow ‘Nginx Full’
UFWを有効化
sudo ufw enable
“`
有効化の際に確認メッセージが表示されるので、y
と入力して進めます。
現在の設定状況は以下のコマンドで確認できます。
bash
sudo ufw status
これで、許可したポート以外からのアクセスはすべてブロックされるようになり、セキュリティが大幅に向上します。
1.5. システムのアップデートとタイムゾーン設定
最後に、システムのパッケージを最新の状態に保ち、タイムゾーンを正しく設定します。
“`bash
パッケージリストを更新
sudo apt update
パッケージをアップグレード
sudo apt upgrade -y
タイムゾーンを設定(例: 日本時間)
sudo timedatectl set-timezone Asia/Tokyo
“`
以上で、サーバーの基本的な初期設定とセキュリティ強化は完了です。これで安心して次のステップに進むことができます。
ステップ2: Webサーバーとデータベースのインストールと設定
アプリケーションを動かすための基盤となる、Webサーバーとデータベースをインストールします。ここでは、パフォーマンスと柔軟性に優れたNginxとPostgreSQLを選択します。
2.1. Webサーバー (Nginx) のインストール
Nginxは、その高いパフォーマンスとリソース効率の良さから、現代のWeb開発で広く採用されているWebサーバーです。リバースプロキシとしての機能も強力で、私たちの目的には最適です。
インストールはaptコマンドで簡単に行えます。
bash
sudo apt install nginx
インストールが完了すると、Nginxは自動的に起動します。動作確認のため、WebブラウザでサーバーのIPアドレス(http://YOUR_SERVER_IP
)にアクセスしてみてください。”Welcome to nginx!”というページが表示されれば、インストールは成功です。
また、先ほどUFWでNginx Full
を許可したため、HTTP(80)とHTTPS(443)のポートはすでに開いています。
2.2. データベース (PostgreSQL) のインストール
PostgreSQLは、堅牢性、拡張性、標準SQLへの準拠度が高いことで知られるオープンソースのリレーショナルデータベースです。
“`bash
PostgreSQLと関連パッケージをインストール
sudo apt install postgresql postgresql-contrib
“`
インストール後、PostgreSQLサービスも自動で起動します。PostgreSQLはpostgres
というLinuxユーザーを作成し、このユーザーがデータベースの管理者となります。
2.3. アプリケーション用データベースとユーザーの作成
セキュリティのベストプラクティスとして、アプリケーションごとに専用のデータベースと、そのデータベースにのみアクセス権を持つ専用のユーザーを作成します。
まず、postgres
ユーザーに切り替わって、PostgreSQLのコマンドラインツールpsql
を起動します。
bash
sudo -i -u postgres
psql
psql
のプロンプト(postgres=#
)が表示されたら、以下のSQLコマンドを実行してデータベースとユーザーを作成します。ここでは、データベース名をmyapp_db
、ユーザー名をmyapp_user
、パスワードをa_strong_password
とします。
“`sql
— ユーザーを作成(強力なパスワードを設定すること)
CREATE USER myapp_user WITH PASSWORD ‘a_strong_password’;
— データベースを作成
CREATE DATABASE myapp_db;
— データベースの所有者を新しいユーザーに設定
ALTER DATABASE myapp_db OWNER TO myapp_user;
— 新しいユーザーに、そのデータベースに対するすべての権限を付与
GRANT ALL PRIVILEGES ON DATABASE myapp_db TO myapp_user;
“`
いくつか設定を変更しておくと、後の開発がスムーズになります。
sql
-- 文字エンコーディングをUTF-8に
ALTER ROLE myapp_user SET client_encoding TO 'utf8';
-- デフォルトのトランザクション分離レベルを設定
ALTER ROLE myapp_user SET default_transaction_isolation TO 'read committed';
-- タイムゾーンをUTCに設定(アプリケーション側でローカルタイムに変換するのが一般的)
ALTER ROLE myapp_user SET timezone TO 'UTC';
設定が完了したら、\q
と入力してpsql
を終了し、exit
でpostgres
ユーザーから元のユーザーに戻ります。
これで、アプリケーションが接続するためのデータベースの準備が整いました。接続情報は、後のステップでアプリケーションの環境変数に設定します。
ステップ3: アプリケーションのデプロイと実行環境の構築
サーバーにアプリケーションのコードを配置し、それを安定して動かし続けるための環境を整えます。
3.1. ランタイムのインストール
アプリケーションが書かれた言語の実行環境(ランタイム)をインストールします。バージョン管理ツールを使うことで、プロジェクトごとに異なるバージョンを柔軟に使い分けることができます。
Node.jsの場合 (nvmを使用):
Node Version Manager (nvm) を使うと、Node.jsのバージョンを簡単に切り替えられます。
“`bash
nvmのインストールスクリプトをダウンロードして実行
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash
シェルを再起動してnvmを有効化
source ~/.bashrc
最新のLTSバージョンをインストールして使用
nvm install –lts
nvm use –lts
“`
Pythonの場合 (venvを使用):
システムのPythonとは別に、プロジェクト専用の仮想環境を作るのが一般的です。
“`bash
必要なツールをインストール
sudo apt install python3-pip python3-dev python3-venv
プロジェクトディレクトリに移動して仮想環境を作成
cd /var/www/my-python-app
python3 -m venv venv
仮想環境をアクティベート
source venv/bin/activate
“`
PHPの場合 (aptを使用):
PHPはaptで直接インストールするのが一般的です。PHP-FPM (FastCGI Process Manager) を使うことで、Nginxと効率的に連携できます。
“`bash
PHP-FPMと一般的な拡張機能をインストール
sudo apt install php-fpm php-mysql php-mbstring php-xml php-bcmath
“`
3.2. アプリケーションコードの配置
アプリケーションのコードは、バージョン管理システムであるGitを使ってサーバーに配置するのが最も効率的です。
“`bash
Webコンテンツを配置する標準的なディレクトリ
sudo mkdir -p /var/www/my-app
sudo chown -R $USER:$USER /var/www/my-app
GitHubなどからコードをクローン
git clone https://github.com/your-username/my-app.git /var/www/my-app
``
/var/wwwディレクトリはrootが所有者なので、
deployユーザーが書き込めるように所有権を変更(
chown`)するのを忘れないようにしましょう。
3.3. 依存関係のインストールと環境変数の設定
コードを配置したら、プロジェクトに必要なライブラリ(依存関係)をインストールします。
“`bash
cd /var/www/my-app
Node.jsの場合
npm install –production
Pythonの場合(仮想環境をアクティベートしてから)
pip install -r requirements.txt
PHPの場合
composer install –no-dev
“`
次に、データベース接続情報やAPIキーなどの機密情報を環境変数として設定します。.env
ファイルを使うのが一般的です。
“`bash
.envファイルを作成
nano /var/www/my-app/.env
“`
ファイルの中身は以下のようになります。
“`dotenv
/var/www/my-app/.env
DATABASE_URL=”postgresql://myapp_user:a_strong_password@localhost:5432/myapp_db”
NODE_ENV=”production”
SECRET_KEY=”some_very_long_random_string”
“`
この.env
ファイルは、絶対にGitリポジトリに含めないでください。.gitignore
ファイルに.env
を追加するのを忘れないようにしましょう。
3.4. プロセス管理ツールによるアプリケーションの永続化
開発中はnode app.js
やpython app.py
のように手動でサーバーを起動しますが、プロダクション環境ではサーバーが再起動してもアプリケーションが自動で立ち上がり、クラッシュした際にも自動で再起動してくれる仕組みが必要です。そのためのツールがプロセス管理ツールです。
Node.jsの場合 (PM2):
PM2はNode.jsアプリケーション用の非常に高機能なプロセス管理ツールです。
“`bash
PM2をグローバルにインストール
sudo npm install pm2 -g
アプリケーションを起動
cd /var/www/my-app
pm2 start index.js –name my-app
サーバー起動時にPM2が自動で起動するように設定
pm2 startup systemd
表示されたコマンドをコピーして実行
現在のプロセスリストを保存
pm2 save
“`
Pythonやその他の言語の場合 (systemd):
systemdは、Ubuntuの標準的なサービス管理システムです。自作のアプリケーションをサービスとして登録することで、永続化を実現できます。
まず、サービスユニットファイルを作成します。
bash
sudo nano /etc/systemd/system/my-app.service
ファイルに以下の内容を記述します(Python/Gunicornの例)。
“`ini
[Unit]
Description=My Python App Service
After=network.target
[Service]
User=deploy
Group=www-data
WorkingDirectory=/var/www/my-app
EnvironmentFile=/var/www/my-app/.env
ExecStart=/var/www/my-app/venv/bin/gunicorn –workers 3 –bind unix:my-app.sock -m 007 wsgi:app
[Install]
WantedBy=multi-user.target
``
User
*,
Group: サービスを実行するユーザーとグループ。
WorkingDirectory
*: 作業ディレクトリ。
EnvironmentFile
*:
.envファイルを読み込む設定。
ExecStart`: アプリケーションを起動するコマンド。ここでは、UNIXソケットを使ってNginxと通信するGunicornの例を示しています。
*
ファイルを作成したら、サービスを有効化して起動します。
“`bash
systemdに新しいサービスを認識させる
sudo systemctl daemon-reload
サービスを起動
sudo systemctl start my-app
サーバー起動時に自動でサービスが起動するように設定
sudo systemctl enable my-app
“`
これで、アプリケーションはバックグラウンドで安定して動作し続けます。
ステップ4: Nginxをリバースプロキシとして設定
現在、アプリケーションは特定のポート(例: 3000番)やUNIXソケットでリッスンしていますが、外部から直接アクセスさせるのは非効率的でセキュリティ上も好ましくありません。
そこで、WebサーバーであるNginxを「リバースプロキシ」としてアプリケーションの前に配置します。これにより、以下のようなメリットが得られます。
* SSL/TLS終端: HTTPSの暗号化・復号処理をNginxに任せられる。
* 静的ファイルの配信: 画像やCSSなどの静的ファイルを、アプリケーションサーバーを経由せずNginxが直接高速に配信できる。
* 負荷分散: 複数のアプリケーションサーバーにリクエストを振り分けることができる(将来的なスケールアップ)。
* セキュリティ: アプリケーションサーバーを直接インターネットに公開せずに済む。
4.1. Nginxのサイト設定ファイルを作成
ドメインごとに設定ファイルを作成するのが一般的です。
bash
sudo nano /etc/nginx/sites-available/my-app
このファイルに、リバースプロキシの設定を記述します。
“`nginx
server {
listen 80;
server_name your_domain.com www.your_domain.com;
# ログファイルの場所
access_log /var/log/nginx/my-app.access.log;
error_log /var/log/nginx/my-app.error.log;
# 静的ファイルの配信設定
location /static/ {
root /var/www/my-app/public;
expires 30d;
}
# それ以外のリクエストをアプリケーションに転送
location / {
proxy_pass http://localhost:3000; # Node.js (ポート3000) の場合
# proxy_pass http://unix:/var/www/my-app/my-app.sock; # Python/Gunicorn (UNIXソケット) の場合
# 必要なヘッダー情報
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
“`
listen 80;
: HTTP(ポート80)でリクエストを受け付けます。server_name
: この設定を適用するドメイン名を指定します。location /static/
:/static/
で始まるURLへのリクエストは、アプリケーションに送らず、Nginxが直接/var/www/my-app/public/static/
ディレクトリからファイルを返します。location /
: それ以外のすべてのリクエストをproxy_pass
で指定したアプリケーションサーバーに転送します。proxy_set_header
: アプリケーション側で、元のリクエスト情報を正しく認識できるようにヘッダーを追加します。これは非常に重要です。
4.2. 設定の有効化とNginxの再起動
作成した設定ファイルを有効にするため、sites-enabled
ディレクトリにシンボリックリンクを作成します。
“`bash
デフォルトの設定は不要なので削除
sudo rm /etc/nginx/sites-enabled/default
新しい設定ファイルのシンボリックリンクを作成
sudo ln -s /etc/nginx/sites-available/my-app /etc/nginx/sites-enabled/
Nginxの設定ファイルに構文エラーがないかテスト
sudo nginx -t
“`
syntax is ok
と表示されたら、設定を反映させるためにNginxを再起動します。
bash
sudo systemctl restart nginx
これで、ドメイン名へのHTTPリクエストがNginx経由でアプリケーションに届くようになりました。
ステップ5: ドメイン設定とSSL/TLS証明書の導入
最後の仕上げとして、独自ドメインをサーバーに向け、通信を暗号化するSSL/TLS証明書を導入してHTTPS化します。
5.1. ドメインとDNSの設定
まず、ドメインレジストラ(お名前.com, Google Domainsなど)でドメインを取得します。
次に、ドメインのDNS設定で、Aレコードを作成し、値にサーバーのIPアドレスを設定します。これにより、your_domain.com
というドメイン名が、あなたのサーバーを指すようになります。
Type: A
Name: your_domain.com (または @)
Value: YOUR_SERVER_IP
TTL: 3600 (任意)
wwwサブドメインも使いたい場合は、同様にwww
のAレコードも作成するか、CNAMEレコードでyour_domain.com
を指すように設定します。
DNSの変更がインターネット全体に反映される(伝播する)までには、数分から数時間かかる場合があります。
5.2. Let’s EncryptとCertbotによる無料SSL証明書の導入
Let’s Encryptは、無料でSSL/TLS証明書を発行してくれる認証局です。Certbotというツールを使うことで、証明書の取得、Nginxへの設定、そして定期的な自動更新をすべて自動で行うことができます。
Ubuntu 22.04では、snap
を使って最新版のCertbotをインストールするのが推奨されています。
“`bash
snapdが最新であることを確認
sudo snap install core; sudo snap refresh core
古いcertbot-autoやapt版があれば削除
sudo apt-get remove certbot
Certbotをインストール
sudo snap install –classic certbot
Certbotコマンドを使えるようにシンボリックリンクを作成
sudo ln -s /snap/bin/certbot /usr/bin/certbot
“`
準備が整ったら、以下のコマンド一発で証明書の取得と設定が完了します。
bash
sudo certbot --nginx
このコマンドを実行すると、CertbotはNginxの設定ファイルを解析し、server_name
に書かれたドメインを検出します。対話形式で以下のことを聞かれます。
- メールアドレスの入力(証明書の有効期限が近い場合などのお知らせ用)。
- 利用規約への同意。
- どのドメインに証明書を適用するか選択。
これらを選択すると、Certbotが証明書を取得し、Nginxの設定ファイル(/etc/nginx/sites-available/my-app
)を自動で書き換えて、HTTPSの設定を追加してくれます。さらに、HTTPでのアクセスをHTTPSに自動でリダイレクトする設定も追加してくれます。
5.3. 証明書の自動更新の確認
Let’s Encryptの証明書の有効期限は90日ですが、Certbotは自動で更新する仕組み(systemdタイマーやcronジョブ)をセットアップしてくれます。
以下のコマンドで、自動更新が問題なく動作するかをテストできます。
bash
sudo certbot renew --dry-run
“Congratulations, all simulated renewals succeeded.”と表示されれば、自動更新のセットアップは成功です。
最後に、Webブラウザで https://your_domain.com
にアクセスしてみてください。URLの横に鍵マークが表示され、サイトが安全に保護されていることが確認できれば、すべてのセットアップは完了です!
まとめと次のステップ
お疲れ様でした!これで、セキュリティが確保され、安定して動作するプロダクションサーバーの基本的なセットアップが完了しました。
今回行った5つのステップを振り返ってみましょう。
1. サーバーの初期設定とセキュリティ強化: sudoユーザー作成、SSHキー認証、ファイアウォール設定でサーバーの防御を固めました。
2. Webサーバーとデータベースのインストール: NginxとPostgreSQLを導入し、アプリケーションの土台を準備しました。
3. アプリケーションのデプロイと実行環境の構築: Gitでコードを配置し、PM2やsystemdでアプリケーションを永続化させました。
4. Nginxをリバースプロキシとして設定: Nginxをアプリケーションの前に配置し、パフォーマンスとセキュリティを向上させました。
5. ドメイン設定とSSL/TLS証明書の導入: Certbotで簡単にHTTPS化を実現し、信頼性を高めました。
この5つのステップは、多くのWebアプリケーションに適用可能な、汎用性の高い基盤となります。
しかし、プロダクション環境の運用はこれで終わりではありません。ここからが本当のスタートです。より安定したサービスを提供するために、次に検討すべきステップは以下の通りです。
- 監視: サーバーのリソース(CPU, メモリ, ディスク使用率)やアプリケーションのパフォーマンスを監視する仕組み(Prometheus, Grafana, Datadogなど)を導入する。
- ロギング: アプリケーションログやアクセスログを一元的に収集・分析する基盤(Fluentd, ELK Stack, Lokiなど)を構築する。
- バックアップ: データベースやユーザーがアップロードしたファイルなどを定期的にバックアップする戦略を立て、実行する。
- CI/CD (継続的インテグレーション/継続的デプロイメント): GitHub ActionsやGitLab CI/CDを使い、コードのプッシュからテスト、デプロイまでを自動化する。
サーバー運用は、一度構築したら終わりではなく、継続的な改善とメンテナンスが不可欠です。このガイドで得た知識を基盤として、あなたのアプリケーションと共に、より堅牢でスケーラブルなシステムへと成長させていってください。