atbox packages AtoM as a small,
role-based container image family plus a Helm chart for attached deployments.
The project is scoped around separating public read traffic from authenticated
metadata-editing and lifecycle tasks while keeping all roles built from the same
AtoM source and dependency layers.
ghcr.io/sevein/atbox-public: public read-only web runtime.ghcr.io/sevein/atbox-admin: authenticated metadata-editing web runtime.ghcr.io/sevein/atbox-cli: lifecycle/CLI runtime for one-shot jobs.ghcr.io/sevein/atbox-worker: long-running AtoM Gearman worker runtime.ghcr.io/sevein/atbox-worker-toolchain: worker command-line toolchain only.
The chart in charts/atbox provides presets for read-only, admin-only, and
public-plus-admin topologies where MySQL, Elasticsearch, Memcached, and
Gearman are provided externally.
- Serve AtoM over
nginx+php-fpmwiths6-overlaysupervision for web roles. - Keep runtime web services (
nginx,php-fpm) on a non-root user. - Support public read-only browsing workloads backed by external MySQL, Elasticsearch, and Memcached.
- Isolate admin metadata-editing behavior in a separate image instead of a runtime switch on the public image.
- Provide a CLI image for lifecycle commands such as search indexing.
- Provide a worker image for AtoM background jobs backed by external Gearman.
- Ship Helm presets and validation coverage alongside the images.
atbox is a single container that runs:
s6-overlayas init/supervisor (/init)nginx(HTTP server)php-fpm(application runtime)
This is intentional for AtoM's legacy Symfony 1.x deployment model: fewer moving pieces, predictable startup ordering, and a simpler operational model for read-mostly workloads.
- Runtime services are expected to log directly to container streams.
php-fpmis configured to run in foreground with-Oand global logs routed to container output.- Symfony/application logging is configured for warning-level and above.
- No file-tail sidecars; no background
tail -flog shims.
- AtoM is forced into
read_only: true. - Uploads are disabled at PHP level.
- Session and cache behavior are explicitly configured for this profile.
atbox-admin is a separate image target, not a runtime switch on the public
image. It enables AtoM write behavior and accepts legacy form POST requests,
with uploads disabled by default. Enable uploads only when the admin tier has
shared writable uploads/ storage and an accompanying worker tier.
atbox-worker bootstraps the same AtoM config, connects to external Gearman,
and runs php -d memory_limit=-1 -d error_reporting=E_ALL symfony jobs:worker
as the non-root atbox user. The image includes the media and document tooling
used by AtoM jobs through the Nix-defined worker toolchain, including
ImageMagick, Ghostscript, Poppler, FFmpeg, Java, Apache FOP, and Unzip.
Worker abilities are the upstream AtoM defaults from generated gearman.yml.
The repository includes a Nix flake that defines the external command-line
tools AtoM expects from the runtime environment. The flake entrypoint remains
at the repository root, while the tool manifest and Nix implementation live
under nix/. This scope is intentionally limited to tools AtoM shells out to
directly, plus Ghostscript as the ImageMagick delegate required for PDF
derivatives. The covered paths are digital object derivatives, PDF text
extraction, PDF finding aid generation, SWORD package extraction, and small
command probes:
- ImageMagick:
convert,identify,mogrify,composite,magick - Ghostscript:
gs,ps2pdf - FFmpeg:
ffmpeg,ffprobe - Poppler utilities:
pdfinfo,pdftotext - Apache FOP:
fop - Java:
java - Unzip:
unzip - Which:
which
The aggregate packages are:
.#atbox-toolchain: all managed AtoM tools..#atbox-admin-toolchain: tools needed by admin web paths that can run in the request, including digital object uploads, derivative generation, PDF text extraction, and repository theme image cropping..#atbox-cli-toolchain: tools needed by AtoM CLI tasks that generate digital object derivatives, extract text, or generate finding aids..#atbox-worker-toolchain: tools needed by worker jobs, including finding aid generation, queued imports, derivative generation, text extraction, and SWORD package extraction.
Docker builds use these role-specific Nix aggregates as the source for AtoM external command tools in the admin, CLI, and worker images. The public read-only image does not include the AtoM toolchain.
The worker toolchain is also published as
ghcr.io/sevein/atbox-worker-toolchain:<tag> for downstream Docker builds that
need the same pinned tools without the full AtoM worker runtime. This image
contains only the Nix-built .#atbox-worker-toolchain closure and
/usr/local/bin shims. It does not include AtoM source, PHP, Gearman, nginx,
s6-overlay, entrypoints, or role rootfs files.
Downstream Dockerfiles can consume the toolchain as a build source:
COPY --from=ghcr.io/sevein/atbox-worker-toolchain:<tag> /nix /nix
COPY --from=ghcr.io/sevein/atbox-worker-toolchain:<tag> /usr/local/bin /usr/local/binUseful Nix commands on Linux, or on another host with a Linux builder:
nix build .#atbox-worker-toolchain
nix build .#atbox-cli-toolchain
nix run .#version-report
nix developThe toolchain does not include service dependencies or language/runtime
packages such as MySQL, Elasticsearch, Memcached, Gearman, PHP extensions,
nginx, s6-overlay, or the Saxon and XML resolver jars bundled by AtoM.
Those remain part of the application image, external services, or AtoM source
tree as appropriate.
atbox uses external Memcached for application cache and session storage, and
keeps PHP OPcache as an in-process opcode cache. ATOM_NAMESPACE scopes both
cache keys and the session cookie name.
In this public read-only profile, nginx allows only GET and HEAD requests
at the edge and rejects all other HTTP methods.
The read-only profile is for serving existing artifacts, not for anonymous
report-generation workflows that enqueue jobs and create new files under
downloads/reports. If you need report, finding-aid, or export generation, run
those workflows in a separate authenticated writer/admin tier.
In multi-instance deployments, uploads/ should use shared durable storage (for
example NFS), and downloads/ should be shared only if generated artifacts must
be available from every instance. The container paths are /atom/src/uploads
and /atom/src/downloads, matching AtoM's /atom/src web root. Public
read-only instances should mount these paths as read-only, while the
writer/admin tier and workers use read-write mounts. Native object-storage
semantics are not first-class in this image yet, so object storage currently
requires an external integration layer; upstream support remains a future
direction.
- HTTP listen port:
8080 - Runtime user:
atbox(UID/GID configurable) - External dependencies: MySQL + Elasticsearch + Memcached + Gearman
- Process supervision:
s6-overlayfor web roles
atbox-cli does not run s6-overlay; it bootstraps the same AtoM config and
then executes the supplied command, for example php symfony search:populate.
atbox-worker also does not run s6-overlay; it bootstraps config, drops to the
runtime user, and execs the worker command.
atbox is intentionally narrow in scope: a minimal, reliable, read-oriented
AtoM runtime container. It does not automatically bootstrap persistent state or
orchestrate environment-specific migration workflows (for example SQL dump
import, one-time Elasticsearch population, or cross-service idempotency/state
tracking). That transitional/bootstrap logic belongs outside this image so the
atbox runtime remains simple, stable, and reusable across environments.
In read-only environments, exposing existing files from uploads/* and
downloads/* is expected; creating new user-triggered artifacts from anonymous
requests is not part of the supported profile.
docker run --rm -p 8080:8080 \
-e ATOM_ELASTICSEARCH_HOST=elasticsearch:9200 \
-e ATOM_MEMCACHED_HOST=memcached:11211 \
-e ATOM_NAMESPACE=atom-prod-a \
-e ATOM_MYSQL_DSN='mysql:host=mysql;dbname=atom;charset=utf8mb4' \
-e ATOM_MYSQL_USERNAME=atom \
-e ATOM_MYSQL_PASSWORD='replace-me' \
ghcr.io/sevein/atbox-public:<tag>Then open http://localhost:8080.
For local development builds from this repository, see CONTRIBUTING.md.
| Variable | Required | Default | Notes |
|---|---|---|---|
ATOM_ELASTICSEARCH_HOST |
Yes | none | Elasticsearch endpoint (host[:port]). |
ATOM_GEARMAN_HOST |
No | 127.0.0.1:4730 |
Gearman endpoint (host[:port]). Required for job-backed admin/worker use. |
ATOM_MEMCACHED_HOST |
Yes | none | Memcached endpoint (host[:port]). |
ATOM_MYSQL_DSN |
Yes | none | PDO DSN for MySQL. |
ATOM_MYSQL_USERNAME |
Yes | none | MySQL username. |
ATOM_MYSQL_PASSWORD |
Yes | none | MySQL password. |
ATOM_NAMESPACE |
No | atom |
Convenience default used by cache/session namespace settings when they are not set directly. |
ATOM_CACHE_NAMESPACE |
No | ATOM_NAMESPACE |
Memcached key prefix. Set per tenant/deployment to avoid cache collisions. |
ATOM_WORKERS_KEY |
No | empty | AtoM worker key. Must match across admin, CLI, and worker roles sharing a Gearman server. |
ATOM_SESSION_NAME |
No | ATOM_NAMESPACE |
Session cookie name. Use a distinct value when public/admin tiers should not share login state. |
ATOM_SESSION_COOKIE_SECURE |
Admin only | true |
Set false only for local plain-HTTP admin testing. |
ATOM_SESSION_COOKIE_SAMESITE |
Admin only | lax |
One of strict, lax, or none. |
ATOM_OIDC_ENABLED |
Admin only | false |
Enables AtoM's arOidcPlugin and makes admin login use OIDC. |
ATOM_OIDC_PROVIDER_URL |
Admin OIDC | none | OIDC issuer/provider URL, for example a Keycloak realm URL. |
ATOM_OIDC_CLIENT_ID |
Admin OIDC | none | Confidential OIDC client ID used by the AtoM admin web runtime. |
ATOM_OIDC_CLIENT_SECRET |
Admin OIDC | none | Confidential OIDC client secret. Use a Kubernetes Secret in Helm deployments. |
ATOM_OIDC_REDIRECT_URL |
Admin OIDC | none | Public AtoM callback URL, ending in /oidc/login. |
ATOM_OIDC_LOGOUT_REDIRECT_URL |
Admin OIDC | none | Public URL where the identity provider redirects after logout. |
ATOM_OIDC_SEND_LOGOUT |
Admin OIDC | true |
Sends OIDC logout requests when the provider supports end-session. |
ATOM_OIDC_ENABLE_REFRESH_TOKEN_USE |
Admin OIDC | true |
Allows AtoM to use refresh tokens when the provider issues them. |
ATOM_OIDC_SERVER_CERT |
Admin OIDC | false |
Certificate path for provider validation, or false for local/test deployments. |
ATOM_OIDC_SET_GROUPS_FROM_ATTRIBUTES |
Admin OIDC | true |
Maps OIDC role claims into AtoM ACL group membership. |
ATOM_OIDC_SCOPES |
Admin OIDC | openid,profile,email |
Comma-separated OIDC scopes. |
ATOM_OIDC_ROLES_SOURCE |
Admin OIDC | access-token |
Token source for role claims. |
ATOM_OIDC_ROLES_PATH |
Admin OIDC | realm_access,roles |
Comma-separated path to role claims. |
ATOM_OIDC_USER_MATCHING_SOURCE |
Admin OIDC | oidc-email |
One of oidc-email or oidc-username. |
ATOM_OIDC_AUTO_CREATE_ATOM_USER |
Admin OIDC | true |
Creates missing AtoM users from trusted OIDC claims. |
ATOM_OIDC_USER_GROUPS_JSON |
Admin OIDC | built-in AtoM group mappings | JSON role-to-group map for AtoM ACL groups. |
ATOM_UPLOADS_ENABLED |
Admin only | false |
Enables PHP uploads and AtoM upload UI when shared writable storage is mounted. |
ATOM_UPLOAD_LIMIT |
Admin only | -1 |
AtoM upload limit in gigabytes; 0 disables uploads, -1 is unlimited. |
ATOM_PHP_POST_MAX_SIZE |
Admin only | 512M |
PHP post_max_size when uploads are enabled. |
ATOM_PHP_UPLOAD_MAX_FILESIZE |
Admin only | 512M |
PHP upload_max_filesize when uploads are enabled. |
ATOM_PHP_MAX_FILE_UPLOADS |
Admin only | 20 |
PHP max_file_uploads when uploads are enabled. |
ATOM_WORKER_MEMORY_LIMIT |
Worker | -1 |
PHP memory limit passed to the worker process. |
ATOM_WORKER_MAX_JOB_COUNT |
Worker | empty | Optional worker shutdown threshold after N completed jobs. |
ATOM_WORKER_MAX_MEM_USAGE |
Worker | empty | Optional worker shutdown threshold in kB RSS. |
This repository includes a chart in charts/atbox for attached deployments
where MySQL, Elasticsearch, Memcached, and Gearman are provided externally.
Presets are included for read-only, admin-only, and public-plus-admin
topologies:
helm template atbox charts/atbox \
--values charts/atbox/values-public-plus-admin.yamlThe chart exposes annotation maps on Deployments, Pods, Services, Jobs, and the
database Secret for GitOps tools such as Argo CD. Worker deployments require
existing PVCs for shared uploads/ and downloads/ storage.
Admin OIDC can be enabled through atom.admin.oidc. Use a dedicated
confidential identity-provider client for AtoM admin sessions and store the
client secret in a Kubernetes Secret:
atom:
admin:
enabled: true
oidc:
enabled: true
providerUrl: https://keycloak.example.org/realms/atom
clientId: atom-admin
clientSecret:
existingSecret: atom-admin-oidc
key: client-secret
redirectUrl: https://atom.example.org/oidc/login
logoutRedirectUrl: https://atom.example.orgEnabling OIDC automates the AtoM runtime configuration in the admin container:
the image enables arOidcPlugin, switches admin login to the OIDC module, uses
oidcUser, and writes the plugin provider configuration at startup. It does not
create the identity-provider client, migrate local AtoM users into the identity
provider, or guarantee account linking.
Before switching an existing admin deployment to OIDC:
- Create a dedicated confidential OIDC client for AtoM admin login.
- Add the AtoM callback URL to the client redirect allowlist.
- Choose
oidc-emailoroidc-usernamematching deliberately. - Verify existing AtoM users have matching email or username claims in the identity provider.
- Configure role claims and
userGroupsbefore allowing users to sign in. - Set
autoCreateAtomUser: falseif every admin user must be pre-created and explicitly matched.
When OIDC is enabled, admin login is OIDC-only. Existing local AtoM passwords remain in the database but are no longer the admin web login path for that runtime.