Gå till innehållet

Running Kurbits with Docker

Kurbits ships as a single Docker image containing both the backend and the built web interface.

Quick start

Pull the image and run it:

docker pull ghcr.io/kurbits-digital-preservation/kurbits-ais:latest

docker run -d --name kurbits-ais -p 8080:8080 \
  -e DATABASE_URL=sqlite:////app/database/kurbits.db \
  -v kurbits_db:/app/database \
  asegerberg/kurbits-ais

Then open http://localhost:8080 in your browser.

What the options do:

  • -d — runs the container in the background so your terminal is free; drop it if you'd rather watch the logs directly.
  • --name kurbits-ais — gives the container a fixed name so you can refer to it later (e.g. when running CLI commands below).
  • -p 8080:8080 — makes Kurbits available on port 8080 of your machine.
  • -e DATABASE_URL=sqlite:////app/database/kurbits.db — stores the database as a SQLite file inside the container.
  • -v kurbits_db:/app/database — keeps that database in a named Docker volume so your data survives when the container is replaced. Without this, your data is lost when the container stops.

Database migrations run automatically on startup.

Setting up your institution and admin user

Kurbits needs at least one institution and one admin user before anyone can log in. The backend exposes these as Flask CLI commands, which you run inside the running container with docker exec.

Fastest path: one-command demo setup

For trying Kurbits out or setting up a demo, dev-setup creates everything in one go — an institution, a system admin, the default hierarchies (ISAD(G), Library, Physical Storage, Classification), and default vocabularies:

docker exec -it kurbits flask dev-setup

This uses sensible defaults (institution "Demo Institution", admin admin@kurbits.dev / admin) and also creates an archivist and a read-only test user so you can try out role-based access. All of it is configurable:

docker exec -it kurbits-ais flask dev-setup \
  --institution-name "Gothenburg Municipal Archive" \
  --country-code SE \
  --institution-code GMA \
  --admin-email admin@example.org \
  --admin-password "a-much-stronger-password" \
  --no-extra-users \
  --language sv

The command prints a summary of every account it created (or found already existing) at the end, including credentials — keep that output somewhere safe, or better, change the password afterwards.

Step-by-step path: production setup

For a real deployment you'll usually want more control than dev-setup gives you. This is the same result built from the smaller building-block commands:

1. Create the institution:

docker exec -it kurbits-ais flask create-institution

This prompts you for --name, --slug, --country-code, and --institution-code interactively. You can also pass them directly as flags to skip the prompts:

docker exec -it kurbits-ais flask create-institution \
  --name "Gothenburg Municipal Archive" \
  --slug gothenburg-municipal-archive \
  --country-code SE \
  --institution-code GMA

Note the institution id it prints — you'll need it in the next steps.

2. Create your admin user:

docker exec -it kurbits-ais flask create-admin

Prompts for --username, --email, and --password (the password is hidden as you type and asked for twice to confirm). This creates a system admin — a user with full access across every institution.

3. Attach the admin to the institution:

docker exec -it kurbits-ais flask add-user \
  --email admin@example.org \
  --institution-id 1 \
  --role institution_admin

Replace 1 with the institution ID from step 1. This step also sets the institution as the user's active institution, so it's selected automatically on login. --role accepts institution_admin, archivist, or read_only — use institution_admin for the account you'll administer with day to day.

4. Seed default hierarchies and vocabularies:

docker exec -it kurbits-ais flask seed-hierarchies 1
docker exec -it kurbits-ais flask seed-vocabularies 1 --language en

Replace 1 with your institution ID again. seed-hierarchies installs the standard hierarchy types (ISAD(G), Library, Physical Storage, Classification); seed-vocabularies installs the default controlled vocabularies (--language accepts en or sv). Both skip silently if something's already been seeded — pass --force to seed-vocabularies to re-seed anyway.

You should now be able to log in at http://localhost:8080 with the admin email and password you chose.

Checking what exists

Two read-only commands are useful for verifying setup or troubleshooting later:

# List every institution, with its ID and reference-code prefix
docker exec -it kurbits-ais flask list-institutions

# List every user, or just the users in one institution
docker exec -it kurbits-ais flask list-users
docker exec -it kurbits-ais flask list-users --institution-id 1

If your container isn't named kurbits-ais

All the commands above assume you started the container with --name kurbits-ais, as shown in Quick start. If you used a different name, or didn't set one, substitute your own name, or find the container ID with:

docker ps

and use that in place of kurbits in the docker exec commands.

Keeping uploaded files

Attached files are stored separately from the database. To keep them too, add a second volume:

docker run -d --name kurbits-ais -p 8080:8080 \
  -e DATABASE_URL=sqlite:////app/database/kurbits.db \
  -v kurbits_db:/app/database \
  -v kurbits_uploads:/app/uploads \
  asegerberg/kurbits-ais

Building the image yourself

From the project root (the folder containing backend/ and frontend/):

docker build -t kurbits-ais .

Then run it with the same docker run command as above, substituting kurbits for asegerberg/kurbits-ais as the image name.

Common settings

Set these with additional -e flags if needed:

Variable Purpose
DATABASE_URL Database connection. SQLite (above) or PostgreSQL (postgresql://user:pass@host:5432/dbname)
SECRET_KEY Secret used to sign sessions — set a long random value in production
PORT Port inside the container (default 8080)

Updating

Pull the newest image and start a fresh container using the same volumes — your data is preserved:

docker pull asegerberg/kurbits-ais
docker stop kurbits && docker rm kurbits
docker run -d --name kurbits -p 8080:8080 \
  -e DATABASE_URL=sqlite:////app/database/kurbits.db \
  -v kurbits_db:/app/database \
  asegerberg/kurbits-ais