RHEL8 设置简易Git Server

背景介绍

目标: 在一台RHEL8 Linux主机配置一个Git Server(不采用GitLab),这样别的电脑可以连接到它上面并把该主机作为一个Remote Repository。

准备:
两台电脑: 1台RHEL8作为服务器,另一台Linux或者Mac,作为客户端

操作概要:

  1. 服务器端创建一个新用户,命名为git,稍后客户端将使用此用户名登陆。
  2. 客户端运行ssh-keygen命令生成用于SSH登陆的私钥和公钥,并把公钥保存到服务器上以实现客户端可以通过SSH Key文件方式远程登录到服务器, 因为稍后的git push和pull操作都需要通过SSH连接实现。
  3. 服务器端创建一个bare型git repo
  4. 客户端创建一个local repo并执行各种git 操作保存文件。 添加远程repo,成功后就可以实现远程操作了。

具体操作

1. 服务器端添加一个新用户git

# useradd git
sudo useradd git
useradd: cannot open /etc/passwd

原因: passwd文件以及shadown文件都被系统锁定,防止被删除或更改。需要先解锁这两个文件才可以继续创建新用户:

# use lsattr Command view /etc/passwd Hidden permissions
$ lsattr /etc/passwd
----i--------------- /etc/passwd  # i: Can't be deleted or changed
sudo chattr -i /etc/passwd  # -i : remove i, +i: add i

同样操作适用于/etc/shadow文件,都去掉i属性后,就可以创建新用户了,用户名git,密码随意,因为我们稍后不会再使用用户名密码方式登陆服务器。

# useradd git
sudo useradd git  # create user 'git'
sudo passwd git   # update password for new user 'git'

创建并修改完密码后就可以锁定上述两个文件了, 使用参数‘+i’:

sudo chattr +i /etc/passwd  # -i : remove i, +i: add i
sudo chattr +i /etc/shadow  # -i : remove i, +i: add i

2.客户端生成用于SSH登陆的私钥和公钥

客户端Mac或Linux 命令行运行ssh-keygen命令生成用于SSH登陆的私钥和公钥。可以使用默认的私钥名称id_rsa, 也可以自己重新命名。生成的公钥文件名是'私钥.pub'格式以方便区分。如果客户端本地之前运行过ssh-kengen命令,也可以复用某个私钥公钥对,不过建议重新生成一组新的,并给予清晰命令以方便后续识别或移除。

执行完该命令后打开生成的公钥文件,里面是一段文本,这段文本稍后需要复制到远端服务器上。

以git用户名登陆到远端服务器后,在git用户home目录下/home/git检查是否存在.ssh文件夹,不存在,则创建,并修改属性为700,只允许git用户访问此文件夹

cd /home/git
mkdir .ssh
chmod 700 git

之后cd进入.ssh文件夹,查看是否存在名为authorized_keys的文件,不存在则创建并修改文件属性为600。之后编辑此文件,将客户端生成的公钥文件添加到此文件。

权限问题: 网上搜索文章都推荐设置.ssh文件夹和authorized_keys文件夹属性为700和600,经过我RHEL8测试,authorized_keys不能有执行权限,否则会导致无法登陆,报错“Received disconnect from xx: Too many authentication failures”。.ssh文件夹倒是要求不高,我试过不同数值755等都不影响登陆。如果出现该错误,请注意检查此两处的权限设置是否正确。推荐设置为700和600来降级系统风险。

nano authorized_keys

3. 服务器端创建一个bare型git repo

以git用户名登陆服务器,在home目录下创建一个文件夹用来保存repo文件。这里我们操作如下:

cd /home/git
mkdir gitrepos
cd gitrepos
mkdir test.git  # 采用一个明显的文件夹名用来区分各个repo
cd test.git     
git init --bare # --bare 参数很重要

执行完毕后, /home/git/gitrepos/test.git文件夹下就生成了一堆文件,已经可以接受客户端的push了,如下所示:

[git@localhost test.git]$ ls -al
total 12
drwxrwxr-x. 7 git git 119 Oct 15 00:00 .
drwxrwxr-x. 3 git git  22 Oct 14 23:58 ..
drwxrwxr-x. 2 git git   6 Oct 14 23:58 branches
-rw-rw-r--. 1 git git  66 Oct 14 23:58 config
-rw-rw-r--. 1 git git  73 Oct 14 23:58 description
-rw-rw-r--. 1 git git  23 Oct 14 23:58 HEAD
drwxrwxr-x. 2 git git 241 Oct 14 23:58 hooks
drwxrwxr-x. 2 git git  21 Oct 14 23:58 info
drwxrwxr-x. 7 git git  60 Oct 15 00:00 objects
drwxrwxr-x. 4 git git  31 Oct 14 23:58 refs

4. 客户端创建一个local repo并执行各种git 操作保存文件

这个就是git的常规操作了,简单记录如下:

mkdir testlocalgit
cd testlogcalgit
git init
nano README.txt
git add .
git commit -m "Init Commit with README file"

之后重点来了,给此repo添加Remote, 采用SSH方式连接,注意要和服务器上的repo路径一致。

# 添加远端Repo
git add remote origin ssh://git@192.../home/git/gitrepos/test.git

# push 本地repo到服务器上对应的远端Repo:
git push origin master

讨论

本地客户端SSH配置以运行多个不同用户连接和Key文件

实际工作中常遇到的如下两种情况:

  1. 一台工作电脑可能要SSH连接到不同的服务器上,为了安全,每个服务器连接时会产生一对不同的私钥和公钥文件。
  2. 对于同一个远端服务器,可能需要使用不同用户名进行登陆链接,比如一个是git用户用于git repo操作,另一个是普通用户,用于执行其他各种操作,为了安全起见,分别给他们创建了不同的私钥和公钥文件。

针对上述两种情况,就需要对客户端的SSH进行配置。搜索了一下,找到了几个参考链接:
SSH config使用教程和总结, ssh配置文件详解.
官方手册可以通过如下命令查询:

man ssh_config

ssh(1) obtains configuration data from the following sources in the following order:

           1.   command-line options
           # 命令行参数,如-p 10086, -i /path/to/identity_file 等选项来设置SSH的端口号或认证证书位置
           
           2.   user's configuration file (~/.ssh/config)
           # 针对某个用户的配置文件,所在路径为~/.ssh/config,默认是不存在的,需要手动创建
           
           3.   system-wide configuration file (/etc/ssh/ssh_config)
           # 针对系统所有用户的配置文件,,所在路径为/etc/ssh/ssh_config
     
     For each parameter, the first obtained value will be used.  

注意看最后一行,对于同一个参数在上面1,2,3多处有不同取值时,第一个获取的参数值为有效。因此上面3个方式的优先级也是 1 > 2 > 3。这里我主要记录通过第2种方式来配置本地的SSH连接,也就是修改本地的~/.ssh/ssh_config文件。打开该文件后,可以发现它里面包含多个Host 代码块,每个Host块就是一个匹配规则。具体格式如下:

Host alias1                        # 机器别名
    HostName 192.168.1.2           # 主机地址
    User root                      # 用户名
    IdentityFile ~/.ssh/id_ecdsa   # 认证文件
    Port 22  
 
Host alias2
    HostName 192.168.1.3
    Port  9002
    User  Jones

上面解释的已经比较清楚了,机器别名特别好用,可以节省好多打字 😃

上面例子中,alias1 代码块里指定了用户名,ip地址,私钥文件地址,因此,一个繁琐的标准命令:

ssh -i ~/.ssh/id_ecdsa root@192.168.1.2

就可以用如下简单命令代替, 是不是很方便?容易区分还不容易出错。

ssh alias1

有了别名,我们就可以通过给不同服务区使用不同别名,或者给同一个服务器的不同用户分配一个不同别名alias,再分别 ssh alias 就可以了。例如

Host LocalGit                      # 机器别名
    HostName 192.168.2.123         # 主机地址
    User git                       # 用户名是git
    IdentityFile ~/.ssh/id_ecdsa   # 认证文件
    Port 22  

Host LocalUser                     # 机器别名
    HostName 192.168.2.123         # 主机地址
    User tom                       # 用户名tom
    IdentityFile ~/.ssh/tom_key    # 认证文件
    Port 22  

就可以通过如下两个短命令进行访问。

ssh LocalGit
ssh LocalUser

同样的,如果使用了别名,那么上面在添加Git远程仓库的时候,就可以对应地直接使用别名:

# 添加远端Repo
git add remote origin ssh://git@192.../home/git/gitrepos/test.git

# 添加远端Repo
git add remote origin ssh://LocalGit/home/git/gitrepos/test.git