楽々セキュアな Redmine 環境を構築する【podman】

今回はコンテナで、Redmine の SSL(Let’s Encript) 環境を作ってみましたので、手順をご紹介します。なお前回、 Nextcloud を構築したホスト上に、Redmine のコンテナ(pod)を準備して、フロントエンドの Bunkerweb でマルチサイトとしました。マルチサイトにする必要がない場合は、前回の記事で、Bunkerweb をシングルサイトで設定していますので、そちらも参考にしてみてください。

参考:

https://docs.podman.io/en/v4.4/markdown/podman-pod-create.1.html
https://docs.podman.io/en/latest/markdown/podman-run.1.html
https://hub.docker.com/_/redmine
https://hub.docker.com/_/mysql
https://docs.bunkerweb.io/1.4/
前回の記事はこちら:

今回はコンテナで、Nextcloud の SSL(Let's Encript) 環境を作ってみましたので、手順をご紹介します。仮想化技術のおかげでどんどん楽にサーバーが立てられ...
スポンサーリンク

今回紹介する Redmine の構成

今回紹介するのは、Redmine と mariadb の2つのコンテナを1つの pod として扱います。この pod はバックエンドになります。フロントエンドには、 Bunkerweb のコンテナを利用しました。ここでは、Bunkerweb については、細かくは触れませんがセキュアなフロントエンドとして利用することができますし、Let’s Encript の操作を自動化してくれ、さらに複数のバックエンド(ウェブサイト)に名前(DNS名)で振り分けることも可能な(簡単にマルチサイト化できる)ため採用しました。

Bunkerweb は現時点で、1.5系 が出ていますが、複数のコンテナを上げる必要があるようで、少し理解に時間がかかりそうだったので、1.4系を利用しています。

環境

Rocky Linux release 9.3 (Blue Onyx)
podman version 4.6.1

コマンド操作は全て、root アカウントで実施しています。

下準備

コンテナを終了させても、Redmine はデータを保持したいため、永続化ボリュームが必要です。永続化ボリュームなどを配置するために、ディレクトリを作成します。chown は後の pod を作成させる際に、ホストとコンテナ間でuid/gidのマッピングを行っているため、これに合わせて設定します。

mkdir -p /var/local/containers/redmine/{db,app}
chown -R 100999.100999 /var/local/containers/redmine

また、ログを残すためにログのディレクトリも作成しておきます。

mkdir -p /var/log/containers/

バックエンドの Bunkerweb のための永続化ボリュームの準備し、ファイアウォールを開けておきます。

mkdir -p /var/local/containers/bunkerweb/data
chown 100101.100101 /var/local/containers/bunkerweb/data
firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --add-port=443/tcp --permanent
firewall-cmd --reload

バックエンド(Redmine)を立ち上げる

バックエンドとなる pod を準備します。この pod は、ホストの 3080 ポートへアクセスされると、pod(コンテナ)の 3000 ポートへアクセスさせます。また、uid や gid は、コンテナの 0 をホストの 100000 にマップします。

podman pod create --hostname redpod --name redmine -p 3080:3000 --uidmap 0:100000:5000 --gidmap 0:100000:5000

pod の中に、mariadb のコンテナを作成します。–log-driver を指定しているのは、–log-opt path に指定したファイルにログを吐かせるためです。デフォルトでは思ったところにログを吐いてくれませんでした。latest が安定バージョンのようです(現時点で 11.2.2 でした)。-v で ローカルホストの /var/local/containers/redmine/db に コンテナの /var/lib/mysql をマウントさせます。これでコンテナをつぶしても DB が残ります。「:Z」 は、SELinux のためのオプション(プライベート非共有ラベル)です。

podman run -d --tz=Asia/Tokyo --pod=redmine --name=red-db \
--log-driver k8s-file --log-opt path=/var/log/containers/red-db.log \
-e MYSQL_ROOT_PASSWORD="password" -e MYSQL_DATABASE="redmine" -e MYSQL_USER="redmine" -e MYSQL_PASSWORD="password" \
-v /var/local/containers/redmine/db:/var/lib/mysql:Z \
docker.io/library/mariadb:latest

pod の中に、redmine のコンテナを作成します。latest で問題ないでしょう・・。(現時点で 5.1.1 でした)。「:z」は、SELinux のためのオプション(共有コンテンツラベル)です。

podman run -d --tz=Asia/Tokyo --pod=redmine --name=red-app \
--log-driver k8s-file --log-opt path=/var/log/containers/red-app.log \
-e REDMINE_DB_MYSQL="127.0.0.1" -e REDMINE_DB_USERNAME="redmine" -e REDMINE_DB_PASSWORD="password" \
-v /var/local/containers/redmine/app:/usr/src/redmine/files:z \
docker.io/library/redmine:latest

これだけで、Redmine が立ち上がっているはずです。いったん http://ホストのIP:3080 にアクセスして確認してみましょう。Redmine が立ち上がっていると思います。右上のログインから admin/admin でログインできます。

今作った Redmine pod を systemd で自動起動するために以下のコマンドを実行します。
一旦、停止して、

podman pod stop redmine

systemd の設定ファイルを生成し、systemd で起動しなおします。

cd /etc/systemd/system/
podman generate systemd --files --name redmine
systemctl daemon-reload
systemctl enable pod-redmine.service
systemctl start pod-redmine.service

フロントエンド(Bunkerweb)を立ち上げる

Let’s Encript(SSL) の自動化と、セキュリティを強化するために、フロントエンドに  Bunkerweb を立ち上げます。社内や自宅内だけで使う場合は、先ほど立ち上げたバックエンドだけでも十分に機能すると思います。

通常は、NATルーターの中にホストがあると思いますので、以下の作業をする前に ルーターに 80 と 443 ポートをホストにマッピング(フォワード)してあげてください。

/var/local/containers/bunkerweb/podman.env ファイルを作成し以下を記載。マルチサイトにしない場合は、前回の記事(Nextcloud)を参考にシングルサイトとして設定してください。

MULTISITE=yes
SERVER_NAME=server1.example.com server2.example.com
server1.example.com_REVERSE_PROXY_URL=/
server1.example.com_REVERSE_PROXY_HOST=http://ホストのIP:2080
server2.example.com_REVERSE_PROXY_URL=/
server2.example.com_REVERSE_PROXY_HOST=http://ホストのIP:3080
USE_REVERSE_PROXY=yes
ALLOWED_METHODS=GET|POST|HEAD|PROPFIND|DELETE|PUT|MKCOL|MOVE|COPY|PROPPATCH|REPORT|OPTIONS
BAD_BEHAVIOR_STATUS_CODES=400 401 403 405 444
INTERCEPTED_ERROR_CODES=400 401 403 405 500 501 502 503 504
USE_DNSBL=no
USE_BUNKERNET=no
USE_MODSECURITY=no
USE_MODSECURITY_CRS=no
LIMIT_REQ_RATE=40r/s
SERVE_FILES=no
DISABLE_DEFAULT_SERVER=yes
AUTO_LETS_ENCRYPT=yes
USE_LETS_ENCRYPT_STAGING=yes       (1)
USE_GZIP=yes
X_FRAME_OPTIONS=SAMEORIGIN
MAX_CLIENT_SIZE=10G
(注1) USE_LETS_ENCRYPT_STAGING は、完成したら no にします。初回構築で何度も、動作確認を繰り返すことになる場合は、USE_LETS_ENCRYPT_STAGING を yes で使いましょう。
さらっと書いていますが、Bunkerwebのキモとなる設定です。動くようになるまで結構悩みました。Bunkerweb 本家の説明をよく確認してください。自宅サーバーで必要なレベルには調整しているつもりですが、特に LIMIT_REQ_RATE は環境に合わせて設定が必要だと思います。

/etc/systemd/system/container-bunkerweb.service を作成し、以下を記載

[Unit]
Description=Podman container-bunkerweb.service

[Service]
Restart=on-failure
ExecStartPre=/usr/bin/rm -f %t/%n-pid %t/%n-cid
ExecStart=/usr/bin/podman run --conmon-pidfile %t/%n-pid --cidfile %t/%n-cid \
-d -p 80:8080 -p 443:8443 \
-v /var/local/containers/bunkerweb/data:/data:z \
--uidmap 0:100000:5000 --gidmap 0:100000:5000 \
--tz=Asia/Tokyo \
--env-file /var/local/containers/bunkerweb/podman.env \
--log-driver k8s-file \
--log-opt path=/var/log/containers/bunkerweb.log \
--name=bunkerweb docker.io/bunkerity/bunkerweb:1.4.8
ExecStop=/usr/bin/podman stop -t 10 bunkerweb
ExecStopPost=/usr/bin/sh -c "/usr/bin/podman rm bunkerweb"
KillMode=none
Type=forking
PIDFile=%t/%n-pid

[Install]
WantedBy=default.target

以下のコマンドで Bunkerweb が自動起動するように設定します。

systemctl daemon-reload
systemctl start container-bunkerweb
systemctl enable container-bunkerweb

同様に、複数のサービスをコンテナで立ち上げて、Bunkerweb でマルチサイト設定を追加することで、HTTPS通信可能なサイトが複数作れます。