今天主要叙述在家里台式机的虚拟机上搭建支持
https 的 ubuntu git 服务器。

实际上,从一个用户请求家里
git 服务器代码,最终完成代码的传输,主要是通过以下的过程:

首先,从外界寻找到连接上互联网的家里的路由器,由路由器发送请求到虚拟机的
host,由 host 发送到虚拟机,由虚拟机的 apache 服务器将 https 请求转化为 git 数据请求发送给 git 服务程序,git 服务器程序拿到数据以后原路返还,下面一点一点的将这个过程说清楚。

第一步:从外界找到家里的路由器

由于家里的网络是动态拨号,没有固定
ip,所以想实现这个需求,就必须使用动态 DNS

可以使用花生壳的 DDNS,这一步每一个路由器都不同,所以不再详述。

第二步:从路由器发送到 host

发送到 host 的过程主要用到路由器的端口映射功能,并且需要配置 host 的防火墙以保证入站是通畅的。

  1. 规划好路由器对外暴露的端口和主机暴露的端口,以及主机的局域网
    ip

    路由器对外暴露的端口,最后我们会以
    https://XXXX.YYYYY.CCCCC:路由器对外端口/XX的形式访问到内部服务,这里假设为 10086

    Host 暴露的接口,路由器会将请求发送给这个端口,以提供服务,这里假设为 56789。

    主机的局域网 ip 用来配置端口映射时,让路由器知道应该将请求发送到哪个机器去,这里假设为 192.168.3.50

  2. 配置主机
    ip

    有两个方法,一个是主机直接在 ip 设置里面手动配置,但是这种配制方法不一定能完全消除 ip 冲突(虽然家庭局域网的 ip 冲突不常见),所以可以利用路由器的 ip 分配功能,每个路由器不一样,在我的路由器界面如下:

    为特定
    mac 地址分配了特定的 ip

  3. 配置路由器到主机的端口映射

    这一步每个路由器的界面都不一样,但是配置的原理是共通的

    我使用的是
    netgear orbi,其配置界面如下(高级——高级设置——端口映射/端口触发——添加自定义服务),外部端口组指的是路由器对外开放的端口,内部端口组是局域网提供服务主机的端口。

    1. 为主机添加防火墙规则

    进入以上界面,点击"入站规则"后,再点击右侧栏的"新建规则",出现以下界面:

    至此,第二步配置完毕

第三步:从
host 转发到虚拟机

这一步需要配置虚拟机 NAT 模式的端口转发,并且设置虚拟机的
ip 地址,还要配置虚拟机 apache 服务器 https git 服务的端口

  1. 规划虚拟机
    ip、服务端口、网段等

    这里假设子网
    ip 为 192.168.158.0,掩码是 255.255.255.0

    虚拟机 ip 是 192.168.158.20

    给虚拟机分配的 git 服务端口是 5000

  2. 设置虚拟机软件


    vmware 为例(其他虚拟机软件也有类似功能),点击"编辑"——"虚拟网络编辑器",按照如下界面配置

    之所以
    dhcp 从 128 开始,是因为保证 .20 这个地址没有自动分配到别的虚拟机去。

  3. 配置主机虚拟机软件的端口转发规则

    注意这里的网关
    ip,下面要用到

  4. 设置虚拟机

    开启虚拟机,这里以
    ubuntu 16.04 LTS 英文版版本为例,其他版本大同小异

    "system settings"——"network"

    注意,这里的 DNS Server 和上面的网关 ip 设置一样,也可以设置为家里路由器的地址,比如 192.168.3.1

    然后关闭并打开下图的开关,重新让虚拟机连一下网,使之分配到新的 ip 去

    尝试在虚拟机里连接一下网络,测试一下。

    至此,第三步已经全部完毕。

    关于第三步,实际上可以使用虚拟机的桥接模式,使之成为局域网中的一个独立机器,这样,直接从路由器就可以给虚拟机分配一个
    ip(详见步骤二),并且配置端口转发。这种方法省去了配置 host 防火墙的步骤,容易维护(不用修改虚拟机 NAT 规则,也不用在虚拟机里面配置静态 ip,直接使用路由器的预留 ip,虚拟机使用 dhcp 获得就可以了)

    但是我这里之所以使用了 NAT 模式,是因为我上一个路由器这样做有
    bug(吐槽荣耀 pro……),在如此配置之后,路由器只能识别虚拟机的网卡,却不能识别主机的网卡,导致分配到主机的其他服务全都用不了了,所以只能使用 NAT 模式,如果路由器能支持识别桥接的虚拟机,那当然要用桥接。我这里就不改了,算是提供一个桥接不行的时候的思路。

第四步:从
apache 服务器将 https 请求转化为 git 数据请求发送给数据程序

这一步需要配置
apache 的服务器,开启 https 支持,开启 git 支持,增加 Git 账户名和密码。

进入虚拟机:

  1. 安装
    apache2 的相关工具

    sudo apt-get install apache2 apache2-utils openssl

  2. Create git repository folder

    创建一个用于存储代码仓库的文件夹,后面配置服务器主机的时候会用到

    cd /opt

    sudo mkdir git

    sudo chown youraccountname:www-data git

    之所以将 owner 变为当前登录服务器的用户名,是因为这样好管理,后来管理代码库时,用不着每一次都 sudo

  3. 创建
    CA 证书,这里以 self signed 为例

    这里创建的是自己签名的 CA 证书,实际上网上也有很多免费的
    CA 证书,比如腾讯云的。之所以这里选择自己签名的,是因为大多数情况下这种方法够用(毕竟是自己的服务器,几乎只有自己用),不过,自己签名的 CA 证书在 git clone 的时候可能遇到问题,后面步骤会有解决方案。

    我们假设把证书存储在了 /opt/sites_conf 目录中

    sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /opt/sites_conf/apache.key -out /opt/sites_conf/apache.crt

    运行以后,填写方法大概如下:

    Country Name (2 letter code) [AU]:CN

    State or Province Name (full name) [Some-State]:Beijing

    Locality Name (eg, city) []:Beijing

    Organization Name (eg, company) [Internet Widgits Pty Ltd]:这里随便填

    Organizational Unit Name (eg, section) []:这里随便填

    Common Name (e.g. server FQDN or YOUR name) []:这里一定要填写个人服务器的域名,在本例中,就是 XXXX.YYYYY.CCCCC,如果不一致,后面的 ssl 验证会失败

    Email Address []:随便填

  4. Enable apache modules

    sudo a2enmod cgi alias env rewrite

  5. Listen port 5000

    sudo gedit /etc/apache2/ports.conf

    在这个文件里面加入一行:

    Listen 5000

    然后保存退出

  6. Config virtual machine

    cd /etc/apache2/sites-available

    创建新的配置文件并且填入内容:

    sudo gedit git_server.conf

    填入如下内容

    <VirtualHost *:5000>

    ServerAdmin you@example.com

    ServerName RukaCode

    SetEnv GIT_PROJECT_ROOT /opt/git

    SetEnv GIT_HTTP_EXPORT_ALL

    SSLEngine on

    SSLCertificateFile /opt/sites_conf/apache.crt

    SSLCertificateKeyFile /opt/sites_conf/apache.key

    DocumentRoot /opt/git

    <Files "git-http-backend">

    AuthType Basic

    AuthName "Git Access"

    AuthUserFile /opt/sites_conf/htpasswd

    Require valid-user

    Order deny,allow

    Deny from env=AUTHREQUIRED

    Satisfy any

    </Files>

    <Location />

    AuthType Basic

    AuthName "Git Repositories"

    AuthUserFile /opt/sites_conf/htpasswd

    Require valid-user

    Order allow,deny

    Allow from all

    </Location>

    ScriptAlias / /usr/lib/git-core/git-http-backend/

    RewriteEngine On

    RewriteCond %{QUERY_STRING} service=git-receive-pack [OR]

    RewriteCond %{REQUEST_URI} /git-receive-pack$

    RewriteRule ^/ - [E=AUTHREQUIRED]

    </VirtualHost>

    这里的配置阻止了 invalid user 的 clone,并且也阻止了 http 的访问。如果不需要阻止 invalid user 的 clone(比如开源项目),那么可以将 <Location> 那一段去掉。此时 invalid user 可以 clone 但是不能 push。

    接着,需要将此配置
    link 到 enable 文件夹里面去

    cd ../sites-enabled

    sudo ln -s ../sites-available/git_server.conf .

  7. 启动虚拟机

    sudo apachectl start

    或者如果已经启动了虚拟机的话,那就

    sudo apachectl restart

  8. 在 /opt/git 里面创建需要的代码库

    cd /opt/git

    mkdir test_repo.git

    cd test_repo.git

    git init --bare

    sudo chgrp www-data -R .

  9. 在 /opt/sites_conf 里面创建用户名、密码文件

    htpasswd -c /opt/sites_conf/htpasswd yourusername

    这里的文件路径一定要和上面配置文件里面的

    AuthUserFile /opt/sites_conf/htpasswd

    对应

至此,服务器端已经配置完毕。接下来还需要有两个步骤,一个步骤是创建一个
git 代码库,并且 push 到服务器上去,因为此时创建的 test_repo.git 是空的,其他用户 clone 下来是一个空的 repo,其 HEAD、upstream 等都没有设置好,所以此步骤解决这个问题。还有一个步骤,是将服务器的 self signed 的 CA 证书添加到 git 的信任 sites 里面,这一步主要是因为我们的证书是自签名的,因此 git 在 clone 的时候验证其合法性时,会直接 deny 掉这个请求,需要将其添加到信任证书里。

  1. 在任意机器上,创建一个本地
    repo,假设这个 repo 在 ~/my_test_repo 文件夹下

    mkdir ~/my_test_repo

    cd my_test_repo

    git init

    touch README.txt

    git add .

    git commit -m 'add read me file'

  2. 添加服务器证书到
    git 信任列表里

    git 信任列表由 http.sslCAInfo 来控制,设置这个值为一个文件,git 就会在这个文件里面查找是否是一个受信任的主机,所以我们要做的就是将服务器的 crt 文件内容复制到这里的文件里面。

    要显示服务器的
    crt 文件内容,最简单的就是使用浏览器,但是由于我们并没有给 git 服务器配置网页以供浏览(可以用 Gitweb 实现),所以浏览器如果直接键入网址的话会 deny

    那么只好用命令行,输入以下命令:

    openssl s_client -showcerts -connect yoursitedomain:yoursiteport|sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p'

    注意,要将
    yoursitedomain:yoursiteport 转化为你的 git 服务器的网址和端口,回到第一步可以看到,这里的例子为 XXXX.YYYYY.CCCCC:10086

    如果连接没问题,就会看到如下的信息

    -----BEGIN CERTIFICATE-----

    MIIEGTCCAwGgAwIBAgIJAISj2sI7kbd3MA0GCSqGSIb3DQEBCwUAMIGiMQswCQYD

    VQQGEwJDTjEQMA4GA1UECAwHQmVpamluZzEQMA4GA1UEBwwHQmVpamluZzEVMBMG

    A1UECgwMU25pcGVyIFN3b3JkMRUwEwYDVQQLDAxTbmlwZXIgU3dvcmQxHDAaBgNV

    BAMME3NuaXBlcnN3b3JkLnFpY3AuaW8xIzAhBgkqhkiG9w0BCQEWFGNsY3ZhbXBp

    cmVAZ21haWwuY29tMB4XDTE3MDExNTEzMzgzMFoXDTE4MDExNTEzMzgzMFowgaIx

    CzAJBgNVBAYTAkNOMRAwDgYDVQQIDAdCZWlqaW5nMRAwDgYDVQQHDAdCZWlqaW5n

    MRUwEwYDVQQKDAxTbmlwZXIgU3dvcmQxFTATBgNVBAsMDFNuaXBlciBTd29yZDEc

    MBoGA1UEAwwTc25pcGVyc3dvcmQucWljcC5pbzEjMCEGCSqGSIb3DQEJARYUY2xj

    dmFtcGlyZUBnbWFpbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB

    AQDmrlk2Y3k9OJOg3YPOkJf2f1QcvYwsiRcdSemtWAqNGyXVdGlrXPQNpRgDfOPs

    Qmb5V/ELX6Gl+0rSiKS7N+tKlmru8oJgGvADGUTTU9gMDeGR5ztUmqhik57C3E+V

    AL+Oq2TaJqWoseDB1KdF4/4p3PmFDfeGg+vdWEaSihWG/p2lfRPjH+hr9mH/R2Pn

    ZO7Y+TvNevU8pBVmdhh88nHYorIZ0m1/Zk11ADyVuCBVF3ygt4QYv7Lb/N67SiyT

    uqlfifEZR+CEVfaBkaIqhC21YG6NtnQ40LFa2uqr7Hbx2xz30yYrUmlhcHtEop5w

    ZxdsM7iXvt4aYOyOjhljZ4gXAgMBAAGjUDBOMB0GA1UdDgQWBBTbbonTeEU+JIls

    axkFePsbFVqsjzAfBgNVHSMEGDAWgBTbbonTeEU+JIlsaxkFePsbFVqsjzAMBgNV

    HRMEBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQARaDGHn9/9RT0Qk0AcztRMyjrU

    KOcxgad5SAGmG/8BNJR5zEmgeUm+Az31qKBT1m2JNy16cD1+3ulNTKVkZ7j8judt

    EZiUEzsJxgZ4seQ5eQIeORS1IKuadyQevnjMvubzPOmDzOt4DdQNuHcq+Xmv4XP/

    2afrtYseGTWJl66qH2ssQ9ilkg8ju7G/7MGiFpF+pBve3tWyvcltsmgcDEcJotJq

    BY4uqrVAko+28aPhwVyR63CIk52G7WwJcoJ1sCm0SCzbHbTTNJLqRCbuYBWgXCrb

    kyHbS7ACz8onV219sghBQpsyHjVsIg6nFem9pufa1xbwkI1R3wMEfCqZZZM1

    -----END CERTIFICATE-----

    将这个信息复制到一个文件里(注意,--BEGIN CERTIFICATE— 和 –END CERTIFICATE— 也要一并复制),比如
    ~/git_trust_ca.crt,并保存

    然后设置:

    git config --global http.sslCAInfo '/home/xxxxxx/git_trust_ca.crt'

  3. 第1小步已经创建好了 repo,这一步将其 up 到服务器上去:

    git remote add origin https://XXXX.YYYYY.CCCCC:10086/test_repo.git

    git push origin master

    此时出现输入用户名和密码的地方,直接输入即可
    push

至此,git 个人服务器已经全部搭建完毕,实际上接下来还可以给 git 服务器增加 web 界面,便于管理项目等

最新文章

  1. Day8-面向对象进阶&amp;&amp;socket基础
  2. 结对编程——关于Fault、Error、Failure程序设计
  3. Protocol Buffer基本介绍
  4. @错误抑制运算符和or die()
  5. list的三种遍历方法
  6. Android App 性能评测与调优
  7. LinQ 创建连接、简单增删改查
  8. Java :内部类基础详解
  9. Linux SendMail发送邮件失败诊断案例(四)
  10. docker bulid命令
  11. HDU 2516 斐波那契博弈
  12. python使用mysql
  13. bcm53344 gpio驱动分析
  14. zTree第一章,纯静态
  15. 海思平台交叉编译curl支持SSL功能
  16. IIS调试技术之 Debug Diagnostic (调试诊断)
  17. JBoss类加载机制 ClassLoadingConfiguration
  18. 【问题】SUSE已经安装了libsodium,安装zeromq时出现下面的错误?
  19. mysql行列互相转换
  20. 9 Essential Free Linux Transcoders(转码)

热门文章

  1. &gt;&gt; 计算机的数据表示
  2. 替换ubuntu 14.04的源
  3. jsp页面根据当前时间和定义时间差计算动态倒计时
  4. CSS3 六边形绘制
  5. idea新建项目文件名为红色的解决办法
  6. JTree单击事件
  7. SIGPIPE信号
  8. 项目中处理android 6.0权限管理问题
  9. Angular-ui-router + oclazyload + requirejs实现资源随route懒加载
  10. C# 语言规范_版本5.0 (第16章 异常)