Install automation with blueprints¶
A blueprint is a JSON file that describes an Omeka S instance: the modules and themes it needs, the
files to place in it, the vocabularies and resource templates to import, the users, the sites and the
settings. blueprint:deploy reads it and runs the omeka-s-cli commands that bring an instance to that
state. With the database credentials on the command line, the same command also downloads and
installs Omeka S, so one command takes an empty server to a working site.
The format is the shared Omeka S blueprint specification, which documents every key. This page explains how omeka-s-cli applies a blueprint; the commands and their options are on the Blueprints commands page.
Write a blueprint¶
This blueprint, saved as ~/blueprints/site.blueprint.jsonc like the other examples on this page,
sets up a small collection site:
{
// lets your editor complete and check the file
"$schema": "https://omeka-s-contrib.github.io/omeka-s-blueprints/schema/v0/blueprint-schema.json",
"meta": {
"title": "Collections site",
"description": "A small Omeka S instance for an object collection."
},
// used by the core phase only; the password comes from --admin-password
"install": {
"title": "Digital Collections",
"locale": "en_US",
"timezone": "Europe/Brussels",
"admin": { "name": "Site Admin", "email": "admin@example.org" }
},
"modules": [
// a shared list, replaced in place by its entries
{ "$import": "./shared/modules.jsonc" }
],
"themes": [
"default"
],
"vocabularies": [
{
"prefix": "coll",
"namespaceUri": "https://example.org/ns/collection#",
"label": "Collection",
"source": "./vocabularies/collection.ttl",
"format": "turtle"
}
],
"resourceTemplates": [
{ "source": "./templates/book.json" }
],
"users": [
// no password: the editor sets one with "Forgot password"
{ "email": "editor@example.org", "username": "Collection Editor", "role": "editor" }
],
"sites": [
{
"title": "Collections",
"slug": "collections",
"theme": "default",
"setAsDefault": true,
"permissions": [ { "user": "editor@example.org", "role": "editor" } ]
}
],
"settings": [
{ "installation_title": "Digital Collections" },
{ "$import": "./shared/settings.json" }
]
}
Blueprints may contain // and /* */ comments and trailing commas (jsonc). The $schema key
gives editors that understand JSON Schema completion and inline validation. Every key is optional.
A few things the specification leaves to the tool:
- A module given only by name gets the state
activate(install and enable).installinstalls it without enabling it;downloadonly puts the files inmodules/. - Without a
source, a module or theme is looked up by name, asmodule:download <name>andtheme:download <name>do. Asourcecan be anythingmodule:downloadaccepts: a zip release URL, a local zip (relative to the blueprint), a git URL orgh:owner/repo.versionpicks the catalog release or the git tag. - A module or theme that is already in
modules/orthemes/is used as it is, unlessversiondiffers from the one on disk or you deploy with--update. - A user without
passwordcannot log in until a password is set (for example with Forgot password).roledefaults toauthor. - A site is identified by its
slug, or by its title when it has none. Itsthememust be listed inthemes;defaultships with Omeka S and always counts. settingsis a map of global settings, or a list of maps and$importreferences merged in order (a later value wins).itemsanditemSetsare validated, but not created yet.meta,preferredVersions.phpand top-levelx-keys are accepted and ignored.
Check the blueprint before you deploy it:
Deploy from scratch¶
Point --base-path at an empty directory (or one that does not exist yet) and give the credentials of
an existing, empty database:
omeka-s-cli blueprint:deploy ~/blueprints/site.blueprint.jsonc \
--base-path /var/www/omeka-s \
--db-host db --db-name omeka --db-user omeka --db-password "$DB_PASSWORD" \
--admin-email admin@example.org --admin-password "$ADMIN_PASSWORD"
The deploy downloads Omeka S, writes config/database.ini, installs Omeka S, and then runs the other
phases. The database must exist and the user must be allowed to create tables in it: the deploy does
not create databases. See the core phase for the details.
Set the administrator
The administrator comes from --admin-name, --admin-email and --admin-password, else from
install.admin in the blueprint. Without either, it is admin@example.com with the password
admin. Always pass --admin-password from an environment variable or a secret store.
Phases and order¶
A deploy runs these phases, in this order, and reports each one:
| Phase | Blueprint key | What it does |
|---|---|---|
core |
install, preferredVersions.omeka |
download, configure and install Omeka S (core:*) |
modules |
modules |
module:download, then module:install or module:enable |
themes |
themes |
theme:download |
files |
files |
copy (or unzip) files into the Omeka S directory |
vocabularies |
vocabularies |
vocabulary:import |
resourceTemplates |
resourceTemplates |
resource-template:import (needs the Common module) |
users |
users |
user:add |
sites |
sites |
site:add, site:update (with --update), site:set-permission |
settings |
settings |
config:set |
Vocabularies come before resource templates, so the properties a template uses exist. Users come
before sites, because a site permission names a user. Settings come last, so a module that writes its
defaults when it is installed cannot overwrite them. files destinations are relative to the Omeka S
directory (no absolute paths, no ..), so a file can land inside a module that was just downloaded.
A module's services are only available in a process that starts with the module already active. The
deploy therefore installs every module in a new process of its own, in the order of the blueprint,
and runs the phases from vocabularies on in one more process. List a module after the modules it
depends on (Common first); if the order is wrong, Omeka S reports the missing dependency and the
deploy stops.
--skip leaves out phases, --dry-run lists the actions without performing them. See
the commands page.
Re-run a deploy¶
A deploy can be repeated: what already exists is left alone. To apply a blueprint to an installed
instance without reinstalling it, skip the core phase and confirm with --force:
omeka-s-cli blueprint:deploy ~/blueprints/site.blueprint.jsonc --base-path /var/www/omeka-s --skip core --force
Modules and themes on disk, existing vocabularies, resource templates, users and sites, and existing
permissions are skipped with a note. Settings and files are written every time. With --update, the
deploy also replaces modules, themes, vocabularies and resource templates, and updates sites and
permission roles. Users and permissions are never removed: a blueprint adds and updates, it does not
delete. See Deploy again.
The core phase¶
The core phase runs whenever you do not skip it, and needs --base-path. It:
- downloads Omeka S into
--base-path, unless that directory already holds an Omeka S installation. The version ispreferredVersions.omekafrom the blueprint, else the latest release. - writes
config/database.inifrom the--db-*options, unless the file already holds credentials. - checks that the database is reachable. If Omeka S is already installed in it, the deploy stops,
unless you pass
--force: then it drops all tables of the database. - installs Omeka S with the
title,localeandtimezonefrom the blueprint'sinstall(defaultsOmeka S,en_US,UTC) and the administrator from the--admin-*options orinstall.admin.
So --force without --skip core resets an instance and deploys the blueprint on a clean database:
omeka-s-cli blueprint:deploy ~/blueprints/site.blueprint.jsonc --base-path /var/www/omeka-s --force \
--admin-password "$ADMIN_PASSWORD"
A reset deletes all content
Items, media, sites, users and settings are gone after a reset. Back up the database first.
A reset keeps the existing database.ini, so the --db-* options are not needed (and are ignored).
The files in modules/ and themes/ stay; the module and theme phases install them again. Pass
--admin-password again: without it, the new administrator gets the password from
install.admin.password, else admin.
Share lists between blueprints¶
Any list in a blueprint (modules, themes, files, vocabularies, resourceTemplates, users,
sites, and the settings list) may contain { "$import": "<file or URL>" }. The entry is replaced by
the entries of the referenced list, in place. The site blueprint above imports this module list:
// The modules every site gets. Common comes first: other modules depend on it.
[
{ "name": "Common", "state": "activate" },
{ "name": "Sharing", "state": "activate" }
]
and this settings file:
A shared list can be validated on its own with --as:
omeka-s-cli blueprint:validate ~/blueprints/shared/modules.jsonc --as modules
omeka-s-cli blueprint:validate ~/blueprints/shared/settings.json --as settings
References are resolved relative to the file that contains them, may be nested, and may not be
circular. An entry that appears twice in a list (the same module or theme name, file destination,
vocabulary namespaceUri, resource template label, user email, site slug) is merged into the
first one: the fields of the later entry replace those of the earlier one, and the entry keeps its
first position. That lets a blueprint import a shared list and change one field, without changing the
module order:
{
"$schema": "https://omeka-s-contrib.github.io/omeka-s-blueprints/schema/v0/blueprint-schema.json",
"modules": [
// the shared list lives outside this directory: validate and deploy with --root
{ "$import": "../shared/modules.jsonc" },
// layering: keep Sharing in its place, but only download it
{ "name": "Sharing", "state": "download" }
],
"sites": [
{ "title": "Library", "slug": "library" }
]
}
Here Sharing stays second in the list, with the state download. The merge is shallow: a field
given again (a site's permissions, for example) is replaced as a whole. When a merge changes a
value, blueprint:validate and blueprint:deploy print a warning, so an accidental duplicate does
not go unnoticed.
Reference forms¶
The blueprint given on the command line, every $import, and the paths in files, vocabularies,
resourceTemplates (source) and in modules and themes (a local zip source) accept:
| Form | Example |
|---|---|
| Relative path | ./shared/modules.jsonc, ../shared/modules.jsonc |
| URL | https://example.org/blueprints/site.blueprint.jsonc |
| GitHub file URL | https://github.com/owner/repo/blob/main/site.blueprint.jsonc |
| GitHub short form | gh:owner/repo@main:site.blueprint.jsonc |
| GitLab file URL | https://gitlab.com/group/project/-/blob/main/site.blueprint.jsonc |
| GitLab short form | gl:group/project@main:site.blueprint.jsonc |
GitHub and GitLab file URLs are turned into raw download URLs; GitLab URLs are recognised by their
/-/blob/ segment, so self-hosted GitLab works too. In the short forms, @<branch, tag or commit> is
optional (default: HEAD); gl: always means gitlab.com. A blueprint fetched from a URL resolves its
relative references against that URL, so a blueprint in a repository can import its neighbours. Only
public files can be fetched.
Local references stay inside the root¶
A blueprint must not be able to read any file on the server it is deployed on. Inside a blueprint,
absolute paths, file: URLs and URLs other than http(s) (such as php:// or ftp://) are
rejected; gh: and gl: references are allowed. A relative path must stay inside the blueprint root:
the directory of the blueprint given on the command line. The library blueprint above imports
../shared/modules.jsonc, outside its own directory, so it needs --root:
--root works the same on blueprint:deploy. The path on the command line is not checked: it may be
absolute.
Capture an existing instance¶
blueprint:export writes a blueprint from a running instance, to reproduce it elsewhere or to start
a blueprint from. It covers modules, themes, vocabularies and sites (and, on request, site permissions
with their users), not settings or resource templates yet. See
Export an instance.
Keep secrets out of the blueprint¶
The database password and the administrator password are command-line options, so the blueprint can
go into version control. install.admin.password and the password of a user are stored in the
blueprint in clear text: a blueprint that contains them is a secret itself. Leave them out, and set
the passwords with --admin-password and user:update-password (or let users
use Forgot password).
Bundle a blueprint for offline deploys¶
A deploy downloads the Omeka S core, modules, themes and vocabularies from omeka.org, GitHub and
other hosts, so it fails when one of them is down. blueprint:bundle downloads all of them once into
one directory, and writes a blueprint.json there that only refers to files in that directory:
bundle/
blueprint.json # every $import inlined, every version pinned
core/omeka-s-4.2.1.zip # x-omeka-s-cli.install.source
modules/Common-3.4.71.zip
themes/freedom-1.0.7.zip
vocabularies/coll.ttl
resource-templates/book.json
files/logo.png
The bundle pins what it downloaded:
preferredVersions.omeka(the latest release if the blueprint had none);- every module and theme version;
- the format of each vocabulary.
Modules and themes are bundled as their release ZIPs, unchanged. A git or gh: source can't be
bundled, because a checkout may need build steps before it can be installed: point its source to a
release ZIP (a URL or a path) instead. Add-ons are named after their folder: a module after its
namespace, a catalog theme after its catalog folder.
The blueprint format has no field for the Omeka S release yet, so the bundle stores it in the CLI's
own extension key, x-omeka-s-cli.install.source. Other tools ignore that key. You can set it in any
blueprint, to a release ZIP path or URL, and the core phase installs from it.
Deploy the bundle with --self-contained. It refuses a blueprint that still refers to anything
outside its directory: a catalog name, a git repository, a URL, or a missing
x-omeka-s-cli.install.source.
A bundle can also live in a git repository or on a web server. Deployed from there, for example
gh:org/infra@v1:bundle/blueprint.json, it only downloads from that location.
Passwords in the blueprint (install.admin.password, user passwords) are copied into the bundle
unchanged. Keep them out of the blueprint and pass them at deploy time instead; see
Keep secrets out of the blueprint.
In a Docker image¶
Bundle in a build stage, which has network access. Deploy when the container starts, once the
database is reachable. Only the first start deploys: keep /var/www/omeka-s on a volume, and a
later start finds Omeka S installed and only starts the web server.
# Build stage: has network access, and downloads everything the blueprint needs.
FROM php:8.2-cli AS bundle
RUN apt-get update && apt-get install -y --no-install-recommends git unzip libzip-dev \
&& docker-php-ext-install zip && rm -rf /var/lib/apt/lists/*
COPY --from=composer:2 /usr/bin/composer /usr/local/bin/composer
ADD --chmod=755 https://github.com/GhentCDH/Omeka-S-Cli/releases/latest/download/omeka-s-cli.phar /usr/local/bin/omeka-s-cli
COPY site.blueprint.jsonc /src/
RUN omeka-s-cli blueprint:bundle /src/site.blueprint.jsonc /opt/bundle
# Runtime image (your PHP + web server image): deploys the bundle on the first start, with no
# downloads from omeka.org, GitHub or vocabulary hosts. Keep /var/www/omeka-s on a volume: a later
# start finds Omeka S installed and only starts the web server.
FROM your-omeka-runtime-image
COPY --from=bundle /usr/local/bin/omeka-s-cli /usr/local/bin/omeka-s-cli
COPY --from=bundle /opt/bundle /opt/bundle
CMD omeka-s-cli core:status --is-installed --base-path /var/www/omeka-s || \
omeka-s-cli blueprint:deploy /opt/bundle/blueprint.json --self-contained \
--base-path /var/www/omeka-s --db-host "$DB_HOST" --db-name "$DB_NAME" \
--db-user "$DB_USER" --db-password "$DB_PASSWORD" --admin-password "$ADMIN_PASSWORD" \
&& exec apache2-foreground
Omeka S Playground¶
The format started as the blueprint of the Omeka S Playground,
and a Playground blueprint deploys with omeka-s-cli as it is. Keys that only one tool understands live
under a top-level x- key (x-playground for the Playground's landing page and login, for example);
omeka-s-cli ignores them. Compared with the original Playground format, the specification adds
vocabularies, resourceTemplates, settings, files, module and theme version, the module state
download, and $import.