注意:タイトルはUbuntu 24.04としているけれど、Kopano自体は実際にはUbuntu 20.04で動作している。
Ubuntu 20.04がサポート終了なので、Ubuntu 24.04にアップグレードしようと考えた。
しかし、Kopanoのコミュニティエディションは公開が終了したので、20.04からアップグレードできない。
Sogoも試してとても良かったのだけれど、メモ機能が実装されていないので、ウチではちょっと困ったことになる。
以上のことから、ホストOSをUbuntu 24.04にして、KopanoだけをDockerのUbuntu 20.04で動かすことにした。
ベースとなるイメージの作成
KopanoをDockerで動かすための記事を書いていたので、これをいったんそのまま構築してみたが、イメージの作り込みが甘いのでやり直し。
過去記事: Ubuntu22.04 DockerでKopano
色々なパッケージをダウンロードしてくるので、スクリプトを修正する度にサーバーに負荷を掛けるのは申し訳なさ過ぎる…
ということで、パッケージをダウンロードしてきた結果のイメージを作っておく。
それ以外の箇所、たとえばApacheやPostfixのところは過去記事のままでだいたい動くと思われる。
Dockerfile
Ubuntu 20.04で使う様々なパッケージをインストール。
- 過去記事で1つだったDockerfileを分割し、Ubuntuが起動して使えるところまでを構築。(Kopanoインストールを色々改善する場合にいいかなと)
- 追加でrsyslogをインストール。
~/kopano/Dockerfile.kopanobase
FROM ubuntu:focal
USER root
COPY entrypoint.sh.empty /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
ENV DEBIAN_FRONTEND=noninteractive \
LANG=en_US.UTF-8 \
LANGUAGE=en_US:en \
LC_ALL=en_US.UTF-8
RUN sed -i "s:^path-exclude=/usr/share/man:#path-exclude=/usr/share/man:" /etc/dpkg/dpkg.cfg.d/excludes && \
apt update && \
apt install -y \
apache2 \
curl \
gnupg \
man \
mariadb-client \
iproute2 \
less \
locales \
logrotate \
php \
postfix \
postfix-mysql \
rsyslog \
sasl2-bin \
software-properties-common \
vim && \
rm -f /usr/bin/man && \
dpkg-divert --quiet --remove --rename /usr/bin/man && \
locale-gen en_US.UTF-8
Entrypoint
コンテナを起動したままにするためだけに、空転するスクリプトを用意する。
~/kopano/entrypoint.sh.empty
#!/bin/bash
set -e
sig_term() {
echo "CATCH SIGTERM"
exit 0
}
exec "$@"
trap sig_term SIGTERM
while : ; do sleep 1 ; done
動作確認
イメージを作る。
もしかしたら、これがいるのかもしれない。
$ sudo docker context use default
$ chmod +x ~kopano/entrypoint.sh.empty
$ sudo docker buildx build -f ~/kopano/Dockerfile.kopanobase -t custom/kopano:0.0.0 ~/kopano
起動して中を覗いてみる。--rm指定しているので、コンテナを止めると削除される。
$ sudo docker run --name kopano --rm --detach custom/kopano:0.0.0
$ sudo docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
29cfbaa542c9 custom/kopano:0.0.0 "/entrypoint.sh" 13 seconds ago Up 12 seconds kopano
$ sudo docker exec -it kopano bash --login
# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.0 6980 3328 ? Ss 08:19 0:00 /bin/bash /entrypoint.sh
root 58 0.4 0.0 7244 3840 pts/0 Ss 08:20 0:00 bash --login
root 83 0.0 0.0 5484 1792 ? S 08:20 0:00 sleep 1
root 84 0.0 0.0 8896 3328 pts/0 R+ 08:20 0:00 ps aux
# exit
$ sudo docker stop kopano
問題なく動作しているようだ。
Kopanoが入ったイメージの作成
ベースとなるイメージにKopanoのパッケージをインストールする。
あわせて、Z-Pushのパッケージもインストールして、大量のダウンロードをここで完結させる。
KopanoとZ-Pushのダウンロード
Kopano関連のパッケージをダウンロードし、以下の通り配置する。
- Kopano:download.kopano.io/community
- Z-Push : download.kopano.io/zhub/z-push
kopano/
|-- Dockerfile.kopano
|-- Dockerfile.kopanobase ← 使用済み
|-- entrypoint.sh.empty ← 使用済み
`-- packages
|-- core-11.0.2.51.c08b7f4-Ubuntu_20.04-amd64.tar.gz
|-- webapp-6.0.0.66.43d5c5d-Ubuntu_20.04-all.tar.gz
`-- z-push
|-- z-push-backend-kopano_2.6.4+0-0_all.deb
|-- z-push-common_2.6.4+0-0_all.deb
|-- z-push-config-apache_2.6.4+0-0_all.deb
`-- z-push-ipc-sharedmemory_2.6.4+0-0_all.deb
Dockerfile
ベースとなるイメージにKopanoとZ-Pushのパッケージをコピーし、展開してインストールする。
- KopanoとZ-Pushのパッケージをインストールするところまでを実施。(設定は次の工程で一気に実施)
- Z-Pushのパッケージを事前にダウンロードしておく形式にした。
~/kopano/Dockerfile.kopano
FROM custom/kopano:0.0.0
USER root
COPY ./packages /root/packages
ENV SERVER_MYSQL_HOST=kopano_db \
SERVER_MYSQL_PORT=3306 \
SERVER_MYSQL_USER=kopano \
SERVER_MYSQL_PASSWORD=kopano \
SERVER_MYSQL_DATABASE=kopano
RUN cd /root/packages && \
tar -zxvf core-11.0.2.51.c08b7f4-Ubuntu_20.04-amd64.tar.gz && \
rm core-11.0.2.51.c08b7f4-Ubuntu_20.04-amd64.tar.gz && \
tar -zxvf webapp-6.0.0.66.43d5c5d-Ubuntu_20.04-all.tar.gz && \
rm webapp-6.0.0.66.43d5c5d-Ubuntu_20.04-all.tar.gz && \
dpkg -i core-11.0.2.51.c08b7f4-Ubuntu_20.04-amd64/* || true && \
dpkg -i webapp-6.0.0.66.43d5c5d-Ubuntu_20.04-all/* || true && \
apt -y --fix-broken install && \
apt -y install php-soap && \
dpkg -i z-push/*.deb && \
apt -y --fix-broken install
動作確認
イメージを作る。
$ sudo docker buildx build -f ~/kopano/Dockerfile.kopano -t custom/kopano:0.0.1 ~/kopano
起動して中を覗いてみる。
$ sudo docker run --rm --interactive --tty custom/kopano:0.0.1 bash
# dpkg -l "kopano-common"
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name Version Architecture Description
+++-==============-===========================-============-=================================
ii kopano-common 11.0.2.51.76cf85b89-0+877.1 amd64 Shared files for Kopano services
# exit
パッケージも上手くインストールできているみたいだ。
環境設定されたイメージの作成
環境を設定するスクリプトを3つに分けることにした。
赤文字がこのセクションで作成するファイル。
kopano/
|-- bin
| |-- config-once.sh
| |-- config.sh
| `-- update-mx-cert
|-- Dockerfile
|-- Dockerfile.kopano ← 使用済み
|-- Dockerfile.kopanobase ← 使用済み
|-- entrypoint.sh
|-- entrypoint.sh.empty ← 使用済み
`-- packages ← 使用済み
|-- ...
初期設定
以前のスクリプトを参考に、いくつかの変更を加えた。
- 従来Dockerfileの中に含めていた設定をここで実施、かつ、起動時に都度行う設定を別のスクリプトに切り出す。
- kopanoの各種サービスがログをファイルに出力できていなかったのを修正。
- kopanoのserver.cfgだけ、環境変数が設定されていることを確認していたので削除(ここまでの段階で環境変数は設定されているから)。
- Postfixのログ出力先を標準のものに変更。
- Apacheが起動時にワーニングを出力していたのを修正。
- Apacheのログ出力先をaccess.logに変更し、接続元IPアドレスとしてホスト(リバースプロキシー)ではなく、接続してきたクライアントを出力するように変更。
- Z-Pushで認証失敗時に詳細情報がログ出力されるように変更。
~/kopano/bin/config-once.sh
#!/bin/bash
set -e
#
# rsyslog
#
sed -i '/imklog/s/^/#/' /etc/rsyslog.conf
#
# Postfix
#
# basic settings.
postconf -e myhostname=kopano
postconf -e virtual_mailbox_maps=mysql:/etc/postfix/mysql-aliases.cf
postconf -e virtual_alias_maps=mysql:/etc/postfix/mysql-groups.cf
postconf -e virtual_transport=lmtp:127.0.0.1:2003
postconf -e virtual_mailbox_domains=$MYDOMAIN
postconf -e relayhost=$MYSMTPIP
# get aliases from database.
cat <<EOF > /etc/postfix/mysql-aliases.cf
user = $SERVER_MYSQL_USER
password = $SERVER_MYSQL_PASSWORD
hosts = $SERVER_MYSQL_HOST
dbname = $SERVER_MYSQL_DATABASE
query = select value from objectproperty where objectid=(select objectid from objectproperty where value='%s' limit 1) and propname='loginname';
EOF
chmod 600 /etc/postfix/mysql-aliases.cf
cat <<EOF > /etc/postfix/mysql-groups.cf
user = $SERVER_MYSQL_USER
password = $SERVER_MYSQL_PASSWORD
hosts = $SERVER_MYSQL_HOST
dbname = $SERVER_MYSQL_DATABASE
query = select value from objectproperty where objectid in ( select objectid from objectrelation where parentobjectid in ( select objectid from objectproperty where value='%s' and propname='emailaddress' ) and relationtype=1 ) and propname='emailaddress';
EOF
chmod 600 /etc/postfix/mysql-groups.cf
# enable sasl authentication.
mkdir -p /var/spool/postfix/var/run
cp -ar /var/run/saslauthd /var/spool/postfix/var/run/
sed -i '{
s/^START=no/START=yes/
s/^MECHANISMS="pam"/MECHANISMS="rimap"/
s/^MECH_OPTIONS=""/MECH_OPTIONS="127.0.0.1"/
s/^THREADS=5/THREADS=0/
s@^OPTIONS="-c -m /var/run/saslauthd"@OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd"@
}' /etc/default/saslauthd
adduser postfix sasl
cat <<EOF > /etc/postfix/sasl/smtpd.conf
pwcheck_method: saslauthd
mech_list: plain login
EOF
postconf -e "mua_client_restrictions=permit_sasl_authenticated reject"
sed -i "{
17,21 s/^#//g
23 s/^#//g
}" /etc/postfix/master.cf
#
# Apache
#
sed -i '{
1s/^/<VirtualHost _default_:80>\nErrorLog ${APACHE_LOG_DIR}\/error.log\nCustomLog ${APACHE_LOG_DIR}\/access.log combined_kopano\n\n/
$a </VirtualHost>
}' /etc/apache2/sites-available/kopano-webapp.conf
a2dissite 000-default
a2ensite kopano-webapp
cat <<EOF > /etc/apache2/conf-available/kopanolog.conf
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy $(ip route | sed -n 's/^default via \([^ ]*\).*/\1/p')
LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined_kopano
EOF
a2enmod remoteip
a2enconf kopanolog
echo "ServerName localhost" | tee /etc/apache2/conf-available/fqdn.conf
a2enconf fqdn
a2enmod expires headers
#
# kopano-server
#
mkdir -p /var/lib/kopano/attachments
chown 999:999 /var/lib/kopano/attachments
chmod 750 /var/lib/kopano/attachments
sed -i "{
s/^#mysql_host = localhost\$/mysql_host = $SERVER_MYSQL_HOST/
s/^#mysql_port = 3306\$/mysql_port = $SERVER_MYSQL_PORT/
s/^#mysql_user = root\$/mysql_user = $SERVER_MYSQL_USER/
s/^#mysql_password =\$/mysql_password = $SERVER_MYSQL_PASSWORD/
s/^#mysql_database = kopano\$/mysql_database = $SERVER_MYSQL_DATABASE/
s/^#disabled_features = imap pop3/disabled_features = pop3/
s@^#log_file =.*\$@log_file = /var/log/kopano/server.log@
\$a
\$a # Disable sending reports\nsurveyclient_interval=0
}" /etc/kopano/server.cfg
#
# kopano-dagent
#
sed -i "s:^#log_file =.*\$:log_file = /var/log/kopano/dagent.log:" /etc/kopano/dagent.cfg
#
# kopano-gateway
#
sed -i "{
s/^#imap_listen = \*%lo:143/imap_listen = 0.0.0.0:143/
s:^#log_file =.*\$:log_file = /var/log/kopano/gateway.log:
}" /etc/kopano/gateway.cfg
#
# kopano-ical
#
sed -i "{
s:^#server_timezone = .\+\$:server_timezone = $TZ:
s:^#log_file =.*\$:log_file = /var/log/kopano/ical.log:
}" /etc/kopano/ical.cfg
#
# kopano-monitor
#
sed -i "s:^#log_file =.*\$:log_file = /var/log/kopano/monitor.log:" /etc/kopano/monitor.cfg
#
# kopano-search
#
sed -i "s:^#log_file =.*\$:log_file = /var/log/kopano/search.log:" /etc/kopano/search.cfg
#
# kopano-spooler
#
sed -i "s:^#log_file =.*\$:log_file = /var/log/kopano/spooler.log:" /etc/kopano/spooler.cfg
#
# WebApp
#
sed -i 's/"SECURE_COOKIES", true/"SECURE_COOKIES", false/' /etc/kopano/webapp/config.php
#
# Z-Push
#
chown www-data:www-data /var/lib/z-push/ /var/log/z-push/
sed -i "{
s:define('TIMEZONE', ''):define('TIMEZONE', '$TZ'):
s/define('LOGAUTHFAIL', false)/define('LOGAUTHFAIL', true)/
}" /etc/z-push/z-push.conf.php
#
# Register certificates.
#
update-mx-cert
起動時に環境変数を反映
起動する度に環境変数の設定値を反映させる。
- そもそもcompose.yamlの環境変数が変更されたときに上手く対応できていなかったので新設。
- Apacheがリモート接続してきたクライアントをログに出力するように設定(ネットワーク環境が変わるかもしれないから)。
~/kopano/bin/config.sh
#!/bin/bash
set -e
#
# Postfix
#
postconf -e virtual_mailbox_domains=$MYDOMAIN
postconf -e relayhost=$MYSMTPIP
sed -i "{
s/^user = .*\$/user = $SERVER_MYSQL_USER/
s/^password = .*\$/password = $SERVER_MYSQL_PASSWORD/
s/^hosts = .*\$/hosts = $SERVER_MYSQL_HOST/
s/^dbname = .*\$/dbname = $SERVER_MYSQL_DATABASE/
}" /etc/postfix/mysql-aliases.cf
sed -i "{
s/^user = .*\$/user = $SERVER_MYSQL_USER/
s/^password = .*\$/password = $SERVER_MYSQL_PASSWORD/
s/^hosts = .*\$/hosts = $SERVER_MYSQL_HOST/
s/^dbname = .*\$/dbname = $SERVER_MYSQL_DATABASE/
}" /etc/postfix/mysql-groups.cf
#
# Apache
#
sed -i "s/^RemoteIPInternalProxy.*/RemoteIPInternalProxy $(ip route | sed -n 's/^default via \([^ ]*\).*/\1/p')/" /etc/apache2/conf-available/kopanolog.conf
#
# kopano-server
#
sed -i "{
s/^mysql_host = .*\$/mysql_host = $SERVER_MYSQL_HOST/
s/^mysql_port = .*\$/mysql_port = $SERVER_MYSQL_PORT/
s/^mysql_user = .*\$/mysql_user = $SERVER_MYSQL_USER/
s/^mysql_password = .*\$/mysql_password = $SERVER_MYSQL_PASSWORD/
s/^mysql_database = .*\$/mysql_database = $SERVER_MYSQL_DATABASE/
}" /etc/kopano/server.cfg
#
# Z-Push
#
sed -i "s:define('TIMEZONE', '[A-Za-z\/]*');:define('TIMEZONE', '$TZ');:" /etc/z-push/z-push.conf.php
証明書の設定(未テスト)
以前は、Postfixが提示する証明書として、長期管理用可能な自己署名証明書を利用していたけれど、結局ホストのPostfixとKopanoの中経しかしないので、今は全く使用していない。
とはいえ、何か別の形で使うかもしれないので、少し安全性に配慮した形にして残す。
~/kopano/bin/update-mx-cert
#!/bin/bash
if [[ -f "/etc/ssl/certs/server.pem" && -f "/etc/ssl/private/server.key" ]]; then
postconf -e smtpd_tls_cert_file=/etc/ssl/certs/server.pem
postconf -e smtpd_tls_key_file=/etc/ssl/private/server.key
else
postconf -e smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
postconf -e smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
fi
このスクリプトは初期設定で呼び出すようにした。
証明書を更新するときには、
$ sudo docker cp /etc/ssl/certs/hoge.pem kopano:/etc/ssl/certs/server.pem
$ sudo docker cp /etc/ssl/private/hoge.key kopano:/etc/ssl/private/server.key
$ sudo docker exec kopano update-mx-cert
という感じで行けるだろうと思う。
Entrypoint
サービスを起動して、無限ループでSIGTERMを待つスクリプト。
- rsyslogを起動して、Postfixのログ出力がrsyslogで出力されるようにした。
- Postfixの起動方法を変更して、chrootができるようにした。(/etc/init.d/postfixから初期化処理が呼ばれて/var/spool/postfixにファイルが作られる)
- config.shの置き場を変更。
~/kopano/entrypoint.sh
#!/bin/bash
set -e
echo "Start Kopano container with paramater : $@"
trap sig_term SIGTERM
sig_term() {
echo "CATCH SIGTERM"
pkill -SIGTERM kopano-server
pkill -SIGTERM kopano-dagent
pkill -SIGTERM kopano-gateway
pkill -SIGTERM kopano-ical
pkill -SIGTERM kopano-monitor
pkill -SIGTERM kopano-search
pkill -SIGTERM kopano-spooler
pkill -SIGTERM kopano-statsd
/etc/init.d/saslauthd stop
/etc/init.d/postfix stop
/etc/init.d/apache2 stop
start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile /run/rsyslogd.pid
wait
exit 0
}
# Update configuration.
config.sh
# Start rsyslog.
/etc/init.d/rsyslog start
# Wait for service to start.
while
mysqladmin -h $SERVER_MYSQL_HOST -u $SERVER_MYSQL_USER status -p$SERVER_MYSQL_PASSWORD
[ $? -ne 0 ]
do
sleep 5
done
# Start application services.
/etc/init.d/apache2 start
/etc/init.d/postfix start
/etc/init.d/saslauthd start
/usr/sbin/kopano-server &
/usr/sbin/kopano-dagent -l &
/usr/sbin/kopano-gateway &
/usr/sbin/kopano-ical &
/usr/sbin/kopano-monitor &
/usr/sbin/kopano-search &
/usr/sbin/kopano-spooler &
/usr/lib/x86_64-linux-gnu/kopano/kopano-statsd &
while /etc/init.d/saslauthd status
[ $? -ne 0 ]
do
sleep 3
done
saslauthd -a rimap -O 127.0.0.1 -c
# Execute parameter.
exec "$@"
# Infinite loop.
while : ; do sleep 1 ; done
イメージの構築
Dockerfileを作って構築。
~/kopano/Dockerfile
FROM custom/kopano:0.0.1
USER root
COPY entrypoint.sh /
COPY bin/ /usr/local/bin
#COPY /etc/ssl/cert/hoge.pem /etc/ssl/cert/server.pem
#COPY /etc/ssl/private/hoge.key /etc/ssl/private/server.key
RUN /usr/local/bin/config-once.sh
$ chmod +x entrypoint.sh bin/config-once.sh bin/config.sh bin/update-mx-cert
$ sudo docker buildx build -t custom/kopano:1.0.0 ~/kopano
これでコンテナが動く状態になった。
もし、config-once.shやconfig.sh、entrypoint.shの間違いがあったら、
$ sudo docker container rm <kopanoコンテナに付けた名前>
$ sudo docker image rm custom/kopano:1.0.0
といった感じで消してしまって作り直してもいいし、修正の履歴を残していってもいいのかもしれない。
動作確認
どこでサービスを動かすのがいいのか、いつも迷うが、今回はここ。
$ sudo mkdir /opt/service
バージョンが変わって、composeのデフォルトのファイル名が変わったとか。
/opt/service/compose.yaml
volumes:
kopano:
z-push:
mariadb:
services
kopano:
image: custom/kopano:1.0.0
container_name: kopano
hostname: kopano
restart: unless-stopped
depends_on:
- mariadb
volumes:
# - /var/lib/kopano/attachments:/var/lib/kopano/attachments
- kopano:/var/lib/kopano/attachments
- z-push:/etc/z-push
# - /var/log/docker/kopano:/var/log
networks:
- kopano
ports:
- 8080:80
- 8025:25
- 143:143
- 587:587
environment:
- TZ=Asia/Tokyo
- MYDOMAIN=hogeserver.hogeddns.jp
- MYSMTPIP=192.168.110.34
- SERVER_MYSQL_HOST=mariadb
- SERVER_MYSQL_DATABASE=kopano
- SERVER_MYSQL_USER=kopano
- SERVER_MYSQL_PASSWORD=kopano
mariadb:
image: mariadb:11.7.2-noble
container_name: mariadb
hostname: mariadb
restart: unless-stopped
volumes:
- mariadb:/var/lib/mysql
networks:
- kopano
ports:
- 3306:3306
environment:
- TZ=Asia/Tokyo
- MYSQL=ROOT_PASSWORD=kopano
- MYSQL=PASSWORD=kopano
- MYSQL=DATABASE=kopano
- MYSQL=USER=kopano
networks:
kopano:
ipam:
config:
- subnet: "172.25.0.0/16"
gateway: "172.25.0.1"
添付ファイルを保管する/var/lib/kopano/attachmentsは、バックアップのやり方で決める。
- ボリュームにしたら、コンテナの中でバックアップ処理を走らせる。
- バインドマウントにしたら、ホストでバックアップ処理を走らせる。
バインドマウントにするなら、起動する前に以下を実行。
$ sudo mkdir -p /var/lib/kopano/attachments
$ sudo chown 999:999 /var/lib/kopano/attachments
$ sudo chmod 750 /var/lib/kopano/attachments
起動してみる。
$ cd /opt/service
$ sudo docker compose up --menu=false
※--menu=falseでメニューを無効化しないと、[CTRL]+[z]や[CTRL]+[c]を受け付けない。
まずは、ログで異常がないことを確認。mariadbに接続できないというエラーが表示されるのは、サービス開始を待っているからなので問題なし。
kopano | mysqladmin: connect to server at 'mariadb' failed
kopano | error: 'Can't connect to MySQL server on 'mariadb' (115)'
kopano | Check that mysqld is running and that the socket: '/var/run/mysqld/mysqld.sock' exists!
前回記事の通り、中に入ってkopano-adminでユーザーを作り、ホストのApache(Kopanoにリバースプロキシーしている)にアクセスすれば、少なくともKopanoの中でのメールのやり取りはできるはず。
問題なければ、[CTRL]+[z]とか[CTRL]+[4]とかでデタッチ。
問題があれば、[CTRL]+[c]とかで停止させて調整。
ホスト側でログを監視したい
Fail2banでログを監視して、攻撃を受けたら遮断したい。
とはいえ、監視できるのはWebAppくらいのものだけれど。
ホストからログが見られるようにする
ログ用のディレクトリを作成する。
$ sudo mkdir -p /var/log/docker/kopano/{apache2,kopano,kopano-kweb,z-push}
$ sudo chgrp 107 /var/log/docker/kopano
$ sudo chmod 775 /var/log/docker/kopano
$ sudo chgrp 4 /var/log/docker/kopano/apache2
$ sudo chown 999:999 /var/log/docker/kopano/kopano
$ sudo chown www-data /var/log/docker/kopano/kopano-kweb
$ sudo chown www-data:www-data /var/log/docker/kopano/z-push
※コンテナの中のsyslogはUID:105/GID:107だった。
動作中のコンテナを止める。
$ cd /opt/service
$ sudo docker compose stop
ログ用のフォルダをバインドマウントする。
/opt/service/compose.yaml
...
- /var/log/docker/kopano:/var/log ← 上でコメント化していたものを有効化
...
コンテナを起動。
$ sudo docker compose up --detach
これで、ホスト側では/var/log/docker/kopanoにあるログが監視できるようになる。
WebAppの監視
WebAppでのログイン失敗を監視する。
ログイン画面でユーザー attacker、パスワード hoge と、適当なログインエラーを発生させると、以下が出力される。
ApacheでRemoteIPHeaderとRemoteIPInternalProxyを適切に設定したことで、接続元がリモートPCのIPアドレスに書き換えられている。
/var/log/docker/kopano/apache/error.log
[Fri May 23 21:49:01.918033 2025] [php7:notice] [pid 2324] [client 192.168.110.98:0] Kopano WebApp user: attacker: authentication failure at MAPI. IP: 192.168.110.98, referer: https://kopano.hogeserver.hogeddns.jp/webapp/
Fail2banは動いているとして、牢獄に以下を追加。
/etc/fail2ban/jail.d/my.local
...
[kopano-webapp]
enabled = true
backend = pyinotify
logpath = /var/log/docker/kopano/apache2/error.log
...
フィルターとしては、こんな感じ?
/etc/fail2ban/filter.d/kopano-webapp.conf
[INCLUDES]
before = apache-common.conf
[Definition]
__kap_prefix = %(__prefix_line)s \[php7:notice\] \[pid [0-9]+\]
failregex = ^%(__kap_prefix)s \[client <HOST>:[0-9]+\] Kopano WebApp user: [A-Za-z0-9_\-.@+#]+: authentication failure at MAPI\. IP: [0-9\.]+, referer: https?://.+$
試してみる。
$ fail2ban-regex /var/log/docker/kopano/apache2/error.log kopano-webapp.conf
失敗した数を検知できたので、これで監視ができそうだ。
Z-Pushの監視
Z-Pushの認証エラーを監視する。
ブラウザーでZ-PushのURLにアクセスし、ユーザー attacker、パスワード hoge と、適当なログインエラーを発生させると、以下が出力される。
/var/log/docker/kopano/z-push/z-push-error.log
24/05/2025 09:31:18 [ 51] [FATAL] [attacker] Exception: (AuthenticationRequiredException) - Access denied. Username or password incorrect
24/05/2025 09:31:18 [ 51] [WARN] [attacker] IP: 172.16.110.10 failed to authenticate user 'attacker'
※この手前にもWARNログが出ているけれど、ここだけ見れば良さそう。
Fail2banは動いているとして、牢獄に以下を追加。
/etc/fail2ban/jail.d/my.local
...
[kopano-zpush]
enabled = true
backend = pyinotify
logpath = /var/log/docker/kopano/z-push/z-push-error.log
...
フィルターを設定。
/etc/fail2ban/filter.d/kopano-zpush.conf
[INCLUDES]
before = apache-common.conf
[Definition]
failregex = ^%(__prefix_line)s \[ +[0-9]+\] \[WARN\] \[[A-Za-z0-9_\-.@+#]+\] IP: <HOST> failed to authenticate user.+$
試してみる。
$ fail2ban-regex /var/log/docker/kopano/z-push/z-push-error.log kopano-zpush.conf
失敗した数を検知できたので、これで監視ができそうだ。
既に他のサービスで利用しているMariaDBに同居
このホストではいくつかのサービスを動かそうとしていて、MariaDBには既にWordpressのデーターが入っている状態だった。
そんなに忙しいサーバーって訳でもないので、もう1つMariaDBのコンテナを動かしてもどうにかなりそうな気がするものの、リソースの無駄遣いだよなと思った。
そんなわけで、Kopanoのコンテナを動かす前にMariaDBにユーザーを作っておくことで、同居させることにした。
具体的には、MariaDBのコンテナを起動しておいて、rootで入ってkopanoユーザーを作る。
ユーザー名はともかく、パスワードは複雑なものにしておくといいかなと思う。
$ sudo docker exec -it mariadb /bin/bash --login
# mariadb -u root -p
MariaDB [(none)]> grant all privileges on kopano.* to kopano@'%' identified by 'kopano' with grant option;
MariaDB [(none)]> quit
# exit
こうしてユーザーを用意しておいて、Kopanoのコンテナを起動したら、データーベースが作られて動き出した。
さいごに
今回、色々と修正をするにあたって、Copilotに質問をしながらやってみた。
たいがいの事柄にはストレートに回答をくれるので、かなりの時間短縮になる、というのが感想。
ただし、トラブルになると途端に答えが見えなくなる。
asciiコードで65は何?と聞くと、即座にAと答えてくれるのだけれど、その時に以下が一緒に表示された。
もし他のASCIIコードの対応文字を調べたい場合は、Linuxの printf や echo を使って確認することもできます。
Bash
printf "\x41\n"
まぁそうなんですが、ちょっと面倒だなと思ったので、10進数で表示させる方法はある?と聞いてみた。
printf を使って 10進数でASCIIコードを指定して表示 するには、printf "%c" のフォーマットを使用します。
例: ASCIIコード 65 を表示
Bash
printf "%c\n" 65
どれどれ…
$ printf "%c\n" 65
6
こうなってくると、なかなか答えにたどり着けなくなる感じ。
質問を変えて、asciiコード表を表示するコマンドはある?と聞くと…
$ man ascii
なるほど、これは便利。
コメントはこちらから お気軽にどうぞ ~ 投稿に関するご意見・感想・他