如何在Ubuntu16.04上使用GitHooks部署Jekyll站点

来自菜鸟教程
跳转至:导航、​搜索

作为 Write for DOnations 计划的一部分,作者选择了 Diversity in Tech Fund 来接受捐赠。

介绍

Jekyll 是一个静态站点生成器,它提供了内容管理系统 (CMS) 的一些好处,同时避免了此类数据库驱动站点引入的性能和安全问题。 它是“博客感知”的,包括处理按日期组织的内容的特殊功能,尽管它的用处不限于博客网站。 Jekyll 非常适合需要离线工作、更喜欢轻量级编辑器而不是 Web 表单进行内容维护、并希望使用版本控制来跟踪其网站更改的人。

在本教程中,我们将配置生产环境以使用 Nginx 来托管 Jekyll 站点,以及在将更改推送到站点存储库时使用 Git 来跟踪更改并重新生成站点。 我们还将安装和配置 git-shell 以额外保护您的生产服务器免受未经授权的访问。 最后,我们将配置您的本地开发机器以使用并将更改推送到远程存储库。

先决条件

要遵循本教程,您将需要:

第 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 钩子自动化开发和部署任务