VPSを踏み台サーバーにしてGitLabをホストしてみる

グローバルIPは用意できないけど、外部からアクセスできるGitlabが欲しい私のためのメモ
色々試行錯誤してみてたどり着いた、一通りのやり方

記事内で断定的に書いてあっても私の知見と環境の中での出来事だから普通に間違ってたりする

もっといいやり方あるかもしれないけど、現時点で問題なく動いてるっぽいからとりあえずよし！

やってることは、ローカルに立てたGitLabサーバーとVPSをVPNで繋いで、VPSの特定のポートに対してのアクセスをGitLabサーバーに転送してるだけ
ついでに、ドメインも取って指定のサブドメインへのアクセスをそのポートに飛ばすようにしてみたり

## 環境

|サーバー| OS|CPU|メモリ|ストレージ|
| :------------: | :------------: | :------------: | :------------: | :------------: |
|GitLabサーバー|Ubuntu 22.04 LTS|i7-4770|16GB|HDD 500GB + SSD 2TB|
|Conoha VPS|Ubuntu 20.04 LTS|1コア|512MB|SSD 30GB|

※Gitlab バージョン : 15.3.1-ee

VPSで Ubuntu を使用する場合
Ubuntu Server 22.04 LTS の最小メモリ要件が1GBのため、Conoha VPSの512MBプランを契約している場合は Ubuntu Server 20.04 LTS までしか使用できない

# VPS (+ドメイン) の契約と設定

ドメインは、GitLabの接続時にipを打ちたくないとか、外部の人と共有するときにドメインがあったほうが分かりやすいとかならあったほうがいいのかも
別になくても問題なく使える
~~私はドメインってなんかかっこいいから上の理由を大義名分にドメインを取った~~

## VPS

今回使ったVPSはConoha VPSの512MBプラン
~~ホームページのデザインが好みだったから~~どのくらいの転送量が必要になるか見当がつかなかったから、よほど使わない限り制限のかからない国内のVPSから選んだけど、しばらく使っていく中で転送量の予想がついてきたらもっと安価で細かくスペックの指定できる海外VPSもありかなぁとは思う

VPSを契約したら、Ubuntu 20.04 LTS を選んで構築する。今回は必要な鍵はあらかじめ作ってあるため後でまとめて転送・設定する

rootユーザーでVPSに接続したら初期設定を行っていく
ターミナルからsshでも接続できると思うが、これからsshの設定も変えていくためここではConoha VPS のターミナルから接続した方が良い

***

- 一般ユーザーの作成

```bash
#一般ユーザーの作成
adduser ユーザー名
#一般ユーザーがsudoを使用できるようにする
gpasswd -a ユーザー名 sudo
```  

一般ユーザーの追加が完了したら一度ログアウトし、追加したユーザーでログインしなおす

***

- sshの設定

```bash
#sshd_configのバックアップを作成
sudo cp -p /etc/ssh/sshd_config /etc/ssh/sshd_config_backup
#sshd_configの編集を開始
sudo vi /etc/ssh/sshd_config
```

エディタを開いたら次の行を探して変更

```
#ssh接続に使用するポートの変更
Port 22
    ↓
Port 2222

#rootユーザーでのssh接続の禁止
PermitRootLogin yes
    ↓
PermitRootLogin no
```

誤った編集を行ってしまいバックアップから復元したい場合

```bash
sudo cp -p /etc/ssh/sshd_config_backup /etc/ssh/sshd_config
```

 SSHがデフォルトで使用する22番ポートはブルートフォースアタックの標的にされやすいらしいので変更しておきます。
 このポートは他のサービスで使用していないポートであれば何番でも大丈夫です

 また、rootユーザーでログインされてしまうとシステムが乗っ取られてしまうため一応rootユーザーでの接続も禁止しておきます

 viの使い方は`i`を押すと編集モードに入り、`Esc`を押してから`:wq`で保存して終了、`:q!`で変更を破棄して保存せずに終了

 編集が完了したらSSHサーバーを再起動する

```bash
sudo systemctl restart sshd
```

***

- ファイアウォールの設定
　追加するポートは2つ
    - 1234 : VPSからGitLabサーバーに接続する際に使用するポート (他のサービスで使用していないポートであれば何番でもよい)
    - 2222 : sshの接続用に設定したポート(他のポートを指定した場合そのポートを追加する)

```bash
#ファイアウォールの有効化
sudo ufw enable
#80番の接続を許可
sudo ufw allow 1234
#2222番のTCP接続を許可
sudo ufw allow 2222/tcp
#ファイアウォールの再読み込み
sudo ufw reload
```

ファイアウォールのルールを削除したい場合
```bash
#ファイヤーウォールのルールを番号と一緒に表示
sudo ufw status numberd

#以下例
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 1234                       ALLOW IN    Anywhere
[ 2] 2222/tcp                   ALLOW IN    Anywhere
[ 3] 1234 (v6)                  ALLOW IN    Anywhere (v6)
[ 4] 2222/tcp (v6)              ALLOW IN    Anywhere (v6)
```

この中から消したいルールの番号を確認して削除する

```bash
#1番のルールを削除したい場合
sudo ufw detele 1
```

若い番号のルールから削除していくと削除する度に割り当てられる番号が変わってしまうため、複数削除する場合は番号の数字の大きいルールから削除していくのが良い
ルールの削除が完了したら忘れずファイヤーウォールの再読み込みを行う

```bash
sudo ufw reload
```

***

- パッケージ更新

```bash
sudo apt update
sudo apt upgrade
```

一通り設定が完了したらVPSを再起動する

```bash
sudo reboot
```

***

ここからは、ターミナルからssh接続で作業しても問題ない

接続するときは

```terminal
ssh username@vps.ip.address -p 2222
```

`username` は作成したユーザー名、`vps.ip.address` はVPSのIPアドレス、 `-p` はssh接続に使用するポートの指定。2222以外に設定した場合は設定した数字に変える

また、このとき次の3点も確認できるとよい
- 一般ユーザーで問題なくログインできること
- rootユーザーでログインできない事
- 22番ポートでログインできない事

最後の22番ポートでログインできないかは`-p`のポート指定をしないと、デフォルトのポートである22番ポートでの接続を試みるため確認できる

***

既にssh接続はできるが毎回パスワードを入力する必要がある為、公開鍵認証を用いた接続が行えるようにする。また、後で設定するVPSとGitLabサーバーも公開鍵認証を用いたssh接続を利用するためそのための鍵の生成も行う

VPSに接続する際の鍵とGitLabサーバーに接続する際の鍵は同じものでも構わないが、GitLabサーバーに接続する際の鍵はパスフレーズの設定ができないため、VPSに接続する際の鍵の安全性を確保したい場合は別々の鍵にする必要がある

これから行う作業はローカルで行う

ホームディレクトリに`.ssh`フォルダがない場合はまずそのフォルダを作成する

```powershell
#ホームディレクトリに移動
cd ~
#.sshフォルダを作成
mkdir .ssh
#作成したフォルダに移動
cd .ssh
```

鍵の生成は以下のコマンドで行う

```powershell
ssh-keygen -t ed25519 -f key_name
```

このコマンドでは`ed25519`という暗号化形式で暗号化された鍵のペアを作成する
`-f` 以下を変更することで好きな名前で保存できる

生成する際にパスフレーズを聞かれるが、VPSとGitLabサーバーに接続する際に使用する鍵に関しては何も入力しない

これは後で起動時に鍵を自動で登録するスクリプトを作成するが、スクリプトの実行時にパスフレーズの入力を求められることで正常に処理が完了できないから

***

次にVPSに一般ユーザーでログインし、`.ssh`フォルダを作成する

```bash
cd ~
mkdir .ssh
```

***

そうしたら、ローカルに戻ってVPSへ鍵ファイルを送信する

```powershell
#.sshフォルダに移動　windows以外ならcd ~/.ssh
cd ~\.ssh
```

鍵ファイルの送信には`scpコマンド`を使用する

```powreshell
scp -P 2222 .\key_file username@vps.ip.adderss:~/.ssh
```

`-P` はssh接続に使用するポートの指定、`.\key_file` は送信するファイルの指定。Windows以外なら `./key_file` みたいな感じ
`username` 以下は最後にどのフォルダに送信するかを指定しているのを除いてssh接続するときと同じ

送信するファイルは、次の2つまたは3つ
ここでは例として、VPS接続だけに使用するパスフレーズ付きの鍵を`vpskey_ed25519`、
VPSとGitLabサーバーの接続に使用するパスフレーズ未設定の鍵を`gitlabkey_ed25519`という名前で生成したとする

名前が`vpskey_ed25519`のように生成時の名前だけのファイルが秘密鍵で、名前が`vpskey_ed25519.pub`のように末尾に`.pub`がつくのが公開鍵

送信するファイルが2つなのはVPSへの接続と、VPSからGitlabへの接続を1つの鍵で行う場合
その際は、
- gitlabkey_ed25519
- gitlabkey_ed25519.pub

の2つの鍵を送信する

送信するファイルが3つなのは、VPSへの接続と、VPSからGitlabへの接続を別の鍵で行う場合
その際は、
- vpskey_ed25519.pub
- gitlabkey_ed25519
- gitlabkey_ed25519.pub

の3つの鍵を送信する

***

- 公開鍵の登録

この作業はVPSとGitLabサーバーで行う
ホームディレクトリ直下に`.ssh`フォルダーがなければ作成する
.sshフォルダーに移動後、.sshフォルダー内に`authorized_keys`というファイルがあれば
```bash
cat file_name.pub >> authorized_keys
```

`.ssh` フォルダー内に`authorized_keys`というファイルがなければ

```bash
cp file_name.pub authorized_keys
```

を実行する
`file_name`はVPSへの接続に使用する鍵の名前

その後、`authorized_keys` の権限を変更する

```bash
chmod 600 authorized_keys
```

***

- 秘密鍵の登録

この作業はVPSに接続するコンピューターと、VPSで行う
秘密鍵の登録には `ssh-agent` が必要
Windowsなら管理者権限付きのpowershellで

```powershell
# ssh-agentが自動起動するように設定
Set-Service ssh-agent -StartupType Automatic
# ssh-agentの起動
Start-Service ssh-agent
```

でコンピューター起動時に起動するようにできるが、
Ubuntu(他のディストリビューションとMacは未確認)だと、自動起動されないうえに鍵の登録も行われないため、サービス化する必要がある
VPS上での処理は、後で行う転送の処理と一緒にサービス化するため、ここでは一時的に設定してみる
一時的な設定では、再起動時に設定が初期化されてしまう

```
#ssh-agentの起動
eval $(ssh-agent)
```

秘密鍵の登録は `.ssh` フォルダー内で

```bash
ssh-add key_file
```

で行える
パスフレーズを設定している場合はこの登録の時に聞かれる
また、`ssh-add -l` で登録済みの鍵一覧を表示できる

秘密鍵登録の際に `WARNING: UNPROTECTED PRIVATE KEY FILE!` というエラーが出た場合
Windowsの場合`.ssh`フォルダーがユーザフォルダ以下に配置されているかを確認する
それ以外の場合

```bash
chmod 600 key_file
```

で解決できる

秘密鍵の登録が行えたら

```bash
sudo vi /etc/ssh/sshd_config
```

で、エディタを開いたら次の行を探して変更

```
#公開鍵認証を用いたssh接続を許可
PubkeyAuthentication no
    ↓
PubkeyAuthentication yes
```

コメントアウトされていたらそれもはずす

変更後

```bash
sudo systemctl restart sshd
```

でsshサーバーを再起動後、

```bash
ssh -i key_file username@vps.ip.adderss -p 2222
```

でVPSにssh接続できることを確認する
`-i` は接続に使用する秘密鍵の指定。一度指定して接続すると以後の接続時には必要ない
これは、秘密鍵の登録が毎回必要なUbuntuでも同じ

一度指定すると

```bash
ssh username@vps.ip.adderss -p 2222
```

でパスワードの入力なしでssh接続ができる

sshの接続を公開鍵認証を用いた接続のみにしたい場合は

```bash
sudo vi /etc/ssh/sshd_config
```

で、エディタを開いたら次の行を探して変更

```
#パスワード認証を用いたssh接続の禁止
PasswordAuthentication yes
    ↓
PasswordAuthentication no
```

その後

```bash
sudo systemctl restart sshd
```

でsshサーバーを再起動する

## tailscaleの導入

tailscaleはP2P型のVPNを簡単に使えるようにしているサービス
アカウントにログインするだけで同じアカウントでログインしているコンピューターへVPN接続が行えるようになる
無料でも20台のデバイスを登録することができる
謎にすごいけど、めちゃくちゃ便利
登録とか詳しく知りたい人は[このリンク](https://tailscale.com/)からホームページにアクセスできる

登録が終わったら、ホームページ内にあるダウンロード方法を見てそれぞれのOS用のインストール手順を実行する

今回のVPSはUbuntuなので次のコマンドを実行するとインストールできます

```bash
#インストールに必要なcurlがデフォルトでないためインストール
sudo apt install curl
#tailscaleのインストール用スクリプトを実行
curl -fsSL https://tailscale.com/install.sh | sh
```

インストールが完了したら

```bash
sudo tailscale up
```

でtailscaleの起動を行い、表示されるリンクにアクセスすることでログインできる

Windowsなどでは、GUI操作でログインを行う

また、ログイン後はホームページからログインして管理画面にアクセスし、鍵の有効期限を無効化する
鍵の期限を無効化することでtailscale内のipが再割り当てされないようにする

VPSとGitLabサーバーの両方を同じアカウントでtailscaleに接続したら、VPSからGitLabサーバーにscpコマンドで公開鍵を送信し、VPSで行ったのと同じ方法で登録する

VPSからGitLabサーバーに公開鍵認証を用いたssh接続ができることを確認したら次のコマンドを実行する

```bash
nohup ssh -N -p 22 username@gitlab.tailscale.ip.adderss -L 1234:localhost:80 -g &
```

`username` はGitLabサーバーに接続する際のユーザー名、`gitlab.tailscale.ip.adderss` はGitLabサーバーのtailscaleで割り当てられたIP
GitLabサーバーのssh待ち受けポートも変更している場合は `-p` の部分を変更する

このコマンドを実行することで、VPSの1234番ポートへのアクセスをtailscale経由でGitLabサーバーの80番ポートに転送する

GitLabが80番以外のポートで待ち受けている場合はコマンドに反映させる
同様にVPSの待ち受けポートを1234番以外に設定した場合はコマンドに反映させる

このコマンドを実行することで、VPSの指定したポートにアクセスすることでGitLabに接続できるようになっているはず

***

上手くいっていたらこの内容をサービス化する

```bash
#ホームディレクトリに移動
cd ~
#フォルダ作成
mkdir gitlab-vps
#作成したフォルダに移動
cd gitlab-vps
#gitlab-vps.sh ファイルを作成し編集
sudo vi gitlab-vps.sh
```

エディタが開いたら次の内容を自分の環境に合わせて書き込む

```sh:gitlab-vps.sh
#!/bin/sh
eval $(ssh-agent)
ssh-add /home/username/.ssh/key_file
nohup ssh -N -p 22 username@gitlab.tailscale.ip.adderss -L 1234:localhost:80 -g &
exit 0
```

次に
```bash
sudo vi delayed_gitlab-vps.sh
```

同様に以下を自分の環境に合わせて書き込む

```sh:delayed_gitlab-vps.sh
#!/bin/sh
sleep 5
sh /home/username/gitlab-vps/gitlab-vps.sh
```

最後に

```bash
sudo vi gitlab-vps.service
```

同様に以下を自分の環境に合わせて書き込む

```sh:gitlab-vps.service
[Unit]
Description=gitlab-vps
ConditionPathExists=/home/username/gitlab-vps
After=tailscaled.service

[Service]
Type=forking
ExecStart=/home/username/gitlab-vps/delayed_gitlab-vps.sh
Restart=always
User=username

[Install]
WantedBy=multi-user.target
```

ファイルをすべて作成したら次のコマンドを実行する

```bash
#スクリプトファイルに実行権限を付与
chmod 0755 gitlab-vps.sh
chmod 0755 delayed_gitlab-vps.sh
#ファイルのコピー
sudo cp gitlab-vps.service /etc/systemd/system
#一応？
sudo systemctl daemon-reload
#サービスの有効化
sudo systemctl enable gitlab-vps
#サービスの開始
sudo systemctl start gitlab-vps
```

これで、起動したら勝手にポート転送を開始してGitLabへアクセスできるようになる

## ドメイン

IPアドレスの数列より、ドメインの文字列のほうが覚えやすいから多少便利？

今回は、Cloudflare Registrarでドメインを取得してみた
原価だから安い的な話らしいけど、円安のせいでなんともって感じ
今後に期待して今回はそのままで

ドメイン取ったらDNSの設定のところに行って
ドメインのルートと、サブドメインとして`gitlab`をそれぞれVPSのIPに転送するように設定
`example.com`のドメインを取得したなら、`exapmle.com` と `gitlab.example.com`　を設定する感じ

一番最後にやってるけど、この反映に少し時間かかるから実はVPSの設定の前にVPSのIPが分かった時点でやっておくべきではある

Conoha VPS側にもDNSの設定あるみたいだけど今回は使わなかった
きっと用途が別

今、ドメインにアクセスしてもなんも出ない。だって何も設定してないから
だから、これから `nginx` をVPSに導入してそのあと、リバースプロキシってのでサブドメインへのアクセスを転送する

nginxの導入は

```bash
sudo apt update
sudo apt install nginx
```

で出来る。
そうしたら、nginxでアクセスするために80番ポートを開放する

```bash
sudo ufw allow 80
```

ポートを指定してアクセスしてほしくない(ドメインを使ったアクセスに限定したい)ならこのタイミングで、gitlabへのアクセス用に開放してたポートを閉じる

```bash
sudo ufw status numbered
sudo ufw delete 削除したいルールの番号
```

この状態でドメインにアクセスすると、nginxの初期画面が出てくるはず
サブドメインにアクセスしてもまだ何もないはず

nginxのサブドメインにアクセスしたときのリバースプロキシは
`/etc/nginx/conf.d/example.conf`に書けばいいらしい

今回のサブドメインは`gitlab`なので`gitlab.conf`を作成する

```bash
sudo vi /etc/nginx/conf.d/gitlab.conf
```

エディタが開いたら次の内容を書き込む

```
server {
    server_name  gitlab.example.com;
    location / {
        proxy_pass http://localhost:1234/;
    }
}
```

これは、`gitlab.example.com` へのアクセスをローカルの1234番ポートに転送するための内容
ドメイン名とポート番号はそれぞれ自分の環境にあったものに変更する

ファイルの編集ができたら

```bash
sudo systemctl restart nginx
```

でnginxを再起動する

nginxと作成したgitlab-vpsのサービス両方が問題なく動いていることを確認できたら、リバースプロキシに設定したサブドメインにアクセスする

すると、うまくGitLabにアクセスできるはず

```
gitlab.exapmle.com
        ↓    [nginx リバースプロキシ]
VPSの指定ポート(例 1234)
        ↓    [gitlab-vps.service]
GitLabサーバーの待ち受けポート(例 80)
```

こんな感じで、GitLabサーバーまで転送されてる

# さいごに

実は完全に身内で使うならtailscaleだけで完結したりする
基本20台までって制限はあるけど、IPアドレスを使ったアクセスでいいならtailscaleで割り当てられたIPにアクセスするだけで使える

今回はtailscaleは身内だけで使いつつ外部の人にはgitlabを公開したかったからこんな回りくどくやってみた

最小構成のVPSがどのくらい持つのかわからないけど、NASとかRDPもこれでドメイン経由でアクセスできそうだし便利そうだなぁとか考えてみたり
けど、パスワードの管理ちゃんとするのもめんどいしわざわざやらなくてもいいかなぁとも
RDPに関しては転送速度の関係でどのくらい快適に使えるかわからんし

けど、一応これでグローバルIPのない環境にあるパソコンを公開する術が分かったからよかったのかな

今の時点では過剰ではあるけど、これだけのスペックのgitlabをホストしようと思うと中々高くつきそうだけど、それを月額600円くらいのサーバーと年間1000円くらいのドメインでホストできてるのいいよね
サーバーのスペック自体はしょぼいけど回線だけつよつよのVPSが中々安価に出てくるのを期待したい