如何在Ubuntu16.04上使用GitHooks部署Jekyll站点
作为 Write for DOnations 计划的一部分,作者选择了 Diversity in Tech Fund 来接受捐赠。
介绍
Jekyll 是一个静态站点生成器,它提供了内容管理系统 (CMS) 的一些好处,同时避免了此类数据库驱动站点引入的性能和安全问题。 它是“博客感知”的,包括处理按日期组织的内容的特殊功能,尽管它的用处不限于博客网站。 Jekyll 非常适合需要离线工作、更喜欢轻量级编辑器而不是 Web 表单进行内容维护、并希望使用版本控制来跟踪其网站更改的人。
在本教程中,我们将配置生产环境以使用 Nginx 来托管 Jekyll 站点,以及在将更改推送到站点存储库时使用 Git 来跟踪更改并重新生成站点。 我们还将安装和配置 git-shell
以额外保护您的生产服务器免受未经授权的访问。 最后,我们将配置您的本地开发机器以使用并将更改推送到远程存储库。
先决条件
要遵循本教程,您将需要:
- 一台用于生产的 Ubuntu 16.04 服务器,按照 Initial Server Setup with Ubuntu 16.04 教程 进行配置,包括:
- Nginx,按照【X57X】如何在Ubuntu 16.04上安装Nginx教程【X106X】的前两步安装。
- Jekyll,按照 How to Set Up a Jekyll Development Site on Ubuntu 16.04 进行安装。
- 一台开发机器,安装了 Git 和按照 How to Set Up a Jekyll Development Site on Ubuntu 16.04 教程创建的 Jekyll 站点。
- 或者,如果您想了解更多有关 Jekyll 的信息,可以查看以下两个教程:
- 探索 Jekyll 的默认内容。
- 在 Jekyll 中控制 URL 和链接。
第 1 步 — 设置 Git 用户帐户
出于安全目的,我们将首先创建一个用户帐户,该帐户将托管 Jekyll 站点的 Git 存储库。 该用户将执行 Git hooks 脚本,我们将创建该脚本以在收到更改时重新生成站点。 以下命令将创建一个名为 git 的用户:
sudo adduser git
您将被要求输入并重复密码,然后输入有关用户的非强制性基本信息。 最后,系统会要求您通过输入 Y 来确认信息:
OutputAdding user `git' ... Adding new group `git' (1001) ... Adding new user `git' (1001) with group `git' ... Creating home directory `/home/git' ... Copying files from `/etc/skel' ... Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully Changing the user information for git Enter the new value, or press ENTER for the default Full Name []: Room Number []: Work Phone []: Home Phone []: Other []: Is the information correct? [Y/n]
我们还将准备 Web 根目录来保存生成的站点。 首先,从/var/www/html
目录中删除默认网页:
sudo rm /var/www/html/index.nginx-debian.html
现在,将目录的所有权设置为 git 用户,这样该用户可以在收到更改时更新站点的内容,并将组所有权设置为 www-data
组。 该组确保 Web 服务器可以访问和管理位于 /var/www/html
中的文件:
sudo chown git:www-data /var/www/html
在继续本教程之前,将您的 SSH 密钥复制到新创建的 git 用户,这样您就可以使用 Git 安全地访问您的生产服务器。 您可以按照使用 Ubuntu 16.04 的初始服务器设置教程 的 步骤四来完成此操作。 最简单的方法是使用 ssh-copy-id
命令,但您也可以手动复制密钥。
现在让我们为您的 Jekyll 站点创建一个 Git 存储库,然后配置 Git 挂钩以在更新时重建它。
第 2 步 — 设置 Git 存储库
您的 Git 存储库将包含有关您的 Git 站点的数据,包括更改和提交的历史记录。 在这一步中,我们将在生产服务器上设置 Git 存储库,并使用将重新生成您的站点的 post-receive 挂钩。
存储库将位于 git 用户的主目录中,因此如果您在上一步后已注销此用户帐户,请使用 su
命令切换角色:
su - git
在主目录中,创建一个包含 Git 存储库的文件夹。 目录必须在主目录中,并且使用 repo-name.git
格式命名,以便 git
命令可以发现它。 通常,repo-name
应该是您站点的名称,因此 git
可以轻松识别站点和存储库。 我们将调用我们的站点 sammy-blog
:
mkdir ~/sammy-blog.git
切换到目录并使用 git init
命令初始化 Git 存储库。 --bare
标志设置存储库以在服务器上托管并启用多个用户之间的协作:
cd ~/sammy-blog.git git init --bare
输出包含有关成功初始化的存储库的信息:
OutputInitialized empty Git repository in /home/git/sammy-blog.git
如果您没有看到此类输出,请按照屏幕上的日志解决问题,然后再继续本教程。
我们创建的文件夹包含托管存储库所需的目录和文件。 您可以通过键入以下内容来检查其内容:
ls
Outputbranches config description HEAD hooks info objects refs
如果您没有看到此类输出,请确保您切换到相应的目录并成功执行了 git init
。
hooks 目录包含用于 Git 挂钩的脚本。 默认情况下,它包含每种类型的 Git 钩子的示例文件,因此您可以轻松开始。 出于本教程的目的,一旦使用最新更改更新存储库,我们将使用 post-receive 挂钩重新生成站点。
在 hooks
目录中创建名为 post-receive
的文件,并在您选择的文本编辑器中打开它:
nano ~/sammy-blog.git/hooks/post-receive
我们将配置钩子以克隆临时目录的最新更改,然后重新生成它并将生成的站点保存到 /var/www/html
以便您可以轻松访问它。
将以下内容复制到文件中:
~/sammy-blog.git/hooks/post-receive
#!/usr/bin/env bash GIT_REPO=$HOME/sammy-blog.git TMP_GIT_CLONE=/tmp/sammy-blog PUBLIC_WWW=/var/www/html git clone $GIT_REPO $TMP_GIT_CLONE pushd $TMP_GIT_CLONE bundle exec jekyll build -d $PUBLIC_WWW popd rm -rf $TMP_GIT_CLONE exit
完成后,保存文件并关闭文本编辑器。
确保脚本是可执行的,因此 git 用户可以在收到更改时执行它:
chmod +x ~/sammy-blog.git/hooks/post-receive
此时,我们有一个完全配置的 Git 存储库和一个 Git post-receive 挂钩,可以在收到更改时更新您的站点。 在将站点推送到存储库之前,我们将另外通过配置 git-shell
来保护我们的生产服务器,这是一个交互式 shell,可以在用户通过 SSH 连接时为他们提供各种 Git 命令。
第 3 步 — 配置 Git Shell 以禁用交互式登录
用户可以通过以下方式实现 git-shell
:作为交互式 shell,当他们通过 SSH 连接时为他们提供各种命令,使他们能够创建新的存储库或添加新的 SSH 密钥,或者作为非交互式 shell,禁止通过 SSH 访问服务器控制台,但允许他们使用 git
命令来管理现有存储库。
如果您与任何人共享 git 用户的 SSH 密钥,他们将可以通过 SSH 访问交互式 Bash 会话。 这代表了安全威胁,因为用户可以访问其他与站点无关的数据。 我们将 git-shell
配置为非交互式 shell,因此您无法使用 git 用户启动交互式 Bash 会话。
确保您以 git 用户身份登录。 如果您在上一步之后退出了会话,您可以使用与之前相同的命令再次登录:
su - git
首先创建一个 git-shell-commands
目录,需要 git-shell
工作:
mkdir ~/git-shell-commands
如果您不想允许交互式 shell 访问,则 no-interactive-shell
文件用于定义行为,因此请在您选择的文本编辑器中打开它:
nano ~/git-shell-commands/no-interactive-login
将以下内容复制到文件中。 如果您尝试通过 SSH 登录,它将确保显示欢迎消息:
~/git-shell-commnads/no-interactive-login
#!/usr/bin/env bash printf '%s\n' "You've successfully authenticated to the server as $USER user, but interactive sessions are disabled." exit 128
完成后,保存文件并关闭文本编辑器。
我们需要确保文件是可执行的,所以 git-shell
可以执行它:
chmod +x ~/git-shell-commands/no-interactive-login
返回到你的非 root sudo 用户,这样你就可以修改我们的 git 用户的属性。 如果您使用之前的 su
命令,您可以使用以下命令关闭会话:
exit
最后,我们需要将 git 用户的 shell 更改为 git-shell
:
sudo usermod -s $(which git-shell) git
通过在开发机器上运行 SSH 来验证您是否无法访问交互式 shell:
ssh git@production_server_ip
您应该会看到如下所示的消息。 如果不这样做,请确保您有适当的 SSH 密钥,并在继续本教程之前回溯前面的步骤以解决问题。
OutputWelcome to Ubuntu 16.04.3 LTS (GNU/Linux 4.4.0-109-generic x86_64) ... You've successfully authenticated to the server as git user, but interactive sessions are disabled. Connection to production_server_ip closed.
接下来,您将配置本地开发机器以使用此 Git 存储库,然后我们会将您的站点推送到存储库。 最后,我们将确保您的网站已生成并且您可以从 Web 浏览器访问它。
第 4 步 — 将更改推送到存储库
我们现在已经在生产服务器上初始化并配置了一个 Git 存储库。 在开发机器上,我们需要初始化一个本地存储库,其中包含有关远程存储库的数据以及在本地存储库中所做的更改。
在您的开发机器上,导航到包含该站点的目录:
cd ~/www
我们需要在站点的根目录中初始化一个 Git 存储库,以便我们可以将内容推送到远程存储库:
git init
输出包含有关成功的存储库初始化的消息:
OutputInitialized empty Git repository in /home/sammy/www
如果您没有看到此类输出,请按照屏幕上的消息解决问题,然后再继续。
现在,创建一个远程对象,它代表用于跟踪您正在处理的远程存储库和分支的 Git 对象。 通常,默认遥控器称为 origin,因此我们将在本教程中使用它。
以下命令将创建一个 origin 远程,它将使用 git 用户在生产服务器上跟踪 sammy-blog 存储库:
git remote add origin git@production_server_ip:sammy-blog.git
无输出表示操作成功。 如果您看到错误消息,请确保在继续下一步之前解决它。
每次您想要将更改推送到远程存储库时,您都需要提交它们,然后将提交推送到远程存储库。 一旦远程存储库收到提交,您的站点将使用最新的更改重新生成。
提交用于跟踪您所做的更改。 它们包含一个提交消息,用于描述在该提交中所做的更改。 建议保持消息简短但简洁,包括有关提交中所做的最重要更改的详细信息。
在提交更改之前,我们需要选择要提交的文件。 以下命令标记所有要提交的文件:
git add .
无输出表示命令执行成功。 如果您看到任何错误,请确保在继续之前解决它们。
接下来,使用 -m
标志提交所有更改,其中将包含提交消息。 由于这是我们的第一次提交,我们将其称为 “初始提交”:
git commit -m "Initial commit."
输出包含在该提交中更改的目录和文件的列表:
Commit output 10 files changed, 212 insertions(+) create mode 100644 .gitignore create mode 100644 404.html create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 _config.yml create mode 100644 _posts/2017-09-04-link-test.md create mode 100644 about.md create mode 100644 assets/postcard.jpg create mode 100644 contact.md create mode 100644 index.md
如果您看到任何错误,请确保在继续本教程之前解决它们。
最后,使用以下命令将提交的更改推送到远程存储库:
git push origin master
输出将包含有关推送进度的信息。 完成后,您将看到如下信息:
Push outputCounting objects: 14, done. Delta compression using up to 4 threads. Compressing objects: 100% (12/12), done. Writing objects: 100% (14/14), 110.80 KiB | 0 bytes/s, done. Total 14 (delta 0), reused 0 (delta 0) remote: Cloning into '/tmp/sammy-blog'... remote: done. remote: /tmp/sammy-blog ~/sammy-blog.git remote: Configuration file: /tmp/sammy-blog/_config.yml remote: Source: /tmp/sammy-blog remote: Destination: /var/www/html remote: Incremental build: disabled. Enable with --incremental remote: Generating... remote: done in 0.403 seconds. remote: Auto-regeneration: disabled. Use --watch to enable. remote: ~/sammy-blog.git To git@188.166.57.145:sammy-blog.git * [new branch] master -> master
如果不这样做,请按照屏幕上的日志解决问题,然后再继续本教程。
此时,您的网站已上传到服务器,并在短时间内重新生成。 将您的网络浏览器导航到 http://production_server_ip
。 您应该看到您的网站启动并运行。 如果您不这样做,请回溯前面的步骤以确保您按预期完成了所有操作。
为了在您更改某些内容时重新生成您的站点,您需要将文件添加到提交中,提交它们,然后推送更改,就像您对初始提交所做的那样。
对文件进行更改后,使用以下命令将所有更改的文件添加到提交中。 如果您创建了新文件,您还需要使用 git add
添加它们,就像我们在初始提交中所做的那样。 当您准备好提交文件时,您将需要包含另一条描述您的更改的提交消息。 我们将我们的消息 称为“更新文件”:
git commit -am "updated files"
最后,将更改推送到远程存储库。
git push origin master
输出将与您在初始推送中看到的类似:
Push outputCounting objects: 14, done. Delta compression using up to 4 threads. Compressing objects: 100% (12/12), done. Writing objects: 100% (14/14), 110.80 KiB | 0 bytes/s, done. Total 14 (delta 0), reused 0 (delta 0) remote: Cloning into '/tmp/sammy-blog'... remote: done. remote: /tmp/sammy-blog ~/sammy-blog.git remote: Configuration file: /tmp/sammy-blog/_config.yml remote: Source: /tmp/sammy-blog remote: Destination: /var/www/html remote: Incremental build: disabled. Enable with --incremental remote: Generating... remote: done in 0.403 seconds. remote: Auto-regeneration: disabled. Use --watch to enable. remote: ~/sammy-blog.git To git@188.166.57.145:sammy-blog.git * [new branch] master -> master
此时,您的站点是新生成的,并且最新的更改已经到位。
结论
在本教程中,您学习了如何在将更改推送到 Git 存储库后部署您的网站。 如果您想了解更多关于 Git 的信息,请查看我们的 Git 教程系列。
如果您想了解更多关于其他 Git 钩子的信息,可以查看 如何使用 Git 钩子自动化开发和部署任务。