如何在Ubuntu 16.04上使用Git钩子部署Jekyll站点

Jekyll是一个静态站点生成器,它提供了内容管理系统(CMS)的一些优点,同时避免了由这种由数据库驱动的站点引入的性能和安全问题。在本教程中,您将学习如何使用Git和Git Hooks来自动执行Jekyll站点的部署过程,以及如何使用`git-shell`来额外保护您的生产环境。

作者选择科技基金多元化,作为Write for DOnations计划的一部分,获得300美元的捐赠。

介绍

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

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

先决条件

要学习本教程,您需要:

第1步 - 建立一个Git用户帐户

出于安全考虑,我们将开始创建一个用户帐户,该用户帐户将托管Jekyll站点的Git存储库。 该用户将执行Git钩子脚本,我们将在收到更改时创建该脚本以重新生成站点。 以下命令将创建一个名为git的用户:

sudo adduser git

系统会要求您输入并重复输入密码,然后输入有关用户的非强制性基本信息。 最后,您需要输入Y来确认信息:

Adding 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 Hooks以在更新时重建它。

第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

输出包含有关已成功初始化的存储库的信息:

Initialized empty Git repository in /home/git/sammy-blog.git

如果您看不到此类输出,请在继续教程之前按照屏幕上的日志解决问题。

我们创建的文件夹包含托管存储库所需的目录和文件。 您可以通过输入以下内容来检查其内容:

ls
branches  config  description  HEAD  hooks  info  objects  refs

如果你没有看到这种类型的输出,确保你切换到相应的目录并成功执行git init

钩子目录包含用于Git钩子的脚本。 默认情况下,它包含每种类型的Git钩子的示例文件,以便您可以轻松开始。 为了本教程的目的,我们将使用post-receive钩子在存储库更新最新更改重新生成站点。

hooks目录中创建名为post-receive的文件,并在您选择的文本编辑器中打开它:

nano ~/sammy-blog.git/hooks/post-receive

我们将配置钩子以克隆对临时目录的最新更改,然后重新生成并将生成的网站保存到/var/www/html以便您可以轻松访问它。

将以下内容复制到文件中:

〜/sammy-blog.git /钩/后接收
#!/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 hook来在接收到更改时更新您的网站。 在将网站推送到存储库之前,我们还会通过配置git-shell保护我们的生产服务器, 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的壳commnads /无交互式登录
#!/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密钥,并在继续教程之前回溯前面的步骤以解决问题。

Welcome 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存储库,然后我们会将您的网站推送到存储库。 最后,我们将确保您的网站已生成,并且您可以从网络浏览器访问它。

第4步 - 推动对存储库的更改

我们现在已经在生产服务器上初始化并配置了一个Git仓库。 在开发机器上,我们需要初始化一个本地存储库,其中包含有关远程存储库和本地存储库中所做更改的数据。

在您的开发机器上,导航到包含该站点的目录:

cd ~/www

我们需要在网站的根目录中初始化一个Git仓库,以便将内容推送到远程仓库:

git init

输出包含有关成功存储库初始化的消息:

Initialized empty Git repository in /home/sammy/www

如果您看不到此类输出,请在继续之前按照屏幕上的信息解决问题。

现在,创建一个远程对象,它代表用于跟踪远程存储库和分支的Git对象。 通常,默认的remote被称为origin ,所以我们将在本教程中使用它。

以下命令将创建一个远程源,它将使用git用户跟踪生产服务器上的sammy-blog存储库:

git remote add origin git@production_server_ip:sammy-blog.git

没有输出表示操作成功。 如果您看到错误消息,请确保在继续下一步之前解决它。

每次你想把更改推送到远程仓库时,你需要提交它们,然后将提交推送到远程仓库。 一旦远程存储库收到提交,您的站点将会重新生成最新的更改。

提交用于跟踪您所做的更改。 它们包含一个提交消息,用于描述在该提交中所做的更改。 建议保持简短但简洁的消息,包括有关提交中所做的最重要更改的详细信息。

在提交更改之前,我们需要选择要提交的文件。 以下命令标记所有要提交的文件:

git add .

没有输出表明命令执行成功。 如果您看到任何错误,请确保在继续之前解决它们。

接下来,使用-m标志提交所有更改,其中将包含提交消息。 由于这是我们的第一次提交,我们将其称为“初始提交”

git commit -m "Initial commit."

输出包含在该提交中更改的目录和文件的列表:

 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

输出将包含有关推送进度的信息。 完成后,您将看到以下信息:

Counting 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

输出看起来类似于您在初次推送时看到的内容:

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