自宅にGitLabサーバとUnboundを用いたDNSサーバを建てる

# 背景

業務ではクラウドにしか触ったことがないインフラエンジニアですが、このままではお膳立てされた環境の上でしか生きられない弱々しくハリボテなインフラエンジニアにしかなれないと感じ、自宅サーバ上での環境構築を行っていきたいと考えるようになりました。
今回はその第一弾として、GitLabサーバを自宅サーバ上に建て、自宅LAN内からFQDNでアクセスできるようにしたいと思います。

# ゴール

- Proxmoxサーバ上のVMにGitLabサーバを構築する
- Proxmoxサーバ上のVMにDNSサーバを構築し、自宅LAN内からGitLabサーバへFQDNでアクセスできるようにする。
  - DNSサーバソフトウェアとしてはUnboundを採用

:::note info
なお、今回は仮想化基盤としてProxmoxを利用していますが、GitLabサーバ・DNSサーバの構築に関する内容は仮想化の有無、基盤に関係なく動作する想定です。
:::

### DNSサーバ：使用するソフトウェア

DNSサーバを構築するにあたってはUnboundというソフトウェアを利用しました。
今回必要となるDNSサーバの機能として必要なものは、

- 家庭内LANのクライアントからGitLabサーバのFQDN (今回の場合は`http://gitlab.hoge.home`)へアクセスしようとした場合
  - クライアントは本DNSサーバへ名前解決をし、GitLabサーバのプライベートIPアドレスを返す。
- 家庭内LANのクライアントからインターネット上のFQDN(例えば`https://google.com`)へアクセスしようとした場合
  - クライアントは本DNSサーバへ名前解決をする。対象のFQDNが本DNSサーバの管理配下にない場合には、上位ののDNSコンテンツサーバへクエリを投げて名前解決をし、対象FQDNのグローバルIPアドレスを返す。

となります。

![スライド1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001728/0c0dc9e4-885d-5db1-fe9c-85656c871f1d.png)


Unboundは、オランダのNLnet Labsの開発しているオープンソースのDNSキャッシュサーバです。基本的にはDNSキャッシュサーバとして機能しますが、local-data機能を利用することでDNSコンテンツサーバとしての機能を持たせることができます。

本格的にDNSコンテンツサーバを構築するのであればNSDやBIND等を利用して構築する方が良いようですが、今回の要件においてはUnboundで十分機能するため、Unboundを利用することとしました。

# GitLabサーバを構築する

### 準備

※Proxmoxサーバの構築および、ProxmoxでのVM作成については今回の記事では割愛します。ここではProxmoxで新規VMを用意する前提で記述しています。

GitLabサーバの構築には複数のOSが利用できますが、今回はAlmaLinuxを採用しました。
[GitLab公式サイト : 利用できるOSとインストール方法](https://about.gitlab.com/ja-jp/install/)
VMを構築したらGitLabをインストールしていきます。

### GitLabをVMにインストールする

1. **GitLabパッケージリポジトリを追加してパッケージをダウンロードする**
   以下のコマンドを実行し、GitLabをダウンロードします。

   ```bash
   curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
   ```

   ◼︎ 実行結果

   ```bash
    [gitlab@localhost ~]$ curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
    # 略
    完了しました!
    # 略
    The repository is setup! You can now install packages.
   ```

    :::note info
    なお、公式サイトでは`gitlab-ee`をダウンロード・インストールする手順が記載されていますが、ここでは`gitlab-ce`を利用するため、適宜読み替えています。

   - GitLab EE : GitLab Enterprise Edition
   - GitLab CE : GitLab Community Edition

   このあたりのくわしい話は以下のページで整理していただいておりました。ご確認ください。
   https://techblog.ap-com.co.jp/entry/2023/12/05/191705
   :::

2. **GitLabをインストールする**
   以下のコマンドを実行し、GitLabをインストールします。

   ```bash
   sudo EXTERNAL_URL="http://gitlab.hoge.home" dnf install -y gitlab-ce
   ```

   `EXTERNAL_URL`の値は任意の値を指定しますが、この値は後ほど構築する自宅内DNSサーバに登録する値と同値とします。ここでは`gitlab.hoge.home`としています。
   また、今回は自宅内GitLabサーバの構築ですので、プロトコルは`https`ではなく、`http`としています。

    ◼︎ 実行結果

   ```bash
    [gitlab@localhost ~]$ sudo EXTERNAL_URL="http://gitlab.hoge.home" dnf install -y gitlab-ce
    # 略
    Notes:
    Default admin account has been configured with following details:
    Username: root
    Password: You didn't opt-in to print initial root password to STDOUT.
    Password stored to /etc/gitlab/initial_root_password. This file will be cleaned up in first reconfigure run after 24 hours.
    
    NOTE: Because these credentials might be present in your log files in plain text, it is highly recommended to reset the password following https://docs.gitlab.com/ee/security/reset_user_password.html#reset-your-root-password.
    
    gitlab Reconfigured!
    
           *.                  *.
          ***                 ***
         *****               *****
        .******             *******
        ********            ********
       ,,,,,,,,,***********,,,,,,,,,
      ,,,,,,,,,,,*********,,,,,,,,,,,
      .,,,,,,,,,,,*******,,,,,,,,,,,,
          ,,,,,,,,,*****,,,,,,,,,.
             ,,,,,,,****,,,,,,
                .,,,***,,,,
                    ,*,.
      
    
    
         _______ __  __          __
        / ____(_) /_/ /   ____ _/ /_
       / / __/ / __/ /   / __ `/ __ \
      / /_/ / / /_/ /___/ /_/ / /_/ /
      \____/_/\__/_____/\__,_/_.___/
      
    
    Thank you for installing GitLab!
    # 略
    完了しました!
   ```

### GitLabの動作確認をする

インストールが正常に完了したら、GitLabの動作確認をしましょう。
以下のコマンドを実行して、rootユーザのパスワードを取得します。

```bash
cat /etc/gitlab/initial_root_password
```

◼︎ 実行結果

```bash
[gitlab@localhost ~]$ sudo cat /etc/gitlab/initial_root_password
# WARNING: This value is valid only in the following conditions
#          1. If provided manually (either via `GITLAB_ROOT_PASSWORD` environment variable or via `gitlab_rails['initial_root_password']` setting in `gitlab.rb`, it was provided before database was seeded for the first time (usually, the first reconfigure run).
#          2. Password hasn't been changed manually, either via UI or via command line.
#
#          If the password shown here doesn't work, you must reset the admin password following https://docs.gitlab.com/ee/security/reset_user_password.html#reset-your-root-password.

Password: xxxxxxxxxxxxxxxxxxxxxxxxxxx

# NOTE: This file will be automatically deleted in the first reconfigure run after 24 hours.
```

パスワードを取得したら、GitLabをインストールしたサーバのIPアドレスを取得し、手元のPCからアクセスします。
アクセス先：`http://{GitLabをインストールしたサーバのIPアドレス}`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001728/9d00bed9-735b-738a-3805-df8f34412f5d.png)

GitLabのログイン画面が表示されたら、以下のユーザ情報でログインを試行します。
ユーザ名 : `root`
パスワード : 前段で取得した初期パスワード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001728/37e37424-a2c3-d708-91fd-385b73f1a799.png)


GitLabのトップページへアクセスできたら成功です。

# DNSサーバを構築する

### 準備

※GitLabサーバと同様にProxmoxサーバの構築および、ProxmoxでのVM作成については今回の記事では割愛します。

OSについては今回はUbuntuを採用しました。
[日本Unboundユーザー会 : Unboundのパッケージの状況](https://unbound.jp/unbound/packages/)
VMを構築したらUnboundをインストールしていきます。

### UnboundをVMにインストールする

1. **Unboundのインストール**
   構築したDNSサーバにログインし、以下のコマンドを実行します。

   ```bash
   sudo apt-get install unbound
   ```

   インストールが完了したら自動的にUnboundが起動します。
   以下のコマンドを実行して、Unboundが53番ポートをリッスンしているかを確認します。

   ```bash
   sudo ss -lntp | grep unbound
   ```

   ◼︎ 実行結果

   ```bash
   dns-admin@dns-sv:~$ sudo ss -lntp | grep unbound
   LISTEN 0      256        127.0.0.1:53        0.0.0.0:*    users:(("unbound",pid=2093,fd=6))        
   LISTEN 0      256        127.0.0.1:8953      0.0.0.0:*    users:(("unbound",pid=2093,fd=8))        
   LISTEN 0      256            [::1]:53           [::]:*    users:(("unbound",pid=2093,fd=4))        
   LISTEN 0      256            [::1]:8953         [::]:*    users:(("unbound",pid=2093,fd=7))   
   ```

   8953ポートはUnboundの制御用に待ち受けているポートです。

2. **Unboundの設定**
   現時点でもDNSキャッシュサーバとして機能していますが、local-data機能を利用してGitLabサーバを名前解決できるようにします。
   Unnoundの設定は以下のファイルに記載します

   ```bash
   cat /etc/unbound/unbound.conf
   ```

   ◼︎ 実行結果

   ```bash
   dns-admin@dns-sv:~$ cat /etc/unbound/unbound.conf
   # Unbound configuration file for Debian.
   #
   # See the unbound.conf(5) man page.
   #
   # See /usr/share/doc/unbound/examples/unbound.conf for a commented
   # reference config file.
   #
   # The following line includes additional configuration files from the
   # /etc/unbound/unbound.conf.d directory.
   include-toplevel: "/etc/unbound/unbound.conf.d/*.conf"
   ```

   最終行から分かるように設定ファイルは`/etc/unbound/unbound.conf.d/`ディレクトリ内の`*.conf`ファイルとして保存しておけば良いことがわかります。

   ここでは設定ファイルを以下の2ファイルに分割します。

   - `/etc/unbound/unbound.conf.d/server.conf`
     - DNSサーバとしての基本的な設定を記述する
   - `/etc/unbound/unbound.conf.d/local-data.conf`
     - local-data機能を利用するために必要な設定を記述する

   #### server.conf

   以下のコマンドを実行し、`server.conf`を編集します。(新規作成になります。)

   ```bash
   sudo vi /etc/unbound/unbound.conf.d/server.conf
   ```

   ◼︎ etc/unbound/unbound.conf.d/server.conf に記述する内容

   ```bash
   server:
       interface: 0.0.0.0
       access-control: 127.0.0.1/32 allow
       access-control: 192.168.1.0/24 allow
   ```

   - 2行目 : `interface`
     - 全IPアドレス範囲 `0.0.0.0` からのクエリーをリッスンします。
   - 3~4行目 : `access-control`
     - 明示的なアクセス許可を記述します。
     - 自分自身 `127.0.0.1` と家庭内LANのCIDRを指定します。

   編集が完了したら、保存します。

   #### local-data.conf

   以下のコマンドを実行し、`local-data.conf`を編集します。(新規作成になります。)

   ```bash
   sudo vi /etc/unbound/unbound.conf.d/local-data.conf
   ```

   ◼︎ /etc/unbound/unbound.conf.d/local-data.conf に記述する内容

   ```bash
   server:
       local-data: "gitlab.hoge.home.    IN A 192.168.1.100"
   ```

   - 2行目 : `local-data`
     - `"{FQDN}. IN A {対象サーバのIPアドレス}"` の書式で記載します。
     - FQDNの後にピリオド`.`を置くことを忘れないようにしてください。
     - 他にも名前解決させたいホストが存在する場合には3行目以降に同様の記述を続けます。

3. **systemd-resolvedの無効化**
   以上でUnboundの設定は完了ですが、設定を有効化する前にUnboundと同じく53番ポートをリッスンするsystemd-resolvedを無効化します。無効化しないとUnbound起動時にエラーが発生します。
   以下のコマンドを実行します。

   ```bash
   sudo systemctl disable systemd-resolved
   ```

   ◼︎ 実行結果

   ```bash
   dns-admin@dns-sv:~$ sudo systemctl disable systemd-resolved
   Removed /etc/systemd/system/multi-user.target.wants/systemd-resolved.service.
   Removed /etc/systemd/system/dbus-org.freedesktop.resolve1.service.
   ```

4. **サーバの再起動**
   Unboundへの設定を反映するためにサーバを再起動します。
   ※本来はUnboundサービスのみの再起動で良いのですが、私の環境ではエラーが発生したため、サーバごとの再起動をここでは行います。

   ```bash
   sudo reboot
   ```

### Unboundの動作確認をする

#### DNS設定を変更する

DNSサーバの再起動が完了したら、Unboundの動作確認を行いましょう。
まずは、LAN内のクライアントのネットワーク設定を変更して構築したDNSサーバで名前解決をするように変更しましょう。

ここでは、Macでの設定例を紹介します。

1. Commandキー + Spaceキーを押下し、Spotlight検索を開き、「DNSサーバ」と入力する
2. 候補に表示された「DNSサーバ」を開く
3. ［DNSサーバ］欄の［＋］ボタンを押下して、構築したDNSサーバのIPアドレスを入力する
4. ［DNSサーバ］欄に記載のある他のDNSサーバのIPアドレスを選択してから［ー］ボタンを押下して、手順3で追加したDNSサーバ以外の登録を削除する

◼︎DNSサーバのIPアドレスが`192.168.1.53`の場合の設定例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1001728/36d0d253-fa23-d94b-3e7c-ea59fcea91a3.png)

#### 名前解決をしてみる

DNSサーバに関するネットワーク設定を実施したクライアントで以下のコマンドを実行し、LAN内のGitLabサーバとインターネット上のホストを名前解決できているかを確認してください。

```bash
dig gitlab.hoge.home
dig google.com
```

◼︎ 実行結果

```bash
myaccount@mymac ~ % dig gitlab.hoge.home
# 略
;; ANSWER SECTION:
gitlab.hoge.home.	3600	IN	A	192.168.1.100
# 略

myaccount@mymac ~ % dig google.com
# 略
;; ANSWER SECTION:
google.com.		300	IN	A	142.250.207.110
# 略
```

- `gitlab.hoge.home`のIPアドレスとして`192.168.1.100`が返ってきていること
- `google.com`のIPアドレスが返ってきていること

が確認できたので、名前解決の動作確認は完了です。

#### GitLabサーバへアクセスする

最後にGitLabサーバへWebアクセスしてみましょう。
Webブラウザのアドレスバーに`http://gitlab.hoge.home`を入力し、移動します。

GitLabページへアクセスできたら成功です。

# 補足

### Unbuondの設定について
構築したDNSサーバが参照するより上流のDNSサーバはDNSサーバのOS設定に依存します。
これは、今回の設定ではUnboundに対して明示的に上流のDNSサーバを指定する設定を行っていないからです。
Unboundに対して明示的に上流のDNSサーバを指定するには`unbound.conf`ファイル(またはそこにincludeされるファイル)に対して`forward-zone`の設定を追加する必要があります。
このように、今回は最低限の設定のみを実施しています。詳しい設定ファイルの書き方は以下のサイトをご参照ください。
[日本Unboundユーザー会 : unbound.conf(5)](https://unbound.jp/unbound/unbound-conf/)

### バージョン等
- GitLabサーバ
    - OS
        - AlmaLinux　9.4
    - GitLab
        - GitLab Community Edition v17.3.0
- DNSサーバ
    - OS
        - Ubuntu 22.04.4 LTS
    - Unbound
        - Unbound 1.13.1
- クライアント
    - OS
        - macOS 14.3 Sonoma