Install on a server
Jigsaw targets fresh or dedicated Ubuntu or Debian machines with public
hostnames. The installer configures Docker, clones the app to /opt/jigsaw by default, writes
secrets, pulls images from GitHub Container Registry, and starts the stack.
Prerequisites
| Requirement | Notes |
|---|---|
| OS | Ubuntu 22.04+ or Debian 12+. Other distros are not tested by the install script. |
| Hardware | At least 2 GB RAM and enough disk for Docker images, PostgreSQL data, and site files (plan for growth). |
| Network | Public IPv4 (or correct DNS/routing for your setup). Ports 80 and 443 must reach the host for HTTP-01 TLS. |
| Domain | A registered domain you control. You will point DNS at this server before or during install. |
| Access | SSH with sudo. The installer must run as root (use sudo). |
| Docker | Not required beforehand — the script installs Docker Engine and the Compose plugin if missing. |
ufw:
ufw allow OpenSSH && ufw allow 80/tcp && ufw allow 443/tcp && ufw enable
DNS before you run the installer
Create A records for the panel hostname, Keycloak, and Traefik dashboard. All three should point to the same public IP as your server (the installer checks public DNS against your detected public IP).
| Host | Type | Value |
|---|---|---|
panel.example.com |
A | Your server's public IP |
auth.panel.example.com |
A | Same IP |
traefik.panel.example.com |
A | Same IP |
Replace panel.example.com with the real FQDN you will enter when prompted (for example
panel.yourdomain.com). Keycloak is always at auth.<PANEL_DOMAIN> and the
Traefik UI at traefik.<PANEL_DOMAIN>.
Each customer site you create will need its own DNS record later (typically an A record to the same server).
SKIP_DNS_CHECK=1 sudo ./install.sh — only do this when you understand the TLS implications.
One-line install
Download and run the official installer from the main branch (review the script on GitHub first if you prefer):
curl -fsSL https://raw.githubusercontent.com/03c/jigsaw/main/install.sh | sudo bash
Equivalent steps (explicit temp file, same effect):
curl -fsSL https://raw.githubusercontent.com/03c/jigsaw/main/install.sh -o /tmp/jigsaw-install.sh \
&& chmod +x /tmp/jigsaw-install.sh \
&& sudo /tmp/jigsaw-install.sh
If you already cloned the repository (for example to /opt/jigsaw), run the script from that
directory:
cd /opt/jigsaw && sudo ./install.sh
What the installer does
- Installs Docker Engine and Compose if needed (APT on Debian/Ubuntu).
- Clones or updates the repo (default
/opt/jigsaw). - Prompts for panel domain, Let's Encrypt email, admin email, and Keycloak admin password.
- Generates or preserves secrets (
POSTGRES_PASSWORD,SESSION_SECRET, OIDC and OAuth2 proxy secrets). - Validates DNS for the panel and
auth.<domain>when possible. - Patches
keycloak/jigsaw-realm.jsonwith your domain and credentials. -
Pulls panel, PHP, and WordPress site images from
ghcr.io/03c/jigsaw/(builds locally if pull fails). - Runs
docker compose up -d, waits for PostgreSQL and Keycloak, updates OIDC redirect URIs, runsnpm run db:pushin the panel container. - Waits until HTTPS responds for the panel and auth hostnames.
After install
- Open
https://<PANEL_DOMAIN>— you will be redirected to Keycloak. -
Sign in with username
adminand the Keycloak admin password you set, or use Register to create a new account (new users get theuserrole and can create sites up to the configured limit). - Manage users and realm security settings at
https://auth.<PANEL_DOMAIN>(Keycloak admin console). - Open the Traefik dashboard at
https://traefik.<PANEL_DOMAIN>(OAuth2 Proxy + Keycloak).
Sign up, DNS, and WordPress
Self-service sign-up is enabled in the default Keycloak realm so visitors can register without the admin console. To require invitations only, disable registration in Keycloak: Realm settings → Login → User registration.
Per-site DNS: before creating a site for blog.example.com, add an
A record for that hostname to your server's public IP (same IP as the panel). Traefik
issues TLS certificates per hostname once DNS resolves correctly.
WordPress (MVP flow):
- In the panel, go to Create site, enter a site name and domain.
- Keep Create database and Install WordPress checked (defaults).
-
The panel provisions MariaDB, copies WordPress core from the WordPress site Docker image
into your site folder, writes
wp-config.php, then starts thejigsaw-wordpressweb container (same Nginx + PHP stack as generic sites, with baked core in the image). - Open
https://your-domainand complete WordPress's web installer (title, admin user).
New Keycloak accounts use verifyEmail=false in the imported realm so users can sign in
immediately. Turn on email verification in Keycloak if your deployment needs it.
Upgrading
cd /opt/jigsaw
git pull
docker compose pull
docker compose exec jigsaw npm run db:push
docker compose up -d
Rerunning sudo ./install.sh is also supported; it keeps existing .env secrets when present.
Manual install (advanced)
See the repository README — Manual install
for cloning, hand-written .env, realm patching, image pulls, and docker compose up.