自宅サーバをはじめる

はじめに

自宅サーバを導入した。Webページを公開したり、Discord Botを動かしたり、DNSで広告を遮断したりと用途はいくつかあるが、何か明確なサービスを必要としていたというより、サーバというものを自分で所有し、構築し、壊しながら遊んでみたかったという理由が大きい。

使用しているマシンは GMKtec NucBox G3 Plus である。Intel N150、RAM 16 GB、SSD 512 GBという小型PCで、購入価格はおよそ2万円だった。

Proxmox VEを入れる

物理マシンに直接Ubuntuなどを入れて、その上ですべてのサービスを動かすこともできる。しかし今回は、Proxmox VEを導入した。

Proxmox VEはDebianを基盤とした仮想化環境で、KVMによる仮想マシンとLXCによるコンテナを一つの管理画面から扱える。したがって、物理マシン一台をいくつかの独立した計算機に分割して使うことができる。

自宅サーバを始めた段階では、どのサービスをどのような構成で運用することになるのか分からない。その状態で一つのOSにすべてを直接インストールすると、試しに導入したソフトウェアや設定が徐々に蓄積し、何がどのサービスのために存在しているのか分からなくなりやすい。

そこで、最初はサービスごとにLXCを分けることにした。たとえばDNSサーバを試したければDNS用のLXCを作り、VPNを試したければVPN用のLXCを作る。不要になればそのコンテナごと削除できる。失敗しても他のサービスへの影響を限定できるし、バックアップやスナップショットも取りやすい。

この段階では、コンテナを細かく分けること自体が目的というより、「よく分からないもの同士を最初から混ぜない」ための境界としてLXCを利用する。

Proxmox自体には、たとえば次のようなアドレスを設定している。

FQDN        server.example.internal
IP Address  192.168.1.10/24
Gateway     192.168.1.1
DNS         192.168.1.1

同一LANから https://192.168.1.10:8006 にアクセスすると、Web UIから仮想マシンやLXCを管理できる。

LXCとVMをどう使うか

運用を続けると、「サービス一つにつきLXC一つ」という構成が必ずしも扱いやすいわけではないことが分かる。

LXCは軽量で便利だが、それぞれのLXCの中に直接アプリケーションとその依存関係をインストールしていくと、今度はLXCそのものを個別に管理する必要が生じる。サービスが増えるほど、パッケージの更新方法、設定ファイルの場所、デプロイ方法などがばらばらになっていく。

現在は、アプリケーションについてはVMを一台の実行基盤として用意し、そのVM内部でDockerコンテナとして管理する構成を主に使っている。

概念的には次のような構造になる。

Physical Server
└── Proxmox VE
    ├── LXC: VPN
    ├── LXC: DNS
    └── VM: Application Host
        ├── Container: Web
        ├── Container: Discord Bot
        └── Container: その他のアプリケーション

現時点では、

  • ネットワークへの接続経路そのものを担うもの
  • その他のアプリケーション

という程度の境界を設けている。自宅サーバでは最初から完全な構成を設計するより、運用しながら「一緒に管理したいもの」と「故障や変更を分離したいもの」の境界を見つけていく方が自然なのだと思う。

外部から自宅へ入る

自宅サーバを置くと、次に問題になるのが外部との通信である。LANの中だけで利用するなら簡単だが、Webサイトをインターネットに公開したり、外出先から自宅のサービスへ接続したりする場合には、自宅ネットワークと外部との境界を考える必要がある。

現在は用途によって二つの経路を使っている。

Webサービスの公開にはCloudflare Tunnelを利用している。自宅ルータのポートをインターネットへ直接開放する代わりに、自宅側からCloudflareへトンネルを確立し、その経路を通してHTTPリクエストを受け取る。

一方、自分自身が外部からLANへ接続するときにはTailscaleを利用している。Tailscale用のコンテナをサブネットルータとして動かし、自宅LANの 192.168.1.0/24 へ外部からアクセスできるようにしている。

アプリケーションを動かす

実際に利用するアプリケーションを配置する。Webサイト、Discord Bot、そのほか常時動かしておきたいプログラムなどである。

アプリケーションはできるだけコンテナイメージとして扱う。ホストOSに直接依存関係をインストールするのではなく、アプリケーション、実行環境、依存ライブラリをまとめた単位として配布し、そのイメージをサーバ側で起動する。

構築手順をコードにする

ProxmoxのWeb UIからLXCを作り、SSHで入り、必要なパッケージを手動でインストールする作業が主である。数台であればこれで問題ない。しかし、一度作った環境を作り直したくなったときに困る。

たとえば一つのコンテナについて、

Ubuntuを作成する

固定IPを設定する

ユーザーを作る

SSHを設定する

必要なパッケージを入れる

設定ファイルを置く

サービスを起動する

という操作を行っていたとしても、その手順が自分の記憶にしか残っていなければ、同じ環境をもう一度作ることは難しいし、手間である。

そこでTerraformとAnsibleを導入した。

TerraformにはProxmox上にどのような仮想マシンやLXCが存在するべきかを書く。CPU、メモリ、ネットワーク、ディスクといった、仮想マシンそのものの構成を扱う。

その上でAnsibleを使い、作成されたOS内部の状態を設定する。パッケージをインストールし、設定ファイルを配置し、サービスを有効化する。

おおまかには、

物理マシン

Proxmox

Terraform

VM / LXC

Ansible

OSの設定

Docker Composeなど

アプリケーション

という層になっている。

すべてをコード化したからといって、突然運用が簡単になるわけではない。むしろ、小規模な自宅サーバにTerraformやAnsibleを持ち込むことは過剰である。ただし、その過剰さも自宅サーバを持つ目的の一つであろう。Terraformを試すためにAWSへ大量のリソースを作る必要はないし、Ansibleを学ぶために何十台もの実機を用意する必要もない。自宅に一台のProxmoxがあれば、小さいながらも実際に壊れる可能性のあるインフラを対象に試すことができる。