ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

从零搭建公网可访问私有Git仓库:SSH密钥认证与服务器部署全指南

从零搭建公网可访问私有Git仓库:SSH密钥认证与服务器部署全指南 1. 项目概述为什么我们需要一个公网可访问的私有Git仓库最近在带团队做一个小型项目代码管理成了个不大不小的麻烦。用GitHub、Gitee这些公有平台吧代码放别人服务器上总有点不放心尤其是涉及一些内部业务逻辑的代码。用公司内网的GitLab服务器吧一旦需要在家办公或者和外部协作者沟通访问就成了大问题。相信不少独立开发者、小团队或者学生党都遇到过类似的困境既想要私有仓库的安全性又希望它能像公有仓库一样随时随地可访问。这个需求其实非常普遍。你可能正在开发一个商业项目原型代码暂时不想公开或者是一个课程设计需要和同学协作又或者像我一样管理着多个个人项目的代码需要一个统一的、私有的、自己完全掌控的托管中心。公有云服务要么有隐私顾虑要么有容量或协作人数限制。而自建一个能在公网访问的私有Git仓库就成了一个极具吸引力的解决方案。它不仅能让你完全掌控数据还能根据团队习惯定制工作流更重要的是它打通了内网与公网的壁垒让分布式协作变得和用GitHub一样方便。听起来好像很复杂涉及到服务器、网络、安全等一系列问题。但别担心这篇教程的目标就是把它拆解成一个个清晰的步骤即使你之前没有太多服务器运维经验只要跟着操作也能一步步搭建起来。整个过程的核心可以概括为在一台具有公网IP的服务器或通过内网穿透技术暴露到公网的本地机器上部署Git服务并配置SSH访问最终实现通过类似gityour-domain.com:project.git这样的地址进行克隆、推送和拉取。2. 核心方案选型与前期准备在动手之前我们需要明确几个关键选择这直接决定了后续的搭建路径和复杂程度。主要分为两大方向拥有公网IP的云服务器和无公网IP的本地机器依赖内网穿透。2.1 服务器环境选择云服务器 vs. 本地穿透方案一使用云服务器推荐给大多数用户这是最直接、最稳定的方案。你需要在阿里云、腾讯云、华为云等厂商购买一台最低配置的云服务器通常1核1G或1核2G就足够新用户首年成本极低。它的优势非常明显拥有独立的公网IP这是实现公网访问的基石无需依赖第三方穿透服务的中转速度更快连接更稳定。控制权完整你可以完全掌控服务器的防火墙、安全组策略定制化程度高。24小时在线云服务器默认持续运行无需担心家里断电或网络波动导致服务中断。对于长期使用或小型团队协作我强烈建议选择此方案。初期投入不大但换来的是省心和高可靠性。本教程也将主要围绕云服务器方案展开。方案二本地机器 内网穿透适合临时或学习用途如果你的代码仓库只是临时用用或者想先零成本体验一下可以使用此方案。它利用内网穿透工具如 frp、ngrok、花生壳等将你本地电脑的某个端口如SSH的22端口或Git服务的端口映射到一个公网地址上。优点零硬件成本利用现有电脑即可。缺点依赖第三方服务大多数免费的穿透服务有带宽、流量、连接数或域名稳定性的限制。稳定性差你的本地电脑必须一直开机并保持网络连接一旦关机或重启服务就中断了。安全性挑战将本地端口直接暴露到公网如果配置不当风险比云服务器更高。性能瓶颈数据传输需要经过穿透服务商的中转服务器速度受其影响。注意对于生产环境或重要项目请务必使用方案一。方案二仅建议用于演示、测试或个人临时同步。2.2 操作系统与基础工具准备无论选择哪种方案我们都需要一个Linux环境。绝大多数云服务器镜像和本地虚拟化都首选Ubuntu Server LTS或CentOS/Rocky Linux。本教程以Ubuntu 22.04 LTS为例因为其软件源较新社区支持好命令也相对通用。在开始之前请确保你拥有服务器的root权限或可通过sudo执行管理员命令。你需要通过SSH工具如系统自带的终端、PuTTY、Xshell、VS Code Remote-SSH插件等连接到你的服务器。首先我们进行系统更新和安装最基础的Git软件包# 更新软件包列表 sudo apt update # 升级已安装的软件包可选但建议执行 sudo apt upgrade -y # 安装 Git 和用于管理用户的工具 sudo apt install git -y安装完成后可以通过git --version验证。3. 搭建Git服务核心配置SSH访问与仓库目录Git本身是一个分布式版本控制系统它可以通过多种协议传输数据其中最常用、最安全高效的就是SSH协议。我们自建私有仓库本质上就是在服务器上创建一个可以通过SSH访问的Git用户并将仓库目录配置为该用户的授权访问区域。3.1 创建专用的Git系统用户为了安全和管理方便我们不建议直接使用root用户来管理Git仓库。创建一个专用的、权限受限的用户是更佳实践。# 创建一个名为‘git’的系统用户并指定其家目录为 /home/git sudo adduser --system --shell /bin/bash --gecos Git Version Control --group --disabled-password --home /home/git git命令参数解释--system: 创建系统用户无登录密码。--shell /bin/bash: 为其指定bash shell方便后续操作。--home /home/git: 指定家目录。--disabled-password: 禁用密码登录强制使用更安全的SSH密钥认证。3.2 配置SSH密钥认证免密登录的核心SSH密钥认证是安全访问的黄金标准。它使用一对加密密钥公钥和私钥来代替传统的密码。公钥放在服务器上私钥留在你的本地电脑。连接时服务器用公钥挑战本地用私钥应答验证通过即可登录。第一步在本地生成SSH密钥对如果你还没有的话在你的本地电脑Windows/Mac/Linux上打开终端或Git Bash执行ssh-keygen -t ed25519 -C your_emailexample.com-t ed25519: 指定使用Ed25519算法它比传统的RSA更安全、更快、密钥更短。如果你的旧系统不支持可以用-t rsa -b 4096替代。-C: 添加注释通常用你的邮箱便于识别密钥所有者。 执行命令后会询问你密钥保存路径直接回车使用默认路径~/.ssh/id_ed25519和设置密钥密码可选为私钥再加一层保护直接回车则不留密码。完成后你会在~/.ssh/目录下得到两个文件id_ed25519:私钥文件绝对不要分享给任何人相当于你的家门钥匙。id_ed25519.pub:公钥文件需要上传到服务器。相当于一把能开你家门锁的“锁芯”交给服务器保管。第二步将本地公钥上传到服务器我们需要将本地的公钥内容添加到服务器上git用户的授权密钥列表中。查看并复制你的公钥内容cat ~/.ssh/id_ed25519.pub全选复制输出的那一长串以ssh-ed25519 AAA...开头注释结尾的文本。在服务器上切换到git用户并创建SSH授权目录和文件# 切换到git用户 sudo su - git # 创建.ssh目录并设置严格权限700表示只有所有者可读、写、执行 mkdir -p ~/.ssh chmod 700 ~/.ssh # 创建authorized_keys文件并设置权限600表示只有所有者可读、写 touch ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys # 编辑该文件将你复制的公钥粘贴进去 nano ~/.ssh/authorized_keys在nano编辑器中粘贴你的公钥然后按CtrlX再按Y最后回车保存退出。第三步测试SSH密钥登录在本地终端尝试用git用户SSH连接到你的服务器将your-server-ip替换为你的服务器公网IP或域名ssh gityour-server-ip如果配置正确你应该不需要输入密码就能直接登录或只输入你之前为私钥设置的密码并看到类似githostname:~$的提示符。输入exit退出。实操心得权限 (chmod 700和600) 是SSH密钥认证能否成功的关键。权限过松如755SSH出于安全考虑会直接拒绝连接并可能在服务器的/var/log/auth.log中看到Authentication refused: bad ownership or modes的错误。这一步务必检查仔细。3.3 初始化第一个裸仓库Bare RepositoryGit仓库分为两种工作仓库Working Repository和裸仓库Bare Repository。工作仓库包含工作区你看到的项目文件和.git目录。而裸仓库没有工作区只有.git目录里的内容专门用于作为中央仓库进行推送和拉取。我们的服务器上应该存放裸仓库。在服务器上我们以git用户身份操作# 确保在git用户的家目录或你规划的目录下 cd /home/git # 创建一个用于存放所有仓库的目录例如叫‘repositories’ mkdir repositories cd repositories # 初始化一个裸仓库名字叫‘my-project.git’ git init --bare my-project.git--bare参数是关键。初始化后你会看到my-project.git目录下直接就是branches、hooks、objects等Git内部目录而没有项目源文件。这个目录就是你的远程仓库地址。4. 从本地连接与使用自建仓库服务端配置好后现在你可以在任何能通过SSH访问到这台服务器的机器上像使用GitHub一样使用这个私有仓库了。4.1 本地克隆远程仓库假设你的服务器IP是123.123.123.123仓库路径是/home/git/repositories/my-project.git。那么远程仓库的地址就是git123.123.123.123:/home/git/repositories/my-project.git通常我们会为git用户设置一个简化的访问路径。这可以通过修改服务器上git用户的shell来实现但更简单通用的方法是直接使用上述绝对路径。在你的本地电脑上找一个合适的目录执行克隆命令git clone git123.123.123.123:/home/git/repositories/my-project.git因为我们已经配置了SSH密钥这里不会要求输入密码。克隆完成后你会得到一个空的my-project目录因为仓库是刚初始化的。4.2 进行常规Git操作进入克隆下来的本地仓库目录进行常规开发cd my-project echo # My Private Project README.md git add README.md git commit -m Initial commit git push origin main如果你的本地默认分支是master则将最后一句改为git push origin master。push命令会将本地的提交推送到你的自建远程仓库。4.3 为仓库添加更多协作者团队协作时你需要将其他成员的公钥也添加到服务器git用户的~/.ssh/authorized_keys文件中。每个成员一行一个公钥占一行。重要安全与管理建议对于稍大的团队将所有成员的公钥都放在同一个authorized_keys文件里会难以管理。更专业的做法是使用Gitolite或Gitolite3。它是一个用Perl写的Git仓库管理工具能基于公钥实现精细到分支的读写权限控制。你可以指定用户A只能读develop分支用户B可以读写main和develop分支等。对于超过3人的团队我强烈建议在完成基础搭建后研究部署Gitolite它能极大提升管理效率和安全性。5. 安全加固与高级配置将服务器暴露在公网上安全是头等大事。以下是一些必须做的基础加固措施。5.1 修改SSH服务端口默认的SSH端口22是黑客扫描的重灾区。修改为一个非标准的高位端口如2222能过滤掉绝大部分自动化攻击脚本。 在服务器上编辑SSH配置文件sudo nano /etc/ssh/sshd_config找到#Port 22这一行去掉注释#并将22改为你想要的端口例如Port 2222务必注意修改前请确保你有其他方式能访问服务器如云控制台的VNC并且修改后不要立即重启SSH服务先测试新端口是否可用。5.2 测试新端口并禁用密码登录在本地新开一个终端窗口测试新端口连接ssh -p 2222 gityour-server-ip确认能够成功登录。禁用SSH密码认证强制使用密钥 再次编辑/etc/ssh/sshd_config确保以下配置PasswordAuthentication no PubkeyAuthentication yes PermitRootLogin no # 禁止root用户直接SSH登录增加安全性重启SSH服务使配置生效sudo systemctl restart sshd重启后立即用已经测试成功的新端口终端窗口再次连接确保一切正常。现在任何尝试用密码登录的行为都会被拒绝只有拥有有效私钥的用户才能连接。5.3 配置服务器防火墙使用ufw(Uncomplicated Firewall) 可以轻松管理防火墙规则。# 安装ufw如果未安装 sudo apt install ufw -y # 设置默认策略拒绝所有入站允许所有出站 sudo ufw default deny incoming sudo ufw default allow outgoing # 允许新的SSH端口 sudo ufw allow 2222/tcp # 如果你后续需要通过HTTP/HTTPS访问GitWeb之类的界面可以开放80/443端口 # sudo ufw allow 80/tcp # sudo ufw allow 443/tcp # 启用防火墙 sudo ufw enable # 查看规则状态 sudo ufw status verbose现在只有端口2222是对外开放的其他所有端口都被屏蔽大大减少了攻击面。5.4 为仓库配置域名可选但推荐总是用IP地址访问不够优雅也不利于记忆。你可以购买一个域名并为其添加一条A记录指向你的服务器IP。例如将git.yourdomain.com解析到123.123.123.123。之后你的仓库克隆地址就可以变得更专业git clone gitgit.yourdomain.com:/home/git/repositories/my-project.git你还可以在本地SSH配置文件~/.ssh/config中为这个连接创建别名进一步简化Host mygit HostName git.yourdomain.com Port 2222 User git IdentityFile ~/.ssh/id_ed25519配置后克隆命令简化为git clone mygit:/home/git/repositories/my-project.git6. 常见问题排查与维护技巧即使按照步骤操作也可能会遇到一些问题。这里记录一些我踩过的坑和解决方案。6.1 SSH连接失败问题排查表问题现象可能原因排查命令/步骤Connection refused1. SSH服务未运行2. 防火墙阻止3. 端口错误1.sudo systemctl status sshd2.sudo ufw status3. 确认连接命令中的IP和端口Permission denied (publickey)1. 公钥未正确上传2.authorized_keys文件权限错误3. 私钥未加载或路径不对1. 检查服务器~/.ssh/authorized_keys内容2. 确认权限为600.ssh目录为7003. 本地执行ssh-add -l查看加载的密钥或用-i指定私钥路径连接超时1. 服务器IP错误2. 安全组/网络ACL未放行端口云服务器1. 核对服务器公网IP2. 登录云控制台检查安全组规则是否允许你的IP访问指定端口克隆时提示not a git repository远程路径错误或仓库不是裸仓库1. 确认服务器上仓库路径是否正确2. 确认是用git init --bare创建的一个关键的调试技巧在本地连接时添加-v参数如ssh -v -p 2222 gityour-server-ip会输出详细的连接过程日志能精准定位到在哪一步失败了。6.2 Git操作相关问题推送时提示[remote rejected] (branch is currently checked out) 这是因为你推送到了服务器上一个非裸仓库即有工作区的仓库。服务器上的仓库必须是--bare的。解决方法是备份服务器上该仓库的文件删除原目录重新用git init --bare初始化或者将本地仓库推送到一个新的裸仓库地址。如何备份服务器上的所有仓库最简单的方式是定期打包整个/home/git/repositories/目录并传输到其他存储位置。sudo tar -czf /backup/git-repos-$(date %Y%m%d).tar.gz -C /home/git repositories/也可以使用git bundle命令对单个仓库进行增量备份。仓库越来越大如何清理长期项目会产生很多松散对象和过期引用。可以在服务器仓库目录下执行git gc --aggressive --prunenow来进行垃圾回收和压缩。对于本地克隆的仓库定期执行git gc也有好处。6.3 性能与监控建议对于小规模使用上述配置性能完全足够。如果仓库数量增多或团队变大可以考虑启用Git的打包功能在服务器仓库的hooks/post-update文件中加入git gc命令让每次推送后自动优化仓库。监控磁盘空间确保/home分区有足够空间可以用df -h查看。查看连接日志关注/var/log/auth.log可以及时发现异常登录尝试。7. 内网穿透方案补充说明如果你因为条件所限只能采用本地机器内网穿透的方案其核心步骤与上述云服务器方案在“创建Git用户”、“配置SSH密钥”、“初始化仓库”部分是完全一致的。区别仅在于网络层选择穿透工具以frp为例你需要在公网有一台具有固定IP的服务器可以是另一台云服务器也可以是朋友提供的作为frp 服务端在你的本地机器上运行frp 客户端。配置端口映射在 frp 客户端配置文件中将本地22端口或你为Git服务指定的其他端口映射到服务端的某个高位端口如6000。连接地址变化此时你的远程仓库地址将变为gitfrp-server-ip:6000:/path/to/repo.git。你需要通过-p参数指定映射后的端口。踩坑提醒使用内网穿透时务必在本地防火墙和路由器中做好端口转发设置。同时由于SSH连接经过中转首次克隆或推送大型仓库时可能会比较慢且稳定性高度依赖于穿透服务商的质量。因此再次强调此方案仅作临时用途。走到这里你已经拥有了一个完全受自己控制、通过公网可访问的私有Git仓库。它可能没有GitLab、Gitea那些Web界面和项目管理功能但它核心的版本控制、分布式协作能力是完整且高效的。对于个人或小团队来说这种极简的SSHGit方案往往是最轻量、最直接的选择。后续如果你需要Issue跟踪、Pull Request、Web代码浏览等功能可以考虑在同样的服务器上部署Gitea或GitLab CE它们提供了更完善的开源解决方案但部署和维护的复杂度也会相应增加。无论如何今天搭建的这个基础服务已经为你打开了自建代码托管的大门。
返回列表