wireguardを利用した自宅ファイルサーバーの構築

## はじめに
外出先からでも自宅ファイルサーバーにアクセスしたいけど、ドメイン取得とかめんどくさい！って人向けの記事
DockerでnextCloudとwireguard(vpn)を立ち上げ、スマホからアクセスするところまで

## 環境
macOS: 14.2.1(Sonoma)
docker: v24.0.7
docker-compose: v2.23.3
※すでにdocker・docker-composeのインストール及び、初期設定が完了していることを想定


## ディレクトリ構成
```
.
├── nextCloud
│   ├── .env
│   ├── docker-compose.yml
│   └── outputVolumes
│       └── .gitignore
└── wireguard
    ├── config
    │   └── .gitignore
    └── docker-compose.yml
```

## ファイル内容
### ./nextCloud/docker-compose.yml
```
version: "3.7"
services:
  nextcloud_main:
    image: nextcloud
    container_name: nextcloud_main
    environment:
      TZ: Asia/Tokyo
    volumes:
      - ./outputVolumes/nextcloud/data:/var/www/html/data
      - ./outputVolumes/nextcloud/config:/var/www/html/config
    ports:
      - 80:80
    restart: unless-stopped

  nextcloud_db:
    image: mariadb
    container_name: nextcloud_db
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - ./outputVolumes/mariadb/mysql:/var/lib/mysql
    restart: unless-stopped
```
restart: unless-stopped・・・手動でコンテナを停止した場合を除き、PCを再起動した際に自動でコンテナを立ち上げ直してくれる

### ./wireguard/docker-compose.yml
```
version: "3"
services:
  wireguard:
    image: linuxserver/wireguard
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      - PUID=1000 # ホストのuid(「$ id」)
      - PGID=1000 # ホストのgid(「$ id」)
      - TZ=Asia/Tokyo # タイムゾーン
      - SERVERURL=auto # ドメイン名
      - SERVERPORT=51820 # ポート
      - PEERS=5 # 接続できる端末数
      - PEERDNS=auto
      - INTERNAL_SUBNET=10.13.13.0 # VPNのネットワークアドレス
      - ALLOWEDIPS=0.0.0.0/0 # 疎通を許可するネットワーク
    volumes:
      - ./config:/config
      - /lib/modules:/lib/modules
    ports:
      - 51820:51820/udp
    restart: unless-stopped
```
色々コメントが書かれているが、基本何も変えなくても良い
environmentの「PEERS」の値を「vpnを使用したい端末の数」に合わせて変更する

### ./nextCloud/.env
```
# MariaDB
MYSQL_ROOT_PASSWORD=root
MYSQL_DATABASE=nextcloud
MYSQL_USER=user
MYSQL_PASSWORD=password
```
値は各自で変更

### ./nextCloud/outputVolumes/.gitignore  ./wireguard/config/.gitignore
```
*
!.gitignore
```
蓄積されたデータを間違えてgitにあげてしまうのを阻止する役割
また、gitにあげる際にoutputVolumesフォルダが空だった場合、フォルダ自体が削除されてしまうのでその対策

## nextCloud立ち上げ
ターミナル(コマンドライン)を起動し、先ほどのディレクトリ配下まで移動
nextCloudフォルダ配下に移動し、コンテナを起動させる
```
$ cd ./nextCloud
$ docker-compose up -d
$ docker ps (起動中のコンテナ確認コマンド)
```
ブラウザで http://localhost:80 を検索バーに打ち込み、この画面が表示されれば成功
![スクリーンショット 2024-01-16 17.13.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320196/d160cd06-846a-8fae-aa0e-31b3e3ff3fdd.png)

管理者のユーザー名、パスワードを自由に入力後、その下にある「ストレージとデータベース」を押下し、「MySQL/MariaDB」を選択

各設定は以下の通り
|欄|入力値|
|---|---|
|データベースのユーザー名|./nextCloud/envで設定した「MYSQL_USER」の値|
|データベースのパスワード|./nextCloud/envで設定した「MYSQL_PASSWORD」の値|
|データベース名|./nextCloud/envで設定した「MYSQL_DATABASE」の値|
|データベースのホスト名|./nextCloud/docker-compose.ymlに記載されたDBサービスの名前|

![スクリーンショット 2024-01-16 17.30.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320196/96f72500-a030-c239-13e9-47fafc9eaa28.png)

インストールボタンを押下し、少し待つとトップ画面が表示されるので、「フォルダ」を選んでファイルのアップロード・ダウンロードが正常に動作するかを確認する

## wireguard立ち上げ
ターミナルでwireguardフォルダ内へ移動し、コンテナを起動させる
```
$ cd ./wireguard
$ docker-compose up -d
```
正常に起動できていれば wireguard/config/ 配下に「peer~」というフォルダがdocker-compose.ymlに設定した「PEERS」の数だけ生成されている
![スクリーンショット 2024-01-16 17.39.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320196/b714eeb4-ad2d-b15d-85d3-52844fff24dc.png)

### vpnを使用したい端末にアプリをインストールする
https://www.wireguard.com/install/

iPhone・Androidからファイルサーバーにアクセスする場合は、アプリを起動後「QRコードをスキャン」を選択し、 peer1/peer1.png を読み込む

windows・macからファイルサーバーにアクセスする場合は、はアプリを起動後「ファイルからトンネルをインポート」を選択し、 peer1/peer1.conf を読み込む

## 実際に試してみる
nextCloudに接続する端末を「<font color="red">接続元</font>」、
nextCloudを立ち上げたPCを「<font color="blue">接続先</font>」と呼称する
1. <font color="red">接続元</font>のWi-Fi接続を切り、モバイル通信をONにする(ファイルサーバーと同じWi-Fiに接続していたら正しくvpnが機能しているかわからない為)
1. <font color="red">接続元</font>のwireguardアプリを開き、vpnをonにする
1. <font color="blue">接続先</font>のipアドレスを確認する(192.168.xxx.xxx)
1. <font color="red">接続元</font>でブラウザを開き、 http://192.168.xxx.xxx を検索バーに打ち込む
1. 正常にnextCloudの画面が表示されていればOK🎉

※「信頼できないドメインを介したアクセス」と表示される場合は以下を追記する
./nextCloud/outputVolumes/nextcloud/config/config.php
```
'trusted_domains' => 
  array (
    0 => 'localhost',
    1 => '192.168.xxx.xxx', <== 追記箇所 (192.168.xxx.xxxは実際のIPアドレスを入れる)
    
    # docker-compose.ymlでポートを80以外に設定した場合は「1 => '192.168.xxx.xxx:8080'」のように書く
  ),
```

※「このページは動作していません」と表示される場合は、<font color="blue">接続先PC</font>のパーソナルファイアウォールが有効化されているかもしれないのでPCの設定を見直す

※vpnがONの状態で通常のweb検索も行えない場合は、ルーターの転送ルールを設定する
(例)
![ポートマッピング.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320196/b48d4492-9603-a67e-407b-0cc2bb092598.png)

※コンテナを停止させたい場合は、nextCloud・wireguardそれぞれのディレクトリで「$ docker-compose down」を実行する

## まとめ
### メリット
・Dockerを使った構築のため、PCを汚さずに素早く立ち上げることが可能
・サーバーの契約やドメイン取得、サーバー証明書が不要で、どこからでもアクセスできるファイルサーバーを立ち上げられる
・**無料**

### デメリット
・あくまで遊びや練習レベルのものなので、実際に運用していくとなるとセキュリティが不十分
・ファイルサーバーのIPアドレスを固定しないとアクセスできなくなる可能性がある(各環境でルーターもしくはPCからIP固定化する)
・~~NASでよくね？~~

### その他
今回は一つのPCにファイルサーバーとvpnサーバーを構築したが、wireguardをraspiなどの消費電力少なめのマシンで常に立ち上げつつ、ファイルサーバーはもっとストレージに余裕があるPCで基本は電源OFF、必要に応じてWoL(Wake On LAN)で電源を入れる運用にすると電気代の節約になる

また、今回はドメインなし・サーバー証明書なしで構築したが、MyDNSなどで無料ドメインを取得し、「jrcs/letsencrypt-nginx-proxy-companion」でサーバー証明書を取得する構成にすればvpnを使用しなくても通常のサイトと同じようにアクセスできるようになる

## さいごに
今回の記事がQiita初投稿なので、色々至らずところあると思いますが、コメントもしくはご指摘いただけると励みになります！🙇‍♂️🙇‍♂️🙇‍♂️

## 追記(2024/01/18)
### WireGuardをWebUIで管理したい
コメントをいただいて、確かにと思ったので追記
> 自分自身の経験上、ノードが増えていくと対応できなくなるため、WireGuard Easyなどを使わずに、素のWireGuardを使うのは、苦行以外の何物でもないと思います。

#### WireGuard Easyとは
ざっくりいうと webUI で WireGuard を一元管理できるもの(便利ですね)

https://github.com/wg-easy/wg-easy

使用する場合は以下の手順に沿って作成する

#### ディレクトリ構成
wireguardEasyディレクトリを新たに追加
```
.
├── nextCloud
├── wireguard
└── wireguardEasy
    ├── .env
    ├── etc_wireguard
    │   └── .gitignore
    └── docker-compose.yml
```
wireguard フォルダは必要なくなるので「$ docker-compose down」を実行し削除してしまっても良い

#### ./wireguardEasy/docker-compose.yml
```
version: "3.8"
services:
  wg-easy:
    image: ghcr.io/wg-easy/wg-easy
    container_name: wg-easy
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      PASSWORD: ${WG_EASY_WEB_PASSWORD} # WebUIにパスワードをつけない場合は不要
      WG_HOST: ${WG_EASY_HOST}
    ports:
      - 51820:51820/udp
      - 51821:51821/tcp
    restart: unless-stopped
    sysctls:
      - net.ipv4.ip_forward=1
      - net.ipv4.conf.all.src_valid_mark=1
    volumes:
      - ./etc_wireguard:/etc/wireguard
```

#### ./wireguardEasy/.env
```
# wg-easy
WG_EASY_WEB_PASSWORD=password
WG_EASY_HOST=example.co.jp // 自身が取得しているドメインに置き換える
```
ドメインを取得していない場合はグローバルIPアドレス(例: 123.45.678.123)でもOK

https://rakko.tools/tools/2/

※静的なグローバルIPでない場合はルーターの再起動等で、アドレスが別のものに振り直されてしまう事があるので注意

#### 起動
ファイル作成後は、他ディレクトリと同様に「$ docker-compose up -d」をターミナルで実行すればコンテナが起動する
http://localhost:51821 にアクセスし、こんな画面が出れば成功🎉
![スクリーンショット 2024-01-18 1.31.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320196/c140fa5c-56d0-19c2-af25-8f8a5d826fa9.png)