fix: [carbone-ee] enable Studio and template management

The charm had no ``hooks/init``, so Carbone started in its default
stateless mode: no Studio, no template management, and ``CARBONE_BIND``
defaulting to ``127.0.0.1`` (unreachable behind the web-proxy).

Add ``hooks/init`` to:
- bind on ``0.0.0.0`` so the ``web-proxy`` can reach the service ;
- serve the Studio and ``/carbone-studio.js`` (``CARBONE_STUDIO``) ;
- enable stateful template management (``CARBONE_TEMPLATE_MANAGEMENT``):
  stable 64-bit template IDs, versioning and the ``/template`` endpoints ;
- align the datastore/configstore ownership on the unprivileged
  ``carbone`` image user, otherwise the container crash-loops with
  ``EACCES`` on ``/app/config/config.json``.

Persist ``/app/config`` as a ``config-resources`` and set a
``docker-compose.stop_grace_period`` of 200s: Carbone flushes its
template metadata on graceful shutdown, and Docker's 10s default would
SIGKILL it and lose templates on redeploy.  Flush metadata every
5 minutes to shrink the hard-crash window.

Bump the image to ``full-5.15.1`` and add a local ``basic-deploy`` test.

Verified locally: ``/status`` 200, ``/carbone-studio.js`` 200,
``GET /templates`` 200, template upload with versioning plus render
from the stable template ID, and metadata survival across a container
recreation.
This commit is contained in:
Stéphan Sainléger
2026-09-25 19:06:38 +02:00
parent fda96565ad
commit 002d8fe196
4 changed files with 117 additions and 6 deletions

View File

@@ -4,14 +4,63 @@
From: Carbone https://hub.docker.com/r/carbone/carbone-ee#running-carbone-community-edition-forever-free From: Carbone https://hub.docker.com/r/carbone/carbone-ee#running-carbone-community-edition-forever-free
## Usage : Upstream documentation:
- On-premise configuration: https://carbone.io/documentation/developer/on-premise-installation/configuration.html
- Template management: https://carbone.io/documentation/developer/on-premise-installation/template-management.html
- Studio Web Component: https://carbone.io/documentation/developer/embedding/studio-web-component.html
* What this charm enables
By default Carbone starts in the *stateless* mode: it only renders the
template sent with each request, exposes no Studio and keeps no template
metadata. The =init= hook turns it into the *stateful* service, which is
what the charm is meant to provide:
- =CARBONE_STUDIO=true= serves the Studio web interface and the
=/carbone-studio.js= Web Component.
- =CARBONE_TEMPLATE_MANAGEMENT=true= enables stable 64-bit template IDs,
versioning, the =GET/POST/PATCH /template= endpoints and the
=embedded-versioning= Studio mode.
- =CARBONE_BIND=0.0.0.0= makes Carbone listen on all interfaces so the
=web-proxy= can reach it (the upstream default is =127.0.0.1=).
* Usage
ex : ex :
``` #+begin_src yaml
carbone: carbone:
relations: relations:
web-proxy: web-proxy:
frontend: frontend:
domain: carbone.dev1.elabore.coop domain: carbone.dev1.elabore.coop
``` #+end_src
* Persistence
| Path | Resource type | Content |
|-----------------+------------------+------------------------------------------------------|
| =/app/template= | =data-resources= | Templates and the metadata store (metadata.db) |
| =/app/config= | =config-resources= | Optional license, authentication public key (key.pub) |
Templates and their versioning metadata both live under =/app/template=,
so they survive redeploys and are covered by the =backup= relation.
* Enterprise license
Carbone runs fine without a license (Community Edition, forever free).
Advanced features (dynamic images/colors, barcodes, charts, HTML
aggregation, PDF operations, ...) require an Enterprise license.
To enable it, drop your =*.carbone-license= file into the config store
(=/app/config= on the host side, i.e.
=$SERVICE_CONFIGSTORE/app/config=) and redeploy the service.
* API authentication
Authentication is *disabled by default*: the API is reachable as soon as
the service is up, which is the expected setup behind the =web-proxy=.
If you ever need an API key (JWT), enable =CARBONE_AUTHENTICATION=true=,
generate an EC keypair with =generate-keys=, expose the public key as
=/app/config/key.pub= and generate a token with =generate-token=. See
the upstream "Deploy with Docker" documentation for the exact commands.

47
carbone/hooks/init Executable file
View File

@@ -0,0 +1,47 @@
#!/bin/bash
## Init is run on host
## For now it is run every time the script is launched, but
## it should be launched only once after build.
## Accessible variables are:
## - SERVICE_NAME Name of current service
## - DOCKER_BASE_IMAGE Base image from which this service might be built if any
## - SERVICE_DATASTORE Location on host of the DATASTORE of this service
## - SERVICE_CONFIGSTORE Location on host of the CONFIGSTORE of this service
set -e
## The image runs as the unprivileged "carbone" user, while the datastore
## and configstore bind mounts are created by root. Both /app/template
## (templates + metadata.db) and /app/config (config.json, keys, license)
## must be writable by that user, otherwise the container crash-loops with
## "EACCES: permission denied, open '/app/config/config.json'".
uid_gid=($(docker_get_uid_gid "$SERVICE_NAME" "carbone" "carbone")) || exit 1
uid="${uid_gid[0]}"
gid="${uid_gid[1]}"
mkdir -p "$SERVICE_DATASTORE/app/template" "$SERVICE_CONFIGSTORE/app/config"
chown "$uid:$gid" "$SERVICE_DATASTORE/app/template" "$SERVICE_CONFIGSTORE/app/config"
## Carbone starts in stateless mode (document generation only) and binds
## to 127.0.0.1 by default (see `carbone webserver --help`, v5.15.1).
## Inside Docker it must:
## - listen on all interfaces so the web-proxy can reach it (CARBONE_BIND) ;
## - serve the Studio web interface and /carbone-studio.js (CARBONE_STUDIO) ;
## - enable stateful template management: stable 64-bit template IDs,
## versioning and the GET/POST/PATCH /template endpoints
## (CARBONE_TEMPLATE_MANAGEMENT).
##
## CARBONE_TEMPLATE_METADATA_FLUSH_CRON defaults to once a day; flushing
## every 5 minutes shrinks the window where a hard crash (SIGKILL, OOM)
## would lose template metadata. The graceful-shutdown flush remains the
## safety net for redeploys (see docker-compose.stop_grace_period).
init-config-add "
$SERVICE_NAME:
environment:
CARBONE_BIND: \"0.0.0.0\"
CARBONE_STUDIO: \"true\"
CARBONE_TEMPLATE_MANAGEMENT: \"true\"
CARBONE_TEMPLATE_METADATA_FLUSH_CRON: \"*/5 * * * *\"
"

View File

@@ -1,7 +1,20 @@
## From carbone/carbone-ee:full-5.4.2 ## From carbone/carbone-ee:full-5.15.1
docker-image: docker.0k.io/carbone-ee:5.4.2 docker-image: docker.0k.io/carbone-ee:5.15.1
docker-compose:
## Carbone flushes its template metadata to disk on graceful shutdown.
## Docker's default 10s stop timeout is shorter than Carbone's shutdown
## sequence (exitQuietPeriod + flush), so a plain redeploy would SIGKILL
## it and lose the templates/versioning. Keep this above Carbone's
## exitDeadline (default 3 min).
stop_grace_period: 200s
data-resources: data-resources:
## Templates and the template-management metadata store (metadata.db)
## both live here, so they survive redeploys and are covered by backup.
- /app/template - /app/template
config-resources:
## Holds the optional Enterprise license (*.carbone-license) and the
## authentication public key (key.pub). See README.org.
- /app/config
uses: uses:
web-proxy: web-proxy:

View File

@@ -0,0 +1,2 @@
carbone-test:
charm: carbone