commit 95e06ba47cc040c6de0e57a79a748c83e58300ba Author: chemavx Date: Tue Apr 14 17:39:51 2026 +0000 feat: initial custom n8n image with n8n-nodes-upload-post@0.1.42 - Dockerfile based on n8nio/n8n:2.15.1 - Pre-installs n8n-nodes-upload-post@0.1.42 as PVC bootstrap - CI/CD with SHA tags matching polymarket-bot pattern - README with version bump process and migration warnings Co-Authored-By: Claude Sonnet 4.6 diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..df44ed3 --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,55 @@ +name: CI/CD + +on: + push: + branches: + - main + +env: + REGISTRY: git.chemavx.xyz + K8S_MANIFESTS_REPO: http://chemavx:${{ secrets.CI_TOKEN }}@gitea.gitea.svc.cluster.local:3000/chemavx/k8s-manifests.git + GIT_SSL_NO_VERIFY: "true" + +jobs: + build-and-push: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ssl-verify: false + + - name: Set image tag + id: tag + run: echo "TAG=${GITHUB_SHA::8}" >> $GITHUB_OUTPUT + + - name: Build and push n8n image + uses: aevea/action-kaniko@master + with: + registry: git.chemavx.xyz + username: chemavx + password: ${{ secrets.CI_TOKEN }} + image: chemavx/n8n + tag: ${{ steps.tag.outputs.TAG }} + path: . + build_file: Dockerfile + extra_args: --insecure --skip-tls-verify + + - name: Update k8s manifests + run: | + TAG=${{ steps.tag.outputs.TAG }} + + git config --global user.email "ci@git.chemavx.xyz" + git config --global user.name "Gitea CI" + + git clone ${{ env.K8S_MANIFESTS_REPO }} /tmp/k8s-manifests + cd /tmp/k8s-manifests + + sed -i "s|image: .*chemavx/n8n.*\|image: .*n8nio/n8n.*|image: git.chemavx.xyz/chemavx/n8n:${TAG}|g" \ + n8n/deployment-n8n.yaml + sed -i "s|imagePullPolicy: Always|imagePullPolicy: IfNotPresent|g" \ + n8n/deployment-n8n.yaml + + git add n8n/deployment-n8n.yaml + git diff --cached --quiet || git commit -m "ci: update n8n image to ${TAG} [skip ci]" + git push diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..b96d504 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM n8nio/n8n:2.15.1 + +# Pre-install community node as bootstrap. +# NOTE: at runtime the PVC mounts over /home/node/.n8n, so n8n uses the +# version from the PVC. This installation acts as a fallback if the PVC +# is ever lost or a fresh volume is used. +USER root + +RUN mkdir -p /home/node/.n8n/nodes && \ + cd /home/node/.n8n/nodes && \ + echo '{"name":"installed-nodes","private":true,"dependencies":{}}' > package.json && \ + npm install n8n-nodes-upload-post@0.1.42 && \ + chown -R node:node /home/node/.n8n + +USER node diff --git a/README.md b/README.md new file mode 100644 index 0000000..da40eab --- /dev/null +++ b/README.md @@ -0,0 +1,96 @@ +# n8n — Custom Image + +Imagen custom de n8n basada en la oficial, con `n8n-nodes-upload-post` preinstalado como bootstrap. + +## Versión actual + +| Componente | Versión | +|---|---| +| n8n base | `2.15.1` | +| n8n-nodes-upload-post | `0.1.42` | + +## Arquitectura + +``` +Gitea repo (chemavx/n8n) + └── Dockerfile + └── FROM n8nio/n8n:2.15.1 + + n8n-nodes-upload-post@0.1.42 (bootstrap) + └── CI/CD → git.chemavx.xyz/chemavx/n8n: + └── k8s-manifests/n8n/deployment-n8n.yaml (parcheado automáticamente) + └── ArgoCD → despliega en cluster +``` + +**Nota sobre el nodo custom**: el nodo está instalado en la imagen como fallback. En operación normal, el PVC monta sobre `/home/node/.n8n` y n8n usa la versión del PVC (instalada via UI). Si el PVC se pierde o se usa un volumen nuevo, la imagen ya trae el nodo listo. + +## Cómo hacer bump de versión de n8n + +1. Revisa el [changelog de n8n](https://github.com/n8n-io/n8n/releases) para breaking changes o migraciones de BD. + +2. Edita el `Dockerfile`: + ```dockerfile + FROM n8nio/n8n:X.Y.Z # ← cambiar aquí + ``` + +3. Commit y push a `main`: + ```bash + git commit -am "chore: bump n8n to X.Y.Z" + git push + ``` + +4. El CI construye la imagen y actualiza el manifiesto automáticamente. + +### ⚠️ Advertencia crítica sobre migraciones de BD + +n8n ejecuta migraciones de esquema SQLite automáticamente al arrancar con una versión nueva. + +**Una vez que el pod arranca con la nueva versión, NO se puede hacer rollback de imagen** si hubo migraciones — la versión antigua no sabe leer el esquema nuevo y n8n no arrancará. + +**Regla**: hacer backup ANTES de cualquier bump de versión mayor o minor: + +```bash +# 1. Checkpoint WAL +kubectl exec -n n8n deployment/n8n -- node -e " +const sqlite3 = require('/usr/local/lib/node_modules/n8n/node_modules/.pnpm/sqlite3@5.1.7/node_modules/sqlite3'); +const db = new sqlite3.Database('/home/node/.n8n/database.sqlite'); +db.run('PRAGMA wal_checkpoint(TRUNCATE)', () => { console.log('OK'); db.close(); }); +" + +# 2. Backup manual +kubectl create job --from=cronjob/backup backup-pre-n8n-upgrade-$(date +%Y%m%d%H%M) -n backup-system +kubectl wait --for=condition=complete job/backup-pre-n8n-upgrade-... -n backup-system --timeout=300s +``` + +Los bumps de **patch** (2.15.1 → 2.15.2) son generalmente seguros. Los bumps de **minor o major** requieren revisar el changelog. + +## Cómo actualizar n8n-nodes-upload-post + +Edita el `Dockerfile`: +```dockerfile +RUN ... npm install n8n-nodes-upload-post@X.Y.Z && ... +``` + +Después actualiza también el nodo desde la UI de n8n para que el PVC quede sincronizado con la imagen. + +## Secreto requerido en el cluster + +El deployment requiere el secret `n8n-secret` en el namespace `n8n`: + +```bash +kubectl create secret generic n8n-secret \ + --from-literal=encryption-key='' \ + -n n8n +``` + +**Sin este secret, n8n arranca pero no puede descifrar ninguna credencial.** + +## Rollback de emergencia + +Si el nuevo deploy falla **antes** de que n8n arranque (imagen no disponible, error de config): + +```bash +# Volver a la imagen anterior (sustituir ) +kubectl set image deployment/n8n n8n=git.chemavx.xyz/chemavx/n8n: -n n8n +``` + +Si n8n ya arrancó con la nueva versión y hubo migraciones, no hacer rollback de imagen — restaurar desde backup.