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

介绍

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

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

准备

要学习本教程,您需要:

  • 一个用于生产的Ubuntu 16.04服务器,包括:
  • 安装Nginx。
  • 安装Jekyll。
  • 一个安装了Git和创建了Jekyll站点的服务器。参考腾讯云社区的基于Ubuntu系统安装Git搭建 Jekyll的教程。

第一步 - 设置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-dat组。该组确保Web服务器可以访问和管理位于/var/www/html位置的文件:

$ sudo chown git:www-data /var/www/html

在继续本教程之前,将SSH密钥复制到新创建的git用户,这样您就可以使用Git安全地访问生产服务器。最简单的方法是使用该ssh-copy-id命令,但您也可以手动复制密钥。

现在让我们为您的Jekyll站点创建一个Git存储库,然后配置Git hooks以在更新时重建它。

第二步 - 设置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

hooks目录包含用于Git的脚本。默认情况下,它包含每种类型的Git hooks的示例文件,因此您可以轻松入门。出于本教程的目的,一旦使用最新更改更新存储库,我们将使用post-receive挂钩重新生成站点。

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

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

我们将配置hook以克隆对临时目录的最新更改,然后重新生成它并将生成的站点保存到/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 hook,用于在收到更改时更新您的站点。在将站点推送到存储库之前,我们还将通过配置git-shell来保护我们的生产服务器,git-shell是一个交互式shell,可以在用户通过SSH连接时为用户提供各种Git命令。

第三步- 配置Git Shell以禁用交互式登录

用户可以通过以下方式实现git-shell:作为交互式shell,在通过SSH连接时为他们提供各种命令,使他们能够创建新的存储库或添加新的SSH密钥,或者作为非交互式shell,禁用对服务器控制台的访问通过SSH,但允许他们使用git命令来管理现有的存储库。

如果您与任何人共享git用户的SSH密钥,他们将可以通过SSH访问交互式Bash会话。这表示了存在安全威胁,因为用户可以访问其他非站点相关数据。我们将配置git-shell为非交互式shell,因此您无法使用git用户启动交互式Bash会话。

请确保您以git用户身份登录。如果在上一步之后退出会话,则可以使用与以前相同的命令再次登录:

$ su - git

首先创建一个为git-shell工作所需的目录git-shell-commands

$ 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

返回到您的使用sudo命令的非root用户,这样您就可以修改我们的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存储库,然后我们将您的站点推送到存储库。最后,我们将确保您的网站已生成,您便可以从网络浏览器访问它。

第四步 - 将更改推送到存储库

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

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

$ cd ~/www

我们需要在站点的根目录中初始化Git存储库,以便我们可以将内容推送到远程存储库:

$ git init

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

Initialized 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标志提交所有更改,其中包括提交消息。由于这是我们的第一次提交,我们称之为“初始提交(Initial commit)”

$ 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

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

Push output
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添加它们,就像我们在初始时提交所做的那样。当您准备提交文件时,您将需要包含另一个描述更改的提交消息。我们会将消息称为“更新文件(updated files )”

$ git commit -am "updated files"

最后,将更改推送到远程存储库。

$ git push origin master

输出结果看起来与您在初始推送时看到的类似:

Push output
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存储库之后部署网站,同时腾讯云社区提供关于在 Linux 上搭建Jekyll静态博客的教程,欢迎使用。


参考文献:《How To Deploy a Jekyll Site Using Git Hooks on Ubuntu 16.04》

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小樱的经验随笔

mount命令详解及常见问题汇总

一 、mount命令(用来挂载硬盘或镜像等) 用法:mount [-t vfstype] [-o options] device dir 1、-t vfstyp...

8865
来自专栏菩提树下的杨过

Spring JDBCTemplate使用JNDI数据源

接上回继续,项目开发好以后,通常要在多个环境部署,象我们公司多达5种环境:本机环境(local)、(开发小组内自测的)开发环境(dev)、(提供给测试团队的)测...

35710
来自专栏云计算教程系列

在Ubuntu 16.04如何使用Percona将MySQL类别的数据库备份到指定的对象存储上呢?

数据库通常会在您的基础架构中存储一些最有价值的信息。因此,在发生事故或硬件故障时,必须具有可靠的备份以防止数据丢失。

1503
来自专栏大内老A

ASP.NET Core的配置(5):配置的同步[ 实例篇]

ConfigurationBuilder在生成以Configuration对象的时候会利用注册其中的ConfigurationProvider加载原始的配置数据...

2298
来自专栏Java技术分享

Maven下载、安装和配置

这两件事情他都做到了,而且还做了更多的事情。Maven还可以管理项目的整个声明周期,包括编 译,构建,测试,发布,报告等等。目前Apache下绝大多数项目都已经...

2617
来自专栏SpringBoot 核心技术

第八章:使用拦截器记录你的SpringBoot的请求日志本章目标构建项目配置拦截器初尝试运行项目总结

3182
来自专栏菩提树下的杨过

javascript: 带分组数据的Table表头排序

接上回继续,项目开发好以后,通常要在多个环境部署,象我们公司多达5种环境:本机环境(local)、(开发小组内自测的)开发环境(dev)、(提供给测试团队的)测...

23410
来自专栏Laoqi's Linux运维专列

shell命令基本知识点

命令历史 # cat /root/.bash_history       //存放历史命令的地方 # history      //查看命令历史的条数 # ec...

3668
来自专栏Albert陈凯

linux目录结构和常用命令

一、Linux目录结构 你想知道为什么某些程序位于/bin下,或者/sbin,或者/usr/bin,或/usr/sbin目录下吗?例如,less命令位于/us...

2704
来自专栏跟着阿笨一起玩NET

如何正确运用异步编程技术

4.1、既然异步可以大大提供应用程序的响应能力?那么ASP.NET MVC 如果全部用异步控制器(Async Controller),会有什么效果?会成为高吞吐...

1022

扫码关注云+社区

领取腾讯云代金券