git_server.html (11484B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width,initial-scale=1"> 6 <link rel="stylesheet" type="text/css" href="/style.css"> 7 <link rel="icon" type="image/x-icon" href="/pics/favicon.ico"> 8 <title>Gitサーバーの設定 on OpenBSD</title> 9 </head> 10 <body> 11 <header> 12 <a href="/">主頁</a> | 13 <a href="/about.html">自己紹介</a> | 14 <a href="/journal">日記</a> | 15 <a href="/farm">農業</a> | 16 <a href="/kitchen">台所</a> | 17 <a href="/computer">電算機</a> | 18 <a href="/poetry">詩</a> | 19 <a href="/books">本棚</a> | 20 <a href="/gallery">絵</a> | 21 <a href="/plant">植物</a> | 22 <a href="https://git.mtkn.jp">Git</a> 23 </header> 24 <main> 25 <article> 26 <h1>Gitサーバーの設定 on OpenBSD</h1> 27 <time>2024-02-15</time> 28 29 <h2>はじめに</h2> 30 <p> 31 GitHubがMicrosoft傘下になり久しい。MincraftがMicrosoftアカウントなしでは遊べなくなった。このままではGitHubもそのうちMicrosoftアカウントを要求するようになるかもしれない。ということでGitサーバーを自前で持つことにした。</p> 32 <p> 33 ところでOpenBSDの開発者がGotという別のgit実装を作成しているので、この記事は近いうちにいらなくなりそう。 34 </p> 35 36 <h2>手順</h2> 37 <p> 38 以下ではssh接続によるpull/push及び、httpsによるpullを設定の上、stagitというウェブフロントエンドを導入する。 39 </p> 40 41 <h3>概要</h3> 42 <ol> 43 <li>ドメインの設定(任意)</li> 44 <li><code>httpd(8)</code>の設定</li> 45 <li>gitパッケージのインストールとchroot環境の整備</li> 46 <li>stagitの導入</li> 47 </ol> 48 49 <h3>ドメインの設定(任意)</h3> 50 <p> 51 ドメインを設定する。IPアドレスでアクセスできればいいならこの設定はいらない。</p> 52 <p> 53 今回はgitというサブドメインを登録した: 54 </p> 55 <table> 56 <thead> 57 <tr> 58 <th>サブドメイン</th> 59 <th>種別</th> 60 <th>内容</th> 61 <th>優先度</th> 62 </tr> 63 </thead> 64 <tbody> 65 <tr> 66 <td>git</td> 67 <td>A</td> 68 <td><i>サーバーのIPアドレス</i></td> 69 <td></td> 70 </tr> 71 </tbody> 72 </table> 73 74 <h3><code>httpd(8)</code>の設定</h3> 75 <p> 76 httpsで接続する場合、<code>acme-client(8)</code>を設定する(IPアドレスで接続するなら自己証明書を発行することになる)。まず<code>/etc/acme-client.conf</code>にドメインを追加する: 77 </p> 78 <pre><code>domain git.mtkn.jp { 79 domain key "/etc/ssl/private/git.mtkn.jp.key" 80 domain full chain certificate "/etc/ssl/git.mtkn.jp.fullchain.pem" 81 sign with letsencrypt 82 } 83 </code></pre> 84 85 <p> 86 続いて<code>/etc/httpd.conf</code>を設定する。</p> 87 <pre><code>server "git.mtkn.jp" { 88 listen on * port 80 89 location "/.well-known/acme-challenge/*" { 90 root "/acme" 91 request strip 2 92 } 93 location "*" { 94 block return 302 "https://$HTTP_HOST$REQUEST_URI" 95 } 96 } 97 98 server "git.mtkn.jp" { 99 listen on * tls port 443 100 tls { 101 certificate "/etc/ssl/git.mtkn.jp.fullchain.pem" 102 key "/etc/ssl/private/git.mtkn.jp.key" 103 } 104 location "/.well-known/acme-challenge/*" { 105 root "/acme" 106 request strip 2 107 } 108 location "/*/git-receive-pack" { 109 block 110 } 111 location "/*/git-upload-pack" { 112 fastcgi { 113 param SCRIPT_FILENAME "/usr/local/libexec/git/git-http-backend" 114 param GIT_PROJECT_ROOT "/git" 115 param GIT_HTTP_EXPORT_ALL "true" 116 } 117 } 118 location "/*/info/refs" { 119 fastcgi { 120 param SCRIPT_FILENAME "/usr/local/libexec/git/git-http-backend" 121 param GIT_PROJECT_ROOT "/git" 122 param GIT_HTTP_EXPORT_ALL "true" 123 } 124 } 125 } 126 </code></pre> 127 <p> 128 <code>location "/*/git-receive-pack"</code>はpushの設定。今回はhttpsでのpushを受付けないので<code>block</code>する。</p> 129 <p> 130 <code>location "/*/git-upload-pack"</code>は手元のパソコンから<code>git clone</code>や<code>git pull</code>したときのもの。<code>location "/*/info/refs"</code>は上記を含むアクセスがあったときのもの。ここではCGIを使って<code>git-http-backend</code>を呼んでいるだけである。<code>SCRIPT_FILENAME</code>は<code>httpd(8)</code>のchroot環境でのパスである。必要なファイルは後でこのchroot環境にコピーする。 131 </p> 132 <p> 133 この後同じURLでフロントエンドをホストしたいので、上記のように必要なURLからのみCGIを実行するようにした。gitのhttpクライアントがどのURLを利用しているのかは[2]に書いていた。</p> 134 135 136 137 <p> 138 httpsが必要ない場合は1つ目の<code>server</code>に各<code>location</code>を書くだけでいい。 139 </p> 140 <p> 141 <code>httpd(8)</code>と<code>slowcgi(8)</code>を起動する: 142 </p> 143 <pre><code># echo httpd_flags= >> /etc/rc.conf.local 144 # echo slowcgi_flags= >> /etc/rc.conf.local 145 # rcctl start httpd 146 # rcctl enable httpd 147 # rcctl start slowcgi 148 # rcctl enable slowcgi 149 </code></pre> 150 <p> 151 サーバー証明書の発行: 152 </p> 153 <pre><code># acme-client -v git.mtkn.jp 154 </code></pre> 155 <p> 156 <code>crontab(1)</code>にサーバー証明書の自動更新を登録: 157 </p> 158 <pre><code>#minute hour mday month wday [flags] command 159 ~ 2 * * * acme-client git.mtkn.jp && rcctl reload httpd 160 </code></pre> 161 162 <h3>gitパッケージのインストールとchroot環境の整備</h3> 163 <p> 164 gitパッケージをインストールし、ssh接続用のユーザーを作成する。httpsでも公開するので、gitユーザーのホームディレクトリは<code>/var/www</code>下にする: 165 </p> 166 <pre><code># pkg_add git 167 # useradd -b /var/www -m -s /usr/local/bin/git-shell git 168 </code></pre> 169 <p> 170 ssh接続用の公開鍵を<code>/var/www/git/.ssh/authorized_keys</code>に登録する。ところでこのファイルに公開鍵を書き込むとgitユーザーとしてsshでログインできるので、部外者がこのファイルの編集をできないようにしておく必要がある。一応所有者は<code>git:git</code>、権限は<code>-rw-------</code>なので大丈夫だと思うが、心配なら<code>httpd(8)</code>のchroot環境の外にこのファイルを移動させておいてもいいかもしれない。</p> 171 <p> 172 httpsでアクセスするためにchroot環境を整備する。<code>httpd(8)</code>は既定では<code>/var/www</code>にchrootして実行されるので、CGIに必要なファイルをこのディレクトリ以下に用意する必要がある。まずはgitのコマンドをコピー: 173 </p> 174 <pre><code># mkdir -p /var/www/usr/local/libexec/git 175 # cp /usr/local/libexec/git/git-{http-backend,receive-pack,upload-pack} /var/www/usr/local/libexec/git/ 176 # chown www:www /var/www/usr/local/libexec/git/git-{http-backend,receive-pack,upload-pack} 177 # chmod 0500 /var/www/usr/local/libexec/git/git-{http-backend,receive-pack,upload-pack} 178 # mkdir -p /var/www/usr/local/bin 179 # cp /usr/local/bin/git /var/www/usr/local/bin/ 180 # chown www:www /var/www/usr/local/bin/git 181 # chmod 0500 /var/www/usr/local/bin/git 182 </code></pre> 183 <p> 184 続いてコマンドの実行に必要なライブラリをコピー: 185 </p> 186 <pre><code># mkdir -p /var/www/usr/lib /var/www/usr/local/lib /var/www/usr/libexec 187 # find /var/www/{bin,usr} -type f | grep git | xargs ldd | awk '{print $7}' | grep -v -e '^/var/www/' -e '^$' -e 'Name' | sort | uniq | awk '{printf "cp %s /var/www%s && chown www:www /var/www%s && chmod 0400 /var/www%s\n", $1, $1, $1, $1}' | sh -s 188 </code></pre> 189 <p> 190 <code>/dev/null</code>をコピーする(<code>mknod(8)</code>参照): 191 </p> 192 <pre><code># mkdir /var/www/dev 193 # mknod -m 666 /var/www/dev/null c 2 2 194 </code></pre> 195 <p> 196 最後に、<code>/var/www/dev/null</code>を作成するために<code>/etc/fstab</code>の<code>/var</code>エントリーから<code>nodev</code>オプションを削除し、再起動する。 197 </p> 198 199 <p> 200 gitパッケージやシステムの更新後、chroot環境のコマンドやライブラリも更新しないといけないのでそのためのスクリプトを適当に作った: 201 </p> 202 <pre><code>#!/bin/sh -xe 203 204 oso=$(find /var/www/usr -type f -name '*.so*') 205 rm $oso 206 207 bin=$(find /var/www/bin /var/www/usr -type f ! -name '*.so*' | 208 grep -v bgpctl | 209 sed 's|^/var/www||' 210 ) 211 echo "$bin" | sed 's|.*|cp & /var/www&|' | sh -s 212 echo "$bin" | sed 's|.*|chown www:www /var/www&|' | sh -s 213 echo "$bin" | sed 's|.*|chmod 0500 /var/www&|' | sh -s 214 215 nso=$(echo "$bin" | sed 's|^|/var/www|' | 216 xargs ldd | awk '{print $7}' | 217 grep -v -e '^/var/www/' -e '^$' -e 'Name' | 218 sort | uniq 219 ) 220 echo "$nso" | sed 's|.*|cp & /var/www&|' | sh -s 221 echo "$nso" | sed 's|.*|chown www:www /var/www&|' | sh -s 222 echo "$nso" | sed 's|.*|chmod 0400 /var/www&|' | sh -s 223 </code></pre> 224 225 <h3><code>stagit(1)</code>の導入</h3> 226 <p> 227 ウェブフロントエンドとしてstagitを導入する: 228 </p> 229 <pre><code># pkg_add stagit 230 </code></pre> 231 <p> 232 <code>httpd.conf(5)</code>の<code>server "git.mtkn.jp"</code>の中に以下の設定を追加する(<code>location</code>のマッチは上から順番に評価されるので、上で設定したgitのhttpクライアント用の<code>location</code>よりも下に記入する): 233 </p> 234 <pre><code> location "/" { 235 directory index index.html 236 root "/htdocs/git.mtkn.jp" 237 } 238 location "*" { 239 directory index log.html 240 root "/htdocs/git.mtkn.jp" 241 } 242 </code></pre> 243 <p> 244 stagit用のディレクトリを作成して<code>httpd(8)</code>を再読込する: 245 </p> 246 <pre><code># mkdir /var/www/htdocs/git.mtkn.jp 247 # chown git:git /var/www/htdocs/git.mtkn.jp 248 # rcctl reload httpd 249 </code></pre> 250 251 <p> 252 gitリポジトリが更新されたときにウェブページも更新するように設定する。gitリポジトリはなにか更新があった場合、そのリポジトリのディレクトリの中の<code>hooks/post-receive</code>というファイルを自動で実行する。そのためこのファイルに、stagitの更新をするスクリプトを書いておけばいい: 253 </p> 254 <pre><code>#!/bin/sh 255 256 git_root="/var/www/git" 257 stagit_root="/var/www/htdocs/git.mtkn.jp" 258 repo="$(basename "$(pwd)" | sed 's/\.git$//')" 259 src="$(pwd)" 260 stagit_dst="$stagit_root/$repo" 261 262 mkdir -p "$stagit_dst" 263 (cd "$stagit_dst" && stagit -l 64 "$src") 264 (cd "$stagit_root" && stagit-index $git_root/*.git > index.html) 265 </code></pre> 266 267 <h2>レポジトリの作成</h2> 268 <p> 269 レポジトリを作成するにはサーバーで以下のようにする。</p> 270 <pre><code>$ cd /var/www/git 271 $ doas -u git mkdir <i>repo</i>.git 272 $ cd <i>repo</i>.git 273 $ doas -u git git init --bare 274 </code></pre> 275 276 <p> 277 これで手元のパソコンからクローンできる: 278 </p> 279 <pre><code>$ git clone git@git.mtkn.jp:<i>repo</i>.git 280 </code></pre> 281 <p> 282 または 283 </p> 284 <pre><code>$ git clone https://git.mtkn.jp/<i>repo</i>.git 285 </code></pre> 286 287 <h2>参考</h2> 288 <ul> 289 <li>[1] <a href="https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols">Git - The Protocols.Git</a></li> 290 <li>[2] <a href="https://git-scm.com/docs/http-protocol">Git - http-protocol Documentation.Git</a></li> 291 <li>[3] <a href="https://codemadness.org/stagit.html">Stagit: a static git page generator - Codemadness</a></li> 292 </ul> 293 </article> 294 295 </main> 296 <footer> 297 <address>info(at)mtkn(dot)jp</address> 298 <a href="http://creativecommons.org/publicdomain/zero/1.0?ref=chooser-v1" rel="license noopener noreferrer">CC0 1.0</a> 299 </footer> 300 </body> 301 </html>