很多时候考虑到企业项目可维护性,大家还是希望拥有自己的代码版本库,github、gitee都是不错的选择,但是完全依赖于这些平台,对代码安全性总有疑虑,也不利于自己团队在版本管理上的成长。gitee企业版今天也出了点小问题,登录后总提示500错误。于是考虑了落实自建git服务器的计划。
Git服务器搭建过程
参考文章:
Aaron的个人技术博客 CentOS7搭建git 服务器。
正如Aaron所说,这个方案适合于自己开发,自己使用,遇到团队作战时,管理起来就不那么方便灵活了。但是熟悉Git服务器搭建过程,是继续团战的基础。本文会根据Aaron和Git中文网的资料,进行团战搭建的介绍。
本文是实践总结,主要记录按照上述文章实际搭建中遇到的问题。
- yum 安装 git
# yum install git
- 备注:网上有很多从源码安装的例子,我实操下来感觉不是很有必要,yum库安装速度快,还可以避免一些目录和权限的问题,所以推荐直接yum 安装 git。
- 确认git版本
# git --version
git version 1.8.3.1
- 备注:CentOS7 自带了1.8.3.1
- 添加git用户组和git用户
# groupadd git
# adduser git -g git
# passwd
- 备注1:原文只使用 adduser git,但实际上他也是创建了git组的,我还是老老实实用了上面这串命令
- 备注2:passwd执行后,要求输入密码,就是给git账号设置密码
- 创建git工作目录
# mkdir -p /home/git/.ssh
# chmod 700 /home/git/.ssh
# chown -R git:git /home/git
- 备注:加上-p支持 mkdir创建多级目录
- 创建用户公钥保存的文件
# touch /home/git/.ssh/authorized_keys
# vi /home/git/.ssh/authorized_keys
- 备注1:添加用户公钥时,要一行一个。
- 备注2:windows下获取ssh公钥的方法,可在git客户端的git bash下执行如下的命令
# ssh-keygen
- 备注3:上面的命令可以一路yes,一路默认,不输入密码。最终在windows的用户目录下的.ssh目录下,可以找到id_rsa.pub,把内容copy出来,一行一个用户的粘贴到上面的文件中即可。
- 创建测试代码库
# cd /home
# git init --bare test.git
Initialized empty Git repository in /home/test.git/
# chown -R git:git test.git
# ll
total 0
drwxr-xr-x 7 git git 119 Jan 27 22:44 test.git
- 设置git用户只能登录执行git-shell,且每次都要登录
# vi /etc/passwd
找到git:x开头的那行改为
git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
- 备注:上面这里的/usr/bin/git-shell是你的git-shell所在的目录,如果用yum安装git,应该就是在这个目录,如需要确认,可执行下面的命令查找
# find / | grep git-shell
find: ‘/proc/1831’: No such file or directory
/usr/bin/git-shell
/usr/share/doc/git-1.8.3.1/contrib/git-shell-commands
- 本地电脑远程克隆test.git测试
这里给出两个方案:
方案1: 如果你的ssh端口号没有变动,可能下面的命令已经可以执行了,我自己的服务器是改了ssh端口号的,所以我不知道下面的命令是否可以正常执行
# git clone git@服务器IP地址:/home/test.git
Cloning into 'test'...
warning: You appear to have cloned an empty repository.
方案2: 如果你的ssh端口号变了,要按照下面的命令来执行,才能成功。这也是我一开始没搞定的原因,特此记录。
# git clone ssh://git@服务器IP地址:ssh端口/home/test.git
Cloning into 'test'...
The authenticity of host '[服务器IP]:ssh端口 ([服务器IP]:ssh端口)' can't be established.
ECDSA key fingerprint is SHA256:************************************************.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[服务器IP]:ssh端口' (ECDSA) to the list of known hosts.
warning: You appear to have cloned an empty repository.
- 备注:至此,git服务器搭建完成了,我们还要把自己的git库传到服务器上去,这个问题等一会儿会讲。
增加Gitosis管理,方便团队化作战
安装Gitosis
恭喜你,经过刚才的实践,你已经掌握了Git服务器的搭建方法。上面的方案有三个问题:
- git clone 的远程git路径,是全路径,相对来说记忆比较困难。
- 用户的添加是通过修改/home/git/.ssh/authorized_keys,人员增加后维护起来就比较麻烦。
- 这个问题应该比较关键。 git仓库无法进行多项目的权限控制,一旦增加人员,就自动获取了全部项目的代码访问权限。
为了解决上述问题,Gitosis应运而生了。
Gitosis 主要解决两个问题:
- 相对路径问题
- 项目的分组管理和人员授权访问问题。
还是先进行安装实践,我会结合实际情况,介绍解决遇到的一些问题。
- 安装python依赖
Gitosis 的工作依赖于某些 Python 工具,所以首先要安装 Python 的 setuptools 包
# yum install python-setuptools
1.1 (补充) 执行上面的命令时,在一个新的阿里云服务器上出了问题
Installed /usr/lib/python2.7/site-packages/gitosis-0.2-py2.7.egg
Traceback (most recent call last):
File "setup.py", line 64, in
'setuptools>=0.6c5',
File "/usr/lib64/python2.7/distutils/core.py", line 152, in setup
dist.run_commands()
File "/usr/lib64/python2.7/distutils/dist.py", line 953, in run_commands
self.run_command(cmd)
File "/usr/lib64/python2.7/distutils/dist.py", line 972, in run_command
cmd_obj.run()
File "/usr/lib/python2.7/site-packages/setuptools/command/install.py", line 73, in run
self.do_egg_install()
File "/usr/lib/python2.7/site-packages/setuptools/command/install.py", line 101, in do_egg_install
cmd.run()
File "/usr/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 380, in run
self.easy_install(spec, not self.no_deps)
File "/usr/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 604, in easy_install
return self.install_item(None, spec, tmpdir, deps, True)
File "/usr/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 655, in install_item
self.process_distribution(spec, dist, deps)
File "/usr/lib/python2.7/site-packages/setuptools/command/easy_install.py", line 701, in process_distribution
distreq.project_name, distreq.specs, requirement.extras
TypeError: __init__() takes exactly 2 arguments (4 given)
搜索后确认,是yum 安装的setuptools 版本不对
# ll /usr/lib/python2.7/site-packages/
drwxr-xr-x 5 root root 4096 Mar 4 23:29 setuptools
drwxr-xr-x 2 root root 4096 Mar 4 23:29 setuptools-0.9.8-py2.7.egg-info
-rw-r--r-- 1 root root 793874 Mar 5 00:10 setuptools-33.1.1-py2.7.egg
drwxr-xr-x 2 root root 4096 Nov 29 11:40 setuptools-36.4.0.dist-info
-rw-r--r-- 1 root root 30 Mar 5 00:10 setuptools.pth
网上的解决方案是 删除 该目录下 所有的 setuptools文件夹,然后再重新安装
# yum remove python-setuptools
# rm /usr/lib/python2.7/site-packages/setuptool* -rf
用pip重新安装 setuptools
# wget https://bootstrap.pypa.io/ez_setup.py
--2019-03-05 00:09:44-- https://bootstrap.pypa.io/ez_setup.py
Resolving bootstrap.pypa.io (bootstrap.pypa.io)... 151.101.228.175, 2a04:4e42:36::175
Connecting to bootstrap.pypa.io (bootstrap.pypa.io)|151.101.228.175|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 12537 (12K) [text/x-python]
Saving to: ‘ez_setup.py’
100%[=============================================================================================================>] 12,537 --.-K/s in 0.07s
2019-03-05 00:09:45 (177 KB/s) - ‘ez_setup.py’ saved [12537/12537]
# python ez_setup.py
ez_setup.py is deprecated and when using it setuptools will be pinned to 33.1.1 since it's the last version that supports setuptools self upgrade/installation, check https://github.com/pypa/setuptools/issues/581 for more info; use pip to install setuptools
Downloading https://pypi.io/packages/source/s/setuptools/setuptools-33.1.1.zip
Extracting in /tmp/tmpi_jCtH
Now working in /tmp/tmpi_jCtH/setuptools-33.1.1
...
Installed /usr/lib/python2.7/site-packages/setuptools-33.1.1-py2.7.egg
Processing dependencies for setuptools==33.1.1
Finished processing dependencies for setuptools==33.1.1
# easy_install-2.7 pip
Searching for pip
Best match: pip 18.1
Adding pip 18.1 to easy-install.pth file
Installing pip script to /usr/bin
Installing pip3.7 script to /usr/bin
Installing pip3 script to /usr/bin
Using /usr/lib/python2.7/site-packages
Processing dependencies for pip
Finished processing dependencies for pip
# pip2.7 install --upgrade pip
Looking in indexes: http://mirrors.aliyun.com/pypi/simple/
Collecting pip
Downloading http://mirrors.aliyun.com/pypi/packages/d8/f3/413bab4ff08e1fc4828dfc59996d721917df8e8583ea85385d51125dceff/pip-19.0.3-py2.py3-none-any.whl (1.4MB)
100% |████████████████████████████████| 1.4MB 73.7MB/s
Installing collected packages: pip
Found existing installation: pip 18.1
Uninstalling pip-18.1:
Successfully uninstalled pip-18.1
Successfully installed pip-19.0.3
# rm /usr/lib/python2.7/site-packages/setuptool* -rf
# python -m pip install --upgrade pip setuptools wheel
DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7.
Looking in indexes: http://mirrors.aliyun.com/pypi/simple/
Requirement already up-to-date: pip in /usr/lib/python2.7/site-packages (19.0.3)
Collecting setuptools
Downloading http://mirrors.aliyun.com/pypi/packages/d1/6a/4b2fcefd2ea0868810e92d519dacac1ddc64a2e53ba9e3422c3b62b378a6/setuptools-40.8.0-py2.py3-none-any.whl (575kB)
100% |████████████████████████████████| 583kB 52.2MB/s
Collecting wheel
Downloading http://mirrors.aliyun.com/pypi/packages/96/ba/a4702cbb6a3a485239fbe9525443446203f00771af9ac000fa3ef2788201/wheel-0.33.1-py2.py3-none-any.whl
Installing collected packages: setuptools, wheel
Found existing installation: wheel 0.29.0
Uninstalling wheel-0.29.0:
Successfully uninstalled wheel-0.29.0
Successfully installed setuptools-40.8.0 wheel-0.33.1
最后得到 setuptools-40.8.0 这个版本
再次执行
# python setup.py install
安装成功
- 获取 Gitosis 源码,并安装
# git clone https://github.com/tv42/gitosis.git
# cd gitosis
# python setup.py install
- 备注: 这会安装几个供 Gitosis 使用的工具。默认 Gitosis 会把 /home/git 作为存储所有 Git 仓库的根目录。
- 修改git账号的权限
# vi /etc/passwd
找到 git:x: 开头那行,改回
git:x:1001:1002::/home/git:/bin/bash
- 备注:上一段,我们直接用Git服务器时,为了避免git账户的非法登录,我们改成每次必须登录,命令行为git命令行的方式。但是由于gitosis需要的系统命令更多,所以还是必须要改回bin/bash的模式
- 清掉/home/git/.ssh/authorized_keys
# rm -rf /home/git/.ssh/authorized_keys
# touch /home/git/.ssh/authorized_keys
# chown -R git:git /home/git/
- 备注:因为Gitosis需要接管Git服务器的授权访问控制,所以authorized_keys将由Gitosis来维护,为了避免控制面的冲突,我们需要清掉authorized_keys,重新通过Gitosis来创建用户。不用担心之前的访问权限丢失,下一步将之前的账号加回来之后,权限自然恢复。
- 初始化Gitosis
准备工作:用ftp或其他将你的id_rsa.pub,ssh公钥文件上传的git服务器,假设位置在/tmp/id_rsa.pub。
然后还是在刚才的Gitosis源码目录下
# su - git
# gitosis-init < /tmp/id_rsa.pub
# cd ~
# ll
total 0
drwxr-xr-x 2 git git 27 Jan 28 01:28 gitosis
drwxr-xr-x 8 git git 124 Jan 28 01:37 repositories
- 备注:这里我执行时,只遇到过权限导致的问题,解决方案就是 回到 root账号下,执行 chown -R git:git /home/git/
- 总结一下,上面干了什么
主要工作是:
- 利用Python安装好了Gitosis的环境
- 利用 /tmp/id_rsa.pub 初始化了一个管理Gitosis的账户
一切的真相在你打开 /home/git/.ssh/authorized_keys 后就知晓了。
# vi /home/git/.ssh/authorized_keys
你会看到刚才被我们清掉的authorized_keys文件里,被导入了id_rsa.pub的内容,但是和我们自己的写入的时候有所差异
### autogenerated by gitosis, DO NOT EDIT
command="gitosis-serve 用户名",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
管理Gitosis
刚才我们安装Gitosis后,发现/home/git下多了两个目录
# ll
total 0
drwxr-xr-x 2 git git 27 Jan 28 01:28 gitosis
drwxr-xr-x 8 git git 124 Jan 28 01:37 repositories
重要的目录只有一个repositories,这里面存储以后我们所有的项目的git仓库文件
# cd /home/git/repositories
# ll
total 0
drwxr-x--- 7 git git 139 Jan 28 01:28 gitosis-admin.git
目前这个目录下只有一个文件夹gitosis-admin.git,这就是Gitosis自带的管理工具了,接下来我们需要把这个工具clone到本地,来管理一下Gitosis
- clone Gitosis-admin
在你刚才获得id_rsa.pub的那台电脑,一般就是你的工作机吧。
# git clone git@服务器IP:gitosis-admin.git
如果是ssh端口号改变的情况
# git clone ssh://git@服务器IP:ssh端口号/gitosis-admin.git
- 备注1:注意到吗?gitosis-admin.git的并没有使用全路径来获取。如果你执行上面的命令成功了,说明你已经可以使用相对路径来访问git仓库了
- 备注2:如果你遇到错误:fatal: '/gitosis-admin.git' does not appear to be a git repository ,也就是相对路径不生效。原因只是因为你可能没有清空/home/git/.ssh/authorized_keys,该文件里有不是Gitosis标准的公钥配置存在,导致了Gitosis出错了。方法就是删掉authorized_keys,走刚才的安装Gitosis时的第5步,重新初始化一下他,一般问题就解决了。
- clone成功,怎么通过gitosis-admin就能管理Gitosis和Git呢?
原理:gitosis-admin 通过gitosis.conf来配置项目组、用户组和权限关系,通过keydir目录保存用户的公钥,通过git提交实现对Gitosis服务配置的更新维护。
看一下gitosis-admin的目录
# dir
2019/01/28 01:15 .
2019/01/28 01:15 ..
2019/01/28 01:22 365 gitosis.conf
2019/01/28 01:21 keydir
- 编辑gitosis.conf,实现项目和用户管理
[gitosis]
// gitosis-admin的可访问用户设置
[group gitosis-admin]
writable = gitosis-admin // 可读写的工程项目
members = Administrator // 这里名字和keydir目录下的pub文件名字要保持一致,也就是说keydir目录下要有一个名为 Administrator.pub 的文件
// 组可以只有用户而没有工程项目,这种可以方便的对项目的访问权限进行用户群组管理
[group developer]
members = tom Jams KK // 开发组,完整的读写权限
[group tester]
member = miya lucy lily //测试组,只需要只读权限
// 工程项目实例
[group test1]
writable = test1 // 可读写的工程项目
member = @developer // 三个开发组成员将同时具有该项目的读写权限。
[group test1_readonly]
readonly = test1 // 只读权限
member = @tester Jack // 三个测试组成员和Jack可以克隆和获取更新,但 Gitosis 不会允许他向项目推送任何内容。
- 小结
通过上面的工作,我们搞定了Gitosis管理Git服务器。Gitosis利用Git本身非常巧妙的实现了控制Git服务器的目的。
如何将已有git代码迁移到自己的git服务器
这部分估计很多人都有经验了,但是我还是记录一下,让这个经验总结有头有尾,方便大家查看。
- 将本地代码的变更及时缓存起来
# git add .
# git commit -m "init own git server"
- 在git服务器上创建空白仓库
# cd /home/git/repositories
# mkdir 仓库名.git
# cd 仓库名.git
# git init --bare
- 利用Gitosis赋予仓库访问权限
# vi gitosis-admin/gitosis.conf
将内容编辑为
[gitosis]
[group gitosis-admin]
members = administrator
writable = gitosis-admin
[group common]
members = Jack
[group 仓库名]
members = @common
writable = 仓库名
提交变更
# cd gitosis-admin
# git add .
# git commit -m "添加仓库"
# git push
- 备注:到这里,仓库名.git就能够用Jack的账户进行远程更新和上传了。
- 修改本地代码的git remote,将代码上传到git服务器
# git remote remove origin
# git remote add origin ssh://git@服务器IP:ssh端口/仓库名.git
# git push -u origin master
# git pull
# git branch --set-upstream-to=origin/master master
# git pull
这里,Jack的本地代码和git服务器的代码就关联起来了。