Web Server Administration

Web サーバー管理 包括ガイド(Apache / Nginx)

目次

  1. はじめに
  2. Apache HTTP Server
  3. Nginx
  4. Apache vs Nginx 比較
  5. Let's Encrypt / certbot
  6. トラブルシューティング
  7. ベストプラクティス
  8. 参考資料

はじめに

Web サーバーは、インターネットインフラの根幹を担うソフトウェアである。Linux 環境では Apache HTTP ServerNginx が二大 Web サーバーとして君臨している。Apache は柔軟なモジュールシステムと .htaccess による分散設定で知られ、Nginx はイベント駆動アーキテクチャによる高い同時接続処理能力で評価されている。本記事では両方の Web サーバーについて、アーキテクチャから実践的な設定、セキュリティ、パフォーマンスチューニングまで包括的に解説する。


Apache HTTP Server

アーキテクチャと MPM

Apache は MPM(Multi-Processing Module) によって接続処理方式を切り替えられる。

MPM Prefork:
+------------------+
| Master Process   |
+--------+---------+
         |
    +----+----+----+----+
    |    |    |    |    |
   [P1] [P2] [P3] [P4] [P5]   ← 各プロセスが1リクエストを処理
    |    |    |    |    |
   1req 1req 1req 1req 1req

MPM Worker:
+------------------+
| Master Process   |
+--------+---------+
         |
    +----+----+
    |         |
   [P1]     [P2]        ← 子プロセス
    |         |
  +--+--+   +--+--+
  |  |  |   |  |  |     ← 各プロセス内のスレッド
 [T][T][T] [T][T][T]

MPM Event:
+------------------+
| Master Process   |
+--------+---------+
         |
    +----+----+
    |         |
   [P1]     [P2]        ← 子プロセス
    |         |
  +--+--+   +--+--+
  |  |  |   |  |  |     ← ワーカースレッド
 [T][T][T] [T][T][T]
    +              
  [Listener Thread]      ← Keep-Alive接続を非同期管理

MPM 比較表:

特徴PreforkWorkerEvent
処理モデルプロセスベーススレッドベースイベント駆動+スレッド
メモリ使用量高い中程度低い
同時接続数低い中程度高い
スレッドセーフ不要はいいいえいいえ
Keep-Alive 処理プロセス占有スレッド占有非同期(効率的)
PHP mod_php 互換はいいいえいいえ
推奨用途レガシー/mod_php一般用途高負荷環境(推奨)

Apache インストールとディレクトリ構造

# RHEL/CentOS/Rocky Linux
sudo dnf install httpd mod_ssl
sudo systemctl enable --now httpd

# Debian/Ubuntu
sudo apt install apache2
sudo systemctl enable --now apache2

# バージョン確認
httpd -v    # RHEL系
apache2 -v  # Debian系
出力例:
Server version: Apache/2.4.57 (Rocky Linux)
Server built:   Jun 15 2025 00:00:00

ディレクトリ構造:

パス(RHEL系)パス(Debian系)説明
/etc/httpd/conf/httpd.conf/etc/apache2/apache2.confメイン設定ファイル
/etc/httpd/conf.d//etc/apache2/conf-available/追加設定ディレクトリ
/etc/httpd/conf.modules.d//etc/apache2/mods-available/モジュール設定
/var/www/html//var/www/html/デフォルトドキュメントルート
/var/log/httpd//var/log/apache2/ログディレクトリ
/etc/httpd/conf.d/ssl.conf/etc/apache2/sites-available/default-ssl.confSSL設定

httpd.conf 基本設定

# /etc/httpd/conf/httpd.conf (RHEL系の例)

# === サーバー基本設定 ===
ServerRoot "/etc/httpd"
Listen 80
ServerAdmin admin@example.com
ServerName www.example.com:80

# === MPM Event 設定 ===
# /etc/httpd/conf.modules.d/00-mpm.conf
LoadModule mpm_event_module modules/mod_mpm_event.so
# LoadModule mpm_prefork_module modules/mod_mpm_prefork.so  # 無効
# LoadModule mpm_worker_module modules/mod_mpm_worker.so    # 無効

<IfModule mpm_event_module>
    StartServers             4
    MinSpareThreads         75
    MaxSpareThreads        250
    ThreadsPerChild         25
    MaxRequestWorkers      400
    MaxConnectionsPerChild   0
    AsyncRequestWorkerFactor  2
</IfModule>

# === ドキュメントルート ===
DocumentRoot "/var/www/html"

<Directory "/var/www/html">
    Options -Indexes +FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

# === セキュリティヘッダー ===
ServerTokens Prod
ServerSignature Off
TraceEnable Off

Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-XSS-Protection "1; mode=block"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"

# === タイムアウト設定 ===
Timeout 60
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

# === MIME タイプ ===
TypesConfig /etc/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz

# === ログ設定 ===
ErrorLog "logs/error_log"
LogLevel warn

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
CustomLog "logs/access_log" combined

# === 追加設定の読み込み ===
IncludeOptional conf.d/*.conf

VirtualHost 設定

# /etc/httpd/conf.d/example.com.conf

# === HTTP VirtualHost (HTTPSへリダイレクト) ===
<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    
    # HTTPSへリダイレクト
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>

# === HTTPS VirtualHost ===
<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    ServerAdmin admin@example.com
    DocumentRoot /var/www/example.com/public_html
    
    # SSL設定
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    
    # ディレクトリ設定
    <Directory /var/www/example.com/public_html>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    
    # ログ
    ErrorLog /var/log/httpd/example.com-error.log
    CustomLog /var/log/httpd/example.com-access.log combined
    
    # カスタムエラーページ
    ErrorDocument 404 /errors/404.html
    ErrorDocument 500 /errors/500.html
</VirtualHost>

# === 名前ベースの仮想ホスト(複数サイト) ===
<VirtualHost *:443>
    ServerName app.example.com
    DocumentRoot /var/www/app.example.com/public_html
    
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/app.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/app.example.com/privkey.pem
    
    # リバースプロキシ(バックエンドアプリ)
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:3000/
    ProxyPassReverse / http://127.0.0.1:3000/
    
    <Directory /var/www/app.example.com/public_html>
        Require all granted
    </Directory>
</VirtualHost>

# === IP ベースの仮想ホスト ===
<VirtualHost 192.168.1.10:443>
    ServerName internal.example.com
    DocumentRoot /var/www/internal
    
    SSLEngine on
    SSLCertificateFile /etc/pki/tls/certs/internal.pem
    SSLCertificateKeyFile /etc/pki/tls/private/internal.key
    
    <Directory /var/www/internal>
        Require ip 192.168.1.0/24
    </Directory>
</VirtualHost>
# 設定テスト
httpd -t        # RHEL系
apache2ctl -t   # Debian系

# VirtualHost 一覧
httpd -S
出力例:
VirtualHost configuration:
*:80                   is a NameVirtualHost
         default server example.com (/etc/httpd/conf.d/example.com.conf:1)
         port 80 namevhost example.com (/etc/httpd/conf.d/example.com.conf:1)
                 alias www.example.com
*:443                  is a NameVirtualHost
         default server example.com (/etc/httpd/conf.d/example.com.conf:10)
         port 443 namevhost example.com (/etc/httpd/conf.d/example.com.conf:10)
         port 443 namevhost app.example.com (/etc/httpd/conf.d/example.com.conf:35)

モジュール管理

# === RHEL系 ===
# ロード済みモジュールの一覧
httpd -M
出力例:
Loaded Modules:
 core_module (static)
 so_module (static)
 http_module (static)
 mpm_event_module (shared)
 authz_core_module (shared)
 log_config_module (shared)
 ssl_module (shared)
 rewrite_module (shared)
 proxy_module (shared)
 proxy_http_module (shared)
 headers_module (shared)
 deflate_module (shared)
 ...
# モジュールの追加インストール
sudo dnf install mod_ssl mod_security mod_fcgid

# モジュール設定ファイル
ls /etc/httpd/conf.modules.d/
# 00-base.conf  00-mpm.conf  00-ssl.conf  01-cgi.conf  ...

# === Debian系 ===
# モジュールの有効化/無効化
sudo a2enmod ssl rewrite proxy proxy_http headers
sudo a2dismod autoindex
sudo systemctl restart apache2

# 有効なモジュール一覧
apache2ctl -M

.htaccess

# /var/www/example.com/public_html/.htaccess

# === URL リライト ===
RewriteEngine On

# www あり → www なしへリダイレクト
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]

# クリーンURL(拡張子を隠す)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.html -f
RewriteRule ^(.*)$ $1.html [L]

# === アクセス制御 ===
# 特定IPのみアクセス許可
<RequireAll>
    Require ip 192.168.1.0/24
    Require ip 10.0.0.0/8
</RequireAll>

# 特定ファイルへのアクセス拒否
<FilesMatch "\.(env|htpasswd|htaccess|git|svn)">
    Require all denied
</FilesMatch>

# === キャッシュ制御 ===
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
    ExpiresByType text/html "access plus 1 hour"
</IfModule>

# === 圧縮 ===
<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/css
    AddOutputFilterByType DEFLATE application/javascript application/json
    AddOutputFilterByType DEFLATE application/xml text/xml
</IfModule>

# === セキュリティヘッダー ===
Header set X-Content-Type-Options "nosniff"
Header set X-Frame-Options "DENY"

# === カスタムエラーページ ===
ErrorDocument 404 /errors/404.html
ErrorDocument 403 /errors/403.html
ErrorDocument 500 /errors/500.html

mod_ssl / TLS 設定

# /etc/httpd/conf.d/ssl.conf

Listen 443 https

SSLPassPhraseDialog     exec:/usr/libexec/httpd-ssl-pass-dialog
SSLSessionCache         shmcb:/run/httpd/sslcache(512000)
SSLSessionCacheTimeout  300
SSLRandomSeed startup file:/dev/urandom  256
SSLRandomSeed connect builtin

# === 推奨 TLS 設定(Mozilla Modern 準拠) ===
SSLProtocol             all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite          ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder     off
SSLSessionTickets       off

# OCSP Stapling
SSLUseStapling On
SSLStaplingCache "shmcb:logs/ssl_stapling(32768)"
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off

# HSTS
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"

mod_rewrite

# === mod_rewrite 設定例 ===

# HTTPSへの強制リダイレクト
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# メンテナンスモード
RewriteEngine On
RewriteCond %{REMOTE_ADDR} !^192\.168\.1\.100$
RewriteCond %{REQUEST_URI} !^/maintenance\.html$
RewriteRule ^(.*)$ /maintenance.html [R=503,L]

# API バージョニング
RewriteEngine On
RewriteRule ^/api/v([0-9]+)/(.*)$ /api/index.php?version=$1&path=$2 [L,QSA]

# ボットブロック
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} (BadBot|EvilScraper|SpamBot) [NC]
RewriteRule .* - [F,L]

# トレーリングスラッシュの追加
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(.*)/$
RewriteRule ^(.*)$ $1/ [L,R=301]

mod_proxy

# === リバースプロキシ設定 ===

# 基本的なリバースプロキシ
<VirtualHost *:443>
    ServerName app.example.com
    
    SSLEngine on
    SSLCertificateFile /etc/letsencrypt/live/app.example.com/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/app.example.com/privkey.pem
    
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/
    
    # プロキシヘッダー
    RequestHeader set X-Forwarded-Proto "https"
    RequestHeader set X-Forwarded-Port "443"
</VirtualHost>

# === ロードバランサー ===
<Proxy "balancer://appcluster">
    BalancerMember http://192.168.1.11:8080 loadfactor=1
    BalancerMember http://192.168.1.12:8080 loadfactor=1
    BalancerMember http://192.168.1.13:8080 loadfactor=1 status=+H
    ProxySet lbmethod=byrequests
    # lbmethod: byrequests, bytraffic, bybusyness, heartbeat
</Proxy>

<VirtualHost *:443>
    ServerName app.example.com
    
    ProxyPreserveHost On
    ProxyPass / balancer://appcluster/
    ProxyPassReverse / balancer://appcluster/
    
    # ヘルスチェック
    ProxyHCExpr ok234 {%{REQUEST_STATUS} =~ /^[234]/}
    ProxyPass / balancer://appcluster/ hcmethod=GET hcexpr=ok234 hcuri=/health
</VirtualHost>

# === WebSocket プロキシ ===
<VirtualHost *:443>
    ServerName ws.example.com
    
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} websocket [NC]
    RewriteCond %{HTTP:Connection} upgrade [NC]
    RewriteRule ^/?(.*) "ws://127.0.0.1:8080/$1" [P,L]
    
    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/
</VirtualHost>

Apache 認証設定

# === Basic 認証 ===
<Directory /var/www/example.com/admin>
    AuthType Basic
    AuthName "Admin Area"
    AuthUserFile /etc/httpd/.htpasswd
    Require valid-user
</Directory>

# === Digest 認証 ===
<Directory /var/www/example.com/secure>
    AuthType Digest
    AuthName "secure"
    AuthDigestProvider file
    AuthUserFile /etc/httpd/.htdigest
    Require valid-user
</Directory>
# パスワードファイルの作成
htpasswd -c /etc/httpd/.htpasswd admin     # 新規作成
htpasswd /etc/httpd/.htpasswd user1        # ユーザー追加

# Digest認証用
htdigest -c /etc/httpd/.htdigest "secure" admin

Apache ログ設定

# === カスタムログフォーマット ===

# 標準 combined フォーマット
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

# JSON フォーマット
LogFormat "{\"time\":\"%{%Y-%m-%dT%H:%M:%S%z}t\",\"remote_ip\":\"%a\",\"method\":\"%m\",\"uri\":\"%U\",\"query\":\"%q\",\"status\":%>s,\"bytes\":%B,\"referer\":\"%{Referer}i\",\"user_agent\":\"%{User-Agent}i\",\"response_time\":%D}" json_log

CustomLog "logs/access_log" json_log

# 条件付きログ(画像リクエストを除外)
SetEnvIf Request_URI "\.(gif|jpg|png|css|js|ico)$" no_log
CustomLog "logs/access_log" combined env=!no_log

# ログローテーション(rotatelogs使用)
CustomLog "|/usr/sbin/rotatelogs /var/log/httpd/access_log.%Y%m%d 86400" combined
ErrorLog "|/usr/sbin/rotatelogs /var/log/httpd/error_log.%Y%m%d 86400"

Apache パフォーマンスチューニング

# === MPM Event チューニング ===
<IfModule mpm_event_module>
    ServerLimit           16
    StartServers           4
    MinSpareThreads       75
    MaxSpareThreads      250
    ThreadLimit           64
    ThreadsPerChild       25
    MaxRequestWorkers    400
    MaxConnectionsPerChild 10000
    AsyncRequestWorkerFactor 2
</IfModule>

# === 圧縮 ===
<IfModule mod_deflate.c>
    SetOutputFilter DEFLATE
    DeflateCompressionLevel 6
    AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css
    AddOutputFilterByType DEFLATE application/javascript application/json
    AddOutputFilterByType DEFLATE application/xml application/xhtml+xml
    # 除外(既に圧縮済みのファイル)
    SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|zip|gz|bz2)$ no-gzip
</IfModule>

# === ファイルキャッシュ ===
<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault "access plus 1 month"
    ExpiresByType text/html "access plus 1 hour"
    ExpiresByType text/css "access plus 1 year"
    ExpiresByType application/javascript "access plus 1 year"
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/webp "access plus 1 year"
    ExpiresByType font/woff2 "access plus 1 year"
</IfModule>

# === ETag の無効化(CDN利用時) ===
FileETag None

# === KeepAlive チューニング ===
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

# === DNS ルックアップの無効化 ===
HostnameLookups Off

# === 不要モジュールの無効化 ===
# /etc/httpd/conf.modules.d/00-base.conf で不要なモジュールをコメントアウト

Nginx

Nginx アーキテクチャ

Nginx はイベント駆動(非同期/ノンブロッキング)アーキテクチャを採用しており、少ないリソースで多数の同時接続を効率的に処理できる。

Nginx アーキテクチャ:

+------------------+
| Master Process   |  ← 設定読み込み、ポートバインド、ワーカー管理
| (root)           |
+--------+---------+
         |
    +----+----+----+----+
    |    |    |    |    |
   [W1] [W2] [W3] [W4]        ← Worker Processes(CPUコア数分)
    |    |    |    |            各ワーカーがイベントループで
    |    |    |    |            数千の同時接続を処理
    E    E    E    E    
    v    v    v    v    
    e    e    e    e    
    n    n    n    n            E = epoll/kqueue イベントループ
    t    t    t    t    
         |
    +----+----+
    | Cache   |                ← Cache Manager / Cache Loader
    | Process |
    +---------+

接続処理の流れ:
1. Master がポートをリッスン
2. Worker が accept() で接続を受け付け
3. イベントループ(epoll/kqueue)で非同期処理
4. 1つの Worker で数千の同時接続を処理

Nginx インストールとディレクトリ構造

# RHEL/CentOS/Rocky Linux(公式リポジトリ)
sudo dnf install nginx
sudo systemctl enable --now nginx

# Debian/Ubuntu
sudo apt install nginx
sudo systemctl enable --now nginx

# バージョン確認
nginx -v
nginx -V    # コンパイルオプション含む
出力例:
nginx version: nginx/1.26.1
built by gcc 11.4.1 (Rocky Linux 11.4.1-2)
built with OpenSSL 3.0.7
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx
  --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf
  --with-http_ssl_module --with-http_v2_module --with-http_realip_module
  --with-http_gzip_static_module --with-http_stub_status_module
  --with-stream --with-stream_ssl_module ...

ディレクトリ構造:

パス説明
/etc/nginx/nginx.confメイン設定ファイル
/etc/nginx/conf.d/追加設定(*.conf を自動読み込み)
/etc/nginx/sites-available/仮想ホスト定義(Debian系)
/etc/nginx/sites-enabled/有効な仮想ホスト(symlink)
/etc/nginx/mime.typesMIME タイプ定義
/var/www/html/デフォルトドキュメントルート
/var/log/nginx/ログディレクトリ
/var/cache/nginx/キャッシュディレクトリ

nginx.conf 基本設定

# /etc/nginx/nginx.conf

# ワーカープロセス数(auto = CPUコア数)
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;

# ワーカーのCPUアフィニティ(任意)
# worker_cpu_affinity auto;

events {
    worker_connections 4096;
    multi_accept on;
    use epoll;    # Linux(kqueue は BSD/macOS)
}

http {
    # === 基本設定 ===
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    charset utf-8;

    # === ログフォーマット ===
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    '$request_time $upstream_response_time';

    log_format json escape=json '{'
        '"time":"$time_iso8601",'
        '"remote_addr":"$remote_addr",'
        '"method":"$request_method",'
        '"uri":"$request_uri",'
        '"status":$status,'
        '"body_bytes_sent":$body_bytes_sent,'
        '"request_time":$request_time,'
        '"upstream_response_time":"$upstream_response_time",'
        '"http_referer":"$http_referer",'
        '"http_user_agent":"$http_user_agent"'
    '}';

    access_log /var/log/nginx/access.log main;

    # === パフォーマンス設定 ===
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 1000;
    types_hash_max_size 2048;
    server_tokens off;
    client_max_body_size 100M;

    # === バッファ設定 ===
    client_body_buffer_size 16k;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;

    # === Gzip 圧縮 ===
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_min_length 1024;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/json
        application/javascript
        application/xml
        application/xml+rss
        application/atom+xml
        image/svg+xml;

    # === セキュリティヘッダー ===
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # === SSL 共通設定 ===
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 1d;
    ssl_session_tickets off;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 5s;

    # === 追加設定の読み込み ===
    include /etc/nginx/conf.d/*.conf;
}

Server Blocks

# /etc/nginx/conf.d/example.com.conf

# === HTTP → HTTPS リダイレクト ===
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    
    # ACME チャレンジ用(Let's Encrypt)
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
    
    location / {
        return 301 https://$host$request_uri;
    }
}

# === メインサイト(HTTPS) ===
server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;
    
    root /var/www/example.com/public_html;
    index index.html index.htm;
    
    # SSL 証明書
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # HSTS
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
    
    # www → non-www リダイレクト
    if ($host = www.example.com) {
        return 301 https://example.com$request_uri;
    }
    
    # ログ
    access_log /var/log/nginx/example.com-access.log main;
    error_log /var/log/nginx/example.com-error.log warn;
    
    # エラーページ
    error_page 404 /errors/404.html;
    error_page 500 502 503 504 /errors/50x.html;
    
    location /errors/ {
        internal;
        root /var/www/example.com;
    }
    
    # 静的ファイルの配信
    location ~* \.(jpg|jpeg|gif|png|webp|svg|ico|css|js|woff2|ttf)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }
    
    # .ht* ファイルへのアクセス拒否
    location ~ /\.ht {
        deny all;
    }
    
    # 隠しファイルへのアクセス拒否
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
}

Location Blocks

# === Location ブロックの優先順位 ===
# 1. = (完全一致)           最高優先度
# 2. ^~ (前方一致・正規表現より優先)
# 3. ~ (正規表現・大文字小文字区別)
# 4. ~* (正規表現・大文字小文字無視)
# 5. / (プレフィックス一致)   最低優先度

server {
    # 完全一致 - / のみにマッチ
    location = / {
        return 200 "Welcome to the homepage\n";
    }
    
    # 完全一致 - /health のみ
    location = /health {
        access_log off;
        return 200 "OK\n";
        add_header Content-Type text/plain;
    }
    
    # 前方一致(正規表現より優先)
    location ^~ /static/ {
        root /var/www/example.com;
        expires 30d;
        access_log off;
    }
    
    # 正規表現(大文字小文字無視)
    location ~* \.(jpg|jpeg|gif|png|webp|svg|ico)$ {
        root /var/www/example.com/images;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    # 正規表現(大文字小文字区別)
    location ~ ^/api/v[0-9]+/ {
        proxy_pass http://api_backend;
    }
    
    # プレフィックス一致
    location /docs/ {
        alias /var/www/documentation/;
        index index.html;
    }
    
    # プレフィックス一致(その他すべて)
    location / {
        try_files $uri $uri/ =404;
    }
}

Nginx リバースプロキシ

# === 基本的なリバースプロキシ ===
server {
    listen 443 ssl http2;
    server_name app.example.com;
    
    ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem;
    
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        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;
        proxy_set_header X-Forwarded-Port $server_port;
        
        # タイムアウト
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
        
        # バッファ
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
    }
    
    # WebSocket プロキシ
    location /ws/ {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 86400;
    }
}

ロードバランシング

# === アップストリーム定義 ===

# ラウンドロビン(デフォルト)
upstream app_backend {
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
    server 192.168.1.13:8080;
}

# 重み付きラウンドロビン
upstream app_weighted {
    server 192.168.1.11:8080 weight=5;
    server 192.168.1.12:8080 weight=3;
    server 192.168.1.13:8080 weight=1;
}

# IP ハッシュ(セッション固定)
upstream app_iphash {
    ip_hash;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
    server 192.168.1.13:8080;
}

# 最小接続数
upstream app_least_conn {
    least_conn;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
    server 192.168.1.13:8080;
}

# ヘルスチェック付き
upstream app_health {
    server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.12:8080 max_fails=3 fail_timeout=30s;
    server 192.168.1.13:8080 backup;    # バックアップサーバー
    # server 192.168.1.14:8080 down;    # 手動で無効化
    
    keepalive 32;    # アップストリームへのKeep-Alive接続数
}

server {
    listen 443 ssl http2;
    server_name app.example.com;
    
    location / {
        proxy_pass http://app_health;
        proxy_http_version 1.1;
        proxy_set_header Connection "";    # keepalive用
        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_next_upstream error timeout http_500 http_502 http_503;
        proxy_next_upstream_tries 3;
    }
}

Nginx SSL/TLS 設定

# /etc/nginx/conf.d/ssl-params.conf
# Mozilla SSL Configuration Generator 準拠

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

# セッション設定
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;

# DH パラメータ
ssl_dhparam /etc/nginx/ssl/dhparam.pem;

# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

# HSTS
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# DH パラメータの生成
sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048

# SSL 設定のテスト
nginx -t

キャッシング

# === プロキシキャッシュ設定 ===

# nginx.conf の http ブロック内
proxy_cache_path /var/cache/nginx/proxy
    levels=1:2
    keys_zone=proxy_cache:10m
    max_size=10g
    inactive=60m
    use_temp_path=off;

# FastCGI キャッシュ
fastcgi_cache_path /var/cache/nginx/fastcgi
    levels=1:2
    keys_zone=fcgi_cache:10m
    max_size=5g
    inactive=60m;

server {
    # プロキシキャッシュの使用
    location / {
        proxy_pass http://app_backend;
        proxy_cache proxy_cache;
        proxy_cache_key "$scheme$request_method$host$request_uri";
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 404 1m;
        proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
        proxy_cache_background_update on;
        proxy_cache_lock on;
        
        # キャッシュステータスヘッダー
        add_header X-Cache-Status $upstream_cache_status;
    }
    
    # キャッシュをバイパスする条件
    location /api/ {
        proxy_pass http://app_backend;
        proxy_cache proxy_cache;
        proxy_cache_bypass $http_cache_control $cookie_nocache;
        proxy_no_cache $http_pragma $http_authorization;
    }
    
    # 静的ファイルのブラウザキャッシュ
    location ~* \.(css|js)$ {
        root /var/www/example.com;
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    # キャッシュパージ(要 ngx_cache_purge モジュール)
    location ~ /purge(/.*) {
        allow 127.0.0.1;
        allow 192.168.1.0/24;
        deny all;
        proxy_cache_purge proxy_cache "$scheme$request_method$host$1";
    }
}

レート制限

# nginx.conf の http ブロック内

# リクエストレート制限ゾーンの定義
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/s;
limit_req_zone $server_name zone=per_server:10m rate=100r/s;

# 接続数制限ゾーンの定義
limit_conn_zone $binary_remote_addr zone=addr:10m;

# レート制限のステータスコード
limit_req_status 429;
limit_conn_status 429;

server {
    # 一般的なレート制限
    location / {
        limit_req zone=general burst=20 nodelay;
        limit_conn addr 10;
        proxy_pass http://app_backend;
    }
    
    # ログイン・認証エンドポイント(厳格なレート制限)
    location /login {
        limit_req zone=login burst=5 nodelay;
        proxy_pass http://app_backend;
    }
    
    # API エンドポイント
    location /api/ {
        limit_req zone=api burst=50 nodelay;
        limit_conn addr 20;
        proxy_pass http://app_backend;
    }
    
    # レート制限のカスタムエラーページ
    error_page 429 /429.html;
    location = /429.html {
        internal;
        return 429 '{"error": "Rate limit exceeded. Please retry later."}';
        add_header Content-Type application/json;
    }
}

FastCGI / PHP-FPM

# === PHP-FPM 連携設定 ===

# /etc/nginx/conf.d/php-site.conf
server {
    listen 443 ssl http2;
    server_name php.example.com;
    root /var/www/php.example.com;
    index index.php index.html;
    
    ssl_certificate /etc/letsencrypt/live/php.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/php.example.com/privkey.pem;
    
    # PHP ファイルの処理
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass unix:/run/php-fpm/www.sock;
        # fastcgi_pass 127.0.0.1:9000;    # TCP接続の場合
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        
        # FastCGI バッファ
        fastcgi_buffer_size 32k;
        fastcgi_buffers 8 16k;
        fastcgi_busy_buffers_size 32k;
        
        # タイムアウト
        fastcgi_connect_timeout 60s;
        fastcgi_send_timeout 60s;
        fastcgi_read_timeout 60s;
        
        # FastCGI キャッシュ
        fastcgi_cache fcgi_cache;
        fastcgi_cache_valid 200 10m;
        fastcgi_cache_key "$scheme$request_method$host$request_uri";
        fastcgi_cache_bypass $cookie_nocache $arg_nocache;
        add_header X-FastCGI-Cache $upstream_cache_status;
    }
    
    # WordPress 用 URL リライト
    location / {
        try_files $uri $uri/ /index.php?$args;
    }
    
    # wp-admin の保護
    location /wp-admin/ {
        allow 192.168.1.0/24;
        deny all;
        try_files $uri $uri/ /index.php?$args;
    }
    
    # アップロードディレクトリでの PHP 実行禁止
    location ~* /uploads/.*\.php$ {
        deny all;
    }
}
# PHP-FPM の設定
cat /etc/php-fpm.d/www.conf
[www]
user = nginx
group = nginx
listen = /run/php-fpm/www.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660

pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
pm.max_requests = 500

; スロウログ
slowlog = /var/log/php-fpm/www-slow.log
request_slowlog_timeout = 5s

; ステータスページ
pm.status_path = /fpm-status
ping.path = /fpm-ping

HTTP/2 設定

server {
    # HTTP/2 を有効化(SSL 必須)
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com;
    
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    
    # HTTP/2 サーバープッシュ(非推奨化の流れ)
    # http2_push /css/style.css;
    # http2_push /js/app.js;
    # http2_push_preload on;
    
    # HTTP/2 固有の設定
    http2_max_concurrent_streams 128;
    
    root /var/www/example.com;
    
    location / {
        try_files $uri $uri/ =404;
    }
}

Nginx パフォーマンスチューニング

# === nginx.conf パフォーマンス最適化 ===

user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
pid /run/nginx.pid;

events {
    worker_connections 8192;
    multi_accept on;
    use epoll;
}

http {
    # === ファイル送信の最適化 ===
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    
    # === タイムアウト ===
    keepalive_timeout 65;
    keepalive_requests 1000;
    client_body_timeout 12;
    client_header_timeout 12;
    send_timeout 10;
    reset_timedout_connection on;
    
    # === バッファ ===
    client_body_buffer_size 16k;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;
    client_max_body_size 100M;
    
    # === open_file_cache ===
    open_file_cache max=200000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;
    
    # === Gzip 圧縮 ===
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types
        text/plain text/css text/xml text/javascript
        application/json application/javascript application/xml
        application/rss+xml application/atom+xml
        image/svg+xml font/woff2;
    
    # === Brotli 圧縮(モジュール必要) ===
    # brotli on;
    # brotli_comp_level 6;
    # brotli_types text/plain text/css text/xml text/javascript
    #     application/json application/javascript application/xml;
    
    # === ログ最適化 ===
    access_log /var/log/nginx/access.log main buffer=16k flush=2m;
    # access_log off;    # 静的ファイルのログ無効化
}
# カーネルパラメータのチューニング
# /etc/sysctl.d/99-nginx-tuning.conf

net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

# 適用
sudo sysctl -p /etc/sysctl.d/99-nginx-tuning.conf

# ファイルディスクリプタの上限
# /etc/security/limits.d/nginx.conf
# nginx   soft    nofile  65535
# nginx   hard    nofile  65535

Apache vs Nginx 比較

項目ApacheNginx
アーキテクチャプロセス/スレッドベース(MPM)イベント駆動(非同期)
同時接続処理中程度(MPM依存)非常に高い
メモリ使用量高い(接続あたり)低い
静的コンテンツ良好非常に優れている
動的コンテンツmod_php で直接処理可能FastCGI/PHP-FPM が必要
設定の柔軟性.htaccess で分散設定可能集中設定のみ
モジュールシステム動的ロード/アンロードコンパイル時に組み込み(動的モジュールも可)
リバースプロキシmod_proxy(機能的)ネイティブ(非常に優れている)
ロードバランシングmod_proxy_balancerネイティブ(高機能)
URL リライトmod_rewrite(強力)rewrite ディレクティブ
ドキュメント非常に豊富豊富
OS サポートLinux, Windows, macOSLinux, BSD, macOS(Windows は制限あり)
設定リロードgraceful restartシームレスリロード
市場シェア(2026)約 30%約 35%
推奨用途共有ホスティング、.htaccess必要時リバースプロキシ、高負荷環境、API ゲートウェイ

パフォーマンス比較

同時接続数 vs メモリ使用量(概念図):

メモリ
使用量 ^
      |
      |    Apache (Prefork)  /
      |                     /
      |   Apache (Event)   /
      |                   /
      |             /----/
      |            /
      |    Nginx  /
      |  --------/
      +-------------------------> 同時接続数

レスポンスタイム(静的ファイル配信):

リクエスト/秒 ^
              |   Nginx
              |   ████████████████████████
              |
              |   Apache (Event)
              |   ███████████████████
              |
              |   Apache (Prefork)
              |   ████████████████
              +

Let's Encrypt / certbot

certbot のインストールと証明書取得

# certbot のインストール
# RHEL/CentOS/Rocky Linux
sudo dnf install epel-release
sudo dnf install certbot python3-certbot-nginx python3-certbot-apache

# Debian/Ubuntu
sudo apt install certbot python3-certbot-nginx python3-certbot-apache

# === Nginx 用 ===
# 自動設定(Nginx設定を自動変更)
sudo certbot --nginx -d example.com -d www.example.com

# 証明書のみ取得(設定は手動)
sudo certbot certonly --nginx -d example.com -d www.example.com

# === Apache 用 ===
sudo certbot --apache -d example.com -d www.example.com

# === スタンドアロンモード(サーバー停止が必要) ===
sudo certbot certonly --standalone -d example.com

# === Webroot モード(サーバー実行中に取得) ===
sudo certbot certonly --webroot -w /var/www/example.com -d example.com -d www.example.com
出力例:
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for example.com and www.example.com

Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at:         /etc/letsencrypt/live/example.com/privkey.pem
This certificate expires on 2026-07-09.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.

証明書の管理と自動更新

# 証明書一覧
sudo certbot certificates
出力例:
Found the following certs:
  Certificate Name: example.com
    Serial Number: 03a1b2c3d4e5f6
    Key Type: ECDSA
    Domains: example.com www.example.com
    Expiry Date: 2026-07-09 (VALID: 89 days)
    Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
    Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem
# 手動更新テスト(ドライラン)
sudo certbot renew --dry-run

# 手動更新
sudo certbot renew

# 特定の証明書のみ更新
sudo certbot renew --cert-name example.com

# 自動更新タイマーの確認
sudo systemctl list-timers | grep certbot

# 更新後のフック(Webサーバー再読み込み)
# /etc/letsencrypt/renewal/example.com.conf に追加
# [renewalparams]
# renew_hook = systemctl reload nginx

# または certbot コマンドで指定
sudo certbot renew --deploy-hook "systemctl reload nginx"

# ワイルドカード証明書(DNS チャレンジ必要)
sudo certbot certonly --manual --preferred-challenges dns \
    -d "*.example.com" -d example.com

# 証明書の削除
sudo certbot delete --cert-name example.com

トラブルシューティング

Apache トラブルシューティング

# 設定テスト
httpd -t
apachectl configtest

# 詳細なエラー表示
httpd -t -D DUMP_VHOSTS    # VirtualHost一覧
httpd -t -D DUMP_MODULES   # ロード済みモジュール
httpd -t -D DUMP_RUN_CFG   # ランタイム設定

# ログの確認
sudo tail -f /var/log/httpd/error_log
sudo tail -f /var/log/httpd/access_log

# プロセス確認
ps aux | grep httpd
pstree -p $(pidof httpd | awk '{print $1}')

# ポート確認
sudo ss -tlnp | grep :80
sudo ss -tlnp | grep :443

# mod_status による状態監視
# httpd.conf に追加:
# <Location /server-status>
#     SetHandler server-status
#     Require ip 127.0.0.1
# </Location>
curl http://localhost/server-status?auto
出力例(server-status):
Total Accesses: 125678
Total kBytes: 456789
CPULoad: .234567
Uptime: 86400
ReqPerSec: 1.456
BytesPerSec: 5432.1
BytesPerReq: 3729.12
BusyWorkers: 12
IdleWorkers: 388
Scoreboard: ____W___W__W__W_...
# SELinux 問題の確認
sudo ausearch -m AVC -ts recent | grep httpd
sudo setsebool -P httpd_can_network_connect on
sudo setsebool -P httpd_can_network_relay on

Nginx トラブルシューティング

# 設定テスト
nginx -t
nginx -T    # 全設定を出力

# ログの確認
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/nginx/access.log

# プロセス確認
ps aux | grep nginx

# stub_status による状態監視
# nginx.conf に追加:
# location /nginx_status {
#     stub_status;
#     allow 127.0.0.1;
#     deny all;
# }
curl http://localhost/nginx_status
出力例:
Active connections: 156
server accepts handled requests
 234567 234567 890123
Reading: 4 Writing: 12 Waiting: 140
# 設定のリロード(ダウンタイムなし)
sudo nginx -s reload

# ワーカープロセスのグレースフルシャットダウン
sudo nginx -s quit

# アップストリームの接続テスト
curl -v http://127.0.0.1:8080/health

# SSL 証明書の確認
openssl s_client -connect example.com:443 -servername example.com < /dev/null 2>/dev/null | openssl x509 -text -noout

# SSL テスト
openssl s_client -connect example.com:443 -tls1_2
openssl s_client -connect example.com:443 -tls1_3

# ベンチマーク
# ab(Apache Bench)
ab -n 10000 -c 100 https://example.com/

# wrk
wrk -t4 -c400 -d30s https://example.com/
出力例(wrk):
Running 30s test @ https://example.com/
  4 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    12.34ms   5.67ms  234.56ms   78.90%
    Req/Sec     8.12k     1.23k   12.34k    67.89%
  972345 requests in 30.00s, 1.23GB read
Requests/sec:  32411.50
Transfer/sec:     42.00MB

ベストプラクティス

共通ベストプラクティス

  1. TLS 1.2/1.3 のみを有効化: SSLv3, TLS 1.0, 1.1 を無効化する
  2. HSTS を設定する: Strict-Transport-Security ヘッダーを追加
  3. セキュリティヘッダーを追加する: X-Content-Type-Options, X-Frame-Options, CSP 等
  4. サーバーバージョンを隠す: Apache は ServerTokens Prod、Nginx は server_tokens off
  5. Let's Encrypt で無料 SSL 証明書を使用する: 自動更新を設定
  6. アクセスログと監視を設定する: 異常なトラフィックパターンを検出
  7. レート制限を実装する: ブルートフォース攻撃やDDoSを軽減
  8. Gzip/Brotli 圧縮を有効化する: 帯域幅を節約
  9. 静的ファイルにキャッシュヘッダーを設定する: ブラウザキャッシュを活用
  10. 定期的に設定を監査する: SSL Labs や Mozilla Observatory でテスト

Apache 固有のベストプラクティス

  1. MPM Event を使用する: Prefork より効率的
  2. .htaccess の使用を最小限にする: パフォーマンスに影響するため、可能なら VirtualHost に記述
  3. 不要なモジュールを無効化する: 攻撃面を減らす
  4. AllowOverride を適切に設定する: None から必要な機能のみ許可
  5. Directory Indexes を無効化する: Options -Indexes

Nginx 固有のベストプラクティス

  1. worker_processes auto を使用する: CPUコア数に自動調整
  2. worker_connections を適切に設定する: 予想される同時接続数に合わせる
  3. open_file_cache を活用する: ファイルディスクリプタキャッシュで性能向上
  4. upstream の keepalive を設定する: バックエンドへの接続を再利用
  5. try_files を使用する: 効率的なファイル存在チェック

参考資料


最終更新日: 2026-04-10
対象OS: RHEL 9 / Rocky Linux 9 / Ubuntu 24.04 LTS
Apache バージョン: 2.4.57+
Nginx バージョン: 1.26+