らくがきちょう

なんとなく

AmazonLinux2 + Gogs で LDAP 認証 / TLS 対応な Git リポジトリを構築する

気軽に使える Git リポジトリを作る場合、手軽に初められる Gogs が便利です。 今回は AmazonLinux2 + nginx + gogs + Sqlite3 + Let's Encrypt 環境の構築手順をメモしておきます。

環境

今回、構築する環境のポイントは以下です。

  • AmazonLinux2 上で構築する
  • Gogs で Git リポジトリを構築する
  • Gogs へのログインは Samba4 へ LDAP 認証を行う
  • Gogs のフロントエンドとして Nginx を構築する (クライアント → Nginx → Gogs)
  • Nginx で SSL/TLS を終端する
  • Nginx に設定するサーバ証明書は Let's Encrypt を使い、無料で取得する

Let's Encrypt で証明書を取得する

lego で Let's Encrypt の証明書を取得します。 認証方式は環境鏡に合わせて利用可能なものを選択すれば良いですが、個人的には DNS 認証が手軽だと思います。 ここでは説明しませんが cron 等を使い、定期更新の設定も実施しておきます。

lego --accept-tos \
     --path=/etc/letsencrypt \
     --email="email@example.com" \
     --dns="route53" \
     --domains="git.example.com" \
     run

Nginx のインストール

amazon-linux-extras に Nginx のパッケージがありますが、バージョンが 1.12 と古い為、今回は Nginx の公式リポジトリからインストールします。 まず、リポジトリの定義ファイルを作成します。

cat << EOF > /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
EOF

Nginx をインストールします。

yum -y install nginx

SSL/TLS の設定をする際、ssl_dhparam というパラメータで Diffie-Helman 鍵交換アルゴリズムで使われる素数を格納したファイルを指定します。

curl https://ssl-config.mozilla.org/ffdhe2048.txt > /etc/nginx/dhparam.pem

SSL/TLS の設定ファイルを定義すべく、下記の内容で /etc/nginx/conf.d/ssl.conf というファイルを新規作成します。 proxy_pass を指定していますが、これは後ほどインストールする Gogs が Listen する URL です。

server {
    server_name [HOST.EXAMPLE.COM];

    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    ssl_certificate /etc/letsencrypt/certificates/[HOST.EXAMPLE.COM].crt;
    ssl_certificate_key /etc/letsencrypt/certificates/[HOST.EXAMPLE.COM].key;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets off;
    ssl_dhparam /etc/nginx/dhparam.pem;
    ssl_protocols TLSv1.2;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;

    location / {
        proxy_pass http://localhost:3000/;
    }
}

ここまで設定出来たら起動&自動起動の設定を行います。

systemctl enable nginx
systemctl start nginx

Gogs のインストール

Gogs の動作には git が必須である為、インストールします。

yum -y install git

Gogs を動作させるユーザを作成します。 今回は git というユーザを作成しました。

useradd git

git ユーザへ変更したら、Gogs をインストールしていきます。

sudo su - git
curl -O https://dl.gogs.io/0.11.86/gogs_0.11.86_linux_amd64.tar.gz
tar zxvf gogs_0.11.86_linux_amd64.tar.gz
rm gogs_0.11.86_linux_amd64.tar.gz
cd gogs
mkdir -p custom/conf/
cat << EOF > custom/conf/app.ini
[server]
PROTOCOL     = http
DOMAIN       = [HOST.EXAMPLE.COM]
ROOT_URL     = [http://HOST.EXAMPLE.COM/]
HTTP_ADDR    = 127.0.0.1
HTTP_PORT    = 3000
EOF

今回は Git リポジトリSSH アクセスに Gogs 内蔵の SSH デーモンを使います (その為、OS へアクセスする為のポートは 22/TCP では無い、別のポートへ変更してあります)。 しかし、このままでは Gogs が 22/TCP を Listen 出来ない為、setcap で権限を付与しておきます。

setcap 'cap_net_bind_service=+ep' /home/git/gogs/gogs

起動&自動起動の設定

systemd 用のスクリプトscripts/systemd/gogs.service に用意されているのですが、このまま使うと少なくても AmazonLinux2 では下記のエラーとなり、Gogs が起動しません。

# systemctl status gogs
● gogs.service - Gogs
   Loaded: loaded (/etc/systemd/system/gogs.service; enabled; vendor preset: disabled)
   Active: failed (Result: start-limit) since Sun 2019-07-07 13:57:28 JST; 3min 1s ago
 Main PID: 3630 (code=exited, status=1/FAILURE)

Jul 07 13:57:28 git.example.com systemd[1]: gogs.service: main process exited, code=exited, status=1/FAILURE
Jul 07 13:57:28 git.example.com systemd[1]: Unit gogs.service entered failed state.
Jul 07 13:57:28 git.example.com systemd[1]: gogs.service failed.
Jul 07 13:57:28 git.example.com systemd[1]: gogs.service holdoff time over, scheduling restart.
Jul 07 13:57:28 git.example.com systemd[1]: start request repeated too quickly for gogs.service
Jul 07 13:57:28 git.example.com systemd[1]: Failed to start Gogs.
Jul 07 13:57:28 git.example.com systemd[1]: Unit gogs.service entered failed state.
Jul 07 13:57:28 git.example.com systemd[1]: gogs.service failed.

そこで以下の内容で systemd 用のファイルを新規作成します。

cat << EOF > /etc/systemd/system/gogs.service
[Unit]
Description=Gogs
After=syslog.target
After=network.target

[Service]
# Modify these two values and uncomment them if you have
# repos with lots of files and get an HTTP error 500 because
# of that
###
#LimitMEMLOCK=infinity
#LimitNOFILE=65535
Type=simple
User=git
Group=git
WorkingDirectory=/home/git/gogs
ExecStart=/home/git/gogs/gogs web
Restart=always
Environment=USER=git HOME=/home/git

[Install]
WantedBy=multi-user.target
EOF

これで用意は出来ました。 起動&自動起動の設定を行います。

systemctl daemon-reload
systemctl enable gogs
systemctl start gogs

ActiveDirectory (LDAP) 認証の設定

今回は認証をドメインコントローラ化した Samba4 で実施します。 認証の設定例は以下の通りです。 ここではバインド DN に Administrator を指定していますが、セキュリティを考慮するのであれば権限が低く、ディレクトリサービスの検索しか出来ないユーザを指定した方が好ましいです。

項目
認証タイプ LDAP (via BindDN)
認証名 (任意の値を入力)
セキュリティプロトコル Unencrypted
ホスト (ドメインコントローラのアドレス)
ポート 389
バインド DN CN=Administrator,CN=Users,DC=example,DC=com
バインドパスワード (バインド DN に指定したユーザのパスワード)
ユーザ検索ベース OU=People,DC=example,DC=com
User フィルター (&(sAMAccountName=%s)(memberOf=CN=Members,OU=Groups,DC=example,DC=com))
Admin フィルター (空欄)
ユーザー名属性 (空欄)
名前属性 (空欄)
名字属性 (空欄)
E メール属性 mail
グループメンバーシップを確認します。 チェックしない
グループサーチベース DN (空欄)
グループフィルター (空欄)
ユーザーのリストを含むグループ属性 (空欄)
グループのユーザー属性 (空欄)
属性をバインド DN のコンテクストから取得する チェックしない
認証の有効化 チェックする
This authentication is default login source チェックする

参考

gogs/scripts/systemd/gogs.service

Gogs に付属する systemd 用ファイルは下記の通りです。 本文中でも触れましたが、下記の設定があると AmazonLinux2 では Gogs を systemd 経由で起動出来ませんでした。

  1. ProtectSystem=full
  2. PrivateDevices=yes
  3. PrivateTmp=yes
  4. NoNewPrivileges=true
[Unit]
Description=Gogs
After=syslog.target
After=network.target
After=mariadb.service mysqld.service postgresql.service memcached.service redis.service

[Service]
# Modify these two values and uncomment them if you have
# repos with lots of files and get an HTTP error 500 because
# of that
###
#LimitMEMLOCK=infinity
#LimitNOFILE=65535
Type=simple
User=git
Group=git
WorkingDirectory=/home/git/gogs
ExecStart=/home/git/gogs/gogs web
Restart=always
Environment=USER=git HOME=/home/git

# Some distributions may not support these hardening directives. If you cannot start the service due
# to an unknown option, comment out the ones not supported by your version of systemd.
ProtectSystem=full
PrivateDevices=yes
PrivateTmp=yes
NoNewPrivileges=true

[Install]
WantedBy=multi-user.target