如何使用Ubuntu 14.04上的Git Hooks将Hugo站点部署到生产环境

2018-09-26 17:16:02 浏览数 (1)

介绍

Hugo是一个静态站点生成器,允许您通过使用简单的标记语言轻松创建和发布Web内容。Hugo可以根据提供的要求解析您的内容并应用主题,以生成可以轻松托管在任何Web服务器或主机上的一致网页。

在本指南中,我们将向您展示如何设置一个系统git,您可以使用该系统将新内容自动部署到生产Web服务器。

准备

对于本指南,我们假设您已经启动并运行了Ubuntu 14.04计算机作为您的开发计算机。(一台已经设置好可以使用sudo命令的非root账号的Ubuntu服务器,并且已开启防火墙。没有服务器的同学可以在这里购买,不过我个人更推荐您使用免费的腾讯云开发者实验室进行试验,学会安装后再购买服务器。)

我们将建立第二台 Ubuntu 14.04服务器来为我们的实际生产网站服务。在此服务器上,确保已创建具有sudo权限的非root用户。

准备开发服务器

我们将从我们的开发服务器(通过之前的Hugo指南设置的服务器)开始。使用您上次使用的相同非root帐户登录该服务器。

我们需要在此服务器上执行一些操作以设置一步式部署。我们要:

  • 配置对我们的生产服务器的SSH密钥访问
  • 将初始git存储库传输到生产服务器
  • 将生产服务器作为git远程添加到我们的站点存储库中

让我们开始吧。

配置对生产服务器的SSH密钥访问

我们要做的第一件事是在两台服务器之间配置SSH密钥访问。这将允许我们部署而无需每次都输入密码。如果要在每个部署中提示输入密码,可以跳过此步骤。有些人喜欢在部署过程中保持密码提示,这是在推送内容之前重新考虑的一个小机会。

首先,检查您是否已在开发服务器上的帐户中配置了SSH密钥对:

代码语言:javascript复制
ls ~/.ssh/id_rsa

如果您返回如下所示的行,则尚未配置SSH密钥对:

代码语言:javascript复制
ls: cannot access /home/demouser/.ssh/id_rsa: No such file or directory

您可以键入以下内容来创建缺少的密钥对:

代码语言:javascript复制
ssh-keygen

在所有提示中按ENTER键以创建无密码密钥。

另一方面,如果该ls命令为您提供了如下所示的行,则您的帐户中已有一个密钥:

代码语言:javascript复制
/home/demouser/.ssh/id_rsa

获得密钥对后,可以通过键入密钥将公钥传输到生产服务器。在命令中,在本指南的先决条件阶段替换您在生产服务器上配置的非root帐户名称:

代码语言:javascript复制
ssh-copy-id username@production_domain_or_IP

如果这是您第一次在这两台计算机之间使用SSH,则会要求您键入“是”来确认连接。之后,系统将提示您输入生产服务器的用户密码。您的公钥将被传输到生产服务器,允许您下次无需密码登录。

通过使用以下ssh命令询问生产服务器的主机名来测试此功能:

代码语言:javascript复制
ssh username@production_domain_or_IP cat /etc/hostname

这次不应该提示您输入密码。您应该收到生产服务器的主机名:

代码语言:javascript复制
prodserver

将Initial Git Repo传输到Production Server

接下来,我们需要将Hugo仓库的初始克隆转移到我们的生产服务器。我们将需要这个以便post-receive稍后在生产服务器上设置一个钩子。为了实现这一点,我们需要创建一个gitrepo 的“裸”克隆并将其复制到我们的其他服务器。

裸存储库是一个git没有工作目录的特殊存储库。在传统的gitrepos中,项目文件保存在主目录中,git版本控制数据保存在被调用的隐藏目录中.git。裸仓库没有项目文件的工作目录,因此通常保存在隐藏.git文件夹中的文件和目录位于主文件夹中。Bare repos通常用于远程服务器,因为它简化了推送内容的过程。

我们将从/tmp目录中的主Hugo存储库创建一个裸仓库。裸回购通常由尾随.git后缀标识。要创建此副本,我们将使用git clone带有以下--bare选项的命令:

代码语言:javascript复制
git clone --bare ~/my-website /tmp/my-website.git

我们可以将这个裸存储库传输到我们的生产服务器scp。确保在命令末尾包含尾部“:”,以便将repo放置在远程系统上用户的主目录中。

代码语言:javascript复制
scp -r /tmp/my-website.git username@production_domain_or_IP:

为Production Server添加Git Remote

现在我们git在生产服务器上有了我们的裸仓库,我们可以将生产服务器添加为跟踪的远程仓库。这将允许我们轻松地将新内容推送到我们的生产服务器。

回到你的Hugo目录:

代码语言:javascript复制
cd ~/my-website

我们需要做的就是决定遥控器的名称。在本指南中,我们将使用prod。然后,我们可以在远程系统上指定裸存储库的连接信息和位置:

代码语言:javascript复制
git remote add prod username@production_domain_or_IP:my-website.git

在我们的生产服务器上安装git之前,您将无法测试此远程链接。

设置生产服务器

现在我们的开发机器已完全配置,我们可以继续设置我们的生产系统。

在我们的生产系统中,我们需要完成以下步骤:

  • 安装gitnginxpygments
  • 安装Hugo和Hugo主题
  • 配置nginx为从主目录中的位置提供文件
  • 创建post-receive脚本以部署推送到我们的存储库的新内容

在Production Server上安装Git,Pygments和Nginx

我们应该做的第一件事就是安装gitpygmentsnginx到服务器上。虽然我们的项目存储库已经在我们的服务器上,但我们需要该git软件来接收推送并执行我们的部署脚本。我们需要pygments为任何代码块应用服务器端语法高亮。我们将使用nginxWeb服务器,使访问者可以访问我们的内容。

更新本地包指数和安装git,并nginx从Ubuntu的默认存储库。我们需要安装pipPython包管理器来获取pygments

代码语言:javascript复制
sudo apt-get update
sudo apt-get install git nginx python-pip

然后我们可以pip用来安装pygments

代码语言:javascript复制
sudo pip install Pygments

下载完成后,我们可以测试我们是否在开发计算机上正确设置了远程存储库。在您的开发计算机上,进入Hugo项目目录并使用以下git ls-remote命令:

代码语言:javascript复制
cd ~/my-website
git ls-remote prod

如果git可以在开发和生产机器上的存储库之间建立连接,它将显示refs列表,如下所示:

代码语言:javascript复制
103902f5d448cf57425bd6830e544128d9522c51    HEAD
103902f5d448cf57425bd6830e544128d9522c51    refs/heads/master

在Production Server上安装Hugo

回到我们的生产服务器,我们需要安装Hugo。我们将在生产服务器之后构建静态资产,而不是在我们的开发服务器上构建我们的内容git push。要做到这一点,我们需要安装Hugo。

我们可以使用与开发机器相同的方法安装Hugo。首先检查生产服务器的体系结构:

代码语言:javascript复制
uname -i

接下来,访问Hugo发布页面。向下滚动到最新Hugo版本的“下载”部分。右键单击与您的体系结构对应的链接:

  • 如果该uname -i命令生成了x86_64,请右键单击并复制以该amd64.deb结尾的链接
  • 如果该uname -i命令生成了i686,请右键单击并复制以该i386.deb结尾的链接

在生产服务器上,进入您的主目录并使用wget下载您复制的链接:

代码语言:javascript复制
cd ~
wget https://github.com/spf13/hugo/releases/download/v0.14/hugo_0.14_amd64.deb

下载完成后,您可以通过键入以下内容来安装软件包:

代码语言:javascript复制
sudo dpkg -i hugo*.deb

通过要求Hugo显示其版本号来测试安装是否成功:

代码语言:javascript复制
hugo version

您应该看到显示的版本行,表明Hugo现在可用:

代码语言:javascript复制
Hugo Static Site Generator v0.14 BuildDate: 2015-05-25T21:29:16-04:00

在我们继续之前,我们需要将Hugo主题克隆到我们的生产服务器:

代码语言:javascript复制
git clone --recursive https://github.com/spf13/hugoThemes ~/themes

配置Nginx以服务部署期间生成的文件

接下来,我们需要稍微修改我们的Nginx配置。

为了简化部署,不是将生成的内容放在var/www/html目录中,而是将内容放在public_html用户主目录中调用的目录中。

让我们继续创建public_html目录:

代码语言:javascript复制
mkdir ~/public_html

接下来,让我们打开默认的Nginx服务器块配置文件进行必要的调整:

代码语言:javascript复制
sudo nano /etc/nginx/sites-available/default

我们需要更改的唯一选项是server_name,应指向生产服务器的域名或IP地址以及root指令,该指令应指向我们刚刚创建的public_html目录:

代码语言:javascript复制
server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;
​
        root /home/username/public_html;
        index index.html index.htm;
​
        # Make site accessible from http://localhost/
        server_name server_domain_or_IP;
​
. . .

确保将root指令中的“username”替换为生产服务器上的实际用户名。完成后保存并关闭文件。

重新启动Nginx服务器以应用您的更改:

代码语言:javascript复制
sudo service nginx restart

我们的Web服务器现在可以为我们放入public_html目录的文件提供服务。

创建一个Post-Receive Hook来部署Hugo站点

现在,我们终于准备好创建我们的post-receive部署钩子脚本了。每当您将新内容推送到生产代码时,都会调用此脚本。

要创建此脚本,我们将在生产服务器上的裸存储库中进入名为hooks的目录。立即进入该目录:

代码语言:javascript复制
cd ~/my-website.git/hooks

这个目录有很多示例脚本,但我们需要一个post-receive本指南的脚本。在hooks目录中创建并打开具有此名称的文件:

代码语言:javascript复制
nano post-receive

在文件的顶部,在指出这是一个bash脚本之后,我们将从定义一些变量开始。我们将设置GIT_REPO为裸存储库。我们将把它克隆到WORKING_DIRECTORY变量指定的临时存储库,以便Hugo可以访问其中的内容来构建实际的站点。因为我们的gitrepo中的themes目录实际上只是指向父目录中某个位置的符号链接,所以我们需要确保工作目录克隆在与我们下载的Hugo主题相同的位置创建。

公共Web文件夹将由PUBLIC_WWW变量指定,备份Web文件夹将通过BACKUP_WWW变量保持可访问。最后,我们将设置MY_DOMAIN为服务器的域名或公共IP地址:

考虑到这一点,文件的开头应如下所示:

代码语言:javascript复制
#!/bin/bash
​
GIT_REPO=$HOME/my-website.git
WORKING_DIRECTORY=$HOME/my-website-working
PUBLIC_WWW=$HOME/public_html
BACKUP_WWW=$HOME/backup_html
MY_DOMAIN=server_domain_or_IP

设置变量后,我们可以从脚本的逻辑开始。首先,我们将使用bash的set -e命令指定脚本在遇到任何错误时应立即退出。我们将在瞬间出现问题时使用它来清理。

之后,让我们确保为我们的部署设置了环境。我们想要删除任何现有的工作目录,因为我们希望在部署期间克隆新的副本。我们还想备份我们的web目录,以便我们可以在出现任何问题时进行恢复。我们在这里使用rsync是因为它处理空目录和目录,其中的内容比cp一致。确保在$PUBLIC_WWW后面包含尾部/,以便正确解析caommand。

我们要做的最后一个设置过程是设置trap命令,以便在收到“退出”信号时进行响应。由于我们包含了该set -e命令,因此只要我们的部署中的命令失败,就会发生退出信号。在这种情况下,陷阱指定的命令会将我们的备份副本还原到Web目录并删除工作git目录的任何实例。

代码语言:javascript复制
#!/bin/bash
​
GIT_REPO=$HOME/my-website.git
WORKING_DIRECTORY=$HOME/my-website-working
PUBLIC_WWW=$HOME/public_html
BACKUP_WWW=$HOME/backup_html
MY_DOMAIN=server_domain_or_IP
​
set -e
​
rm -rf $WORKING_DIRECTORY
rsync -aqz $PUBLIC_WWW/ $BACKUP_WWW
trap "echo 'A problem occurred.  Reverting to backup.'; rsync -aqz --del $BACKUP_WWW/ $PUBLIC_WWW; rm -rf $WORKING_DIRECTORY" EXIT

现在,我们可以开始部署了。我们将创建一个我们裸仓库的常规克隆,以便Hugo可以访问repo内容。然后,我们将从公共Web目录中删除所有内容,以便公共Web目录中只有新文件可用。之后,我们将使用Hugo来构建我们的网站。我们将它指向我们的新克隆作为源目录,并告诉它将生成的内容放在公共Web文件夹中。我们还将传递包含我们的生产服务器的域名或IP地址的变量,以便它可以正确地构建链接。

在Hugo构建内容之后,我们将删除工作目录。然后,我们将重置trap命令,以便在脚本尝试退出时,我们的备份副本不会立即覆盖我们的新内容:

代码语言:javascript复制
#!/bin/bash
​
GIT_REPO=$HOME/my-website.git
WORKING_DIRECTORY=$HOME/my-website-working
PUBLIC_WWW=$HOME/public_html
BACKUP_WWW=$HOME/backup_html
MY_DOMAIN=server_domain_or_IP
​
set -e
​
rm -rf $WORKING_DIRECTORY
rsync -aqz $PUBLIC_WWW/ $BACKUP_WWW
trap "echo 'A problem occurred.  Reverting to backup.'; rsync -aqz --del $BACKUP_WWW/ $PUBLIC_WWW; rm -rf $WORKING_DIRECTORY" EXIT
​
git clone $GIT_REPO $WORKING_DIRECTORY
rm -rf $PUBLIC_WWW/*
/usr/bin/hugo -s $WORKING_DIRECTORY -d $PUBLIC_WWW -b "http://${MY_DOMAIN}"
rm -rf $WORKING_DIRECTORY
trap - EXIT

此时,我们的脚本已完成。完成后保存并关闭文件。

我们现在要做的就是使脚本可执行,以便git在适当的时候调用它:

代码语言:javascript复制
chmod  x post-receive

我们的部署系统现已完成。我们来试试吧。

测试部署系统

现在我们已经建立了系统,我们可以继续进行测试。

让我们开始测试我们的post-receive钩子脚本。这将允许我们使用我们的Web内容的初始副本填充我们的~/public_html目录。它还有助于验证脚本的主要组件是否按预期工作:

代码语言:javascript复制
bash ~/my-website.git/hooks/post-receive

这应该运行您的脚本并将普通git和Hugo消息输出到屏幕:

代码语言:javascript复制
Cloning into '/home/justin/my-website-working'...
done.
0 draft content
0 future content 
4 pages created
0 paginator pages created
0 tags created
1 categories created
in 26 ms

如果您在Web浏览器中访问生产服务器的域名或IP地址,您应该会看到您网站的当前版本:

代码语言:javascript复制
http://production_domain_or_IP

现在,我们可以回到我们用于Hugo开发的机器。在那台机器上,让我们创建一个新帖子:

代码语言:javascript复制
hugo new post/Testing-Deployment.md

在新帖子中,只需添加一些内容,以便我们可以测试我们的系统:

代码语言:javascript复制
   
categories = ["misc"]
date = "2015-11-11T16:24:33-05:00"
title = "Testing Deployment"

   

## A Test of the New Deployment System

I hope this works!

现在,将内容添加到git并提交更改:

代码语言:javascript复制
git add .
git commit -m 'Deployment test'

现在,如果一切按计划进行,我们只需推送到我们的生产服务器即可部署新的更改:

代码语言:javascript复制
git push prod master

现在,如果您在Web浏览器中重新访问您的生产站点,您应该看到新内容:

代码语言:javascript复制
http://production_domain_or_IP

我们的部署系统似乎运行正常。

结论

在本指南中,我们设置了一个单独的生产服务器,专门为访问者提供Web内容。在此服务器上,我们安装并配置了多个组件,以便Hugo可以正确构建和提供我们的内容。然后,我们创建了一个部署脚本,只要我们从开发计算机将新内容推送到服务器,就会触发该脚本。

我们的部署系统中涉及的实际机制是相当基本的。但是,它们构成了易于维护的系统的基础,可以快速,轻松地在Web服务器上获取本地内容。由于部署过程是自动化的,因此您无需与服务器进行交互即可进行简单的git push更改。

更多Ubuntu教程请前往腾讯云 社区学习更多知识。

参考文献:《How To Deploy a Hugo Site to Production with Git Hooks on Ubuntu 14.04》

0 人点赞