Ir al contenido
use-cases / cert-renewal-no-ssh / hero
CRON · EXEC · SIN SSH

Rota tus certificados TLS sin sesión SSH

Hoody Cron lleva el horario. Hoody Exec lleva la lógica de renovación. Domingo a las 04:00 dispara un curl, certbot corre, el nuevo bundle se PATCHea al proxy, y el reload se confirma. Sin sesión de shell, sin clave en ~/.ssh, sin jump host entre tú y el certificado.

use-cases / cert-renewal-no-ssh / lifecycle

Tres URLs, sin shell

Toda la pipeline de renovación son dos endpoints y un horario de 5 campos. Cron dispara Exec. Exec llama a ACME y hace PATCH al proxy. La confirmación vuelve como un 200.

CICLO DE RENOVACIÓNPOSTEADO UNA VEZ · CORRE SEMANALMENTE
01 · PROGRAMAR

POST de una entrada de cron

POST /users/me/entries con schedule "0 4 * * 0" y command "curl /scripts/certs/renew". El servicio de cron lo escribe en el crontab del usuario y arranca a contar. Esto lo hiciste una vez, desde cualquier sitio con HTTPS.

02 · EJECUTAR

Exec corre el script

Domingo 04:00, cron hace curl al URL de exec. Exec arranca el script, habla con el endpoint ACME de Let's Encrypt, valida el reto http-01, y escribe el bundle renovado en /files. Sin login en el nodo, sin sesión necesaria.

03 · RECARGAR

PATCH al bundle del proxy

El script hace PATCH del nuevo cert y key al endpoint bundle del proxy de Hoody. El proxy hace hot-reload — sin reinicio — y el siguiente handshake TLS sirve el nuevo certificado. Todo el ciclo está por debajo del minuto.

Cada paso es una llamada HTTP que puedes reproducir desde una terminal — `curl --dry-run` si quieres depurar, `curl -i` si quieres las cabeceras. La pipeline no depende en ningún momento de una sesión iniciada.

use-cases / cert-renewal-no-ssh / mechanism

Cómo se ven los dos endpoints

A la izquierda, la entrada de cron que programa el job. A la derecha, el script de exec que hace el trabajo. Ambos son direccionables vía HTTP — ambos son auditables, ambos son reproducibles desde cualquier portátil o móvil.

cron · registrar el horario
POST · una vez
# register the weekly renewal
curl -X POST \
  https://cron.containers.hoody.com/users/me/entries \
  -H "Content-Type: application/json" \
  -d '[ "schedule":"0 4 * * 0", "command":"curl -fsS https://exec.containers.hoody.com/scripts/certs/renew", "comment":"weekly TLS renewal", "enabled":true ]'

# response
HTTP/1.1 201 Created
{ "id":"7a92", "schedule":"0 4 * * 0", "enabled":true }
exec · scripts/certs/renew.ts
GET · corre semanalmente
// scripts/certs/renew.ts
// @mode serverless
// @timeout 120000

const domains = ["your-app.com", "api.your-app.com", ...];

for (const d of domains) {
  const cert = await acme.order(d);
  await fetch("/api/v1/proxy/cert/bundle", {
    method: "PATCH",
    body: JSON.stringify({ d, cert })
  });
}

return { "renewed": domains.length };

Dos URLs, una mañana de domingo, cero SSH. La entrada de cron son datos — POST una vez y ahí está hasta que hagas DELETE. El script de exec es un archivo — cámbialo vía la API y la siguiente ejecución coge la nueva lógica. Nada de este bucle requiere que una persona esté en una máquina.

use-cases / cert-renewal-no-ssh / powers

Por qué esto vence al crontab por SSH

El mismo resultado — un certificado renovado cada semana — con tres propiedades que el setup legacy nunca tuvo.

AUTH · TOKEN DE URL

Sin clave privada en ~/.ssh

La auth es un token de URL, no una clave SSH. Rótala vía la API y el token viejo deja de funcionar en todas partes a la vez. Sin agent forwarding, sin bastión, sin un archivo de clave que olvidaste que copiaste a una caja de CI hace tres años.

AUDITORÍA · TRAZA HTTP

Cada renovación es un log de petición

Cada ejecución es una fila en el log de cron y una línea de petición en el log de exec. Haz grep por quién la disparó, cuándo, qué cert, qué código de respuesta. El 200 del proxy es el recibo de que el reload aterrizó.

DEBUG · UN CURL EN DRY-RUN

No haces SSH para depurar

Reproduce la renovación desde tu portátil con `curl /scripts/certs/renew?dry_run=true`. Mira la respuesta, arregla el script vía la API de escritura de exec, reintenta. Todo el bucle pasa por HTTPS — la misma tubería que usa el horario de producción.

use-cases / cert-renewal-no-ssh / capacity

Lo que te ahorras

Números del despliegue, no benchmarks. Lo que importa es la forma: muy pocas piezas móviles, todas hablan HTTP.

  1. SESIONES SSH0

    El setup es un POST. La renovación es un GET en un horario. El debug es un curl. No hay sesión de shell en la pipeline en ningún punto — tu clave privada nunca tiene que estar en la caja.

  2. ENDPOINTS USADOS2

    Una entrada de cron para programar la ejecución. Una ruta de exec que corre el script. La tercera URL — el PATCH al bundle del proxy — vive dentro del script y recarga el cert.

  3. CAMPOS · HORARIO CRON5

    Expresión estándar de 5 campos "0 4 * * 0" — domingo 04:00. O `@weekly` si te da igual qué día. El servicio de cron acepta ambas, más auto-expiración para renovaciones de un solo disparo.

Servicio cron: expresiones de 5 campos y macros (`@hourly`, `@daily`, `@weekly`, `@monthly`, `@yearly`), aislamiento por usuario, `expires_at` opcional. Exec: aislados V8, runtime Bun, comentarios mágicos para mode/timeout/CORS. El flujo ACME se maneja en tu script — Hoody no corre el certbot por ti, corre tu código en un horario.

use-cases / cert-renewal-no-ssh / punchline

La renovación es un curl en un horario — sin sesión de shell, sin clave, sin jump host.

antes · sábado antes de que expiraran los certsahora · el cron lleva nueve meses corriendo
CÓMO ERA EL STACK ANTIGUOssh prod && certbot renew && systemctl reload nginxclave en ~/.ssh · bastión por delante · rezar que la línea de cron sobreviviera al último reinicio
CÓMO ES AHORA
use-cases / cert-renewal-no-ssh / replaces

Qué reemplaza esto

Las formas estándar de mantener TLS válido en producción. Cada una quiere una sesión de shell, un servicio de control plane, o ambos. El par cron-más-exec no quiere ninguno.

  • SSH + certbot manualUna sesión de shell, una clave, un paso de renew que olvidas cuando estás de vacaciones
  • ssh-bastion + scriptUn jump host que mantienes solo para correr un script de una línea
  • AWS Certificate Manager (closed-loop)Gratis, pero solo en AWS — y el cert nunca sale de su proxy
  • HashiCorp Vault PKITodo un daemon de secretos para emitir certs que renuevas una vez por semana
  • cert-manager en KubernetesUn controlador, un CRD, un webhook — para lo que son dos llamadas HTTP
  • pipeline de cron de renovación a medida + jump hostScripts pegamento en un bastión, una clave por runner de CI, sin rastro de auditoría
use-cases / cert-renewal-no-ssh / cta

Deja de hacer login para renovar certs. Haz POST del horario una vez. Mira cómo el proxy se recarga solo cada domingo por la mañana.

use-cases / cert-renewal-no-ssh / related

Lee los otros