gitlab之server端hook自动创建项目分支
- 之前已经搭建了gitlab下的server hook,做了简单的测试,是可以生效的,接下来准备通过这个hook实现,代码分支的自动发布
- 思路如下:
1.在gitlab的server的post-receive下定义一个脚本
2.在这个脚本里面通过ssh登录到宿主机,然后执行宿主机上的脚本,在这个脚本里面,执行拉取代码操作
- 环境准备:
由于要使用ssh服务,所以必须要在系统安装ssh
1.检查ssh是否安装
systemctl status ssh
2.如果没有安装,可以通过如下方式安装
$ sudo apt install -y openssh-server
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
ncurses-term openssh-sftp-server ssh-import-id
Suggested packages:
molly-guard monkeysphere ssh-askpass
The following NEW packages will be installed:
ncurses-term openssh-server openssh-sftp-server ssh-import-id
0 upgraded, 4 newly installed, 0 to remove and 247 not upgraded.
Need to get 751 kB of archives.
After this operation, 6,046 kB of additional disk space will be used.
Get:1 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-updates/main amd64 openssh-sftp-server amd64 1:8.9p1-3ubuntu0.11 [38.7 kB]
Get:2 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-updates/main amd64 openssh-server amd64 1:8.9p1-3ubuntu0.11 [435 kB]
Get:3 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy-updates/main amd64 ncurses-term all 6.3-2ubuntu0.1 [267 kB]
Get:4 http://mirrors.tuna.tsinghua.edu.cn/ubuntu jammy/main amd64 ssh-import-id all 5.11-0ubuntu1 [10.1 kB]
Fetched 751 kB in 3s (245 kB/s)
Preconfiguring packages ...
Selecting previously unselected package openssh-sftp-server.
(Reading database ... 287328 files and directories currently installed.)
Preparing to unpack .../openssh-sftp-server_1%3a8.9p1-3ubuntu0.11_amd64.deb ...
Unpacking openssh-sftp-server (1:8.9p1-3ubuntu0.11) ...
Selecting previously unselected package openssh-server.
Preparing to unpack .../openssh-server_1%3a8.9p1-3ubuntu0.11_amd64.deb ...
Unpacking openssh-server (1:8.9p1-3ubuntu0.11) ...
Selecting previously unselected package ncurses-term.
Preparing to unpack .../ncurses-term_6.3-2ubuntu0.1_all.deb ...
Unpacking ncurses-term (6.3-2ubuntu0.1) ...
Selecting previously unselected package ssh-import-id.
Preparing to unpack .../ssh-import-id_5.11-0ubuntu1_all.deb ...
Unpacking ssh-import-id (5.11-0ubuntu1) ...
Setting up openssh-sftp-server (1:8.9p1-3ubuntu0.11) ...
Setting up openssh-server (1:8.9p1-3ubuntu0.11) ...
Creating config file /etc/ssh/sshd_config with new version
Creating SSH2 RSA key; this may take some time ...
3072 SHA256:Bc6mfCjp5qrlFU0x7wu1fcSGY718FeEXXnwcU4PHeDA root@tianyi510s (RSA)
Creating SSH2 ECDSA key; this may take some time ...
256 SHA256:wirUnlfZcsdMjIy3lhIEfkWnItdXByl+uxTyVEpzNzQ root@tianyi510s (ECDSA)
Creating SSH2 ED25519 key; this may take some time ...
256 SHA256:hMriVpK3rh8cVNiQvlU82t3hw0KUDkIvAYhJC1munkQ root@tianyi510s (ED25519)
Created symlink /etc/systemd/system/sshd.service → /lib/systemd/system/ssh.service.
Created symlink /etc/systemd/system/multi-user.target.wants/ssh.service → /lib/systemd/system/ssh.service.
rescue-ssh.target is a disabled or a static unit, not starting it.
ssh.socket is a disabled or a static unit, not starting it.
Setting up ssh-import-id (5.11-0ubuntu1) ...
Setting up ncurses-term (6.3-2ubuntu0.1) ...
Processing triggers for man-db (2.10.2-1) ...
Processing triggers for ufw (0.36.1-4build1) ...
guoshipeng@tianyi510s:~$
guoshipeng@tianyi510s:~$ sudo systemctl start ssh
guoshipeng@tianyi510s:~$
guoshipeng@tianyi510s:~$ systemctl status ssh
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2025-03-06 00:16:38 CST; 27s ago
Docs: man:sshd(8)
man:sshd_config(5)
Main PID: 22674 (sshd)
Tasks: 1 (limit: 18753)
Memory: 1.7M
CPU: 11ms
CGroup: /system.slice/ssh.service
└─22674 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"
Mar 06 00:16:38 tianyi510s systemd[1]: Starting OpenBSD Secure Shell server...
Mar 06 00:16:38 tianyi510s sshd[22674]: Server listening on 0.0.0.0 port 22.
Mar 06 00:16:38 tianyi510s sshd[22674]: Server listening on :: port 22.
Mar 06 00:16:38 tianyi510s systemd[1]: Started OpenBSD Secure Shell server.
guoshipeng@tianyi510s:~$
guoshipeng@tianyi510s:~$ sudo systemctl enable ssh //设置开机自启动
- 步骤如下:
第一部分,配置ssh连接
1.由于需要ssh 连接到宿主机,需要将本地主机的SSH公钥安装到远程主机的授权密钥文件中
1>在容器中通过openssh 生成SSH密钥
root@gitlab:/# apt-get install -y openssh-client
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
openssh-server openssh-sftp-server
Suggested packages:
keychain libpam-ssh monkeysphere ssh-askpass molly-guard ufw
Recommended packages:
xauth default-logind | logind | libpam-systemd ncurses-term ssh-import-id
The following packages will be upgraded:
openssh-client openssh-server openssh-sftp-server
3 upgraded, 0 newly installed, 0 to remove and 17 not upgraded.
Need to get 1376 kB of archives.
After this operation, 0 B of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 openssh-sftp-server amd64 1:8.9p1-3ubuntu0.11 [38.7 kB]
Get:2 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 openssh-server amd64 1:8.9p1-3ubuntu0.11 [435 kB]
Get:3 http://archive.ubuntu.com/ubuntu jammy-updates/main amd64 openssh-client amd64 1:8.9p1-3ubuntu0.11 [903 kB]
Fetched 1376 kB in 3s (479 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
(Reading database ... 112282 files and directories currently installed.)
Preparing to unpack .../openssh-sftp-server_1%3a8.9p1-3ubuntu0.11_amd64.deb ...
Unpacking openssh-sftp-server (1:8.9p1-3ubuntu0.11) over (1:8.9p1-3ubuntu0.10) ...
Preparing to unpack .../openssh-server_1%3a8.9p1-3ubuntu0.11_amd64.deb ...
Unpacking openssh-server (1:8.9p1-3ubuntu0.11) over (1:8.9p1-3ubuntu0.10) ...
Preparing to unpack .../openssh-client_1%3a8.9p1-3ubuntu0.11_amd64.deb ...
Unpacking openssh-client (1:8.9p1-3ubuntu0.11) over (1:8.9p1-3ubuntu0.10) ...
Setting up openssh-client (1:8.9p1-3ubuntu0.11) ...
Setting up openssh-sftp-server (1:8.9p1-3ubuntu0.11) ...
Setting up openssh-server (1:8.9p1-3ubuntu0.11) ...
debconf: unable to initialize frontend: Dialog
debconf: (No usable dialog-like program is installed, so the dialog based frontend cannot be used. at /usr/share/perl5/Debconf/FrontEnd/Dialog.pm line 78.)
debconf: falling back to frontend: Readline
invoke-rc.d: could not determine current runlevel
invoke-rc.d: policy-rc.d denied execution of restart.
root@gitlab:/#
root@gitlab:/#
root@gitlab:/#
root@gitlab:/# ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:3c4MshoBmZ4/mH7PqsAbJY6fxa5lHkopWN8cXp8YKkE root@gitlab.example.com
The key's randomart image is:
+---[RSA 4096]----+
| |
| o |
| E |
| o o . . |
| o = o S o . |
|.= * O = * * |
|+ B @ O o o + |
| + & o.= |
| *.=oooo |
+----[SHA256]-----+
root@gitlab:/#
root@gitlab:/# cd ~/.ssh/
root@gitlab:~/.ssh# ls
id_rsa id_rsa.pub
2>通过 ssh-copy-id 命令,将本地主机的SSH公钥安装到远程主机的授权密钥文件中
root@gitlab:~/.ssh# ssh-copy-id guoshipeng@192.168.5.17
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.5.17 (192.168.5.17)' can't be established.
ED25519 key fingerprint is SHA256:hMriVpK3rh8cVNiQvlU82t3hw0KUDkIvAYhJC1munkQ.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/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
guoshipeng@192.168.5.17's password:
Permission denied, please try again.
guoshipeng@192.168.5.17's password:
Number of key(s) added: 1
Now try logging into the machine, with: "ssh 'guoshipeng@192.168.5.17'"
and check to make sure that only the key(s) you wanted were added.
root@gitlab:~/.ssh#
3>ssh-copy-id 原理
它会读取本地的SSH公钥(通常是 ~/.ssh/id_rsa.pub)
将公钥上传到远程服务器
添加到远程服务器的授权密钥列表中
语法:
ssh-copy-id user@hostname
参数:
user:远程服务器的用户名
hostname:远程服务器的IP地址或域名
注意:
执行这个命令时:
会提示你输入远程服务器的密码
成功后,你就可以无密码SSH登录该服务器了
确保只对可信的服务器使用
2.配置SSH配置文件,在容器中编辑 ~/.ssh/config 文件,简化连接,内容如下:
Host hostmachine
HostName 宿主机IP地址
User 宿主机用户名
IdentityFile ~/.ssh/id_rsa
对于 ~/.ssh/config 文件,如果不存在,可以直接创建:
touch ~/.ssh/config
chmod 600 ~/.ssh/config
我的配置内容如下:
Host myserver
HostName 192.168.5.17
User guoshipeng
Port 22
IdentityFile ~/.ssh/id_rsa
这样配置后,就可以直接使用 ssh myserver 连接,而不需要每次输入完整的用户名和IP(ssh user@host 的方式)。所以最好取一个有意义的名称(别名),这里是myserver
需要注意的是:
文件权限必须是600(仅对所有者可读可写)
可以配置多个不同的主机
简化日常SSH连接操作
3.确保宿主机SSH服务器配置,在宿主机 /etc/ssh/sshd_config 中确认以下配置:
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
查看宿主机相关配置,如下(根据需要爱哦已经做了修改):
#PubkeyAuthentication yes
PubkeyAuthentication yes
# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile .ssh/authorized_keys .ssh/authorized_keys2
AuthorizedKeysFile .ssh/authorized_keys
然后重启宿主机的ssh:
sudo systemctl restart ssh
关于AuthorizedKeysFile的解释:
这个配置项 AuthorizedKeysFile .ssh/authorized_keys 中的 .ssh/authorized_keys 是一个文件路径,它指定了用于SSH公钥认证的授权密钥存储位置。
具体解释:
.ssh/ 是一个目录,位于用户的主目录下
authorized_keys 是存储授权公钥的文件
完整路径通常是 ~/.ssh/authorized_keys(针对普通用户)或 /root/.ssh/authorized_keys(针对root用户)
这个文件的作用是:
存储所有被允许通过SSH密钥登录到此账户的公钥
每个公钥占一行
当有人尝试使用SSH密钥登录时,服务器会检查该文件中是否包含对应的公钥
当你运行 ssh-copy-id 命令时,它实际上是把你的公钥添加到远程服务器上这个文件中。
文件格式示例:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAA... 用户@主机
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABBB... 另一个用户@另一个主机
4.测试ssh 连接是否可用
# 使用别名连接
ssh hostmachine
# 或直接连接
ssh user@宿主机IP
我这里执行:
root@gitlab:~/.ssh# ssh myserver
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 6.8.0-52-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
* Introducing Expanded Security Maintenance for Applications.
Receive updates to over 25,000 software packages with your
Ubuntu Pro subscription. Free for personal use.
https://ubuntu.com/pro
Expanded Security Maintenance for Applications is not enabled.
201 updates can be applied immediately.
To see these additional updates run: apt list --upgradable
3 additional security updates can be applied with ESM Apps.
Learn more about enabling ESM Apps service at https://ubuntu.com/esm
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
New release '24.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
Last login: Sun Mar 9 19:01:30 2025 from 172.17.0.4
guoshipeng@tianyi510s:~$
或者:
root@gitlab:~/.ssh# ssh guoshipeng@192.168.5.17
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 6.8.0-52-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
* Introducing Expanded Security Maintenance for Applications.
Receive updates to over 25,000 software packages with your
Ubuntu Pro subscription. Free for personal use.
https://ubuntu.com/pro
Expanded Security Maintenance for Applications is not enabled.
201 updates can be applied immediately.
To see these additional updates run: apt list --upgradable
3 additional security updates can be applied with ESM Apps.
Learn more about enabling ESM Apps service at https://ubuntu.com/esm
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
New release '24.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
Last login: Sun Mar 9 19:21:10 2025 from 172.17.0.4
guoshipeng@tianyi510s:~$
说明是可以在容器里,使用ssh连接宿主机的, 接下来就是编写脚本了
第二部分,编写脚本
1.修改post-receive,添加如下内容
#!/bin/bash
read oldrev newrev refname
BRANCH="refs/heads/dev"
if [ "$refname" == "$BRANCH" ]; then
echo "$(date '+%Y-%m-%d %H:%M:%S') - Push to dev branch detected: $newrev" >> /var/log/gitlab/custom_hooks.log
echo "Detected push to $BRANCH branch, triggering deploy..."
ssh -vvv guoshipeng@192.168.5.17 "/home/guoshipeng/Documents/code/deploy/deploy.sh" >> /var/log/gitlab/custom_hooks.log 2>&1
fi
2.在宿主机 /home/guoshipeng/Documents/code/deploy/ 下新建如下 deploy.sh 脚本
#!/bin/bash
PROJECT_DIR="/home/guoshipeng/Documents/code/deploy/laravel-12"
#GIT_REPO="git@gitlab.example.com:9022/dev/laravel12.git"
#由于使用的是ssh,所以要加这个前缀,否则 git clone 失败,报: remote: The project you were looking for could not be found or you don't have permission to view it.
GIT_REPO="ssh://git@gitlab.example.com:9022/dev/laravel12.git"
BRANCH="dev"
echo "==== [$(date)] 开始部署 Laravel 12 ===="
# 如果目录不存在,克隆仓库
if [ ! -d "$PROJECT_DIR/.git" ]; then
echo ">>> 目录不存在,克隆仓库..."
git clone -b $BRANCH $GIT_REPO $PROJECT_DIR
else
echo ">>> 目录已存在,拉取最新代码..."
cd $PROJECT_DIR || exit
git fetch origin $BRANCH
git reset --hard origin/$BRANCH
fi
# 安装依赖
echo ">>> 安装 PHP 依赖..."
#docker run --rm -v $PROJECT_DIR:/app -w /app composer install --no-dev --optimize-autoloader
# 运行数据库迁移
echo ">>> 运行数据库迁移..."
#docker-compose -f $DOCKER_COMPOSE_FILE exec app php artisan migrate --force
# 重新启动 Laravel 项目
echo ">>> 重新启动 Laravel 项目..."
#docker-compose -f $DOCKER_COMPOSE_FILE up -d --build
echo "==== [$(date)] 部署完成 ===="
上面脚本的内容只是做一个简单的测试,所以具体的逻辑还没使用,只是做了echo 操作
第三部分,测试脚本
新建项目(这里是laravel12),然后拉到本地,新建dev分支,然后 push 到远程仓库,到宿主机的 /home/guoshipeng/Documents/code/deploy/目录下看有没有laravel-12项目,结果发现没有
但是脚本中的日志 /var/log/gitlab/custom_hooks.log
echo "$(date '+%Y-%m-%d %H:%M:%S') - Push to dev branch detected: $newrev" >> /var/log/gitlab/custom_hooks.log
有日志信息,证明这个脚本是执行了,但是ssh没有执行
我直接在gitlab容器里执行:
root@gitlab:/var/opt/gitlab/git-data/repositories/@hashed/9f/14/9f14025af0065b30e47e23ebb3b491d39ae8ed17d33739e5ff3827ffb3634953.git/custom_hooks# ssh guoshipeng@192.168.5.17 "/home/guoshipeng/Documents/code/deploy/deploy.sh"
==== [Fri Mar 7 12:07:37 AM CST 2025] 开始部署 Laravel 12 ====
>>> 目录不存在,克隆仓库...
Cloning into '/home/guoshipeng/Documents/code/deploy/laravel-12'...
remote:
remote: ========================================================================
remote:
remote: The project you were looking for could not be found or you don't have permission to view it. //这是另一个问题,上面已经解决
remote:
remote: ========================================================================
remote:
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
>>> 安装 PHP 依赖...
>>> 运行数据库迁移...
>>> 重新启动 Laravel 项目...
==== [Fri Mar 7 12:07:37 AM CST 2025] 部署完成 ====
发现脚本是可以执行的,那就很奇怪了,为什么hook下,ssh没有执行
第四部分,解决hook下,ssh没有执行的问题
目前的问题:
手动执行 ssh guoshipeng@192.168.5.17 "/home/guoshipeng/Documents/code/deploy/deploy.sh" 可以正常执行;
自动执行 post-receive hook 时,这个 SSH 命令没有被执行。
这表明: SSH 可能无法在 git 用户的环境中执行
在gitlab容器里查看日志 vim /var/log/gitlab/custom_hooks.log
...
...
debug1: Authenticating to 192.168.5.17:22 as 'guoshipeng'^M
debug1: load_hostkeys: fopen /var/opt/gitlab/.ssh/known_hosts: No such file or directory^M
debug1: load_hostkeys: fopen /var/opt/gitlab/.ssh/known_hosts2: No such file or directory^M
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts: No such file or directory^M
debug1: load_hostkeys: fopen /etc/ssh/ssh_known_hosts2: No such file or directory^M
debug3: order_hostkeyalgs: no algorithms matched; accept original^M
debug3: send packet: type 20^M
debug1: SSH2_MSG_KEXINIT sent^M
debug3: receive packet: type 20^M
debug1: SSH2_MSG_KEXINIT received^M
debug2: local client KEXINIT proposal^M
...
...
这说明 hook 脚本里执行 ssh 的用户为 git 用户,但是这个 git 用户没有被认证,这个 git 用户的默认加目录为: /var/opt/gitlab,而不是root用户的/root,之前在第一部分添加的认证其实都是root用户的,所以这里git用户执行ssh会失败
解决办法:
1.在容器里切换到git用户
sudo -u git mkdir -p /var/opt/gitlab/.ssh
sudo -u git ssh-keyscan 192.168.5.17 >> /var/opt/gitlab/.ssh/known_hosts
sudo -u git chmod 644 /var/opt/gitlab/.ssh/known_hosts
但是很遗憾,报:
root@gitlab:~# sudo -u git
bash: sudo: command not found
这是因为: 在 GitLab 容器里,默认是 没有 sudo 的,因为容器通常是最小化的环境
2.在 GitLab 容器里,并且是 root,切换到 git 用户:
su - git
如下:
root@gitlab:~# su - git
$ pwd
/var/opt/gitlab
然后执行:
mkdir -p ~/.ssh
ssh-keyscan 192.168.5.17 >> ~/.ssh/known_hosts
chmod 644 ~/.ssh/known_hosts
但是很遗憾,报:
git 用户下,执行脚本报
cannot create /var/opt/gitlab/.ssh/known_hosts: Permission denied
但是 前面的 mkdir -p ~/.ssh 却执行了,我想可能是 ssh-keyscan 没有权限吧
3.git 用户没有权限写入 /var/opt/gitlab/.ssh/known_hosts,可以用 root 用户 先创建 .ssh 目录并赋权给 git 用户:
从上面的git用户exit 出到root,执行:
mkdir -p /var/opt/gitlab/.ssh //这个其实不用执行了,因为上面已经创将了
chown -R git:git /var/opt/gitlab/.ssh
chmod 700 /var/opt/gitlab/.ssh
然后:
su - git #
# 添加 SSH 服务器的 key 到 known_hosts,避免 SSH 连接报错
ssh-keyscan 192.168.5.17 >> /var/opt/gitlab/.ssh/known_hosts //如果哦还有问题,就直接在root用户下执行,然后修改目录归属
chmod 644 /var/opt/gitlab/.ssh/known_hosts
我这里执行 ssh-keyscan 192.168.5.17 >> /var/opt/gitlab/.ssh/known_hosts 的效果如下:
ssh-keyscan 192.168.5.17 >> ~/.ssh/known_hosts //这个是我之前使用root的时候为root用户生成的, 其实root用户和git用户的known_hosts 存的内容都一样
# 192.168.5.17:22 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.11
# 192.168.5.17:22 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.11
# 192.168.5.17:22 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.11
# 192.168.5.17:22 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.11
# 192.168.5.17:22 SSH-2.0-OpenSSH_8.9p1 Ubuntu-3ubuntu0.11
$
$ ls -l ~/.ssh/known_hosts
-rw-r--r-- 1 git git 834 Mar 8 14:58 /var/opt/gitlab/.ssh/known_hosts
vim /var/opt/gitlab/.ssh/known_hosts, 内容如下:
192.168.5.17 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDLE4ptNJOj0gOQRqtADbuxXvWW+B+7GLTlqh2/MzRKgB2vchs5e3HlDdQ80UkQC6UqtUgzEdPljEw9+DfAUwd1kFw8YyL4ht/mu/m6Ru6xikvRml6m+5ZR8WeS0x9DTIByLplLWNRQvN9v3FMQNXo2b2l+rhVidsMMHhkS+eB9AUFr1dT101Nega+VHmLeVZTU96jFTxxHZCm9COID4ygwyDBTqLHr743D4H/dfEvkdy7GhMKtXPCdrBBATxykfD9KbGm65mlGxPAbyu7igo4rmNvsCBPxji90mL2UrtuSTB1UFuV2LabcQCHIUwAIdJF9JLyfPiROMcM4EAkl8xkCj/sOC+AfxGZx/HHpEdqo3iU+9xInnlgyuzSTcWXs2IiHE67Gczg4rovkMgXTrVRwotfAgy13XKX1TFGWvmg50qbBO6RUKRxNfONcXsnUdAi46kYRUqUuZ4NG8Fet6LyQvA6Gb0mO26lek6t2oo6KSeULHL/a5OYSPxhuUNEIyys=
192.168.5.17 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFERYqCHXozlOK5lE7F+FX5Cy3ejnURAs0XxzAPLmOVixwZgPKJ63HA8LrvZn2J9XUgSnFWSfN3wS85defqrLCg=
192.168.5.17 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICKLoOAsvzRv7gLc/edywOmsH7ewq+KVay+N/9n63eDP
在git 用户下测试:
ssh -T guoshipeng@192.168.5.17
...
...
debug1: Next authentication method: publickey^M
debug1: Trying private key: /var/opt/gitlab/.ssh/id_rsa^M
debug3: no such identity: /var/opt/gitlab/.ssh/id_rsa: No such file or directory^M
debug1: Trying private key: /var/opt/gitlab/.ssh/id_ecdsa^M
debug3: no such identity: /var/opt/gitlab/.ssh/id_ecdsa: No such file or directory^M
debug1: Trying private key: /var/opt/gitlab/.ssh/id_ecdsa_sk^M
debug3: no such identity: /var/opt/gitlab/.ssh/id_ecdsa_sk: No such file or directory^M
debug1: Trying private key: /var/opt/gitlab/.ssh/id_ed25519^M
debug3: no such identity: /var/opt/gitlab/.ssh/id_ed25519: No such file or directory^M
debug1: Trying private key: /var/opt/gitlab/.ssh/id_ed25519_sk^M
debug3: no such identity: /var/opt/gitlab/.ssh/id_ed25519_sk: No such file or directory^M
debug1: Trying private key: /var/opt/gitlab/.ssh/id_xmss^M
debug3: no such identity: /var/opt/gitlab/.ssh/id_xmss: No such file or directory^M
debug1: Trying private key: /var/opt/gitlab/.ssh/id_dsa^M
debug3: no such identity: /var/opt/gitlab/.ssh/id_dsa: No such file or directory^M
debug2: we did not send a packet, disable method^M
debug3: authmethod_lookup password^M
debug3: remaining preferred: ,password^M
debug3: authmethod_is_enabled password^M
debug1: Next authentication method: password^M
...
...
如果有 Permission denied (publickey)的问题,那说明 git 用户的 SSH Key 不正确或者不存在,大概率是不存在,执行:
su - git //切换到git用户
ssh-keygen -t rsa -b 4096 -C "git@gitlab" -f ~/.ssh/id_rsa -N ""
然后将 id_rsa.pub 复制到 192.168.5.17:
ssh-copy-id -i ~/.ssh/id_rsa.pub guoshipeng@192.168.5.17
会提示输入远程服务器的密码
成功后,就可以无密码SSH登录该服务器了
通过一下命令验证git 的 ssh key 是否被添加:
root@gitlab:~/.ssh# ssh -i /var/opt/gitlab/.ssh/id_rsa guoshipeng@192.168.5.17
Welcome to Ubuntu 22.04.2 LTS (GNU/Linux 6.8.0-52-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
* Introducing Expanded Security Maintenance for Applications.
Receive updates to over 25,000 software packages with your
Ubuntu Pro subscription. Free for personal use.
https://ubuntu.com/pro
Expanded Security Maintenance for Applications is not enabled.
201 updates can be applied immediately.
To see these additional updates run: apt list --upgradable
3 additional security updates can be applied with ESM Apps.
Learn more about enabling ESM Apps service at https://ubuntu.com/esm
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
New release '24.04.2 LTS' available.
Run 'do-release-upgrade' to upgrade to it.
Last login: Sun Mar 9 19:21:50 2025 from 172.17.0.4
guoshipeng@tianyi510s:~$
说明添加成功
还有个问题,对于 git 用户,我没有在它的.ssh目录下添加 config,用来添加host 别名,以简化连接,如果需要也可以为git用户添加一个 ~/.ssh/config,类似root用户的。
接下来,再重新提交代码,可以发现 /home/guoshipeng/Documents/code/deploy 下有了 laravel-12 这个目录,说明post-receive 这个脚本中的 ssh 被执行了
第五部分,关于known_hosts的作用
ssh-keyscan 192.168.5.17 >> ~/.ssh/known_hosts 的作用
这个命令的作用是 将 192.168.5.17 服务器的 SSH 主机密钥添加到 known_hosts 文件,避免 SSH 连接时手动确认主机身份。
原理如下:
SSH 连接时,客户端会检查服务器的身份,具体流程如下:
客户端尝试连接服务器(如 ssh user@192.168.5.17)。
服务器返回自己的 SSH 公钥(host key)。
客户端检查 ~/.ssh/known_hosts 文件:
如果 文件里已经有匹配的主机密钥,SSH 连接继续。
如果 文件里没有该服务器的密钥,SSH 会提示:
The authenticity of host '192.168.5.17 (192.168.5.17)' can't be established.
ECDSA key fingerprint is SHA256:xxxxx.
Are you sure you want to continue connecting (yes/no)?
选择 yes 后,该密钥会存入 known_hosts,以后就不会再提示。
ssh-keyscan 的作用:
ssh-keyscan 自动获取服务器的 SSH 主机密钥,并写入 known_hosts,避免手动确认。
如:
ssh-keyscan 192.168.5.17 >> ~/.ssh/known_hosts
等价于:
连接 192.168.5.17 获取 SSH 主机密钥(但不会真的 SSH 登录)。
把这个主机密钥追加 (>>) 到 ~/.ssh/known_hosts,避免手动输入 yes。
ssh-keyscan 可用于批量获取多台服务器的密钥:
ssh-keyscan 192.168.5.17 192.168.5.18 192.168.5.19 >> ~/.ssh/known_hosts
ssh-keyscan 不会验证 服务器身份,只是盲目地获取密钥,所以如果 DNS 劫持或中间人攻击发生,可能会存储错误的密钥。ssh-keyscan 可以获取任意服务器的 SSH 主机密钥,前提是该服务器允许通过 SSH 进行连接。ssh-keyscan 的作用就是 扫描并获取远程服务器的公钥,并将其输出到标准输出(通常是终端或指定文件)。它并不会尝试进行登录操作,只是读取服务器的公钥信息。
第六部分,关于ssh-copy-id
ssh-copy-id 是一个非常实用的命令,用于将本地主机的SSH公钥安装到远程主机的授权密钥文件中。细解释一下:
基本功能:
ssh-copy-id 的主要作用是简化SSH免密登录的配置过程。它会自动将你的公钥添加到远程服务器的 ~/.ssh/authorized_keys 文件中。这个命令大大简化了SSH免密登录的配置过程,是系统管理员和开发人员常用的效率工具。
工作原理:
它会读取本地的SSH公钥(通常是 ~/.ssh/id_rsa.pub)
将公钥上传到远程服务器
添加到远程服务器的授权密钥列表中
示例:
ssh-copy-id user@hostname
user:远程服务器的用户名
hostname:远程服务器的IP地址或域名
具体操作流程:
# 1. 先生成SSH密钥(如果还没有)
ssh-keygen -t rsa
# 2. 复制公钥到远程服务器
ssh-copy-id root@192.168.1.100
执行这个命令时:
会提示你输入远程服务器的密码
成功后,你就可以无密码SSH登录该服务器了
安全注意事项:
确保只对可信的服务器使用
保护好私钥
不要随意分享私钥
第七部分,检查宿主机下的 authorized_keys 有哪些
guoshipeng@tianyi510s:~$ pwd
/home/guoshipeng
guoshipeng@tianyi510s:~$ vim ~/.ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDLr/1E9ipQEN1au7R2SkjVXEuYFlnH3OHbRxXmWC7Ib4e+tj8jwwv/WSX2wV2FOTHZ7csoHdxqAHE8C9fTPBBAHyk+vhV+8BS/yYp+poqqTLHDO+Rkqy2ZZ2VIx3cQAhUTOtsYCP1Pkf55YeJmOpEunqE9CQyGNPuwCv1EF5zeTe+knV4g6EhTBJ/hXIRfb3kd1YJSOIJYWMElF5hiiiUuDu3+ZovlBmVHE3YNavV7GzJzPDkgHIWRMqMz9dVA+of4N3UHR5Sc54RhSlL3LErQ00Q24DEBfW29LC/oqNeKMDs+BPS7ArsCiHPVNZd1vSexufqh6GDf/B879II1FNB1/gFYTnphAH20JRcJK4JMEncC3UybUMDNCDiS7rarSSldmKhc0yrUL2bazUoFfCpmoQVUqaQHPsbDaIpfiJOSz64dOqUkVZfIxj73Q+02WN73dfaRskqySftRmoP36PhHIqLAKRjZZDft20hvrE0/KVXVuNem7W6Dq0uHGdYunLEhF82TpDZTNoZfvdtMACF8cAOVFRoLIJjRqBWQmKTTQF+xFo/P9JmnkgxJ9puDFm/bHH/fou9OcYKP7TPXIB7LGyEpkxX8iM6DqOOs/6XxJzQ+NFVvSVrHHceDRpJAYdKiQjAhC88qhxC6S1seCwWCs4xHgpiPsw37vl/BYYgMWw== root@gitlab.example.com
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDDMN/yVIWUufSrJBtB1hXSu3/zXwlcrXwihycTbjmc9L+3ukDXwa3JkEMJgrYPVNZQy/iEc6u9HbGEQv2ld60BtDuUagZvMgJfiinFq6D/BXxvdeCOo1TE2NrDvHrhUC67G0pT40vYgfa/Y5o/JYemu/MhRuj/rW/g1LZ+9vUOXhXuDDPSzGUueRJUmAOzDUkcsihHpFH6NlgQ9Adn+cUod9pw/z1EsUltroyuMZC3qJzADt3dXdEmiYDV0sw0B5oSE3v9Sm4nm+02hC0OL12xBisPXZR7FyxLHEW983XXGsomTX4f9rsdHVkaDv9ObI/pzbClYgFsWwj46xqt/rExZ550IExtUnh1CpXz2UD57m9AoLYph7bV21+0c48lMUwh/m7AYLXuBtAm7vPGA0mJWVei5Iuw5XIr+dNhg+IS+LWsjBKQis2UrqDLBNWYMGnlg0HLye6qIuPRiNb5quMfzx63KUygMHwkcG+/L9+7a7iA13/guMVNNEqjc8Ibe7Ikj33uc56rW+WVPF9MI9ITQsOOwTsW1cdx7856e+iYhs+WIs5da8llGrwaqbXuniSy5INbrG/E75+lu9iceptdt9853jL2giWiP7+jaQjqkV2zIHGtk4IulWZ+6myk/i+YUrxHiU5oEXeS+KJZxSXjvvZcGzmNS+b02ueD01ax6Q== git@gitlab
说明之前为 root 和 git 添加的 ssh key 都被保存到宿主机.
第八部分,总结
一定要为当前执行ssh的用户添加相应的权限,包括和目标服务器的连接.
四部分:
1.add known-hosts
2.generate SSH key
3.copy SSH key
4.grant role
