Maintenance
Everyday commands
Section titled “Everyday commands”docker compose ps # status including health checksdocker compose logs -f aimiddleware # follow middleware outputdocker compose restart ktdocker # restart one servicedocker compose down # stop everything; data is keptdocker compose up -d # start again / apply a changeChanging rw/ktbs.cl requires a restart of the application:
docker compose restart ktdockerOne-off commands against the instance:
docker compose --profile tools run --rm cms /finish-installationdocker compose --profile tools run --rm -it cms \ /reset-administrator user@example.comThe application writes its log files inside the container to /rw/var/log,
visible on the host under rw/var/log/. It rotates them once per day into
rw/var/log.bak/, so two generations are kept.
# application logs on the hostsudo ls -l rw/var/log/
# container outputdocker compose logs --tail 100 ktdockerThe container output is normally almost empty, but it is where startup failures
show up — a failed database connection, for instance, never reaches
rw/var/log/ because the application does not get that far.
Reverse proxy
Section titled “Reverse proxy”The application speaks plain HTTP on port 8080. TLS termination and public exposure are the reverse proxy’s job (nginx, HAProxy, Caddy).
Three requirements:
- The proxy must be reachable under the host name configured as
:proxy-host-nameinrw/ktbs.cl. A mismatch produces broken redirects. - The proxy must send
X-Forwarded-Proto: https. The application marks session cookies asSecureonly when that header sayshttpsand:proxy-protocol-schemeis"https". Without the header the cookies go out unprotected. - It should also send
X-Forwarded-Hostwith the public host name. If it does not, the application falls back to:proxy-host-namefromrw/ktbs.cl, so both have to agree.
Backup
Section titled “Backup”Two things carry state that cannot be recreated:
- the database
rwshared/— the file blobs of the disk pool
Both belong in the same backup, from the same point in time. Restoring only one of them gives you an instance whose records point at documents that are not there, or the other way round.
rw/ is largely derived and does not have to be backed up: the configuration
comes from rap.config.sh, the license from the installation directory, and
the links and directories are recreated by the container on every start. The
exception is rw/var/, where queued tasks and import/export working
directories live — include it if you rely on those features.
Upgrading the application
Section titled “Upgrading the application”# 1. Set the new image tag$EDITOR docker-compose.yml
# 2. Pull and recreatedocker compose pulldocker compose up -dup -d is what applies the change: Compose replaces containers whose
configuration differs from the file, so the new tag takes effect.
docker compose restart would not — it restarts the existing container with
the image it already has.
Replacing the license
Section titled “Replacing the license”The license file is read at startup, so a new one takes effect with a restart of the application. Nothing else changes.
sudo cp <new-license>.cl rw/license.clsudo chown 1234:1234 rw/license.clsudo chmod 0400 rw/license.cl
docker compose restart ktdockerKeep the original file in the installation directory as well — its name records which application version the license is bound to.
Disk space
Section titled “Disk space”rwshared/ is the part that grows. Watch it:
du -sh rwshared/df -h .Neither log location grows without bound: the container logs are capped by the Compose file, and the application logs keep two generations.