Laravel Envoy
Laravel Envoy 是用于执行你经常在远程服务器上运行的常见任务的工具。
我认为 Envoy
被低估了,尽管我一直觉得它非常实用,但我很少看到它被使用。在这篇文章中,我们将探讨 Envoy
如何帮助你提高生产力🚀。
Laravel Envoy 不仅针对 Laravel 开发者,也不仅限于 Laravel 项目,任何人都可以使用它 ❤️。
首先,让我们讨论 Envoy
中的两个关键概念
- 任务:代表特定的动作,如更新服务器或克隆存储库。
- 故事:是任务的集合。
现在你需要知道的就这些,你总是可以阅读关于所有功能的文档(链接)。
我们在自动化什么?
在这篇文章中,我们将自动化开发者在部署应用程序时通常会做的两件事
- 配置Nginx。
- 生成SSH密钥并将它们添加到GitHub,以便能够访问私有仓库。
是的,我知道,大多数时候 Envoy
用于CI/CD工作流程,但它在实际上可以做到 一切,真的是这样。
Envoy的设置
首先创建一个目录
mkdir tuto && cd $_
$ take tuto
如果你使用的是zsh
。
通过运行以下命令安装 Envoy
composer require laravel/envoy --dev
请确保你已经安装了 composer。
现在创建一个名为 Envoy.blade.php
的文件。是的,我们将使用 Blade
语法,超级酷吧?
touch Envoy.blade.php
这就完了!你只需要一个脚本。它不一定要专门针对 Laravel 或任何 Laravel 相关项目。让我们开始自动化!😁
配置 Nginx
我们有一个全新的服务器,我们想要设置 Nginx。如果我们分解这个过程,它将像
- 更新服务器
- 安装 Nginx
- 配置 Nginx
这就是我们将用 Envoy
做的,把每一步想象成一个 任务
,整个过程想象成一个 故事
。
所以,让我们把刚刚说的转换成一个故事
@servers(['web' => '[email protected]', 'local' => '127.0.0.1'])
@story('setup-nginx')
update-server
install-nginx
copy-nginx-stub
configure-nginx
@endstory
使用
@servers
指令可以指定我们将要运行任务的服务器。
现在我们可以开始定义每个任务了 😁
我们的第一个任务 update-server
将确保服务器的包和依赖项是最新的
@task('update-server', ['on' => ['web']])
echo "Updating server..."
apt update && apt upgrade -y
@endtask
第二个任务 install-nginx
将在服务器上安装 Nginx
@task('install-nginx', ['on' => ['web']])
echo "Installing nginx..."
apt install nginx -y
rm /etc/nginx/sites-enabled/default /etc/nginx/sites-available/default
touch /etc/nginx/sites-available/{{ $application_name }}.conf
ln -s /etc/nginx/sites-available/{{ $application_name }}.conf /etc/nginx/sites-enabled/{{ $application_name }}.conf
@endtask
注意,我们已经删除了默认的 Nginx 链接,为我们自己的应用程序创建了一个新的链接,链接名称来自 $application_name
变量。
为了使用该变量,您需要将其声明,因此我们需要包含 @setup
指令
@setup
$application_name = 'your-application-name';
@endsetup
现在我们可以继续进行第三个任务 copy-nginx-stub
。以我的情况为例,我正在部署一个 Laravel 应用程序,所以我将使用由 文档 提供的 Nginx 配置文件,并进行一些调整。如果您正在部署不同的应用程序,您可以将相同的概念应用于您自己的配置文件。
在刚刚创建的目录中,运行以下命令
mkdir stubs; nano stubs/nginx.conf
然后,将以下内容粘贴到编辑器中,保存并退出
server {
listen 80;
listen [::]:80;
server_name public_ip;
root /var/www/app_name/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
public_ip
和 app_name
仍然是占位符,稍后会自动用我们的变量替换。
现在让我们开始编写任务本身
@task('copy-nginx-stub', ['on' => 'local'])
scp -P{{ $production_port }} -r ./stubs/nginx.conf
{{ $production_host }}:/etc/nginx/sites-available/{{ $application_name }}.conf
@endtask
此任务将在本地计算机上执行,而不是在远程服务器上。我们使用
'on' => 'local'
指定这一点。
别忘了更新 @setup
指令所需变量
@setup
$application_name = 'your-application-name';
$production_port = 22;
$production_host = '[email protected]';
@endsetup
第四个和最后一个任务 configure-nginx
将更新占位符,以便我们可以正确地提供应用程序
@task('configure-nginx', ['on' => 'web'])
echo "Configuring nginx..."
cd /etc/nginx/sites-available/
sed -i 's/app_name/{{ $application_name }}/g' {{ $application_name }}.conf
sed -i 's/public_ip/{{ $production_ip }}/g' {{ $application_name }}.conf
@endtask
请注意
cd
命令。这是因为每个任务都是单独执行的,所以它总是从远程服务器的家目录开始。
我们在安装 Nginx 时已经创建了符号链接,所以我们现在不用担心它。
这一部分就完成了!你的脚本应该看起来像这样
@servers(['web' => '[email protected]', 'local' => '127.0.0.1'])
@setup
$application_name = 'your-application-name';
$production_port = 22;
$production_host = '[email protected]';
@endsetup
@story('setup-nginx')
update-server
install-nginx
copy-nginx-stub
configure-nginx
@endstory
@task('update-server', ['on' => ['web']])
echo "Updating server..."
apt update && apt upgrade -y
@endtask
@task('install-nginx', ['on' => ['web']])
echo "Installing nginx..."
apt install nginx -y
rm /etc/nginx/sites-enabled/default /etc/nginx/sites-available/default
touch /etc/nginx/sites-available/{{ $application_name }}.conf
ln -s /etc/nginx/sites-available/{{ $application_name }}.conf /etc/nginx/sites-enabled/{{ $application_name }}.conf
@endtask
@task('copy-nginx-stub', ['on' => 'local'])
scp -P{{ $production_port }} -r ./stubs/nginx.conf
{{ $production_host }}:/etc/nginx/sites-available/{{ $application_name }}.conf
@endtask
@task('configure-nginx', ['on' => 'web'])
echo "Configuring nginx..."
cd /etc/nginx/sites-available/
sed -i 's/app_name/{{ $application_name }}/g' {{ $application_name }}.conf
sed -i 's/public_ip/{{ $production_ip }}/g' {{ $application_name }}.conf
@endtask
SSH 密钥配置
既然我们已经配置了 Nginx,并且它已经准备好为我们的应用程序提供服务,我们就需要生成 ssh 密钥,并将公钥添加到 Github,以便我们可以拉取私有存储库。
为此,我们将使用 GitHub REST API,所以在我们开始之前,您需要 创建一个 token。
在创建您的 token 时,确保您只选择 "admin:public_key" 范围。
现在您已经创建了一个 token,让我们首先定义一些变量
@setup
$ssh_key = '~/.ssh/id_rsa_github';
$github_api_key = 'your-github-token';
$email = '[email protected]';
@endsetup
到目前为止,您可能想知道这个过程中的步骤。好吧,我们可以把它分成两个步骤
- 生成 SSH 密钥
- 将公钥复制到 Github
这个过程中将再一次是我们的故事
@story('setup-ssh-keys')
generate-ssh-keys
add-ssh-keys-to-github
@endstory
第一个任务 generate-ssh-keys
可以通过运行一个简单的命令来完成
@task('generate-ssh-keys', ['on' => ['web']])
echo "Generating ssh keys..."
ssh-keygen -t ed25519 -f {{ $ssh_key }} -N '' -q -C "{{ $email }}"
@endtask
一旦我们生成了我们的 SSH 密钥,我们就可以使用 Github API 将公钥添加到 Github。这可以通过一个简单的请求完成
@task('add-ssh-keys-to-github', ['on' => ['web']])
echo "Adding ssh keys to github..."
key=$(cat {{ $ssh_key }}.pub)
curl --request POST \
--url https://api.github.com/user/keys \
--header 'Accept: application/vnd.github+json' \
--header 'Authorization: Bearer {{ $github_api_key }}' \
--header 'Content-Type: application/json' \
--header 'X-GitHub-Api-Version: 2022-11-28' \
--data '{
"title": "[Envoy] Public key",
"key": "'"$key"'"
}'
@endtask
这样就完成了!如果你访问你的GitHub开发者设置,你应该能看到你刚刚创建的密钥。
通过合并这两个部分,你的最终脚本应该看起来像这样
@servers(['web' => '[email protected]', 'local' => '127.0.0.1'])
@setup
$application_name = 'your-application-name';
$production_port = 22;
$production_host = '[email protected]';
$ssh_key = '~/.ssh/id_rsa_github';
$github_api_key = 'your-github-token';
$email = '[email protected]';
@endsetup
@story('setup-nginx')
update-server
install-nginx
copy-nginx-stub
configure-nginx
@endstory
@story('setup-ssh-keys')
generate-ssh-keys
add-ssh-keys-to-github
@endstory
@task('update-server', ['on' => ['web']])
echo "Updating server..."
apt update && apt upgrade -y
@endtask
@task('install-nginx', ['on' => ['web']])
echo "Installing Nginx..."
apt install nginx -y
rm /etc/nginx/sites-enabled/default /etc/nginx/sites-available/default
touch /etc/nginx/sites-available/{{ $application_name }}.conf
ln -s /etc/nginx/sites-available/{{ $application_name }}.conf /etc/nginx/sites-enabled/{{ $application_name }}.conf
@endtask
@task('copy-nginx-stub', ['on' => 'local'])
scp -P{{ $production_port }} -r ./stubs/nginx.conf
{{ $production_host }}:/etc/nginx/sites-available/{{ $application_name }}.conf
@endtask
@task('configure-nginx', ['on' => 'web'])
echo "Configuring nginx..."
cd /etc/nginx/sites-available/
sed -i 's/app_name/{{ $application_name }}/g' {{ $application_name }}.conf
sed -i 's/public_ip/{{ $production_ip }}/g' {{ $application_name }}.conf
@endtask
@task('generate-ssh-keys', ['on' => ['web']])
echo "Generating ssh keys..."
ssh-keygen -t ed25519 -f {{ $ssh_key }} -N '' -q -C "{{ $email }}"
@endtask
@task('add-ssh-keys-to-github', ['on' => ['web']])
echo "Adding ssh keys to github..."
key=$(cat {{ $ssh_key }}.pub)
curl --request POST \
--url https://api.github.com/user/keys \
--header 'Accept: application/vnd.github+json' \
--header 'Authorization: Bearer {{ $github_api_key }}' \
--header 'Content-Type: application/json' \
--header 'X-GitHub-Api-Version: 2022-11-28' \
--data '{
"title": "creating from script",
"key": "'"$key"'"
}'
@endtask
结论
我们学习了如何使用Envoy
来自动化常见任务。这是一款功能强大的工具,甚至比我们在这里探索的更多。不要只限于部署你的应用程序,Envoy
可以自动化任何终端命令,字面上的任何事情都可以。
下次当你发现自己重复相同的命令时,考虑使用它,我保证它做的工作远不止CI/CD 😛😛
用户driesvints喜欢这篇文章