ホームラボでは、Ubuntu 18.04~22.04が仕事をしている。18.04で動いているシステムは、22.04に置き換えたいと思ったりして、そのためにはシステムを再構築が必要になるのだけれど、色々なシステムを同居させながら問題なく動くようにしていくには、それなりに気を遣う。
多くのOSSを使わせていただいているのだけれど、一部が22.04に対応していなかったりすると、20.04で環境構築せざるを得ないため、構築のサイクルが短くなってしまう。
そこで、各システムをDockerで動かして、OSではコンテナを再生するだけにすれば、ベースとなるOSの入れ替えが簡単になるんじゃね?という発想で検討を進めている。
ということで、幾つもテーマがあるけれど、オフィシャルイメージのないKopanoに挑戦してみることにした。
正確には、開発元で作っていて、オフィシャルになろうとしているというところのようにも見えるのだが、ライセンスなどの問題も発生しそうなので、コミュニティエディションを使えるようにしていく。
計画
できあがりの構成。
┌────┐┌────┐┌──────────────────┐┌──────────┐ │ ││ ││ Container ││ Container │ │ ││ ││┌────┐┌────┐┌────┐││ │ │ Apache ││Postfix │││ Apache ││Postfix ││ Kopano │├┤ │ │ ││ ││└────┘└────┘└────┘││ │ │(Reverse││(Relay) ││ Ubuntu:focal ││mariadb:10.8.3-jammy│ │ Prosy)││ │├──────────────────┴┴──────────┤ │ ││ ││ Dcoker Engine │ └────┘└────┘└──────────────────────────────┘ ┌──────────────────────────────────────────┐ │ Ubuntu 22.04 LTS Server │ └──────────────────────────────────────────┘
- コンテナ2つを起動すれば、閉じた世界なら運用が可能なところまで整理。
- httpでWebAppが使える。
- WebAppでメールの送受信ができる。
- IMAP、SMTP(SMTP AUTH)が使える。
- ActiveSync(Z-push)が使える。
- UbuntuにApacheをインストールして、外部にHTTPSでKopanoの機能を提供する。
- UbuntuにPostfixをインストールして、外部と25ポートでやりとりする機能を提供する。
ApacheとPostfixは他のサーバーに立てても動作するような作りにできれば、運用がしやすくなるかと。
色々と試しまくる環境を作る
Ubuntuのオフィシャルイメージを起動しても、すぐに終了してしまう。
hello world!を表示するだけではあまり面白くない。
とりあえず起動し続けてくれて、aptでパッケージをインストールできたりして。とにかく何かができるコンテナが作りたい。
じゃないと、試行錯誤しにくい。
Dockerのインストール
公式で示されている手順を過去に整理したので、その方法でインストール。
docker-compose-pluginがインストール対象になっていた。
$ sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg $ echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null $ sudo apt update $ sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin $ docker -v Docker version 20.10.17, build 100c701 $ docker compose version Docker Compose version v2.6.0
コンテナの構築
作業ディレクトリを作り、docker-compose.ymlを作成する。
$ mkdir -p ~/kopano/packages $ cd ~/kopano
docker-compose.yml ※新規作成
version: "3.9" services: kopano: image: ubuntu:focal container_name: kopano
実行してみたけれども、すぐにコンテナが止まってしまった。bashも実行できない。
$ sudo docker compose up --build Attaching to kopano kopano exited with code 0 $ sudo docker exec -it kopano /bin/bash --login Error response from daemon: Container 8f40dcb0be9cadd9e749858b106f4b04183cf2a5306f44b369030d1a8027ca3c is not running
そこで、何もせずにただ待つだけ、というentrypoint.shを作って組み込んでみる。
entrypoint.sh ※新規作成
#!/bin/bash set -e sig_term() { echo "CATCH SIGTERM" exit 0 } exec "$@" trap sig_term SIGTERM while : ; do sleep 1 ; done
※sleep infinityではSIGTERMを受け取れなかった。
Dockerfile ※新規作成
FROM ubuntu:focal USER root ADD entrypoint.sh / ENTRYPOINT ["/entrypoint.sh"]
※ENTRYPOINTはこの書き方(Exec形式)でないと、SIGTERMを受け取れなかった。
docker-compose.yml ※Dockerfileでビルドするように変更
version: "3.9" services: kopano: #image: ubuntu:jammy build: ./ image: custom/kopano:0.0.1 container_name: kopano
これでもコンテナは起動したままになるので、お手軽にログイン可能になる。
でも、何かを動かしたいなら、entrypoint.sh的なものが必要になると思われる。
docker-compose.yml
version: "3.9"
services:
kopano:
image: ubuntu:focal
container_name: kopano
tty: true
ちょっと状態を見てみる。
$ sudo docker compose up -d --build $ sudo docker exec -it kopano /bin/bash --login
# ls bin boot dev etc home lib lib32 lib64 libx32 media mnt opt proc root run sbin srv sys tmp usr var # getent passwd root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin _apt:x:100:65534::/nonexistent:/usr/sbin/nologin # logout
$ sudo docker compose stop
これで、
- docker-compose.yml
- Dockerfile
- entrypoint.sh
を色々と書き換えて試すことができるようになった。
Kopanoを動かす
とりあえず動く環境を作ってみた。
小さな範囲で運用するなら、これで十分いける気がする。というか、ホームラボならこれで十分すぎる便利さ。
ホームラボは、192.168.110.0/24で運用している。
ホームラボだけで通用するhogeserver.hogeddns.jpというドメインがあり、各種サーバーの名前解決ができるようにDNSを設定してある。
ファイル構成と内容
ファイル構成は以下の通り。
~/ └ kopano/ ├ docker-compose.yml ├ Dockerfile ├ entrypoint.sh └ packages/ ├ config.sh ├ core-11.0.2.51.c08b7f4-Ubuntu_20.04-amd64.tar.gz ├ webapp-6.0.0.66.43d5c5d-Ubuntu_20.04-all.tar.gz └ cert ├ server.crt ※ここにこの名前でファイルが置いてあれば、Postfixがsnakeoilの代わりにこの証明書を提示。 └ server.key ※server.crtとセットで置く・置かないようにする。
2022/09/18
ちょっと別のテーマでKopanoを真面目に使うことにしたので、Postfixのsubmissionがホームラボだけで通用する自己署名証明書を提示できるように処理を改変した。
名前はserver.crtとserver.keyで固定だけれども、気に入らない場合は、config.shで処理するファイル名を変更する。
それぞれの中身はこんな感じ。
docker-compose.yml
~/kopano/docker-compose.yml
version: "3.9" volumes: kopano: z-push: kopano_db: services: kopano: #image: ubuntu:jammy build: ./ image: custom/kopano:0.0.1 container_name: kopano hostname: kopano restart: unless-stopped depends_on: - kopano_db volumes: - kopano:/var/lib/kopano/attachments - z-push:/etc/z-push networks: - kopano environment: - TZ=Asia/Tokyo - MYDOMAIN=hogeserver.hogeddns.jp - MYSMTPIP=192.168.110.34 - SERVER_MYSQL_HOST=kopano_db - SERVER_MYSQL_USER=kopano - SERVER_MYSQL_PASSWORD=kopano ports: - 8080:80 - 8025:25 - 143:143 - 587:587 kopano_db: image: mariadb:10.8.3-jammy container_name: kopano_db restart: unless-stopped command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW volumes: - kopano_db:/var/lib/mysql networks: - kopano 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"
Kopanoの環境変数は、config.shを作り実行時に動くように仕掛けておいて、指定された値をシステムに反映していく。
- MYDOMAINでKopanoで運営したいドメインを指定している。Kopanoはマルチドメインに対応しているが、ホームラボはドメイン1つなので、これでいいや…と。
- MYSMTPIPで、外部とやりとりするためのPostfixのIPアドレスを指定している。
DatabaseにはMariaDBを使用している。
Postfixでメールを転送可能したいので、サブネットを指定して、ネットワークがコロコロと変わるのを止めている。
※2023/07/01 追記
実際に使う環境を作ろう!と思ったとき、以下が気になったので設定を追加している。
- Kopano → Postfix のリレーで記録されるメールのヘッダーを編集しようと思ったら、ホスト名が確定していないと特定が難しかった。
そのため、hostname指定でホスト名を固定した。 - Z-pushでカレンダー共有の設定をするが、コンテナを削除したら消えてしまう。
そのため、/etc/z-pushディレクトリをボリューム指定して永続化した。
Dockerfile
~/kopano/Dockerfile
FROM ubuntu:focal USER root ADD entrypoint.sh / ENTRYPOINT ["/entrypoint.sh"] COPY ./packages /root/packages ENV DEBIAN_FRONTEND=noninteractive SERVER_MYSQL_HOST=kopano_db SERVER_MYSQL_PORT=3306 SERVER_MYSQL_USER=kopano SERVER_MYSQL_PASSWORD=kopano SERVER_MYSQL_DATABASE=kopano LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8 RUN cd /root/packages && 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 logrotate php postfix postfix-mysql sasl2-bin software-properties-common vim && rm -f /usr/bin/man && dpkg-divert --quiet --remove --rename /usr/bin/man && mkdir -p /var/spool/postfix/var/run && cp -ar /var/run/saslauthd /var/spool/postfix/var/run/ && 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 && curl https://download.kopano.io/zhub/z-push:/final/Ubuntu_20.04/Release.key -o zhub.key && apt-key add zhub.key && rm zhub.key && add-apt-repository "deb https://download.kopano.io/zhub/z-push:/final/Ubuntu_20.04/ /" && apt install -y z-push-backend-kopano z-push-ipc-sharedmemory z-push-config-apache && chown www-data:www-data /var/lib/z-push/ /var/log/z-push/ && a2dissite 000-default && a2ensite kopano-webapp && a2enmod expires headers && mkdir -p /var/lib/kopano/attachments && chown 999:999 /var/lib/kopano/attachments && chmod 750 /var/lib/kopano/attachments && locale-gen en_US.UTF-8
大まかな流れとしては、
- 環境変数のデフォルト値を設定。これは、config.shでデフォルト値を持っておいて処理する方法もある。
- コンテナの中で使いたいパッケージをインストール。
- Kopano-CoreとWebAppを展開してインストールし、依存するパッケージをインストール(--fix-broken)。
CoreとWebAppのバージョンをべた書きしているので、バージョンが変わっていたら修正が必要。 - 公式のz-hubからZ-pushをインストールし、/var/lib/kopanoと/var/log/kopanoの所有者を変更。
- Ubuntuパッケージに含まれているApache用のz-push.confをコピー。
- ApacheでKopanoサイト、および、必要モジュールを有効化。
- docker-compose.ymlでvolumes指定するディレクトリを先に作って、所有者や権限を付けておく。
(これをやっておかないと、所有者がrootになって、kopanoからアクセスができなくなる) - 最後にロケールを指定している。これを最初にやってしまうと、z-push-backend-kopanoの依存関係でエラーが発生するが、理由がよく分からず解決ができなかったため。
となっている。
あれこれ使うので、ssコマンドと、vimをインストールしている。
それこそ、何度も作っては消し、作っては消しを繰り返したので、ホームラボに立てているミラーサーバーを見に行くように、RUNの最初にこれを入れたりしていた。
本番環境ではいらないので、その行だけを切り出してメモしておく。
sed -i 's@http://.+/ubuntu@http://mirror.hogeserver.hogeddns.jp/ubuntu@' /etc/apt/sources.list &&
※2023/07/01 追記
いざ、ホームラボのKopanoはすべてDockerで動かす!と決めると、マニュアルが見られない。
多少容量は増えてしまうが、マニュアルが見られるように必要な処置を入れた。
※2023/08/05 追記
ログローテーションができていないので、インストールするパッケージを追加。
entrypoint.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 /usr/sbin/postfix stop /usr/sbin/apachectl stop wait exit 0 } # Make configuration. /root/packages/config.sh # 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 services. /usr/sbin/apachectl start /usr/sbin/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
作ったファイルに実行権を付けておく。
$ chmod +x ~/kopano/entrypoint.sh
設定値を書き換えるconfig.shを実行した後、それぞれのサービスを起動していく。
コンテナの中でsystemdを使うためには色々とやらなきゃならないみたいなので、その方法は諦めて、コマンドを実行して常駐させていった。
MariaDBが動作していないとエラーが起きて、その後の動きがおかしくなることがあったので、MariaDBが起動していることを確認している。
また、saslauthdも起動していないうちにコマンド実行しても効果がないので、起動していることを確認している。
最後に無限ループを書いている。1秒スリープ→1秒スリープ…を繰り返す形で書いているが、このようにしないとコンテナ終了の割り込みを受け取ることができなかった。
これはもうちょっと良いものがあるのでは?と思うけれども、今はこの方法しか思いつかなかった。
config.sh
~/kopano/packages/config.sh
#!/bin/bash # # Postfix # # basic settings. postconf -e maillog_file=/var/log/postfix.log 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. sed -i "s/^START=no/START=yes/" /etc/default/saslauthd sed -i 's/^MECHANISMS="pam"/MECHANISMS="rimap"/' /etc/default/saslauthd sed -i 's/^MECH_OPTIONS=""/MECH_OPTIONS="127.0.0.1"/' /etc/default/saslauthd sed -i "s/^THREADS=5/THREADS=0/" /etc/default/saslauthd sed -i '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" /etc/postfix/master.cf sed -i "23 s/^#//g" /etc/postfix/master.cf # disable chroot for all acrive service. sed -i "s/^([a-z]+ +[a-z-]+ +[a-z-]+ +[a-z-]+ +)y( +.+$)/1n2/g" /etc/postfix/master.cf # log rotation. cat <<EOF > /etc/logrotate.d/postfix /var/log/postfix.log { rotate 4 weekly missingok notifempty compress delaycompress } EOF # # kopano-server # if [ -v SERVER_MYSQL_HOST ]; then sed -i "s/^#mysql_host = localhost$/mysql_host = $SERVER_MYSQL_HOST/" /etc/kopano/server.cfg; fi if [ -v SERVER_MYSQL_PORT ]; then sed -i "s/^#mysql_port = 3306$/mysql_port = $SERVER_MYSQL_PORT/" /etc/kopano/server.cfg; fi if [ -v SERVER_MYSQL_USER ]; then sed -i "s/^#mysql_user = root$/mysql_user = $SERVER_MYSQL_USER/" /etc/kopano/server.cfg; fi if [ -v SERVER_MYSQL_PASSWORD ]; then sed -i "s/^#mysql_password =$/mysql_password = $SERVER_MYSQL_PASSWORD/" /etc/kopano/server.cfg; fi if [ -v SERVER_MYSQL_DATABASE ]; then sed -i "s/^#mysql_database = kopano$/mysql_database = $SERVER_MYSQL_DATABASE/" /etc/kopano/server.cfg; fi sed -i "s/^#disabled_features = imap pop3/disabled_features = pop3/" /etc/kopano/server.cfg # # kopano-gateway # sed -i "s/^#imap_listen = *%lo:143/imap_listen = 0.0.0.0:143/" /etc/kopano/gateway.cfg # # kopano-ical # sed -i "s@^#server_timezone = .+$@server_timezone = $TZ@" /etc/kopano/ical.cfg # # WebApp # sed -i 's/"SECURE_COOKIES", true/"SECURE_COOKIES", false/' /etc/kopano/webapp/config.php # # Z-Push # sed -i "s@define('TIMEZONE', '');@define('TIMEZONE', '$TZ');@" /etc/z-push/z-push.conf.php # # Register certificates. # cp -a /root/packages/cert/server.crt /etc/ssl/certs/ && postconf -e smtpd_tls_cert_file=/etc/ssl/certs/server.crt cp -a /root/packages/cert/server.key /etc/ssl/private/ && postconf -e smtpd_tls_key_file=/etc/ssl/private/server.key
作ったファイルに実行権を付けておく。
$ chmod +x ~/kopano/packages/config.sh
Postfixについて、マスタープロセス設定でchrootしないように設定を変更している。
これをやっておかないと、上手く外側にあるSMTPと通信ができなかった。
ただ、全部そうしておく必要があるのかどうか、という点については未確認のままではある。
受け取ったメールはLMTPでKopanoに流し込むように設定している。
受け取ったメールアドレスの有効性は、mysql-aliases.cfとmysql-groups.cfで確認しているが、グループの方はサンプルを見つけることができなかったので自作している。
多分大丈夫だろう…とは思うものの、違う宛先にメールが届くと大変なことになるので、よく確認しておくと良い。
kopano-serverのところでは、環境変数を使って設定値を変更している。
他の設定値を変えたいときには、環境変数を追加してあげて、ここで編集するようなコードを書けば良いだろう。
(オフィシャルイメージを全然調べていないので、こんな方法がスタンダードなのかどうかは分からない)
コンテナがホスト側と通信する場合に、localhostでポートを開けても上手く動かなかった。
そのため、0.0.0.0というアドレスでサービスを起動するようにしている。
※2023/08/05 追記
Postfixのログローテーションについて、定義ファイルを追加。
CoreとWebApp
Kopanoのコミュニティーエディションはこちらからダウンロードできる。
https://download.kopano.io/community/
coreとwebappをダウンロードしてくる。
$ cd ~/kopano/packages $ wget https://download.kopano.io/community/core%3A/core-11.0.2.51.c08b7f4-Ubuntu_20.04-amd64.tar.gz $ wget https://download.kopano.io/community/webapp%3A/webapp-6.0.0.66.43d5c5d-Ubuntu_20.04-all.tar.gz
※この日のバージョンなので、適宜置き換える。
コンテナを起動してユーザーを作る
準備ができたので、コンテナを起動する。
色々ダウンロードするし、やることが多いので、ホームラボではコンテナが起動するまで100秒掛かっている。
$ cd ~/kopano $ sudo docker compose up --build
起動すると、ログがどどっと出てくるので、止まるまで待つ。
このターミナルを眺めながら、別のターミナルを起動してユーザーとグループを作る。
$ sudo docker exec -it kopano /bin/bash --login
# kopano-admin -c root -p password -e root@hogeserver.hogeddns.jp -f "Adminstrator" -a yes # kopano-admin -c hoge -p password -e hoge@hogeserver.hogeddns.jp -f "Hoge User" -a no # kopano-admin -g first -e first@hogeserver.hogeddns.jp # kopano-admin -i first -b root # kopano-admin -i first -b hoge # logout
※メールアドレスは適宜。
-aパラメーターで管理者・一般を決められる。
ここでは、rootという管理者と、hogeという一般ユーザーを作っている。
作ったユーザーは、以下のコマンドで確認できる。
$ sudo docker exec -it kopano kopano-admin -l User list for Default(3): Username Fullname Homeserver ----------------------------------------------- SYSTEM SYSTEM Unknown root Administrator hoge Hoge User $ sudo docker exec -it kopano kopano-admin -L Group list for Default(2): groupname ------------------------------------- Everyone first
Apache
ホストにApacheをインストールして、リバースプロキシとして動作させる。
$ sudo apt install apache2 $ sudo ufw allow http $ sudo ufw allow https
これは、単純にプロキシしているだけ。ホームラボだけで通用する自己署名証明書を使って、SSLで通信することのみ設定している。
/etc/apache2/sites-available/kopano.conf ※新規作成
<VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot /var/www/html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined ProxyPreserveHost On ProxyPass / http://localhost:8080/ ProxyPassReverse / http://localhost:8080/ </VirtualHost> <VirtualHost *:443> ServerAdmin webmaster@localhost DocumentRoot /var/www/html ErrorLog ${APACHE_LOG_DIR}/error.log CustomLog ${APACHE_LOG_DIR}/access.log combined ProxyPreserveHost On ProxyPass / http://localhost:8080/ ProxyPassReverse / http://localhost:8080/ # SSL SSLEngine on SSLCertificateFile /etc/ssl/private/wild.hogeserver.hogeddns.jp.crt SSLCertificateKeyFile /etc/ssl/private/wild.hogeserver.hogeddns.jp.key </VirtualHost>
※ポート80にアクセスされたら、443に飛ばすような設定の方が良いのだろうけれども、テストの間はどちらからでもアクセスできるようにしている。
コンテナで8080ポートを開いているので、ufwの設定に関係なく、他のサーバーからリバースプロキシすることもできる。
設定を有効にする。
$ sudo a2dissite 000-default.conf $ sudo a2ensite kopano.conf $ sudo a2enmod proxy_http $ sudo systemctl restart apache2
https://kopano.hogeserver.hogeddns.jp/webapp にアクセスすると、保護された接続でKopano WebAppにアクセスできる。
簡単な動作確認として、root→hoge, hoge→(グループ)firstにメールを送って、受信できることを確認する。
また、メールクライアントを使って、SMTP/MAPIを使ったメール送受信をしてみる。
これらが上手く動作すれば、あともう一息。
Postfix
ホストにPostfixをインストールして、メールを中継させる。
この設定ができると、ホームラボの他のメールサーバーとやりとりができるようになる。
$ sudo apt install postfix
■問い合わせと応答
(1) General type of mail configuration:
Internet site
(2) System mail name:
mx.hogeserver.hogeddns.jp
$ sudo ufw allow smtp
※System mail nameには、Kopanoのコンテナで指定したドメイン名とは違うものを設定。他のサーバーから名前解決できるホスト名が良さそうだ。
Kopanoからのメールを他のサーバーにリレーするように、Kopanoのネットワークをmynetworksに追加する。
サブネットはdocker-compose.ymlで指定したもの。docker-compose.ymlで指定していない場合、downするたびにネットワークが作り直されて、変わってしまう。
stackoverflow / How do configure docker compose to use a given subnet if a variable is set, or choose for itself if it isn't?
$ sudo docker network ls NETWORK ID NAME DRIVER SCOPE 2b8ff560b0e7 bridge bridge local 7e5a353618cb host host local abc762363406 kopano_kopano bridge local 03f4fd1bc728 none null local $ sudo docker network inspect kopano_kopano | grep Subnet "Subnet": "172.25.0.0/16", $ postconf -p mynetworks mynetworks = 192.168.110.0/24 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128 $ sudo postconf -e "mynetworks=172.25.0.0/16 192.168.110.0/24 127.0.0.0/8 [::ffff:127.0.0.0]/104 [::1]/128"
※mynetworksには、ローカルネットワークが登録されていたので、それをそのまま活かしておけば、他のローカルサーバーからのメールをKopanoにリレーできる。
kopano→rohhie.netのメールを、rohhie.netに配送。
合わせて、他のサーバー→kopanoのメールを、8025ポートに配送。
$ sudo postconf -e transport_maps=regexp:/etc/postfix/transport $ sudo tee /etc/postfix/transport > /dev/null <<EOF /rohhie.net$/ smtp:rohhie.net /kopano.hogeserver.hogeddns.jp$/ smtp:127.0.0.1:8025 EOF
あと、念のためにIPv4のみでメールをやりとりするようにする。
ここまでIPv6の設定をしていないのが理由で、IPv6も意識した設定にしているならこの操作はいらない。
$ sudo postconf -e inet_protocols=ipv4[Kopano] <---> [kopano.hogeserver.hogeddns.jp] --> [rohhie.het] というつながりができた。
この後、rohhie.net側で [kopano.hogeserver.hogeddns.jp] <-- [rohhie.het] を定義した(同じようにtransportを定義した)ので、相互にやりとりができた。
ホームラボでは、インターネットに向けたメール配信には、プロバイダーのメールサーバーを利用させていただいている。
この場合、relayhostにその設定を入れれば良い。
2023/08/05 追記
このサーバーで動作するCronからの通知メールを受け取ることができていなかった。
cronがroot宛てにメールを送信
→ Postfixが root@host.kopano.hogeserver.hogeddns.jp にアドレスを書き換え
→ Kopanoがそんなユーザーはいないとメールを拒否。
そこで、以下を設定して、root@kopano.hogeserver.hogeddns.jpになるようにした。
$ sudo postconf -e myorigin=kopano.hogeserver.hogeddns.jp
append_at_myorigin や append_dot_mydomain の設定と効果を確認したり、aliasesを試したりしたけれども上手くいかなかったので、上記設定としている。
2023/12/18 追記
グループに届いたメールを処理できていなかった。
$ postconf local_recipient_maps local_recipient_maps = proxy:unix:passwd.byname $alias_maps
これって、getent passwdで見えるユーザーと、alias指定しているユーザーにメールが届くということ。
このPostfixは宛先がhogeserver.hoge.ddns.jpの場合にメールをKopanoに流してくれたら、Kopanoの側で判断するわけだから、チェックする必要がない。
ということで、以下の設定を入れる。
$ sudo postconf -e local_recipient_maps=
この設定でPostfixは受信者の確認をしなくなるので、コンテナの中で動くPostfixにメールを転送してくれる。
メールを受け取るかどうかの判断は、コンテナの中で動くPostfixに任せることができる。
ポートを閉じる設定
インターネットにメールサーバーを公開する場合、受信や転送に関して、しっかりとしたセキュリティ設定が必要。
それはそれとして、ネットワークのどこに置くのかによるけれども…
8080/tcpと8025/tcpはについて、よそのホストからはアクセスできないようにしておきたい。
IMAP(143/tcp)とSMTP AUTH(587/tcp)については、ローカルからの接続を許し、他からアクセスができないようにしたい。
とすると、以下のようにポートを閉じる設定が必要になってくる。
この仮想ゲストのネットワークインターフェースはens33なので、そこから入ってくるパケットをフィルターする。
$ sudo iptables -I DOCKER-USER -i ens33 ! -s 192.168.110.34 -p tcp -m multiport --dports 80,25 -j DROP $ sudo iptables -I DOCKER-USER -i ens33 ! -s 192.168.110.0/24 -p tcp -m multiport --dports 143,587 -j DROP
※DOCKER-USERチェーンでポート指定をする場合、ホストのポート番号ではなく、コンテナのポート番号を指定しないと効果がなかった。
DOCKER COMMUNITY FORUMS / Restricting exposed Docker ports with iptables
これを実行すれば、確かにちゃんとポートは閉じるのだけれども、ホストを起動するたびにこの設定を追加したい。
ufwも動かしているし、Dockerでもnet filterは操作しているだろうから、iptables-persistentという仕組みで永続化するのはちょっと心配。
などと考えながら探していたら、かなりぴったりくる実行方法を教えてくれていた。
Qiita / docker-compose で起動させた Docker コンテナから送出するパケットを iptables で制限する
少し改変してやってみることにした。
~/kopano/add-user-rules.sh
#!/bin/bash iptables $1 DOCKER-USER -i ens33 ! -s 192.168.110.34 -p tcp -m multiport --dports 80,25 -j DROP iptables $1 DOCKER-USER -i ens33 ! -s 192.168.110.0/24 -p tcp -m multiport --dports 143,587 -j DROP
実行権を付ける。
$ chmod +x add-user-rules.sh
dockerのユニットファイルを編集する。
$ sudo systemctl edit docker
エディタが開くので、赤文字部分を追加する。
### Editing /etc/systemd/system/docker.service.d/override.conf
### Anything between here and the comment below will become the new contents of the file
[Service]
ExecStartPost=/home/rohhie/kopano/add-user-rules.sh -I
ExecStop=/home/rohhie/kopano/add-user-rules.sh -D
### Lines below this comment will be discarded
…
※スクリプトを置く場所は適宜設定のこと。
ホストを再起動。
$ sudo reboot
ルールが追加されることを確認する。
$ sudo iptables --list-rules -t filter -P INPUT DROP -P FORWARD DROP … -A DOCKER-USER ! -s 192.168.110.0/24 -p tcp -m multiport --dports 143,587 -j DROP -A DOCKER-USER ! -s 192.168.110.34/32 -p tcp -m multiport --dports 80,25 -j DROP -A DOCKER-USER -j RETURN …
これで、接続元を絞って安全を確保することができた。
LDAP認証
ホームラボで運用しているKopanoの1つは、ユーザー管理をSamba ad dcに任せている。
最終的にDockerの環境に移行してくるために、Kopanoによるユーザー管理から、LDAP認証に変更する。
既に、Samba ad dcにスキーマ登録は済ませているので、Kopano側の設定だけをすれば良い。
LDAP
まず、LDAP simple bindを設定する。
設定方法については、ここで教えてくれていた。
Kopano Knowledge Base / Postfix
~/kopano/Dockerfile
…
RUN cd /root/packages &&
…
apt install -y
apache2
curl
gnupg
mariadb-client
iproute2
php
postfix
postfix-ldap
postfix-mysql
sasl2-bin
software-properties-common
vim &&
…
※赤文字部分を追加。
~/kopano/docker-compose.yml
…
services:
kopano:
…
environment:
- MYDOMAIN=hogeserver.hogeddns.jp
- MYSMTPIP=192.168.110.34
- SERVER_MYSQL_HOST=kopano_db
- SERVER_MYSQL_USER=kopano
- SERVER_MYSQL_PASSWORD=kopano
- LDAP_URI=ldap://addc.hogeserver.hogeddns.jp:389
- LDAP_BIND_USER=ssoauth@hogeserver.hogeddns.jp
- LDAP_BIND_PASSWD=password
- LDAP_SEARCH_BASE=cn=users,dc=hogeserver,dc=hogeddns,dc=jp
- LDAP_USER_SEARCH_FILTER=(&(objectClass=user)(kopanoAccount=1))
- LDAP_GROUP_SEARCH_FILTER=(&(objectClass=group)(kopanoAccount=1))
ports:
…
※赤文字部分を追加。Active Directoryの人は、LDAP_SEARCH_BASEとかが違ってくるものと思われる。
~/kopano/packages/config.sh
… # # LDAP Settings # if [ -z "$LDAP_URI" ]; then exit 0 fi sed -i "s/^#user_plugin = db$/user_plugin = ldap/" /etc/kopano/server.cfg sed -i "s/^#user_plugin_config = .+$/user_plugin_config = /etc/kopano/ldap.cfg/" /etc/kopano/server.cfg sed -i "s/^(!include /usr/share/kopano/ldap.openldap.cfg)$/#1/" /etc/kopano/ldap.cfg sed -i "s/^#(!include /usr/share/kopano/ldap.active-directory.cfg)$/1/" /etc/kopano/ldap.cfg sed -i "s@^ldap_uri =$@ldap_uri = $LDAP_URI@" /etc/kopano/ldap.cfg sed -i "s/^ldap_bind_user =$/ldap_bind_user = $LDAP_BIND_USER/" /etc/kopano/ldap.cfg sed -i "s/^ldap_bind_passwd =$/ldap_bind_passwd = $LDAP_BIND_PASSWD/" /etc/kopano/ldap.cfg sed -i "s/^ldap_search_base =$/ldap_search_base = $LDAP_SEARCH_BASE/" /etc/kopano/ldap.cfg sed -i "$ a ldap_user_search_filter = $LDAP_USER_SEARCH_FILTER" /etc/kopano/ldap.cfg sed -i "$ a ldap_group_search_filter = $LDAP_GROUP_SEARCH_FILTER" /etc/kopano/ldap.cfg postconf -e virtual_mailbox_maps=ldap:/etc/postfix/ldap-users.cf postconf -e "virtual_alias_maps=ldap:/etc/postfix/ldap-aliases.cf ldap:/etc/postfix/ldap-groups.cf" cat <<EOF > /etc/postfix/ldap-users.cf server_host = $LDAP_URI bind = yes version = 3 bind_dn = $LDAP_BIND_USER bind_pw = $LDAP_BIND_PASSWD search_base = $LDAP_SEARCH_BASE query_filter = (&$LDAP_USER_SEARCH_FILTER(mail=%s)) scope = sub result_attribute = mail EOF cat <<EOF > /etc/postfix/ldap-aliases.cf server_host = $LDAP_URI bind = yes version = 3 bind_dn = $LDAP_BIND_USER bind_pw = $LDAP_BIND_PASSWD search_base = $LDAP_SEARCH_BASE query_filter = (&$LDAP_USER_SEARCH_FILTER(otherMailbox=%s)) scope = sub result_attribute = mail EOF cat <<EOF > /etc/postfix/ldap-groups.cf server_host = $LDAP_URI bind = yes version = 3 bind_dn = $LDAP_BIND_USER bind_pw = $LDAP_BIND_PASSWD search_base = $LDAP_SEARCH_BASE query_filter = (&$LDAP_GROUP_SEARCH_FILTER(mail=%s)) scope = sub result_attribute = mail special_result_attribute = member leaf_result_attribute = mail EOF
※LDAP Settings以下を最後に追加。
ボリュームを消し、コンテナを作り直して、起動。
$ sudo docker compose down $ sudo docker volume rm kopano_kopano kopano_kopano_db $ sudo docker compose build --no-cache $ sudo docker compose up -d
Kopanoがユーザーとグループを上手く検索できているか確認。
$ sudo docker exec -it kopano kopano-admin -l Username Fullname Homeserver -------------------------------------------------------- SYSTEM SYSTEM Unknown Administrator Administrator hogeuser hogeuser rohhie rohhie … $ sudo docker exec -it kopano kopano-admin -L Group list for Default(6): groupname ------------------------------------- Everyone Family parent …
続いて、WebAppを使ってメールの送受信、グループへのメール送受信。
SMTP/IMAPでユーザー、グループへのメール送受信を試して、上手く動けば設定完了。
以前構築した環境では、グループ宛てのメールを上手く処理できていなかったことが、今回見直してみてはっきり分かった。
上手く動かないから…と、/etc/aliasesにグループメンバーを登録して動かしていたので。でも、everyoneへのメール送信ができないことは悪くない、とか思っちゃってたので、きっちり問題解消させていなかった。
今回の設定では、グループが持つメールアドレスにメールを送れば、ちゃんとメンバーに展開してくれるようになっている。
LDAPS
暗号化なしのsimple bindはパスワードが平文で流れるので、TLSの設定をして保護してみる。
ホームラボには、自己署名した認証局がある(いわゆる、オレオレ認証局)。
Samba ad dcは、オレオレ認証局が署名した証明書を利用している。
この場合、コンテナの中でオレオレ認証局を信頼しておく必要がある。
そこで、packagesの下にcertというディレクトリを作り、そこに証明書を入れておいて、コンテナが作られるときにコピーされるように仕掛けておく。
~/
└ kopano/
├ …
└ packages/
├ …
└ cert
└ ca.crt
起動時に、/root/packages/certというディレクトリがあれば、中身を登録する処理を追加する。
~/kopano/packages/config.sh ※赤文字部分を追加
…
#
# Register certificates.
#
cp -a /root/packages/cert/ca.crt /usr/local/share/ca-certificates/ &&
update-ca-certificates
cp -a /root/packages/cert/server.crt /etc/ssl/certs/ &&
postconf -e smtpd_tls_cert_file=/etc/ssl/certs/server.crt
cp -a /root/packages/cert/server.key /etc/ssl/private/ &&
postconf -e smtpd_tls_key_file=/etc/ssl/private/server.key
#
# LDAP Settings
#
if [ -z "$LDAP_URI" ]; then
…
LDAPサーバーのURIを修正。
~/kopano/docker-compose.yml
… services: kopano: … environment: … - LDAP_URI=ldaps://addc.hogeserver.hogeddns.jp:636 … ports: …
データー移行
現在稼働中のシステムからデーターを復元する。このことには過去に取り組んでいるので、それを実行すれば良さそうだ。
テスト用には、毎日取っているバックアップデーターを使おう。
$ sudo apt install cifs-utils unzip $ sudo mkdir temp $ sudo mount -o 'username=hoge,password=hogepass,vers=2.0' //linkstation/backup ./temp
といった感じでNASに接続して、そこからファイルを取り出しておく。
確認してみたところ、データーベースの名前がkopanoではなく、kopanoserverだった。
コンテナとボリュームを削除する。
$ sudo docker compose down $ sudo docker volume rm kopano_kopano kopano_kopano_db
データーベースの名前を変更。
docker-compose.yml
… services: kopano: … environment: … - SERVER_MYSQL_HOST=kopano_db - SERVER_MYSQL_USER=kopano - SERVER_MYSQL_PASSWORD=kopano - SERVER_MYSQL_DATABASE=kopanoserver - LDAP_URI=ldap://addc.hogeserver.hogeddns.jp:389 … kopano_db: … environment: - TZ=Asia/Tokyo - MYSQL_ROOT_PASSWORD=kopano - MYSQL_PASSWORD=kopano - MYSQL_DATABASE=kopanoserver - MYSQL_USER=kopano …
コンテナを作り直して、起動。
$ sudo docker compose build --no-cache $ sudo docker compose up -d
問題なく動いていそうか確かめる。
$ sudo docker exec -it kopano /bin/bash --login
# kopano-admin -l
Username Fullname Homeserver
--------------------------------------------------------
SYSTEM SYSTEM Unknown
Administrator Administrator
hogeuser hogeuser
rohhie rohhie
…
# mysql -h kopano_db -u root -p
Enter password: パスワード[Enter]
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| kopanoserver |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.001 sec)
MariaDB [(none)]> use kopanoserver
MariaDB [kopanoserver]> show tables;
+------------------------+
| Tables_in_kopanoserver |
+------------------------+
| abchanges |
| acl |
| changes |
…
| users |
| versions |
+------------------------+
25 rows in set (0.001 sec)
MariaDB [kopanoserver]> exit
# logout
kopano-serverを止める。
$ sudo docker exec -it kopano pkill -SIGTERM kopano-server
添付ファイルを復元。
$ sudo docker cp var/lib/kopano/attachments kopano:/var/lib/kopano/ $ sudo docker exec kopano chown -R 999:999 /var/lib/kopano/attachments
※添付ファイルのバックアップをどう作ったのかによるが、ホームラボのバックアップの場合はvar/lib/kopano/attachmentsに入っている。
データベースをkopanoのコンテナにコピーして、MariaDBにリストアする。
コンテナの外からは上手く実行できなかったので、中に入って実行。
$ sudo docker cp root/work/backup/kopanoserver.dmp kopano:/ $ sudo docker exec -it kopano /bin/bash --login
# mysql -h kopano_db -u root -p -D kopanoserver < kopanoserver.dmp
Enter password: パスワード[Enter]
ERROR 1064 (42000) at line 1299: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'Process 87248 detected
Child process is finished, exiting...' at line 1
# rm kopanoserver.dmp
# logout
※添付ファイルのバックアップをどう作ったのかによるが、ホームラボのバックアップの場合はroot/work/backup/kopanoserver.dmpに入っている。
これでkopano-serverを実行し直せば動作するにはするのだけれど、kopano-searchが上手く動けない状態になるので、一旦コンテナを落として、改めて起動する。
$ sudo docker compose stop $ sudo docker compose start
これでリストアができたはずなので、WebAppでログインして中身を確認してみる。
メールも見られて、添付ファイルも見られて…問題なし。
Z-Pushのカレンダー共有
これは、是非自動登録したいのだけれど、方法が分からないので手動設定。
やったことは、過去に書いた手順と同じ。
$ sudo docker exec -it kopano /bin/bash --login
# /usr/share/z-push/backend/kopano/listfolders.php -l rohhie Available folders in store 'rohhie': -------------------------------------------------- … Folder name: Calendar Folder ID: 5a3271c9f53f42de88d5c9702dad7602298900000000 Type: SYNC_FOLDER_TYPE_USER_APPOINTMENT …
として、各ユーザーのカレンダーの情報を調べておいて、z-pushの設定ファイルに追加する。
/etc/z-push/z-push.conf.php
…
$additionalFolders = array(
// demo entry for the synchronization of contacts from the public folder.
// uncomment (remove '/*' '*/') and fill in the folderid
/*
array(
'store' => "SYSTEM",
'folderid' => "",
'name' => "Public Contacts",
'type' => SYNC_FOLDER_TYPE_USER_CONTACT,
'flags' => DeviceManager::FLD_FLAGS_NONE,
),
*/
array(
'store' => "rohhie",
'folderid' => "5a3271c9f53f42de88d5c9702dad7602298900000000",
'name' => "Rohhie's Calendar",
'type' => SYNC_FOLDER_TYPE_USER_APPOINTMENT,
'flags' => DeviceManager::FLD_FLAGS_NONE,
),
);
追加した部分はコンテナの外にメモとして保管しておいて、コンテナを作り直したら手で追加。という運用になる。
各ユーザーが自分のカレンダーを「誰かに見せる」設定をすれば、その「誰か」にアクセス権ができて、カレンダーを参照できるようになる。
ログローテーション
※2023/08/05時点で実験中。
サービスを開始すると、アクセスに応じてログが出力されはじめる。
ローテーションさせなければ。
コンテナの中でsystemdもcronも動いていないので、ホストの側でローテーションを呼び出してみる。
/etc/crontab
0 0 * * * root docker exec kopano /usr/sbin/logrotate /etc/logrotate.conf
当面の間、-vオプションで詳細情報を出してもらって、動作を確認する。
動作が確認できれば、記事を更新する。
他のサービスを動かしてみる
他の機能を組み込んで使っているケースもあるかもしれない。
systemctlが使えない環境でどうやって動かすのか、というところだけ試してみた。
パッケージをインストールした結果、ユニットファイルは
/lib/systemd/system/kopano-server.service
にできている。
中を見てみると、これだけのサービスがインストールされている。
#ll /lib/systemd/system/kopano-*
-rw-r--r-- 1 root root 465 Feb 2 11:04 /lib/systemd/system/kopano-dagent.service
-rw-r--r-- 1 root root 468 Feb 2 11:04 /lib/systemd/system/kopano-gateway.service
-rw-r--r-- 1 root root 575 Apr 29 2021 /lib/systemd/system/kopano-grapi.service
-rw-r--r-- 1 root root 461 Feb 2 11:04 /lib/systemd/system/kopano-ical.service
-rw-r--r-- 1 root root 431 Oct 28 2020 /lib/systemd/system/kopano-kapid.service
-rw-r--r-- 1 root root 695 Jun 17 2021 /lib/systemd/system/kopano-kidmd.service
-rw-r--r-- 1 root root 464 May 6 2021 /lib/systemd/system/kopano-konnectd.service
-rw-r--r-- 1 root root 762 Sep 30 2020 /lib/systemd/system/kopano-kwebd.service
-rw-r--r-- 1 root root 443 Feb 2 11:04 /lib/systemd/system/kopano-monitor.service
-rw-r--r-- 1 root root 440 Feb 2 11:02 /lib/systemd/system/kopano-search.service
-rw-r--r-- 1 root root 530 Feb 2 11:04 /lib/systemd/system/kopano-server.service
-rw-r--r-- 1 root root 554 Jun 12 2021 /lib/systemd/system/kopano-smtpstd.service
-rw-r--r-- 1 root root 472 Feb 2 11:02 /lib/systemd/system/kopano-spamd.service
-rw-r--r-- 1 root root 437 Feb 2 11:04 /lib/systemd/system/kopano-spooler.service
-rw-r--r-- 1 root root 237 Feb 2 11:04 /lib/systemd/system/kopano-statsd.service
中をよく見て動かしてみる。
konnectを動かす
konnectは認証サービスのようで、他のサービス(NextCloudとか)に認証サービスを提供できるようだ。
~kopano/Dockerfile
…
RUN cd /root/packages &&
…
a2enmod expires headers &&
# konnect
cp /root/packages/kopano-konnect.conf /etc/apache2/conf-available &&
a2enconf kopano-konnect &&
a2enmod proxy_http &&
#
mkdir -p /var/lib/kopano/attachments &&
…
※赤文字部分を追加。
~kopano/entrypoint.sh
… sig_term() { echo "CATCH SIGTERM" pkill -SIGTERM kopano-server … pkill -SIGTERM konnectd /etc/init.d/saslauthd stop … } … /usr/lib/x86_64-linux-gnu/kopano/kopano-statsd & /root/packages/start_konnect while /etc/init.d/saslauthd status …
※赤文字部分を追加。
~/kopano/packages/kopano-konnect.conf ※新規作成
ProxyPreserveHost On ProxyPass /.well-known/openid-configuration http://localhost:8777/.well-known/openid-configuration retry=0 ProxyPass /konnect/v1/jwks.json http://localhost:8777/konnect/v1/jwks.json retry=0 ProxyPass /konnect/v1/token http://localhost:8777/konnect/v1/token retry=0 ProxyPass /konnect/v1/userinfo http://localhost:8777/konnect/v1/userinfo retry=0 ProxyPass /konnect/v1/static http://localhost:8777/konnect/v1/static retry=0 ProxyPass /konnect/v1/session http://localhost:8777//konnect/v1/session retry=0 # Kopano Konnect login area ProxyPass /signin/ http://localhost:8777/signin/ retry=0
~/kopano/packages/start_konnect ※新規作成
#!/bin/bash LC_CTYPE=en_US.UTF-8 #su -s /bin/bash -c "/usr/sbin/kopano-konnectd setup" konnect su -s /bin/bash -c "/usr/sbin/kopano-konnectd serve --log-timestamp=false &" konnect
※setupの方は/etc/kopano/konnectkeysというディレクトリを必要としているのだが、なくても動作しているようなので止めている。
実行権を付ける。
$ chmod +x ~/kopano/packages/start_konnect
ファイルの変更・追加ができたら以下を実行。
$ sudo docker compose up --build
起動したら、ここにアクセスして、テストしてみる。
https://kopano.hogeserver.hogeddns.jp/signin/v1/welcome
※サイトの部分は環境に合わせて変える。ポイントは赤文字のところ。
サインイン画面が表示されるので、登録済みのユーザーで試してみたところ、ログインができた。
他のサービスで認証できるところまでは試していないが、動きそうな気配。
Kraphを動かす(途中まで)
Kopano Meet等を利用するために必要。Microsoft Graphと互換性を持たせられるそうだが、一応動くっぽいところまで試してみる。
Github / Kopano-dev / grapi
~kopano/Dockerfile
…
RUN cd /root/packages &&
…
a2enmod expires headers &&
# Kraph
cp /root/packages/kopano-kraph.conf /etc/apache2/conf-available &&
a2enconf kopano-kraph &&
a2enmod proxy_http &&
openssl rand -out /etc/kopano/kapid-pubs-secret.key -hex 64 &&
mkdir /var/run/kopano-grapi &&
chown kapi:kapi /var/run/kopano-grapi/ &&
#
mkdir -p /var/lib/kopano/attachments &&
…
※赤文字部分を追加。
~kopano/entrypoint.sh
… sig_term() { echo "CATCH SIGTERM" pkill -SIGTERM kopano-server … pkill -SIGTERM kapid pkill -SIGTERM grapi /etc/init.d/saslauthd stop … /usr/lib/x86_64-linux-gnu/kopano/kopano-statsd & /root/packages/start_grapi /root/packages/start_kapi while /etc/init.d/saslauthd status …
※赤文字部分を追加。
~/kopano/packages/config.sh
…
#
# kopano-kapi
#
sed -i "s/^#oidc_issuer_identifier=$/oidc_issuer_identifier=https://$MYDOMAIN/" /etc/kopano/kapid.cfg
#
# LDAP Settings
#
if [ -z "$LDAP_URI" ]; then
…
※赤文字部分を追加。
~/kopano/packages/kopano-kraph.conf ※新規作成
ProxyPreserveHost On ProxyPass /api/gc/ http://localhost:8039/api/gc/ retry=0 ProxyPass /api/pubs/ http://localhost:8039/api/pubs/ retry=0
~/kopano/packages/start_kapi ※新規作成
#!/bin/bash LC_CTYPE=en_US.UTF-8 su -s /bin/bash -c "/usr/sbin/kopano-kapid setup" kapi su -s /bin/bash -c "/usr/sbin/kopano-kapid serve --log-timestamp=false &" kapi
~/kopano/packages/start_grapi ※新規作成
#!/bin/bash LC_CTYPE=en_US.UTF-8 socket_path=/var/run/kopano-grapi persistency_path=/var/lib/kopano-grapi su -s /bin/bash -c "/usr/sbin/kopano-grapi setup kapi:kopano" kapi su -s /bin/bash -c "/usr/sbin/kopano-grapi serve &" kapi
実行権を付ける。
$ chmod +x ~/kopano/packages/start_kapi ~/kopano/packages/start_grapi
ファイルの変更・追加ができたら以下を実行。
$ sudo docker compose up --build
これで、起動はしたけれども、Meetを動かしていないので正しく動いているのか確認はできていない。
やったこと
オフィシャルイメージを使った構築の場合は、環境変数をどう設定するのかがメインの作業になる。
今回は、Ubuntuイメージに各種アプリをインストールしていって、少しずつ設定していくことになったので、コンテナの中で色々と試行錯誤をした。
PostfixのLDAP設定を確認
KopanoをLDAP認証に対応させたら、PostfixもLDAPでユーザーやグループの情報を見て配信するように設定する必要があった。
でも、全然上手く動かなかった。
設定したLDAPの設定が上手く動くかどうか、試す方法があった。
# postmap -q rohhie@hogeserver.hogeddns.jp ldap:/etc/postfix/ldap-users.cf rohhie@hogeserver.hogeddns.jp # postmap -q administrator@hogeserver.hogeddns.jp ldap://etc/postfix/ldap-aliases.cf root@hogeserver.hogeddns.jp # postmap -q parent@hogeserver.hogeddns.jp ldap://etc/postfix/ldap-groups.cf hogewife@hogeserver.hogeddns.jp,hoge@hogeserver.hogeddns.jp
ちゃんと設定ができてもメールが配信されないのは何でだろ…とやっていったら、alias_mapsにこの3つを入れていても上手く動かないのだった。
virtaul_mailbox_mapsにldap-users.cf、virtual_alias_mapsにldap-aliases.cfとldap-groups.cfを設定し、virtual_transportにlmtp:127.0.0.1:2003を設定したところ、上手く配信されるようになった。
なお、これはLDAPに限られる訳ではなく、mysqlでも使うことができた。
# postmap -q parent@hogeserver.hogeddns.jp mysql:/etc/postfix/mysql-groups.cf hogewife@hogeserver.hogeddns.jp,hoge@hogeserver.hogeddns.jp
グループ宛のメール
ホームラボではLDAP認証を使っているが、グループ宛のメールはWebAppから出す場合にしか働いていなかった。
仕方がないので、グループ宛のメールは/etc/aliasesで設定して動作させていた。
今回色々と試してみて、ようやくグループ宛のメールが上手く配信されるようになった。
しかし、LDAPではなく、Kopanoでユーザー管理をしている場合、グループ宛のメールを上手く配信するにはどうしたらよいのだろう…
結論からすると、こうなった。
/etc/postfix/mysql-groups.cf
user = kopano password = kopano hosts = kopano_db dbname = kopanoserver 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';
/etc/postfix/main.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-aliases.cf virtual_alias_maps = mysql:/etc/postfix/mysql-groups.cf virtual_transport = lmtp:127.0.0.1:2003 virtual_mailbox_domains=$MYDOMAIN ← docker-compose.ymlで指定したドメイン名
この結論を導き出すために、データーベースを少しだけ見てみた。
ユーザーとグループはobjectpropertyというテーブルに入っている。
列 | 意味 |
---|---|
objectid | 1から1つずつ増えて行く整数。 複数行からなるユーザーとグループの詳細情報を、1つにまとめるために使われている。 |
propname | 1行に1つの情報を持っていて、7行でユーザーの情報を表す。 emailaddress, fullname, isadmin, ishidden, loginname, modtime, password グループは4行で表している。 emailaddress, groupname, ishidden, modtime |
value | propnameに対応する値。 |
具体的にはこのような値。
# mysql -h kopano_db -u root -p MariaDB [(none)]> use kopanoserver; MariaDB [kopanoserver]> select * from objectproperty; +----------+--------------+------------------------------------------+ | objectid | propname | value | +----------+--------------+------------------------------------------+ | 1 | emailaddress | root@hogeserver.hogedns.jp | | 1 | fullname | Administrator | | 1 | isadmin | 1 | | 1 | ishidden | 0 | | 1 | loginname | root | | 1 | modtime | 2022-07-31 11:14:31 | | 1 | password | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | | 2 | emailaddress | hoge@hogeserver.hogedns.jp | | 2 | fullname | Hoge User | | 2 | isadmin | 0 | | 2 | ishidden | 0 | | 2 | loginname | hoge | | 2 | modtime | 2022-07-31 11:14:31 | | 2 | password | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | | 3 | emailaddress | first@hogeserver.hogedns.jp | | 3 | groupname | first | | 3 | ishidden | 0 | | 3 | modtime | 2022-07-31 11:14:31 | +----------+--------------+------------------------------------------+
一方、objectrelationというテーブルでは、オブジェクト同士のつながりを表現している。
列 | 意味 |
---|---|
objectid | 子供のID。 |
parentobjectid | 親のID。 |
relationtype | 今のところ1しか見たことがなく、他にどのような値があるのかは分かっていない。 |
具体的にはこのような値。
MariaDB [kopanoserver]> select * from objectrelation; +----------+----------------+--------------+ | objectid | parentobjectid | relationtype | +----------+----------------+--------------+ | 1 | 3 | 1 | | 2 | 3 | 1 | +----------+----------------+--------------+
これで、以下の関係を示しているようだった。
┌───────┐ │Group: Family │ │ objectid=3 │ └──┬────┘ │ ┌───────┐ ├─┤User: root │ │ │ objectid=1 │ │ └───────┘ │ ┌───────┐ └─┤User: hoge │ │ objectid=2 │ └───────┘
そこで、
- objectpropertyテーブルを宛先メールアドレスで検索し、IDを取り出す。
事前にユーザーは探しているであろうことから、グループしか見つからないことが想定される。 - objectrelationテーブルを親であろうグループのIDで検索し、子供のIDを取り出す。
- objectpropertyテーブルを子供のIDで検索し、メールアドレスを取り出す。
というSQL文を書いて、グループに含まれているユーザーのメールアドレスが取り出せるようにした。
これで、グループ宛にメールが配信されるようになったが、パターンをすべて調査したわけではないので、漏れに気付いたらぜひ教えていただきたい。
SMTP AUTH
IMAPはKopanoが用意してくれているので、サービスを起動すれば使えるようになる。
でも、メール送信するためにはPostfixを動かしておく必要がある。
サーバーをインターネットに公開することも意識するなら、SMTP AUTHを実装しなければ…ということで、教えていただいたとおりにやったらできた。
Zarafa Wiki / SMTP-Auth for IMAP users
本編では、entrypoint.shから呼び出すconfig.shで事前設定をしておいて、postfixを起動してから
saslauthd -a rimap -O 127.0.0.1 -c
を実行している。
記事自体はZarafa時代のものだけれども、ほぼそのままで上手く動いてくれた。
volumes指定したディレクトリの所有者
volumes指定をすると、ディレクトリの所有者が変わってしまう。
■volumes指定前 # ls -ld /var/lib/kopano/attachments/ drwxr-x--- 2 kopano kopano 4096 Jul 18 08:08 /var/lib/kopano/attachments/ ■volumes指定後 # ls -ld /var/lib/kopano/attachments/ drwxr-xr-x 2 root root 4096 Jul 18 08:06 /var/lib/kopano/attachments/
Dockerfileで先にディレクトリを作り、所有者とパーミッションを設定してみた。
… RUN cd /root/packages && … mkdir -p /var/lib/kopano/attachments && chown 999:999 /var/lib/kopano/attachments && chmod 750 /var/lib/kopano/attachments …
結果として、所有者と権限は想定通りのものになった。
# ls -ld /var/lib/kopano/attachments/ drwxr-x--- 2 kopano kopano 4096 Jul 18 08:19 /var/lib/kopano/attachments/
Kopanoは先に /var/lib/kopano/attachments が作られていても、それによって問題が引き起こされるような作りにはなっていない。
むしろ、Kopanoのバックアップ→リストアでこのディレクトリを先に復旧するようなことをやっていて、上手くデーターが引き継げている。
このことから、まっさらからスタートしたとしても、先にディレクトリができていたからといって問題はないと思われ、これを対策とした。
デフォルトのエディタを変更
systemdのユニットファイルを編集しようと、以下のコマンドを実行したところ、nanoが起動した。
$ sudo systemctl edit docker
これをvimに変更しようと思ったら、幾つかやり方があるらしい。
StackExchange / Change default editor to vim for _ sudo systemctl edit [unit-file] _
デフォルトのエディタを変えてしまおうと思った。
$ sudo update-alternatives --config editor
There are 4 choices for the alternative editor (providing /usr/bin/editor).
Selection Path Priority Status
------------------------------------------------------------
* 0 /bin/nano 40 auto mode
1 /bin/ed -100 manual mode
2 /bin/nano 40 manual mode
3 /usr/bin/vim.basic 30 manual mode
4 /usr/bin/vim.tiny 15 manual mode
Press <enter> to keep the current choice[*], or type selection number: 3[Enter]
これでvimが起動してくるようになった。
使用するメモリ
コンテナを止めて、再起動してホストのメモリーの使用量を見てみる。
$ free total used free shared buff/cache available Mem: 3984356 385176 2907772 2032 691408 3359932 Swap: 3983356 0 3983356
コンテナを起動し、WebAppやZ-pushでアクセスをした後に、ホストのメモリーの使用量を見てみる。
$ free total used free shared buff/cache available Mem: 3984356 1686564 666636 11532 1631156 2002900 Swap: 3983356 0 3983356
ざっくり、メモリーの消費量は1.2GB程度とみられる。ホストで動いているApacheやPostfix含めても1.6GB。
本気で色々とアクセスがあれば、その分だけメモリーの消費は増えるだろうけれども、これだけたくさんの機能を持ったサービスにしては、非常に少ないリソースで動いていると言って良いのではないだろうか。
起きたこと
色々と試している中で、起きてしまった問題への対処をメモしておく。
宛先のないメール
テストの段階で宛先のないメールができてしまった。
Qiita / Postfixのメールキューを確認、削除する方法
$ postqueue -p -Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient------- B6C8C2245FA 1388 Mon Jul 18 13:59:12 rohhie@rohhie.net (Host or domain name not found. Name service error for name=kopano type=AAAA: Host not found, try again) hoge@kopano -- 1 Kbytes in 1 Request.
※hoge@kopano という訳の分からない宛先のメールができてしまった…
キューにあるメールを削除する。
$ sudo postsuper -d B6C8C2245FA postsuper: B6C8C2245FA: removed postsuper: Deleted: 1 message または $ sudo postsuper -d ALL postsuper: Deleted: 1 message
メールを再送させるには、以下のコマンドを実行すれば良かった。
$ sudo postfix fulsh
Dockerfileを変更しているのに再構築されない
どの条件でイメージが再構築されるのかがよく分からない。でも、Dockerfile変更の結果を反映することができないでいた。
探してみると、以下で再構築ができることが分かった。
$ sudo docker compose build --no-cache
dockerが容量を大量に使っていた
色々とやっているうちに、容量不足になった。
$ df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 390M 2.1M 388M 1% /run
/dev/sda2 39G 35G 1.5G 97% /
tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
/dev/sda1 1.1G 5.3M 1.1G 1% /boot/efi
tmpfs 390M 4.0K 390M 1% /run/user/1000
最初イメージがとても大きいように見えた。
$ sudo docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 35 6 22.22GB 20.22GB (90%)
Containers 6 6 664.3MB 0B (0%)
Local Volumes 5 5 795.8MB 0B (0%)
Build Cache 101 7 123.6MB 0B
イメージが巨大化していたので削除。
$ sudo docker image prune WARNING! This will remove all dangling images. Are you sure you want to continue? [y/N] y Deleted Images: deleted: sha256:558bed5eaed24de5c902ffcc843559a51e662eeeef8b24792f521d4fa95207cb … deleted: sha256:19052a86b47aec58ff0d626973f3c0ca03fc93a9ba58a483751a9778857f8788 Total reclaimed space: 0B
しかし、容量が減っていない。
$ df -h
Filesystem Size Used Avail Use% Mounted on
tmpfs 390M 2.3M 387M 1% /run
/dev/sda2 39G 36G 579M 99% /
tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs 5.0M 0 5.0M 0% /run/lock
/dev/sda1 1.1G 5.3M 1.1G 1% /boot/efi
tmpfs 390M 4.0K 390M 1% /run/user/1000
ImageからBuild Cacheに移動したようだ。
$ sudo docker system df TYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 11 7 5.926GB 3.084GB (52%) Containers 8 8 665.3MB 0B (0%) Local Volumes 6 6 952.4MB 0B (0%) Build Cache 101 0 17.12GB 17.12GB
Build Cacheを削除したら、容量が解放できた。コマンド実行まで、ちょっと待たされるけれども。
Qiita / DockerのBuild Cacheの削除
$ sudo docker builder prune
WARNING! This will remove all dangling build cache. Are you sure you want to continue? [y/N] y
Deleted build cache objects:
4xtb74e12euukxwoxobw3urhg
…
ng4skeex414lbfx2jd730y52f
Total reclaimed space: 17.12GB
確認してみる。
$ sudo docker system df TYPE TOTAL ACTIVE SIZE RECLAIMABLE Images 11 7 5.926GB 3.084GB (52%) Containers 8 8 665.3MB 0B (0%) Local Volumes 6 6 952.4MB 0B (0%) Build Cache 37 0 0B 0B $ df -h Filesystem Size Used Avail Use% Mounted on tmpfs 390M 2.3M 387M 1% /run /dev/sda2 39G 19G 18G 52% / tmpfs 1.9G 0 1.9G 0% /dev/shm tmpfs 5.0M 0 5.0M 0% /run/lock
環境変数がコンテナで使えない
ホームラボのデーターベースはkopanoではなく、kopanoserverとなっていた。
そこで、環境変数でkopanoserverを設定したのだけれど、何故かコンテナの中で使えない。
~/kopano/Dockerfile
FROM ubuntu:focal
USER root
ADD entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
COPY ./packages /root/packages
ENV TZ=Asia/Tokyo
DEBIAN_FRONTEND=noninteractive
SERVER_MYSQL_HOST=kopano_db
SERVER_MYSQL_PORT=3306
SERVER_MYSQL_USER=kopano
SERVER_MYSQL_PASSWORD=kopano
SERVER_MYSQL_DATABASE=kopano
…
~/kopano/docker-compose.yml
version: "3.9"
volumes:
kopano:
kopano_db:
services:
kopano:
…
environment:
- MYDOMAIN=hogeserver.hogeddns.jp
- MYSMTPIP=192.168.110.34
- SERVER_MYSQL_HOST=kopano_db
- SERVER_MYSQL_USER=kopano
- SERVER_MYSQL_PASSWORD=kopano
- SERVER_MYSQL_DATABASE = kopanoserver
…
これで上手く動くだろう…と思ってコンテナを起動してみたら、エラーが出てる。
/etc/kopano/server.cfgが上手く設定できていない。
コンテナの中に入って環境変数を見てみると…
$ sudo docker exec -it kopano /bin/bash --login
# echo $SERVER_MYSQL_DATABASE kopano # printenv SERVER_MYSQL_DATABASE kopano # env | grep SERVER_MYSQL_DATABASE SERVER_MYSQL_DATABASE = kopanoserver SERVER_MYSQL_DATABASE=kopano
あ!! ということで、以下を修正。
~/kopano/docker-compose.yml
- SERVER_MYSQL_DATABASE=kopanoserver ←イコール記号の前後にあった空白を削除
これで問題が解消した。
さいごに
現段階では、確実に動作するであろうところまで試したところで、本番運用はしていない。
一応、できあがった記事で最初からやってみて動くことは確認している。
本番運用していないのは、他にもたくさんこの形にしたいシステムがあり、どう進めていくかを思案しているから。
今後、本番運用に入って気付いた問題があれば、都度記事を修正して、将来に役立てようと思う。
現に、過去のメモがだいぶ役に立っている。
一方で、公開しているメモにもかかわらず、足りてないところも見えてきている。
今なら分かるけれど、当時は全然分からなかったこと多数。
分かる人にはちゃんちゃらおかしい話かもしれないが、仕方がない、少しずつ理解して前に進んでいくしかない。
しかし…
ホントKopanoって凄いシステムだー、提供していただきありがとうございます。
メンテナンスが続いていくことを願っています。
コメントはこちらから お気軽にどうぞ ~ 投稿に関するご意見・感想・他