最小構成のUbuntuサーバーを常時稼働ノードとして使うとき、管理要素を後から足していく運用は崩れやすい。Ubuntu 24.04 minimized を土台にして、常駐サービスを systemd と Quadlet で管理する前提を先に固める方針で整理した。

狙いは単純だった。軽量さを保ちながらも、監視、ログ、防御、監査、バックアップまでを破綻なく回せる状態を最初から作ること。Quadlet でサービスを systemd に載せると、ログ確認・再起動制御・自動起動・障害切り分けを journalctlsystemctl に集約できる。

背景と設計の前提

コンテナを雑に起動したままにしないこと、Linux サーバーとして必要な保守運用を後回しにしないことが出発点だった。

rootless と rootful の責務も曖昧にしない。Loki、Prometheus、mktxp を rootless 側に、Exporter 群を rootful 側に分ける。公開ポートやホスト監視の扱いが単純になるためだ。関連する Podman Pods 設計でも rootful は GPU・ネットワーク・基盤系、rootless は UI・開発系という分離が基本になっていて、この方針と一致する。

ベース構成の方針

/opt/containers 配下の役割を最初から分ける。共通資産、ビルド資産、compose 系、実行時マウント、systemd 定義が混ざると、バックアップや権限整理のたびに判断がぶれる。

  /opt/containers/
├─ _shared/                # 共通資産 (certs, secrets, config)
├─ build/                  # 各appのDockerfile等
├─ compose/                # docker/podman-compose (rootful/rootless)
├─ runtime/                # 実行構成・マウント先
│  ├─ loki/
│  ├─ prometheus/
│  └─ ...
└─ systemd/
   ├─ rootless/
   └─ rootful/
  

この構成にしておくと、どこが定義ファイルで、どこが永続データで、どこが共有設定なのかが明確になる。Quadlet は /home/ksh3/.config/containers/systemd に展開して、systemd のユーザーユニットとして動かす。

ベースの前提は次のとおり。

  • OS: Ubuntu 24.04 (minimized)
  • 管理: systemd + Quadlet (/opt/containers/systemd/{rootless,rootful})
  • コンテナ: rootless(Loki, Prometheus, mktxp)+ rootful(Exporter 群)
  • ストレージ: /opt/containers/runtime 配下に用途別で整理

必須パッケージ(minimized 補完セット)

minimized 構成は軽い反面、運用で当たり前に使う道具が足りない。用途別の補完セットを入れる前提で整理する。

分類推奨パッケージ理由
基本運用sudo, less, vim, bash-completion, curl, wget操作・編集・確認用
監視・診断htop, iotop, iftop, ncdu, needrestart状況確認・再起動検出
システム管理ufw, fail2ban, chronyFirewall, SSH防御, 時刻同期
ユーティリティjq, yq, git設定やJSON/YAMLの整形
セキュリティ監査lynis, chkrootkit設定診断、rootkit検出
ウイルススキャンclamav, clamav-daemonファイル監査・定期スキャン

この一覧は単なるおすすめではない。後続の各セクションで使う要素を先に揃える意味がある。ufwfail2ban は外部公開面の防御に直結するし、lynischkrootkit は「導入した後に忘れやすい定期監査」を仕組みに乗せる入口になる。

Firewall と防御

外部公開面をまず ufw で絞る。rootful コンテナが公開するポートだけ通せばよい。rootless 側は slirp4netns を経由するため、基本的に外部から直接到達しない。

  sudo apt install ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp comment "SSH"
sudo ufw allow 9090/tcp comment "Prometheus"
sudo ufw allow 3100/tcp comment "Loki"
sudo ufw allow 9633/tcp comment "smartctl exporter"
sudo ufw enable
sudo systemctl enable --now ufw
  

公開責務が rootful 側にまとまることで、ファイアウォールルールの理由が曖昧にならない。どのユニットが外部ポートを持つかを決めておけば、ルール管理が単純になる。

セキュリティ監査と整備

運用を続ける前提なら、初期構築の時点で監査を仕込んでおく。lynis を週次、chkrootkit を月次で回す前提にしている。

Lynis(システム全体の設定診断)

  sudo apt install lynis
sudo lynis audit system
  

週次に実行するなら /etc/cron.weekly/lynis:

  /usr/sbin/lynis audit system --quiet --no-colors \
  --logfile /var/log/lynis-$(date +%F).log
  

Chkrootkit(月次で十分)

  sudo apt install chkrootkit
sudo chkrootkit
  

重要なのは、監査を「必要なときだけ実行するコマンド」にしないことだ。最小構成サーバーほど、導入直後はきれいでも数週間で状態が見えにくくなる。ログファイルを残す形にしておけば、後から比較もしやすい。

ウイルス・マルウェア対策

常時稼働ノードでも、共有領域や取得ファイルを扱うならファイルスキャンの導線は必要になる。clamavclamav-daemon を有効にし、chkrootkit を侵入検出側の補助に置く。

ClamAV(ファイルスキャン)

  sudo apt install clamav clamav-daemon
sudo systemctl enable --now clamav-freshclam
  

定期スキャン例

/etc/cron.weekly/clamav-scan:

  #!/bin/bash
LOG=/var/log/clamav/scan_$(date +%F).log
clamscan -r --bell -i /home /opt /srv > "$LOG"
  

Rootkit 検出の併用

  sudo chkrootkit
  

/home/opt/srv をまとめて見ている点が実用的だった。前半で整理した /opt/containers 配下の資産や、バックアップ対象になる /srv と自然につながる。

journalctl / systemd 運用 Tips

Quadlet を使うなら、運用の観測点は podman logs より journalctlsystemctl に寄せたほうが揃う。障害時の切り分けを systemd ベースで完結させることを重視した。

操作コマンド例
追尾ログjournalctl --user -u loki.service -f
エラーのみjournalctl --user -u loki.service -p err..alert
このブート以降journalctl --user -u prometheus.service -b
Quadlet generator ログ確認journalctl --user -g 'generator|quadlet'
一覧確認systemctl --user list-units --type=service --state=running
監視モードwatch -n 2 'SYSTEMD_COLORS=1 systemctl --user list-units --type=service'

Pod 単位でライフサイクルを揃える発想(Podman Pods 設計)と同様に、Quadlet では systemd のユニット管理で同じことを実現する。見るべき状態が分散しないことが重要だった。

Quadlet 運用の利点まとめ

従来の compose / run ベースと比べた差分を表にする。何が日々楽になるかを示している。

機能旧来 (compose/run)Quadlet 化後
自動起動cron or compose restartWantedBy=default.target
再起動ポリシー手動設定[Service] Restart=always
ログ統合podman logsjournalctl -u
セキュリティCLI引数管理systemd sandbox 設定可能
管理方法podman start/stopsystemctl start/stop

特に効くのは、自動起動、再起動、ログ統合の三つだ。ここが揃うと、常駐サービス運用が「コンテナを知っている人だけが触れる環境」から「Linux サービスとして扱える環境」に変わる。

journald 設定チューニング

ログ管理を journald に寄せる前提なので、容量制御も最初に決めておく。

/etc/systemd/journald.conf 例:

  SystemMaxUse=1G
SystemMaxFileSize=100M
RuntimeMaxUse=512M
Storage=persistent
Compress=yes
  

保存を永続化しつつ、肥大化を抑える。logrotate は不要で、journald にローテーションと圧縮を任せる。Quadlet や systemd user unit に運用を寄せるなら、この一元化は相性が良い。

バックアップ運用

定義ファイルとデータを分けてバックアップする。コンテナ実行系は再生成できても、永続データや共通資産は失うと戻しにくい。

Podman volume バックアップ

  podman run --rm -v loki-data:/data -v /srv/backup:/backup alpine \
  sh -lc 'tar czf /backup/loki-data_$(date +%F_%H%M).tar.gz -C /data .'
  

systemd 構成 + _shared 資産バックアップ

  tar czf /srv/backup/containers_config_$(date +%F).tar.gz \
    -C /opt/containers systemd runtime/_shared
  

前者は volume の中身を回収するためのもの、後者は systemd 定義と共有資産をまとめるためのものとして役割が分かれている。サービス再構築とデータ復旧を別々に扱えるようになる。

結論

この構成は、最小構成 Ubuntu に対して「軽量・静的・セキュアな常時稼働ノード」を作るための土台として有効だ。運用の核は次の4本柱にある。

  1. journald — ログ管理の一元化
  2. ufw + fail2ban — 攻撃面防御
  3. clamav + chkrootkit — ファイルと侵入検知
  4. lynis — 設定監査(週次)

Quadlet でサービスを管理するにせよ、Pods で束ねるにせよ、rootful と rootless の境界、公開ポートの扱い、ログの一元化、バックアップ対象の明確化が揃っていれば、運用は崩れにくい。Ubuntu minimized を土台にしつつ、これらをひとまとまりの運用単位として扱うことで、後から付け足すより安定した構成になる。

今後の改善

  • rootless / rootful の対象サービス一覧を明文化する。サービス名・公開ポート・バックアップ対象を表にしておくと、UFW ルールと復旧手順の整合が取りやすい。
  • cron.weekly で書かれている監査・スキャンを systemd timer に移す。Quadlet でサービス管理を systemd に乗せている以上、定期ジョブ側も同じ管理面に寄せたほうが確認しやすい。
  • Quadlet ユニットの命名規則やディレクトリ構成に「どの責務に属するサービスか」が見えるようにしておく。規模が増えたときに効いてくる。