通过 Github Action 自动化部署网站到远程服务器
通过上篇【通过域名+服务器搭建一个最基础的网站】 我们知道了如何通过搭建自己的博客,接下来稍微介绍下如何通过工作流做自动化部署。
开始
上篇中,已配置好 Nginx,并且当我们访问 https://blog.emooa.com 时,可以正确的访问到网站资源。
1 | server { |
我们注意到 root
指向 /home/blog
,通常 Nginx
的默认文档根目录通常是 /usr/share/nginx/html
或 /var/www
,因为我的服务器是 Ubuntu
,所以应该是 /var/www
。
为什么不是放在个人目录下?
个人用户的主目录下通常不是最佳做法,因为这些文件通常需要具有公共访问权限,以便 Web 服务器可以提供它们给外部访问者。用户主目录通常默认是不允许公共访问的,如果多个用户使用同一台服务器托管不同的网站或服务,通常无法访问其他用户的个人目录,因此需要在更适合公开访问的位置存储网站或服务文件。
比如我当前的账户为 hfs
,于是在 /var/www
下新建个人目录,将 blog
文件夹移动到 /var/www/hfs
下,并修改 ngixn
配置
1 | ssh hfs@*.*.*.* |
1 | location / { |
我们继续访问 https://blog.emooa.com 不错,依然能访问到页面。
配置 Workflows
创建一个包含以下步骤的工作流程(workflow)文件(命名为 .github/workflows/deploy.yml)并将其添加到你的代码仓库中:
1 | name: CI/CD |
第一步使用 actions/checkout 动作来检出最新的代码。
第二步用于安装应用程序的依赖项。你可以根据你的项目使用 npm 或 yarn。
第三步用于构建你的应用程序。你需要替换为适用于你的项目的构建命令。
第四步是将构建好的文件部署到你的服务器。你需要根据你的服务器和部署方式来编写对应的命令,例如使用 scp 或 rsync。
注意:通常情况下需要验证服务器具有正确的部署凭证,并且可以从 GitHub Actions 访问你的服务器。如果需要,你还需要设置 SSH 密钥或其他身份验证方法来与你的服务器通信。
配置 SSH 密匙认证
通常我们在建立 SSH
连接时,是需要输入密码的,但是由于在通过 workflow
工作流进行 ssh 连接时,不涉及到交互式操作,所以我们需要通过基于 SSH
密匙的认证。
方式一:使用 SSH 密钥认证(推荐)
1、生成 SSH 密钥对
SSH 密钥认证更安全和便捷,通常是首选的方法。公钥文件(id_rsa.pub)包含了你的公钥,而密钥文件(id_rsa)则应该保持在本地,不要共享或泄露。密钥是用于身份验证的一半,而公钥是用于验证身份的另一半。当你尝试通过 SSH 连接到服务器时,你的密钥与服务器上存储的公钥进行匹配,以便验证你的身份。
首先,确保你的本地计算机上已经生成了 SSH 密钥对,包括公钥和密钥。如果你还没有生成密钥对,你可以在本地电脑使用以下命令生成:
1 | ssh-keygen -t rsa -b 4096 -C "your_email@example.com" |
2、添加公钥到服务器
这将生成一个 SSH 密钥对,为 id_rsa
, id_rsa.pub
。 然后,将你的公钥添加到服务器上的 ~/.ssh/authorized_keys
文件中。你可以使用以下命令将公钥复制到服务器:
1 | ssh-copy-id $USER_NAME@$IP // 比如:ssh-copy-id hfs@$*.*.*.* |
确保 $USER_NAME 和 $IP 替换为服务器的用户名和 IP 地址。此命令会讲公匙追加到服务器上的 authorized_key
文件中。
如果没有 ssh-copy-id 命令,你可以手动将公钥的内容复制到服务器的 ~/.ssh/authorized_keys
文件中。
1 | cat ~/.ssh/id_rsa.pub | ssh $USER_NAME@$IP 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys' |
这个命令将本地的公钥内容通过 SSH 连接发送到服务器,并追加到 `authorized_keys`` 文件中。完成后,你应该能够无需密码进行 SSH 连接。
3、添加密钥到 Github Action
你应该注意到 yml
文件中的环境变量 SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
,这是由于在 `workflow`` 工作流连接服务器的时候,需要进行身份验证,我们已经在服务器添加了公钥,这时候就需要把密钥添加到工作流当中进行 SSH 认证。
复制密钥文件 id_rsa 的内容读。
1
cat ~/.ssh/id_rsa
在 GitHub 仓库的 “Settings” > “Secrets” 页面中,创建一个新的 Secret,命名为 SSH_PRIVATE_KEY(或其他你喜欢的名称),并将第一步中的密钥内容粘贴到 “Value” 字段中。
GitHub Actions 的工作流程中,使用 Secrets 中的 SSH_PRIVATE_KEY 变量来设置密钥,然后用它进行 SSH 认证。示例步骤如下:
1
2
3
4
5
6
7- name: Deploy blog.emooa.com
env:
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
run: |
mkdir -p ~/.ssh
echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa // 设置文件权限
4、首次验证主机密钥
通常,在第一次 SSH 连接时会要求我们确认服务器的公钥指纹。由于是 workflow 工作流非交互式部署,我们需要提前添加服务器的公钥到工作流的的 known_hosts
文件中,这个文件位于 ~/.ssh/known_hosts
可以在你的 GitHub Actions 步骤中使用 ssh-keyscan 命令获取服务器的公钥并追加到 known_hosts 文件。
如果本地主机不存在 IP 对应的公钥,可以执行 ssh USERNAME@IP
后根据提示生成。
1 | ssh-keyscan $SSH_KNOWN_HOSTS >> ~/.ssh/known_hosts |
方式二:服务器 SSH 服务器配置(不推荐)
确保服务器上的 SSH 服务器配置允许 SSH 密钥认证。在服务器上的 /etc/ssh/sshd_config 文件中,确保以下配置项没有被注释掉:
1 | PubkeyAuthentication yes |
可能会遇到的问题
问题一 无法验证主机密钥
Run ssh $USER_NAME@$IP ‘mkdir -p /var/www/$USER_NAME/blog’ Host key verification failed. Error: Process completed with exit code 255.
原因:通常出现在首次连接到远程服务器时,SSH 客户端无法验证目标服务器的主机密钥。这通常是因为 SSH 客户端没有保存目标服务器的公钥,或者保存的公钥不匹配。解决:上面提到的 首次验证主机密钥
问题二 权限不足
cannot create directory ‘/var/www/hfs/blog’: Permission denied
1 | Run ssh $USER_NAME@$IP 'mkdir -p /var/www/$USER_NAME/blog' |
原因:遇到了文件权限问题,这意味着你的 SSH
用户在远程服务器上没有足够的权限来创建目录 /var/www/$USER_NAME/blog
。解决:
使用超级用户权限(例如 root 用户)登录到服务器。
使用 chown 命令将目录的所有者更改为
$USER_NAME
用户。这将确保$USER_NAME
用户具有修改该目录的权限使用 chmod 命令为目录添加写权限。你可以授予
$USER_NAME
用户写入权限,而其他用户只能读取或执行。1
2sudo chown -R $USER_NAME:$USER_NAME /var/www/$USER_NAME
sudo chmod -R 755 /var/www/$USER_NAME
问题三:如何查看日志
在 SSH 时可能出现一些不清楚具体原因导致的,可以通过打开日志来检查
1 | ssh -v -i ~/.ssh/id_rsa $USER_NAME@$IP |