Raspberry Pi 3でNextcloudを動かす時の注意点

nextcloud start
おうちサーバーをどうするかほったらかしです。
これなら使えそうだと思ったものにNextcloudというソフトウエアがあります。自宅サーバーでおうちクラウドが作れます。スマホのアプリもあり外から自宅サーバーへ簡単にアクセスできます。
今回はNextcloudを動かす方法を紹介してみます。


Nextcloudってなに?

Nextcloudは自分専用のクラウドサーバーを作れるオープンソースソフトウエアです。
公式サイトはこちら
Nextcloudhttps://nextcloud.com/
OneDriveやGoogle Driveのようなクラウドストレージを自宅で立ち上げる事ができます。それならGoogle Driveでいいのでは?と思うでしょうが自分の手元にファイルがあるというのを重要視する人にお勧めです。
追加アプリでGoogle Driveと連携する事もできます。追加アプリは他にもカレンダー、メール、チャットや音楽プレーヤなどがあります。ビデオファイルはプレビュー機能で見ることもできます。

このように機能豊富なNextcloudを早速試してみようと思いました。しかし、NextcloudはLinuxのソフトウエアです。Windowsユーザーからするととてもとっつきにくい。
Linux専用PCがあれば気軽に試すでしょうが我が家にはRaspberry Piくらいしかありません。Raspberry Piとは5千円ほどのボードコンピュータです。
今回はRaspberry Pi 3 Bを使ってNextcloudを動かしてみます。

DockerでNextcloudを動かす

Raspberry PiにNextcloudを直接インストールしても良いのですが、初めて使うソフトウエアだと設定の仕方がわからず動いたころにはOSの設定がぐしゃぐしゃになってしまいます。動いたは良いがどの設定で動いたのか?とか必要ない設定までしているのでは?とか2度と再現できないかも…などといったことになりがちです。
こんな経験をLinuxを使っている人たちは何度もしています。そこで生み出されたのがDockerというソフトウエアです。

DockerはLinuxの仮想OSを作ってその上でプログラムを動かします。仮想OSなのでOSの状態をファイルとして残しておけます。詳しいことは他のサイト様にお任せですのでググってください。
DockerはOSとプログラムの設定をファイルとして残しておけます。そしていつでも真っ新なOSから設定を再現できます。PCを新しくした場合でもDockerとそのファイルさえあればすぐにソフトウエアを再現できるのです。

それではNextcloudを動かす準備をしていきます。
Raspberry PiのOSにはこの記事公開時で最新の
Raspbian Buster with desktop Version:September 2019
を使います。
 OSのインストールの説明は他のサイト様にお任せです。イメージファイルをSDメモリーカードに書き込むだけです。

DockerとDocker Composeのインストール

RaspbianにDockerをインストールします。これは以前の記事を参照してください。
関連記事:Raspberry PiにDockerをインストールする

Dockerは複数の仮想OSを動かした時の管理が大変なのでDocker Composeというソフトウエアもインストールします。
関連記事:Raspberry PiにDocker Composeをインストールする

Nextcloudに必要な他のソフトウエア

Nextcloudは他のソフトウエアと一緒に動かす必要があります。ユーザや状態を管理するデータベース、インターネットへ公開する場合のリバースプロキシ、動作を高速化するメモリキャッシュの3つです。
他のソフトウエアもDocker上で動かします。複数のDockerコンテナの設定をまとめて書けるのがdocker-compose.ymlファイルです。
公式の例はこちらにあります。
docker/.examples/docker-compose/ | GitHub
しかしながらRaspberry Piでこの例を動かすことはできません。Raspberry Piでは公式のmariaDBが動きません。これらはインテルやAMDのパソコン用CPUで動きます。この例を参考にRaspberry Pi用のdocker-compose.ymlファイルを作っていきます。

まずはNextcloudのDockerイメージがなければ始まりません。
nextcloud | Docker Hub
A safe home for all your data
これはRaspberry Piで動きます。

データベースは多くの場合mySQLを使います。しかしながらDockerにはRaspberry Piで動くmySQLの公式イメージがありません。非公式ながらRaspberry Piで動くmySQLイメージを公開してくれている方々がいます。
今回はhypriot/rpi-mysqlを使います。
hypriot/rpi-mysql | Docker Hub
RPi-compatible Docker Image with Mysql 
【2020/1/14 追記:jsurf/rpi-mariadb の方が良さそう
関連記事 ラズパイのDockerで使うデータベースイメージは何が良いか?🍣🍺

家の外、インターネット経由でNextcloudを使いたい場合はNextcloudをインターネットへ公開する設定をしなくてはなりません。Nextcloud単体でもインターネットへ公開する設定はできるのですが、Dockerは複数の仮想化したソフトウエアを動かせるので他のソフトウエアとインターネットへの接続が競合してしまうかもしれません。こんな場合にはリバースプロキシというソフトウエアを動かします。リバースプロキシはインターネットとの窓口となって暗号化、データの圧縮やリクエストの振り替えをやってくれます。ソフトウエア毎にセキュリティ設定をする必要が無くなるのでいろいろなプログラムを動かす時にも便利です。
今回はnginxを使います。
nginx | Docker Hub
Official build of Nginx.
細かいデータをメモリーにキャッシュしてくれるソフトウエアも使います。これは無くとも動きますが簡単に設定できるので使いましょう。
Redis | Docker Hub
Redis is an open source key-value store that functions as a data structure server.

ホストとゲストのディレクトリを準備する

Dockerを使っているとややこしいのが使っているファイルやディレクトリがどこにあるのか?という点です。
Raspberry Piで直接動いているOSはRaspbianです。これをホストOSと呼びます。そのホストOSであるRaspbianの上でDockerを動かしています。
Dockerで動いているコンテナのOSをゲストOSと呼びます。ホストOSとゲストOSは独立しています。ホストOSのディレクトリやファイルとは関係なく、ゲストOSは独自のディレクトリとファイルを持っています。複数のゲストOSも各々独立しています。互いに他のゲストOSのファイルを直接読み書きする事はできません。
ネットワークもホストOSとは独立しています。何も設定しなければホストからゲストへは通信できません。ゲストOSから外へはつながります。Docker上には仮想的なネットワークが自動的に作らるのでゲストOS同士の通信はできます。
ゲストOSが独立しすぎて何も設定できないので必要最低限の通信方法とファイルの置き場所をdocker-compose.ymlファイルでDockerに教えてあげます。

docker-compose.ymlファイルを書く前にゲストOSで使うファイルのホストOSでの置き場所を作っておきます。ゲストOSのファイルはコンテナ内にあります。コンテナを削除すると設定ファイルなども消えてしまいます。消えては困るファイルをホストOS上に置くようにします。
次のディレクトリを作りました。
mkdir ~/Docker
mkdir ~/Docker/nginx1
mkdir ~/Docker/nginx1/ssl
mkdir ~/Docker/db4nextcloud1
mkdir ~/Docker/nextcloud
mkdir ~/Docker/nextcloud/dockerfile
mkdir ~/Docker/nextcloud/skeleton
ディレクトリ名を見ればわかるようにnginx用、database用とNextcloud用のディレクトリです。私は既に自宅サーバー用の証明書を持っているのでnginx1/sslには自宅サーバーの証明書を置いておきます。
Nextcloudの設定ファイルやクラウドサーバー上のファイルをホストOS上に置くようにします。またNextcloudのイメージを追加で手を加えるのでDockerfileを置く場所を作ります。skeletonディレクトリは新規ユーザー用の初期ファイルを置く場所です。

docker-compose.ymlファイルを書く

docker-comose.ymlファイルを作ります。
cd ~/Docker
新しくdocker-compose.ymlファイルを作ります。
nano docker-compose.yml
エディタにnanoを使いましたがデスクトップ環境ならleafpadやgeanyの方が便利でしょう。
早速ファイルの中身を紹介します。
version: '3'
volumes:
  redis:
services:
  nginx:
    image: nginx
    volumes:
      - ./nginx1/nginx.conf:/etc/nginx/nginx.conf
      - ./nginx1/conf.d:/etc/nginx/conf.d
      - ./nginx1/html:/usr/share/nginx/html
      - ./nginx1/ssl/server.crt:/etc/pki/tls/certs/server.crt
      - ./nginx1/ssl/server.key:/etc/pki/tls/private/server.key
    ports: 
      - 443:443
    depends_on:
      - nextcloud1
  db4nc:
    image: hypriot/rpi-mysql
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    restart: always
    volumes:
      - ./db4nextcloud1:/var/lib/mysql
      - /etc/localtime:/etc/localtime:ro
    environment:
      - MYSQL_ROOT_PASSWORD=pass
      - MYSQL_PASSWORD=pass
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
  nextcloud1:
    build:
      context: ./nextcloud/dockerfile
    ports:
      - 8180:80
    volumes:
      - ./nextcloud/html:/var/www/html
      - ./nextcloud/skeleton:/var/www/skeleton
      - /etc/localtime:/etc/localtime:ro
    restart: always
    depends_on:
      - db4nc
      - redis
    environment:
      - REDIS_HOST=redis 
#      - SQLITE_DATABASE
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_PASSWORD=pass
      - MYSQL_HOST=db4nc:3306
#      - POSTGRES_DB
#      - POSTGRES_USER
#      - POSTGRES_PASSWORD
#      - POSTGRES_HOST
#      - NEXTCLOUD_TABLE_PREFIX
#      - NEXTCLOUD_DATA_DIR
  redis:
    image: redis
    restart: always
    volumes:
      - redis:/data
volumesでゲストOSのディレクトリにホストOSのディレクトリをリンクさせます。
rediasという名前でゲストOSとは独立したファイル置き場を作ります。
environmentでは環境変数を設定してゲストOSの初期値を設定しています。主にデータベースの設定です。db4ncというデータベース用ゲストOSにNextcloudのゲストOSからアクセスできるように同じデータベース名、ユーザー名とパスワードを設定します。データベースのパスワードは適当に変えてください。

Nextcloud用Dockerfileを作る

Nextcloudのイメージを作るDockerfileを作ります。Windowsのファイル共有フォルダを外部ドライブとしてマウントできるようsmbclientを追加でインストールするためです。
Dockerfileを~/Docker/nextcloud/dockerfileディレクトリに作ります。
中身はこんな感じ。
FROM nextcloud:latest
RUN apt-get update \
   && apt-get install -y --no-install-recommends \
#        libsmbclient-dev \
        smbclient \
#  && pecl install  smbclient \
#  && echo "extension=smbclient.so" > /usr/local/etc/php/conf.d/docker-php-ext-smbclient.ini \
#  && docker-php-ext-enable smbclient \
   && apt-get purge  --autoremove -y -o APT::AutoRemove::RecommendsImportant=false \
   && rm -rf /var/lib/apt/lists/*
# RUN sed -i -e "/\[global\]/a\client max protocol = SMB3" /etc/samba/smb.conf \
#  && sed -i -e "/\[global\]/a\client min protocol = SMB2" /etc/samba/smb.conf
この記事執筆時、Winodwsサーバーの共有フォルダをマウントできていません。Linux系NASのSMB1の共有フォルダしかマウントできていません。
いろいろ設定をいじってみましたが成功しませんでした。
【64bitイメージを使うと成功しました
Raspberry Pi 3で64bit ubuntuを使ってNextcloudのSMB共有アクセスが成功した

Docker Composeを仮に動かす

docker-compose.ymlとホストOSのディレクトリの準備ができたらDocker Composeを動かしてみます。ゲストOSの作る初期設定ファイルをホスト上に展開するためです。
cd ~/Docker
docker-compose up
イメージがダウンロードされ実行されるでしょう。
Starting docker_redis_1    ... done
Starting docker_db4nc_1    ... done
Starting docker_nextcloud1_1 ... done
Starting docker_nginx1_1     ... done
doneと表示されれば成功です。
ここでNextcloudを表示させ管理ユーザを登録します。
今回は初期設定なので
https://localhost:8180
をブラウザで表示させます。NextcloudのゲストOSへ直接つながり表示されます。リバースプロキシの設定をしていないのでnginx経由ではまだ表示できません。
nextcloud admin
データベースの環境変数を正しく設定していればデータベースの入力メニューは表示されません。ここで入れるユーザー名とパスワードが管理者として設定されます。セットアップを完了させます。
”作業を完了しています...”と表示されてから数分かかります。
初期設定が終わるとファイルサーバーが表示されます。
この時点で先ほど作ったディレクトリのnextcloudの下にhtmlというディレクトリができているでしょう。ここにnextcloudの表示用ページ設定が展開されています。
db4nextcloud1ディレクトリの下にNextcloudで使うデータベースが展開されているでしょう。

仮の実行を止めます。Ctrl+Cを押すと止まるでしょう。

Nextcloudの設定をする

ディレクトリnextcloudの下にNextcloudの設定フォルダもできています。
cd ~/Docker/nextcloud/html/config
ここのconfig.phpを編集します。
sudo nano config.php

trusted domains配列に自分のドメインを追加します。
Nextcloudは最初の管理ユーザを登録した時のwebブラウザのURLを信頼したドメインとして登録してしまいます。信頼したドメイン以外のURLでアクセスすると何もできない画面が表示されます。
not trusted

Raspberry PiのローカルIPアドレスと自宅用に取得したドメイン名を追加しておきます。
'trusted_domains' => 
  array (
    0 => 'localhost:8180',
    1 => '192.168.xxx.yyy',
    10 => 'home.example.com',
  ),
ドメイン名でのアクセスは自宅の外、インターネットからのアクセスになります。このアクセスはリバースプロキシnginxを経由させます。nginx経由でNextcloudにアクセスした時用の設定を追加します。
'trusted_proxies' => 
  array (
    0 => 'nginx1',
  ),
  'overwritehost' => 'home.example.com:xxxx',
  'overwrite.cli.url' => 'https://home.example.com:xxxx',
  'overwriteprotocol' => 'https',
  'overwritewebroot' => '/',
  'overwritecondaddr' => '',
nginx1はdocker-compose.ymlで書いたnginxコンテナの名前です。Docker内のゲストOS同士はコンテナ名で通信できます。
xxxxにはインターネット側のポート番号を設定します。通常のhttpsのポート443番ならば書かなくても良いです。

nginxの設定をする

インターネットからアクセスするためにリバースプロキシnginxの設定をします。
cd ~/Docker/nginx1/conf.d
sudo nano proxy.conf
proxy.confというファイルを新しく作りリバースプロキシの設定を書きます。
upstream nextcloud {
  server nextcloud1;
  keepalive 300;
}

server {
  listen 443 ssl http2;
  listen [::]:443 ssl http2;
  server_name home.example.com;
  ssl_certificate /etc/pki/tls/certs/server.crt;
  ssl_certificate_key /etc/pki/tls/private/server.key;
#  ssl_stapling on;
#  ssl_stapling_verify on;
#  index index.html;
  client_max_body_size 0;
  underscores_in_headers on;
#  include /etc/nginx/snippets/ssl.conf;

  location / {
    proxy_pass http://nextcloud/;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_http_version 1.1;
    proxy_set_header Host $host;
    proxy_set_header HTTP_X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    add_header Front-End-Https on;

    send_timeout 180;
    proxy_connect_timeout 600;
    proxy_read_timeout    600;
    proxy_send_timeout    600;
    add_header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload";
  }

  location ~ /\.(?!file).* { deny all; }

  location = /.well-known/carddav {
    return 301 $scheme://$http_host/remote.php/dav;
  }
  location = /.well-known/caldav {
    return 301 $scheme://$http_host/remote.php/dav;
  }
}
ルータのポートフォワーディング設定でインターネットからのアクセスはLAN内で443番に送る設定の場合です。もしもLAN内で異なるポート番号を使う場合はlinsten文を変えてください。
sslディレクトリにドメインの証明書を置きます。この例ではserver.crtとserver.keyというファイル名にします。
【2020/1/15 追記: 真面目にSSL設定をしてみました。
関連記事:自宅サーバをnginxで公開するときのssl設定はどうすればいいの?

動作確認をする

以上で基本的な設定は終わりです。もう一度動かしてみます。
cd ~/Docker
docker-compose up
間違えが無ければNextcloudが動くでしょう。インターネットからのアクセスも試してみましょう。プロキシの設定はややこしいので一回では動かないかもしれません。インターネット側のポート番号、ルータのポートフォワーディング設定、nginxの転送設定など順番に確認します。

一通り動いたらNextcloudの概要画面を表示させてみます。簡単なセルフチェック機能があります。
self check
ここまでうまく設定できていればMySQLの警告だけ出ているでしょう。上の画面の例ではわざと警告をたくさん出しています。
4バイト文字をサポートしないとWindowsでUTF8の文字をファイル名に使ったファイルをNextcloudへアップロードすることができません。MySQLの警告を参考に設定を進めると4バイト文字を使えるようになります。その手順はここでは説明しません。この記事を参考にNextcloudを設定する人は多くないと思っているので書くのが面倒だからです。ご要望があればコメントください。

まとめ

NextcloudをDockerで動かしてみました。nginxをリバースプロキシとして使っています。
ドメインの証明書を取得している前提の手順を紹介しました。証明書が無い場合はlet's encryptなどフリーの証明書を発行するサービスを使うと良いでしょう。Nextcloudの説明にはlet's encryptの証明書を自動更新するコンテナを使う例も紹介されています。

なんだか良くわからなくて動かないという場合はnextcloudpiを使うと良いでしょう。nextcloudpiはRaspberry PiでNextcloudを動かすSDメモリーカードイメージです。イメージをダウンロードしてSDメモリーカードに書き込むだけで動かせます。ドメインSSL証明書の取得もWeb画面でできるようになっています。

.well-knownの警告を消すのに時間がかかりました。インターネットからポート443以外でアクセスする設定にしていると正しいアクセスURLになりません。ルータのポートフォワーディングでポート番号が変わってしまうためアクセス元のポート番号がわからないためです。
$http_hostという変数がアクセス元のURLとポート番号を表しているようです。
ですがどうも動いている気がしません。GoogleカレンダーにNextcloudのカレンダーを登録したのですが予定が反映されません。何か足りないようです。

Windowsのファイル共有を使うことができていません。smb1.0なNASとはできます。また、nextcloudpiではWindowsでもできています。今回の手順は最新のnextcloudpiを使いますがnextcloudpiではバージョンが一つ前のNextcloudが動きます。それと関係あるかもしれません。
【64bitイメージを使うと成功しました
Raspberry Pi 3で64bit ubuntuを使ってNextcloudのSMB共有アクセスが成功した

Nextcloudではビデオファイルのプレビュー再生や音楽プレーヤもあり、スマートフォン用アプリも用意されているので自宅クラウドとして便利そうです。

ですがLinuxゆえの弱点もあります。それはファイル名の文字数が足りないことです。Windowsで長いファイル名を付けてしまうとNextcloudでは文字数が多すぎアップロードできないのです。どうやら文字数をフルパスで数えているのが事態を悪化させる原因のようですがフォーラムで時折話題になるだけで改善される気配はありません。
音楽ファイルではデータベースから自動的にファイル名を更新してしまう事があるでしょう。この時ファイル名がとても長くなる曲もあります。私の場合2割近い音楽ファイルがファイル名の文字数制限に引っかかってしまいます。

今回はRaspberry Pi 3で動かしましたがハッキリ言って動作が遅いです。Dockerを使って動かしたのはRaspberry Pi 4へ簡単に移行するためです。技適を取得したRaspberry Pi 4を早く試したいです。来年にはWindowsのWSL2が正式に使えるようになります。そうなればWindows10へも簡単に移行できるでしょう。

コメント

最近のコメント

Threaded Recent Comments will be here.