Laravel Envoy es una herramienta para ejecutar tareas comunes que ejecuta en sus servidores remotos.
Creo que Envoy
está subestimado; No veo que se use muy a menudo aunque siempre me ha resultado súper útil. En este artículo, exploraremos cómo Envoy
puede ayudarlo a aumentar su productividad🚀.
Laravel Envoy no es exclusivo de los desarrolladores de Laravel ni se limita a proyectos de Laravel, cualquiera puede usarlo ❤️.
Primero, analicemos dos conceptos clave en Envoy
:
Tareas : esto representa una acción específica como actualizar el servidor o clonar un repositorio.
Historias : que es una colección de Tareas.
Eso es todo lo que necesitas saber por ahora; Siempre puedes leer sobre todas las funciones en los documentos .
En este artículo, automatizaremos 2 cosas que hacen la mayoría de los desarrolladores al implementar sus aplicaciones:
Configurando Nginx.
Generar claves SSH y agregarlas a GitHub para poder acceder a repositorios privados.
Sí, lo sé, la mayor parte del tiempo Envoy
se utiliza para flujos de trabajo de CI/CD, pero puede hacer TODO , literalmente.
Primero, creemos un directorio:
mkdir tuto && cd $_
$ take tuto
si estás usandozsh
.
Instale Envoy
ejecutando el siguiente comando:
composer require laravel/envoy --dev
Asegúrate de tener el compositor instalado.
Ahora, crea un archivo llamado Envoy.blade.php
. Sí, usaremos la sintaxis Blade
, genial, ¿verdad?
touch Envoy.blade.php
¡Eso es todo! Todo lo que necesitas es un único script. No tiene que ser específico de Laravel ni de ningún proyecto relacionado con Laravel. ¡Empecemos a automatizar! 😁
Tenemos un servidor nuevo y queremos configurar Nginx. Si desglosamos el proceso, quedaría así:
Eso es exactamente lo que haremos con Envoy
; Piense en cada paso como una Task
y en todo el proceso como una Story
.
Entonces, traduzcamos lo que acabamos de decir en una historia:
@servers(['web' => '[email protected]', 'local' => '127.0.0.1']) @story('setup-nginx') update-server install-nginx copy-nginx-stub configure-nginx @endstory
La directiva
@servers
se utiliza para especificar los servidores en los que ejecutaremos nuestras tareas más adelante.
Ahora podemos proceder a definir cada tarea 😁
Nuestra primera tarea update-server
garantizará que los paquetes y dependencias del servidor estén actualizados:
@task('update-server', ['on' => ['web']]) echo "Updating server..." apt update && apt upgrade -y @endtask
La segunda tarea install-nginx
instalará Nginx en nuestro servidor:
@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
Observe que eliminamos el enlace Nginx predeterminado y creamos uno nuevo para nuestra aplicación, con el nombre proveniente de la variable $application_name
.
Para poder usar esa variable, debes declararla, por lo que debemos incluir la directiva @setup
:
@setup $application_name = 'your-application-name'; @endsetup
Ahora podemos pasar a la tercera tarea copy-nginx-stub
. En mi caso, estoy implementando una aplicación Laravel, por lo que usaré el archivo de configuración de Nginx proporcionado por los documentos , con algunos ajustes. Si está implementando una aplicación diferente, puede aplicar el mismo concepto a su propio archivo de configuración.
En el directorio que acabamos de crear, ejecute el siguiente comando:
mkdir stubs; nano stubs/nginx.conf
Luego, pegue el siguiente contenido en el editor, guárdelo y salga:
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
y app_name
son marcadores de posición por ahora y se actualizarán automáticamente con nuestras variables.
Pasemos a escribir la tarea en sí:
@task('copy-nginx-stub', ['on' => 'local']) scp -P{{ $production_port }} -r ./stubs/nginx.conf {{ $production_host }}:/etc/nginx/sites-available/{{ $application_name }}.conf @endtask
Esta tarea se ejecutará en nuestra máquina local en lugar del servidor remoto. Especificamos esto usando
'on' => 'local'
.
Y no olvides actualizar la directiva @setup
con las variables necesarias:
@setup $application_name = 'your-application-name'; $production_port = 22; $production_host = '[email protected]'; @endsetup
La cuarta y última tarea configure-nginx
actualizará los marcadores de posición, para que podamos servir la aplicación correctamente:
@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
Tenga en cuenta el comando
cd
. Esto se debe a que cada tarea se ejecuta por separado, por lo que siempre comienza desde el directorio de inicio del servidor remoto.
Ya creamos el enlace simbólico al instalar Nginx, no tenemos que preocuparnos por eso ahora.
¡Y hemos terminado con esta sección! Su script debería verse así:
@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
Ahora que configuramos Nginx y está listo para servir nuestra aplicación, necesitamos generar claves SSH y agregar la clave pública a GitHub para que podamos extraer los repositorios privados.
Para esto, usaremos la API REST de GitHub , por lo que antes de comenzar, debe crear un token .
Al crear su token, asegúrese de seleccionar solo el alcance "admin:public_key".
Ahora que creaste tu token, comencemos por definir algunas variables:
@setup $ssh_key = '~/.ssh/id_rsa_github'; $github_api_key = 'your-github-token'; $email = '[email protected]'; @endsetup
En este punto, es posible que se pregunte acerca de los pasos involucrados en este proceso. Bueno, podemos dividirlo en dos pasos:
Generar claves SSH
Copie la clave pública a GitHub
Una vez más, este proceso será nuestra historia:
@story('setup-ssh-keys') generate-ssh-keys add-ssh-keys-to-github @endstory
La primera tarea, generate-ssh-keys
, se puede realizar ejecutando un solo comando:
@task('generate-ssh-keys', ['on' => ['web']]) echo "Generating ssh keys..." ssh-keygen -t ed25519 -f {{ $ssh_key }} -N '' -q -C "{{ $email }}" @endtask
Una vez que hayamos generado nuestras claves SSH, podemos agregar la clave pública a GitHub usando la API de GitHub. Esto se puede hacer con una sola solicitud:
@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
¡Y eso es! Si visita la configuración de desarrollador de GitHub, debería ver su clave recién creada.
Al combinar las dos secciones, su guión final debería verse así:
@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
Aprendimos a utilizar Envoy
para automatizar tareas comunes. Es una herramienta poderosa con incluso más capacidades de las que hemos explorado aquí. No se limite sólo a implementar sus aplicaciones; Envoy
puede automatizar CUALQUIER comando de terminal, literalmente cualquier cosa que se le ocurra.
La próxima vez que te encuentres repitiendo los mismos comandos, considera usarlo, te prometo que hace mucho más que CI/CD 😛😛