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 <noreply@anthropic.com>
This commit is contained in:
chemavx
2026-04-14 17:39:51 +00:00
commit 95e06ba47c
3 changed files with 166 additions and 0 deletions
+55
View File
@@ -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
+15
View File
@@ -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
+96
View File
@@ -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:<sha>
└── 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='<VALOR_EN_VAULTWARDEN>' \
-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 <sha-anterior>)
kubectl set image deployment/n8n n8n=git.chemavx.xyz/chemavx/n8n:<sha-anterior> -n n8n
```
Si n8n ya arrancó con la nueva versión y hubo migraciones, no hacer rollback de imagen — restaurar desde backup.