Laravel Envoy 是一个用于执行在远程服务器上运行的常见任务的工具。
我认为Envoy
被低估了;尽管我一直觉得它非常有用,但我并不经常使用它。在本文中,我们将探讨Envoy
如何帮助您提高工作效率🚀。
Laravel Envoy 并非 Laravel 开发人员专属,也不仅限于 Laravel 项目,任何人都可以使用它 ❤️。
首先,我们来讨论一下Envoy
中的两个关键概念:
任务:这代表特定的操作,例如更新服务器或克隆存储库。
故事:是任务的集合。
这就是您现在需要知道的全部内容;您可以随时在文档中阅读有关所有功能的信息。
在本文中,我们将自动执行大多数开发人员在部署应用程序时所做的两件事:
配置 Nginx。
生成 SSH 密钥并将其添加到 GitHub 以便能够访问私有存储库。
是的,我知道,大多数时候Envoy
用于 CI/CD 工作流,但实际上它可以做任何事情。
首先,让我们创建一个目录:
mkdir tuto && cd $_
如果您使用
zsh
,$ take tuto
。
通过运行以下命令安装Envoy
:
composer require laravel/envoy --dev
确保您已经安装了 Composer。
现在,创建一个名为Envoy.blade.php
的文件。是的,我们将使用Blade
语法,超酷吧?
touch Envoy.blade.php
就是这样!你只需要一个脚本。它不必特定于 Laravel 或任何与 Laravel 相关的项目。让我们开始自动化吧!😁
我们有一台全新的服务器,我们想设置 Nginx。如果我们分解这个过程,它将是这样的:
这正是我们将要用Envoy
做的事情;将每个步骤视为一个Task
,将整个过程视为一个Story
。
那么,让我们把刚才所说的内容转化成一个故事:
@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 应用程序,因此我将使用docs提供的 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
现在我们已经配置了 Nginx,它已准备好为我们的应用程序提供服务,我们需要生成 SSH 密钥并将公钥添加到 GitHub,以便我们可以拉取私有存储库。
为此,我们将使用GitHub REST API ,因此在开始之前,您需要创建一个令牌。
创建令牌时,请确保只选择“admin:public_key”范围。
现在您已经创建了令牌,让我们首先定义一些变量:
@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 功能强大得多😛😛