Ubuntu

Ubuntu22.04 DockerでNextcloud

Ubuntu

Alfresco 7.2をインストールしてみたけれど、いくつか課題が出てきた。
そうなってみて、自分でも理由は分からないが課題の解決が面倒になり、次のシステムを探し始めた。

すぐに見つかったのがNextcloud。人気のシステムだけに、インストールやトラブル対応に関する記事も多い。
開発も継続的に行われていて、とても良さそうだ。



広告


元々記事が多いところに、似たような記事を投稿することは気が引けるが…自分用のメモということでご容赦いただきたい。
なお、「手順が確立するまでにやったこと」以降は、何故今回の手順にしたのかを思い出すために書き残したもので、あまり使うことはなさそう。

インストール

ホームラボで試験環境を作り、そこで手順を確立する。
nextcloud.hogeserver.hogeddns.jp(192.168.110.34) ※宅内では名前解決ができるが、インターネットには存在しない。
手順を確立したら、本番環境を作り、インターネットに向けてサービスを公開する。

今回整理した手順で、

  • Nextcloud
  • Nextcloud Office(Collabora)
  • Talk(チャット、ビデオ会議)
  • Elasticsearch(全文検索)

が使えるようになる。

サーバーの初期設定

いつも通り、VMware Playerで手順を確立する。
CPUx1、メモリー6GB、HDD40GBの仮想PCを作り、以下の設定を追加して起動。

Nextcloud.vmx

firmware = "efi"
efi.legacyBoot.enabled = "FALSE"
uefi.secureBoot.enabled = "FALSE"
ulm.disableMitigations="TRUE"

本番環境のESXiを無理矢理7.0にバージョンアップしたので、ゲストはEFIにしないとまともに動かないので、事前テストの環境もEFIにしておく。

nextcloud.hogeserver.hogeddns.jp で名前解決ができるように、宅内のDNSを設定してある。

起動後、Ubuntu 22.04 LTS Serverをインストール。
途中でSSHのインストールを選択。
nextcloudを一緒にインストールできるようになっていることに気付いたけれども、Dockerでインストールする方向なので、ここではインストールしない。

起動後、タイムゾーンを変えて、更新をかけて再起動。

$ sudo timedatectl set-timezone Asia/Tokyo
$ sudo apt update; sudo apt -y dist-upgrade; sudo apt -y autoremove
$ sudo reboot

SSHを設定。

$ ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/rohhie/.ssh/id_ed25519): [Enter]
Enter passphrase (empty for no passphrase): パスフレーズ[Enter]
Enter same passphrase again: パスフレーズ[Enter]
Your identification has been saved in /home/rohhie/.ssh/id_ed25519

$ cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys

/etc/ssh/sshd_config

…
# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
PasswordAuthentication no
#PermitEmptyPasswords no
…
# Example of overriding settings on a per-user basis
#Match User anoncvs
#       X11Forwarding no
#       AllowTcpForwarding no
#       PermitTTY no
#       ForceCommand cvs server
#PasswordAuthentication yes

※コメントアウトされているのはデフォルト値のようで、Hostkey指定は何もしなくて大丈夫だった。過去ずっと先頭の#を外していた…

設定変更を反映。

$ sudo systemctl restart ssh

ファイアウォールを設定。

$ sudo ufw allow ssh
$ sudo ufw enable

syslogにファイアウォールのブロックログが出るのを好まないので、以下を設定。
/etc/rsyslog.d/20-ufw.conf

& stop

※コメントになっているのを有効にする。

設定変更を反映。

$ sudo systemctl restart rsyslog

固定IPアドレスの場合は、gateway4の指定をちょっとだけ手直し
/etc/netplan/00-installer-config.yaml

# This is the network config written by 'subiquity'
network:
  ethernets:
    ens33:
      addresses:
      - 192.168.110.34/24
      - fdnn:nnnn:nnnn:nnnn:nnnn:nnnn:110:5/64
#     gateway4: 192.168.110.1
      routes:
        - to: default
          via: 192.168.110.1
#       - to: 10.20.20.0/24
#         via: 192.168.110.6
#       - to: default
#         via: fdnn:nnnn:nnnn:nnnn:nnnn:nnnn:110:1
      nameservers:
        addresses:
        - 192.168.110.2
        - fdnn:nnnn:nnnn:nnnn:nnnn:nnnn:110:2
        search:
        - hogeserver.hogeddns.jp
  version: 2

設定変更を反映。

$ sudo netplan apply

アップデートしたときに、デーモンの再起動を確認されるようになったが、自動で再起動してもらう
/etc/needrestart/needrestart.conf

…
# Restart mode: (l)ist only, (i)nteractive or (a)utomatically.
#
# ATTENTION: If needrestart is configured to run in interactive mode but is run
# non-interactive (i.e. unattended-upgrades) it will fallback to list only mode.
#
#$nrconf{restart} = 'i';
$nrconf{restart} = 'a';

自動更新ログチェックは割愛。ログチェックは自分に必要な情報を取り出せるようにカスタマイズしておくのが良いかと。

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コマンドを使っていたけれども、docker composeというサブコマンド形式で使っていくことになる模様。

Apacheのインストール

この手順を確立するまでは、本体をインストールしてテスト、機能を追加してテスト…と、コンテナを作って消すことを繰り返していたのだけれども、インストールしたその瞬間の状態でNextcloudの設定が(ほんのちょっとだけど)変わったりする。

そこで、Nextcloudとアプリが動作するProxy設定を先に入れる。

Apacheをインストール。

$ sudo apt install apache2

ファイアウォールのポート80と443を開ける。

$ sudo ufw allow http
$ sudo ufw allow https

一度、http://nextcloud.hogeserver.hogeddns.jpにアクセスして開通を確認。

問題なければ、デフォルトの設定ファイルを無効化。

$ sudo a2dissite 000-default.conf

公式のページを参考に、NextcloudへのProxy設定を作成。
あわせてCollaboraのProxy設定も入れている。

/etc/apache2/sites-available/nextcloud.conf ※新規作成

<VirtualHost *:80>
    ServerName nextcloud.hogeserver.hogeddns.jp

    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
    RewriteCond %{SERVER_NAME} =nextcloud.hogeserver.hogeddns.jp
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:443>
    ServerName nextcloud.hogeserver.hogeddns.jp

    # Reverse proxy
    RewriteEngine On
    ProxyPreserveHost On
    RewriteRule ^/\.well-known/carddav https://%{SERVER_NAME}/remote.php/dav/ [R=301,L]
    RewriteRule ^/\.well-known/caldav https://%{SERVER_NAME}/remote.php/dav/ [R=301,L]

    # Enable h2, h2c and http1.1
    Protocols h2 h2c http/1.1

    Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"

    # Collabora Online
    AllowEncodedSlashes NoDecode
    # cert is issued for collaboraonline.example.com and we proxy to localhost
    SSLProxyEngine On
    SSLProxyVerify None
    SSLProxyCheckPeerCN Off
    SSLProxyCheckPeerName Off
    # static html, js, images, etc. served from coolwsd
    # browser is the client part of Collabora Online
    ProxyPass           /browser https://127.0.0.1:9980/browser retry=0
    ProxyPassReverse    /browser https://127.0.0.1:9980/browser
    # WOPI discovery URL
    ProxyPass           /hosting/discovery https://127.0.0.1:9980/hosting/discovery retry=0
    ProxyPassReverse    /hosting/discovery https://127.0.0.1:9980/hosting/discovery
    # Capabilities
    ProxyPass           /hosting/capabilities https://127.0.0.1:9980/hosting/capabilities retry=0
    ProxyPassReverse    /hosting/capabilities https://127.0.0.1:9980/hosting/capabilities
    # Main websocket
    ProxyPassMatch      "/cool/(.*)/ws$"      wss://127.0.0.1:9980/cool/$1/ws nocanon
    # Admin Console websocket
    ProxyPass           /cool/adminws wss://127.0.0.1:9980/cool/adminws
    # Download as, Fullscreen presentation and Image upload operations
    ProxyPass           /cool https://127.0.0.1:9980/cool
    ProxyPassReverse    /cool https://127.0.0.1:9980/cool
    # Compatibility with integrations that use the /lool/convert-to endpoint
    ProxyPass           /lool https://127.0.0.1:9980/cool
    ProxyPassReverse    /lool https://127.0.0.1:9980/cool

    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/

    # SSL
    SSLEngine on
    SSLCertificateFile /etc/ssl/private/wild.hogeserver.crt
    SSLCertificateKeyFile /etc/ssl/private/wild.hogeserver.key
</VirtualHost>

※サーバーの証明書と秘密鍵は、自前運営のCAで署名したもの。秘密鍵のパスワードは外してある。
※リバースプロキシサーバーを別に立てているときは、127.0.0.1のところをNextcloudをインストールするサーバーのIPアドレス(or FQDN)に変える。

新規作成した設定を有効化。

$ sudo a2ensite nextcloud.conf

サーバー起動時に出る警告メッセージを防ぐ。

$ echo "ServerName localhost" | sudo tee /etc/apache2/conf-available/fqdn.conf
$ sudo a2enconf fqdn

必要なモジュールを有効にする。

$ sudo a2enmod rewrite proxy proxy_http ssl

設定の確認。

$ sudo apachectl configtest
Syntax OK

Apacheを再起動。

$ sudo systemctl restart apache2

Nextcloudのインストール

Nextcloudのイメージはこちらにある。
Docker Hub / nextcloud
Github / docker-library / docs / nextcloud ※文字数制限のため、こちらにすべてが書かれているとのこと。
Github / nextcloud /docker / .examples

同時にいくつかのコンテナも起動する。
Docker Hub / mariadb
DockerHub / Redis
DockerHub / collabora/code
Dockerhub / coturn / coturn
DockerHub / elasticsearch

作業ディレクトリを作り、いくつかのファイルを作る。

$ mkdir -p ~/work/{nextcloud/script,elastic}
$ cd ~/work

docker-compose.yml ※新規作成 イメージのタグを指定している。Docker Hubでそのときに使えるものに変えること。

version: '3.8'

volumes:
  nextcloud:
  mariadb:
  elastic:

services:
  mariadb:
    image: mariadb:10.8.3-jammy
    container_name: mariadb
    restart: unless-stopped
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    volumes:
      - mariadb:/var/lib/mysql
    networks:
      - nextcloud
    environment:
      - MYSQL_ROOT_PASSWORD=nextcloud
      - MYSQL_PASSWORD=nextcloud
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud

  redis:
    image: redis:7.0.2-alpine
    container_name: redis
    restart: unless-stopped
    networks:
      - nextcloud
    command: >
      --requirepass nextcloud

  collabora:
    image: collabora/code:22.05.3.1.1
    container_name: collabora
    restart: unless-stopped
    ports:
      - 9980:9980
    networks:
      - nextcloud
    environment:
      - password=nextcloud
      - username=nextcloud
      - domain=nextcloud.hogeserver.hogeddns.jp
      - extra_params=--o:ssl.enable=true

  coturn:
    image: coturn/coturn:4.5.2-r12-alpine
    container_name: coturn
    restart: unless-stopped
    ports:
      - 3478:3478
      - 49160-49200:49160-49200
    networks:
      - nextcloud
    command: >
      -n
      --log-file=stdout
      --min-port=49160
      --max-port=49200
      --use-auth-secret
      --static-auth-secret=nextcloud
      --realm=hogeserver.hogeddns.jp

  elastic:
   #image: elasticsearch:7.17.4 ※8は使えないので7の最新
    build: ./elastic
    image: elasticsearch:7.17.4-custom
    container_name: elastic
    restart: unless-stopped
    volumes:
      - elastic:/usr/share/elasticsearch/data
    networks:
      - nextcloud
    environment:
      - "ES_JAVA_OPTSi=-Xms512m -Xmx512m"
      - logger.level=WARN
      - discovery.type=single-node

  nextcloud:
   #image: nextcloud:24.0.1-apache
    build: ./nextcloud
    image: nextcloud:24.0.1-apache-custom
    container_name: nextcloud
    restart: unless-stopped
    depends_on:
      - mariadb
      - redis
      - elastic
    ports:
      - 8080:80
    volumes:
      - nextcloud:/var/www/html
    networks:
      - nextcloud
    environment:
      - MYSQL_PASSWORD=nextcloud
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_HOST=mariadb
      - REDIS_HOST=redis
      - REDIS_HOST_PASSWORD=nextcloud
      - TRUSTED_PROXIES=nextcloud.hogeserver.hogeddns.jp
      - OVERWRITEHOST=nextcloud.hogeserver.hogeddns.jp
      - OVERWRITEPROTOCOL=https
      - TZ=Asia/Tokyo

networks:
  nextcloud:

※極力余計なポートを外に開けないつもりで作ってみた。
※赤文字にしたパスワードはそれっぽい複雑なものにしておくのが良い。

nextcloud/Dockerfile ※新規作成

FROM nextcloud:24.0.1-apache
USER root
RUN apt update && apt install -y libmagickcore-6.q16-6-extra smbclient libsmbclient-dev && \
    pecl install smbclient && \
    docker-php-ext-enable smbclient && \
    sed -Ei 's/(exec "\$@")/\/bin\/su -s \/bin\/bash -c "\/usr\/local\/bin\/turn-on.sh" www-data \&\n\1/' /entrypoint.sh
COPY ./script /usr/local/bin

nextcloud/script/turn-on.sh

#!/bin/bash
/bin/sleep 30
/var/www/html/occ fulltextsearch:stop
/var/www/html/occ fulltextsearch:live --service &

実行権を付けておく。

$ chmod +x nextcloud/script/turn-on.sh

elastic/Dockerfile ※新規作成

FROM elasticsearch:7.17.4
RUN bin/elasticsearch-plugin install --batch ingest-attachment && \
    bin/elasticsearch-plugin install --batch analysis-icu && \
    bin/elasticsearch-plugin install --batch analysis-kuromoji

コンテナを構築・起動する。別のコンソールで実行した。
パラメーターに -d を付けていないので、各サーバーが出力する情報が流れてくる。しばらく様子を見ながら設定を進める。

$ cd work
$ sudo docker compose up --build

コンソールに起動状況が表示される。落ち着いてきたら、サイトにアクセスしてみる。
https://nextcloud.hogeserver.hogeddns.jp

インストール画面が表示されるので、管理者アカウントの情報を入力し、インストールをクリックする。

推奨アプリの表示がされる。ここではキャンセルする。

ログイン後に一通り説明をみたら、設定の管理-概要に進む。

セットアップの警告がいくつか表示されている。

警告は表示されているが、ここまで来ていればインストールはできている。

初期設定

電話地域

デフォルトの電話地域を設定するため、以下のコマンドを実行する。

$ sudo docker exec -u www-data nextcloud php occ config:system:set default_phone_region --value=JP
System config value default_phone_region set to string JP

これで、/var/lib/docker/volumes/work_nextcloud/_data/config/config.php に設定が書き込まれる。

一旦ダッシュボードに戻り、設定の管理-概要を表示させて結果を確かめる。

電話地域の警告が解消できた。

メールサーバー

管理-概要にメールサーバーの警告が残っているので、設定をしていく。

ホームラボのメールサーバーは、LANのサーバーからであれば認証なしでメールが送信できるようになっているが、受信はpostfix-policyd-spf-pythonで送信元を確認している。
このままではNextcloudから発信されたメールが受信できないので、

  • SPFレコードでメールの送信元として nextcloud.hogeserver.hogeddns.jp のIPアドレスを設定
  • SPFチェック対象からIPアドレスを除外

のどちらかを実施しておく必要があった(あくまでもホームラボの話であって、一般的な話ではない)。

今回は、SPFチェック対象からIPアドレスを除外した。
/etc/postfix-policyd-spf-python/policyd-spf.conf

#skip_addresses = 127.0.0.0/8,::ffff:127.0.0.0/104,::1
skip_addresses = 127.0.0.0/8,::ffff:127.0.0.0/104,::1,192.168.110.34

※192.168.110.34を除外。

さて…Nextcloudでadminのメールアドレスを設定する。
設定を開くと、そこでメールアドレスが入力できる。

続いて、設定の管理-基本設定を開くと、メールサーバーの設定がある。

これは、ホームラボで使う設定値。メールサーバーが要求する値はそれぞれ違うだろうから、サーバーに合わせた値を設定する。

設定項目設定値
送信モードSMTP
暗号化なし
送信元アドレスadministrator@hogeserver.hogeddns.jp
認証方法なし
認証を必要とするチェックなし
サーバーアドレスmx.hogeserver.hogeddns.jp
ポート25

設定項目を入力したら、Test and verify email settingsの横にある「メールを送信」を押すと、adminに設定したメールアドレスに「メール設定のテスト」が送信される。
中身は「このメールが見えているということは、メール設定が上手くいっているということです。」というもの。

これで、メールサーバーが設定でき、警告が解消できた。

Collabora

ブラウザでOffice文書を直接編集できるようになる。
既にサーバーはセットアップ済み。

Nextcloudに管理者でログインし、+アプリの Office & テキスト を開き、Collabora Onlineをインストールする。

続けて、設定の管理-Nextcloud Office を開き、自分のサーバーを使用する、を選択。
https://nextcloud.hogeserver.hogeddns.jp と入力し、証明書の検証を無効化する。

Saveはクリックしなくても設定は保存されていた。

Home/Documents/Welcome to Nextcloud Hub.docxを開いてみる。

これは凄い。

なお、ホームラボでOffice文書にアクセスしたところ、以下のログが出力されていた。

[no app in context] 警告: Host 192.168.110.34 was not connected to because it violates local access rules

GET /core/preview?fileId=5440&x=250&y=250
from 172.18.0.1 by E7541AA2-489E-429A-A86A-D7A1B48C3B53 at 2022-07-01T19:56:21+00:00

これを回避するため、ローカルアドレスを持つリモートサーバーを許可する設定 allow_local_remote_servers 指定をconfig.phpに設定する

$ sudo docker exec -u www-data nextcloud php occ config:system:set allow_local_remote_servers --value=true
System config value allow_local_remote_servers set to string true

これで、設定できたと思ったのだが、ファイルを開いて閉じると、以下のメッセージが表示されていることに気付いた。

■ファイルを開いたとき
wsd-00001-00130 2022-07-09 08:56:44.076403 +0000 [ docbroker_007 ] WRN  Waking up dead poll thread [HttpSynReqPoll], started: false, finished: false| net/Socket.hpp:722
wsd-00001-00130 2022-07-09 08:56:44.238295 +0000 [ docbroker_007 ] WRN  Waking up dead poll thread [HttpSynReqPoll], started: false, finished: false| net/Socket.hpp:722

■ファイルを閉じたとき
wsd-00001-00030 2022-07-09 08:56:51.766208 +0000 [ prisoner_poll ] WRN  Prisoner connection disconnected but without valid socket.| wsd/COOLWSD.cpp:3079
sh: 1: /usr/bin/coolmount: Operation not permitted
frk-00031-00031 2022-07-09 08:56:52.328996 +0000 [ forkit ] ERR  Failed to unmount [/opt/cool/child-roots/pB8YbyWmwHgf507c/tmp]| common/JailUtil.cpp:70
sh: 1: /usr/bin/coolmount: Operation not permitted
frk-00031-00031 2022-07-09 08:56:52.341093 +0000 [ forkit ] ERR  Failed to unmount [/opt/cool/child-roots/pB8YbyWmwHgf507c/lo]| common/JailUtil.cpp:70
sh: 1: /usr/bin/coolmount: Operation not permitted
frk-00031-00031 2022-07-09 08:56:52.355114 +0000 [ forkit ] ERR  Failed to unmount [/opt/cool/child-roots/pB8YbyWmwHgf507c]| common/JailUtil.cpp:70

この問題について議論されていて、特権モードにすれば、この問題は発生せずにパフォーマンスが最大化する。特権モードにすることの危険性とのトレードオフ。
特権モードにしなくても動作はする、とされている。
Github / CollaboraOnline / online / In docker log sh: 1: /usr/bin/loolmount: Operation not permitted #779

表示されるタイミングを考えると、そんなに遅くなっているように思えなかったので、エラーメッセージが表示されることを受け入れることにした。

これでCollaboraの設定は完了。

Talk

チャット、ビデオ会議ができるようになる。

Nextcloudに管理者でログインし、+アプリの ソーシャル・コミュニケーション を開き、Talkをインストールする。

Talkをインストールして設定画面を見てみると、STUNとTURNという設定項目が出てきた。
LANだけで使う分には何も設定せずともWeb会議ができるが、インターネットにある端末とWeb会議をするのにTURNサーバーが必要だった。
既にcoTURNサーバーはセットアップ済み。

設定値をみると、STUNサーバーには stun.nextcloud.com:443 が設定されており、このサーバーを使わせていただけるようだ。

TURNサーバーに、nextcloud.hogeserver.hogeddns.jp、Secretにdocker-compose.ymlで指定したstatic-auth-secretの値を設定したところ、テストOKとなった。

高性能バックエンド(Higi-performance backend)は、4人以上の会議でクライアント側に高い負荷が掛かる問題を解消する素晴らしいもののようなんだけれども、今回はパス。

続いて、ルーターの設定。
ホームラボではUFWでルーターを構築しているので、ルーターに以下の設定を追加し、coTURN宛てのパケットをNATする。

/etc/ufw/before.rules

# NAT rules
*nat
:PREROUTING ACCEPT [0:0]
…
-A PREROUTING -i ppp0 -p tcp --dport 3478 -j DNAT --to-destination 192.168.110.34
-A PREROUTING -i ppp0 -p udp --dport 3478 -j DNAT --to-destination 192.168.110.34
-A PREROUTING -i ppp0 -p tcp --dport 49160:49200 -j DNAT --to-destination 192.168.110.34
-A PREROUTING -i ppp0 -p udp --dport 49160:49200 -j DNAT --to-destination 192.168.110.34
…

新しいルールを反映し、転送を許可。

$ sudo ufw reload

$ sudo ufw route allow in on ppp0 out on ens160 to 192.168.110.34 port 3478 proto tcp
$ sudo ufw route allow in on ppp0 out on ens160 to 192.168.110.34 port 3478 proto udp
$ sudo ufw route allow in on ppp0 out on ens160 to 192.168.110.34 port 49160:49200 proto tcp
$ sudo ufw route allow in on ppp0 out on ens160 to 192.168.110.34 port 49160:49200 proto udp

利用しているルーター機器によって設定は違ってくるだろうと思うけれど、ウチの場合はこれで上手く動いた。
AWSのEIPを使う場合には、coTURNの起動パラメーターにexternal-ipというのを使うと良いらしいのだが、使っていないのでメモだけ残しておく。
Nextcloud Talk API documentation / Configuring coTURN

ダッシュボードに戻ると、「トークでの言及(メンションのこと?)」が表示されるようになっており、Talkのアップデートについてのメッセージを読むことができた。
ユーザーを追加した後、LANの中のPCと、とあるキャリアの回線につながったAndroid端末で会議ができるところまで確認できた。

Elasticsearch

全文検索ができるようになる。
既にサーバーはセットアップ済み。

Nextcloudに管理者でログインし、+アプリの検索にある以下をインストールした。

  • Full text search
  • Full text search – Elasticsearch Platform
  • Full text search – Files

ここで、設定の管理-全文検索で、Elasticksearchを設定する。
ユーザーから直接アクセスしないサービスのため、ポートを公開していないので、Docker内部で使えるホスト名を指定している。

項目設定値
検索プラットフォームElasticsearch(選択肢はこれだけ)
サーブレットのアドレスhttp://elastic:9200
インデックスnextcloud
アナライザ トークナイザstandard

画面からの設定を終えたら、nextcloudコンテナに入り、コマンドを実行して、動作を確認。

$ sudo docker exec -it -u www-data nextcloud /bin/bash --login
$ ./occ fulltextsearch:test

全部OKとなったので、インデックスを作ってみる。

$ ./occ fulltextsearch:index

全ファイルのインデックスを作り直す場合は、以下を実行。
(Elasticsearchのコンテナを作り直した時に、リセットしないとインデックスを作り直すことができなかった)

$ ./occ fulltextsearch:stop
$ ./occ fulltextsearch:reset
$ ./occ fulltextsearch:index

これで、検索窓に文字を入れてみると、全文検索の結果を表示してくれる。

この後「ファイルが追加されたらインデックス」が追加されるようにする。
具体的には、以下のコマンドでliveをデーモンモードで走らせておく必要があるのだが…
Nextcloud / Community / How do I run occ “fulltextsearch:live” as a service?

./occ fulltextsearch:live --service &

コンテナが起動したときに、このコマンドを実行するように仕掛けてあるので、ここでコンテナを再起動してみる。

$ logout
$ sudo docker restart nextcloud

起動後、もう一度コンテナに入り、デーモンモードでコマンドが動作していることを確認する。

$ sudo docker exec -it -u www-data nextcloud /bin/bash --login
$ ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.1  0.9 270020 39324 ?        Ss   07:26   0:00 apache2 -DFOREGROUND
www-data      42  0.0  0.2 270060  9728 ?        S    07:26   0:00 apache2 -DFOREGROUND
www-data      43  0.0  0.2 270060  9728 ?        S    07:26   0:00 apache2 -DFOREGROUND
www-data      44  0.0  0.2 270060  9728 ?        S    07:26   0:00 apache2 -DFOREGROUND
www-data      45  0.0  0.2 270060  9728 ?        S    07:26   0:00 apache2 -DFOREGROUND
www-data      46  0.0  0.2 270060  9728 ?        S    07:26   0:00 apache2 -DFOREGROUND
www-data      47  0.8  1.7 173756 69736 ?        S    07:27   0:00 php /var/www/html/occ fulltextsearch:live --service
www-data      54  0.7  0.0   4100  3364 pts/0    Ss   07:28   0:00 /bin/bash --login
www-data      61  0.0  0.0   6700  2928 pts/0    R+   07:28   0:00 ps aux
$ logout

適当なExcelブックを放り込んで、ブック内にある文言を検索ボックスに入れ、放り込んだファイルが検索結果として表示されれば設定完了。

ロケールと言語

LDAP認証で作られたユーザーの言語は日本語になっていた。でも、管理者アカウントでユーザーを作ってみたら英語になっていた。
デフォルトの言語を日本語にする
また、LDAP認証で作られたユーザーも、管理者アカウントで作られたユーザーも、ロケールがEnglish (United States)になっていた。

デフォルトを、日本語・日本ロケールにする。

$ sudo docker exec -u www-data nextcloud php occ config:system:set default_language --value=ja
$ sudo docker exec -u www-data nextcloud php occ config:system:set default_locale --value=ja_JP

外部ストレージのマウント

ホームラボにあるSambaサーバーの共有フォルダをNextcloudで共有したくなった。
家族写真などのURLを作り、親族と共有できれば便利。
Qiita / Nextcloud の外部ストレージ連携

Nextcloudに管理者でログインし、+アプリで無効なアプリ-External storage supportを有効にする。
※本当はカテゴリーの中から見つけたかったのだけれど、どうにも見つからない。無効になっていたアプリのところで見つかった。

設定の管理-外部ストレージで、必要情報を入力していく。
このサーバーはUbuntu+Sambaで構成されており、ゲストアクセスも許可しているが、このアプリではゲストアクセスは許されないようだった。
仕方がないので、共有用のユーザーを作って接続することにした。

設定が終わったところで、右側のチェックマークをクリックすると接続が始まり、フォルダー名(今回はWinShare)の左側に緑のチェックマークが表示されれば設定完了。

最初、smbclientがインストールされていない、というエラーが表示されたが、この設定方法を教えてくれた人がいた
コンテナを作成するDockerfileで、教えてくれた方法を使って必要モジュールをインストールしている。

なお、「読み取り専用」にしなければファイルを追加したり、書き換えたりすることができ、書き換えれば履歴も取られる。
ただ、Wordの文書を更新してみたらSambaから更新ができなくなっていたので、Sambaでの使用を取りやめるのでない限り、読み取り専用にしておいた方が良いのかなと思った。

再起動と動作確認

ここまで、1つのターミナルがずっとコンテナの状況を表示していた。
ここで一旦コンテナを止め、改めて起動する(起動した状態で再起動しないと、コンテナが再起動するようになっていないから)。

$ sudo docker compose up -d

問題なく動作したので、サーバーを再起動。

$ sudo reboot

再起動後も問題なく動作するようなら設定完了。

for Desktop

デスクトップ版のアプリケーションがあるので、ダウンロードしてインストールしてみる。
この日にダウンロードしてきたのは、Windows用のNextcloud-3.5.1-x64.msiだった。

インストール後に再起動を求められたので、再起動した。

再起動後に、Nextcloudを起動してみる。

デフォルトのままで進んだところ、C:\Users\<ユーザー名>\Nextcloudに同期用のフォルダが作られ、ファイルのエントリーだけが作られた。
保存してあったExcelブックをダブルクリックしてみたところ、ファイルが取り込まれて、ファイルが開いた。
編集して保存すると、サーバーのファイルが更新され、履歴も取られていた。

これは良い!さぁ、色々と試してみよう!

Nextcloud内でファイルの移動をしてみたところ、移動の履歴が取られた。

ファイルを削除してみたところ、Windowsでゴミ箱に入り、Nextcloudでもゴミ箱に入った。
Windowsのゴミ箱からファイルを復元すると、Nextcloudのゴミ箱にファイルは入ったままで、新しいファイルが作られた。
これは、理想ではないかもしれないが、納得の動作であった。

メインダイアログで検索文字列を入力すると、ファイルが検索できる。
ファイル名で表示された検索結果にはプレビューが表示され、クリックするとブラウザでファイルが開かれる。
全文検索の結果も表示されるが、こちらはクリックしても何も動作しなかった。とはいえ、ファイル名が分かるので、どうにかアクセスはできるだろうし、どうしてもブラウザで開きたいなら、ブラウザでNextcloudにアクセスすれば良いので、あまり困ることはなさそうだった。

とても便利に使えそうだ。

バックアップとリストア

Nextcloudは便利に使えそうなので、使用頻度が上がりそう。
バックアップはいままでより重要になるから、きっちり手順を整理しよう。リストアの手順も確立しておきたい。

イメージのバックアップ

どうやら、Nextcloudは割とアップデートが頻繁に行われるようだ。
いざ復元!と考えたときに、当該のイメージがないからと泣かずに済むように、使っているイメージをバックアップしておきたいと考えた。

$ sudo docker save -o backup/mariadb_10.8.3-jammy.tar mariadb:10.8.3-jammy
$ sudo docker save -o backup/redis_7.0.2-alpine.tar redis:7.0.2-alpine
$ sudo docker save -o backup/collabora_code_21.11.5.3.1.tar collabora/code:21.11.5.3.1
$ sudo docker save -o backup/coturn_coturn_4.5.2-r12-alpine.tar coturn/coturn:4.5.2-r12-alpine
$ sudo docker save -o backup/elasticsearch_7.17.4.tar elasticsearch:7.17.4
$ sudo docker save -o backup/nextcloud_24.0.1-apache.tar nextcloud:24.0.1-apache

ファイルサイズはこうなっていた。

ファイルサイズ
mariadb_10.8.3-jammy.tar372MB
redis_7.0.2-alpine.tar29MB
collabora_code_21.11.5.3.1.tar1.5GB
coturn_coturn_4.5.2-r12-alpine.tar30MB
elasticsearch_7.17.4.tar606MB
nextcloud_24.0.1-apache.tar867MB

保険と考えれば、このくらいのサイズになるのは仕方がないかな。

ボリュームのバックアップ

Nextcloudはバックアップ機能を用意してくれているのだけれど、Dockerでボリュームのバックアップをするならどうするのか、というところを整理してみた。

$ sudo docker volume ls
DRIVER    VOLUME NAME
local     1a791d857a30d30fdff401a3b65e60dd55f7833e7549396af3fb52bd5b268e04
local     8f19887cd255dcfa0249d2207fc97a815b091d57b93b94db6400b514ba8b78ef
local     work_elastic
local     work_mariadb
local     work_nextcloud

バックアップを取っておきたいのは、NextcloudとMariaDB、Elasticsearch。

$ sudo docker volume inspect work_nextcloud | grep Mountpoint
        "Mountpoint": "/var/lib/docker/volumes/work_nextcloud/_data",
$ sudo docker volume inspect work_mariadb | grep Mountpoint
        "Mountpoint": "/var/lib/docker/volumes/work_mariadb/_data",
$ sudo docker volume inspect work_elastic | grep Mountpoint
        "Mountpoint": "/var/lib/docker/volumes/work_elastic/_data",

Tarで固めておこう。

$ sudo docker compose stop ※Nextcloudが稼働しているなら止めておく。

$ sudo tar -zcvf backup/work_nextcloud.tar.gz /var/lib/docker/volumes/work_nextcloud/_data
$ sudo tar -zcvf backup/work_mariadb.tar.gz /var/lib/docker/volumes/work_mariadb/_data
$ sudo tar -zcvf backup/work_elastic.tar.gz /var/lib/docker/volumes/work_elastic/_data

ほとんどファイルは保管していない状態だけれども、サイズはこのくらいになっていた。

ファイルサイズ
work_nextcloud.tar.gz220MB
work_mariadb.tar.gz8.9MB
work_elastic.tar.gz38MB

環境を全部消去

動作させるコンテナを増やすタイミングで、一旦すべてを消してやり直し…を、何度も試している。
今回はリストアの手順も整理したかったので、一旦、環境をまるごと消してしまう。
※本当に全部消えてしまうので、本番環境で実行してはいけない。

このコマンドでコンテナが消える。

$ sudo docker compose down

他のコンテナやイメージを消す。

$ sudo docker container rm <コンテナ名>
$ sudo docker image rm <コンテナ名>
等々

未使用の色々を削除。

$ sudo docker container prune
$ sudo docker image prune
$ sudo docker volume prune

最後の docker volume prune でボリュームが消える=登録されているデーターが全部消えるので注意。

リストア

イメージ、ボリュームのバックアップを作り、すべてを消したので、リストアの手順を試してみる。

まずは、イメージをリストアしてみる。

$ sudo docker load -i backup/mariadb_10.8.3-jammy.tar
$ sudo docker load -i backup/redis_7.0.2-alpine.tar
$ sudo docker load -i backup/collabora_code_21.11.5.3.1.tar
$ sudo docker load -i backup/coturn_coturn_4.5.2-r12-alpine.tar
$ sudo docker load -i backup/elasticsearch_7.17.4.tar
$ sudo docker load -i backup/nextcloud_24.0.1-apache.tar

※ElasticsearchとNextcloudはレイヤーもなく、静かにloadが終了した。

続いて、ボリュームをリストアしてみる。

$ sudo tar -zxvf backup/work_nextcloud.tar.gz -C /
$ sudo tar -zxvf backup/work_mariadb.tar.gz -C /
$ sudo tar -zxvf backup/work_elastic.tar.gz -C /

起動に使っていた、docker-compose.ymlで起動してみる。

$ sudo docker compose up -d --build

インターネットからイメージを読み込むこともなくコンテナ達が起動し、データーも完全に復元された。
Dockerのこの仕組みを作った開発者と、それを完全に活かしきる各イメージの開発者達はホントにスゴい。

Nextcloudが、停止時間の少ないバックアップツールを開発してくれているようだけれども、ホームラボは夜中ほとんど動かない。
なので、コンテナを止めてボリュームをバックアップ(=フルバックアップ)し、終わったらコンテナを立ち上げれば良いかなと思った。

その他

色々とセットで動くようなやり方をしたので、

  • docker-compose.ymlと、そこから呼び出すDockerfile、スクリプト。
  • Apacheのnextcloud.conf(Proxy設定)

も重要なバックアップの対象となる。イチから書けといわれたらとても面倒なので、しっかりバックアップしておこう。

バージョンアップ

バージョンアップの仕組み

Dockerで環境構築するとき、/var/lib/docker/volumes/work_nextcloud/_data にプログラム本体が置かれており、ここがvolume指定されている。
実際、アップデートってどんな風にされるのだろうか。

結論からすると、コンテナが作られて起動したときに、volumeに入っているNextcloudのバージョンがチェックされ、コンテナのものより古いとわかるとアップデートが行われるようだ。起動直後のコンテナに入ってプロセスを確認してみたら、rsyncコマンドが動作していた。
更新が終わると、turn-on.shが動作していた。なるほど、更新後にコンテナが再起動するように仕掛けがなされているのだろう。

動きを見るために、試験環境をいったんきれいにする。

$ sudo docker compose down
$ sudo docker volume prune

※下の行でボリュームが消えるので、本番環境でやってはいけない…。

現在、22.2.9というバージョンがあったので、これで環境を構築してみる。

work/nextcloud/Dockerfile

FROM nextcloud:22.2.9-apache
USER root
…

docker-compose.yml

…
  nextcloud:
   #image: nextcloud:22.2.9-apache
    build: ./nextcloud
    image: nextcloud:22.2.9-apache-custom
    container_name: nextcloud
…

Nextcloud 22.2.9 を起動。

$ sudo docker compose up -d --build

インストール画面は最新のものと同じだった。
ガチャガチャと操作していたら、23.0.6が利用可能であると教えてくれるようになった。

「アップデーターを開く」をクリックしたが、画面がダッシュボードに遷移するだけだった。

そこで、公式の手順に従い、コンテナーを停止し、nextcloudを削除する。

$ sudo docker compose stop
$ sudo docker container rm nextcloud

イメージのバージョンを、教えてくれているものに置き換えてみる。

work/nextcloud/Dockerfile

FROM nextcloud:23.0.6-apache
USER root
…

docker-compose.yml

…
  nextcloud:
   #image: nextcloud:23.0.6-apache
    build: ./nextcloud
    image: nextcloud:23.0.6-apache-custom
    container_name: nextcloud
…

起動の仕方がちょっと分からなかったけれど、とりあえずこれで。

$ sudo docker compose up -d --build
$ sudo docker ps -a
CONTAINER ID   IMAGE                            COMMAND                  CREATED          STATUS          PORTS                                                                     NAMES
699d2acad565   nextcloud:24.0.1-apache-custom   "/entrypoint.sh apac…"   29 seconds ago   Up 23 seconds   0.0.0.0:8080->80/tcp, :::8080->80/tcp                                     nextcloud
0ac92afc59c6   coturn/coturn:4.5.2-r12-alpine   "docker-entrypoint.s…"   24 minutes ago   Up 24 seconds   3478/udp, 5349/udp, 0.0.0.0:3478->3478/tcp, :::3478->3478/tcp, 5349/tcp   coturn
a3dd4d865c82   redis:7.0.2-alpine               "docker-entrypoint.s…"   24 minutes ago   Up 24 seconds   6379/tcp                                                                  redis
2c94d164a715   mariadb:10.8.3-jammy             "docker-entrypoint.s…"   24 minutes ago   Up 24 seconds   3306/tcp                                                                  mariadb
1e88d9e3e523   collabora/code:21.11.5.3.1       "/start-collabora-on…"   24 minutes ago   Up 25 seconds   0.0.0.0:9980->9980/tcp, :::9980->9980/tcp                                 collabora
288e3de036fc   elasticsearch:7.17.4-custom      "/bin/tini -- /usr/l…"   24 minutes ago   Up 24 seconds   9200/tcp, 9300/tcp                                                        elastic

※コンテナが作られた時間を見ると、大丈夫そうだと分かる。

これで、設定の管理-概要を見に行ったら、バージョンが新しくなっていた。

メンテナンスもしやすいし、アップデートもしやすい、本当によく考えられた仕組みだと思った。

メジャーバージョンアップ

バージョンアップの方法は分かったので、23.0.6でメールサーバー設定をして、Talk、Collabora、Elastic searchが動作するようにした。
これが24.0.2でも問題なく動作するか、試してみる。

$ sudo docker compose stop
$ sudo docker container rm nextcloud

イメージのバージョンを、書かれているものに置き換えてみる。

work/nextcloud/Dockerfile

FROM nextcloud:24.0.2-apache
USER root
…

docker-compose.yml

…
  nextcloud:
   #image: nextcloud:24.0.2-apache
    build: ./nextcloud
    image: nextcloud:24.0.2-apache-custom
    container_name: nextcloud
…

コンテナを起動。

$ sudo docker compose up -d --build

22→23と挙動が少し違う。
起動はしたのだけれど、アクセスするとメンテナンスモードと表示され、いつまで経っても解消されない。

メンテナンスモードを解除してみる

$ sudo docker exec -u www-data nextcloud php occ maintenance:mode --off
Nextcloud or one of the apps require upgrade - only a limited number of commands are available
You may use your browser or the occ upgrade command to do the upgrade
Maintenance mode disabled

すると、ブラウザの画面が再表示された。

バックアップを取っておくように書かれている。
確かに、本番環境をアップデートするときは、バックアップをしっかり取っておくべき。
今回は、試験環境なので、無視してそのまま進めていく。

アップデートを開始ボタンをクリックしようと思ったが、大規模サイトの場合にタイムアウトする場合があると書かれている。
コマンドでやってみよう。

$ sudo docker exec -u www-data nextcloud php occ upgrade
Nextcloud or one of the apps require upgrade - only a limited number of commands are available
You may use your browser or the occ upgrade command to do the upgrade
Setting log level to debug
Turned on maintenance mode
Updating database schema
Updated database
Starting code integrity check...
Finished code integrity check
Update successful
Turned off maintenance mode
Resetting log level

コマンド終了後に、https://nextcloud.hogeserver.hogeddns.jpにアクセスしたところ、ログイン画面が出てきた。
バージョンアップは成功したようだ。

ただ、ログインしたところ、Talkが無効になっていた。
そして、設定の管理-概要を表示させてみると、データーベースにいくつかのインデックスがないと表示されていた。

書いてあるコマンドを実行してみる。

$ sudo docker exec -u www-data nextcloud php occ db:add-missing-indices
Check indices of the share table.
Check indices of the filecache table.
Check indices of the twofactor_providers table.
Check indices of the login_flow_v2 table.
Check indices of the whats_new table.
Check indices of the cards table.
Check indices of the cards_properties table.
Check indices of the calendarobjects_props table.
Check indices of the schedulingobjects table.
Check indices of the oc_properties table.
Check indices of the oc_jobs table.
Check indices of the oc_direct_edit table.
Adding direct_edit_timestamp index to the oc_direct_edit table, this can take some time...
oc_direct_edit table updated successfully.

oc_direct_editというテーブルがなかったようだ。

これで、管理-概要を再度表示させてみると、問題が解消されており、24.0.2になっていた。

Talkが無効化していることはダッシュボードで分かったが、確認してみるとCollabora、Elasticsearchも無効化していた。

Talkは、14.0.2にアップデート、未テストのアプリを有効にすることで復旧。
Collaboraは、Nextcloud Officeを6.1.0にアップデート、未テストのアプリを有効にして復旧。

Elasticsearchについては、Full text searchを有効にし、さらに、Full text search – Elasticsearch Platformを24.0.0にアップデート、未テストのアプリを有効にする。
そして、管理-全文検索で、検索プラットフォームにElasticsearchを選択し直して復旧。

インデックス作成用のデーモンが動いていないので、nextcloudコンテナを再起動する。

$ sudo docker restart nextcloud

若干の再設定が必要ではあったものの、バージョンアップができた。
「未テストのアプリ」の問題はは、事前にアプリをアップデートしておけば解消できるかもしれない。

マイナーバージョンアップ

結論からすると、メジャーバージョンアップとやることは一緒だった。

一旦、試験環境をきれいにして、バージョン22をインストールし、23にバージョンアップした。
23→24にバージョンアップする際、24.0.1にアップデートしてみた。

24.0.1→24.0.2へのマイナーバージョンアップの準備ができたので、アップデートしてみる。
コンテナを全部止めて、nextcloudを削除する。

$ sudo docker compose stop
$ sudo docker container rm nextcloud

イメージのバージョンを、書かれているものに置き換えてみる。

work/nextcloud/Dockerfile

#FROM nextcloud:24.0.1-apache
FROM nextcloud:24.0.2-apache
USER root
…

docker-compose.yml

…
  nextcloud:
   #image: nextcloud:24.0.2-apache
    build: ./nextcloud
    image: nextcloud:24.0.2-apache-custom
    container_name: nextcloud
…

コンテナを起動。

$ sudo docker compose up -d --build

このマイナーバージョンアップでは、23→24のような挙動にはならず、ログイン画面が出てきたが、CollaboraとTalkが無効化していたので、有効化して復旧。
なお、最初のインストールがNextcloud 24.0.1、そこから24.0.2にバージョンアップした際には、この問題は発生しなかった(本番環境)。

セキュリティチェック

確立した手順で本番環境を作り、インターネットにサービスを公開した。

  • 必要なときに、PCやスマホからデーターがみられる。
  • 誰かとサイズの大きなファイルをやりとりをするときに使える。

がメリットだけれども、当然、リスクはある。

管理-概要にあるセキュリティスキャンのリンクをクリックしてみたところ、診断してくれるサイトが表示された。
URL欄にサービス公開したURL(https://nextcloud.my.domain)を入力してみた。

ランクはA。24.0.1の時に一度診断してAになったが、そのときの結果が再表示されている。
この時点で24.0.2というバージョンが出ていたので、最新ではないことがA+にならない理由だった。

診断結果の下にある trigger re-scan を押してみたところ、5分後に再チェックしてくれるようだ。

5分後、結果はA+となった。だから安心!ということではない、この診断サイトが認識している課題はクリアできている、ということ。
十分に注意してサイト運営していこう。

ホームラボでやることあれこれ

LDAP認証

NextcloudはOAuth 2.0が使えるみたいだった。

ホームラボでは、Samba ad dcが稼働しており、これがLDAPサーバーになっている。
Keycloakも動いているのでOAuth 2.0でできないことはないのだけれど、それはホームラボのシステム全部を一気に変える日までお預け。
とりあえず、LDAP認証を設定していく。

Nextcloudに管理者でログインし、+アプリのアプリバンドル-エンタープライズバンドルにあるLDAP user and group backendを有効にする。

続いて、設定からLDAP/AD統合へと進み、設定していく。

タブ:サーバー

設定項目設定値
ホストaddc.hogeserver.hogeddns.jp
ポート389
本当はLDAPS(636)を使いたいが、ホームラボのCA証明書を恒久的にインストールする必要がある。
できないことはないけれど、今回はパス。
ユーザーDNCN=ssoauth,CN=Users,DC=hogeserver,DC=hogeddns,DC=jp
パスワードssoauthのパスワード
ベースDNCN=users,DC=hogeserver,DC=hogeddns,DC=jp

タブ:ユーザー

設定項目設定値
このオブジェクトクラスからのみperson
これらのグループからのみFamily(家族が登録されているグループ)
LDAPクエリの編集空っぽにすると自動設定される

タブ:ログイン属性

設定項目設定値
LDAP/ADユーザー名チェック
LDAP/ADメールアドレスチェックなし
その他の属性選択なし
LDAPクエリの編集空っぽにすると自動設定される

タブ:グループ

設定項目設定値
このオブジェクトクラスからのみgroup
これらのグループからのみ同期したいグループを選択
LDAPクエリの編集空っぽにすると自動設定される

ところがですね…登録済みの家族のユーザーがどうやっても表示されない。
で、たまたま親族のユーザーが表示されたりしたので(ラッキー!)、違いを埋めてみて、原因をはっきりさせる。

$ sudo samba-tool user edit <account name> -U <admin user>

※この環境ではvimが起動してくる。

表示された属性にdisplayNameがなかったので追加し、このサーバーを利用可能なユーザーを確かめる。
 ユーザーのアクティブユーザー数
これでユーザーが表示された。

ちゃんとした検索条件を書くことができれば、利用者だけを同期させることができそうだが、登録ユーザー数が少ないので、とりあえず利用予定のない人は「無効なユーザー」としておいた。

スクリプトによるファイル登録

ホームラボにはブラザー製の家庭用複合機があり、スキャンしたら共有サーバーに保管される仕組みを構築済み。
そして、保管したPDFファイルをAlfrescoに登録する仕組みも構築してあったので、スキャンするだけで外出先でそれを読むことができた。
これと同じことをNextcloudでもできるようにしたい。

Nextcloudでは、curlでアップロードできるとのこと。
世界Linux新聞 / nextcloudにcURLでファイルをアップロード/ダウンロードする方法

$ curl -X PUT -u admin:<password> \
https://nextcloud.hogeserver.hogeddns.jp/remote.php/dav/files/admin/Documents/ \
-T ./memo.txt

アップロード先に同名のファイルが存在する場合、上書きされる。というか、改版されて、新しいバージョンになる。

最初、登録先の最後にスラッシュを入れなかったらエラーが出た。
何かの役に立つかもしれないのでメモしておく。

$ curl -X PUT -u admin:<password> \
https://nextcloud.hogeserver.hogeddns.jp/remote.php/dav/files/admin/Documents \
-T ./memo.txt
<?xml version="1.0" encoding="utf-8"?>
<d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns">
  <s:exception>Sabre\DAV\Exception\Conflict</s:exception>
  <s:message>PUT is not allowed on non-files.</s:message>
</d:error>

問題への対処

インストールしては問題発生、修正しては問題発生、の繰り返しだった。
ここに発生した問題と対処を整理しておく。

アプリのカテゴリが見えない

日頃使っている回線はまぁまぁ速いのだが、サービスを公開する回線は遅い…かなり遅い。
本番環境は遅い回線を使っており、+アプリの画面を表示してみたら、アプリのカテゴリが見えなかった。

このことに触れているブログがあり、確認してみたところ、カテゴリの情報をダウンロードするときに60秒を超えてしまい、タイムアウトしていることが分かった。
世界Linux新聞 / nextcloudでアプリ一覧が表示されない場合の対処方法

[appstoreFetcher] 警告: Could not connect to appstore: cURL error 28: Operation timed out after 60000 milliseconds with 3725148 bytes received (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://apps.nextcloud.com/api/v1/apps.json

GET /settings/apps
from 172.18.0.1 by E7541AA2-489E-429A-A86A-D7A1B48C3B53 at 2022-07-03T03:54:20+00:00

コンテナの中に入ってcurlしてみたところ、あからさまに遅い…

コードの中で直接タイムアウト時間を延ばし、解決することもできるようだが、apps.nextcloud.com宛てのルーティングを速い回線に向けることで問題解消した。
レスポンスが早い方がいいかなと。
もし、宛先のIPアドレスが変わるようなことがあったら、そのときにはまたルーティングを修正しよう。

全文検索のインデックス作成で問題発生

何度もコンテナを作り直したが、その中で、何かを契機に発生し、その後はどうしても解消できない問題があった。
24.0.1で発生する問題で、24.0.2でも発生する模様。
Nextcloud community / NC24 + EL7: Error: Call to a member function getUID() on null

$ ./occ fulltextsearch:index
…
An unhandled exception has been thrown:
Error: Call to a member function getUID() on null in /var/www/html/custom_apps/files_fulltextsearch/lib/Service/FilesService.php:449
Stack trace:
#0 /var/www/html/custom_apps/files_fulltextsearch/lib/Service/FilesService.php(324): OCA\Files_FullTextSearch\Service\FilesService->generateFilesDocumentFromFile('1722A895-8F0A-4...', Object(OC\Files\Node\File))
#1 /var/www/html/custom_apps/files_fulltextsearch/lib/Provider/FilesProvider.php(269): OCA\Files_FullTextSearch\Service\FilesService->getFilesFromUser('1722A895-8F0A-4...', '/Enjoy/(1) CPU-...')
…

これで問題解消。
Github / nextcloud / fulltextsearch / Error indexing getUID() null

念のためにバックアップを取っておく。

$ sudo cp -ar /var/lib/docker/volumes/work_nextcloud/_data/custom_apps/files_fulltextsearch/lib/Service/FilesService.php \
/var/lib/docker/volumes/work_nextcloud/_data/custom_apps/files_fulltextsearch/lib/Service/FilesService.php.org

/var/lib/docker/volumes/work_nextcloud/_data/custom_apps/files_fulltextsearch/lib/Service/FilesService.php

… 449行目
                $document->setAccess(new DocumentAccess($file->getOwner()->getUID()));
…

※打ち消し線の部分を削除。

この後、以下を実行して、問題が解消できた(ファイル数が多ければ時間が掛かるので注意)。

$ sudo docker exec -it -u www-data nextcloud /bin/bash --login
$ ./occ fulltextsearch:stop
$ ./occ fulltextsearch:reset
$ ./occ fulltextsearch:index

※インデックスができたらliveプロセスを起動
$ ./occ fulltextsearch:live --service &

全文検索のインデックスが作られない

手順を整理している過程で、Excelブックを登録しても、インデックスが登録されない症状が発生…。
fulltextsearch:liveは起動しているが、上手く動けていないようだ。

以下を実行してみたところ、インデックスが登録されるようになった。

$ sudo docker exec -it -u www-data nextcloud /bin/bash --login
$ ./occ fulltextsearch:stop
$ ./occ fulltextsearch:index
$ ./occ fulltextsearch:live --service &

この問題が発生する原因は、

$ ./occ fulltextsearch:live --service &

を実行する前に、

$ ./occ fulltextsearch:stop

を実行していないことだった。

liveを実行する時に、何か不揮発な情報を書き込んでいるのではないかと想像されたが、原因を突き止めることはしていない。
コンテナ起動時に実行される /entrypoint.sh から呼び出されるように仕込んだスクリプトに stop を入れた。

Sambaが遅い

Samba共有で、ファイルが大量に入ったフォルダがいくつかあり、サーバーがうなりを上げていた。前々から、Sambaが遅い遅いと思っていたのだけれど…
のふ処(旧クソゲ~製作所)/ Samba 4.6のファイルコピーがCPU 100%近く使い超絶遅い件
大文字・小文字を区別せずに扱うための処理で強烈にCPUを食われてしまうようだった。

この設定による副作用はあるし、Sambaとしてはサポートしない設定のようなんだけれども、Sambaが動作しているサーバーが重くなりすぎてまともに使えなくなってしまうことの方が痛い、とこの時は思ったので、教えてくれた指定を入れた。

Samba_Server : /etc/samba/smb.conf

[global]
…
    case sensitive = yes

設定反映。

$ sudo systemctl restart smbd

どうにか実用的な速度で動作するようになった。

でもね、ファイル名の大文字小文字を変えることがありました、今日。
Excelのアドインを作って、hogehogeAddin.xlamとしたわけです。でも、Add
inじゃなくて、AddInな訳ですよ、Microsoftのサイトでみると。
で、ローカルでファイル名を変えたところで、あ、このSambaの設定ヤバい…と気付く。

ということで、さっきの設定変更は諦めて、全文検索で外部ストレージのインデックスを取るのを止めた。

Windows Serverなら、きっとこんな問題に悩むことはない。
Sambaの場合は、ファイル数の多いフォルダがあるなら、インデックスは諦めるのが正解なのだろうと思う。

手順が確立するまでにやったこと

手順を確立するまでにやったことが色々あったので、将来どこかで似たようなことが起きたときのために、メモとして書き残しておく。

Proxyなしではじめると起きること

NextcloudのDockerイメージがどう動くのか見てみたいと考えた。
まず、基本機能のみを動かしてみよう。

docker-compose.yml

version: '2'

volumes:
  nextcloud:
  db:

services:
  db:
    image: mariadb:10.8.3-jammy
    restart: always
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    volumes:
      - db:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=nextcloud
      - MYSQL_PASSWORD=nextcloud
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud

  app:
    image: nextcloud:24.0.1-apache
    restart: always
    ports:
      - 8080:80
    links:
      - db
    volumes:
      - nextcloud:/var/www/html
    environment:
      - MYSQL_PASSWORD=nextcloud
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_HOST=db

※バージョンをきっちりと指定してみた。頻繁にバージョンアップするみたいなので、手順を確立するまでは変化を極力止めたい。

起動。

$ sudo docker compose up

http://nextcloud.hogeserver.hogedns.jp:8080 にアクセスしたところ、インストール画面が表示された。
管理者アカウントとなるユーザーとパスワードを入力してインストールをクリックすると、初期設定が行われ、ログイン画面が表示される。

設定の管理-概要をみたところ、セットアップに関する警告がいくつか書かれている。
やはり、HTTPでのアクセスは不安と見なされるようだ。

で、この後にApacheでProxy設定して、今度は https://nextcloud.hogeserver.hogedns.jp に接続してみたところ、こんな画面が表示された。

これは、最初にアクセスしたときにtrusted_domainsの設定にポート指定が入ったため、別のポートでのアクセスを攻撃と捉えたことが原因だった。

ポート指定を削除してみる。
/var/lib/docker/volumes/work_nextcloud/_data/config/config.php

…
  'trusted_domains' =>
  array (
    0 => 'nextcloud.hogeserver.hogeddns.jp:8080',
  ),
…

これで問題は解消できたのだけれど、やっぱり手順をしっかりと整理して、こういった余計な設定が入らないようにすべきだと考えた。
それで、本編では先にApacheのProxy設定を作っている。

Proxyの設定が足りなくて表示された警告

trusted_domainsのポート指定を削除したところ、ログインできるようにはなったが、別の警告が表示された。

The reverse proxy header configuration is incorrect, or you are accessing Nextcloud from a trusted proxy. If not, this is a security issue and can allow an attacker to spoof their IP address as visible to the Nextcloud. Further information can be found in the documentation ↗.
リバースプロキシヘッダーの構成が正しくないか、信頼できるプロキシからNextcloudにアクセスしています。そうでない場合、これはセキュリティに問題があり、攻撃者がNextcloudを表示できるようにIPアドレスを偽装することができます。詳細については、ドキュメント↗をご覧ください。

これは、trusted_proxies、overwritehost、overwriteprotocolの設定を追加したことで表示されなくなった。
本編では、コマンドでこの値を設定している。

/var/lib/docker/volumes/work_nextcloud/_data/config/config.php

…
  'trusted_domains' =>
  array (
    0 => 'nextcloud.hogeserver.hogeddns.jp',
  ),
  'trusted_proxies' =>
  array (
    0 => 'nextcloud.hogeserver.hogeddns.jp',
  ),
  'overwritehost' => 'nextcloud.hogeserver.hogeddns.jp',
  'overwriteprotocol' => 'https',
  'datadirectory' => '/var/www/html/data',
…

この状態でアクセスしてみたところ、また別の警告が表示された。

The “Strict-Transport-Security” HTTP header is not set to at least “15552000” seconds. For enhanced security, it is recommended to enable HSTS as described in the security tips ↗
Strict-Transport-Security “HTTP ヘッダーの秒数が少なくとも”15552000” に設定されていません。セキュリティを強化するには、セキュリティのヒント↗で説明されているようにHSTSを有効にすることをお勧めします。

これは、ApacheにRewriteRule(carddavとcaldav)を追加したことで表示されなくなった。

/etc/apache2/sites-available/nextcloud.conf ※新規作成

<VirtualHost *:443>
    ServerName nextcloud.hogeserver.hogeddns.jp

    # Reverse proxy
    RewriteEngine On
    ProxyPreserveHost On
    RewriteCond %{HTTP:Upgrade} websocket [NC]
    RewriteCond %{HTTP:Connection} upgrade [NC]
    RewriteRule .* "ws://localhost:8080/$1" [P,L]
    RewriteRule ^/\.well-known/carddav https://%{SERVER_NAME}/remote.php/dav/ [R=301,L]
    RewriteRule ^/\.well-known/caldav https://%{SERVER_NAME}/remote.php/dav/ [R=301,L]
    ProxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/

    # Enable h2, h2c and http1.1
    Protocols h2 h2c http/1.1
…

本編では、Apacheの設定にこれを組み込んである。

デフォルトの電話地域が設定されていない

設定の管理-概要に、デフォルトの電話地域が設定されていないという警告が出ていた。

設定について教えてくれているサイトを発見。
matoken’s meme / Nextcloud 21のセキュリティ&セットアップ警告の修正 default_phone_region(電話地域)を設定

設定ファイルを編集。
/var/lib/docker/volumes/work_nextcloud/_data/config/config.php

… 先程のメールサーバーの設定が書き込まれている!
'mail_from_address' => 'administrator',
  'mail_sendmailmode' => 'smtp',
  'mail_domain' => 'hogeserver.hogeddns.jp',
  'mail_smtphost' => 'mx.hogeserver.hogeddns.jp',
  'mail_smtpport' => '25',
  'default_phone_region' => 'JP',
);

※赤文字部分を追記。

これで管理の概要ページをスーパーリロード[Ctrl]+[F5]すると、警告が消えていた。

本編では、コマンドでこの値を設定している。

SVGをサポートしていない

バージョン21の頃からこの問題が発生しているようだ。

Module php-imagick in this instance has no SVG support. For better compatibility it is recommended to install it.
このインスタンスのphp-imagickモジュールはSVGをサポートしていません。互換性の向上のために、インストールすることをお勧めします。

どうやら、何らかの理由でライブラリがインストールされていないらしい。

$ sudo docker exec -it work-app-1 /bin/bash --login
root@64469d633fc0:/var/www/html# dpkg -l libmagick*
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
+++-===========================-====================-============-======================================================
===
un  libmagickcore-6.q16         <none>               <none>       (no description available)
un  libmagickcore-6.q16-2       <none>               <none>       (no description available)
un  libmagickcore-6.q16-3       <none>               <none>       (no description available)
un  libmagickcore-6.q16-4       <none>               <none>       (no description available)
ii  libmagickcore-6.q16-6:amd64 8:6.9.11.60+dfsg-1.3 amd64        low-level image manipulation library -- quantum depth Q16
un  libmagickcore-6.q16-6-extra <none>               <none>       (no description available)
un  libmagickcore-6.q16hdri-4   <none>               <none>       (no description available)
ii  libmagickwand-6.q16-6:amd64 8:6.9.11.60+dfsg-1.3 amd64        image manipulation library -- quantum depth Q16

ということで、このライブラリをインストールする。

root@64469d633fc0:/var/www/html# apt update
root@64469d633fc0:/var/www/html# apt install -y libmagickcore-6.q16-6-extra

これで管理の概要ページをスーパーリロード[Ctrl]+[F5]すると、警告が消えていた。
ただ…これ、バージョン21からの問題で、24になっても修正されていないということは、何らかの事情があって、今後もずっと必要な手順なのかもしれないと思った。

本編では、Dockerfileにライブラリをインストールするコマンドを追加して、この問題を解消している。

Redisのインストールで追加される設定

最初に試したNextcloud All In Oneでインストールされていたので、ここでもインストールしようと考えた。

Radisはインメモリデーターベースで、Nextcloudのパフォーマンス向上に役立つとのこと。
ホームラボで使っている程度では必要ないのかもしれないけれども、導入が推奨されているようなので、ここでもインストールしてみる。

Redisのコンテナを起動して、Nextcloudからアクセスができるようになっていれば良い。
外からアクセスする必要はないので、docker-compose.ymlでポート指定はしなかった。
試行錯誤した結果がこちら。

docker-compose.yml

services:
…
  redis:
    image: redis:7.0.2-alpine
    container_name: redis
    restart: unless-stopped
    networks:
      - nextcloud
    command: >
      --requirepass nextcloud
…
  nextcloud:
…
    depends_on:
      - mariadb
      - redis
      - elastic
…
    environment:
      - MYSQL_PASSWORD=nextcloud
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_HOST=mariadb
      - REDIS_HOST=redis
      - REDIS_HOST_PASSWORD=nextcloud

コンテナとボリュームを消して、改めて起動した結果、Redis関連で追加された設定は以下と思われる。

/var/lib/docker/volumes/work_nextcloud/_data/config/config.php

…
  'memcache.locking' => '\\OC\\Memcache\\Redis',
  'redis' =>
  array (
    'host' => 'redis',
    'password' => 'nextcloud',
    'port' => 6379,
  ),
  'instanceid' => 'ocrjqzdwly6e',
…

本編では、最初からRedisを組み込むことで、設定が追加されるようにしている。

Collaboraのインストールと動作確認

Nextcloud All In Oneでインストールされていたので、ここでもインストールしようと考えた。

上手く動作しないので情報を探して回ったのだけれども、構成がなかなか理解できなかった。
結論、Collaboraのコンテナを起動しておいて、Nextcloudで特定のディレクトリへのアクセスがあれば、ポート9980にProxyする、という構成だった。
TeckOverflow / How to run Collabora office for Nextcloud using docker-compose

docker-compose.yml

…
  collabora:
    image: collabora/code:21.11.5.3.1
    container_name: collabora
    restart: unless-stopped
    ports:
      - 9980:9980
    networks:
      - nextcloud
    environment:
      - password=nextcloud
      - username=nextcloud
      - domain=nextcloud.hogeserver.hgoeddns.jp
      - extra_params=--o:ssl.enable=true
…

一旦各コンテナを止めて、改めて起動する。

$ sudo docker compose stop
$ sudo docker compose up

この段階で、管理ページにアクセスできることを確認しておく。
確認方法は、この書き込みで分かった。構成が上手く理解できない中で、これはとてもありがたかった。
https://nextcloud.hogeserver.hogeddns.jp:9980/browser/dist/admin/admin.html
※usernameとpasswordはdocker-compose.ymlで書いたものを使う。

続いて、Proxyの設定。本家で教えてくれているものを追加する。
Collabora Online SDK / Installation Guide / Proxy settings

/etc/apache2/sites-available/nextcloud.conf

…
    # Collabora Online
    AllowEncodedSlashes NoDecode
    # cert is issued for collaboraonline.example.com and we proxy to localhost
    SSLProxyEngine On
    SSLProxyVerify None
    SSLProxyCheckPeerCN Off
    SSLProxyCheckPeerName Off
    # static html, js, images, etc. served from coolwsd
    # browser is the client part of Collabora Online
    ProxyPass           /browser https://127.0.0.1:9980/browser retry=0
    ProxyPassReverse    /browser https://127.0.0.1:9980/browser
    # WOPI discovery URL
    ProxyPass           /hosting/discovery https://127.0.0.1:9980/hosting/discovery retry=0
    ProxyPassReverse    /hosting/discovery https://127.0.0.1:9980/hosting/discovery
    # Capabilities
    ProxyPass           /hosting/capabilities https://127.0.0.1:9980/hosting/capabilities retry=0
    ProxyPassReverse    /hosting/capabilities https://127.0.0.1:9980/hosting/capabilities
    # Main websocket
    ProxyPassMatch      "/cool/(.*)/ws$"      wss://127.0.0.1:9980/cool/$1/ws nocanon
    # Admin Console websocket
    ProxyPass           /cool/adminws wss://127.0.0.1:9980/cool/adminws
    # Download as, Fullscreen presentation and Image upload operations
    ProxyPass           /cool https://127.0.0.1:9980/cool
    ProxyPassReverse    /cool https://127.0.0.1:9980/cool
    # Compatibility with integrations that use the /lool/convert-to endpoint
    ProxyPass           /lool https://127.0.0.1:9980/cool
    ProxyPassReverse    /lool https://127.0.0.1:9980/cool

    # 最後に / が処理されるように定義する。
    ProxyPass / http://localhost:8080/
    ProxyPassReverse / http://localhost:8080/
…

※ProxyPass・ProxyPassReverseは定義された順番に評価されるので、最後に/を定義している。

設定変更を反映。

$ sudo systemctl reload apache2

ここで、Proxyが動作していることを確認する。※ポート指定なしでSSL接続する。
https://nextcloud.hogeserver.hogeddns.jp/browser/dist/admin/admin.html
これで管理画面が表示できれば、設定はきっとできている。

これ以降、Nextcloudに管理者でログインして、Collabora Onlineをインストールしていくが、本編と同じ内容なので割愛。

coTURNが動作するまで

Nextcloud All In Oneでインストールされていたので、ここでもインストールしようと考えた。

これも、設定ができるまでに時間が掛かったものの1つ。
ポートの開け方、公開方法がなかなか掴めなかった。

Talkをインストールして設定画面を見てみると、STUNとTURNという設定項目が出てきた。
過去にみたことがあるな…Jitsi Meetであまり意識せずにちゃんとセットアップされるアレだ、きっと。

検索してみると、詳しく教えてくれている方がいた。
インターネットにサービスを公開し、ビデオ会議をするのに必要な仕組みであることが分かってくる。
Qiita / 【初心者向け】STUN/TURNサーバをざっくり解説してみた

設定値をみると、STUNサーバーには stun.nextcloud.com:443 が設定されており、このサーバーを使わせていただけるようだ。

TURNサーバーとして、coTURNをのセットアップ方法が書かれている。
Dockerで行こうと思うので探してみたところ、プロジェクトはここにあるようだった。
Github / coturn / coturn
Dockerhub / coturn / coturn

インストール方法を頭からきっちり書いてくれている投稿を見つけることができた。
Nextcloud community / HowTo: Ubuntu + Docker + Nextcloud + Talk + Collabora

これらを色々と見比べながら設定値を決めていく。
docker-compose.yml

…
  coturn:
    image: coturn/coturn:4.5.2-r12-alpine
    container_name: coturn
    restart: unless-stopped
    ports:
      - 3478:3478
      - 49160-49200:49160-49200
    networks:
      - nextcloud
    command: >
      -n
      --log-file=stdout
      --min-port=49160
      --max-port=49200
      --use-auth-secret
      --static-auth-secret=nextcloud
      --realm=hogeserver.hogeddns.jp
…

起動。

$ sudo docker compose up

TURNサーバーに、nextcloud.hogeserver.hogeddns.jp、Secretにdocker-compose.ymlで指定した文言を設定したところ、テストOKとなった。

本編では、このサービスをインターネットに公開するため、ルーターにNATを設定している。

Elasticsearch

Alfrescoには全文検索機能(Solrが使われている)があり、かなり便利だった。
ぜひ、全文検索ができるようにしたい。

Elasticsearchのインストール

+アプリの検索から、以下をダウンロードして有効にした。

  • Full text search
  • Full text search – Elasticsearch Platoform
  • Full text search – Files

全文検索の設定画面を見てみると、検索プラットフォームはElasticsearchのようだった。
導入は、こちらの記事をかなりの部分で使わせていただいた。
Qiita / nextcloud + Elasticsearch で日本語全文検索が動いたメモ
GitHub / nextcloud / fulltextsearch / Installation of FullTextSearch with ElasticSearch and a Files Indexer

この日のElasticsearchの最新版は8.2.3だったが、調べた限り動かすことができなかった。
そのため、7.17.4を指定している。

docker-compose.yml

…
  elastic:
    #image: elasticsearch:7.17.4
    build: ./elastic
    image: elasticsearch:7.17.4-custom
    container_name: elastic
    restart: unless-stopped
    networks:
      - nextcloud
    environment:
      - "ES_JAVA_OPTSi=-Xms512m -Xmx512m"
      - logger.level=WARN
      - discovery.type=single-node
…

elastic/Dockerfile

FROM elasticsearch:7.17.4
RUN bin/elasticsearch-plugin install --batch ingest-attachment && \
    bin/elasticsearch-plugin install --batch analysis-icu && \
    bin/elasticsearch-plugin install --batch analysis-kuromoji

起動。

$ sudo docker compose up

ここで、設定の管理-全文検索で、サーバーの設定を入れる。

項目設定値
検索プラットフォームElasticsearch(選択肢はこれだけ)
サーブレットのアドレスhttp://elastic:9200
インデックスnextcloud
アナライザ トークナイザstandard

画面からの設定を終えたら、nextcloudコンテナに入り、コマンドを実行して、動作を確認。

$ sudo docker exec -it -u www-data nextcloud /bin/bash --login
$ php ./occ fulltextsearch:test

全部OKとなったので、インデックスを作ってみる。

$ php ./occ fulltextsearch:index

これで、登録済みの文書については全文検索ができるようになった。

リアルタイムでインデックス作成

この後から登録されるファイルは、このコマンドをデーモンとして実行させればインデックスが作られる。
Nextcloud / Community / How do I run occ “fulltextsearch:live” as a service?

実際に、コンテナに入って以下を実行すれば、リアルタイムにインデックスが作られる。

$ ./occ fulltextsearch:live --service &
※止めるときは、./occ fulltextsearch:stop

※最後の & を忘れると、プロセスを読んだままで帰ってこなくなる。

なお、liveで動作中のプロセスがあると、testやreset等、他のコマンドが失敗する。

In RunningService.php line 86:
                            
  Index is already running  
                            

testやresetを実行したい時は、fulltextsearch:stopで止める。

liveを起動時に実行する

さて…サーバーを起動し、コンテナが起動したときにliveを自動実行したいと思ったが、上手い方法が見つからなかった。

  • entrypointを削除して、コマンドを実行する形式に変えて、ついでに実行。
    → あれこれやってみたけれども、上手く起動させられなかった。
  • systemdはなかった。
  • init.dはありそうだったけれど(無保証)、あの定義を書くのは苦手。
  • rc.localは置いてみたけれども動作しなかった。

そこで、/entrypoint.sh でApacheを起動する直前に実行させてみた。

$ sed -Ei 's/(exec "\$@")/\/bin\/su -s \/bin\/bash -c "\/var\/www\/html\/occ fulltextsearch:live --service \&" www-data \&\n\1/' /entrypoint.sh
※消すときは、sed -i '/su -s/d' /entrypoint.sh

結果、ファイルはこうなる。
nextcloud:/entrypoint.sh

/bin/su -s /bin/bash -c "/bin/sleep 30; /var/www/html/occ fulltextsearch:live --service &" www-data &
exec "$@"

コンテナを再起動してみる。

$ sudo docker compose restert nextcloud

上手く動いた。

でも、2回目から上手くいかない。コンテナに入って、

$ ./occ fulltextsearch:stop
$ ./occ fulltextsearch:live --service &

とすると、上手く動くようだ。

以上のことから、本編では、exec “$@” の手前でスクリプトを呼び出すようにして、スクリプトでstop→liveの順で実行している。

その他にやったこと

今までに書いたことの他にやったことをメモしておく。

なぜ8080にアクセスできるのか

インストール直後の段階で、ポート22と443を解放していたが、なぜ8080にアクセスができていたのか確認してみた。
この観点で情報を探してみたところ、Dockerが起動しているコンテナへの転送を許可する設定をしているそうだ。

ルールをみてみると、外からパケットがやってきたとき、宛先のポートが9980、3478、8080だと宛先のIPアドレスが書き換えられ(DNAT)、転送されようとする。その転送は、UFWより先に評価され、転送が許可されて、各コンテナに届けられる。
各コンテナからパケットが送られてきたら、送信元IPアドレスが書き換えられ(MASQUERADE)、宛先がDockerが持つ他のネットワークグループ(?)以外なら転送が許可される。

$ sudo iptables -t nat --list-rules
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N DOCKER
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.18.0.0/16 ! -o br-d874d2574b3c -j MASQUERADE
-A POSTROUTING -s 172.20.0.0/16 ! -o br-bec3d43a4e7c -j MASQUERADE
-A POSTROUTING -s 172.26.0.0/16 ! -o br-8f72c0a09bed -j MASQUERADE
-A POSTROUTING -s 172.22.0.0/16 ! -o br-6f2e37dd255b -j MASQUERADE
-A POSTROUTING -s 172.22.0.2/32 -d 172.22.0.2/32 -p tcp -m tcp --dport 9980 -j MASQUERADE
-A POSTROUTING -s 172.22.0.3/32 -d 172.22.0.3/32 -p tcp -m tcp --dport 3478 -j MASQUERADE
-A POSTROUTING -s 172.22.0.7/32 -d 172.22.0.7/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER -i br-d874d2574b3c -j RETURN
-A DOCKER -i br-bec3d43a4e7c -j RETURN
-A DOCKER -i br-8f72c0a09bed -j RETURN
-A DOCKER -i br-6f2e37dd255b -j RETURN
-A DOCKER ! -i br-6f2e37dd255b -p tcp -m tcp --dport 9980 -j DNAT --to-destination 172.22.0.2:9980
-A DOCKER ! -i br-6f2e37dd255b -p tcp -m tcp --dport 3478 -j DNAT --to-destination 172.22.0.3:3478
-A DOCKER ! -i br-6f2e37dd255b -p tcp -m tcp --dport 8080 -j DNAT --to-destination 172.22.0.7:80

※br-6f2e37dd255b: 172.22.0.1/16
 172.22.0.2: Collabraのコンテナに割り振られている
 172.22.0.3: coTURNのコンテナに割り振られている
 172.22.0.8: Nextcloudのコンテナに割り振られている

$ sudo iptables -t filter --list-rules
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-N DOCKER
-N DOCKER-ISOLATION-STAGE-1
-N DOCKER-ISOLATION-STAGE-2
-N DOCKER-USER
-N ufw-after-forward
…
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
…
-A FORWARD -o br-6f2e37dd255b -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o br-6f2e37dd255b -j DOCKER
-A FORWARD -i br-6f2e37dd255b ! -o br-6f2e37dd255b -j ACCEPT
-A FORWARD -i br-6f2e37dd255b -o br-6f2e37dd255b -j ACCEPT
-A FORWARD -j ufw-before-logging-forward
-A FORWARD -j ufw-before-forward
-A FORWARD -j ufw-after-forward
-A FORWARD -j ufw-after-logging-forward
-A FORWARD -j ufw-reject-forward
-A FORWARD -j ufw-track-forward
…
-A DOCKER -d 172.22.0.2/32 ! -i br-6f2e37dd255b -o br-6f2e37dd255b -p tcp -m tcp --dport 9980 -j ACCEPT
-A DOCKER -d 172.22.0.3/32 ! -i br-6f2e37dd255b -o br-6f2e37dd255b -p tcp -m tcp --dport 3478 -j ACCEPT
-A DOCKER -d 172.22.0.7/32 ! -i br-6f2e37dd255b -o br-6f2e37dd255b -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -i br-6f2e37dd255b ! -o br-6f2e37dd255b -j DOCKER-ISOLATION-STAGE-2
:::
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o br-d874d2574b3c -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o br-bec3d43a4e7c -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o br-8f72c0a09bed -j DROP
-A DOCKER-ISOLATION-STAGE-2 -o br-6f2e37dd255b -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
…

過去、コンテナにパケットが届くようにと、不必要なポートを開けていたかもしれない(そのポートが指定された時点でDNATされるから、無害といえば無害ではある)。

Elasticsearch 8

Elasticsearch 8.2.3で上手く動作させることができない。

$ sudo docker exec -it -u www-data nextcloud /bin/bash -login
$ ./occ fulltextsearch:test

.Testing your current setup:
Creating mocked content provider. ok
Testing mocked provider: get indexable documents. (2 items) ok
Loading search platform. (Elasticsearch) ok
Testing search platform. fail
In StaticNoPingConnectionPool.php line 64:

                                        
  No alive nodes found in your cluster  

                                        


fulltextsearch:test [--output [OUTPUT]] [-j|--json] [-d|--platform_delay PLATFORM_DELAY]

$ ./occ fulltextsearch:check
Full text search 24.0.0

- Search Platform:
Elasticsearch 24.0.0 (Selected)
{
    "elastic_host": [
        "http://elastic:9200"
    ],
    "elastic_index": "nextcloud",
    "fields_limit": "10000",
    "es_ver_below66": "0",
    "analyzer_tokenizer": "standard"
}

…

$ curl http://elastic:9200
curl: (52) Empty reply from server

色々と調べてみると、8ではセキュリティが強化されているようだった。
ポートを外に見せたりしない設定なので、セキュリティを緩めてみた。

docker-compose.yml

…
  elastic:
    #image: elasticsearch:7.17.4
    build: ./elastic
    image: elasticsearch:7.17.4-custom
    container_name: elastic
    restart: unless-stopped
    networks:
      - nextcloud
    environment:
      - "ES_JAVA_OPTSi=-Xms512m -Xmx512m"
      - logger.level=WARN
      - discovery.type=single-node
      - xpack.security.enabled=false

これで、情報が戻ってくるようにはなった。

$ curl http://elastic:9200
{
  "name" : "3aedee1b275f",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "Q6ZSixxpQfilHeVItGYvYQ",
  "version" : {
    "number" : "8.2.3",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "9905bfb62a3f0b044948376b4f607f70a8a151b4",
    "build_date" : "2022-06-08T22:21:36.455508792Z",
    "build_snapshot" : false,
    "lucene_version" : "9.1.0",
    "minimum_wire_compatibility_version" : "7.17.0",
    "minimum_index_compatibility_version" : "7.0.0"
  },
  "tagline" : "You Know, for Search"
}

でも、インデックスは作成できない。

$ ./occ fulltextsearch:index
…
In Connection.php line 675:

  {"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"request [/nextcloud] contains unrecognized p
  arameter: [include_type_name]"}],"type":"illegal_argument_exception","reason":"request [/nextcloud] contains unreco
  gnized parameter: [include_type_name]"},"status":400}


fulltextsearch:index [--output [OUTPUT]] [-r|--no-readline] [--] [<options>]

探してみるとこのページが見つかり、Elasticsearch 8との組み合わせでは使えないことが分かった。
bbz internet / Elasticsearch-8.2.2 と 7.17.4 を Windows10 と Ubuntu22 で動かす方法
Github / nextcloud / fulltextsearch / illegal_argument_exception while starting a new index #525

Google先生によれば、include_type_nameはElasticsearch 7で廃止され、8で削除されたと翻訳された。
だけど、実際には7で非推奨となり、8で廃止のようだ。DeepL先生の翻訳ではそうなった。

ということで、NextcloudのFulltextsearchが対応するまでは、Elasticsearch 7で運用する。

Nextcloud AIOのインストール

Nextcloudのインストールページに行ってみたところ、いくつかのインストール方法が用意されていることが書かれている。
その中で、最初にトライしたのはALL-IN-ONE DOCKER IMAGEだった。

結論としては、このインストール方法を断念した。Collaboraの設定方法が分からず、コンテナを削除して作り直し…を繰り返しているうちに、AIOのバージョンが上がり、グローバルIPアドレスを持たないサーバーにはインストールができなくなった。

It seems like the ip-address is set to an internal or reserved ip-address. This is not supported. (It was found to be set to ‘192.168.110.34’)
ip-addressが内部または予約済みのip-addressに設定されているようです。 これはサポートされていません。 (「192.168.110.34」に設定されていることがわかりました)

Google先生の翻訳

どちらかというと、最初にインストールできてしまったことの方が問題だったようだ。

とはいえ、せっかく立ち上がるところまでは行ったのだから、メモとして残しておくことにした。

インストール

Nextcloud All In Oneはこちらに置かれている。
GitHub / nextcloud / all-in-one

docker-compose.ymlをローカル環境にコピー。
このファイルを置いた場所で、以下を実行。

$ mkdir ~/work
$ cd ~/work
docker-compose.ymlを用意して…
$ sudo docker compose up -d

この段階で、nextcloud-aio-domaincheckとnextcloud-aio-mastercontainerの2つが動作している。

これで、https://nextcloud.hogeserver.hogeddns.jp:8080 にアクセスすると、セットアップ画面が表示された。
httpsなのでブラウザから警告が表示されるが、そのままアクセスする。

setup画面に表示されているパスワードをメモしておき、Open Nextcloud AIO loginボタンをクリックする。

ログイン画面が表示されるので、メモしておいたパスワードを入力し、ログインボタンをクリックする。
新規インストールなので、New AIO instanceのところにドメイン名を入れてSubmitする。
(この画面で、バックアップから復元することもできるようだ)

ところが、Submitボタンを押したところで、以下のメッセージが表示されて先に進めなかった。

The server is not reachable on Port 443. You can verify this e.g. with ‘https://portchecker.co/’ by entering your domain there as ip-address and port 443 as port.
サーバーはポート443に到達できません。例えば、’https://portchecker.co/’ で、ip-address にあなたのドメイン、port に 443 を入力することで確認することができます。

DeepL先生の翻訳

443ポートを開放することで、先に進められるようになる。

$ sudo ufw allow https

アドオンとタイムゾーンの設定が表示される。
Start containersボタンを押すと、必要なコンテナがダウンロードされて、動作し始めるらしい。こんなことができるのね…凄い。
ダウンロードが終わると、コンテナが起動する。画面はダウンロード直後のもので、Reloadボタンを押すと、起動状態が表示される。

この段階で、8つのコンテナが起動している。追加されたのは6つのコンテナ。
nextcloud-aio-apache, nextcloud-aio-nextcloud, nextcloud-aio-redis, nextcloud-aio-database, nextcloud-aio-talk, nextcloud-aio-collabora

この画面で、パスワード変更ができるようなので、パスワードを変更した。

オプションの変更などをする場合に、コンテナを一旦止める必要があったので、Stop containersボタンを押して停止させる。
これで、nextcloud-aio-mastercontainer以外のコンテナが停止した。

Optional addonsにOnlyOffice(AscensioSystem独自開発・互換性重視)という選択肢がある。
使用する場合は、Collabora(Libreofficeベース)を外すようだ。
何分初めてなので、デフォルトのCollaboraのままにしておいた。
Nextcloud community support / Collabora vs. Onlyoffice

Timezone changeでタイムゾーンを変更しておく。
Asia/Tokyo
この変更は、mastercontainerとバックアップオプションには適用されないとのこと。

設定変更が終わったので、Start containersボタンを押す。

これで動作するようなのだが、ログイン画面(https://nextcloud.hogeserver.hogeddns.jp)にアクセスすることはできなかった。
リバースプロキシが必要なようだ。

しかし、…Dockerのコンテナが、Dockerデーモンと直接対話をして、コンテナを作って起動したり、作り直したりしている。
こんなことができるのか、凄い。

リバースプロキシ

リバースプロキシを設定する。
GitHub / nextcloud / all-in-one / Reverse Proxy Documentation

コンテナをすべて一旦停止。

$ sudo docker compose stop
$ sudo docker stop nextcloud-aio-apache nextcloud-aio-nextcloud nextcloud-aio-redis nextcloud-aio-database nextcloud-aio-talk nextcloud-aio-collabora

$ sudo docker ps
※これでコンテナが表示されなければ全部停止している。

Apacheをインストールし、デフォルトの設定ファイルを無効化。

$ sudo apt install apache2
$ sudo a2dissite 000-default.conf

公式のページを参考に、設定ファイルを作成。

/etc/apache2/sites-available/nextcloud.conf ※新規作成

Listen 8443

<VirtualHost *:80>
    ServerName nextcloud.hogeserver.hogeddns.jp

    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
    RewriteCond %{SERVER_NAME} =nextcloud.hogeserver.hogeddns.jp
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

<VirtualHost *:443>
    ServerName nextcloud.hogeserver.hogeddns.jp

    ErrorLog ${APACHE_LOG_DIR}/nextcloud-error.log
    CustomLog ${APACHE_LOG_DIR}/nextcloud-access.log combined

    # Reverse proxy
    RewriteEngine On
    ProxyPreserveHost On
    RewriteCond %{HTTP:Upgrade} websocket [NC]
    RewriteCond %{HTTP:Connection} upgrade [NC]
    RewriteRule .* "ws://localhost:11000/$1" [P,L]
    ProxyPass / http://localhost:11000/
    ProxyPassReverse / http://localhost:11000/

    # Enable h2, h2c and http1.1
    Protocols h2 h2c http/1.1

    # SSL
    SSLEngine on
#    Include /etc/letsencrypt/options-ssl-apache.conf
#    SSLCertificateFile /etc/letsencrypt/live/<your-nc-domain>/fullchain.pem
#    SSLCertificateKeyFile /etc/letsencrypt/live/<your-nc-domain>/privkey.pem
    SSLCertificateFile /etc/ssl/private/wild.hogeserver.crt
    SSLCertificateKeyFile /etc/ssl/private/wild.hogeserver.key

    # Disable HTTP TRACE method.
    TraceEnable off
    <Files ".ht*">
        Require all denied
    </Files>
</VirtualHost>

<VirtualHost *:8443>
    ServerName nextcloud.hogeserver.hogeddns.jp

    # Reverse proxy
    SSLProxyEngine On
    SSLProxyCheckPeerCN Off
    ProxyPass / https://localhost:8080/
    ProxyPassReverse / https://localhost:8080/

    # SSL
    SSLEngine on
    SSLCertificateFile /etc/ssl/private/wild.hogeserver.crt
    SSLCertificateKeyFile /etc/ssl/private/wild.hogeserver.key
</VirtualHost>

※サーバーの証明書と秘密鍵は、指定した場所に入れておく。秘密鍵のパスワードは外してある。

新規作成した設定を有効化。

$ sudo a2ensite nextcloud.conf

必要なモジュールを有効にする。

$ sudo a2enmod rewrite proxy proxy_http ssl headers

Apacheを再起動。

$ sudo systemctl restart apache2

このままだと、マスターコンテナやnextcloud-aio-apacheが同じポート取ってしまうので、利用ポートを変更。
このことが想定されていたので、編集は簡単だった。
docker-compose.yml

…
services:
  nextcloud:
…
    ports:
      #- 80:80 # Can be removed when running behind a reverse proxy. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
      - 8080:8080
      #- 8443:8443 # Can be removed when running behind a reverse proxy. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md
    environment: # Is needed when using any of the options below
      - APACHE_PORT=11000 # Is needed when running behind a reverse proxy. See https://github.com/nextcloud/all-in-one/blob/main/reverse-proxy.md

※ポートを塞ぎつつ、Apache関連でコメント化されていた赤文字行を有効にした。

コンテナを起動。

$ sudo docker compose up -d
$ sudo docker start nextcloud-aio-apache nextcloud-aio-nextcloud nextcloud-aio-redis nextcloud-aio-database nextcloud-aio-talk nextcloud-aio-collabora

これで、ログイン画面にいけるようになった。
https://nextcloud.hogeserver.hogeddns.jp

あれ?でもログイン情報って??
コンテナページにアクセスしてみると、最初のユーザーとパスワードが表示されている。
https://nextcloud.hogeserver.hogeddns.jp:8443/containers

改めてログインしてみる。

動き出した。

LDAP認証

本編でも記載した手順だが、先にAIOで試し、問題なく動作するところまで確認していた。
同じ内容になるので割愛。

メールサーバーの設定

こちらも本編で記載した手順で、問題なく動作するところまで確認していた。
ただし…Test and verify email settingsの横にある「メールを送信」を押したときの動作が違っていた。

具体的には、

  • adminに設定したメールアドレスに「メール設定のテスト」が送信される。
    中身は「このメールが見えているということは、メール設定が上手くいっているということです。」というもの。
  • アクティブユーザーに「”Nextcloud” のアクティビティ通知」が送信される。
    中身は「管理者があなたをグループxxに追加しました。」というもの。

が送信されたのだが、本編の手順では、後者が送信されないように思う。

やり直し・確認ができなかったので、そういうことがあるかもしれないと用心しておく程度。

Collaboraの設定

この設定で挫折。今になればひょっとしたら…と思うところもあるが、結論は出せていない。
やり直しのためにAIOを削除して、もう一回!と思ったら、二度とインストールができない状態になっていた。

AIOのメモはここまで。

さいごに

クラウドにある情報と、ローカルにある情報を同期する = 容量が2倍になっちゃうじゃん、ということで、OneDriveもDropboxも使ってこなかった。
でも、最近は色々なデバイスで大きな容量を手軽に取り扱えるようになってきており、利便性の方が大きくなってきている。

実際にNextcloudを使い始めてみた感想は、至極よく作り込まれていて使いやすい、だった。
ユーザーにとっても使いやすいだろうし、管理も手間が掛からないように作り込まれている。人気には理由があるんだなと実感。

Dockerもまだ知らないことが多いけれど、今回のことで便利さが少し分かってきた。
Dockerイメージが提供されていない「とあるシステム」をどうにかして自作してみたいなぁ。

開発に携わる皆様に感謝。

以上で、今回の巨大なメモは終了。

コメントはこちらから お気軽にどうぞ ~ 投稿に関するご意見・感想・他