Guía de tecnologías

Instalar Strapi en Rocky Linux 9 con Nginx y PM2

7 min read DevOps Actualizado 13 Oct 2025
Instalar Strapi en Rocky Linux 9 con Nginx y PM2
Instalar Strapi en Rocky Linux 9 con Nginx y PM2

Descripción rápida

Strapi es un CMS sin cabeza (headless) de código abierto construido en JavaScript. No incluye frontend por defecto; expone una API que permite crear sitios con frameworks como React o Next.js. Su panel de administración y la API son extensibles mediante plugins, y ofrece control detallado de permisos de usuarios.

Imagen introductoria:

Alt: Diagrama de arquitectura con Strapi, base de datos y proxy inverso Nginx

Variantes de búsqueda útiles

  • instalar Strapi en Rocky Linux
  • Strapi con PostgreSQL y Nginx
  • desplegar Strapi en producción
  • Strapi PM2 Nginx SSL

Requisitos previos

  • Un servidor con Rocky Linux 9, mínimo 2 GB RAM y 1 vCPU.
  • Un usuario no root con privilegios sudo.
  • Un nombre de dominio totalmente cualificado (FQDN), por ejemplo strapi.example.com.
  • Sistema actualizado y paquetes básicos instalados.

Ejecuta actualización del sistema:

$ sudo dnf update

Instala utilidades necesarias:

$ sudo dnf install wget curl nano unzip yum-utils -y

Algunas pueden ya estar presentes.

Resumen de la metodología (mini-methodology)

  1. Abrir puertos y configurar FirewallD.
  2. Instalar y configurar PostgreSQL 15.
  3. Instalar Node.js LTS (v18) y crear el proyecto Strapi.
  4. Ejecutar Strapi en producción con PM2.
  5. Instalar Nginx como proxy inverso y obtener SSL con Certbot.
  6. Aplicar endurecimiento básico de seguridad y rutinas de backup.

1. Configurar el cortafuegos

Rocky Linux usa Firewalld. Comprueba el estado:

$ sudo firewall-cmd --state
running

Lista los servicios permitidos en la zona pública (por defecto):

$ sudo firewall-cmd --permanent --list-services

Salida esperada (ejemplo):

cockpit dhcpv6-client ssh

Permite HTTP y HTTPS:

$ sudo firewall-cmd --permanent --add-service=http
$ sudo firewall-cmd --permanent --add-service=https
$ sudo firewall-cmd --reload

Verifica de nuevo:

$ sudo firewall-cmd --permanent --list-services

Salida esperada:

cockpit dhcpv6-client http https ssh

Importante: Evita exponer puertos de administración (p. ej. 1337) al público en producción. Usa Nginx para proxy y TLS.

2. Instalar y configurar PostgreSQL

Strapi funciona con PostgreSQL 11+. Usaremos PostgreSQL 15.

Añade la clave GPG del repositorio y el repositorio:

$ curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | sudo tee /usr/share/keyrings/postgresql-key.gpg >/dev/null
$ sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

Deshabilita el módulo integrado y instala PostgreSQL 15:

$ sudo dnf -qy module disable postgresql
$ sudo dnf install -y postgresql15-server

Inicializa, habilita y arranca el servicio:

$ sudo /usr/pgsql-15/bin/postgresql-15-setup initdb
$ sudo systemctl enable postgresql-15
$ sudo systemctl start postgresql-15
$ sudo systemctl status postgresql-15

Salida de ejemplo del estado del servicio (no modifiques):

? postgresql-15.service - PostgreSQL 15 database server
     Loaded: loaded (/usr/lib/systemd/system/postgresql-15.service; enabled; vendor preset: disabled)
     Active: active (running) since Wed 2023-02-01 13:21:27 UTC; 41min ago
       Docs: https://www.postgresql.org/docs/15/static/
    Process: 53088 ExecStartPre=/usr/pgsql-15/bin/postgresql-15-check-db-dir ${PGDATA} (code=exited, status=0/SUCCESS)
   Main PID: 53093 (postmaster)

Crea la base de datos y el usuario para Strapi:

$ sudo -i -u postgres psql
postgres=# CREATE DATABASE strapidb;
postgres-# CREATE USER strapiuser WITH PASSWORD 'Your_Password';
postgres-# ALTER DATABASE strapidb OWNER TO strapiuser;
postgres-# \q

Prueba las credenciales:

$ psql --username strapiuser --password --host localhost strapidb
Password:
psql (15.1)
Type "help" for help.

strapidb=>

Nota: Sustituye ‘Your_Password’ por una contraseña fuerte y almacénala de forma segura.

3. Instalar Node.js (versión LTS)

Rocky Linux incluye Node v16; instalaremos la LTS (v18 en el momento del tutorial).

Obtén el instalador de NodeSource e instala Node.js:

$ curl -fsSL https://rpm.nodesource.com/setup_18.x | sudo bash -
$ sudo dnf install nodejs -y

Verifica la versión:

$ node -v
v18.13.0

4. Instalar Strapi

Crea el proyecto Strapi con npx:

$ npx create-strapi-app@latest howtoforge-project
Need to install the following packages:
  [email protected]
Ok to proceed? (y) y

Selecciona “Custom” y responde los parámetros para PostgreSQL:

? Choose your installation type Custom (manual settings)
? Choose your preferred language JavaScript
? Choose your default database client postgres
? Database name: strapidb
? Host: 127.0.0.1
? Port: 5432
? Username: strapiuser
? Password: Your_Password
? Enable SSL connection: No

Puedes optar por JavaScript o TypeScript según tus preferencias.

Una vez creado el proyecto, construye la UI de administración e inicia Strapi para pruebas locales:

$ cd howtoforge-project
$ NODE_ENV=production npm run build
$ node ~/howtoforge-project/node_modules/.bin/strapi start

Abre temporalmente el puerto 1337 si necesitas acceder directamente (solo para pruebas locales):

$ sudo firewall-cmd --permanent --add-port=1337/tcp
$ sudo firewall-cmd --reload

Accede a http://:1337 para ver la app. Cuando termines, detén el servidor con Ctrl+C y quita la regla del firewall:

$ sudo firewall-cmd --permanent --remove-port=1337/tcp
$ sudo firewall-cmd --reload

Pantalla de ejemplo (Strapi arrancado en modo desarrollo):

Strapi CMS Home

Alt: Página principal de Strapi mostrando la interfaz inicial en modo desarrollo

5. Ejecutar Strapi en producción con PM2

PM2 permite ejecutar Node.js como servicio y crear integración con systemd.

Instala PM2 globalmente:

$ sudo npm install pm2@latest -g

Crea el archivo de configuración PM2 (ecosystem.config.js). Abre el editor:

$ sudo nano ecosystem.config.js

Pega el contenido (modifica la ruta y credenciales según tu usuario/proyecto):

module.exports = {
  apps: [
    {
      name: 'strapi',
      cwd: '/home/navjot/howtoforge-project',
      script: 'npm',
      args: 'start',
      env: {
        NODE_ENV: 'production',
        DATABASE_HOST: 'localhost',
        DATABASE_PORT: '5432',
        DATABASE_NAME: 'strapidb',
        DATABASE_USERNAME: 'strapiuser',
        DATABASE_PASSWORD: 'Your_Password',
      },
    },
  ],
};

Guarda y arranca con PM2:

$ pm2 start ecosystem.config.js

Salida de ejemplo de PM2 (resumen, no editar):

[PM2] App [strapi] launched (1 instances)

Haz que PM2 se inicie con el sistema:

$ pm2 startup

Copia y ejecuta el comando que te indique (puede variar por usuario), por ejemplo:

$ sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u navjot --hp /home/navjot

Guarda la lista de procesos para restaurarla al reinicio:

$ pm2 save
[PM2] Successfully saved in /home/navjot/.pm2/dump.pm2

Nota: Cambia ‘navjot’ por tu usuario. PM2 resucitará procesos tras reinicios si se ha ejecutado el comando startup y pm2 save.

6. Instalar Nginx como proxy inverso

Instala el repositorio oficial de Nginx y la versión estable:

$ sudo nano /etc/yum.repos.d/nginx.repo

Pega:

[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

Instala y arranca Nginx:

$ sudo dnf install -y nginx
$ sudo systemctl enable nginx --now
$ sudo systemctl status nginx

Verifica la versión:

$ nginx -v
nginx version: nginx/1.22.1

7. Obtener SSL con Certbot (Let’s Encrypt)

Para Certbot usaremos snapd. Instala EPEL, snapd y Certbot:

$ sudo dnf install -y epel-release
$ sudo dnf install -y snapd
$ sudo systemctl enable snapd --now
$ sudo snap install core && sudo snap refresh core
$ sudo ln -s /var/lib/snapd/snap /snap
$ echo 'export PATH=$PATH:/var/lib/snapd/snap/bin' | sudo tee -a /etc/profile.d/snapd.sh
$ sudo snap install --classic certbot
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
$ certbot --version

Genera el certificado para tu dominio (sustituye correo y dominio):

$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d strapi.example.com

Los certificados quedarán en /etc/letsencrypt/live/strapi.example.com.

Genera Diffie–Hellman para mayor seguridad:

$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096

Prueba la renovación automática con una ejecución de prueba:

$ sudo certbot renew --dry-run

8. Configurar Nginx como proxy TLS hacia Strapi

Ajusta nginx.conf para evitar errores de nombres largos:

$ sudo nano /etc/nginx/nginx.conf

Añade antes de include /etc/nginx/conf.d/*.conf;:

server_names_hash_bucket_size  64;

Crea el bloque de servidor para Strapi:

$ sudo nano /etc/nginx/conf.d/strapi.conf

Pega (sustituye strapi.example.com por tu dominio):

server {
  # Redirect any http requests to https
  listen         80;
  listen         [::]:80;
  server_name    strapi.example.com;
  return 301     https://$host$request_uri;
}

server {
  listen                    443 ssl http2;
  listen                    [::]:443 ssl http2;
  server_name               strapi.example.com;

  access_log                /var/log/nginx/strapi.access.log;
  error_log                 /var/log/nginx/strapi.error.log;

  # TLS configuration
  ssl_certificate           /etc/letsencrypt/live/strapi.example.com/fullchain.pem;
  ssl_certificate_key       /etc/letsencrypt/live/strapi.example.com/privkey.pem;
  ssl_trusted_certificate   /etc/letsencrypt/live/strapi.example.com/chain.pem;
  ssl_protocols             TLSv1.2 TLSv1.3;

  ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384';
  ssl_prefer_server_ciphers on;
  ssl_session_cache         shared:SSL:50m;
  ssl_session_timeout       1d;

  # OCSP Stapling ---
  # fetch OCSP records from URL in ssl_certificate and cache them
  ssl_stapling on;
  ssl_stapling_verify on;
  ssl_dhparam /etc/ssl/certs/dhparam.pem;

  location / {
    proxy_set_header        X-Real-IP $remote_addr;
    proxy_set_header        X-Forwarded-Proto $scheme;
    proxy_set_header        X-Forwarded-Host $http_host;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass              http://127.0.0.1:1337;
  }
}

Verifica la sintaxis y reinicia Nginx:

$ sudo nginx -t
$ sudo systemctl restart nginx

Ahora accede a https://strapi.example.com.

Pantalla de ejemplo en producción:

Strapi Production Home

Alt: Página de Strapi en modo producción con la interfaz pública accesible por HTTPS

Accede a la administración en https://strapi.example.com/admin para crear el usuario administrador:

Strapi Admin User Create Page

Alt: Formulario para crear el usuario administrador de Strapi

Tras crear la cuenta verás el panel de control:

Strapi Admin Dashboard

Alt: Panel de administración de Strapi mostrando contenido y secciones principales

9. Actualizar Strapi

Para actualizar realiza los siguientes pasos básicos:

  1. Detén la app con PM2:
$ cd ~
$ pm2 stop ecosystem.config.js
  1. Edita package.json en el directorio del proyecto y actualiza las versiones de los paquetes de Strapi a la última estable.
$ cd howtoforge-project
$ nano package.json

Ejemplo (actualiza los números a la versión más reciente):

"dependencies": {
  "@strapi/strapi": "4.5.5",
  "@strapi/plugin-users-permissions": "4.5.5",
  "@strapi/plugin-i18n": "4.5.5",
  "pg": "8.6.0"
},
  1. Instala, reconstruye y reinicia:
$ npm install
$ NODE_ENV=production npm run build
$ cd ~
$ pm2 start ecosystem.config.js

Nota: Revisa las notas de migración oficiales antes de actualizar versiones mayores. Haz backup de la base de datos y del directorio ./config.

Verificación y pruebas de aceptación

Criterios de aceptación:

  • El dominio https://strapi.example.com devuelve el sitio usando TLS válido.
  • El panel /admin permite iniciar sesión con el administrador creado.
  • PM2 muestra el proceso strapi como online tras reinicio del servidor.
  • Renovación de certificado mediante certbot renew --dry-run funciona sin errores.

Pruebas rápidas:

curl -I https://strapi.example.com
pm2 status
sudo certbot renew --dry-run
psql --username=strapiuser --host=localhost strapidb -c "SELECT 1;"

Seguridad y endurecimiento

  • No expongas el puerto 1337 públicamente; siempre usa proxy TLS.
  • Usa contraseñas fuertes y, si es posible, autenticación basada en certificados para conexiones administrativas.
  • Habilita un firewall a nivel de red y reglas de fail2ban para intentos de acceso SSH.
  • Restringe el acceso a PostgreSQL mediante pg_hba.conf y redes permitidas.
  • Mantén sistema y dependencias actualizadas; evalúa usar escáneres de vulnerabilidades.

Copias de seguridad y recuperación

  • Base de datos: configura dumps regulares con pg_dump y retén en almacenamiento externo.
  • Archivos: haz tar/rsync del directorio de proyecto y carpeta ./public si la usas.
  • PM2: usa pm2 save y automatiza dumps antes de actualizaciones.

Proceso de recuperación rápido:

  1. Restaurar dump en PostgreSQL.
  2. Restaurar directorio del proyecto.
  3. npm install y NODE_ENV=production npm run build.
  4. pm2 resurrect o pm2 start ecosystem.config.js.

Cuándo falla y soluciones rápidas (counterexamples)

  • Error: 502 Bad Gateway tras configurar Nginx: revisa que PM2 tenga la app corriendo en 127.0.0.1:1337 y que proxy_pass apunte a la dirección correcta.
  • Error de conexión a la DB: verifica credenciales en environment variables y que PostgreSQL acepte conexiones locales.
  • Certbot no puede validar el dominio: comprueba DNS y que el puerto 80 esté accesible mientras Certbot valida.

Checklist por rol

Administrador de sistema:

  • Crear usuario no root con sudo
  • Abrir puertos HTTP/HTTPS en FirewallD
  • Instalar y asegurar PostgreSQL Desarrollador backend:
  • Generar proyecto Strapi con DB configurada
  • Verificar endpoints y roles en panel admin DevOps:
  • Configurar PM2 y systemd startup
  • Configurar Nginx con TLS y OCSP stapling
  • Implementar backups y monitorización

Mapa de decisiones rápido

  • Necesitas hosting gestionado y no quieres mantener infra: considera Strapi Cloud o proveedores PaaS.
  • Quieres control total y costes previsibles: seguir este despliegue con PM2 + Nginx.

Conclusión

Has instalado Strapi en Rocky Linux 9 con PostgreSQL 15, Node.js v18, PM2 y Nginx con TLS. A partir de aquí puedes:

  • Crear colecciones y tipos de contenido en el panel de administración.
  • Integrar un frontend consumiendo la API REST o GraphQL.
  • Añadir plugins y configurar roles y permisos según tus necesidades.

Resumen final:

  • Mantén backups y pruebas de restauración.
  • Revisa notas de seguridad y actualizaciones de Strapi antes de actualizar.
  • Automatiza renovación de certificados y arranque de PM2.

Si tienes preguntas concretas sobre un paso o error, indica el comando que estás ejecutando y la salida para poder ayudarte.

Autor
Edición

Materiales similares

Podman en Debian 11: instalación y uso
DevOps

Podman en Debian 11: instalación y uso

Apt-pinning en Debian: guía práctica
Sistemas

Apt-pinning en Debian: guía práctica

OptiScaler: inyectar FSR 4 en casi cualquier juego
Guía técnica

OptiScaler: inyectar FSR 4 en casi cualquier juego

Dansguardian + Squid NTLM en Debian Etch
Redes

Dansguardian + Squid NTLM en Debian Etch

Arreglar error de instalación Android en SD
Android

Arreglar error de instalación Android en SD

Conectar carpetas de red con KNetAttach
Redes

Conectar carpetas de red con KNetAttach