アットウィキロゴ

[AWS]最新版のApache2.4のインストール【AlmaLinux 10】

標準のApacheは2.4.63で、現在では最新版より古くなっています。
そこでデフォルトリポジトリのappstreamではなく、サードパーティーのCodeIT(el10)を利用して、最新版をインストールします。
※現行の最新バージョン:2.4.66

1. 準備作業

(1) /etc/mime.types
「/etc/mime.types」が必要なのでインストールします。
なお、この「/etc/mime.types」は「mailcap」パッケージに含まれます。
# dnf install mailcap

(2) openssl
「openssl」をインストールします。
# dnf install openssl
# dnf install openssl-devel

(3) libev
「epel」リポジトリをインストールする方法は、dnfのリポジトリの追加登録方法【AlmaLinux 10】を参照して下さい。

# dnf --enablerepo=epel install libev
# dnf --enablerepo=epel install libev-devel

(4) libnghttp2
※ALBを使用する場合には「nghttp2」、「libnghttp2」、「libnghttp2-devel」はインストールしません。

(5) openldap-devel
# dnf install openldap-devel

(6) expat-devel
# dnf install expat-devel

(7) almalinux-logos
# dnf install almalinux-logos
もしくは
# dnf install system-logos

(8) libdb-devel
# dnf install libdb-devel

(9) sscg
※ALBを使用する場合には「sscg」はインストールしません。

(10) perl
# dnf install perl

2. Apache 2.4のインストール

CodeITリポジトリを利用するので、「dnfのリポジトリの追加登録方法【AlmaLinux 10】」を参照して、先に「CodeIT」リポジトリをインストールしておいて下さい。
# dnf install apr-devel
# dnf install apr-util-devel
# dnf install apr-util-ldap
# dnf install almalinux-logos-httpd

# dnf --enablerepo=CodeIT module enable httpd:codeit
# dnf --enablerepo=CodeIT install httpd
# dnf --enablerepo=CodeIT install httpd-devel
# dnf --enablerepo=CodeIT install mod_ldap
# dnf --enablerepo=CodeIT install mod_session
# dnf --enablerepo=CodeIT install mod_md
※ALBを使用する場合には「mod_ssl」はインストールしません。

3. 各ファイルの設定

ここでは一例を挙げます。サーバの環境や使用目的などによって任意に変更して下さい。
(1) /etc/httpd/conf/httpd.conf
ServerAdmin webmaster@example.jp
ServerName www.example.jp:80
<Directory "/var/www/html">
    Options FollowSymLinks IncludesNOEXEC
    AllowOverride All
    Require all granted
</Directory>
※Optionsの「Indexes」は必ず削除して下さい。

※ALB経由の場合にはALBのIPアドレスが記録されてしまうので、「X-Forwarded-For」ヘッダを追記します。
これによりきちんとアクセス元のIPアドレスが記録されます。
#LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

1日ごとにログを分けます。
また、死活監視用ファイル「_health.html」および画像ファイルを記録させない設定にします。
なお、ALBを使用している場合には、ELB-HealthCheckerのログが大量に書き込まれるので、これを抑止します。
ErrorLog "|/usr/sbin/rotatelogs logs/www-example.jp-error_log-%Y%m%d.log 86400 540"
 
SetEnvIf User-Agent "ELB-HealthChecker.*" nolog
SetEnvIf Request_URI "_health\.html|health\.html|\.(gif|jpg|png|ico)$" nolog
CustomLog "|/usr/sbin/rotatelogs logs/www-example.jp-access_log-%Y%m%d.log 86400 540" combined env=!nolog

CGIを使用しない場合はコメントアウト。
<IfModule alias_module>
#    ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
</IfModule>
 
#<Directory "/var/www/cgi-bin">
#    AllowOverride None
#    Options None
#    Require all granted
#</Directory>
SSIを使用する場合に、その拡張子を指定します。
AddType text/html .html
AddOutputFilter INCLUDES .html

デフォルトの文字エンコードをOffにします。
#AddDefaultCharset UTF-8
AddDefaultCharset Off

■サイト共通・セキュリティ設定
サイト全体の共通およびセキュリティ設定ファイルを作成します。
# vi /etc/httpd/conf.d/_00-site-global.conf
KeepAlive On
KeepAliveTimeout 120
Timeout 120
ServerTokens Prod
ExtendedStatus Off
ServerSignature Off
UseCanonicalName Off
TraceEnable Off
 
<IfModule mod_headers.c>
    Header set X-XSS-Protection "1;mode=block"
    Header set X-Content-Type-Options nosniff
    Header always unset X-Powered-By
    Header always set X-Frame-Options "SAMEORIGIN"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
</IfModule> 

■サイトごとの設定(VirtualHostで記述)
複数のサイトがある場合はサイトごとに作成します。
# vi /etc/httpd/conf.d/_01-www.example.jp.conf
<VirtualHost *:80>
  RemoteIPHeader X-Forwarded-For
 
  ServerName www.example.jp
  ServerAlias ec2-www.example.jp
 
  DocumentRoot "/var/www/html"
  <Directory "/var/www/html">
    Options FollowSymLinks IncludesNOEXEC
    AllowOverride All
    Require all granted
  </Directory>
 
  <Location "/">
    <LimitExcept GET POST HEAD>
        Require all denied
    </LimitExcept>
  </Location>
 
  TraceEnable Off
  ProxyErrorOverride on
 
  ErrorLog "|/usr/sbin/rotatelogs logs/www.example.jp-error_log-%Y%m%d.log 86400 540"
 
  SetEnvIf User-Agent "ELB-HealthChecker.*" nolog
  SetEnvIf Request_URI "_health\.html|\.(gif|jpg|png|ico)$" nolog
  CustomLog "|/usr/sbin/rotatelogs logs/www.example.jp-access_log-%Y%m%d.log 86400 540" combined env=!nolog
</VirtualHost> 
※アクセス元のIPアドレスを取得するため「RemoteIPHeader X-Forwarded-For」を追記します。
(2) /etc/httpd/conf.d/autoindex.conf
Index機能は無効にしているので、このファイルをリネームします。
# cd /etc/httpd/conf.d
# mv autoindex.conf{,.bak} 
(3) /etc/httpd/conf.d/ssl.conf
※ALBを使用する場合はこのファイルは使用しません。ファイルが存在した場合はリネームして下さい。
# cd /etc/httpd/conf.d
# mv ssl.conf{,.bak} 
(4) /etc/httpd/conf.d/userdir.conf
ユーザディレクトリ機能は使用しないのでリネームします。
※使用する場合には有効にして下さい。
# cd /etc/httpd/conf.d
# mv userdir.conf{,.bak} 
(5) /etc/httpd/conf.modules.d/00-dav.conf
WebDAV機能は使用しないのでリネームします。
※使用する場合には有効にして下さい。
# cd /etc/httpd/conf.modules.d
# mv 00-dav.conf{,.bak} 
(6) /etc/httpd/conf.modules.d/00-lua.conf
mod_luaは組み込み系スクリプト言語です。この機能も使用しないのでリネームします。
# cd /etc/httpd/conf.modules.d
# mv 00-lua.conf{,.bak} 
(7) /etc/httpd/conf.modules.d/00-mpm.conf
デフォルトの「event」のままでOKです。
#LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
#LoadModule mpm_worker_module modules/mod_mpm_worker.so
LoadModule mpm_event_module modules/mod_mpm_event.so
(8) /etc/httpd/conf.modules.d/00-optional.conf
初期値ではすべて無効化されています。
必要なモジュールがありましたら、有効化して下さい。
#
# This file lists modules included with the Apache HTTP Server
# which are not enabled by default.
#

#LoadModule asis_module modules/mod_asis.so
#LoadModule buffer_module modules/mod_buffer.so
#LoadModule heartbeat_module modules/mod_heartbeat.so
#LoadModule heartmonitor_module modules/mod_heartmonitor.so
#LoadModule usertrack_module modules/mod_usertrack.so
#LoadModule dialup_module modules/mod_dialup.so
#LoadModule charset_lite_module modules/mod_charset_lite.so
#LoadModule log_debug_module modules/mod_log_debug.so
#LoadModule log_forensic_module modules/mod_log_forensic.so
#LoadModule ratelimit_module modules/mod_ratelimit.so
#LoadModule reflector_module modules/mod_reflector.so
#LoadModule sed_module modules/mod_sed.so
#LoadModule speling_module modules/mod_speling.so
(9) /etc/httpd/conf.modules.d/00-proxy.conf
このままでOKです。
(10) /etc/httpd/conf.modules.d/00-ssl.conf
このままでOKです。
LoadModule ssl_module modules/mod_ssl.so
(11) /etc/httpd/conf.modules.d/00-systemd.conf
このままでOKです。
# This file configures systemd module:
LoadModule systemd_module modules/mod_systemd.so
(12) /etc/httpd/conf.modules.d/01-cgi.conf
CGI機能は使用しないのでリネームします。
※使用する場合には有効にして下さい。
# cd /etc/httpd/conf.modules.d
# mv 01-cgi.conf{,.bak} 
(13) /etc/httpd/conf.modules.d/10-h2.conf
※ALBを使用する場合はこのファイルは使用しません。ファイルが存在した場合はリネームして下さい。
# cd /etc/httpd/conf.modules.d
# mv 10-h2.conf{,.bak} 

(14) /etc/httpd/conf.modules.d/10-proxy_h2.conf
※ALBを使用する場合はこのファイルは使用しません。ファイルが存在した場合はリネームして下さい。
# cd /etc/httpd/conf.modules.d
# mv 10-proxy_h2.conf{,.bak} 

(15) /etc/httpd/conf.d/manual.conf
脆弱性として指摘される場合もあるので、ファイルが存在した場合は無効にしておきます。
# cd /etc/httpd/conf.d
# mv manual.conf{,.bak} 
(16) logrotateの無効化
logrotateでApacheのログは自動的に整理されますが、ログを日ごとに管理している場合に自動的に整理されると不都合を生じますので、この機能を解除します。
※デフォルトの場合はこのまま有効化しておいて下さい。
vi /etc/logrotate.d/httpd
ファイルの内容をコメントアウトします。
#/var/log/httpd/*log {
#    missingok
#    notifempty
#    sharedscripts
#    postrotate
#        /sbin/service httpd reload > /dev/null 2>/dev/null || true
#    endscript
#} 
(17) 設定ファイルのエラーチェック
設定ファイルにエラーがないかどうかチェックします。
# apachectl configtest
※「Syntax OK」と表示されたらOKです。

4. サービスの起動

httpdサービスの起動と自動起動設定を行います。
■ サービスの起動
# systemctl start httpd.service
■ サービスの自動起動
# systemctl enable httpd.service
その他のコマンド。
■ サービスの停止
# systemctl stop httpd.service
■ サービスの自動起動解除
# systemctl disable httpd.service
■ サービスが自動起動かどうかチェック
# systemctl is-enabled httpd.service

5. gzip圧縮の設定

アクセス速度アップのために、通信速度を短縮する「gzip圧縮」を導入します。
「/etc/httpd/conf.d」フォルダに「gzip.conf」というファイルを作成します。
※ファイル名は任意です。
# vi /etc/httpd/conf.d/gzip.conf
以下の内容を記入します。
<IfModule mod_deflate.c>
    #
    # gzip圧縮を有効にする対象
    # 主にテキスト系のみを対象にする
    #
    AddOutputFilterByType DEFLATE text/plain
    AddOutputFilterByType DEFLATE text/html
    AddOutputFilterByType DEFLATE text/css
    AddOutputFilterByType DEFLATE text/javascript
    AddOutputFilterByType DEFLATE application/javascript
    AddOutputFilterByType DEFLATE application/x-javascript
    AddOutputFilterByType DEFLATE application/json
    AddOutputFilterByType DEFLATE application/xml
    AddOutputFilterByType DEFLATE text/xml
    AddOutputFilterByType DEFLATE application/rss+xml
    AddOutputFilterByType DEFLATE application/atom+xml
    AddOutputFilterByType DEFLATE image/svg+xml
    AddOutputFilterByType DEFLATE font/ttf
    AddOutputFilterByType DEFLATE font/otf
    AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
    AddOutputFilterByType DEFLATE font/woff
    AddOutputFilterByType DEFLATE font/woff2
 
    #
    # 既に圧縮済み、または圧縮効果が薄い拡張子は除外
    #
    SetEnvIfNoCase Request_URI \
        "\.(?:gif|jpe?g|png|webp|avif|ico|mp3|aac|ogg|m4a|mp4|mpeg|mov|avi|webm|wmv|zip|gz|tgz|bz2|xz|7z|rar|pdf|exe|iso)$" \
        no-gzip dont-vary
 
    #
    # プロキシ経由時の不整合回避で使われることがある設定
    #
    Header append Vary Accept-Encoding
</IfModule>

Apacheを再起動します。
# systemctl reload httpd.service

6. Apacheログ退避スクリプト

当日以外のApacheログをS3バケットに退避させるスクリプトです。
バックアップデバイス S3
バケット名 example-jp-s3-backup
バックアップディレクトリ /apache_log/yyyymm
バックアップログ /var/log/backup/apache_log_backup.log
※「バックアップディレクトリ」は「example-jp-s3-backup/apache_log」配下に年月ディレクトリを作成して保存
#!/usr/bin/env bash
set -euo pipefail
 
############################################################
# 設定
############################################################
LOG_DIR="/var/log/httpd"
 
# S3設定
S3_BUCKET="example-jp-s3-backup"
 
# Apacheログバックアップ保存先プレフィックス
S3_PREFIX="apache_log"
 
# ログ出力
BACKUP_LOG_FILE_BASE="/var/log/backup"
BACKUP_LOG_FILE="${BACKUP_LOG_FILE_BASE}/backup_apache_log.log"
 
# コマンド定義
DATE_CMD="/bin/date"
RM_CMD="/bin/rm"
MKDIR_CMD="/bin/mkdir"
TOUCH_CMD="/bin/touch"
CHMOD_CMD="/bin/chmod"
PRINTF_CMD="/usr/bin/printf"
BASENAME_CMD="/usr/bin/basename"
AWS_CMD="/usr/local/bin/aws"
 
############################################################
# ログ出力関数
############################################################
log() {
  local msg="$1"
  local now
  now="$("${DATE_CMD}" '+%Y-%m-%d %H:%M:%S')"
  "${PRINTF_CMD}" '[%s] %s\n' "${now}" "${msg}" >> "${BACKUP_LOG_FILE}"
}
 
############################################################
# S3オブジェクト存在確認
# 存在する: 0
# 存在しない: 1
############################################################
s3_object_exists() {
  local bucket="$1"
  local key="$2"
 
  if "${AWS_CMD}" s3api head-object --bucket "${bucket}" --key "${key}" >/dev/null 2>&1; then
    return 0
  else
    return 1
  fi
}
 
############################################################
# ログファイル作成
############################################################
"${MKDIR_CMD}" -p "${BACKUP_LOG_FILE_BASE}"
if [[ ! -e "${BACKUP_LOG_FILE}" ]]; then
  "${TOUCH_CMD}" "${BACKUP_LOG_FILE}"
  "${CHMOD_CMD}" 600 "${BACKUP_LOG_FILE}"
fi
 
############################################################
# 事前チェック
############################################################
if [[ ! -d "${LOG_DIR}" ]]; then
  log "ERROR: Apacheログディレクトリが存在しません: ${LOG_DIR}"
  exit 1
fi
 
if [[ ! -x "${AWS_CMD}" ]]; then
  log "ERROR: AWS CLI が見つかりません: ${AWS_CMD}"
  exit 1
fi
 
# バケット存在確認
if ! "${AWS_CMD}" s3api head-bucket --bucket "${S3_BUCKET}" >/dev/null 2>&1; then
  log "ERROR: S3バケットにアクセスできません: ${S3_BUCKET}"
  exit 1
fi
 
############################################################
# 当日日付
# ファイル名内の yyyymmdd と比較する
############################################################
TODAY_YMD="$("${DATE_CMD}" '+%Y%m%d')"
TODAY_YMD_DATE="$("${DATE_CMD}" '+%Y-%m-%d')"
 
log "================================================"
log "${TODAY_YMD_DATE}"
log "================================================"
log "START: Apacheログ退避処理を開始します"
log "対象ディレクトリ: ${LOG_DIR}"
log "バックアップ先: s3://${S3_BUCKET}/${S3_PREFIX}/"
log "ログ出力先: ${BACKUP_LOG_FILE}"
 
############################################################
# 対象ファイル処理
# 例:
#   www.example.jp-access_log-20260323.log
#   www.example.jp-error_log-20260323.log
############################################################
shopt -s nullglob
 
copied_count=0
skip_count=0
error_count=0
 
for filepath in "${LOG_DIR}"/*-access_log-*.log "${LOG_DIR}"/*-error_log-*.log; do
  [[ -e "${filepath}" ]] || continue
 
  filename="$("${BASENAME_CMD}" "${filepath}")"
 
  if [[ "${filename}" =~ ^.+-(access_log|error_log)-([0-9]{8})\.log$ ]]; then
    file_ymd="${BASH_REMATCH[2]}"
    file_ym="${file_ymd:0:6}"
 
    # 当日ログは退避しない
    if [[ "${file_ymd}" == "${TODAY_YMD}" ]]; then
      log "SKIP: 当日ログのため退避しません: ${filename}"
      ((skip_count+=1))
      continue
    fi
 
    s3_key="${S3_PREFIX}/${file_ym}/${filename}"
    s3_uri="s3://${S3_BUCKET}/${s3_key}"
 
    # 退避先に同名オブジェクトがある場合はリネームして残す
    if s3_object_exists "${S3_BUCKET}" "${s3_key}"; then
      backup_suffix="$("${DATE_CMD}" '+%Y%m%d%H%M%S')"
      renamed_key="${s3_key}.bak.${backup_suffix}"
      renamed_uri="s3://${S3_BUCKET}/${renamed_key}"
 
      n=1
      while s3_object_exists "${S3_BUCKET}" "${renamed_key}"; do
        renamed_key="${s3_key}.bak.${backup_suffix}.${n}"
        renamed_uri="s3://${S3_BUCKET}/${renamed_key}"
        ((n+=1))
      done
 
      if "${AWS_CMD}" s3 mv "${s3_uri}" "${renamed_uri}" >/dev/null; then
        log "RENAME: 既存バックアップを退避しました: ${s3_uri} -> ${renamed_uri}"
      else
        log "ERROR: 既存バックアップの退避に失敗しました: ${s3_uri} -> ${renamed_uri}"
        ((error_count+=1))
        continue
      fi
    fi
 
    # S3へアップロード
    if "${AWS_CMD}" s3 cp "${filepath}" "${s3_uri}" >/dev/null; then
      log "COPIED: ${filepath} -> ${s3_uri}"
 
      # アップロード成功後に元ファイル削除
      "${RM_CMD}" -f "${filepath}"
      log "REMOVED: 元ファイルを削除しました: ${filepath}"
 
      ((copied_count+=1))
    else
      log "ERROR: S3アップロードに失敗しました: ${filepath} -> ${s3_uri}"
      ((error_count+=1))
      continue
    fi
  else
    log "SKIP: 対象形式外のため処理しません: ${filename}"
    ((skip_count+=1))
  fi
done
 
log "END: Apacheログ退避処理が完了しました copied=${copied_count} skip=${skip_count} error=${error_count}"
exit 0
最終更新:2026年05月20日 13:49