feat(easypanel): agregar instrucciones y validaciones para secretos en EasyPanel, incluyendo generación de contraseñas seguras y actualización de archivos de configuración
Some checks are pending
Container / meta (analyzer) (push) Waiting to run
Container / meta (api) (push) Waiting to run
Container / meta (legacy) (push) Waiting to run
Container / meta (nginx) (push) Waiting to run
Container / meta (playout) (push) Waiting to run
Container / meta (worker) (push) Waiting to run
Container / build (push) Blocked by required conditions
Project / pre-commit (push) Waiting to run
Project / test-tools (push) Waiting to run
Release-Please / release-please (push) Waiting to run
Some checks are pending
Container / meta (analyzer) (push) Waiting to run
Container / meta (api) (push) Waiting to run
Container / meta (legacy) (push) Waiting to run
Container / meta (nginx) (push) Waiting to run
Container / meta (playout) (push) Waiting to run
Container / meta (worker) (push) Waiting to run
Container / build (push) Blocked by required conditions
Project / pre-commit (push) Waiting to run
Project / test-tools (push) Waiting to run
Release-Please / release-please (push) Waiting to run
This commit is contained in:
parent
ac2806e2f6
commit
83724ddc26
@ -12,8 +12,32 @@ Requisitos/Notas:
|
|||||||
- `update.sh` usa utilidades estándar de shell y `perl` (normalmente disponible en sistemas UNIX). Si tu entorno no tiene `perl`, el script puede adaptarse a `python`.
|
- `update.sh` usa utilidades estándar de shell y `perl` (normalmente disponible en sistemas UNIX). Si tu entorno no tiene `perl`, el script puede adaptarse a `python`.
|
||||||
- Revisa y completa las variables de entorno requeridas por `docker-compose.easypanel.yml` (p. ej. secretos: `POSTGRES_PASSWORD`, `RABBITMQ_DEFAULT_PASS`, etc.) desde la UI de EasyPanel.
|
- Revisa y completa las variables de entorno requeridas por `docker-compose.easypanel.yml` (p. ej. secretos: `POSTGRES_PASSWORD`, `RABBITMQ_DEFAULT_PASS`, etc.) desde la UI de EasyPanel.
|
||||||
|
|
||||||
|
|
||||||
Siguientes pasos recomendados:
|
Siguientes pasos recomendados:
|
||||||
- (Opcional) Añadir un `update.js` si prefieres implementar clonación/actualizaciones con las utilidades de EasyPanel (no obligatorio).
|
|
||||||
- (Opcional) Añadir un `update.js` si prefieres implementar clonación/actualizaciones con las utilidades de EasyPanel (no obligatorio). Este repo incluye `easypanel/update.js` que realiza la misma función que `update.sh` usando Node.js.
|
- (Opcional) Añadir un `update.js` si prefieres implementar clonación/actualizaciones con las utilidades de EasyPanel (no obligatorio). Este repo incluye `easypanel/update.js` que realiza la misma función que `update.sh` usando Node.js.
|
||||||
- (Opcional) Añadir un archivo `README.md` con la lista de variables que EasyPanel debe exponer en la interfaz de instalación.
|
- (Opcional) Añadir un archivo `README.md` con la lista de variables que EasyPanel debe exponer en la interfaz de instalación.
|
||||||
|
|
||||||
|
## Instrucciones específicas para EasyPanel
|
||||||
|
|
||||||
|
1. En la UI de EasyPanel, crea un nuevo servicio apuntando a este repositorio (o sube un ZIP).
|
||||||
|
2. En la sección de variables/Environment, pega el contenido de `easypanel/service.env` (o sube el archivo).
|
||||||
|
- Marca como `secret` las variables: `POSTGRES_PASSWORD`, `RABBITMQ_DEFAULT_PASS`, `ICECAST_SOURCE_PASSWORD`, `ICECAST_ADMIN_PASSWORD`, `ICECAST_RELAY_PASSWORD`.
|
||||||
|
3. EasyPanel ejecutará `easypanel/update.sh` por convención; el script intenta ejecutar `easypanel/update.js` si Node.js está disponible, y usa un fallback en shell si no lo está.
|
||||||
|
4. Después de ejecutar el script, EasyPanel usará `easypanel/code/docker-compose.yml` para desplegar el stack. Revisa ese archivo antes de confirmar el despliegue.
|
||||||
|
5. Si necesitas exponer puertos manualmente en EasyPanel, revisa `docker-compose.easypanel.yml` y ajusta `NGINX_PORT`, `ICECAST_PORT`, etc., o deja que EasyPanel gestione el ruteo.
|
||||||
|
|
||||||
|
Consejos:
|
||||||
|
- Asegúrate de que `LIBRETIME_GENERAL_PUBLIC_URL` apunte a tu dominio público antes de desplegar.
|
||||||
|
- Para entornos de producción, establece `LIBRETIME_DEBUG=false` y usa contraseñas fuertes en los secrets.
|
||||||
|
|
||||||
|
Generar contraseñas seguras
|
||||||
|
---------------------------
|
||||||
|
Puedes usar el script `easypanel/generate_secrets.sh` para generar contraseñas seguras y sus hashes SHA-256. El script imprime un bloque `.env` listo para pegar en la UI de EasyPanel. Ejecútalo localmente y no subas las contraseñas al repositorio.
|
||||||
|
|
||||||
|
Ejemplo:
|
||||||
|
```bash
|
||||||
|
cd easypanel
|
||||||
|
chmod +x generate_secrets.sh
|
||||||
|
./generate_secrets.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
version: "3.9"
|
|
||||||
|
|
||||||
# LibreTime Docker Compose (EasyPanel-ready)
|
# LibreTime Docker Compose (EasyPanel-ready)
|
||||||
# Esta versión está pensada para usarse desde un repositorio en EasyPanel.
|
# Esta versión está pensada para usarse desde un repositorio en EasyPanel.
|
||||||
@ -16,7 +15,7 @@ services:
|
|||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_USER: ${POSTGRES_USER:-libretime}
|
POSTGRES_USER: ${POSTGRES_USER:-libretime}
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-libretime}
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-Jz/XxRUodVl2g0HE59DszTBJVY8Sdmv7}
|
||||||
POSTGRES_DB: ${POSTGRES_DB:-libretime}
|
POSTGRES_DB: ${POSTGRES_DB:-libretime}
|
||||||
volumes:
|
volumes:
|
||||||
- postgres_data:/var/lib/postgresql/data
|
- postgres_data:/var/lib/postgresql/data
|
||||||
@ -33,7 +32,7 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_DEFAULT_VHOST:-/libretime}
|
RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_DEFAULT_VHOST:-/libretime}
|
||||||
RABBITMQ_DEFAULT_USER: ${RABBITMQ_DEFAULT_USER:-libretime}
|
RABBITMQ_DEFAULT_USER: ${RABBITMQ_DEFAULT_USER:-libretime}
|
||||||
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_DEFAULT_PASS}
|
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_DEFAULT_PASS:-Bn321PQSRXanvmZlppuulVCB0ShN5Dz2}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ["CMD-SHELL", "rabbitmq-diagnostics check_port_connectivity"]
|
test: ["CMD-SHELL", "rabbitmq-diagnostics check_port_connectivity"]
|
||||||
interval: 30s
|
interval: 30s
|
||||||
@ -97,9 +96,9 @@ services:
|
|||||||
image: ghcr.io/libretime/icecast:2.4.4
|
image: ghcr.io/libretime/icecast:2.4.4
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
environment:
|
||||||
ICECAST_SOURCE_PASSWORD: ${ICECAST_SOURCE_PASSWORD:-hackme}
|
ICECAST_SOURCE_PASSWORD: ${ICECAST_SOURCE_PASSWORD:-dna1g1GcaaHakSN6C9X7rcPRpIIc/jV2}
|
||||||
ICECAST_ADMIN_PASSWORD: ${ICECAST_ADMIN_PASSWORD:-hackme}
|
ICECAST_ADMIN_PASSWORD: ${ICECAST_ADMIN_PASSWORD:-BLoYLPlUXfmkxrsvGF7LP0TtVtuKNuzJ}
|
||||||
ICECAST_RELAY_PASSWORD: ${ICECAST_RELAY_PASSWORD:-hackme}
|
ICECAST_RELAY_PASSWORD: ${ICECAST_RELAY_PASSWORD:-jYzhEjwdiJlTk30QOYHum6UE61FHo+sd}
|
||||||
ICECAST_ADMIN_USER: ${ICECAST_ADMIN_USER:-admin}
|
ICECAST_ADMIN_USER: ${ICECAST_ADMIN_USER:-admin}
|
||||||
ICECAST_HOSTNAME: ${ICECAST_HOSTNAME:-localhost}
|
ICECAST_HOSTNAME: ${ICECAST_HOSTNAME:-localhost}
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
},
|
},
|
||||||
"update_script": "easypanel/update.js",
|
"update_script": "easypanel/update.js",
|
||||||
"compose_path": "easypanel/code/docker-compose.yml",
|
"compose_path": "easypanel/code/docker-compose.yml",
|
||||||
|
"env_file": "easypanel/service.env",
|
||||||
"services": {
|
"services": {
|
||||||
"notes": "El archivo compose generado tendrá los servicios principales: postgres, rabbitmq, api, legacy, nginx, icecast, playout, liquidsoap, worker, analyzer y config-generator."
|
"notes": "El archivo compose generado tendrá los servicios principales: postgres, rabbitmq, api, legacy, nginx, icecast, playout, liquidsoap, worker, analyzer y config-generator."
|
||||||
},
|
},
|
||||||
@ -120,4 +121,6 @@
|
|||||||
],
|
],
|
||||||
"notes": "Después de clonar, EasyPanel debe ejecutar el `update_script` y usar el compose generado en `compose_path`. Asegúrate de proveer los secretos marcados como `secret: true` en la UI de EasyPanel.",
|
"notes": "Después de clonar, EasyPanel debe ejecutar el `update_script` y usar el compose generado en `compose_path`. Asegúrate de proveer los secretos marcados como `secret: true` en la UI de EasyPanel.",
|
||||||
"last_updated": "2025-10-01"
|
"last_updated": "2025-10-01"
|
||||||
|
,
|
||||||
|
"install_instructions": "1) Copia el contenido de easypanel/service.env en la sección Environment/Secrets del servicio en EasyPanel.\n2) Marca como secreto las variables que contienen contraseñas (POSTGRES_PASSWORD, RABBITMQ_DEFAULT_PASS, ICECAST_*_PASSWORD).\n3) EasyPanel ejecutará el script indicado en 'update_script' (easypanel/update.js o update.sh) para generar el compose final en easypanel/code/docker-compose.yml.\n4) Revisa el compose generado y despliega el servicio."
|
||||||
}
|
}
|
||||||
|
|||||||
63
easypanel/generate_secrets.sh
Normal file
63
easypanel/generate_secrets.sh
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# genera contraseñas seguras y muestra sus hashes SHA-256
|
||||||
|
# Uso: ./generate_secrets.sh
|
||||||
|
# Salida: muestra las contraseñas (plaintext) y sus hashes; imprime un bloque .env listo para pegar en EasyPanel
|
||||||
|
|
||||||
|
rand_pass() {
|
||||||
|
# 24 bytes -> 32 chars base64 approx
|
||||||
|
openssl rand -base64 24
|
||||||
|
}
|
||||||
|
|
||||||
|
sha256() {
|
||||||
|
if command -v openssl >/dev/null 2>&1; then
|
||||||
|
printf "%s" "$1" | openssl dgst -sha256 -r | awk '{print $1}'
|
||||||
|
else
|
||||||
|
# fallback to python
|
||||||
|
python3 - <<PY
|
||||||
|
import hashlib, sys
|
||||||
|
print(hashlib.sha256(sys.stdin.read().encode()).hexdigest())
|
||||||
|
PY
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "Generando contraseñas seguras...\n"
|
||||||
|
|
||||||
|
POSTGRES_PASSWORD=$(rand_pass)
|
||||||
|
RABBITMQ_DEFAULT_PASS=$(rand_pass)
|
||||||
|
ICECAST_SOURCE_PASSWORD=$(rand_pass)
|
||||||
|
ICECAST_ADMIN_PASSWORD=$(rand_pass)
|
||||||
|
ICECAST_RELAY_PASSWORD=$(rand_pass)
|
||||||
|
|
||||||
|
# Mostrar en pantalla con hashes
|
||||||
|
cat <<EOF
|
||||||
|
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
|
||||||
|
POSTGRES_PASSWORD.sha256: $(sha256 "$POSTGRES_PASSWORD")
|
||||||
|
|
||||||
|
RABBITMQ_DEFAULT_PASS: $RABBITMQ_DEFAULT_PASS
|
||||||
|
RABBITMQ_DEFAULT_PASS.sha256: $(sha256 "$RABBITMQ_DEFAULT_PASS")
|
||||||
|
|
||||||
|
ICECAST_SOURCE_PASSWORD: $ICECAST_SOURCE_PASSWORD
|
||||||
|
ICECAST_SOURCE_PASSWORD.sha256: $(sha256 "$ICECAST_SOURCE_PASSWORD")
|
||||||
|
|
||||||
|
ICECAST_ADMIN_PASSWORD: $ICECAST_ADMIN_PASSWORD
|
||||||
|
ICECAST_ADMIN_PASSWORD.sha256: $(sha256 "$ICECAST_ADMIN_PASSWORD")
|
||||||
|
|
||||||
|
ICECAST_RELAY_PASSWORD: $ICECAST_RELAY_PASSWORD
|
||||||
|
ICECAST_RELAY_PASSWORD.sha256: $(sha256 "$ICECAST_RELAY_PASSWORD")
|
||||||
|
|
||||||
|
# Bloque .env para pegar en EasyPanel (REEMPLAZA/NO COMMIT)
|
||||||
|
cat <<ENDF
|
||||||
|
|
||||||
|
# ------------------ EasyPanel .env snippet (DO NOT COMMIT) ------------------
|
||||||
|
POSTGRES_PASSWORD=$POSTGRES_PASSWORD
|
||||||
|
RABBITMQ_DEFAULT_PASS=$RABBITMQ_DEFAULT_PASS
|
||||||
|
ICECAST_SOURCE_PASSWORD=$ICECAST_SOURCE_PASSWORD
|
||||||
|
ICECAST_ADMIN_PASSWORD=$ICECAST_ADMIN_PASSWORD
|
||||||
|
ICECAST_RELAY_PASSWORD=$ICECAST_RELAY_PASSWORD
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
ENDF
|
||||||
|
EOF
|
||||||
|
|
||||||
|
printf "\nAVISO: No dejes estas contraseñas en el repositorio. Copia y pégalas en la UI de EasyPanel y marca las variables como SECRET.\n"
|
||||||
59
easypanel/service.env
Normal file
59
easypanel/service.env
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Archivo de variables para EasyPanel (alineado con docker-compose.easypanel.yml)
|
||||||
|
# Copia/pega este bloque en la sección Environment/Secrets del servicio en EasyPanel.
|
||||||
|
# Marca como SECRET las variables indicadas (POSTGRES_PASSWORD, RABBITMQ_DEFAULT_PASS, ICECAST_*_PASSWORD, etc.).
|
||||||
|
|
||||||
|
# ------------------ General ------------------
|
||||||
|
# Versión de las imágenes de LibreTime (usa la etiqueta de la imagen)
|
||||||
|
LIBRETIME_VERSION=4.5
|
||||||
|
# URL pública de la instalación (REEMPLAZA por tu dominio)
|
||||||
|
LIBRETIME_GENERAL_PUBLIC_URL=https://tu-dominio.example
|
||||||
|
# Habilitar debug (false en producción)
|
||||||
|
LIBRETIME_DEBUG=false
|
||||||
|
# Claves opcionales para la API/secretos internos (opcional)
|
||||||
|
LIBRETIME_API_KEY=
|
||||||
|
LIBRETIME_SECRET_KEY=
|
||||||
|
|
||||||
|
# ------------------ Postgres ------------------
|
||||||
|
POSTGRES_USER=libretime
|
||||||
|
# SECRET (REQUIRED): contraseña de Postgres
|
||||||
|
POSTGRES_PASSWORD=Jz/XxRUodVl2g0HE59DszTBJVY8Sdmv7
|
||||||
|
POSTGRES_DB=libretime
|
||||||
|
# Opcional: host/puerto si los cambias
|
||||||
|
POSTGRES_HOST=postgres
|
||||||
|
POSTGRES_PORT=5432
|
||||||
|
|
||||||
|
# ------------------ RabbitMQ ------------------
|
||||||
|
RABBITMQ_DEFAULT_VHOST=/libretime
|
||||||
|
RABBITMQ_DEFAULT_USER=libretime
|
||||||
|
# SECRET (REQUIRED): contraseña de RabbitMQ
|
||||||
|
RABBITMQ_DEFAULT_PASS=Bn321PQSRXanvmZlppuulVCB0ShN5Dz2
|
||||||
|
RABBITMQ_HOST=rabbitmq
|
||||||
|
RABBITMQ_PORT=5672
|
||||||
|
|
||||||
|
# ------------------ Nginx / puertos ------------------
|
||||||
|
# EasyPanel suele gestionar ruteo; ajusta si es necesario
|
||||||
|
NGINX_PORT=8080
|
||||||
|
NGINX_WORKER_PROCESSES=auto
|
||||||
|
|
||||||
|
# ------------------ Icecast ------------------
|
||||||
|
ICECAST_PORT=8000
|
||||||
|
# SECRET: contraseñas de Icecast (marcar como secret)
|
||||||
|
ICECAST_SOURCE_PASSWORD=dna1g1GcaaHakSN6C9X7rcPRpIIc/jV2
|
||||||
|
ICECAST_ADMIN_PASSWORD=BLoYLPlUXfmkxrsvGF7LP0TtVtuKNuzJ
|
||||||
|
ICECAST_RELAY_PASSWORD=jYzhEjwdiJlTk30QOYHum6UE61FHo+sd
|
||||||
|
ICECAST_ADMIN_USER=admin
|
||||||
|
ICECAST_HOSTNAME=stream.tu-dominio.example
|
||||||
|
|
||||||
|
# ------------------ Liquidsoap ------------------
|
||||||
|
LIQUIDSOAP_HARBOR_PORT=8001
|
||||||
|
LIQUIDSOAP_TELNET_PORT=8002
|
||||||
|
|
||||||
|
# ------------------ Opcionales / Compatibilidad ------------------
|
||||||
|
# Estas variables las usa el generador de config; es seguro incluirlas aquí
|
||||||
|
RABBITMQ_HOST=${RABBITMQ_HOST:-rabbitmq}
|
||||||
|
RABBITMQ_PORT=${RABBITMQ_PORT:-5672}
|
||||||
|
POSTGRES_HOST=${POSTGRES_HOST:-postgres}
|
||||||
|
POSTGRES_PORT=${POSTGRES_PORT:-5432}
|
||||||
|
|
||||||
|
# FIN: reemplaza los valores marcados con 'CAMBIA...' por secretos reales y
|
||||||
|
# marca las variables sensibles como SECRET en la UI de EasyPanel antes del deploy.
|
||||||
@ -12,9 +12,53 @@ const SRC = path.resolve(__dirname, '../docker-compose.easypanel.yml');
|
|||||||
const DEST_DIR = path.resolve(__dirname, './code');
|
const DEST_DIR = path.resolve(__dirname, './code');
|
||||||
const DEST = path.join(DEST_DIR, 'docker-compose.yml');
|
const DEST = path.join(DEST_DIR, 'docker-compose.yml');
|
||||||
|
|
||||||
|
// Variables secret requeridas para evitar despliegues con valores vacíos
|
||||||
|
const REQUIRED_SECRETS = ['POSTGRES_PASSWORD', 'RABBITMQ_DEFAULT_PASS'];
|
||||||
|
|
||||||
|
function parseEnvFile(filePath) {
|
||||||
|
const out = {};
|
||||||
|
if (!fs.existsSync(filePath)) return out;
|
||||||
|
const raw = fs.readFileSync(filePath, 'utf8');
|
||||||
|
raw.split(/\n/).forEach(line => {
|
||||||
|
line = line.trim();
|
||||||
|
if (!line || line.startsWith('#')) return;
|
||||||
|
const m = line.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
|
||||||
|
if (m) {
|
||||||
|
let val = m[2];
|
||||||
|
// strip optional quotes
|
||||||
|
if ((val.startsWith("\'") && val.endsWith("\'")) || (val.startsWith('"') && val.endsWith('"'))) {
|
||||||
|
val = val.slice(1, -1);
|
||||||
|
}
|
||||||
|
out[m[1]] = val;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateRequiredSecrets() {
|
||||||
|
const envFilePath = path.join(__dirname, 'service.env');
|
||||||
|
const fileEnv = parseEnvFile(envFilePath);
|
||||||
|
const missing = [];
|
||||||
|
REQUIRED_SECRETS.forEach(k => {
|
||||||
|
const v = (process.env[k] || '').trim() || (fileEnv[k] || '').trim();
|
||||||
|
// treat obvious placeholders as missing
|
||||||
|
if (!v || /^\s*(CAMBIA|pon_aqui|tu_|CHANGE|REPLACE)/i.test(v)) {
|
||||||
|
missing.push(k);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (missing.length) {
|
||||||
|
console.error('ERROR: faltan valores seguros para las siguientes variables:', missing.join(', '));
|
||||||
|
console.error('Asegúrate de definirlas en la sección Environment/Secrets de EasyPanel o en', envFilePath);
|
||||||
|
console.error('Variables requeridas:', REQUIRED_SECRETS.join(', '));
|
||||||
|
process.exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function removeContainerNamesAndPorts(content) {
|
function removeContainerNamesAndPorts(content) {
|
||||||
// Eliminar container_name: <valor> líneas
|
// Eliminar container_name: <valor> líneas
|
||||||
content = content.replace(/^[ \t]*container_name:[^\n]*\n/gm, '');
|
content = content.replace(/^[ \t]*container_name:[^\n]*\n/gm, '');
|
||||||
|
// Eliminar version: ... para evitar advertencias en EasyPanel
|
||||||
|
content = content.replace(/^[ \t]*version:[^\n]*\n/gm, '');
|
||||||
// Eliminar bloques de ports:
|
// Eliminar bloques de ports:
|
||||||
// ports:\n - "..."\n - ...
|
// ports:\n - "..."\n - ...
|
||||||
content = content.replace(/^[ \t]*ports:[^\n]*\n(?:^[ \t]+-.*\n)*/gim, '');
|
content = content.replace(/^[ \t]*ports:[^\n]*\n(?:^[ \t]+-.*\n)*/gim, '');
|
||||||
@ -22,6 +66,8 @@ function removeContainerNamesAndPorts(content) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
|
// Validar secretos antes de generar el compose final
|
||||||
|
validateRequiredSecrets();
|
||||||
if (!fs.existsSync(SRC)) {
|
if (!fs.existsSync(SRC)) {
|
||||||
console.error('ERROR: no se encuentra', SRC);
|
console.error('ERROR: no se encuentra', SRC);
|
||||||
process.exit(2);
|
process.exit(2);
|
||||||
|
|||||||
@ -10,6 +10,39 @@ SRC="$BASE_DIR/../docker-compose.easypanel.yml"
|
|||||||
DEST_DIR="$BASE_DIR/code"
|
DEST_DIR="$BASE_DIR/code"
|
||||||
DEST="$DEST_DIR/docker-compose.yml"
|
DEST="$DEST_DIR/docker-compose.yml"
|
||||||
|
|
||||||
|
REQUIRED_SECRETS=(POSTGRES_PASSWORD RABBITMQ_DEFAULT_PASS)
|
||||||
|
|
||||||
|
function read_env_file() {
|
||||||
|
local f="$BASE_DIR/service.env"
|
||||||
|
if [ ! -f "$f" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
# do not source to avoid side effects; parse manually
|
||||||
|
grep -E '^[A-Za-z_][A-Za-z0-9_]*=' "$f" | sed "s/^[^=]*=//" >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_required_secrets() {
|
||||||
|
local missing=()
|
||||||
|
for key in "${REQUIRED_SECRETS[@]}"; do
|
||||||
|
# prefer environment then service.env
|
||||||
|
val="${!key:-}"
|
||||||
|
if [ -z "$val" ] && [ -f "$BASE_DIR/service.env" ]; then
|
||||||
|
val=$(grep -E "^${key}=" "$BASE_DIR/service.env" | head -n1 | sed -E "s/^${key}=//")
|
||||||
|
fi
|
||||||
|
if [ -z "$val" ] || echo "$val" | grep -Eiq '^(CAMBIA|pon_aqui|tu_|CHANGE|REPLACE)'; then
|
||||||
|
missing+=("$key")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ ${#missing[@]} -ne 0 ]; then
|
||||||
|
echo "ERROR: faltan valores seguros para las siguientes variables: ${missing[*]}"
|
||||||
|
echo "Definelas en la sección Environment/Secrets de EasyPanel o en $BASE_DIR/service.env"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
check_required_secrets
|
||||||
|
|
||||||
if command -v node >/dev/null 2>&1 && [ -f "$BASE_DIR/update.js" ]; then
|
if command -v node >/dev/null 2>&1 && [ -f "$BASE_DIR/update.js" ]; then
|
||||||
echo "Node.js detectado, ejecutando easypanel/update.js"
|
echo "Node.js detectado, ejecutando easypanel/update.js"
|
||||||
# Ejecutar con node (permitirá usar la versión JS en lugar del sed/perl)
|
# Ejecutar con node (permitirá usar la versión JS en lugar del sed/perl)
|
||||||
@ -35,11 +68,14 @@ cp "$SRC" "$DEST"
|
|||||||
if command -v perl >/dev/null 2>&1; then
|
if command -v perl >/dev/null 2>&1; then
|
||||||
perl -0777 -pe "s/^[ \t]*container_name:[^\n]*\n//mg" -i "$DEST"
|
perl -0777 -pe "s/^[ \t]*container_name:[^\n]*\n//mg" -i "$DEST"
|
||||||
perl -0777 -pe "s/^[ \t]*ports:[^\n]*\n(?:^[ \t]+-.*\n)*//mg" -i "$DEST"
|
perl -0777 -pe "s/^[ \t]*ports:[^\n]*\n(?:^[ \t]+-.*\n)*//mg" -i "$DEST"
|
||||||
|
perl -0777 -pe "s/^[ \t]*version:[^\n]*\n//mg" -i "$DEST"
|
||||||
else
|
else
|
||||||
# Fallback con awk/sed si perl no está disponible
|
# Fallback con awk/sed si perl no está disponible
|
||||||
# Elimina líneas 'container_name:' y bloques 'ports:' simples
|
# Elimina líneas 'container_name:' y bloques 'ports:' simples
|
||||||
sed -E '/^[ \t]*container_name:/d' -i "" "$DEST" 2>/dev/null || sed -E '/^[ \t]*container_name:/d' -i '$DEST'
|
sed -E '/^[ \t]*container_name:/d' -i "" "$DEST" 2>/dev/null || sed -E '/^[ \t]*container_name:/d' -i '$DEST'
|
||||||
awk 'BEGIN{skip=0} /^[ \t]*ports:[ \t]*$/ {skip=1; next} /^[ \t]*[^ \t]/ { if(skip){skip=0} } { if(!skip) print $0 }' "$DEST" > "$DEST.tmp" && mv "$DEST.tmp" "$DEST"
|
awk 'BEGIN{skip=0} /^[ \t]*ports:[ \t]*$/ {skip=1; next} /^[ \t]*[^ \t]/ { if(skip){skip=0} } { if(!skip) print $0 }' "$DEST" > "$DEST.tmp" && mv "$DEST.tmp" "$DEST"
|
||||||
|
# Elimina 'version:' si queda
|
||||||
|
sed -E '/^[ \t]*version:/d' -i "" "$DEST" 2>/dev/null || sed -E '/^[ \t]*version:/d' -i '$DEST'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Preparado $DEST para EasyPanel. Revisa variables de entorno en el README y súbelas en la UI de EasyPanel."
|
echo "Preparado $DEST para EasyPanel. Revisa variables de entorno en el README y súbelas en la UI de EasyPanel."
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user