Skip to content

Installation

The GoodWorkshop Community Edition runs as one container image plus Postgres, started with Docker Compose. There is no license fee for planning and running your workshops, not even for commercial use. If you don’t want to run a server: GoodWorkshop Cloud is the same product, hosted.

This page summarizes the installation. The authoritative source is the Installation (on-premise) section of the README.

What Requirement
Docker Docker with Compose v2 (docker compose version), amd64 or arm64
Hostname A name that publicly resolves to this server
Ports 80 and 443 free — Let’s Encrypt needs both for the certificate
Database Nothing to do: Postgres runs in the stack and isn’t reachable from outside
Passwords Nothing to do: the stack generates the database passwords itself on first start

You need compose.yaml, Caddyfile and a .env:

Terminal window
git clone https://github.com/roleALPHA/good-workshop.git
cd good-workshop
cp .env.example .env

The releases live in the GitHub Container Registry. compose.yaml pulls the image that GW_VERSION names. latest always points to the newest stable release. Each release is also available under its own number — that way you stay on one version until you update yourself. You don’t need to build anything.

Three values are required. If one is missing, the stack doesn’t start and names the missing value:

Terminal window
GW_APP_URL=https://workshop.example.com # the address the app is reachable at
GW_HOSTNAME=workshop.example.com # the name in the certificate (profile `tls`)
GW_VERSION=latest # the newest stable release, or e.g. 0.8.22 to pin one

Mail can wait. For the first start you don’t need mail delivery: the setup page shows your sign-in link itself. Afterwards you set up delivery in the interface under Mail delivery, see Mail delivery. All other variables are listed under Configuration.

Terminal window
docker compose --profile tls up -d

The following happens in order:

  1. secrets generates the database passwords, one per role.
  2. db starts.
  3. migrate creates the roles, checks the existing data, applies the migrations and sets up the block types.
  4. app only starts once migrate has completed cleanly.
  5. caddy takes over ports 80 and 443 and fetches the certificate.

When everything is running, the health check answers:

Terminal window
curl -fsS https://workshop.example.com/api/health
# {"status":"ok","checks":[{"name":"database","ok":true},{"name":"migrations","ok":true}]}

A 503 isn’t a crash, but the honest answer “this container can’t serve”. checks says whether it’s down to the database or the migration state.

5. Take over the installation in the browser

Section titled “5. Take over the installation in the browser”

A fresh installation announces itself in the log at every start until someone takes it over:

Terminal window
docker compose logs app
This installation has no administrator yet.
https://workshop.example.com/setup
Setup key: 7Qb3…
The key is valid until this process restarts.
  1. Open the /setup address shown.
  2. Enter First name, Last name and Your e-mail address.
  3. Paste the Setup key from the log.
  4. Click Set up this installation.

If no mail delivery is set up yet, the sign-in link is shown right on the page. It works once and then expires. Everything else — mail delivery, more people, branding — you take care of in the interface afterwards.

From the command line, with a shell on the server:

Terminal window
docker compose exec app node scripts/cli.mjs admin create \
--email you@example.com --first-name Anna --last-name Berger

On the very first start: Set GW_BOOTSTRAP_ADMIN_EMAIL=you@example.com in the .env before the stack starts up for the first time. The link is then in docker compose logs migrate, is valid for one hour and is printed exactly once. This is meant for installations that a script sets up rather than a person.

If you can’t find the key or the link, Sign-in and sign-in link will help.