CentOS8にSubversion1.14+httpdをインストールしてnginxでリバースプロキシする

CentOS Stream 8 + Nginxで運用している環境にSubversion + Apache HTTP Serverをインストールして、旧サーバーからリポジトリを移行したときの覚書。

環境: CentOS Stream 8, nginx 1.22.1, httpd 2.4.37, subversion 1.14.1


1. Subversionをインストール

dnf(yum)経由でインストールすることにした。
# dnf module list subversion
# dnf module install subversion:1.14

Apache HTTPサーバー経由でsubversionリポジトリにアクセスするモジュールをインストール
# dnf install httpd mod_dav_svn

/etc/httpd/modules/に配置され、/etc/httpd/conf.modules.d/10-subversion.confで自動で読み込まれる。


2.httpdの設定。nginxからプロキシする。

httpdはポート8080で動かす。外からのポートは開けない。
# less /etc/httpd/conf/httpd.conf

Listen 8080
User apache
Group www
ServerAdmin info@hoge.co.jp

起動、自動起動ON、確認
# apachectl configtest
# systemctl start httpd
# systemctl enable httpd
# systemctl status httpd
# systemctl list-unit-files -t service

インストール時に生成されたconfは別ディレクトリへ
# cd /etc/httpd/conf.d/
# mkdir bak
# mv *.conf bak/

Subversion用リポジトリの置き場所を作成
# mkdir /home/svn
# mkdir /home/svn/repo

svn用httpd設定ファイルを作成
# vi 01_svn.conf

<VirtualHost *:8080>
  ServerName svn.hoge.co.jp
  <Location />
    DAV svn
    SVNParentPath /home/svn/repo
    SVNListParentPath on
  </Location>
</VirtualHost>

httpd再読み込み
# apachectl configtest
# systemctl reload httpd

nginxにリバースプロキシの設定
# cd /etc/nginx/conf.d/
# less 02_svn.conf

server {
    listen       80;
    server_name  svn.*;

    client_max_body_size 300M;

    location / {
        proxy_set_header Host $http_host;
        proxy_set_header Destination $http_destination;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://127.0.0.1:8080;
    }
}

nginx再読み込み
# nginx -t
# systemctl reload nginx

動作テスト
# cd /home/svn/repo/
# svnadmin create test
# chown -R apache.www test/

TortoiseSVNでチェックアウトして確認。


3.Https化

nginxまでをTLSで暗号化する。
certbot用の設定を追記する。
# cd /etc/nginx/conf.d/
# less 02_svn.conf

server {
    listen       80;
    server_name  svn.*;

    client_max_body_size 300M;

    # Accept for Let's Encrypt(certbot)
    location /.well-known/acme-challenge {
        access_log off;
        root /var/www/html/;
    }

    location / {
        proxy_set_header Host $http_host;
        proxy_set_header Destination $http_destination;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://127.0.0.1:8080;
    }
}

nginx再読み込み
# nginx -t
# systemctl reload nginx

certbotでSSL証明書取得
# certbot certonly --webroot -w /var/www/html/ -d svn.hoge.co.jp

nginx設定ファイル編集
# less 02_svn.conf

server {
    listen       80;
    server_name  svn.*;
    return 301 https://svn.hoge.co.jp$request_uri;
}
server {
    listen       443 ssl;
    server_name  svn01.*;

    # Accept for Let's Encrypt(certbot)
    location /.well-known/acme-challenge {
        access_log off;
        root /var/www/html/;
    }

    # Fixed for move japanese file in svn
    set $fixed_destination $http_destination;
    if ( $fixed_destination ~ ^https(?<myurl>.*)$ ) {
        set $fixed_destination "http$myurl";
    }

    location / {
        client_max_body_size 300M;
        access_log off;
        error_log /dev/null;

        proxy_set_header Host $http_host;
        proxy_set_header Destination $http_destination;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://127.0.0.1:8080;
    }

    include conf.d/global/ssl.conf;
    ssl_certificate         /etc/letsencrypt/live/svn.hoge.co.jp/fullchain.pem;
    ssl_certificate_key     /etc/letsencrypt/live/svn.hoge.co.jp/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/svn.hoge.co.jp/chain.pem;
}

日本語ファイル名を名前変更したり移動したときのエラーに対応。
参考: Nginx(HTTPS)でSubversion(HTTP/Apache)をリバースプロキシする場合に日本語ファイル名のmoveが失敗するとしたら 【Nginxの2重URLエンコーディング】 - Qiita

access_logとerror_logはhttpdの方で記録するのでいらないと思う。

nginx再読み込み
# nginx -t
# systemctl reload nginx

TortoiseSVNでチェックアウトして確認。


4.アクセス制御

前はUSVNというウェブ管理ツールを使ってみたけど、USVNは開発が止まっているのでコマンドラインで管理する。
参考: Subversionのウェブ管理ツールUSVNをインストール

Basic認証のユーザーを作成する。
# cd /home/svn/
# htpasswd -c .htpasswd daiki

Subversionのアクセス制御ファイルを作成。
ファイル名に.htを付けているのはhttpd.confでアクセス拒否設定になっているから。
# vi .htauthz

[groups]
admin = daiki

[/]
* =
@admin = rw

デフォルトは全員読み書き不可。
adminグループだけ読み書き可能にしている。

httpd設定ファイル編集。
# cd /etc/httpd/conf.d/
# less 01_svn.conf

<VirtualHost *:8080>
  ServerName svn.hoge.co.jp
  RequestHeader edit Destination ^https http early
  Timeout 600
  <Location />
    DAV svn
    SVNParentPath /home/svn/repo
    SVNListParentPath on
    SVNAdvertiseV2Protocol off

    Require valid-user
    AuthType Basic
    AuthName "SVN"
    AuthUserFile /home/svn/.htpasswd
    AuthzSVNAccessFile /home/svn/.htauthz
  </Location>
</VirtualHost>

httpd再読み込み
# apachectl configtest
# systemctl reload httpd

TortoiseSVNでUpdate/Commitして確認。


5.IPアドレス制限

念のため日本からのIPアドレスしか許可しないようにする。
国別のIPアドレス一覧取得は前の記事を参考に。
参考: GeoIP2のCSVデータでPostgresSQLデータベースを更新して国別拒否リストを生成

nginx設定用の許可一覧を生成する。
# su - postgres
$ psql geo -c "SELECT concat('allow ', network, ';')  FROM geoip2_network gn LEFT JOIN geoip2_location gl on gn.geoname_id = gl.geoname_id WHERE gl.country_iso_code = 'JP';" >> allow_JP.conf

先頭と末尾のいらない行を削除する。
viコマンドは「1G」で先頭に、「G」でファイル末尾に移動できる。
「dd」で行削除。
# less allow_JP.conf

これをサーバーに設置してnginx設定ファイルを編集。
# cd /etc/nginx/conf.d/
# less 02_svn.conf

    # Restrict access from Japan
    include conf.d/global/allow_JP.conf;
    deny all;

nginx再読み込み
# nginx -t
# systemctl reload nginx


6.リポジトリを移行

ディレクトリをまるごとコピーして転送。
# tar -czvf svn_20230101.tgz svn/

Subversionのバージョンが上がっているのでupgradeする。
# cd /home/svn/repo/
# svnadmin upgrade project/

TortoiseSVNでRelocate...して確認。

ディレクトリごとにsvnadmin upgradeするのが面倒くさいのでbashスクリプト書いた。
# vi svnadmin_upgrade.sh

#!/bin/bash

dirs="/home/svn/repo/*"
for dirpath in $dirs; do
  if [ -d $dirpath ] ; then
    echo "----------"
    echo "# svnadmin upgrade $dirpath"
    svnadmin upgrade $dirpath
  fi
done

# chmod +x svnadmin_upgrade.sh
# ./svnadmin_upgrade.sh


新規プロジェクトは次のコマンドで作成。
# cd /home/svn/repo/
# svnadmin create hoge_project
# chown apache.www -R hoge_project


【関連記事】