🔒

NGINXによるリバース・プロキシでGitBucketをSSL化する

2024/08/29に公開

宅内用のUbuntu ServerにGitBucketをインストールした際、NGINXによるリバース・プロキシでHTTPS化しました。その作業手順を自分用に残しておきます。

なお以下ではGitBucketもNGINXもexample.comという1つのサーバに同居しているものとします。

また、作業に関しては特に書かない場合を除いてサーバーであるUbuntuの上での作業です。

リバースプロキシによるHTTPS化とは

GitBucketはgitリポジトリを中心としたプラットフォームですが、それ自身はHTTPSプロトコルに対応していません。そこで、NGINXによるリバース・プロキシを介することで、GitBucketのサービスをHTTPS化します。

リバース・プロキシはプロキシに対応する言葉です。プロキシ・サーバーは内部から外部にアクセスする際のゲートウェイとして働きます。リバース・プロキシはこれと逆で、外部から内部にアクセスする際のゲートウェイとして働きます。

NGINXはこのリバース・プロキシ機能において『HTTPSによる外部からの接続を、HTTPによる内部への接続に変換』してフォワードする機能を持っています。これを使って外部からのGitBucketへのHTTPSアクセスをHTTPアクセスに変換しようというのが今回の目論見です。

NGINXのインストール

NGINXはUbuntuのリポジトリに入っていますので、それをそのまま使います。

sudo apt install nginx

UbuntuのNGINXはやや古いですが、宅内利用で使う分には困りません。それからUbuntu版は設定ファイルの位置がカスタマイズされています。以下の説明はそのカスタマイズされたディレクトリ構造に依存しています。NGINXの公式WEBサイトからダウンロードしてインストールする場合は、以下の説明を適宜読み替える必要があります。

NGINXの設定

/etc/nginx/sites-available/gitbucketを作り、以下の内容を書き込みます。このファイルはGitBucketのGitHub公式リポジトリにあるReverse proxy with NginxにSSL設定を追加したものです。


server {
    listen   443 ssl;
    server_name example.com;
    ssl_certificate              /etc/ssl/private/example.com.crt;
    ssl_certificate_key          /etc/ssl/private/example.com.key;
    ssl_protocols                TLSv1.2 TLSv1.3;
    ssl_ciphers                  'ECDH !aNULL !eNULL !SSLv2 !SSLv3';
    ssl_prefer_server_ciphers    on;    


    location /gitbucket {
        proxy_pass              http://localhost:8080/gitbucket;
        proxy_set_header        Host $host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_connect_timeout   150;
        proxy_send_timeout      100;
        proxy_read_timeout      100;
        proxy_buffers           4 32k;
        client_max_body_size    500m; # Big number is we can post big commits.
        client_body_buffer_size 128k;
    }
}


設定ファイルのserver設定が、NGINXサーバー全体の設定です。ここでは、ポート443でsslプロトコルを監視しています(SSLと書いていますが、実際に使用するのはTLSv1.2とv1.3です)。ssl_certificateとssl_certficate_keyは後で説明するサーバー認証情報の位置を書きます。

location設定は、サービスのコンテキストパスです。コンテキストパスはサーバーが複数のサービスを提供するためのキーワードです。例えば、このサーバーでNGINXを介さずにgitbucketに直接アクセスするには以下のアドレスを使います。

http://example.com:8080/gitbucket/

ここで、https://example.comがホスト名、8080がポート番号、gitbucketがコンテキストパスです。サービスごとに異なるコンテキストパスを使うことで、ひとつのサーバーで複数のサービスを運用できます。そしてNGINXはlocation指定でコンテキストパスごとに異なる設定を行うことができます。

proxy_passは外部からコンテキストパスにアクセスがあった場合、内部のどのような処理に変換するかを指定します。

結果的に、上の設定では外部からのアクセスが次のように変換されます。

外部からのアクセス 内部のサービス
https://example.com/gitbucket/ http://localhost:8080/gitbucket/

最後に以下のコマンドを実行し、シンボリック・リンクを張っておきます。site-enablesは外部のサーバー情報ですのでちょっと気持ち悪いですが、こうしておくとNGINXの他の設定ファイルを変更せずに済みます。

cd /etc/nginx/sites-enable/
sudo ln -s ../sites-avairable/gitbucket

オレオレ認証情報の生成

認証情報(Certificate)は、サーバーの運用者に関する情報を明らかにするためのものです。

これはユーザーを悪意のサーバー運用者から守るためのものであり、Certificateが無いあるいは不正なWEBサイトとの通信にはブラウザから警告が出るようになっています。これはローカル・サーバーへのアクセスでも同じであり、認証情報の無いサーバーへのWEBアクセスはかなりうるさいものになります。したがって、快適なアクセスをしたければこの情報は必須となります。

認証情報は本来公式の認証局(Certificate Authority:CA)への登録によって発行されますが、自宅内部に閉じたアクセスであればそこまでやる必要もありません。いわゆるオレオレ認証で済ませることにします。ファイルの作成については概ねHow to create an HTTPS certificate for localhost domainsに従っています。

まず適当な作業ディレクトリを作ってそこに移ってください。

最初に、認証局の情報を作ります。RootCA.key, RootCA.pemというファイル名は任意です。CAは認証が正しいことを保証する機関であり、こうして作った偽造情報は後でサーバーのCertificateの生成に使うほか、OSの認証レジストリに登録してブラウザから参照させます。

openssl req -x509 -nodes -new -sha256 -days 1024 -newkey rsa:2048 -keyout RootCA.key -out RootCA.pem -subj "/C=US/ST=YourState/L=YourCity/O=Example-Certificates/CN=example.com"
openssl x509 -outform pem -in RootCA.pem -out RootCA.crt

ここで-subの引数は、認証局の補助情報です。適当な値を設定してください。

  • /C 国コード。例えばjp。
  • /ST 県あるいは州名。例えばHokkaido
  • /L 市町村。例えばSapporo
  • /O CA組織名。例えばfoo-bar-baz
  • /CN 認証局のサーバー名。例えばexample.com

次に、ドメインごとの認証情報を作ります。まずドメインの情報をdomains.txtとして適当なディレクトリに作ってください。

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = example.com

以下のコマンドを実行して、ドメインの認証情報を作ります。

openssl req -new -nodes -newkey rsa:2048 -keyout example.com.key -out example.com.csr -subj "/C=US/ST=YourState/L=YourCity/O=Example-Certificates/CN=example.com"
openssl x509 -req -trustout -sha256 -days 1024 -in example.com.csr -CA RootCA.pem -CAkey RootCA.key -CAcreateserial -extfile domains.ext -out example.com.crt

ドメイン認証情報のインストール

作成したドメイン認証情報をNGINXの設定ファイルで指定したディレクトリにコピーします。

sudo cp example.com.* /etc/ssl/private

NGINXの設定のテストとサービスの起動

コマンドラインから以下のコマンドを実行して、設定が正しいか試してください。

sudo nginx -t

正しければ、次のコマンドでサービスを起動します。

sudo systemctl start nginx

また、以下のコマンドを実行すると、サーバーを再起動する際にNGINXが自動的に起動します。

sudo systemctl enable nginx 

NGINXを再起動するには以下のコマンドを実行します。

sudo systemctl enable nginx 

クライアントPCへの認証局情報のインストール

認証局(CA)情報はクライアント側、つまりWebブラウザでアクセスする側のOSにインストールします。これによって、以下のような流れになります。

  1. アクセスしてきたクライアントにサーバーのNGINXがドメイン認証情報を送る。
  2. クライアントのブラウザが、ドメイン認証情報に対応する認証局情報があるかクライアントOSに問い合わせる。
  3. 認証局情報が見つかれば安全なアクセス。見つからなければ危険なアクセスに分類する。

以下ではクライアントOSとしてWindowsの例を説明します。

  1. RootCA.crtをダブルクリックすると、「証明書」ウインドウが開きますので、「証明書のインストール…」をクリックします。
  2. 証明書インポートウィザードが開くので、保存場所として「現在のユーザー」を選ぶ。
  3. 「次へ」ボタンをクリックする。
  4. 証明書ストアの位置を聞かれるので「証明書をすべて次のストアに位置する」を選ぶ。
  5. 「参照…」ボタンをクリックして「信頼されたルート証明機関」を選ぶ。
  6. 「次へ」ボタンをクリックする。
  7. 指定した情報に間違いないことを確認して、「完了」ボタンをクリックする

インストールした認証情報が有効になるまで、少し時間がかかるようです。認証局情報の証明書は3年間有効です。

GitBucketのコンテキストパスとポート

コンテキストパスはgitbucket、ポートは8080と仮定します。shellから以下のコマンドを実行するこで、GitBucketが起動します(この時点ではサーバーのサービス機能を使っていないことに注意)。

java -jar ./gitbucket.war --port=8080 --prefix=/gitbucket

クライアントからWEBブラウザで http://example.com:8080/gitbucket にアクセスして、GitBucketサービスを正常に使えることを確認します。

GitBucketのベースURLの設定

ベースURLはGitBucketサーバーが仮定するサービスの基準アドレスです。無設定の場合はサーバーが自動的に類推しますが、このままではリバースプロキシを挟んだ場合に齟齬が生じますので変更する必要があります。

example.comのGitBucketを以下のコマンドで起動したとします。

java -jar ./gitbucket.war --port=8080 --prefix=/gitbucket

この場合のベースURLは

http://example.com:8080/gitbucket

です。GitBucketをWEBブラウザで開いてHTMLソースコードを確認すると分かりますが、すべてのリソース(CSSやイメージ、リンク先)のアドレスは上のベースURLを起点としてして指定されています。

NGINXを通す場合には、ベースURLは以下のように変更しなければなりません。

https://example.com/gitbucket

クライアントからWEBブラウザで http://example.com:8080/gitbucket にアクセスし、管理者でログオンします。管理者は初期状態では

  • ユーザー名 : root
  • パスワード : root
    です。

右上のメニューから、System Administration → System Settings を開き、BASE URLに

https://example.com/gitbucket

を設定します。

GitBucketをサービスとしてインストール、登録する。

ここまでの説明では、GitBucketをアプリケーションとして起動していました。実運用のためにはこれをサービス化する必要があります。

サービス化についてはInstall as a systemd Serviceを参照してください。

サーバにおけるGitBucketデータの保管場所が変わるため、これまでGitBucketに施した設定はすべて消えます。具体的にはベースURLの設定が消えますので、再度行う必要があります。

SSH対応

Enabling SSH access to repositoryを参考にしつつ、各フィールドは以下のように変更します。

フィールド
BASE URL https://example.com/gitbucket
SSH BIND HOST example.com
SSH BIND PORT 12345

ポート番号は他のサービスと衝突しなければなんでも良いのですが、ufwでポートを開くのを忘れないでください(後述)。

ufwによるファイアーウォール

サーバーを立てたらファイアーウォールも設定しておきます。

NGINXをaptでインストールすると、自動的に対応可能アプリケーションとしてufwに登録されます。対応可能アプリケーションは以下のコマンドで調べることができます。

sudo ufw app list

Ubuntu Server の場合、デフォルトでOpenSSHもインストールされているため、対応可能(かつallow)になっています。

foo@bar:~/baz$ sudo ufw app list
Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH

NGINXによるHTTPS転送を行うために、ポートを開きます。また、前述のSSH BIND PORTで指定したポート番号を、ufwで開けておきます。

sudo ufw allow 'Nginx HTTPS'
sudo ufw allow '12345'

ファイアーウォールを有効にするには以下のコマンドを実行します。

sudo ufw enable

Discussion