🏠

【自宅NAS+VPN】Docker on ProxmoxでNextCloudとTrailscaleを構築

に公開

今回は自分の業務に関係なく一度やってみたかった自宅NASの構築をしてみました。

画面の端っこが液晶漏れしているiPhone11(128GB)を愛用している私ですが、写真で容量がいっぱいで最近はアプリのアップデートすら失敗します。iOSも若干古いです。可哀想です。

ていうことで自宅NAS+VPNを構築して私のiPhoneを助けてあげたいと思います。

システム構成

個人的に気になっていたProxmox VE(PVE)を基盤に構築していきます。PVEはDebianベースのハイパーバイザー型の仮想化基盤です。無料で使えます。
今回は全て一からMiniPCに構築を行っていきます。

MiniPCスペック

特徴 GMKtec Nucbox G3 Plus
CPU 第13世代 Intel N150 (4コア/4スレッド, 最大3.6GHz)
RAM 16GB DDR4
ストレージ 1TB SSD (M.2 NVMe PCIe3.0)
グラフィックス Intel Graphics
OS Debian 13(Trixie)

https://amzn.asia/d/aXlg9ig

仮想マシン構成

Proxmox VE
 ├─ Ubuntu 24.04 (LXC-A)
 │ ├ Nextcloud (Docker)
 │ └ MariaDB (Docker)
 └─ Ubuntu 24.04 (LXC-B)
   └ Tailscale (Docker)

全てDockerHubに公式イメージがあったため、Dockerイメージで各サービスを構築していきます。
Dockerの説明は割愛します。

Proxmox VEの構築

仮想マシンはVMとLXCの2種類あります。VM(Virtual Machine)はPVE上にゲストOSを動作させる仮想化、LXC(Linux Containers)はホストOSとカーネル共有することで非常に軽量に動作可能な仮想化方法です。
Linux以外のOS(Windowsなど)を使いたい、もしくはカーネルモジュールなどを弄りたい、というとき以外は基本LXCを使えば良さそうです。

LXCとDockerの仕組みの違いがあまり分かっていませんが、異なる歴史を持つことと、ポリシーが異なるみたいです。LXCはOSベース、Dockerはプロセスベースといった感じでしょうか。

以下の記事を参考にさせていただきインストールしました。参考記事は沢山あるので手順は割愛します。

LXCの構築

操作は同じネットワーク上の別PCで行っていきます(WindowsPC)。
PVEで「local(pve)」->「CTテンプレート」->「テンプレート」からOSのテンプレートをダウンロードします。今回は「Ubuntu-24.04-standard」を選択しました。

「CTを作成」でLXCを作成していきます。構成は以下です。

項目 LXC-A LXC-B
DISK 128GB 8GB
CPU Core 2core 1core
RAM 4096MB 256MB

容量を増やす分には後からでも簡単にできるので小さめに確保しておくのがベターです。
LXC-A(NASデータ領域)はiPhoneの容量に合わせて128GBに設定しました。
LXC-B(VPN)はTailscaleが軽量とのことでAIに聞いて設定しました。(最小要件は公式で見つけられず)
またお好みですが、IPは固定にして置いた方が後々管理が楽だと思います。


LXCは容量がめちゃくちゃ軽量ですね。これでVMのように使えるのは便利。


左サイドバーにLXCのアイコンが2つ表示されました

Dockerのインストール

LXCアイコンをクリックしてコンソールを選択するとCLIで操作可能になります。

公式手順でDockerをインストールします(apt経由で実施)
https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository

これをLXC-A, LXC-Bの両方に適用します。バージョンが表示されればOKです。

NextCloud+MariaDBの構築(LXC-A)

NextCloudはOSSのクラウドストレージです。スマホアプリも配信されているため、iPhone⇔NAS間のデータを簡単にやりとりできます。
MariaDBはMySQLの派生したRDBです。他と比較して高速なのが特徴とのことです。なんだかんだ触れるのは初めてです。

コンテナの構築

以下のイメージを使っていきます。

Nextcloudはデフォルトsqliteを使用するとのことですが、DockerHubにあるcompose.yamlのサンプルでmariaDBを使っていたので、mariaDBをそのまま採用しています。
Nextcloudのバリエーションとして、apache(web server)かphp-fpm(fastCGI)の2パターンあります。特にこだわりはないので簡潔に済むapache版を選択します。

LXC-Aのターミナルを開き、Docker Composeで構築します。

サンプルに少し手を加えたcompose.yamlが以下です。

services:
  db:
    image: mariadb:12.0.2
    restart: unless-stopped
    command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
    volumes:
      - ./mariadb_data:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD={rootパスワード}
      - MYSQL_PASSWORD={userパスワード}
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud

  app:
    image: nextcloud:31.0.9-apache
    restart: unless-stopped
    ports:
      - 8080:80
    links:
      - db
    volumes:
      - ./nc_html:/var/www/html
      - ./nc_data:/var/www/html/data
    environment:
      - MYSQL_PASSWORD={userパスワード}
      - MYSQL_DATABASE=nextcloud
      - MYSQL_USER=nextcloud
      - MYSQL_HOST=db
  • イメージタグを最新かつ安定してそうなバージョンに指定
  • マウント方法の変更(名前付きボリューム⇒ホストディレクトリ)
    • LXCを移行する際に取り出しが簡単なため

コンテナを構築していきます。

mkdir ~/nextcloud
cd ~/nextcloud
vim.tiny compose.yaml  # 上記compose.yamlを記述
docker compose up -d

ブラウザで「{LXC-A IP}:8080」でアクセスすると画面が表示されます。

NextCloudアカウントの作成

ブラウザ画面の指示に従いアカウントを作成していきます。
推奨アプリのインストールを促されますが、ファイル保存しか興味がないので「スキップ」しました。

ダッシュボードが表示され、アカウント登録は完了です。
一応MariaDBと連携できるか確認します。

「右上のユーザーアイコン」->「管理者設定」->「システム」を選択
「ディスク」項目を見ると空き容量を確認できます。

「データベース」項目の「タイプ」からmysql(MariaDB)を確認できます。バージョンもcompose.yamlと一致しています。

ターミナルからも確認可能です。

cat ~/nextcloud/nc_html/config/config.php


"db_type"がmysqlになっていればOKです。うまく連携されていないとデフォルトのsqliteになります。

Tailscaleの構築(LXC-B)

Tailscaleはゼロトラストで通信保護するVPNサービスです。VPN周りは詳しくないですが、従来のVPNサービスより非常に簡単かつセキュアにVPN環境を構築できるみたいです。

また、Tailscaleのもう一つの機能として「サブネットルーター」があります。
サブネットルーター機能を使うことで、VPNに直接デバイス登録しなくてもサブネット下のデバイスであればVPNを通して通信可能になります。今回の構成はNextCloudと別ホストにしているため、この機能を使って外部接続を実現させます。

公式ページ動画から抜粋

TailscaleのAuthキー取得

Tailscaleのアカウント作成をします。
https://tailscale.com/

「Start connecting devices」から作成画面に進みます。

最初のデバイス登録が促されますが「Skip this introduction」で飛ばします。

「Settings」->「Keys」->「Auth keys」->「Generate auth key...」を選択し、以下の内容でAuthキーを作成(各項目の説明は割愛しますが、拘りなければこれでOK)

「tskey-auth-*******」というAuthキーが生成されるのでコピーして控えておきます。

PVEホスト側での設定(/dev/tun権限付与)

LXC-Bで/dev/tunにアクセスするための設定をします。/dev/tunはVPN接続用デバイスファイルです。
PVEホストから設定します。

左サイドバーの「pve」->「シェル」からログインし、LXC-Bの設定ファイルを開きます。

vim.tiny /etc/pve/lxc/{LXC-BのID}.conf  # IDは左サイドバーに表示される数字(例:101)

ファイルの一番下に下記2行を追記します。

lxc.cgroup2.devices.allow: c 10:200 rwm
lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file

設定を反映するためにLXC-Bを再起動します。

pct reboot 101

https://tailscale.com/kb/1130/lxc-unprivileged

IPフォワーディング有効化

IPフォワーディングを有効化することでルータとして各IPにパケット転送できるようにします。
LXC-Bのターミナルで実行します。

/etc/sysctl.dが存在する場合

echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf

/etc/sysctl.dが存在しない場合

echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p /etc/sysctl.conf

公式記載の通りです。
https://tailscale.com/kb/1019/subnets#enable-ip-forwarding

コンテナの構築

LXC-Bのターミナルを開いてDocker ComposeでTailscaleを構築していきます。
以下のイメージを使っていきます。
https://hub.docker.com/r/tailscale/tailscale

参考情報
https://tailscale.com/kb/1453/quick-guide-docker
https://tailscale.com/kb/1282/docker
https://tailscale.com/kb/1019/subnets

コンテナ環境定義(compose.yamlファイル)

services:
  vpn:
    image: tailscale/tailscale:v1.88.3
    restart: unless-stopped
    hostname: personal_nas
    environment:
      - TS_AUTHKEY=${TS_AUTHKEY}
      - TS_ROUTES=${TS_ROUTES}
      - TS_EXTRA_ARGS=--accept-routes
      - TS_USERSPACE=false
      - TS_STATE_DIR=/var/lib/tailscale
    devices:
      - /dev/net/tun
    volumes:
      - ./tailscale_data:/var/lib/tailscale
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    network_mode: host

環境変数の定義(.envファイル)

TS_AUTHKEY=tskey-auth-*******   -> 取得したAuthキー
TS_ROUTES=192.168.0.0/24        -> サブネットワーク設定(自宅NW全範囲を指定)

cap_addオプションを初めて使いました。感覚としては特権モード(--priviliged)は全ての権限付与をする一方、cap_addは個別で指定ができる感じ。ただし厳密には権限管理の範囲が異なるらしい。

  • NET_ADMINはVPNとLAN間のルーティング設定に必要。
  • SYS_MODULEはカーネルモジュールの操作権限。Tailscaleは内部的にVPNプロトコルのWireGuardを使用。WireGuardがカーネルモジュールで動作するために必要。

コンテナを構築していきます。

mkdir ~/tailscale
cd ~/tailscale
vim.tiny compose.yaml  # 上記compose.yamlを記述
vim.tiny .env          # 上記.envを記述
docker compose up -d

Tailscaleの管理コンソール画面を開きます。

デバイスが追加されていたらひとまず成功です
デバイス右横の「3点リーダ」->「Edit route settings...」を開く

サブネットルータ機能を有効(チェック)して「Save」

これにて自宅NAS+VPNの環境構築は完了です✌️

外部NWからNextCloudに接続する

一通り環境は揃ったので実際にiPhone(モバイルデータ通信)から自宅NASに写真をアップロード、ダウンロードしてみたいと思います。

VPN設定

TailscaleアプリからVPN設定をします。

  1. App Storeで「Tailscale」をインストール

  2. アカウントログインまで進める
     途中でVPN構成の追加許可を問われるが、許可を選択して構成追加

  3. 「Connect」ボタンを押してデバイス登録完了

NextCloudへの接続確認

NextCloudアプリをインストールします。

  1. App Storeで「Next Cloud」をインストール
  2. もしこの時点で自宅LANに接続していたら解除しモバイルデータ通信に切り替えてください
  3. NextCloudを開くと接続先が問われるので、自宅LANで接続するときと同様に"Local IP:Port"(例:192.168.0.100:8080)でアクセス

4.ストレージ画面が表示されたら成功です。適当にフォルダやテキストを作成してPC側でも反映されているか確認してみてください。

終わり!

以前からやってみたかった自宅NAS、VPNの構築をしてみました。
家の外なのに自宅LANに接続できるって感動しますね!

Proxmox、Nextcloud、Tailscaleと初めての要素が多かったので実は結構苦戦しましたが、それでも記事書きつつ丸1日くらいで終えれました。この構成が手軽に無料で組めるなんてすごい世の中です。

とりあえずiPhoneの救出をしに行ってきます👋

Discussion