惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
V
V2EX
博客园 - 【当耐特】
WordPress大学
WordPress大学
爱范儿
爱范儿
美团技术团队
宝玉的分享
宝玉的分享
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
小众软件
小众软件
量子位
Hugging Face - Blog
Hugging Face - Blog
B
Blog RSS Feed
Recorded Future
Recorded Future
Engineering at Meta
Engineering at Meta
雷峰网
雷峰网
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
M
MIT News - Artificial intelligence
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 聂微东
H
Hackread – Cybersecurity News, Data Breaches, AI and More
腾讯CDC
大猫的无限游戏
大猫的无限游戏
Jina AI
Jina AI
博客园 - 叶小钗
GbyAI
GbyAI
Y
Y Combinator Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
F
Full Disclosure
G
Google Developers Blog
D
Docker
T
Tailwind CSS Blog
C
Check Point Blog
Last Week in AI
Last Week in AI
人人都是产品经理
人人都是产品经理
T
The Blog of Author Tim Ferriss
B
Blog
博客园 - 三生石上(FineUI控件)
博客园 - Franky
H
Help Net Security
MyScale Blog
MyScale Blog
U
Unit 42
D
DataBreaches.Net
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
I
InfoQ
阮一峰的网络日志
阮一峰的网络日志
The GitHub Blog
The GitHub Blog
L
LangChain Blog
有赞技术团队
有赞技术团队
Martin Fowler
Martin Fowler
Microsoft Security Blog
Microsoft Security Blog

程序员笔记(huoyijie.cn)

generate new dataset with llm and knowledge graph resume deepseek applications Implement the classic huarongdao game with react Implement the classic tetris game with react Writing admin dashboard template with Nextjs How to AuthN user with OpenLDAP share whiteboard with websocket ocr overview tech notes subscribe topic with sse multi devices github an algorithm used for image text detect an algorithm used for image text detect facial expression recognition technology based on neural network oauth2 mysql store a real time collaborative whiteboard with infinite space How to perform load testing with Grafana k6 fix split of undefined with gitbook theme nodejs http proxy middleware analyze referer of express website writing a CDN origin server with Django a personal lightweight CMS tool writing in Golang profile introduce the post processing introduce the text detect method blockchain for dummies medical applications on ai facial expression recognition study facial expression recognition auth auth with oauth2 auth with jwt chat with sse react chat with websocket react http message signatures infinite whiteboard with socket.io multi factor auth with totp subscribe topic with sse capture screen to gif Golang 经典入门实践教程 · GitBook EFS 加密文件系统 · GitBook 弈杰围棋智能终端 · GitBook 如何把手机触摸屏变成触控板(Touchpad) · GitBook 基于 SOCKET.IO 搭建个人电脑 HTTP 静态服务器代理 · GitBook 三百行代码搭建一个简单的 SOCKS5 代理服务器 · GitBook 微信小程序(蓝牙BLE)远程遥控树莓派小车 · GitBook 语音远程遥控树莓派小车 · GitBook 树莓派的一些使用经验 · GitBook 从零开始制作树莓派小车 · GitBook UDPack 2.0 协议 · GitBook 前言 · GitBook 升级 Ubuntu 到 20.04 LTS 长期维护版本 · GitBook 反向代理服务器实现原理 · GitBook 网站支持 HTTP 2.0 · GitBook 搭建配置邮件服务器 · GitBook 使用 Git 与 Gitbook 创建管理电子书 · GitBook 网站图片视频接入CDN · GitBook a personal lightweight self hosted git server written in Golang 快速搭建CDN回源服务器 · GitBook
基于 Git 搭建代码托管服务器 · GitBook
huoyijie · 2024-05-24 · via 程序员笔记(huoyijie.cn)

我个人的项目代码主要托管在 Github,最近发现无论是 clone 代码还是 push 代码,速度都很慢。如果在我的个人服务器上搭建一个 git server,不但可以托管我个人的私有项目,也可以为我个人的公开项目提供镜像,以提升 git 操作体验。git server 的部署非常简单,主要是在服务器上安装 git 及配置 SSH Keys。我尽可能还原了所有操作细节,可能会显得有点长。

首先登录服务器,安装 git

$ sudo apt-get install git

添加 git 组和 git 用户

$ sudo groupadd git
$ sudo useradd -m -d /home/git -g git git

新建 authorized_keys 文件

$ cd /home/git
$ sudo mkdir .ssh && cd .ssh
$ sudo touch authorized_keys

新建的几个目录或文件的权限非常关键,为避免后面遇到权限错误或安全问题,需确保只有 git 用户有读写权限

$ ls -ld /home/git
drwxr-xr-x 7 git git 4096 Mar 22 14:28 /home/git

$ sudo ls -ld /home/git/.ssh
drwx------ 2 git git 4096 Mar 22 15:32 /home/git/.ssh

$ sudo ls -l /home/git/.ssh
total 4
-rw------- 1 git git 747 Mar 22 15:32 authorized_keys

例如,我在尝试把 /home/git 权限从 755 调整为 775,克隆远程仓库时,git 用户会遇到下面的错误(其他配置正常)

$ git clone git@huoyijie.cn:newproject.git
正克隆到 'newproject'...
Permission denied (publickey).
fatal: 无法读取远程仓库。

请确认您有正确的访问权限并且仓库存在。

下面命令会在控制台输出我的电脑(不是服务器)公钥信息,可进行复制

$ cat ~/.ssh/id_rsa.pub

如果本地没有这个文件,可先创建新的公钥、私钥。

$ ssh-keygen -o
Generating public/private rsa key pair.
Enter file in which to save the key (/home/huoyijie/.ssh/id_rsa):
Created directory '/home/huoyijie/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/huoyijie/.ssh/id_rsa.
Your public key has been saved in /home/huoyijie/.ssh/id_rsa.pub.
The key fingerprint is:
d0:82:24:8e:d7:f1:bb:9b:33:53:96:93:49:da:9b:e3 huoyijie@mylaptop

首先 ssh-keygen 会确认密钥的存储位置(默认是 .ssh/id_rsa),然后它会要求你输入两次密钥口令。如果你不想在使用密钥时输入口令,将其留空即可。 然而,如果你使用了密码,那么请确保添加了 -o 选项,它会以比默认格式更能抗暴力破解的格式保存私钥。

现在来添加 SSH Keys,编辑服务器上 authorized_keys 文件

$ sudo vi authorized_keys

把自己电脑的公钥信息复制过来,写入该文件,每个公钥占一行,保存退出。现在从自己的电脑可以免密码登录服务器了。

需要注意的是,目前所有(获得授权的)开发者用户都能以系统用户 git 的身份登录服务器从而获得一个普通shell。如果你想对此加以限制,则需要修改 /etc/passwd 文件中(git 用户所对应)的 shell 值。借助一个名为 git-shell 的受限 shell 工具,你可以方便地将用户 git 的活动限制在与 Git 相关的范围内。

该工具随 Git 软件包一同提供。如果将 git-shell 设置为用户 git 的登录 shell(login shell),那么该用户便不能获得此服务器的普通 shell 访问权限。若要使用git-shell,需要用它替换掉 bash 或 csh,使其成为该用户的登录 shell。

为进行上述操作,首先你必须确保 git-shell 的完整路径名已存在于 /etc/shells 文件中:

$ cat /etc/shells # 查看 /etc/shells 中 git-shell 是否已存在,如果不存在运行下条命令
$ which git-shell # 区别系统已安装 git-shell 工具,复制该命令路径
$ sudo -e /etc/shells # 把 git-shell 命令路径加入 /etc/shells 文件最后面

现在你可以使用 chsh <username> -s <shell> 命令修改任一系统用户的 shell

$ sudo chsh git -s $(which git-shell)

这样,用户 git 就只能利用 SSH 连接对 Git 仓库进行推送和拉取操作,而不能登录机器并取得普通 shell。如果试图登录,会被拒绝:

$ ssh git@huoyijie.cn
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.
Connection to huoyijie.cn closed.

此时,用户仍可通过 SSH 端口转发来访问任何可达的 git 服务器。 如果你想要避免它,可编辑 authorized_keys 文件并在所有想要限制的公钥之前添加以下选项:

no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty

类似这样:

$ cat ~/.ssh/authorized_keys
no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa
AAAAB3NzaC1yc2EAAAADAQABAAABAQCB007n/ww+ouN4gSLKssMxXnBOvf9LGt4LojG6rs6h
PB09j9R/T17/x4lhJA0F3FR1rP6kYBRsWj2aThGw6HXLm9/5zytK6Ztg3RPKK+4kYjh6541N
YsnEAZuXz0jTTyAUfrtU3Z5E003C4oxOj6H0rfIF1kKI9MAQLMdpGW1GYEIgS9EzSdfd8AcC
IicTDWbqLAcU4UpkaX8KyGlLwsNuuGztobF8m72ALC/nLF6JLtPofwFBlgc+myivO7TCUSBd
LQlgMVOFq1I2uPWQOkOWQAHukEOmfjy2jctxSDBQ220ymjaNsHT4kgtZg2AYYgPqdAv8JggJ
ICUvax2T9va5 gsg-keypair

现在,网络相关的 Git 命令依然能够正常工作,但是开发者用户已经无法得到一个普通 shell 了。

那么应该如何将已有的仓库(如存储于 Github)导入自己的 git 服务器呢?我电脑上有一个放在 Github 的项目 revealjs

$ cd ~/vswork/revealjs
$ git clone --bare revealjs revealjs.git
克隆到纯仓库 'revealjs.git'...
完成。

首先进入项目目录,并执行 clone --bare 操作,生成了 revealjs 仓库的一个裸仓,也就是目录 revealjs.git,按照惯例,裸仓库的目录以 .git 结尾。--bare 是限定克隆出裸仓。裸仓 只包含 .git 目录,克隆裸仓的命令效果类似于:

$ cp -rf revealjs/.git revealjs.git

然后把裸仓放入到服务器上,因为 git 用户本身已限制了 ssh 登录后的权限,只能进行 git 相关操作。所以需要另一个有权限登录 shell 的用户 abc 把 revealjs.git 上传到 /home/git 目录下

$ scp -r revealjs.git abc@huoyijie.cn:/home/abc

用 abc 用户登入远程服务器,把仓库移动到 git 用户可以读写的目录(/home/git)下,并更改刚刚上传的裸仓目录归属及权限

sudo mv /home/abc/revealjs.git /home/git/revealjs.git
sudo chown -R git:git /home/git/revealjs.git
sudo chmod 755 /home/git/revealjs.git

然后可以从远程服务器 clone 这个仓库了,就像从 Github 上面克隆一样的。

$ git clone git@huoyijie.cn:revealjs.git
正克隆到 'revealjs'...
remote: Counting objects: 165, done.
remote: Compressing objects: 100% (159/159), done.
remote: Total 165 (delta 61), reused 0 (delta 0)
接收对象中: 100% (165/165), 1.68 MiB | 127.00 KiB/s, 完成.
处理 delta 中: 100% (61/61), 完成.

如果一个用户(如 git 用户),可 SSH 连接到一个服务器,并且有 /home/git/revealjs.git 目录的写权限,那么该用户将自动拥有推送权限。

那么应该如何创建一个完全新的仓库呢?

首先通过 abc 用户登录服务器,取得 shell,并创建新的裸仓

$ cd /home/git
$ sudo mkdir newproject.git && cd newproject.git
$ sudo git init --bare
Initialized empty Git repository in /home/git/newproject.git/

修改裸仓用户归属

sudo chown -R git:git /home/git/newproject.git

然后客户端就可以远程操作这个仓库了,先配置一下客户端 git 用户身份 (非服务器用户身份),填好 user.name & user.email

git config --global -e

此时可以克隆仓库了,不过现在还是一个空仓库

$ git clone git@huoyijie.cn:newproject.git
正克隆到 'newproject'...
warning: 您似乎克隆了一个空仓库。

注: 克隆代码库时,可以使用相对 /home/git 的相对路径 git clone git@huoyijie.cn:newproject.git,也可以使用绝对路径 git clone git@huoyijie.cn:/home/git/newproject.git

如果本地已有项目,也可以直接让本地目录关联到远程仓库

$ tree -L 2 project
project
└── readme.md

如上,我本地有个目录 project,现在把这个目录绑定到远程仓库 newproject 上面。

$ cd project
$ git init
$ git add .
$ git commit -m 'initial commit'
$ git remote add origin git@huoyijie.cn:/home/git/newproject.git
$ git push origin master
对象计数中: 3, 完成.
写入对象中: 100% (3/3), 214 bytes | 214.00 KiB/s, 完成.
Total 3 (delta 0), reused 0 (delta 0)
To huoyijie.cn:/home/git/newproject.git
 * [new branch]      master -> master

现在新加的 readme.md 文件已经 push 到远程了。

OK,到现在为止,基本可以满足我的代码托管需求了,比较适合几个人以内的小团队管理代码,当然如果有很多权限等方面的定制需求,可以考虑更复杂一些的开源方案,如 Gitlab。

本文参考了 Pro Git book 这本书,可以在 https://git-scm.com 网站上查看或下载。下载这本书