Files
edgar.friendly adb2b4dfe4
deploy-branch / deploy (push) Successful in 2m12s
deploy-branch / teardown (push) Skipped
ci: layout unificado /opt/localesp/<rama>; migrados entornos legacy
2026-07-24 09:56:13 +02:00

114 lines
4.8 KiB
Markdown

# CI/CD — despliegue por rama
Cada rama se despliega automáticamente en `https://<rama>.localesp.es`.
## Cómo funciona
```
push a rama X
│ Gitea Actions (workflow: .gitea/workflows/deploy.yml)
runner self-hosted (host executor, en el propio VPS)
│ npm ci → vite build → scripts/deploy.sh <rama>
/opt/localesp/<slug>/ código + dist/ + node_modules (prod)
systemd localesp-<slug>.service node server/index.js (PORT=80xx)
nginx <slug>.localesp.es proxy_pass → localhost:80xx
certbot *.localesp.es Let's Encrypt (si el DNS ya apunta)
```
El **slug** se deriva del nombre de rama (`Feature/Foo``feature-foo`),
válido como hostname DNS. Un entorno = un subdirectorio bajo `/opt/localesp/`,
un servicio, un vhost y un puerto. La base de datos `localesp.db` de cada
entorno **se conserva** entre despliegues (no se sobreescribe).
Puertos: los históricos son `8080` (prototipo-yb01) y `8081` (master); los
nuevos se asignan desde `8082` hacia arriba. Si la rama ya tiene su
`localesp-<slug>.service`, se reutiliza su puerto (adopta el entorno existente).
## Precondición manual: el registro DNS
El registro A de `<rama>.localesp.es` **se crea a mano** (no está automatizado).
1. En el proveedor DNS de `localesp.es`, añade un registro A:
`<rama>.localesp.es A <IP-pública-del-VPS>`
2. Espera a que propague (`dig +short <rama>.localesp.es`).
3. Lanza el workflow (push a la rama, o *Actions → Run workflow* en Gitea).
Mientras el DNS no apunte al VPS, `deploy.sh` despliega la app igualmente y la
sirve por **HTTP**; emite el cert Let's Encrypt en cuanto detecta que el DNS ya
resuelve. No hay que tocar nada más.
## Añadir una rama nueva
```bash
git checkout -b mi-feature
# ... cambios ...
git push -u origin mi-feature
```
El workflow corre solo. Si quieres URL pública: crea el registro A (arriba).
Si no, el entorno existe pero no es alcanzable por hostname (útil para tests internos
si añades el host a `/etc/hosts`).
## Borrar una rama
Al borrar la rama en Gitea, el job `teardown` limpia el entorno (unit systemd,
vhost, cert y `/opt/localesp-<slug>`). También manual:
```bash
ssh localesp.jumpingcrab.com 'bash /opt/localesp-master/scripts/teardown.sh mi-feature'
```
## Entornos existentes (ya migrados al layout unificado)
Los entornos legacy ya están reubicados bajo `/opt/localesp/<rama>` con sus
systemd units renombradas al esquema `localesp-<slug>.service`, de modo que el
CI los **adopta** sin cambios (reutiliza puerto y vhost):
| Rama | Dir | Unit | Puerto | Hosts |
|---|---|---|---|---|
| `master` | `/opt/localesp/master` | `localesp-master.service` | 8081 | `localesp.es`, `master.localesp.es` |
| `prototipo-yb01` | `/opt/localesp/prototipo-yb01` | `localesp-prototipo-yb01.service` | 8080 | `prototipo-yb01.localesp.es` |
El antiguo `localesp.service` (sin slug) se retiró; ahora todas las units
siguen el patrón `localesp-<slug>.service`. La db de cada entorno se preservó.
## Seguridad
El runner (`gitea-runner`) se ejecuta como **root en el VPS de producción** y en
modo **host** (sin contenedor): cualquier workflow que se ejecute corresponde a
código del repo corriendo con privilegios de root en la caja. Esto es aceptable
mientras el repo sea propio / de baja colaboración. Si entran colaboradores
externos, conviene migrar a:
- runner en contenedor + despliegue por SSH (clave como secret de Gitea), o
- *ephemeral runners* (`gitea-runner register --ephemeral`).
## Evolución: estrategia B (wildcard)
Para eliminar la precondición manual del DNS y el cert por rama, más adelante:
1. Registro **wildcard `*.localesp.es`** (DNS).
2. **Wildcard cert** `*.localesp.es` vía challenge DNS-01 (una sola vez).
3. Un único vhost `*.localesp.es` que enruta por `Host` con un `map` rama→puerto.
`deploy.sh` apenas cambia: se caen los pasos de creación de vhost y certbot.
Nada de lo hecho aquí se pierde.
## Infra del runner (referencia)
Instalado en el VPS (`localesp.jumpingcrab.com`):
- Binario: `/usr/local/bin/gitea-runner` (v2.2.0), host executor.
**Cadena de suministro verificada**: el binario coincide (sha256 `d6b3f5bb…`)
con el descomprimido del release oficial `gitea-runner-2.2.0-linux-amd64.xz`, cuya suma
`13357e0d…` está publicada en el release. Gitea no publica firma GPG del runner; la suma
es la garantía máxima disponible. No hay paquete `dnf` oficial (solo binario o Docker image).
- Config: `/etc/gitea-runner/config.yaml` — etiquetas `self-hosted:host`, `linux:host`.
- Registro: `/var/lib/gitea-runner/.runner` (instance-level, `https://git.localesp.es`).
- Servicio: `gitea-runner.service` (systemd, `User=root`, `WorkingDirectory=/var/lib/gitea-runner`).
Comprobar estado: `systemctl status gitea-runner` · `journalctl -u gitea-runner -f`.
Ver runners en Gitea: *Site administration → Actions → Runners*.