zaki work log

作業ログやら生活ログやらなんやら

[Git] SSHサーバーとGitコマンドのみで構築するGitリポジトリサーバー

ユースケースとしてはコンピュートリソースが乏しいクローズドな環境でGitリポジトリサーバーの用意・利用が困難な場合に、gitコマンドでベアリポジトリを作ればSSHサーバーが動作している普通のLinuxを簡易的なGitリポジトリサーバーとして利用する、など。
使うのはSSHサーバーとOSのファイルシステムのみでDBもなくwebのUIもないので軽量に動作する。

サーバーの設定

gitコマンドは必要なのでインストールする。

リモートリポジトリ作成

複数ユーザーでGitを使用する場合、SSHアクセスをOSユーザーそれぞれのアカウントで行う場合はリポジトリ上のデータはOSのファイルシステム的に全員が読み書きできる必要があるため、「SSHアクセスは共用アカウント(GitHubならgitのように)を使ってOS上のリポジトリデータは共用アカウント権限で作成する」の方がLinuxのファイル管理的にきれいになると思う。(個人の感想です)

それを踏まえGitHubに倣ってgitアカウントを作成し、このアカウントでリポジトリを作成する例。
リポジトリの作成はデータファイルを置きたい任意のパスでgit init --bare [/path/to]を実行。

### ユーザー作成(読み飛ばし可)
zaki@registry:~$ sudo useradd git -m -d /home/git
zaki@registry:~$ sudo passwd git
New password: 
Retype new password: 
passwd: password updated successfully
### ベアリポジトリ作成
zaki@registry:~$ su - git
Password: 
$ 
$ pwd
/home/git
$ mkdir -p repo/sample-app
$ git init --bare repo/sample-app
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint: 
hint:   git config --global init.defaultBranch <name>
hint: 
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint: 
hint:   git branch -m <name>
Initialized empty Git repository in /home/git/repo/sample-app/
$ ls -lF repo/sample-app
total 32
-rw-rw-r-- 1 git git   23 Dec  7 14:26 HEAD
drwxrwxr-x 2 git git 4096 Dec  7 14:26 branches/
-rw-rw-r-- 1 git git   66 Dec  7 14:26 config
-rw-rw-r-- 1 git git   73 Dec  7 14:26 description
drwxrwxr-x 2 git git 4096 Dec  7 14:26 hooks/
drwxrwxr-x 2 git git 4096 Dec  7 14:26 info/
drwxrwxr-x 4 git git 4096 Dec  7 14:26 objects/
drwxrwxr-x 4 git git 4096 Dec  7 14:26 refs/
$ 

これで--bare込みでgit initを実行したパスが「ベアリポジトリ」になる。
あとはこのホストのgitユーザーにアクセスできるようSSHキーペア設定を仕込んでおく。

クライアント設定

SSHキーペア設定(読み飛ばし可)

この辺は通常のSSHアクセス設定。

zaki@cloud-dev2:~$ ssh-keygen -f ~/.ssh/id_private_git
Generating public/private ed25519 key pair.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/zaki/.ssh/id_private_git
Your public key has been saved in /home/zaki/.ssh/id_private_git.pub
The key fingerprint is:
SHA256:f98JDkK2flNAaqjev9N9jxRof14lFTBb6aEf19qSVPc zaki@cloud-dev2
The key's randomart image is:
+--[ED25519 256]--+
|             o.o.|
|           .  +o+|
|        . o  .o.*|
|       . o . o.+E|
|      . So  +.+++|
|     .  o... o++o|
|    . .  oo.+.o.o|
|     . ....=o+.*o|
|        .++ ..+.=|
+----[SHA256]-----+
zaki@cloud-dev2:~$ ssh-copy-id -i ~/.ssh/id_private_git.pub git@192.168.0.21
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/zaki/.ssh/id_private_git.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
git@192.168.0.21's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'git@192.168.0.21'"
and check to make sure that only the key(s) you wanted were added.

キーペア設定が出来たら接続情報を~/.ssh/configへ追加する。

Host registry
    identityfile ~/.ssh/id_private_git
    hostname 192.168.0.21
    user git

クライアントでgit clone

Gitリポジトリへのアクセスする際の書式は以下。パスはフルパスで記述する。

ssh://username@server//path/to/repository-name

cloneするにはこの書式のアドレスをgit cloneの引数に指定する。
前述のリポジトリ作成の例(リポジトリのパスは$HOME以下のrepo/sample-app)であれば以下の通り。

zaki@cloud-dev2:~$ git clone ssh://registry//home/git/repo/sample-app
Cloning into 'sample-app'...
warning: You appear to have cloned an empty repository.
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint:   git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint:   git branch -m <name>
zaki@cloud-dev2:~$ 
zaki@cloud-dev2:~$ cd sample-app/
(master #) zaki@cloud-dev2:~/sample-app$ ls -al
合計 4
drwxr-xr-x.  3 zaki zaki   18 12月  8 00:01 .
drwx------. 26 zaki zaki 4096 12月  8 00:01 ..
drwxr-xr-x.  7 zaki zaki  119 12月  8 00:01 .git
(master #) zaki@cloud-dev2:~/sample-app$ 

まだリポジトリ作成後何もコミットされてないのでファイルは何もない。

commitしてpush

mainじゃなくmasterのまま作業しちゃったけどこの通り。

(master #) zaki@cloud-dev2:~/sample-app$ echo "# sample-app" > README.md
(master #%) zaki@cloud-dev2:~/sample-app$ git add README.md 
(master +) zaki@cloud-dev2:~/sample-app$ git commit -m 'initial commit'
[master (root-commit) 9e9bfcc] initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 README.md
(master) zaki@cloud-dev2:~/sample-app$ git push
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 229 bytes | 229.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
To ssh://registry//home/git/repo/sample-app
 * [new branch]      master -> master
(master =) zaki@cloud-dev2:~/sample-app$ 
(master =) zaki@cloud-dev2:~/sample-app$ git log
commit 9e9bfccd447dc018fbe1244eac298bf09c478044 (HEAD -> master, origin/master)
Author: zaki-lknr <zaki.hmkc+github@gmail.com>
Date:   Sun Dec 8 00:03:15 2024 +0900

    initial commit
(master =) zaki@cloud-dev2:~/sample-app$ 

別のローカルリポジトリで変更が反映されてるかチェック

別マシンでcloneしてみると以下の通り、リモートリポジトリにちゃんとpushした内容が反映されている。

zaki@cheddar:~$ git clone ssh://registry//home/git/repo/sample-app
Cloning into 'sample-app'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.
zaki@cheddar:~$ ls -l sample-app/
total 4
-rw-rw-r-- 1 zaki zaki 13 Dec  8 00:10 README.md
zaki@cheddar:~$ cat sample-app/README.md 
# sample-app

まとめ

この通り、SSHサーバーとGitコマンドだけでGitリモートリポジトリは構築できる。
webのUIやDBも使わないため機能は最低限だが簡易的なGitリポジトリとして軽量に機能するので、Gitリポジトリから資材を取得して動作するアプリケーションなどを制限された環境で利用するときに応用できる。

オフライン環境のAAPとかAWXとかね。


ところで ssh-keygen のデフォルト、rsaでなくてed25519になってるんだねぇ。。