DS243100 岡田修門
本ドキュメントは、Amazon Web Services (AWS) の EC2 インスタンス上に Apache HTTP Server を導入し、Webサーバーとして完全に自律駆動させるまでの全インフラ構築プロセスを客観的に記録したものである。
起動時のインスタンス構成パラメータは以下の通りである。
名前 (Name): AirChecker for Shonan Beach FM
インスタンス数: 1
AMI名: Amazon Linux 2023 kernel-6.18 AMI
AMI ID: ami-0967230e9fa45db6d
アーキテクチャ: 64 ビット (x86)
デフォルトユーザー名: ec2-user
インスタンスタイプ: t3.micro(2 vCPU, 1 GiB メモリ / 無料利用枠対象)
ストレージ (ルートボリューム): 12 GiB(gp3, 3000 IOPS, 暗号化なし)
キーペア名: AirChecker for Shonan Beach...
VPC: vpc-00c3fd9db7176625b
プライベート IP アドレス: 172.31.39.88
パブリック IP の自動割り当て: 有効化
セキュリティグループ: 新しいセキュリティグループを作成 (launch-wizard-1)
インバウンドルール:
0.0.0.0/0 / 任意のIPアドレス)HTTPS化の為にドメインとIPアドレスの固定化を行う。通常パブリック IP は再起動の度に再割り当てとなるが、Elastic IPを使用することで、サーバー再起動時もIPが変わらず、DNS設定やSSL/TLS証明書の自動更新エラーを防ぎます。
割り振られた IPv4 アドレス: 35.79.68.243
ネットワークインターフェース ID: eni-003e9a6adabbb4ebb
ネットワークボーダーグループ: ap-northeast-1
レコードタイプ: A
値: 35.79.68.243
エイリアス: いいえ
TTL (秒): 86,400
ルーティングポリシー: Simple
macのターミナルからSSHクライアントとダウンロードした秘密鍵を用いて、以下のコマンドでインスタンスへ接続を行う。
Bash
ssh -i "Downloads/AirChecker for Shonan Beach FM-2.pem" ec2-user@demo20260712.develop.azm.ne.jp
パッケージメタデータの更新確認およびシステム全体のパッケージを最新バージョンに引き上げる。
時間帯を調整する。
Bash
# パッケージメタデータの更新とキャッシュチェック
sudo dnf check-update
# システム全体のパッケージを最新バージョンに引き上げ
sudo dnf update -y
# OSのタイムゾーンをアジア/東京に設定
sudo timedatectl set-timezone Asia/Tokyo
# 時計が日本時間(現在11:41など)になったか確認
date
Amazon Linux 2023 の公式リポジトリより、コアパッケージである httpd(Apache)のインストールを実施する。
Bash
# Apache本体および関連依存パッケージのインストール
sudo dnf install -y httpd
インストール直後の Apache サービスは停止状態(Inactive)であるため、明示的にプロセスを起動し、その稼働ステータスを客観的に検証する。
Bash
# Apache サービス(httpd)の起動
sudo systemctl start httpd
# 稼働状態(ステータス)の確認
sudo systemctl status httpd
コマンド執行後、出力ログの Active: 項目が以下のように active (running) と緑色で表示され、Webサーバーとして正常にプロセスがメモリ上に展開されたことを示す。
Plaintext
● httpd.service - The Apache HTTP Server
Loaded: loaded (/usr/lib/systemd/system/httpd.service; enabled; preset: disabled)
Active: active (running) since Sat 2026-07-11 16:50:00 JST; 1min ago
EC2インスタンスの停止・再起動や予期せぬ瞬断が発生した場合でも、Webサーバーが人間の手を介さずに自動で復旧・常駐するように、OSのシステム管理(systemd)へ自動起動設定を登録する。
Bash
# OS起動時の自動有効化を永続化登録
sudo systemctl enable httpd
外部ブラウザからアクセスされた際に、コンテンツが正常に読み込めるよう、既定のWeb公開ルートディレクトリの権限を確認し、本ドキュメントを index.html として設置する。
URL
http://demo20260712.develop.azm.ne.jp/
Let’s Encrypt が公式に提供している自動化ツール Certbot を利用することで、証明書の取得から Apache の設定更新、さらには有効期限(90日間)の自動更新の設定までを実装する。
/etc/httpd/conf.d/ 配下に新しく設定ファイル(例: airchecker.conf)を作成します。
Bash
sudo vi /etc/httpd/conf.d/airchecker.conf
ファイルの中に以下の内容を記述して保存します。
※ ServerName に指定したドメイン名を正確に記述するのが一番のポイントです。
※ 先ほど変更した airchecker.html を初期画面にする設定(DirectoryIndex)もここに綺麗に統合しておきます。
Plaintext
<VirtualHost *:80>
ServerName demo20260712.develop.azm.ne.jp
DocumentRoot /var/www/html
<Directory "/var/www/html">
AllowOverride None
Require all granted
DirectoryIndex airchecker.html index.html
</Directory>
</VirtualHost>
構文チェックを行い、Apache を再起動して設定を反映させます。
Bash
# 構文チェック(Syntax OK と出れば正常)
sudo httpd -t
# Apache の再起動
sudo systemctl restart httpd
下準備が整ったので、Let’s Encrypt のコマンドを実行します。
Bash
sudo certbot --apache
Apache を再起動して確認する。
Bash
# Apache の再起動
sudo systemctl restart httpd
以下のURLを開く。
URL
https://demo20260712.develop.azm.ne.jp/
URL
[http://demo20260712.develop.azm.ne.jp/airchecker.html
本システムは、Amazon EC2 (Linux) 環境において、湘南ビーチFM(IPサイマルラジオ)の番組をWeb UIから簡単な操作で予約し、バックグラウンドで最高音質(無劣化)のままエアチェック(録音)を行うシステムである。
システムは以下の5つのレイヤーによるバケツリレー方式で堅牢に動作する。
[1. airchecker.html (Web UI)]
│ (JSON形式の予約リクエスト送信 / 曜日タブ・編集機能)
▼
[2. reserve_handler.py (CGI)]
│ (リクエストを検証、大文字始まり曜日正規化、ユニークな予約票JSONを生成)
▼
[3. at_scheduler.py (毎分cron巡回)]
│ (pending状態の予約票を検知、次回該当曜日の具体的な日付(YYYY-MM-DD)を算出)
▼
[4. Linux atd (at デーモン)]
│ (指定日時にec2-user権限でバックグラウンド実行)
▼
[5. ffmpeg (コア録音処理)] ➔ 最高音質(.m4a)で保存 ➔ [後処理] 予約票の自動削除/ステータス復帰
index.html)役割: 番組スケジューラーの表示、予約情報のカスタマイズ、受理状況および録音済みライブラリの可視化。
主要機能:
program_data.json から非同期(fetch)で番組スケジュールをロードし、曜日ごとのタブにカード形式で展開。
番組名は <textarea> でユーザーが自由に変更・編集可能。
予約種別(随時: once / 定期: regular)および延長バッファ(秒単位)を選択可能。
強力なブラウザキャッシュを回避するための キャッシュバスター(ミリ秒タイムスタンプ付与) を搭載し、常に最新のシステム状況とライブラリ一覧を表示。
30秒ごとの自動ポーリング同期によるリアルタイム表示。
reserve_handler.py)役割: Webからのリクエストを受理し、シリアライズしてファイルキューへ渡すCGI(Python3)。
主要機能:
Webサーバー(apache ユーザー)権限で実行。
フロントエンドから送信された曜日文字列(小文字)を大文字始まり(例: monday ➔ Monday)に正規化・クレンジングして保存。
同秒内の連打や同時リクエストによるファイル上書きを完全に防御するため、タイムスタンプ + 4桁のランダム値(例: reserve_1783755988_4321.json)を用いたユニークファイル名生成ロジックを実装。
at_scheduler.py)役割: ファイルキュー(queue/)を毎分監視し、OSの at デーモンへジョブを安全にデプロイするコアスケジューラー(Python3)。
主要機能:
status: "pending" のファイルをスキャン。
曜日から次回配信日を割り出す日付計算ロジック: at コマンドが直近の時刻に誤判定するのを防ぐため、曜日文字列から「次回の該当曜日となる具体的な日付(YYYY-MM-DD)」を算出し、at 16:00 2026-07-13 のように厳格な日時引数を構築。
ジョブの多重登録を防ぐため、at 投入成功と同時にステータスを "scheduled" にロックしてJSONを更新。
ffmpeg コマンドおよびファイル削除コマンドは、環境変数に依存しない完全絶対パスでシェルスクリプトを生成。
atd & ffmpeg)役割: 指定日時に正確に録音コマンドを実行し、無劣化抽出を行う。
主要機能:
ec2-user 権限の at キューでバックグラウンド実行。
無劣化エアチェック処理: -c copy 引数により、配信されているAAC音声ストリームを再エンコードせずにそのまま抽出。EC2のCPU負荷をほぼゼロに抑えながら最高音質で .m4a を生成。
HLSストリーム(MPEG-2 TS)のコンテナビットストリームを一般的なオーディオプレイヤーで再生可能にするため、-bsf:a aac_adtstoasc フィルタを適用。
予約タイプ別のクリーンアップ(後処理):
随時(once): 録音完了後、rm -f により自動的に予約票JSONを完全抹消。
定期(regular): 録音完了後、sed コマンドを自身のジョブから発行し、予約票のステータスを "scheduled" から "pending" へ自動復帰させ、次週の cron 巡回での再登録に備える。
get_recordings.py)役割: 録音済みオーディオファイルの一覧をスキャンして返すCGI(Python3)。
主要機能:
/var/www/html/recordings/ 内の .m4a ファイルをタイムスタンプ逆順(新しい順)でソートしてJSONで応答。
キャッシュによる古い一覧の表示固定を防ぐため、HTTPレスポンスヘッダーに徹底的なキャッシュ制御ヘッダー(Cache-Control: no-store, no-cache... / Pragma: no-cache / 過去の Expires 設定)を射出。
システムをWEBとOSデーモンの両権限で衝突なく安定稼働させるための、厳格なセキュリティおよびアクセス権限の設計シート。
/usr/local/bin/
└── at_scheduler.py [755 / root:root または ec2-user:ec2-user] 巡回
スケジューラー本体
/var/www/html/
├── index.html [644 / apache:apache] Webメイン画面
├── reserve_handler.py [755 / apache:apache] 予約受付CGI
├── program_data.json [644 / apache:apache] マスター番組スケジュール表
├── list_reservations.py [755 / apache:apache] 予約状況一覧CGI
├── get_recordings.py [755 / apache:apache] 録音ファイル一覧CGI
├── queue/ [755 / apache:apache] 予約票(JSON)の一時保管庫
│ └── scheduler.log [644 / ec2-user:ec2-user] 巡回ログ
└── recordings/ [775 / ec2-user:apache] 録音済みオーディオ保管庫
└── rec_*.m4a [664 / ec2-user:apache] 実際の録音ファイル
queue/ ディレクトリ: Apache(CGI)がJSONを生成し、at 執行シェル(ec2-user)が削除または書き換えを行うため、apache を所有者として適切な読込権限を与える。
recordings/ ディレクトリ: at ジョブ(ec2-user)が .m4a を新規作成してサイズを増加させ、Web UI(apache)がそれを読み込んでストリーミング再生するため、グループ権限を apache に設定した 775 (グループ書き込み・読み込み可) でバインドする。これにより、生成されたファイルは自動的に 664 となりWebライブラリに即座に表示される。
スケジューラーは一般ユーザーである ec2-user の cron で安全に稼働する。
Plaintext
* * * * * /usr/bin/python3 /var/www/html/at_scheduler.py >> /var/www/html/queue/scheduler.log 2>&1
現在待機中の録音ジョブ一覧を確認する:
Bash
atq
誤って登録したジョブを取り消す(削除する):
Bash
atrm [ジョブ番号]
(例: atrm 5)