Parte 3 Stack Lemp Roundup Gitea y Quarkus

El día de hoy terminaré de instalar este servidor Nginx (LEMP) al tiempo que actualizo en otro ya existente, los dos sobre Debian 13. Hay una relación importante entre la memoria y el consumo de ella, y por qué usar Gitea. Joel Spolsky, antiguo programador de Microsoft, hablaba de las doce preguntas y una de ellas tenía que ver con builds / compilaciones de un solo paso. Creo que una vez establecido el front end (en este caso React) no necesitas hacerle muchos cambios, pero sí es común que establezcas nuevas funcionalidades «bajo el capó», en backend, que no se ven. Y en eso Quarkus brilla. Además, usa mucho menos memoria que Spring Boot.

Sin embargo, tengo que hacer una reflexión personal. Casi siempre mi trabajo ha sido arreglar desastres. A veces programando de cero, a veces dando mantenimiento a cosas indescriptibles. He visto consumos gigantescos de hosts que no servían, incluyendo transas de las personas de sistemas. Tecnologías corruptas o mal empleadas.

Usando una metáfora, yo no necesito un iPhone. Uso un teléfono Motorola G31 de unos 150 USD. La principal razón es porque tiene el encendido por huella dactilar, sin presionar botón lateral. Un iPhone o iPad solo me interesaría por las fotos de alta calidad, por documentos de juzgados.

Sin embargo, a nadie lo corrían hace años por contratar IBM. Ahora es algo parecido con Azure y AWS. Principalmente en entorno Azure he visto que universidades públicas reciben dinero para promover Azure y sus recién egresados piensan que es lo único. Usando una metáfora… no todos necesitan un Samsung de alta gama o un iPhone. Lo mismo pasa con Azure y AWS.

En este entendido, a veces el presupuesto o vivir en la punta del cerro, aunque puedas y lo quieras, te complican muchísimo comprar un teléfono de alta gama. Y para estar con línea de cobre, sin línea óptica. Otro ejemplo sería que salir con un billete de 1000 MXN a la calle es como traer nada, porque cambiarlo o que te lo acepten es difícil, y debe ser horrible salir a la calle con 3000 pesos en monedas de a peso. Como dato particular, en viajes a la playa solía usar una bolsa agarrable a la pierna, llena de monedas de 10 pesos, el equivalente de 3000 MXN, y se podía mojar.

Muchos de tus clientes de correo o de host son personas que usan pocos recursos. No falta la princesa o el princeso que si no es iPhone 25 no te mira a los ojos. Pues yo creo que salir a la calle con billetes de 100 y 200 te da movilidad. Se trata de resolver un problema, y Quarkus es maravilloso en eso. Pero si sumas su bajo consumo de memoria con relación a Spring Boot, te encuentras con la facilidad de implementación que hablaba Spolsky. Y eso solo te lo da en Web React / Quarkus, o PHP puro.

Asi que empecemos:

Los 3 puntos clave de hoy para Gitea:

  1. Proxy Inverso (Nginx): Despedirnos del puerto 3000 para entrar por git.tu-dominio.com.
  2. SSL Final: Extender el certificado de Certbot para que el subdominio de Gitea y la ruta /app de React sean inexpugnables.
  3. Ajuste del app.ini: Configurar internamente a Gitea para que reconozca su nueva identidad HTTPS y cerrar el puerto en el firewall.

Es como poner carrocería y blindaje al servidor. Digamos que es  un hardening de nivel medio.

Quarkus es Robusto, independiente y eficiente. Como todo buen devops. =)

Ojo con dos errores comunes por ser wordpress:

  • Las Comillas: Al copiar y pegar en editores como WordPress, las comillas rectas » a veces se convierten en curvas “. Asegúrate de que en los bloques de código (especialmente el de Java y Nginx) se mantengan las comillas rectas, o el compilador dará error.
  • Permisos de Ejecución: En la parte donde creas el servicio systemd, debes asegurarte de que el archivo mvnw tenga permisos de ejecución (chmod +x mvnw). Es un detalle que a veces olvidamos.

 

El Backend : Quarkus

Trataré  de explicar y demostrar por qué prefiero la solidez de Java en quarkus sobre Jakarta , Javelin  y sobre todo sobre el «caos» de Node.js con Express. Lo que sigue es:

  1. Instalar el SDK: GraalVM o OpenJDK 21/25 (para ser modernos y eficientes). Se tarda en compilar
  2. Compilación Nativa: Mostrar cómo Quarkus puede arrancar en milisegundos y consumir una miseria de RAM comparado con Spring Boot tradicional.
  3. NO hago la Conexión a la Base de Datos: Ligar Quarkus con la MariaDB que ya instalamos en la Parte 1.
  4. Al final hay un «anexo» Sobre quarkus en desarrollo. Aquí lo verás en modo DEV. Si lees el anexo que esta al final entiendes porqué. Anexo «Uso de Quarkus en producción usando GraalVM».

El hardening o costuras:

Una vez que Quarkus esté arriba, el reto técnico  es:

  1. Proxy Inverso para la API: Hacer que tu-dominio.com/api apunte a Quarkus, mientras /app sigue apuntando a React.
  2. CORS y Seguridad: Configurar el búnker para que solo tu React pueda hablar con tu Quarkus.
  3. Automatización (CI/CD Local)
    • Como ya tienes Gitea, el siguiente paso de «maestro» es configurar Gitea Actions. No lo explico aquí.
    • Hacer que cuando subas código a tu Gitea, el servidor compile Quarkus y React automáticamente y los ponga en producción sin que tú muevas un dedo.
    • Eso es ser Full Stack/DevOps en 2026.

Importante Paso previo a GITEA Quarkus.

Vamos a crear un subdominio, git.tu-dominio.com , la mayoría usa www.tu-dominio.com ,pero como hay cientos de empresas que venden dominios, a ti te corresponde encontrar como hacer un registro A , que apunte a la dirección IP. Como diría Dorothy de el Mago de Oz, creo que ya no estamnos en cpanel Toto.

No prosigas hasta que hayas hecho ese paso y hayan pasado unos diez minutos.

Ya que estés listo, hay que crear un archivo nuevo.

nano /etc/nginx/sites-available/git.tu-dominio.com

Y ahi pones esto:

server {
listen 80;
server_name git.tu-dominio.com;

# Log de errores para debuggear si algo falla
access_log /var/log/nginx/gitea_access.log;
error_log /var/log/nginx/gitea_error.log;

location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# Ajuste para subidas de archivos grandes (ej. commits pesados)
client_max_body_size 512M;
}
}

TIP IMPORTANTE

Notarás que puse client_max_body_size. Puedes ajustarlo, pero es vital. Si no lo pones, cuando quieran subir un repositorio de más de 1MB por HTTP, Nginx les va a escupir un error 413 Request Entity Too Large. Un Devops de 2026 no deja que un límite por defecto arruine su Gitea. En lo personal creo que 256 es mas que suficiente pero  el 512 no sobra.

Que hacemos para enlazar git.tudominio a gitea?

  • Enlazar el archivo: ln -s /etc/nginx/sites-available/git.tu-dominio.com /etc/nginx/sites-enabled/
  • Validar y Reiniciar: nginx -t && systemctl reload nginx
  • Certbot (El momento de la verdad): certbot –nginx -d git.tu-dominio.com (Aquí Certbot leerá tu archivo de Nginx y le inyectará automáticamente las líneas de SSL).
  • Por precaución y por el manejo de puertos lo mejor es probar nuevamente el dry run de cert bot.
    • certbot certonly –dry-run -d git.tu-dominio.com
    • Lo mas seguro es que te de tres o mas opciones. Selecciona la que dice Nginx
      • las versiones más recientes de Certbot aplican el Redirect automáticamente. Antes te preguntaba si querías redirgir automáticamente (Option 2 por defecto) o que, al detectar que ya tienes otros sitios con Redirect, asuma que quieres lo mismo para mantener la coherencia del búnker.

Prueba ahora con http://git.tu-dominio.com y debe abrir normal y con candado verde. VERIFICA que el certificado sea valido.

Que tenemos que hacer ?

Bueno….

en este momento vives en una ip. Lo que significaque si te mueves de zona por ejemplo de Mexico a Estambul,   i de useast a amsterdam en AWS, va sa tener problemas. Vamosa ligar Gitea al nombre del dominio. Además clonar, respaldar o manejar repositorios en direcciones IP y no dominios, es mala práctica además de incómodo.

Vamos a decirle quién es oficialmente.

  • Abre el archivo de configuración: nano /etc/gitea/app.ini
  • Busca la sección [server] y edita estas líneas: (Asegúrate de que tengan el dominio y el HTTPS)
  • [server]
    DOMAIN = git.tu-dominio.com
    HTTP_PORT = 3000
    ROOT_URL = https://git.tu-dominio.com/
    DISABLE_SSH = false
    SSH_DOMAIN = git.tu-dominio.com
    SSH_PORT = 22
    Guarda (Ctrl+O, Enter) y Sal (Ctrl+X).
  • Reinicia Gitea para que lea su nueva identidad: systemctl restart gitea
  • Y como recordarás tenemos el puerto 3000 abierto. Ahora hay cerrarlo, o «colgar el teléfono» porque yaestamosusando el puerto 443 por el SSL
    • ufw delete allow 3000/tcp # Cierra el puerto en el firewall
    • ufw status # Verifica el estado: 

ahora Solo se entra por el subdominio seguro. https://git.tu-dominio.com

¿Ya reiniciaste Gitea? Entra a la web y verifica que en la parte inferior o en los enlaces de clonar ya aparezca tu dominio con HTTPS. Si eso está listo, ya quedó Gitea.

Ahora vamos con Quarkus.

Instalación de Quarkus

Para instalar Quarkus de forma profesional en un entorno Debian (sin llenar el servidor de basura), lo ideal es usar SDKMAN!. Es la herramienta estándar para desarrolladores Java/Quarkus porque te permite gestionar versiones sin pelearte con las variables de entorno manualmente.

Aquí tienes los pasos para dejar el motor listo:

1. Instalar SDKMAN!

Primero, necesitamos zip y unzip (si no los tienes) para que SDKMAN pueda trabajar:

  • apt update && apt install zip unzip curl -y
  • curl -s «https://get.sdkman.io» | bash # instalamos el gestor sdkman
  • source «$HOME/.sdkman/bin/sdkman-init.sh» # la comillas son importantes
  • sdk version # te vaa dar un numero y significaque ya estamos del otro lado y esta instalado.
  • sdk help # probar que si corrió la instalación.

2. Instalar el Java adecuado (El corazón)

Para Quarkus en 2026, lo ideal es Java 21. Vamos a instalar la versión de Temurin (de la fundación Eclipse), que es de las más estables y ligeras:

  • sdk install java 21.0.2-tem # se va a tardar mas que otros procesos …..
  • usa en terminal:    java -version # verificar que todo esté en orden va espacio entre java y version
    • Si estas en una maquina antigua no instalacion limpiapuede ser ue necesites
      • sdk use java 21.0.2-tem
      • Salir y volver a entrar a SSH. Recuerda usar java – version
  • Si obtienes «OpenJDK Runtime Environment», Java ya esta instalado

3. Instalar Quarkus CLI

Ahora sí, instalamos la herramienta de línea de comandos de Quarkus que nos permitirá seguir el proceso. Ejecuta:

  • Ejecuta: sdk install quarkus
  • Verifica con: quarkus –version

Nota Plus. Tengo mis propios medios de verificar servidores, pero prefiero no ponerlos en publico, aisque para fines de este tutorial, haré un monitor de memoria y espacio en uso, usando quarkus y react. Normalmente clonaría uno de mis repositorios privados pero en este caso vamos a hacerlo de cero y simplificado.

3.1 Crear el proyecto «Monitor-Instance»

Es posible que el código este funcionando en un vps, docker, servidor, pero es mas exacto decir que es instancia de Quarkus, y es indiferente o agnóstico a si es Nginx o apache. Así que llamaremos a este proyecto monitor-quarkus-instance y lo pondremos en la carpeta de git que creamos antes.

RECORDATORIO HICIMOS ESTO:

mkdir -p /home/git/proyectos

cd /home/git/proyectos

Vamos a crear el esqueleto pero tenemos que considerar JSON que es lo que consume REACT. Eso lo hacemos con el –extension=resteasy-jackson que ves abajo.

1. Crear el proyecto con el nombre correcto Ubícate en la carpeta que definiste para tus proyectos de Git y genera la app:

  • cd /home/git/proyectos
  • quarkus create app monitor-quarkus-instance –extension=resteasy-jackson
  • cd monitor-quarkus-instance
    • Notaras que te dice sucessfile generated

2. Crear el Recurso (El código del monitor)

Vamos a crear el archivo que lee el «hardware» del servidor. A ti como Admin te interesa ver memoria y uso de disco. Quarkus por defecto crea un GreetingResource.java, vamos a sustituirlo por nuestro monitor:

 

Ojo con esto. CUalquier script kiddie va a estar buscando «stats». Yo usaria un lugar no muy comun, como mis iniciales que son aoa, asi que uso en este ejemplo statsaoa o puede ser statsTUNUMERODEMPLEADO. La lógica es que un bot de escaneo va a buscar /stats, /admin, o /health, pero si lo renombras a algo que solo tú sabes, como statsaoa o un token tipo stats2026aoa, acabas de quitarle el 99% del ruido de los logs de ataques automáticos.

Tienesque tener cuidado que no desaparezcan las comillas. es un error comun.

  • nano src/main/java/org/acme/MonitorResource.java

Pega este código (optimizado para ser ligero):

package org.acme;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

@Path(«/statsaoa»)
public class MonitorResource {

@GET
@Produces(MediaType.APPLICATION_JSON)
public Map<String, String> getStats() {
Map<String, String> stats = new HashMap<>();

// Fecha y hora actual (Instancia)
stats.put(«hora», LocalDateTime.now().format(DateTimeFormatter.ofPattern(«yyyy-MM-dd HH:mm:ss»)));

// Uso de memoria RAM (comando free)
stats.put(«memoria», executeCommand(«free -m | awk ‘NR==2{printf \»%.2f%%\», $3*100/$2 }'»));

// Espacio ocupado en disco (comando df)
stats.put(«disco», executeCommand(«df -h / | awk ‘NR==2{print $5}'»));

return stats;
}

private String executeCommand(String command) {
try {
// El comando debe ir entre comillas
Process process = Runtime.getRuntime().exec(new String[]{«/bin/sh», «-c», command});
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
return reader.readLine();
} catch (Exception e) {
return «Error: » + e.getMessage();
}
}
}

3. Configurar la seguridad (CORS) y el mayordomo del Búnker

Antes de lanzar el motor, necesitamos que Quarkus sepa que tiene permiso para hablar con nuestro Front-end. En el mundo de 2026, los navegadores bloquean cualquier petición que no esté explícitamente autorizada.

Edita el archivo de propiedades:

* nano src/main/resources/application.properties

Añade estas líneas (esto es el equivalente a darle una «lista de invitados» a tu portero o mayordomo):

Properties Pega tal cual

# Permitir que React consuma la API desde tu dominio
quarkus.http.cors=true
quarkus.http.cors.origins=https://tu-dominio.com

4 Hora de probarlo.

Es hora de probar si nuestro código realmente lee el hardware. Ejecuta el modo de desarrollo:

  •  cd /home/git/proyectos/monitor-quarkus-instance
  • chmod +x mvnw # da permisos de ejecución
    • ls -l mvnw  # debes ver color verde una x de  ejecutable en permisos
  • ./mvnw quarkus:dev

(Si es la primera vez, verás que descarga las dependencias. Es el proceso de armar la maquinaria). Una vez que veas que el sistema está listo, abre otra terminal y lanza un ataque de prueba (un simple curl):

Con la letra q te regresa saliendo del shell, al modo terminal. Y debes ver un BUILD SUCCESS en eltras verdes.

Pero no  vas poder probarlo por un detalle simple. Solo esta vivo mientras el modo dev esta presente. Asi que lo normal sería lanzar una segunda terminal de root, pero aveces, por ejemplo vultr no te deja. Asi que lo mejor es que uses powershell o un terminal y hagas desde allí

  • ssh root@tu-ip-de-vultr
    • ahi si puedes abrir las ventanas que quieras. pone el password y ejecuta esto
  • curl http://localhost:8080/statsaoa

Si te responde un JSON con la memoria, el disco y la hora, felicidades: has creado un backend independiente que no le debe nada a nadie.

Y esto es lo que vas a recibir, mas o menos…

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
root@xxxxxx:~# curl http://localhost:8080/statsaoa
{«memoria»:»43.26%»,»hora»:»2026-01-02 20:27:56″,»disco»:»17%»}root@xxxxxx:~#

Ahora si lo que falta es cerrar la puerta. Cuando entras a tu casa, luego cierras la puerta no ?

Hacer seguro el cierre de puertas:

Como ahora ya sabemos que Quarkus responde en el 8080, vamos a cerrar ese puerto al mundo y dejar que solo Nginx hable con él.

Edita tu archivo de Nginx: nano /etc/nginx/sites-available/tu-dominio.com

Añade esto dentro del bloque server: OJO : La barra después del 8080 es super importante hazme caso y dame las gracias después.

Nginx

location /api/ {
proxy_pass http://localhost:8080/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
} # <— No olvides cerrar la llave

Y despues:

  • systemctl reload nginx # recargamos nginx

Y el final es ?

Un programador de FRONT END haría esto en un widget

import React, { useState, useEffect } from ‘react’;

const MonitorAOA = () => {
const [stats, setStats] = useState(null);

useEffect(() => {
const fetchStats = async () => {
try {
const response = await fetch(‘https://tu-dominio.com/api/statsaoa’);
const data = await response.json();
setStats(data);
} catch (err) {
console.error(«Instancia no responde», err);
}
};
fetchStats();
const timer = setInterval(fetchStats, 30000); // Actualiza cada 30 segundos
return () => clearInterval(timer);
}, []);

if (!stats) return <div>Conectando con la instancia…</div>;

return (
<div style={{ border: ‘1px solid #333′, padding: ’15px’, borderRadius: ‘5px’, backgroundColor: ‘#000’, color: ‘#0f0’ }}>
<h4>SISTEMA DE MONITOREO AOA</h4>
<p>RAM: {stats.memoria}</p>
<p>DISCO: {stats.disco}</p>
<small>Sincronizado: {stats.hora}</small>
</div>
);
};

export default MonitorAOA;

Yo haría algo para que quarkus estuviera siempre activo. Pero tiene sus… peligros y lo que me da de comer. Eso va al final en el anexo.

Para que todo este siempre activo Cómo dejarlo encendido permanentemente (Nivel DevOps)

Para esto usaremos systemd, que es el administrador de procesos de Debian. Es lo mismo que mantiene vivos a Nginx y MariaDB.

1. Crea el archivo de servicio:

Bash

nano /etc/systemd/system/monitor-quarkus.service
2. Pega este contenido (Ajusta tus rutas):

[Unit]
Description=Monitor Quarkus Instance AOA
After=network.target

[Service]
Type=simple
User=root
# Ruta a tu carpeta del proyecto
WorkingDirectory=/home/git/proyectos/monitor-quarkus-instance
# Comando para arrancar en modo producción (usando el script de Maven)
ExecStart=/home/git/proyectos/monitor-quarkus-instance/mvnw quarkus:dev -Dquarkus.http.host=0.0.0.0
Restart=always

[Install]
WantedBy=multi-user.target

3. Activa el «Fantasma»:

systemctl daemon-reload
systemctl enable monitor-quarkus
systemctl start monitor-quarkus

Ahora, aunque cierres PowerShell, te vayas a dormir o reinicies el VPS de Vultr, tu API en https://tu-dominio.com/api/statsaoa seguirá respondiendo.

Verificación final:

systemctl status monitor-quarkus #  Debe estar «active (running)»
curl https://tu-dominio.com/api/statsaoa #  Debe devolver JSON
curl https://git.tu-dominio.com #  Debe abrir Gitea con SSL

 

Y la parte 4:

Tengo ocupaciones del mundo real. Pero me encantaría hacerte entrar al mundo de Gitea Actions o la Compilación Nativa con GraalVM en Quarkus. Si tienes menos recursos, o te harta esperar la compilación de Native Quarkus, javelin está bien para proyectos propios pero no hay mucho mercado, ofertas de trabajo ni desastres que arreglar. Uno no vive solo de la elegancia del código, sino de solucionar problemas donde hay dinero y demanda.

Lo mas seguro es que no lo haga en NGINX una parte 4 con Gitea Actions por lo que explico en el watercooler (abajo de laconclusión), pero que si haga algo muy parecido a este documento, pero para levantar LAMP., con apache, spring boot en debian 13 y React con php. Las razones las verás abajo.

Conclusión:

Al terminar este setup, mi servidor Debian consume apenas unos megas para reportar su estado. No necesité un tablero de control de AWS de 100 dólares, ni una infraestructura pesada que se come la RAM antes de servir la primera petición. Como mi Motorola G31: hace exactamente lo que necesito, es eficiente y el control biométrico (mi endpointstatsaoa) es mío. En 2026, lo simple tiene valor de supervivencia

Si. Estoy consciente que esto es todo menos simple por sí mismo. Ver todo lo que carga la primera vez que cargas quarkus dev es impresionante.  Hay formas mas directas, pero esto es lo mas directo usando Java React. Personalmente creo que algo está mal si la solución eficiente , como esta, usa 2 gb de  ram para tener activo el ecosistema. Y por eso cuando se trata de proyectos propios, me voy por alternativas que no son java. Pero Quarkus es lo mas simple de java. Quarkus es lo mejor de un mal necesario (Java enterprise)

Plática de Watercooler:

En el entorno corporativo a veces las personas con experiencia están dispuestos a darte consejos por años de experiencia, y en USA se dice platica de watercooler a una mezcla entre eso y chismes.. En mi propia oficina suelen venir por café y galletas. En lo personal creo que tenemos complejidad innecesaria. Hay demasiados puntos de falla. Si esto es la versión simplificada imaginate como  estará lo demás.

He tenido casos que despues de explicar esto crean muchos micro services. Y luego me llaman a arreglar desastres.

Dije que podiamos usar giteaa actions . Aqui no lo vi a propósito. Lo uso porque se lo que estoy haciendo. Pero cuando tienes cinco o seis programadores con su propia idea de arquitectura y apis, vas aacabar con decenas de procesos fantasma que consumen la memoria. Tener un /statsaoa es una cosa pero  treinta o demas microservices, aunque diga amazon que es bueno, es incontrolable y te lleva a mas puntos de falla,  mayor costo y a diversos vectores de ataque. Creo que el punto que pone mas complejidad es REACT actualmente.

Un punto: La instalación de ORACLE se suele cobrar aparte. Usando un ejemplo, yo instalo servidores si me pagan por ello o si no hay mas remedio. Es responsabilidad y la autoridad es que me paguen.

Sin embargo, por simplicidad lo primero que hago es ver la queja. Los costos de Egress de Amazon. O de WAFs . Lo primero es irte por un costo estable. Regresate a vultr o un proveedor decente de vps. Reduce ese costo.

Y luego arregla el desastre de decenas de microservices que alguien hizo. Es mi principal fuente de ingresos. Por eso finalmente suelo terminar con algo de vultr o un proveedor de vps que no menciono , con apache, y sacando respaldos por una iguala para defender a la empresa de sus mismos programadores.

Un server es tan bueno como su admin. Te vas a enfrentar a muchos programadores bien intencionados pero mediocres. Y muchos admin que no ven el problema con la complejidad innecesaria de su infraestructura.

ANEXO: Uso de Quarkus en producción usando GraalVM

Para fines didácticos, en este post usamos el modo quarkus:dev. Sin embargo, un verdadero DevOps de 2026 sabe que en producción el motor debe ir «sellado» para maximizar la eficiencia y el ahorro de RAM que tanto hemos defendido.
Este anexo lo suelo pasar impreso en word, asi que lleva un formato diferente.

1. Preparando el motor para el mundo real

Antes de configurar el servicio final, debemos compilar nuestra aplicación para generar el paquete de distribución:

bash
# Ubícate en la carpeta del proyecto
cd /home/git/proyectos/monitor-quarkus-instance

# Compilar para producción (Modo JVM estándar)
./mvnw package

Esto generará una carpeta en target/quarkus-app/ con todo lo necesario.

Verificación:

bash
ls -lh target/quarkus-app/quarkus-run.jar
# Debe mostrar el JAR compilado

2. Ajuste del «Fantasma» (Servicio systemd)

Debemos modificar el archivo /etc/systemd/system/monitor-quarkus.service para que apunte al binario compilado y no al gestor de desarrollo. Aquí tienes las dos rutas posibles:

Opción A: Modo JVM (Estable y rápido)

Nota:

TIP DE RUTA: Como usamos SDKMAN, para saber qué poner en ExecStart, ejecuta en tu terminal: whereis java o readlink -f $(which java) La ruta suele verse así: /root/.sdkman/candidates/java/current/bin/java

Si usas el Java 21 que instalamos con SDKMAN:

ini
[Unit]
Description=Monitor Quarkus Instance AOA (Producción JVM)
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/home/git/proyectos/monitor-quarkus-instance
# ↓ La clave del cambio está aquí
ExecStart=/usr/bin/java -jar /home/git/proyectos/monitor-quarkus-instance/target/quarkus-app/quarkus-run.jar
Restart=always

[Install]
WantedBy=multi-user.target

Consumo estimado:

  • RAM: ~70-100 MB
  • Inicio: ~2-3 segundos

Opción B: Modo Nativo (El Santo Grial de la eficiencia)

Si decides compilar usando GraalVM para que el servidor arranque en milisegundos y consuma apenas una fracción de RAM (compilación nativa):

Primero, compilar nativo:

bash
#Solo si usas la Opción B (Nativo)
chmod +x target/monitor-quarkus-instance-1.0.0-SNAPSHOT-runner
# Esto tarda 5-10 minutos (es normal)
./mvnw package -Dnative

# Verificar que se creó el binario
ls -lh target/*-runner

Luego, ajustar el servicio:

ini
[Unit]
Description=Monitor Quarkus Instance AOA (Producción Nativa)
After=network.target

[Service]
Type=simple
User=root
WorkingDirectory=/home/git/proyectos/monitor-quarkus-instance
# ↓ Apunta al ejecutable nativo
ExecStart=/home/git/proyectos/monitor-quarkus-instance/target/monitor-quarkus-instance-1.0.0-SNAPSHOT-runner
Restart=always

[Install]
WantedBy=multi-user.target

Consumo estimado:

  • RAM: ~30-50 MB (¡3x menos que JVM!)
  • Inicio: ~0.05 segundos (50 milisegundos)

¿Por qué hacer este cambio?

Seguridad:
El modo dev deja herramientas de depuración abiertas que no quieres en la calle. Es como dejar la puerta de tu casa abierta «por si acaso».

Rendimiento:
El paquete quarkus-run.jar está optimizado por el «re-augment» de Quarkus para cargar solo lo necesario. No arrastra todo el peso del desarrollo.

Independencia:
Al usar el ejecutable nativo (Opción B), tu servidor se vuelve una pieza de relojería suiza que no depende ni siquiera de una JVM externa para correr. Es un binario único, como Gitea.

3. Aplicar los Cambios

# 1. Edita el servicio con tu opción elegida
nano /etc/systemd/system/monitor-quarkus.service

# 2. Recarga la configuración de systemd
systemctl daemon-reload

# 3. Reinicia el servicio con el nuevo "piloto"
systemctl restart monitor-quarkus

# 4. Verifica que todo está bien
systemctl status monitor-quarkus

# 5. Prueba el endpoint
curl https://tu-dominio.com/api/statsaoa

Tabla Comparativa (Para Tomar Decisión)

Modo RAM Inicio Build Time Complejidad Recomendado Para
dev ~150 MB Inmediato 0 min Baja Aprendizaje
JVM ~80 MB 2-3 seg 1-2 min Baja Producción normal
Nativo ~40 MB 0.05 seg 5-10 min Media Máxima eficiencia

Nota Final del Autor

Si haces este cambio, recuerda ejecutar systemctl daemon-reload y systemctl restart monitor-quarkus para que el sistema reconozca al nuevo «piloto» de producción.

Mi recomendación: Para empresa mediana (50-150 usuarios/día), el Modo JVM (Opción A) es perfecto. Ahorras el tiempo de compilación nativa y el consumo de RAM sigue siendo ridículamente bajo comparado con Spring Boot o Node.js.

Reserva el Modo Nativo (Opción B) para cuando realmente necesites el último gramo de eficiencia o tengas restricciones extremas de RAM. Es el equivalente a pasar de un Motorola G31 a uno ultra-optimizado que solo hace llamadas y SMS pero dura 2 semanas con una carga.