This repository contains a reproducible local or LAN test deployment for the GigaTIFF Kramerius Stack: Kramerius 7.2.1.2 connected to the GigaTIFF IIIF image server.
It tracks configuration and installation scaffolding only. Runtime databases, Akubra object-store data, Solr indexes, imported NDK packages, generated JP2 files, logs, caches and temporary files are intentionally ignored.
Stack version means a tested integration bundle. Component versions keep their own upstream meaning.
Current bundle:
GigaTIFF Kramerius Stack: stack-0.1.13
Runtime directory: gigatiff-kramerius
Compatibility matrix:
Core:
Kramerius API: 7.2.1.2
Kramerius web client v3: 3.0.22-beta
Kramerius admin client: c36565ff75591bc593bc042b31b83b7b6dd17869
GigaTIFF server: 0.3.2
Web-client auth shim: 0.1
Services:
Curator worker: 7.2.1.2
Public worker: 7.2.1.2
Process manager: 1.5
Solr: 10.0.0
PostgreSQL: 18.4
Keycloak PostgreSQL: 14.10
Keycloak: 22.0.11-1.10
Dragonfly: 1.30.3
The machine-readable source of truth is versions.toml.
stack-0.1.5 refreshes the GigaTIFF server image to 0.3.1. That image builds
Grok from upstream commit 06c96bfbc38c74d386ce27018002d3febfff8f0c, which
fixes the lossy RPCL JP2 region/reduce artefact reproduced during local testing.
The recommended JP2 runtime mode remains the hybrid auto mode: OpenJPEG is the
primary decoder and Grok is available as fallback or an explicitly selected
backend.
stack-0.1.6 upgrades the Kramerius API, curator worker and public worker to
7.2.1.1. Upstream release notes mention a new field in the search Solr index
for map/georeference search; the schema tracked in this repository was compared
against the v7.2.1.1 Solr 9 schema and already contains the required fields.
Existing data with maps or georeferences should still be reindexed after the
upgrade so the new index content is populated.
stack-0.1.7 upgrades the Kramerius web client v3 to 3.0.16-beta. The
upstream release refreshes audio-recording pages, favorites-list behavior,
accessibility modes, collection display, metadata grouping, and several document
detail edge cases.
stack-0.1.8 upgrades the Kramerius web client v3 to 3.0.18-beta. This
upstream release changes the runtime configuration layout: client configuration
files are now served directly from /local-config/ instead of
/local-config/<krameriusId>/. The stack follows that layout, so the GigaTIFF
client configuration is tracked as public/local-config/config-main.json,
public/local-config/config-licenses.json and
public/local-config/config-homepage.json.
stack-0.1.9 upgrades the Kramerius web client v3 to 3.0.19-beta. The
upstream release adds optional loading of UI configuration from the Kramerius API
/ui-config/ endpoints. This stack keeps local public/local-config/* files as
the default source of truth and writes apiConfigBaseUrl: "" plus
forceApiConfig: false into assets/env.json; API-loaded configuration can be
enabled later with APP_API_CONFIG_BASE_URL and APP_FORCE_API_CONFIG=true.
The local config-main.json was also aligned with the new upstream config shape
by adding explicit integrations/export settings, features.showExportHistory,
the broader document-type list, and search.facetThreads.
stack-0.1.10 upgrades the Kramerius web client v3 to 3.0.20-beta. The
upstream release focuses on fixes for favorites-list searches, collection data
loading, multivolume-publication search pagination and counts, periodical
filters, year-range validation, mobile reader controls, FAQ display and updated
localization. The runtime configuration shape was checked against the
trinera/cdk-client:3.0.20-beta image and remains compatible with the
stack-0.1.9 local-config layout.
stack-0.1.11 upgrades the Kramerius API, curator worker and public worker to
7.2.1.2. Upstream release notes cover PDF page indexing, map search, SDNNT
license synchronization planning, synchronization process controls and ČDK
worker process changes. The release explicitly requires a Solr schema update and
core/collection reload for map search; this stack updates the tracked search
schema with the new exact-search, path-hierarchy, author-role and spatial fields.
stack-0.1.12 upgrades the Kramerius web client v3 to 3.0.21-beta. The
upstream release focuses on mobile-layout refinements, reader responsiveness,
page-search fixes, PDF viewer alignment, filter dialog loading behavior and CDK
source filtering. The runtime configuration shape was checked against
trinera/cdk-client:3.0.21-beta; this stack keeps local static configuration,
the same-origin auth bridge, the terms/login fallback and the square-corner UI
override.
stack-0.1.13 upgrades the Kramerius web client v3 to 3.0.22-beta and the
GigaTIFF server image to 0.3.2. The web-client release refreshes visual
styling, switches the upstream font family to IBM Plex, adjusts dark-mode and
high-contrast behavior, improves dynamic search placeholders, source-library
selection and reader link handling. The local configuration shape remains
compatible with the previous stack. GigaTIFF 0.3.2 rebuilds the server image
with Grok v20.3.9, including upstream decompressor fixes while keeping the
hybrid JP2 auto backend policy.
- Kramerius 7.2.1.2 API and workers.
- PostgreSQL databases for Kramerius, Keycloak and the process manager.
- Solr 10 with user-managed cores.
- Keycloak for OAuth2 authentication.
- A small web-client auth shim for Keycloak login/token/logout routes.
- Kramerius web client with GigaTIFF branding.
- Kramerius admin client.
- GigaTIFF IIIF image server with Dragonfly response cache.
- Optional Dockhand and Dashy helper tools.
docker-compose.yml- core Kramerius, Solr, Keycloak, workers, web client and admin client.docker-compose.gigatiff.yml- optional integrated GigaTIFF image server and Dragonfly cache.docker-compose.tools.yml- optional Dockhand and Dashy tools.docker-compose.clean.yml- clean-stack override for Buildah-built local images and bootstrap.docker-compose.ghcr.yml- clean-stack override for prebuilt GHCR images.versions.toml- stack version, component pins and GHCR image names.Containerfile.clean-bootstrap- small Debian Trixie bootstrap image for post-start checks and SQL helpers.Dockerfile.auth-shim- small Python auth bridge used by the web client.mnt/import/.kramerius4- Kramerius runtime configuration mounted into API and workers.mnt/containers/solr/data- Solr core configuration only, not generated indexes.public/local-config- web-client runtime configuration.public/favicon.svg- GigaTIFF favicon mounted into the web client.ops/admin-client- Docker build wrapper for the required admin client.ops/auth-shim- OAuth2 login/token/logout bridge for web-client v3.ops/bootstrap- clean-stack bootstrap entrypoint.ops/web-client- GigaTIFF web-client CSS and login fallback assets.ops/keycloak/kramerius-realm.json- disposable test realm import for Keycloak.ops/dockhand/register-stack.sh- Dockhand stack registration helper.ops/dashy/conf.yml- Dashy dashboard configuration.ops/sql/grant-public-read.sql- local test permission helper for public IMG_FULL access.ops/sql/normalize-process-owners.sql- local process manager owner cleanup helper.scripts/build-clean-images.sh- Buildah image builder for the clean stack.scripts/build-ghcr-images.sh- Buildah image builder using the public GHCR image tags.scripts/prepare-clean-stack.sh- creates a clean install directory from Git-managed files only.scripts/configure-endpoints.*- helpers for switching between localhost and LAN URLs.scripts/grant-public-read.*- helpers for applying the public read permission SQL.scripts/normalize-process-owners.*- helpers for fixing process owner JSON compatibility.
Install:
- Buildah on the Linux host that will build the clean local images.
- Docker with Compose v2.
- Git.
- PowerShell 7 or a POSIX shell, depending on which helper scripts you use.
Clone the required repositories side by side. Keep the source checkout and the
runtime deployment directory clearly separated; the examples use
gigatiff-kramerius-stack-src for the Git checkout and gigatiff-kramerius
for the live Compose stack.
mkdir services
cd services
git clone https://github.com/bezverec/gigatiff.git
git clone https://github.com/bezverec/gigatiff-kramerius-stack.git gigatiff-kramerius-stack-src
git clone https://github.com/ceskaexpedice/kramerius-admin-client.git
cd gigatiff-kramerius-stack-srcExpected layout:
services/
gigatiff/
gigatiff-kramerius-stack-src/
kramerius-admin-client/
The admin client checkout is required because the clean Buildah workflow builds
it from ../kramerius-admin-client.
The preferred installation path is the clean Buildah stack. It is the only recommended path for a reproducible test deployment.
Do not copy a running Kramerius directory to create a new install. A live directory may contain PostgreSQL data, Solr indexes, Akubra object-store files, converted JP2 files, logs and caches. The Buildah workflow creates fresh images and a fresh stack directory from Git-managed configuration only.
The clean workflow includes:
- Kramerius configuration.
- Solr schema fixes.
- Keycloak realm import.
- GigaTIFF-branded web-client files.
- Web-client login bridge for Keycloak.
- Integrated GigaTIFF image server and Dragonfly cache.
- Admin-client build output.
- Bootstrap checks and local test SQL helpers.
It deliberately excludes:
- imported NDK packages,
- generated JP2/TIFF image payloads,
- Akubra object-store data,
- PostgreSQL data,
- Solr index data,
- GigaTIFF response cache,
- logs or temporary files.
From the repository checkout, prepare a clean runtime directory:
./scripts/prepare-clean-stack.sh /home/bezverec/services/gigatiff-kramerius
cd /home/bezverec/services/gigatiff-krameriusConfigure endpoint URLs for the target host:
./scripts/configure-endpoints.sh 10.0.120.30 0.0.0.0If another Kramerius stack is already running on the same host, set alternate ports before running the helper:
WEB_CLIENT_PORT=2234 \
ADMIN_CLIENT_PORT=2235 \
KRAMERIUS_API_PORT=28088 \
KRAMERIUS_DEBUG_PORT=25005 \
KRAMERIUS_AJP_PORT=28009 \
KEYCLOAK_PORT=28990 \
SOLR_PORT=28983 \
LOCK_SERVER_PORT_1=25701 \
LOCK_SERVER_PORT_2=25702 \
LOCK_SERVER_PORT_3=25703 \
PROCESS_MANAGER_PORT=28082 \
CURATOR_WORKER_PORT=28084 \
PUBLIC_WORKER_PORT=28086 \
KRAMERIUS_DB_PORT=60432 \
PROCESS_DB_PORT=60433 \
GIGATIFF_PORT=38082 \
DOCKHAND_PORT=23000 \
DASHY_PORT=28080 \
./scripts/configure-endpoints.sh 10.0.120.30 0.0.0.0Build clean local images with Buildah. The build script reads .env, so run
endpoint configuration before this step:
./scripts/build-clean-images.shThe script builds:
localhost/gigatiff-kramerius-web-client:clean
localhost/gigatiff-kramerius-auth-shim:clean
localhost/gigatiff-kramerius-admin-client:clean
localhost/gigatiff-kramerius-bootstrap:clean
By default, it also publishes those images into the local Docker daemon so
Docker Compose can run them. Set PUSH_TO_DOCKER=0 if you only want Buildah
storage images.
The same stack can use prebuilt images from GitHub Container Registry instead of local Buildah images.
Published image names for stack-0.1.13:
ghcr.io/bezverec/gigatiff-kramerius-web-client:stack-0.1.13
ghcr.io/bezverec/gigatiff-kramerius-auth-shim:stack-0.1.13
ghcr.io/bezverec/gigatiff-kramerius-admin-client:stack-0.1.13
ghcr.io/bezverec/gigatiff-kramerius-bootstrap:stack-0.1.13
ghcr.io/bezverec/gigatiff-server:0.3.2
To publish them from GitHub Actions, run the Publish GHCR Images workflow or
push a tag named like stack-0.1.13. The workflow reads versions.toml, checks
out the pinned admin client and GigaTIFF revisions, builds Linux amd64 images,
adds OCI metadata, and publishes SBOM/provenance attestations.
To build the same tags locally with Buildah:
./scripts/build-ghcr-images.shBy default this builds the GHCR-tagged images and also publishes them into the local Docker daemon. To push to GHCR from a logged-in Buildah session:
buildah login ghcr.io
PUSH_TO_GHCR=1 ./scripts/build-ghcr-images.shTo run the stack from GHCR images instead of local Buildah images, add
docker-compose.ghcr.yml after the clean and GigaTIFF files and explicitly
disable local builds:
docker compose \
-f docker-compose.yml \
-f docker-compose.clean.yml \
-f docker-compose.gigatiff.yml \
-f docker-compose.ghcr.yml \
up -d --pull always --no-buildThe admin-client image is runtime-configured from .env, so the same GHCR image
works for localhost and LAN deployments.
Start the clean stack, including the GigaTIFF image server:
docker compose \
-f docker-compose.yml \
-f docker-compose.clean.yml \
-f docker-compose.gigatiff.yml \
up -dRun the bootstrap checks and disposable test permission helpers:
docker compose \
-f docker-compose.yml \
-f docker-compose.clean.yml \
--profile bootstrap run --rm clean-bootstrapclean-bootstrap waits for PostgreSQL, Solr, Keycloak and the Kramerius API,
checks that the Solr schema contains the fields required by our fixes, verifies
that the kramerius realm exists, applies ops/sql/grant-public-read.sql, and
applies ops/sql/normalize-process-owners.sql.
The clean stack imports the test Keycloak realm automatically from:
ops/keycloak/kramerius-realm.json
The imported disposable user is:
username: krameriusAdmin
password: krameriusAdmin
When you want to include the optional helper tools in the same clean deployment, compose the tools file as well:
docker compose \
-f docker-compose.yml \
-f docker-compose.clean.yml \
-f docker-compose.gigatiff.yml \
-f docker-compose.tools.yml \
--profile tools up -dUse a new target directory for every clean deployment. Do not run
prepare-clean-stack.sh over a directory that already contains a live database,
Solr index or imported documents.
The clean stack is configured by .env plus mounted configuration files under
mnt/import/.kramerius4, public/local-config and rewrite.config.
Generate .env with scripts/configure-endpoints.*.
For a localhost-only workstation:
./scripts/configure-endpoints.sh 127.0.0.1 127.0.0.1For a LAN host, for example ZimaBoard at 10.0.120.30:
./scripts/configure-endpoints.sh 10.0.120.30 0.0.0.0PowerShell equivalent:
.\scripts\configure-endpoints.ps1 -PublicHost 10.0.120.30 -BindAddr 0.0.0.0The helper updates:
.envmnt/import/.kramerius4/configuration.propertiesmnt/import/.kramerius4/keycloak.jsonmnt/import/.kramerius4/migration.propertiespublic/local-config/config-main.jsonpublic/local-config/libraries.jsonrewrite.config
The helper deliberately keeps two GigaTIFF addresses:
GIGATIFF_INTERNAL_BASE_URLis written intomigration.propertiesand is used by Kramerius and worker containers during import and image proxying.http://<KRAMERIUS_PUBLIC_HOST>:<GIGATIFF_PORT>/iiif/3is written intorewrite.configfor browser-facing legacy IIP rewrites.
For the clean stack, keep docker-compose.gigatiff.yml running on
GIGATIFF_PORT. Imported Akubra datastreams store
GIGATIFF_INTERNAL_BASE_URL; if that URL points to
host.docker.internal:<GIGATIFF_PORT> but no GigaTIFF server listens there,
ordinary search endpoints can still return 200 while thumbnails, IMG_FULL and
/search/iiif/.../info.json return HTTP 500.
On Docker Desktop, the default internal URL is
http://host.docker.internal:18082/iiif/3. If you run the integrated GigaTIFF
service on the same Compose network and want containers to talk directly, set:
export GIGATIFF_INTERNAL_BASE_URL=http://gigatiff-server:8080/iiif/3
./scripts/configure-endpoints.sh 127.0.0.1 127.0.0.1PowerShell equivalent:
.\scripts\configure-endpoints.ps1 `
-PublicHost 127.0.0.1 `
-BindAddr 127.0.0.1 `
-GigaTiffInternalBaseUrl http://gigatiff-server:8080/iiif/3The clean Buildah stack imports realm kramerius automatically from:
ops/keycloak/kramerius-realm.json
The imported realm contains:
- public client
krameriusClient, - roles
common_users,public_users,kramerius_adminandk4_admins, - disposable user
krameriusAdminwith passwordkrameriusAdmin.
The test realm deliberately uses longer local-development session limits than the Keycloak defaults:
Access token lifespan: 3600 seconds
SSO session idle timeout: 28800 seconds
SSO session max lifespan: 86400 seconds
Client session idle timeout: 28800 seconds
Client session max lifespan: 86400 seconds
Login code lifespan: 1800 seconds
This avoids repeated automatic logout during longer Admin UI import and metadata editing sessions.
Kramerius reads its Keycloak client settings from:
mnt/import/.kramerius4/keycloak.json
mnt/import/.kramerius4/configuration.properties
The expected values are:
keycloak.realm=kramerius
keycloak.clientId=krameriusClient
keycloak.tokenurl=http://keycloak.localhost:8990/realms/kramerius/protocol/openid-connect/tokenFor a LAN clean stack, the generated token URL uses the LAN host instead, for example:
keycloak.tokenurl=http://10.0.120.30:28990/realms/kramerius/protocol/openid-connect/tokenand:
{
"realm": "kramerius",
"auth-server-url": "http://keycloak.localhost:8990/",
"resource": "krameriusClient",
"verify-token-audience": false,
"bearer-only": true,
"public-client": true
}keycloak.localhost is intentional for local Docker use: it is resolvable from
both the host browser and the Kramerius container when the browser runs on the
same machine. For LAN deployments, the endpoint helper defaults
KEYCLOAK_PUBLIC_HOST to KRAMERIUS_PUBLIC_HOST, for example
10.0.120.30, so OAuth redirects are reachable from other computers.
Override KEYCLOAK_PUBLIC_HOST explicitly only when Keycloak should be exposed
through a different DNS name or reverse proxy.
The plain Compose workflow is kept for development and debugging only. It is not the preferred clean installation path.
Use it when iterating on Compose files or local configuration in the repository checkout:
docker compose up -d --buildWatch startup:
docker compose ps
docker compose logs -f --tail=100 krameriusThe first start can take a while because databases and Solr cores need to initialize.
For a fresh machine, also check that the process manager and both workers are running. Imports can be scheduled from the admin client even when workers are not yet polling correctly:
docker compose ps processManager curatorWorker publicWorker
docker compose logs --tail=100 processManager curatorWorker publicWorkerIf you use the development workflow without docker-compose.clean.yml, create
or import the Keycloak realm manually or adapt the clean realm import override
for your local workflow.
If you already run GigaTIFF elsewhere, keep it listening on the configured
GIGATIFF_PORT, default 18082.
To run the integrated GigaTIFF image server next to Kramerius:
docker compose \
-f docker-compose.yml \
-f docker-compose.clean.yml \
-f docker-compose.gigatiff.yml \
up -d --build gigatiff-serverThe integrated GigaTIFF compose uses:
- Dragonfly response cache.
jpeg2000-grok-ffiserver feature.- cache namespace
gigatiff-server-response-v12-jp2-auto-fix. - OpenJPEG FFI for full-resolution JP2 tiles and Grok FFI for reduced JP2 tiles.
Check readiness:
curl "http://127.0.0.1:${GIGATIFF_PORT:-18082}/readyz"
curl "http://127.0.0.1:${GIGATIFF_PORT:-18082}/metrics"Dockhand provides a lightweight Docker UI. Dashy provides a link dashboard.
Dashy browser links point to 127.0.0.1, while its status checks use Docker
service names so they work from inside the Dashy container.
Run the tools from the clean stack directory so they join the same Compose project and Docker network as Kramerius.
Start both:
docker compose -f docker-compose.tools.yml --profile tools up -dIf you want to start the clean stack, GigaTIFF and the tools in one command, use:
docker compose \
-f docker-compose.yml \
-f docker-compose.clean.yml \
-f docker-compose.gigatiff.yml \
-f docker-compose.tools.yml \
--profile tools up -dStop them:
docker compose -f docker-compose.tools.yml --profile tools downDashy config lives in:
ops/dashy/conf.yml
Each Dashy item has two URLs:
urlis the browser-facing localhost URL opened when you click the item.statusCheckUrlis the container-facing URL used by Dashy health checks.
For example, the web client opens as http://127.0.0.1:1234 in your browser,
but Dashy checks it from inside Docker as http://web-client/. If Dashy shows a
service as down while the browser link works, check that the service name in
statusCheckUrl matches the Compose service and that the tools were started
from this repo directory. Services from optional profiles, such as GigaTIFF, are
expected to show as down until that profile is running.
Dockhand gets the local compose stack registered automatically by
dockhand-init. The repo is mounted into the Dockhand container at:
/workspace/gigatiff-kramerius
The registered stack points Dockhand at:
/workspace/gigatiff-kramerius/docker-compose.yml
For the clean Buildah stack, add docker-compose.clean.yml in Dockhand when you
edit the registered stack.
If a .env file exists in the repository root, dockhand-init registers it as:
/workspace/gigatiff-kramerius/.env
The Docker socket is mounted into Dockhand, so it should manage the local Docker daemon directly. If Dockhand shows connection errors, first check:
docker compose -f docker-compose.tools.yml --profile tools logs dockhand-init
docker compose -f docker-compose.tools.yml --profile tools logs dockhanddockhand-init is idempotent. Re-run it after changing stack paths or the .env
file:
docker compose -f docker-compose.tools.yml --profile tools up dockhand-initIf you deploy on a LAN host, update URLs in ops/dashy/conf.yml or regenerate
endpoint config first and adapt the dashboard manually.
Portainer is intentionally not part of this stack. Use Dockhand for this test deployment to keep the operations surface small.
With default localhost settings:
- Web client:
http://127.0.0.1:1234 - Admin client:
http://127.0.0.1:1235 - Kramerius API:
http://127.0.0.1:8088 - Keycloak:
http://127.0.0.1:8990 - Solr:
http://127.0.0.1:8983 - GigaTIFF:
http://127.0.0.1:18082 - Dockhand:
http://127.0.0.1:3000 - Dashy:
http://127.0.0.1:18080
For a LAN deployment, replace 127.0.0.1 with KRAMERIUS_PUBLIC_HOST.
Example ports used for the side-by-side ZimaBoard clean stack:
- Web client:
http://10.0.120.30:2234 - Admin client:
http://10.0.120.30:2235 - Kramerius API:
http://10.0.120.30:28088 - Keycloak:
http://10.0.120.30:28990 - Solr:
http://10.0.120.30:28983
Put NDK import packages into:
mnt/import/.kramerius4/convert
Generated conversion output is written under:
mnt/imageserver/iip-data
Those directories are ignored by Git.
The import configuration is set for IIIF Image API 3 URLs:
convert.useImageServer=true
convert.imageServerTilesURLPrefix=http://host.docker.internal:18082/iiif/3
convert.imageServerImagesURLPrefix=http://host.docker.internal:18082/iiif/3
convert.imageServerSuffix.removeFilenameExtensions=false
convert.imageServerSuffix.tiles=
convert.imageServerSuffix.big=/full/max/0/default.jpg
convert.imageServerSuffix.thumb=/full/,128/0/default.jpg
convert.imageServerSuffix.preview=/full/,700/0/default.jpg
convert.imageServerDirectory=/mnt/imageserver/iip-data
convert.imageServerDirectorySubfolders=trueconvert.imageServerSuffix.tiles must stay empty. Kramerius appends
/info.json itself when proxying IIIF tiles. If the stored tiles-url already
contains /info.json, Kramerius will request .../info.json/info.json and the
viewer will fail.
When an import finishes, check the follow-up index process as well as the import process. A successful conversion can still be followed by a failed reindex if Solr rejects a field:
docker compose logs --tail=200 curatorWorker
docker compose logs --tail=200 solrIf the admin client process list fails with JSONObject["owner"] not a string.,
run the owner normalization helper before retrying the process view:
./scripts/normalize-process-owners.shAfter the first Kramerius boot and before testing public full-image access, run:
./scripts/grant-public-read.shPowerShell equivalent:
.\scripts\grant-public-read.ps1This applies ops/sql/grant-public-read.sql, granting root a_read to
common_users if it is missing. Without it, anonymous users may see thumbnails
but receive 403 for IMG_FULL or IIIF info.json.
This test stack contains a few deliberate local fixes. They are part of the reproducible setup, not accidental generated state.
The Solr configuration under:
mnt/containers/solr/data
is tracked in Git on purpose. Do not replace it with a freshly generated empty Solr core.
The file:
mnt/containers/solr/data/MUST_BE_SYNC_WITH_PROJECT.txt
documents that the local Solr config should stay in sync with the upstream Kramerius Solr 9.x installation profile:
https://github.com/ceskaexpedice/kramerius/tree/master/installation/solr-9.x
The most important core for the web client is:
mnt/containers/solr/data/search/conf/managed-schema
It includes fields used by the Kramerius/CDK web client detail and periodical views, for example:
pidmodelaccessibilityroot.pidown_parent.piddate.strdate.minpart.number.strissue.type.codelicensescontains_licenseslicenses.facet
It also includes fields emitted by the Kramerius 7.2 indexer and by the upstream Solr 9.x profile, for example:
authors.aut.facetauthors.aut.identifierscoords.is_pointcoords.bboxdate_instant.yearsubject_names_personal.searchsubject_names_corporate.facetsubject_temporals.searchsubtype
It also keeps copy rules used by license facets:
<copyField source="contains_licenses" dest="licenses.facet"/>
<copyField source="licenses" dest="licenses.facet"/>
<copyField source="licenses_of_ancestors" dest="licenses.facet"/>If the schema is incomplete, the web client can load the root object but fail on
children/facet queries with HTTP 500 responses from Kramerius. A typical failing
query asks Solr for fields such as date.str, own_parent.pid,
issue.type.code, licenses or sorts by date.min. Import or reindex jobs can
also fail with Solr unknown field errors for newer indexer fields such as
authors.aut.facet, authors.aut.identifiers or spatial fields such as
coords.bbox.
When changing Solr schema files:
- Stop Kramerius and Solr.
- Keep
mnt/containers/solr/data/*/conf/managed-schemaunder version control. - Remove generated Solr indexes only if you want a clean reindex.
- Start Solr and Kramerius again.
- Reindex or reimport affected objects.
For a quick schema sanity check:
grep -n 'own_parent.pid\|date.str\|licenses.facet\|authors.aut.identifiers\|coords.bbox\|subject_names_personal.search' \
mnt/containers/solr/data/search/conf/managed-schemaThe Czech Hunspell dictionary files referenced by managed-schema are tracked
with the Solr config so a fresh Solr core can start without missing analyzer
resources.
The logs core configuration is tracked as well. Kramerius writes access and
DNNT statistics there when documents and pages are opened. Its schema keeps
date.str as a string, year fields as integers and an *_str dynamic field for
Solr's schemaless copy-field processor. Without this, page access can still work
but Kramerius logs repeated Solr 500 errors such as:
copyField dest :'date.str_str' is not an explicit field and doesn't match a dynamicField.
ops/sql/grant-public-read.sql is an idempotent local test helper. It grants
root a_read to common_users.
This fixes the local-test situation where thumbnails are visible, but anonymous
users are still denied full images and IIIF info.json with HTTP 403.
Apply it after the first boot:
./scripts/grant-public-read.shKramerius admin client expects process owner values to be strings. Local or
manual process calls can leave older rows with owner as NULL or empty, which
can surface in the admin client as:
JSONObject["owner"] not a string.
Normalize existing rows after a clean rebuild or after manual process-manager API calls:
./scripts/normalize-process-owners.shPowerShell equivalent:
.\scripts\normalize-process-owners.ps1mnt/import/.kramerius4/migration.properties stores image-server URL suffixes.
The important values are:
convert.imageServerSuffix.tiles=
convert.imageServerSuffix.big=/full/max/0/default.jpg
convert.imageServerSuffix.thumb=/full/,128/0/default.jpg
convert.imageServerSuffix.preview=/full/,700/0/default.jpgconvert.imageServerSuffix.tiles must stay empty because Kramerius appends
/info.json when proxying IIIF tile metadata. If /info.json is stored in the
datastream already, requests can become .../info.json/info.json.
rewrite.config maps old IIP-style requests to GigaTIFF IIIF Image API 3 URLs.
This lets Kramerius paths that still call /fcgi-bin/iipsrv.fcgi resolve to the
same JP2 files served by GigaTIFF.
Examples:
FIF=...&HEI=128&CVT=jpeg -> /iiif/3/.../full/,128/0/default.jpg
FIF=...&HEI=700&CVT=jpeg -> /iiif/3/.../full/,700/0/default.jpg
FIF=...&CVT=jpeg -> /iiif/3/.../full/max/0/default.jpg
iiif=.../info.json -> /iiif/3/.../info.json
Run scripts/configure-endpoints.* again after changing the public host,
because it rewrites GigaTIFF URL prefixes in rewrite.config.
Some imported thumbnail URLs were observed to reach GigaTIFF as:
/iiif/3/<identifier>/full/
instead of the complete:
/iiif/3/<identifier>/full/,128/0/default.jpg
GigaTIFF contains a compatibility fallback for that truncated Kramerius thumbnail form and treats it as a 128-pixel-high JPEG thumbnail. Without that fallback, Kramerius reports thumbnail HTTP 500 errors because GigaTIFF correctly rejects the incomplete IIIF URL with HTTP 400.
The web client image is built through Dockerfile.web-client-gigatiff and uses:
web-client-entrypoint.sh
web-client-nginx.conf
public/favicon.svg
public/local-config
ops/web-client/gigatiff-square.css
ops/web-client/gigatiff-login-shortcut.js
The entrypoint injects local runtime URLs and replaces the upstream favicon with
the GigaTIFF SVG. The nginx config proxies /search/ to Kramerius and serves
legacy favicon paths from the same SVG to avoid stale browser icon references.
The entrypoint also injects a small GigaTIFF UI override. It keeps the current
web client functional, but makes the local test build visually sharper by
removing most rounded corners and by adding a visible login fallback button when
the upstream header does not render one. The fallback follows the upstream CDK
flow: from regular pages it opens /pages/terms?returnUrl=..., and from the
terms page it starts OAuth login through /auth/login.
The Kramerius web client v3 beta expects these same-origin routes:
/auth/login
/auth/token
/auth/logout
Kramerius 7.2.x exposes a different authentication facade, so the stack runs a
small auth-shim service built from Dockerfile.auth-shim. The web-client
nginx configuration proxies both /auth/* and
/search/api/client/v7.0/auth/* to this shim.
The shim:
- redirects
/auth/loginto the configured Keycloak realm, - exchanges
codefor tokens through the internal Keycloak URL, - refreshes tokens through the same Keycloak token endpoint,
- redirects
/auth/logoutto Keycloak logout, - exposes
/auth/healthzfor quick checks.
The public redirect target is controlled by:
KEYCLOAK_PUBLIC_HOST=10.0.120.30
KEYCLOAK_PORT=8990
WEB_CLIENT_PORT=1234For a LAN deployment, the expected quick check is:
curl http://127.0.0.1:1234/auth/healthz
curl -D - -o /dev/null "http://127.0.0.1:1234/auth/login?redirect_uri=http%3A%2F%2F10.0.120.30%3A1234%2Fauth%2Fcallback"The stack expects ../kramerius-admin-client to exist before docker compose up.
The admin build uses:
ops/admin-client/Dockerfile.gigatiff
It injects local GigaTIFF and Kramerius URLs into:
assets/shared/globals.js
If the public host or ports change, rerun scripts/configure-endpoints.* and
rebuild the admin client:
docker compose up -d --build admin-clientCheck stack status:
docker compose ps
docker compose logs --tail=100 krameriusCheck Keycloak:
docker compose ps keycloak_eduid
curl http://127.0.0.1:8990Check web-client login bridge:
docker compose ps auth-shim web-client
curl http://127.0.0.1:1234/auth/healthz
curl -D - -o /dev/null "http://127.0.0.1:1234/auth/login?redirect_uri=http%3A%2F%2F127.0.0.1%3A1234%2Fauth%2Fcallback"
curl -fsS http://127.0.0.1:1234/ | grep -E 'gigatiff-square|gigatiff-login-shortcut'Check GigaTIFF:
curl http://127.0.0.1:18082/readyz
curl http://127.0.0.1:18082/metricsIf login redirects still use keycloak.localhost from a LAN browser, or the web
client login button sends users to an unreachable host, rerun the endpoint
helper with the LAN host and restart Keycloak, Kramerius, auth-shim and the web
client:
./scripts/configure-endpoints.sh 10.0.120.30 0.0.0.0
docker compose -f docker-compose.yml -f docker-compose.clean.yml up -d keycloak_eduid kramerius auth-shim web-client admin-clientFor the side-by-side ZimaBoard clean stack, keep the alternate ports in .env
when rerunning the helper.
Use one browser hostname consistently during login. Mixing 127.0.0.1,
localhost, keycloak.localhost and a LAN IP in the same login flow can leave
stale Keycloak cookies and produce:
Cookie not found. Please make sure cookies are enabled in your browser.
If that happens, close old login tabs, clear cookies for the Keycloak host you
are using, rerun scripts/configure-endpoints.* with the intended public hosts,
and rebuild/restart web-client, admin-client, keycloak_eduid and
kramerius.
If the web client still shows MZK/CDK data, verify the runtime config served by the local nginx container:
curl http://127.0.0.1:1234/local-config/libraries.json
curl http://127.0.0.1:1234/local-config/config-main.jsonThe browser console should report that configuration was loaded for library
gigatiff, and API calls should go to http://127.0.0.1:8088, or to your
configured KRAMERIUS_PUBLIC_HOST. If not, rerun scripts/configure-endpoints.*,
rebuild web-client, and hard-refresh the browser.
If thumbnails load but the main image returns 403, apply:
./scripts/grant-public-read.shIf IIIF info.json returns 500 and logs show a URL ending in
info.json/info.json, verify:
convert.imageServerSuffix.tiles=Then re-import the affected object or patch existing Akubra FOXML datastreams.
If small thumbnails return 500 and Kramerius logs show a GigaTIFF URL ending in
/full/, make sure GigaTIFF includes the compatibility fallback for truncated
Kramerius thumbnail URLs.
Treat upgrades as clean rebuilds unless you intentionally want to preserve runtime databases and imported documents.
Recommended upgrade flow:
cd /home/bezverec/services/gigatiff-kramerius-stack-src
git pull --ff-only
./scripts/prepare-clean-stack.sh /home/bezverec/services/gigatiff-kramerius-new
cd /home/bezverec/services/gigatiff-kramerius-new
./scripts/configure-endpoints.sh 10.0.120.30 0.0.0.0
./scripts/build-clean-images.sh
docker compose \
-f docker-compose.yml \
-f docker-compose.clean.yml \
-f docker-compose.gigatiff.yml \
up -d
docker compose \
-f docker-compose.yml \
-f docker-compose.clean.yml \
--profile bootstrap run --rm clean-bootstrapFor side-by-side testing, use alternate ports as shown in Default Install.
After the new stack is verified, switch external routing or bookmarks to the new
ports. Keep the previous stack directory until the new one is confirmed.
When changing Kramerius, Solr, Keycloak or admin-client versions:
- update
versions.toml, - update image tags in the Compose files,
- rebuild the Buildah images,
- republish GHCR images when the tested bundle changes,
- run
docker compose config --quiet, - run
clean-bootstrap, - check Solr logs for schema/index incompatibilities,
- reimport or reindex test documents if the Solr schema changed.
Do not copy old mnt/containers/* database or Solr index directories into a
clean upgrade unless you are explicitly testing an in-place data migration.
Stop containers without deleting data:
docker compose -f docker-compose.yml -f docker-compose.clean.yml down
docker compose -f docker-compose.gigatiff.yml down
docker compose -f docker-compose.tools.yml --profile tools downRuntime data lives under:
mnt/
logs/
temp/
cache/
Delete those directories only when you intentionally want a fresh test instance.
These credentials are disposable and must not be reused in production:
- PostgreSQL Kramerius:
fedoraAdmin/fedoraAdmin - PostgreSQL process manager:
process/process - Keycloak admin:
keycloakAdmin/keycloakAdmin - Example Keycloak/Kramerius admin user:
krameriusAdmin/krameriusAdmin
For production-like testing, replace all passwords, restrict bind addresses and review every public port before exposing the stack.