Instalación de Laravel con Octane en Amazon Web Services

Instalar Laravel Octane con Swoole en Amazon Web Services

Laravel es el repositorio de GitHub más exitoso de los últimos años y quizás de todos los tiempos. Es un framework para aplicaciones web escrito en PHP, este lenguaje no es de los que están de moda hoy en día, y es que Python, Go y JavaScript (NodeJs) han tenido un gran repunte debido a sus habilidades, principalmente en el lado del análisis de datos y control de servidor.

Más allá de la moda yo sigo considerando PHP cómo el mejor lenguaje para servir front-ends resistentes, debido a lo que otras personas consideran una debilidad de PHP, su poco control del servidor: el PHP moderno se ejecuta en una máquina virtual aislada del resto y se le puede limitar los recursos a los que accede con mucha precisión.

Amazon Web Services (AWS) es una empresa de computación en la nube que nos ha dado a los programadores y arquitectos la habilidad de aplicar Arquitectura Hexagonal, gracias a la facilidad con la que podemos configurar el cómputo distribuido en nuestros proyectos. Existen otras empresas dedicadas a prestar este tipo de servicios, yo empecé con DigitalOcean, y ahora Google junto con Microsoft también están a la vanguardia junto con AWS.

También uso CloudFlare ya que sus servicios de NS y DNS son quizás los mejores (AWS y Google tercerizan con CloudFlare muchos servicios). También existen otras empresas como Akamai o Fastly, incluso AWS y Google tienen servicios parecidos. Pero CloudFlare tiene una relación costo-valor insuperable para los clientes pequeños y medianos. Y esto también aplica para su CDN.

Si no quieres hacer el trabajo que aparece en esta guía

Para eso recomiendo Laravel/Vapor, que es cómo un Laravel/Forge pero en servidores AWS propios, basado en el paradigma ServerLess puedes arrancar tu servidor cómo por arte de magia en un panel de control muy bien construido.

Yo identifico dos casos de uso para Laravel/Vapor:

  1. Presupuesto holgado. Pero no quieres que tu personal IT esté sufriendo con la escalabilidad horizontal a la hora que que experimentes un crecimiento acelerado del uso de tu sistema.
  2. Presupuesto ajustado. Y tu personal IT no tiene las habilidades o el tiempo para configurar y mantener los servidores que responden a tu arquitectura distribuida.

Creamos la instancia VPS que vamos a usar

Tenemos que seleccionar el tipo de instancia, para esta guía será una Amazon Linux 2 AMI (AL), y para eso lanzamos una instancia nueva.

Se puede argumentar sobre usar otros sistemas operativos, en mi caso yo tengo mucha experiencia con Ubuntu. Yo he comparado AL con Ubuntu en mis proyectos y he llegado a la conclusión de que no hay ganador.

AL es más rápido porque está diseñado para integrarse en AWS mientras de Ubuntu tiene más paquetes listos para usar con mejor literatura para su uso. Este artículo no viene a hacer comparativa entre ambos sistemas operativos, yo decidí usar AL en este proyecto porque Laravel/Octane para el núcleo de una app lo que requiere es rendimiento puro.

Selecciona la AIM de Amazon Linux
Selecciona la AIM de Amazon Linux, preferiblemente el procesador ARM ya que son más baratos los Bursts de procesador

Pasamos a elegir los recursos disponibles para nuestro VPS y si vamos a empezar un proyecto desde cero, no hay más que elegir una máquina con dos núcleos y cuatro gigabytes de RAM. La razón para hacerlo es que no sé cuantos recursos va a consumir y ya que la gran ventaja de usar AWS es que podemos pagar por hora, primero medimos, después escalamos.

Elegimos la t4g.medium
Elegimos la t4g.medium

Para los demás pasos de crear la VPS no voy a dar detalles específicos, ya que van a depender de vuestra configuración de cuenta, cómo puede ser la VPN, el grupo de recursos y la zona donde se aloja. Voy a recomendar que, en el caso de una instancia nueva, siempre se aseguren de que el grupo de seguridad tiene el puerto 22 de SSH abierto solamente a vuestra IP local y no lo dejen abierto al mundo. Deben poner atención a guardar de manera correcta la llave encriptada ***.pem para acceder a la instancia ya que es vital tenerla segura.

Configurar la instancia

Si hicimos todo correctamente vamos a poder entrar en la instancia con SSH usando el siguiente comando

ssh ec2-user@***.***.***.*** -i ~/.ssh/****.pem

Lo primero que vamos a notar es que no está actualizada y que además nos da un error con el idioma en la pantalla de bienvenida:

Pantalla de bienvenida de IAM
Así se ve con el error incluido

Reparamos el error con el idioma antes de seguir ya que puede tener consecuencias a futuro y si lo reparamos ahora nuestra máquina funcionará mejor. Para eso creamos el siguiente archivo:

sudo nano /etc/environment

Y le agregamos este par de líneas: (nótese que estamos incluyendo el inglés de Estados Unidos, pero igual podemos incluir el español. Yo prefiero el inglés ya que al preguntar por los errores en stackoverflow me sale más y mejor ayuda)

LANG=en_US.UTF-8
LC_ALL=en_US.UTF-8

Aquí lo que tenemos que hacer es salir de la sesión (exit) y volver a entrar con SSH. Ahora si hacemos el update e instalamos las herramientas de desarrollador con los siguientes comandos: (yo no uso el -y que se ven en la mayoría de las guías, ya que prefiero comprobar la lista de lo que se va a instalar; me ha sucedido en servidores con NGINX me instala el Apache sin yo solicitarlo y se caen los sitios web etc.)

sudo yum update
sudo yum groupinstall "Development Tools"

Teniendo la máquina actualizada y para terminar la configuración establecemos la hora de sistema. Al igual que al establecer el idioma se trata de un paso crítico que afecta lo que se haga a futuro con la instancia.

Explicando un poco las líneas de comando a ejecutar:

  1. La primera sirve para comprobar que el control de hora existe y está trabajando
  2. La segunda nos sirve para listar las zonas disponibles ( el comando :q lo usas para salir de la lista cuando ya encontraste la que buscas)
  3. En la tercera línea establecemos la zona que queremos, en este caso decimos que estamos en Caracas
  4. Volvemos a comprobar
  5. Reiniciamos el sistema para que todos los servicios corran bajo la misma hora
timedatectl
timedatectl list-timezones
sudo timedatectl set-timezone America/Caracas
timedatectl
sudo reboot

Es importante reiniciar el sistema para estar preparados para instalar nuestro software, obviamente volvemos a entrar con SSH. No se asusten si demora un rato, esta es una instancia pequeña y demora más que las instancias con varios núcleos.

Configuración de software general

AWS provee su sistema operativo con un repositorio de software estable y compilado específicamente para sus instancias. La lista de software disponible la podemos consultar con el siguiente comando:

sudo amazon-linux-extras

La última vez que revisé, esta lista tenía cerca de 60 ítems muy interesantes. Debemos tener en cuenta revisar esta lista cada vez que vayamos a instalar algo que nos falte, recuerda que este software está compilado para esta distribución de Linux con estos procesadores etc. la única forma de lograr (o quizás superar) este rendimiento es compilando uno mismo.

PHP8.0

Lo que necesitamos para Laravel/Octane es PHP8.0 así que la siguiente lista de comandos nos llevará a tenerlo en nuestra máquina

sudo amazon-linux-extras enable php8.0
sudo yum clean metadata
sudo yum install php-cli php-pdo php-xml php-curl php-devel php-mysqlnd php-mbstring php-intl php-bcmath
php -v

Alternativa con PHP8.1

Si creemos que necesitamos las últimas y mejores capacidades de PHP, deberíamos usar Ubuntu ya que PHP8.1 aún no es compatible con AL2 (hay que hacer trampas que no valen la pena)

Supervisor

Aunque parezca opcional necesitamos nuestro amigo el Supervisor. Un ayudante escrito en Python que nos mantiene las rutinas vivas. Sirve para que nuestras colas se muevan y para reiniciar el servidor Octane si se cae y muchas utilidades más.

No pienses que el Cron sustituye al buen Supervisor!

Tenemos que activar el repositorio Epel (CentOS) ya que instalar el Supervisor con PIP puede traernos dolores de cabeza.

sudo amazon-linux-extras install epel
sudo yum install supervisor

Nginx

Se usa mucho el Apache en lugar del Nginx, y vuelvo a decir que en este caso tampoco hay ganador. El Nginx, a mi parecer, es un servidor muy rápido, pero es rápido porque no tiene todas las habilidades del Apache y no tiene las taras del Backward Compatibility, otros dirán que al Nginx le faltan cosas.

En este caso de uso yo prefiero el Nginx por su ligereza, solamente lo usaremos para el certificado SSL, hacer un proxy y poco más. Y para eso ejecutaremos los siguientes comandos:

sudo amazon-linux-extras enable nginx1
sudo yum clean metadata
sudo yum install nginx
sudo systemctl start nginx
nginx -v

Si todo sale bien el comando start no nos dará ningún error y el siguiente comando nos dirá la versión de Nginx que estamos usando.

Pero no sabremos si realmente está sirviendo al mundo, Así que haremos unas configuraciones provisionales para que estemos seguros.

Nos vamos a nuestro grupo de seguridad en AWS, que es nuestro firewall primario y abrimos el puerto 80, en este caso lo abrimos con la versión IPv4 pero yo recomiendo ya ir abriendo la versión IPv6 para lo que usaríamos dos reglas. El IPv6 es cada vez más usado.

Configuración en AWS del grupo de seguridad
Configuración en AWS del grupo de seguridad

Seguimos con la configuración en CloudFlare, en nuestro DNS creamos un link tipo A (proxied) a la IP de nuestra instancia (yo siempre tengo nombres de dominio extras para hacer estas pruebas) y nos vamos al apartado de SSL/TLS para decirle que no queremos ninguna encriptación. Esta es una configuración provisional, al final de esta guía debería quedar con la configuración de encriptación completa.

Configuración de seguridad SSL
Así se verá la configuración de seguridad SSL en CloudFlare

Nos resta añadir la URL del dominio que acabamos de apuntar desde CloudFlare hacia nuestra instancia, y para eso cambiamos una línea en la configuración inicial de nuestro Nginx:

sudo nano /etc/nginx/nginx.conf
#// buscamos la siguiente línea
server_name  _;
#// y la cambiamos agregando nuestro dominio
server_name  **********.***;
#// guardamos con CTRL + X, Y, ENTER

Entiendo que existen muchas opciones para configurar un Nginx a nivel avanzado, pero en este caso nuestro servidor solamente va a correr un servicio de núcleo. Para terminar ejecutamos los siguientes comandos:

sudo nginx -t
sudo systemctl reload nginx

Si quieres aprender más sobre la configuración de Nginx, ver sus infinitas opciones o crear reglas personalizadas a tu gusto, recomiendo este generador de configuraciones de Digital Ocean, que es una maravilla.

Estamos listos para hacer la primera prueba y para eso nos dirigimos a la URL del dominio configurado en CloudFlare usando nuestro navegador.

Bienvenidos a Nginx
Bienvenidos a Nginx

Certificado de seguridad autofirmado

La razón para tener en certificado de seguridad es para evitar ataques del tipo Man-In-The-Middle, no es imposible obtener la IP de nuestra instancia y si se conoce el camino que toma la información desde CloudFlare a AWS el atacante podrá leer los datos que viajan de ida y vuelta.

El certificado es autofirmado ya que, en la mayoría de los casos de uso, no se necesita algo mejor. Claro está, esto depende de la confidencialidad de los datos que estamos moviendo y teniendo en cuenta que este certificado no se expone al usuario final; para eso Cloudflare nos aporta un certificado que es el que se expone.

Un certificado firmado por una autoridad verificadora nos aporta métodos adicionales para estar seguros de que la información no ha sido desencriptada y/o manipulada. Si sientes que es necesario para tu caso, recomiendo que ya tengas un entorno de producción con IP fija y todos los demás requerimientos antes de solicitar uno.

Para crear nuestro par de certificados usamos el siguiente comando:

sudo mkdir /etc/ssl/private
sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt

Para saber todos los detalles de este comando pueden consultar el manual de OpenSSL, lo más importante a notar aquí es que usamos el -nodes para decir que no queremos que se necesite usar clave para usarlo cada vez (impracticable en nuestro caso de uso), al certificado le puse una vida de 10 años (3650 días, me gusta así) y es de 2048 bits de largo.

El programa les hará una serie de preguntas que debemos responder de una manera parecida a la siguiente:

Respuestas a OpenSSL
Respuestas a OpenSSL

Al usar OpenSSL, también debe crear un grupo fuerte de Diffie-Hellman (DH), que se usa para negociar Perfect Forward Secrecy con los clientes.

Puedes hacer esto escribiendo:

sudo openssl dhparam -out /etc/nginx/dhparam.pem 4096

Esto va a tardar un buen tiempo y tratándose de un servidor con un solo núcleo le tomará aproximadamente 20 minutos

La Bruma de los Secretos
La Bruma de los Secretos

Añadir el certificado a Nginx

Empezamos creando un par de archivos que nos ayudarán a guardar la configuración de los certificados que acabamos de crear. En AL esta carpeta no existe, así que la creamos y después creamos el archivo:

sudo mkdir /etc/nginx/snippets
sudo nano /etc/nginx/snippets/self-signed.conf

A este archivo le añadimos un par de lineas que van a servir para que Nginx ubique nuestros certificados:

ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
#// guardamos con CTRL + X, Y, ENTER

A continuación, creará otro fragmento que definirá algunas configuraciones de SSL. Esto configurará Nginx con un sólido conjunto de cifrado SSL y habilitará algunas características avanzadas que ayudarán a mantener su servidor seguro.

Para configurar Nginx SSL de forma segura, adaptaremos las recomendaciones de Cipherlist.eu. Cipherlist.eu es un recurso útil y digerible para comprender la configuración de cifrado utilizada para el software más común. Para esto creamos el siguiente archivo:

sudo nano /etc/nginx/snippets/ssl-params.conf

Y le agregamos la siguiente configuración:

ssl_protocols TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/dhparam.pem; 
ssl_ciphers EECDH+AESGCM:EDH+AESGCM;
ssl_ecdh_curve secp384r1;
ssl_session_timeout  10m;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling off;
ssl_stapling_verify off;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable strict transport security for now. You can uncomment the following
# line if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
#// guardamos con CTRL + X, Y, ENTER

He hecho varios cambios con respecto a lo recomendado en Cipherlist.eu:

  • Ambos stapling los puse en off ya que generan advertencias de que nuestro certificado es autofirmado y eso yo ya lo sé.
  • La línea de la cabecera Strict-Transport-Security la dejo comentada ya que requiere mucha configuración y no es necesaria en la mayoría de los casos de uso, actívala y sigue las reglas si la confidencialidad de tus datos lo amerita.
  • Las tres últimas cabeceras también suelo comentarlas, pero no porque su uso no sea habitual, sino que, las agrego en la configuración del server para poder comentarlas más fácil en caso de necesitar hacer un debug.

Prueba de Nginx con SSL

Vamos a hacer otra configuración intermedia para probar que nuestros certificados estén trabajando bien y que logramos hacer una salida SSL hasta CloudFlare. Estos tests intermedios nos permiten descartar errores que nos pudieran confundir al momento de hacer la configuración final.

Editamos nuestra configuración básica de Nginx usando el siguiente comando:

sudo nano /etc/nginx/nginx.conf

Y sustituimos las directivas server por la siguiente configuración:

server {
   listen       80;
   listen       [::]:80;
   server_name  **********.***;
   return 302 https://$server_name$request_uri;
}
server {
   listen       443 ssl http2;
   listen       [::]:443 ssl http2;

   include snippets/self-signed.conf;
   include snippets/ssl-params.conf;

   server_name  **********.***;
   root         /usr/share/nginx/html;
   index index.html;

   location / {
      try_files $uri $uri/ =404;
   }
}
#// guardamos con CTRL + X, Y, ENTER

Para que se entienda esta configuración les hago los siguientes comentarios:

  • Cómo vemos el servidor que escucha el puerto 80 lo único que va a hacer de ahora en adelante es redireccionar al protocolo https://. Esta redirección 302 se convertirá en 301 más adelante
  • El servidor que escucha el puerto 443 también usa http2, esto permite que se comunique más rápido con CloudFlare
  • Se incluyen los dos archivos de configuración que creamos con anterioridad y que contienen los accesos a los certificados y las llaves
  • Lo demás va a cambiar en los siguientes pasos de esta guía

Probamos la configuración y recargamos nuestro servidor Nginx con esta nueva configuración:

sudo nginx -t
sudo systemctl reload nginx

Ahora abrimos es puerto 443 (https) en nuestro grupo de seguridad de AWS, y debería quedar de esta manera:

Puertos abiertos en el grupo de seguridad de AWS
Puertos abiertos en el grupo de seguridad de AWS

Y le decimos a CloudFlare que queremos que todas las comunicaciones entre el y nuestra instancia estén encriptadas:

Configuración SSL encriptada en Cloudflare
Configuración SSL encriptada en Cloudflare

Esta debería ser nuestra configuración definitiva en CloudFlare, con esto ya estaremos seguros de que de ahora en adelante los ataques tipo Man-In-The-Middle sean sumamente complicados.

Recargamos nuestro navegador web y si todo está correcto automáticamente veremos que aparece un candadito donde antes decía que la conexión no era segura.

Conexión Segura
Conexión Segura
Certificado de seguridad proporcionado por CloudFlare
Certificado de seguridad proporcionado por CloudFlare

Claro está, cuando revisamos el certificado con el que nuestro navegador se conecta con nuestra instancia, podemos notar que es un certificado proporcionado por CloudFlare y no el certificado autofirmado que hemos creado.

Esto es lo correcto ya que este certificado autofirmado es para las comunicaciones entre el CloudFlare y nuestra instancia. CloudFlare es un intermediario y nos «regala» este certificado firmado por ellos para que podamos atender a nuestro público.

Laravel con Octane

Laravel es un framework para aplicaciones web con una sintaxis expresiva y elegante. Proporciona una estructura y un punto de partida para crear su aplicación, lo que le permite concentrarse en crear algo increíble mientras Laravel se preocupa por los detalles.

Laravel se esfuerza por brindar una experiencia de desarrollador increíble al mismo tiempo que brinda características poderosas, como una inyección de dependencia completa, una capa de abstracción de base de datos expresiva, colas y trabajos programados, pruebas unitarias y de integración, y más.

Ya sea que sea nuevo en PHP o tenga años de experiencia, Laravel es el framework que puede crecer contigo.

Composer

Laravel funciona con Composer ya que es el que gestiona todas las dependencias del mismo, tanto cuando requerimos acceder a una dependencia nueva, cómo cuando queremos hacer un update.

La instalación del Composer la tenemos que referir a su sitio web Get Composer, no ponemos todos los comandos a ejecutar, porque hay verificaciones de seguridad que hacer y las mismas cambian cada cierto tiempo.

La única recomendación que voy a dar es que usen el siguiente comando para hacer el setup. Esto les permitirá que el uso del Composer sea más limpio y sencillo:

sudo php composer-setup.php --install-dir=/usr/bin/ --filename=composer
composer --version

Esta utilidad es importante mantenerla siempre actualizada, cómo todo en internet puede ser blanco de hackeos, mi costumbre es que al menos una ves al mes ejecuto el siguiente comando:

sudo composer selfupdate

NodeJS

Necesitamos el servidor NodeJS, principalmente en tiempo de desarrollo y si lo prefieren en tiempo de test. Muchas utilidades están escritas en NodeJS y en el caso de Laravel es comparable a una navaja suiza.

Debemos tener en cuenta que NodeJS no es mantenido de la mejor manera en los repositorios Linux de confianza de AWS, y los repositorios que lo mantienen bien, no lo compilan para la distribución AL. Por eso usaremos un script y no el YUM.

Para instalarlo usaremos los siguientes comandos:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash
. ~/.nvm/nvm.sh
nvm install node
npm -v

Open Swoole

Swoole mejora la eficiencia de sus aplicaciones PHP y lo saca del modelo tradicional sin estado, lo que le permite concentrarse en el desarrollo de productos innovadores a gran escala, incorporando bucles de eventos y programación asíncrona al lenguaje PHP.

¿Porqué no usar el RoadRunner? La verdad nunca he instalado el RoadRunner ya que trae menos opciones. El RoadRunner es más fácil de instalar ya que es un binario escrito en GO y vive consigo mismo, y por esta misma razón puede ser más rápido que el Swoole. Pero, al traer menos opciones no me ha interesado. Si no van a usar las cachés que aporta Swoole y quieren más velocidad en producción no duden en probar el RoadRunner.

Para instalar Swoole necesitamos ejecutar esta serie de comandos:

sudo yum install curl-devel
sudo yum install openssl-devel
sudo yum install php-pear
sudo pecl install openswoole

Al introducir el comando pecl nos hará una serie de preguntas que corresponden a los módulos de Swoole que queremos activar. Yo le doy a todos yes menos al de PostgreSQL que no lo uso, en la mitad de mis casos de uso tampoco instalo el Sockets que está de primero en la lista.

Para que este módulo funcione bien debemos recordar sus dependencias, y la verdad es que depende de casi todo PHP, así que, creamos un archivo de configuración exclusivo para él, y usamos el truco de ponerle 90 al inicio del nombre del archivo. En todas mis pruebas entiendo que con ponerle 40 debería alcanzar, pero si quieren comprobar, hacen un ls a /etc/php.d y vean los números que hay allí, Swoole debería ser el último en cargar. Swoole nos pide poner esta línea en el php.ini, no le hagan caso.

Creamos el archivo con el siguiente comando:

sudo nano /etc/php.d/90-openswoole.ini

Y le agregamos el siguiente contenido:

; Enable openswoole extension module
extension=openswoole
; #// guardamos con CTRL + X, Y, ENTER

Si ejecutamos el comando php -v sólo debería aparecer la versión de PHP y ningún error relacionado al Swoole.

Creamos el proyecto Laravel

Ahora si estamos listos para instalar el Laravel y para eso ejecutamos el siguiente comando con el Composer:

composer create-project laravel/laravel central-app

He usado el nombre de proyecto central-app porque hace sentido a que sea el núcleo de una arquitectura hexagonal.

Entramos a la carpeta y le decimos que requerimos el Octane, instalamos nuestras dependencias de NodeJS, corremos la primera carga de recursos con NPM, e instalamos el Octane:

cd central-app
composer require laravel/octane
npm install
npm install --save-dev chokidar
npm run dev
php artisan octane:install
php artisan vendor:publish

Cuando ejecutamos el comando octane:install le decimos que queremos hacerlo con Swoole (1). Al comando vendor:publish suelo responderle que quiero todo (0).

En el archivo .env hay que agregarle el siguiente par de líneas al final (lo más seguro es que la primera ya exista, pero deben estar las dos). Servir con HTTPS es norma para estos proyectos:

OCTANE_SERVER=swoole
OCTANE_HTTPS=true

Probamos que Laravel/Swoole esté funcionando:

php artisan octane:start

Entonces abrimos otra conexión SSH con nuestra instancia y ejecutamos el siguiente comando para ver que nos responde el Octane:

curl http://127.0.0.1:8000

Y el curl nos dirá:

Bruma de la Felicidad
Bruma de la Felicidad – Código HTML

Configuración final del NGINX

Cómo ya sabemos que el servidor Octane/Swoole está trabajando, pasamos a configurar el NGINX para que haga el proxy-pass. Obviamente no exponemos el Octane directamente, no suele ser una buena práctica, además, el NGINX tiene la solidez comprobada para ello.

Entonces, editamos la configuración de NGINX con el siguiente comando:

sudo nano /etc/nginx/nginx.conf

Y reemplazamos las dos directivas server que tenemos por las siguientes tres directivas:

map $http_upgrade $connection_upgrade {
   default upgrade;
   ''      close;
}
server {
   listen       80;
   listen       [::]:80;
   server_name  **********.***;
   return 301 https://$server_name$request_uri;
}
server {
   listen       443 ssl http2;
   listen       [::]:443 ssl http2;
   include snippets/self-signed.conf;
   include snippets/ssl-params.conf;

   server_tokens off;
   server_name  **********.***;
   root         /home/ec2-user/central-app/public;
   index index.php;
   charset utf-8;

   location /index.php {
      try_files /not_exists @octane;
   }
   location / {
      try_files $uri $uri/ @octane;
   }
   location = /favicon.ico { access_log off; log_not_found off; }
   location = /robots.txt  { access_log off; log_not_found off; }

   access_log off;
   error_log  /var/log/nginx/domain.com-error.log error;
   error_page 404 /index.php;

   location @octane {
      set $suffix "";

      if ($uri = /index.php) {
         set $suffix ?$query_string;
      }

      proxy_http_version 1.1;
      proxy_set_header Host $http_host;
      proxy_set_header Scheme $scheme;
      proxy_set_header SERVER_PORT $server_port;
      proxy_set_header REMOTE_ADDR $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection $connection_upgrade;

      proxy_pass http://127.0.0.1:8000$suffix;
   }
}
#// guardamos con CTRL + X, Y, ENTER

Recargamos el servicio NGINX para que la nueva configuración tome efecto:

sudo nginx -t
sudo systemctl reload nginx

Y al navegar el dominio ya deberíamos ver nuestra pantalla de bienvenida:

Pantalla de Bienvenida
Pantalla de Bienvenida de Laravel

Si llegamos hasta este punto ya tenemos un excelente punto de inicio para todo tipo de proyectos, no solo para crear una aplicación de núcleo para una arquitectura hexagonal, sino también, para los servicios que desplieguen sitios web al público, suministrar data a aplicaciones móviles y paneles de control para manejar la aplicación.

Levantar y cerrar el servidor

Cómo te habrás dado cuenta el servidor sólo está al aire cuando ejecutamos el comando octane:start y aunque este seguirá sirviendo en caso de que cerremos la conexión ssh, no es lo que conviene a la hora de tener un servidor en producción. Para ello tenemos a nuestro amigo el Supervisor.

Para configurar el servicio Supervisor ejecutamos el siguiente comando:

sudo nano /etc/supervisord.conf

y le agregamos la siguiente directiva:

[program:central-app]
process_name=%(program_name)s02d
command=/usr/bin/php -d variables_order=EGPCS /home/ec2-user/central-app/artisan octane:start
autostart=true
autorestart=true
numprocs=1
redirect_stderr=true
stdout_logfile=/home/ec2-user/central-app-worker.log
;#// guardamos con CTRL + X, Y, ENTER

Pueden consultar el manual de Supervisor para estar seguros de todos los significados y si quieren quitar o agregar instrucciones que consideren pertinentes para la misma. Pero pueden estar seguros de que solo necesitarán un proceso abierto.

Esta directiva también pone cómo true los casos de autostart y autorestart, lo que significa que cuando la instancia reinicie o el Octane se cierre por algún error el Supervisor siempre tratará de levantarlo dentro de sus posibilidades.

Cargar los servicios en tiempo de arranque

Si el servidor está en producción lo más normal es que querramos que nuestro servidor inicie el Nginx y el Swoole (a travéz del Supervisord) cuando le hacemos un reboot.

Para eso usaremos los siguientes comandos:

sudo chkconfig nginx on
sudo chkconfig supervisord on

Comandos útiles

Para iniciar y detener nuestro servidor Octane a travez del Supervisor tenemos el siguiente par de comandos:

sudo systemctl start supervisord
sudo systemctl stop supervisord
sudo systemctl restart supervisord

Estos comandos, cómo expliqué, son muy útiles para un servidor en producción, pero a la hora de desarrollar, probar, hacer mantenimiento, etc. siempre será mejor usar el artisan para levantar el servidor.

Además a artisan le podemos pedir que use al NodeJS como informante y en el momento en que hagamos cambios a los archivos reinicie el servidor de forma automática.

Para eso usaríamos el siguiente comando (no se puede usar de esta manera en el Supervisor):

php artisan octane:start --watch

Los siguientes comandos también son útiles para tenerlos en cuenta en tiempo de desarrollo:

php artisan octane:start
php artisan octane:reload
php artisan octane:stop
php artisan octane:status

Consideraciones

Cómo podemos leer en los manuales de Laravel, el Octane, gracias a Swoole o al RoadRunner, mantiene nuestra aplicación en memoria después del primer uso. Lo que significa que para las siguientes llamadas ya no volverá a leer el disco-duro para ejecutar PHP.

De allí viene la gran velocidad que aporta el Octane!

Debemos tener en cuenta esto, ya que, los cambios en código no tendrán efecto inmediato, sólo lo harán cuando el Octane sea reiniciado por los métodos que tenemos disponibles.

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.