Puesta en marcha
Opciones de inicio
| Opción | Variable de entorno | Predeterminado | |
|---|---|---|---|
-addr |
IC_ADDR |
:8080 |
Dirección y puerto |
-data |
IC_DATA |
./data |
Carpeta de datos |
-cache-mb |
IC_CACHE_MB |
128 |
Caché de páginas en MB, 0 = desactivada |
-secure-cookies |
IC_SECURE_COOKIES=1 |
desactivado | Cookie de sesión solo por HTTPS; actívalo sin falta detrás de HTTPS |
-rate-limit |
IC_RATE_LIMIT |
120 |
Peticiones a la API por minuto e IP sin iniciar sesión (con token/sesión, el décuple), 0 = desactivado; consulta la documentación de la API |
-headless |
IC_HEADLESS=1 |
desactivado | Forzar el funcionamiento sin app de administración, inicio de sesión ni sesiones; consulta Servidor headless |
| – | IC_MASTER_TOKEN |
– | Token con permiso de escritura sin cuenta de usuario (al menos 32 caracteres); consulta Servidor headless |
| – | IC_SETUP_TOKEN |
– | Opcional: secreto exigido para la primera configuración (primera cuenta de admin) – protege una instancia recién publicada y aún vacía de que un extraño llegue primero. Se pide en el formulario de configuración |
-media-cache-mb |
IC_MEDIA_CACHE_MB |
512 |
Caché en disco para medios en S3 en MB, 0 = desactivada; consulta Guardar los medios en S3 |
| – | IC_ENCRYPTION_KEY |
– | Clave para las credenciales cifradas de los ajustes (al menos 32 caracteres); sin ella, IllusionCMS crea data/secret.key; consulta Guardar los medios en S3 |
Las variables de entorno para las fuentes REST ({env.NAME}) las defines también al arrancar. Las variables con el prefijo IC_ (configuración del CMS, p. ej. IC_MASTER_TOKEN) nunca se pueden leer ahí. Los Workflows no tienen acceso a las variables de entorno.
Además: -version muestra la versión; -create-token "Name" crea un token de API con permiso de escritura, lo muestra y termina; -enable-admin vuelve a activar un admin desactivado en los ajustes; -healthcheck consulta /healthz del servidor en marcha y termina con el código de salida 0 o 1, pensado para el HEALTHCHECK de un contenedor Docker.
Docker y Coolify: los archivos Compose listos (independiente detrás de un proxy inverso como Apache, y para Coolify) se incluyen en cada versión como illusioncms-vX.Y.Z-deploy.zip (junto con los binarios de Linux; instrucciones en el README.md incluido) y en el repositorio de despliegue IllusionCMS-Deployment. Importante detrás de un proxy: el proxy debe transmitir la cabecera Host (en Apache, ProxyPreserveHost On), porque si no IllusionCMS no puede asignar el sitio web al dominio, y debe establecer X-Forwarded-Proto, para que el sitemap y robots.txt usen https://.
Carpeta de datos y copia de seguridad
data/
illusion.db Base de datos (páginas, Snippets, CSS/JS, Collections, ajustes …)
illusion.db-wal Registro de escritura de la base de datos (¡forma parte de ella!)
media/2026/10/… archivos subidos e importados
backups/ copias automáticas: nocturnas sin medios (las 7 últimas)
y antes de importar un Bundle, con medios (las 3 últimas)
cache/media/ caché en disco de medios desde S3 (solo con S3)
secret.key clave de las credenciales cifradas (sin IC_ENCRYPTION_KEY)
Copias de seguridad automáticas: cada noche a partir de las 3:00 (hora del servidor), IllusionCMS guarda todo el contenido (páginas, CSS/JS, Snippets, Collections, ajustes de los archivos …) sin los propios archivos multimedia, pero solo si algo ha cambiado desde la última copia nocturna. Se conservan las 7 últimas. Restaurar: en Ajustes → Sincronización, descarga la copia de seguridad y vuelve a importarla; la carpeta de medios no se modifica. Si quieres que también las entradas de las Collections con Datos en vivo vuelvan al estado de la copia, marca al importar Adoptar también del Bundle las entradas de las Collections con datos en vivo. Lo mejor es guardar además los archivos multimedia junto con la carpeta de datos (cambian poco y solo se eliminan si los eliminas expresamente).
Copia de seguridad: lo más seguro es detener brevemente el servidor y copiar la carpeta entera. Con el servidor en marcha: sqlite3 data/illusion.db ".backup backup.db" más una copia de media/, o simplemente descargar un Bundle (contiene todo el contenido, pero no las cuentas ni los tokens).
Guardar los medios en S3
Por defecto, los archivos subidos e importados están en data/media. Si quieres, IllusionCMS los guarda en un almacenamiento compatible con S3: práctico si el servidor tiene poco espacio o si los archivos deben respaldarse por separado del servidor. Las direcciones no cambian: los archivos siguen accesibles en /media/… e IllusionCMS los obtiene él mismo del bucket (también por rangos para vídeos y descargas reanudables). El bucket sigue siendo privado; no necesita lectura pública.
Dónde: Ajustes → Almacenamiento (en modo remoto, para el servidor conectado). Arriba ves el almacenamiento activo, el número y tamaño de los archivos y la ocupación de la caché en disco.
Campos:
- Endpoint: dirección del servicio S3, p. ej.
https://s3.eu-central-1.amazonaws.com. - Región: p. ej.
eu-central-1; con Garage normalmentegarage, con Cloudflare R2auto. Vacío =us-east-1. - Bucket: debe existir ya. Prefijo (opcional): p. ej.
cms/si varias aplicaciones comparten un bucket. - Clave de acceso y clave secreta: la clave necesita permisos para leer, escribir, eliminar y listar. El secret no se vuelve a mostrar; si más adelante dejas el campo vacío, se conserva el guardado.
- Path style: direccionamiento
endpoint/bucket/archivoen lugar debucket.endpoint/archivo. Necesario para Garage y endpoints con dirección IP.
| Proveedor | Endpoint | Región | Path style |
|---|---|---|---|
| Garage (autoalojado) | http://127.0.0.1:3900 o tu dirección de Garage |
garage |
activado |
| Hetzner Object Storage | https://fsn1.your-objectstorage.com (o nbg1, hel1) |
fsn1 |
desactivado |
| Cloudflare R2 | https://<account-id>.r2.cloudflarestorage.com |
auto |
activado |
| AWS S3 | https://s3.eu-central-1.amazonaws.com |
eu-central-1 |
desactivado |
Probar conexión escribe, lee y elimina un pequeño objeto de prueba en el bucket e indica claramente qué falta (dirección inaccesible, clave desconocida, secret incorrecto, bucket inexistente, faltan permisos). Guardar recuerda los datos; mientras esté activo el almacenamiento local, solo como borrador.
Mudanza: Cambiar a S3 … inicia una migración guiada en segundo plano: se copian todos los archivos (lo que ya existe en el destino con el mismo tamaño se omite, así que una mudanza interrumpida continúa donde se quedó), después se comprueba cada copia y solo entonces IllusionCMS cambia y vacía la caché de páginas. Mientras tanto puedes seguir trabajando: las subidas y eliminaciones van primero al almacenamiento antiguo, se registran y se incorporan al cambiar; las escrituras solo se detienen durante ese breve momento. Con Cancelar o si hay un error, el almacenamiento antiguo sigue activo. Si marcas Eliminar después los archivos antiguos, IllusionCMS limpia el almacenamiento antiguo tras un cambio correcto; si no, queda como respaldo. Volver al almacenamiento local … funciona igual en la otra dirección. El bucket y el prefijo de un almacenamiento S3 activo solo se cambian con una migración; las credenciales nuevas para el mismo bucket se aplican en cuanto la prueba sale bien.
Caché en disco: delante de S3 hay una caché local en data/cache/media (512 MB por defecto, opción de inicio -media-cache-mb o IC_MEDIA_CACHE_MB, por instancia también en los ajustes de almacenamiento). Acelera sobre todo las variantes de imagen y WebP y sigue entregando lo que tiene en caché si S3 no responde durante un momento. Un bucket solo puede usarlo una instancia de IllusionCMS (la caché da por hecho que todos los cambios pasan por ella); para una segunda instancia usa otro bucket u otro prefijo.
Credenciales cifradas: el secret solo se guarda cifrado en la base de datos (AES-256-GCM). La clave viene de la variable de entorno IC_ENCRYPTION_KEY (al menos 32 caracteres, p. ej. openssl rand -hex 32); si no está definida, IllusionCMS crea la primera vez que la necesita el archivo data/secret.key (legible solo por el propietario). Llévate la clave al mudarte a otro servidor: copia también data/secret.key o define la misma IC_ENCRYPTION_KEY. Si falta la clave o es otra, el secret ya no se puede descifrar: IllusionCMS arranca entonces con los archivos locales y muestra el error en los ajustes de almacenamiento; vuelve a introducir el secret y guarda, y S3 vuelve a aplicarse. Los Bundles no contienen a propósito el ajuste de almacenamiento.
Qué está cifrado y qué no: en la base de datos se cifran con la misma clave: el secret de S3, los secrets de webhooks, la contraseña SMTP, los tokens de IllusionDB y los tokens de las conexiones; los valores antiguos en texto plano siguen siendo legibles y se cifran al guardar de nuevo. Los secretos guardados (contraseña SMTP, token de IllusionDB, secret de S3, token de conexión) solo se reutilizan para el mismo destino – si cambian host, dirección, endpoint o bucket, hay que introducirlos de nuevo. No se cifran las cabeceras de las fuentes REST (Authorization …): forman parte del contenido y por eso aparecen en bundles, copias nocturnas y al subir a otra instancia – solo así se puede restaurar una instancia por completo. Trata bundles y copias como credenciales (la carpeta data/backups y la caché de medios solo son legibles por el usuario del servidor); las credenciales de las fuentes también pueden venir de variables de entorno ({env.SHOP_TOKEN}), y entonces no se guardan en ninguna parte de la base de datos.
Copias de seguridad: también con S3 la base de datos sigue siendo local en data/illusion.db (igual que las copias nocturnas). Para respaldarla continuamente en el mismo bucket encaja Litestream: un programa aparte junto a IllusionCMS que replica la base de datos SQLite de forma continua. Ejemplo de litestream.yml (un ejemplo completo de Docker Compose está en el README.md del paquete de despliegue):
dbs:
- path: /data/illusion.db
replicas:
- type: s3
endpoint: https://fsn1.your-objectstorage.com
bucket: firma-media
path: litestream/illusion.db
access-key-id: ${LITESTREAM_ACCESS_KEY_ID}
secret-access-key: ${LITESTREAM_SECRET_ACCESS_KEY}
Para restaurar, con el servidor detenido: litestream restore -config litestream.yml /data/illusion.db. El proveedor de S3 no respalda automáticamente los propios archivos de medios: activa el versionado o la replicación del bucket en el proveedor si está disponible.
Construir en local, publicar en línea (Bundles)
Puedes construir un sitio web en local y luego llevarlo completo a tu servidor en línea. Un Bundle es un archivo con la extensión .icb (bundle de IllusionCMS, técnicamente un ZIP) con todo el contenido de la instancia: sitios web, páginas, CSS/JS, Snippets, archivos, Collections, fuentes REST y redirecciones. Las cuentas y los tokens de API no se incluyen: en el servidor sigues iniciando sesión con tu cuenta de allí.
Todo lo necesario está en Ajustes → Sincronización:
- Descargar: el Bundle como archivo
.icb. - Subir e importar: en el servidor en línea, elige el archivo
.icby pulsa Importar y reemplazar. Los Bundles y copias de seguridad de versiones anteriores (.zip) se pueden seguir importando. - Sincronizar con un servidor: desde el admin local, en un solo paso, a través de una conexión guardada: Subir reemplaza el contenido del servidor por el local, y Traer trae aquí el estado del servidor junto con los datos en vivo (p. ej. a un equipo nuevo o después de una corrección urgente en línea). Se muestra el progreso. Si en el lado que se va a reemplazar ha cambiado algo desde la última sincronización, el CMS avisa antes; los datos en vivo no cuentan como cambio.
Conviene saber:
- La importación reemplaza todo el contenido del destino: lo que solo se haya cambiado en línea desaparece. Antes, el servidor guarda automáticamente su estado anterior (las 3 últimas copias de seguridad están en la misma vista para descargar; restaurar = importar una copia de seguridad).
- Los datos en vivo se conservan: las entradas de las Collections con la casilla Datos en vivo (p. ej. solicitudes de contacto) se conservan siempre en el destino, también las que llegan mientras trabajas en local. Las entradas locales de esas Collections no se transfieren. A la inversa (importar en local un Bundle del servidor en producción, restaurar una copia de seguridad), las adoptas con la casilla Adoptar también del Bundle las entradas de las Collections con datos en vivo.
- Conservar el contenido mantenido en línea: con Conservar las entradas de Collections se mantienen las entradas del servidor (p. ej. artículos de blog escritos en línea); el diseño, las páginas y el código vienen igualmente del estado local. La asignación se hace por el slug de la Collection.
- Dominios: en local, tu sitio web normalmente no tiene dominio. En ese caso, el sitio web del servidor conserva sus dominios registrados. Si introduces dominios en local, se adoptan.
- Los archivos sin cambios no se vuelven a escribir, por lo que las transferencias repetidas son más rápidas. Aun así, se sube el Bundle completo.
- Ambas instancias deberían tener la misma versión de IllusionCMS; un servidor más antiguo rechaza los Bundles de una versión más reciente.
- Si el servidor está detrás de nginx,
client_max_body_sizedebe ser lo bastante grande para el Bundle (Caddy: sin límite). - Con scripts:
curl -H "Authorization: Bearer <token>" -H "Content-Type: application/zip" --data-binary @bundle.icb https://www.firma.de/api/v1/bundle(consulta la API).
Varias instancias: trabajar en directo o sincronizar
En Ajustes → Conexiones registras otras instancias de IllusionCMS: nombre, dirección y un token de API con permiso de escritura de allí (en el servidor, en Ajustes → Tokens de API; en un servidor sin admin, el token maestro o uno creado con -create-token). El token se queda en la base de datos local, no se muestra y no va en el Bundle. Comprobar muestra si el servidor es accesible, qué versión tiene y si funciona en modo headless. Da igual si en el propio servidor funciona el admin: solo hace falta el token. Así gestionas cuantas instancias quieras desde una app local; headless es una opción adicional para servidores que gestionas exclusivamente de esta forma.
Con una conexión hay dos formas de trabajar, y puedes combinarlas:
- Trabajar en directo: arriba en el menú aparece con qué instancia trabaja el admin en ese momento (Local). Si eliges ahí una conexión, todas las vistas (páginas, archivos, Collections, estadísticas, Workflows, registro 404 …) van directamente a ese servidor; los cambios se aplican de inmediato. El menú muestra entonces el nombre de la conexión con LIVE. Así gestionas varios sitios web en distintos servidores desde una app local, y ves sin rodeos los datos en vivo, como las solicitudes de contacto. En local solo quedan las cuentas, los tokens de API y las propias conexiones. La vista previa de páginas, los Pens y las direcciones de los Workflows apuntan al servidor.
- Construir en local y sincronizar: prueba en local sin que los visitantes vean nada y luego sube en Ajustes → Sincronización (ver arriba). Los datos en vivo del servidor se conservan.
Versiones: la app de administración viene siempre de tu instancia local. Al cambiar (y en cada carga) comprueba si el servidor tiene la misma versión de IllusionCMS. Si es distinta o el servidor no es accesible, el selector se vuelve rojo en lugar de amarillo y un aviso indica ambas versiones; en el menú de selección aparecen junto a cada conexión su versión y, si procede, un ⚠. Se puede trabajar igualmente, pero algunas funciones pueden faltar o fallar; lo mejor es actualizar ambas instancias a la vez.
Para correcciones rápidas sirve el modo en vivo; para reformas mayores (diseño nuevo, muchos cambios de CSS), la instancia local: los borradores solo existen para las páginas, y un archivo CSS o un Snippet modificado se aplica en vivo de inmediato en todas partes.
Servidor headless (sin admin)
Quien ya solo gestiona su servidor en producción desde la app local no necesita allí ningún admin. Sin admin, el servidor sirve el sitio web, la API para tokens, las entradas HTTP de los Workflows y los Pens públicos, pero no /cms-admin, ni inicio de sesión, ni sesiones, ni gestión de cuentas o tokens (todo 404). Eso reduce la superficie de ataque: no hay ninguna página de inicio de sesión con la que alguien pueda probar contraseñas.
Lo más sencillo, sin ninguna cuenta de usuario: al arrancar, establece un token maestro y desactiva el admin:
IC_MASTER_TOKEN=$(openssl rand -hex 32) # guárdalo: es el token para la conexión
IC_HEADLESS=1
El token maestro vale como un token de API con permiso de escritura, pero no está en ninguna base de datos y no necesita cuenta (al menos 32 caracteres; si no, el servidor no arranca). En local lo introduces en Ajustes → Conexiones. En el historial aparece como autor Master-Token. No gestiona cuentas ni tokens: eso queda reservado al admin. Queda bloqueado en cuanto eliminas la variable y reinicias.
Desactivar el admin con el interruptor: en lugar de IC_HEADLESS=1, también se puede hacer en Ajustes → Sistema → Desactivar admin, en el admin del propio servidor o, más cómodo, desde tu app local en modo remoto. Solo es posible si existe un token con permiso de escritura (o hay un token maestro definido), para que no te quedes fuera. Volver a activarlo: en modo remoto, en Ajustes → Sistema; por API (PUT /api/v1/system); o en el servidor con illusioncms -enable-admin. Salida de emergencia, si ya no conoces ningún token: define IC_MASTER_TOKEN, reinicia, conéctate con él y activa el admin. Con IC_HEADLESS=1, en cambio, el admin está desactivado de forma fija y el interruptor, bloqueado.
En lugar de un token maestro sirve también un token de API normal: créalo en el servidor en Ajustes → Tokens de API mientras el admin todavía funciona, o por línea de comandos; en el contenedor Docker, p. ej., docker exec <container> illusioncms -data /data -create-token "Lokales Admin".
Exportar como sitio estático
Un sitio web se puede exportar completo como páginas HTML estáticas, para un alojamiento web sencillo con Apache, sin que allí tenga que funcionar IllusionCMS. En el editor de la página de inicio, en Ajustes → Sitio web → Exportar como sitio estático:
- Comprobar exportación: renderiza todas las páginas y muestra un informe: número de páginas, archivos y tamaño, páginas con errores de template, enlaces internos rotos y archivos que faltan.
- Descargar ZIP y descomprimir el contenido en el directorio raíz del dominio (p. ej.
htdocs/opublic_html/).
Qué contiene:
- Cada página como
pfad/index.html:/leistungense convierte enleistungen/index.html. Apache redirige/leistungenautomáticamente a/leistungen/. - Las páginas de detalle tras las páginas Catch-All (artículos de blog individuales) se incluyen si están en el sitemap (Collections o fuente del sitemap, p. ej. IllusionDB) o si están enlazadas en algún sitio, p. ej. desde el resumen del blog.
robots.txtcomo en el CMS.- La página 404 como
404.htmly un.htaccessque la incluye (ErrorDocument 404 /404.html), con todas las redirecciones del sitio web. - Todos los archivos CSS y JS,
sitemap.xml(para el primer dominio del sitio web o la URL base indicada) y las imágenes usadas con sus variantes srcset. Con Incluir todos los archivos de la biblioteca de medios se incluye la carpeta de medios completa, necesario si JavaScript compone él mismo las URL de las imágenes. - Los archivos privados siempre se omiten – también cuando se incluyen todos los archivos de la mediateca – junto con sus variantes y versiones WebP; el informe indica cuántos son.
Límites: todo es una instantánea en el momento de la exportación; los datos REST, las Collections y los cambios posteriores necesitan una nueva exportación. Las páginas con parámetros de consulta (?seite=2) no existen en estático, ni tampoco las llamadas a /api/v1 desde JavaScript. La exportación va en el directorio raíz del dominio, no en una subcarpeta (los enlaces empiezan por /).
Comprobación de estado
GET /healthz responde sin iniciar sesión con 200 y {"status":"ok", …} mientras la base de datos esté accesible; si no, con 503. Adecuado para monitorización de disponibilidad, HEALTHCHECK de Docker o balanceadores de carga. La respuesta contiene además el identificador de compilación de la app de administración y el commit de Git del binario: práctico para comprobar si una actualización está realmente en marcha.
Detrás de un proxy inverso (HTTPS)
IllusionCMS solo habla HTTP. Para HTTPS pones un proxy delante, p. ej. Caddy (obtiene los certificados automáticamente):
www.firma.de, shop.firma.de {
reverse_proxy 127.0.0.1:8080
}
firma.de {
redir https://www.firma.de{uri}
}
Con varios sitios web, registra todos los dominios en el proxy; IllusionCMS elige el sitio web según el dominio solicitado (cabecera Host, que Caddy transmite sin cambios).
Arranca entonces el servidor con -addr 127.0.0.1:8080 -secure-cookies. El sitemap toma el dominio y el esquema de X-Forwarded-Host/X-Forwarded-Proto, que Caddy establece automáticamente.
Las cabeceras de protección como HSTS las puede enviar el propio IllusionCMS (cabeceras de seguridad). La redirección de http:// a https:// debería hacerla el proxy de forma permanente (301 o 308, lo predeterminado en Caddy). En Traefik hace falta para ello permanent: true en el middleware de redirección; si no, redirige con 302. Para Coolify hay instrucciones en el paquete de despliegue (README.md, sección Coolify).
IllusionCMS comprime él mismo las páginas HTML, el CSS/JS y el sitemap (gzip). Por eso no hace falta comprimir en el proxy. Mejor desactívalo allí; si no, también las imágenes se vuelven a empaquetar sin necesidad.
Como servicio (systemd)
[Unit]
Description=IllusionCMS
After=network.target
[Service]
ExecStart=/opt/illusioncms/illusioncms -addr 127.0.0.1:8080 -data /var/lib/illusioncms -secure-cookies
Environment=SHOP_TOKEN=…
Restart=on-failure
User=illusioncms
[Install]
WantedBy=multi-user.target