From 6236f5d9a8ce8c615e4e69477ce57460ae763a5c Mon Sep 17 00:00:00 2001 From: tajniak81 <13187254+tajniak81@users.noreply.github.com> Date: Mon, 19 Oct 2026 16:52:10 +0200 Subject: [PATCH] Docker and Docker-AIO compose setups for SQLite, PocketBase and PostgreSQL Docker/ runs the homeserver, admin panel and web client as separate containers built from the existing Dockerfiles; Docker-AIO/ runs all three (and optionally PostgreSQL) in one warp-aio image, supervised by a small entrypoint. Each has a build file and a .prod.yml that only pulls images from WARP_REGISTRY at WARP_VERSION. Co-Authored-By: Claude Opus 5.5 --- .dockerignore | 1 + Docker-AIO/Dockerfile | 111 ++++++++++++++++++ Docker-AIO/README.md | 47 ++++++++ Docker-AIO/docker-compose.pocketbase.prod.yml | 54 +++++++++ Docker-AIO/docker-compose.pocketbase.yml | 50 ++++++++ Docker-AIO/docker-compose.postgresql.prod.yml | 48 ++++++++ Docker-AIO/docker-compose.postgresql.yml | 44 +++++++ Docker-AIO/docker-compose.sqlite.prod.yml | 42 +++++++ Docker-AIO/docker-compose.sqlite.yml | 38 ++++++ Docker-AIO/entrypoint.sh | 104 ++++++++++++++++ Docker/README.md | 57 +++++++++ Docker/docker-compose.pocketbase.prod.yml | 79 +++++++++++++ Docker/docker-compose.pocketbase.yml | 79 +++++++++++++ Docker/docker-compose.postgresql.prod.yml | 90 ++++++++++++++ Docker/docker-compose.postgresql.yml | 90 ++++++++++++++ Docker/docker-compose.sqlite.prod.yml | 67 +++++++++++ Docker/docker-compose.sqlite.yml | 67 +++++++++++ 17 files changed, 1068 insertions(+) create mode 100644 Docker-AIO/Dockerfile create mode 100644 Docker-AIO/README.md create mode 100644 Docker-AIO/docker-compose.pocketbase.prod.yml create mode 100644 Docker-AIO/docker-compose.pocketbase.yml create mode 100644 Docker-AIO/docker-compose.postgresql.prod.yml create mode 100644 Docker-AIO/docker-compose.postgresql.yml create mode 100644 Docker-AIO/docker-compose.sqlite.prod.yml create mode 100644 Docker-AIO/docker-compose.sqlite.yml create mode 100644 Docker-AIO/entrypoint.sh create mode 100644 Docker/README.md create mode 100644 Docker/docker-compose.pocketbase.prod.yml create mode 100644 Docker/docker-compose.pocketbase.yml create mode 100644 Docker/docker-compose.postgresql.prod.yml create mode 100644 Docker/docker-compose.postgresql.yml create mode 100644 Docker/docker-compose.sqlite.prod.yml create mode 100644 Docker/docker-compose.sqlite.yml diff --git a/.dockerignore b/.dockerignore index 7a47277..6d21cd2 100644 --- a/.dockerignore +++ b/.dockerignore @@ -13,3 +13,4 @@ Docker-AIO *.db *.db-shm *.db-wal +!Docker-AIO/entrypoint.sh diff --git a/Docker-AIO/Dockerfile b/Docker-AIO/Dockerfile new file mode 100644 index 0000000..0d47302 --- /dev/null +++ b/Docker-AIO/Dockerfile @@ -0,0 +1,111 @@ +# warp-aio — the homeserver, the admin panel and the web client in one +# image, with PostgreSQL bundled for those who want it inside too. +# +# Build from the repository root: +# +# docker build -t warp-aio -f Docker-AIO/Dockerfile . +# docker run -p 8008:8008 -p 8009:8009 -p 8080:8080 -v warp-data:/data \ +# -e WARP_SERVER_NAME=warp.example warp-aio +# +# The database is picked the same way as for the homeserver alone, with +# WARP_DB_DRIVER (sqlite, the default, pocketbase or postgres). +# WARP_AIO_EMBEDDED_POSTGRES=true starts the bundled PostgreSQL in the +# container, its data in /data/postgres; see Docker-AIO/entrypoint.sh. + +FROM node:22-alpine AS web + +WORKDIR /src +RUN corepack enable + +# Lockfile and manifests first, so the package store survives source changes. +COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./ +COPY apps/ui/package.json ./apps/ui/ +COPY apps/admin/package.json ./apps/admin/ +COPY apps/web/package.json ./apps/web/ +RUN pnpm install --frozen-lockfile --filter @warp/admin... --filter @warp/web... + +COPY apps/ui ./apps/ui +COPY apps/admin ./apps/admin +COPY apps/web ./apps/web +RUN pnpm --filter @warp/admin build && pnpm --filter @warp/web build + + +FROM golang:1.26-alpine AS build + +ARG VERSION=0.0.0-dev +ARG COMMIT=unknown +ARG BUILD_DATE=unknown +ENV CGO_ENABLED=0 + +WORKDIR /src + +# The homeserver. Dependencies first, so the module cache survives source +# changes. +COPY server/go.mod server/go.sum ./server/ +RUN cd server && go mod download +COPY server ./server +RUN cd server && go build -trimpath \ + -ldflags "-s -w \ + -X github.com/dariuszjaniak/warp/server/internal/buildinfo.Version=${VERSION} \ + -X github.com/dariuszjaniak/warp/server/internal/buildinfo.Commit=${COMMIT} \ + -X github.com/dariuszjaniak/warp/server/internal/buildinfo.BuildDate=${BUILD_DATE}" \ + -o /out/warp ./cmd/warp + +# The admin panel and the web client, each with its frontend embedded. +COPY apps/admin/go.mod ./apps/admin/ +COPY apps/admin/cmd ./apps/admin/cmd +COPY apps/admin/internal ./apps/admin/internal +COPY --from=web /src/apps/admin/internal/panel/build/dist ./apps/admin/internal/panel/build/dist +RUN cd apps/admin && GOWORK=off go build -trimpath -ldflags "-s -w -X main.version=${VERSION}" \ + -o /out/warp-admin ./cmd/warp-admin + +COPY apps/web/go.mod ./apps/web/ +COPY apps/web/cmd ./apps/web/cmd +COPY apps/web/host ./apps/web/host +COPY apps/web/client/client.go ./apps/web/client/ +COPY --from=web /src/apps/web/client/build/dist ./apps/web/client/build/dist +RUN cd apps/web && GOWORK=off go build -trimpath -ldflags "-s -w -X main.version=${VERSION}" \ + -o /out/warp-web ./cmd/warp-web + + +FROM alpine:3.21 + +# tini is PID 1 so signals reach the entrypoint and zombies are reaped. +# PostgreSQL runs as the same unprivileged user as everything else. +RUN apk add --no-cache ca-certificates tzdata curl tini postgresql17 postgresql17-client && \ + adduser -D -u 10001 -h /data warp && \ + mkdir -p /run/postgresql && chown warp:warp /run/postgresql + +COPY --from=build /out/warp /out/warp-admin /out/warp-web /usr/local/bin/ +COPY warp.yaml.example /etc/warp/warp.yaml.example +COPY --chmod=755 Docker-AIO/entrypoint.sh /usr/local/bin/warp-aio + +# Database, signing key and media live here; mount a volume on it. +WORKDIR /data +RUN chown warp:warp /data +USER warp + +ENV WARP_LISTEN_ADDRESS=":8008" \ + WARP_PRIVATE_KEY="/data/signing.key" \ + WARP_DB_DRIVER="sqlite" \ + WARP_DB_CONNECTION_STRING="file:/data/warp.db?_pragma=journal_mode(WAL)&_pragma=busy_timeout(10000)&_pragma=foreign_keys(1)" \ + WARP_MEDIA_BASE_PATH="/data/media" \ + WARP_LOG_FORMAT="json" \ + WARP_ADMIN_LISTEN=":8009" \ + WARP_ADMIN_HOMESERVER="http://127.0.0.1:8008" \ + WARP_ADMIN_LOG_FORMAT="json" \ + WARP_WEB_LISTEN=":8080" \ + WARP_WEB_HOMESERVER="http://127.0.0.1:8008" \ + WARP_WEB_LOG_FORMAT="json" \ + WARP_AIO_ADMIN="true" \ + WARP_AIO_WEB="true" \ + WARP_AIO_EMBEDDED_POSTGRES="false" + +EXPOSE 8008 8009 8080 + +HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \ + CMD curl -fsS http://127.0.0.1:8008/healthz && \ + { [ "$WARP_AIO_ADMIN" != true ] || curl -fsS http://127.0.0.1:8009/healthz; } && \ + { [ "$WARP_AIO_WEB" != true ] || curl -fsS http://127.0.0.1:8080/healthz; } || exit 1 + +ENTRYPOINT ["/sbin/tini", "--", "warp-aio"] diff --git a/Docker-AIO/README.md b/Docker-AIO/README.md new file mode 100644 index 0000000..e270c6f --- /dev/null +++ b/Docker-AIO/README.md @@ -0,0 +1,47 @@ +# Docker-AIO: everything in one image + +`warp-aio` holds the homeserver, the admin panel, the web client and +PostgreSQL 17 in one image, built from [`Dockerfile`](Dockerfile). +[`entrypoint.sh`](entrypoint.sh) starts them in one container; if one +exits, the rest are stopped and the container's restart policy brings the +set back. + +| File | Database | Image | +| --- | --- | --- | +| `docker-compose.sqlite.yml` | SQLite, `/data/warp.db` | built here | +| `docker-compose.pocketbase.yml` | PocketBase (embedded driver), `/data/pb_data` | built here | +| `docker-compose.postgresql.yml` | PostgreSQL in the container, `/data/postgres` | built here | +| `docker-compose.*.prod.yml` | as above | pulled, never built | + +Everything lives in the `warp-data` volume, mounted on `/data`. + +```sh +cd Docker-AIO +WARP_SERVER_NAME=matrix.example.org docker compose -f docker-compose.sqlite.yml up -d --build +docker compose -f docker-compose.sqlite.yml exec warp warp create-account --username admin --admin +``` + +Homeserver on `:8008`, admin panel on `:8009`, web client on `:8080`. + +The embedded PostgreSQL listens only on a Unix socket inside the +container, so it needs no password and is not reachable from outside. + +## Switches + +| Variable | Default | | +| --- | --- | --- | +| `WARP_AIO_ADMIN` | `true` | `false` runs no admin panel | +| `WARP_AIO_WEB` | `true` | `false` runs no web client | +| `WARP_AIO_EMBEDDED_POSTGRES` | `false` | `true` starts the bundled PostgreSQL | + +The other settings are those of [Docker/](../Docker/README.md). + +## Prod files + +The `.prod.yml` files pull `$WARP_REGISTRY/warp-aio:$WARP_VERSION` +(defaults `ghcr.io/dariuszjaniak` and `latest`). Push the image first: + +```sh +docker build -t $WARP_REGISTRY/warp-aio:$WARP_VERSION -f Docker-AIO/Dockerfile . +docker push $WARP_REGISTRY/warp-aio:$WARP_VERSION +``` diff --git a/Docker-AIO/docker-compose.pocketbase.prod.yml b/Docker-AIO/docker-compose.pocketbase.prod.yml new file mode 100644 index 0000000..dada5a9 --- /dev/null +++ b/Docker-AIO/docker-compose.pocketbase.prod.yml @@ -0,0 +1,54 @@ +# Warp all-in-one on PocketBase: the homeserver, the admin panel and the +# web client in one container, pulled from a registry. +# +# cd Docker-AIO +# WARP_SERVER_NAME=matrix.example.org docker compose -f docker-compose.pocketbase.prod.yml up -d +# +# PocketBase is embedded in the homeserver (the pocketbase database driver): +# its data directory, with media in its storage, is /data/pb_data in the +# warp-data volume. Set the WARP_PB_S3_* variables to keep media in an S3 +# bucket instead (docs/configuration.md). +# +# Homeserver http://localhost:8008, admin panel http://localhost:8009, web +# client http://localhost:8080. +# +# Create the first administrator once the server is up: +# +# docker compose -f docker-compose.pocketbase.prod.yml exec warp warp create-account --username admin --admin +# +# Nothing is built here: the image comes from WARP_REGISTRY (default +# ghcr.io/dariuszjaniak) at tag WARP_VERSION (default latest). Pin +# WARP_VERSION to a release in production, and update with +# +# docker compose -f docker-compose.pocketbase.prod.yml pull && docker compose -f docker-compose.pocketbase.prod.yml up -d + +name: warp-aio-pocketbase + +services: + warp: + image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp-aio:${WARP_VERSION:-latest} + pull_policy: always + restart: unless-stopped + environment: + WARP_SERVER_NAME: ${WARP_SERVER_NAME:-localhost} + WARP_WELL_KNOWN_CLIENT_BASE_URL: ${WARP_PUBLIC_BASEURL:-http://localhost:8008} + WARP_DB_DRIVER: pocketbase + WARP_DB_CONNECTION_STRING: /data/pb_data + WARP_PB_S3_ENABLED: ${WARP_PB_S3_ENABLED:-false} + WARP_PB_S3_BUCKET: ${WARP_PB_S3_BUCKET:-} + WARP_PB_S3_REGION: ${WARP_PB_S3_REGION:-} + WARP_PB_S3_ENDPOINT: ${WARP_PB_S3_ENDPOINT:-} + WARP_PB_S3_ACCESS_KEY: ${WARP_PB_S3_ACCESS_KEY:-} + WARP_PB_S3_SECRET: ${WARP_PB_S3_SECRET:-} + WARP_PB_S3_FORCE_PATH_STYLE: ${WARP_PB_S3_FORCE_PATH_STYLE:-false} + WARP_REGISTRATION_ENABLED: ${WARP_REGISTRATION_ENABLED:-false} + WARP_FEDERATION_ENABLED: ${WARP_FEDERATION_ENABLED:-false} + volumes: + - warp-data:/data + ports: + - "${WARP_PORT:-8008}:8008" + - "${WARP_ADMIN_PORT:-8009}:8009" + - "${WARP_WEB_PORT:-8080}:8080" + +volumes: + warp-data: diff --git a/Docker-AIO/docker-compose.pocketbase.yml b/Docker-AIO/docker-compose.pocketbase.yml new file mode 100644 index 0000000..b40e10a --- /dev/null +++ b/Docker-AIO/docker-compose.pocketbase.yml @@ -0,0 +1,50 @@ +# Warp all-in-one on PocketBase: the homeserver, the admin panel and the +# web client in one container, built from this checkout. +# +# cd Docker-AIO +# WARP_SERVER_NAME=matrix.example.org docker compose -f docker-compose.pocketbase.yml up -d --build +# +# PocketBase is embedded in the homeserver (the pocketbase database driver): +# its data directory, with media in its storage, is /data/pb_data in the +# warp-data volume. Set the WARP_PB_S3_* variables to keep media in an S3 +# bucket instead (docs/configuration.md). +# +# Homeserver http://localhost:8008, admin panel http://localhost:8009, web +# client http://localhost:8080. +# +# Create the first administrator once the server is up: +# +# docker compose -f docker-compose.pocketbase.yml exec warp warp create-account --username admin --admin + +name: warp-aio-pocketbase + +services: + warp: + build: + context: .. + dockerfile: Docker-AIO/Dockerfile + image: warp-aio:latest + restart: unless-stopped + environment: + WARP_SERVER_NAME: ${WARP_SERVER_NAME:-localhost} + WARP_WELL_KNOWN_CLIENT_BASE_URL: ${WARP_PUBLIC_BASEURL:-http://localhost:8008} + WARP_DB_DRIVER: pocketbase + WARP_DB_CONNECTION_STRING: /data/pb_data + WARP_PB_S3_ENABLED: ${WARP_PB_S3_ENABLED:-false} + WARP_PB_S3_BUCKET: ${WARP_PB_S3_BUCKET:-} + WARP_PB_S3_REGION: ${WARP_PB_S3_REGION:-} + WARP_PB_S3_ENDPOINT: ${WARP_PB_S3_ENDPOINT:-} + WARP_PB_S3_ACCESS_KEY: ${WARP_PB_S3_ACCESS_KEY:-} + WARP_PB_S3_SECRET: ${WARP_PB_S3_SECRET:-} + WARP_PB_S3_FORCE_PATH_STYLE: ${WARP_PB_S3_FORCE_PATH_STYLE:-false} + WARP_REGISTRATION_ENABLED: ${WARP_REGISTRATION_ENABLED:-false} + WARP_FEDERATION_ENABLED: ${WARP_FEDERATION_ENABLED:-false} + volumes: + - warp-data:/data + ports: + - "${WARP_PORT:-8008}:8008" + - "${WARP_ADMIN_PORT:-8009}:8009" + - "${WARP_WEB_PORT:-8080}:8080" + +volumes: + warp-data: diff --git a/Docker-AIO/docker-compose.postgresql.prod.yml b/Docker-AIO/docker-compose.postgresql.prod.yml new file mode 100644 index 0000000..ce8f6c0 --- /dev/null +++ b/Docker-AIO/docker-compose.postgresql.prod.yml @@ -0,0 +1,48 @@ +# Warp all-in-one on PostgreSQL: the homeserver, the admin panel, the web +# client and PostgreSQL in one container, pulled from a registry. +# +# cd Docker-AIO +# WARP_SERVER_NAME=matrix.example.org docker compose -f docker-compose.postgresql.prod.yml up -d +# +# PostgreSQL runs inside the container, listening only on a Unix socket +# there, with its data in /data/postgres in the warp-data volume. +# +# Homeserver http://localhost:8008, admin panel http://localhost:8009, web +# client http://localhost:8080. +# +# Create the first administrator once the server is up: +# +# docker compose -f docker-compose.postgresql.prod.yml exec warp warp create-account --username admin --admin +# +# Nothing is built here: the image comes from WARP_REGISTRY (default +# ghcr.io/dariuszjaniak) at tag WARP_VERSION (default latest). Pin +# WARP_VERSION to a release in production, and update with +# +# docker compose -f docker-compose.postgresql.prod.yml pull && docker compose -f docker-compose.postgresql.prod.yml up -d + +name: warp-aio-postgresql + +services: + warp: + image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp-aio:${WARP_VERSION:-latest} + pull_policy: always + restart: unless-stopped + # PostgreSQL's fast shutdown runs after the homeserver's; give both time. + stop_grace_period: 30s + environment: + WARP_SERVER_NAME: ${WARP_SERVER_NAME:-localhost} + WARP_WELL_KNOWN_CLIENT_BASE_URL: ${WARP_PUBLIC_BASEURL:-http://localhost:8008} + WARP_AIO_EMBEDDED_POSTGRES: "true" + WARP_DB_DRIVER: postgres + WARP_DB_CONNECTION_STRING: postgres:///warp?host=/run/postgresql&user=warp&sslmode=disable + WARP_REGISTRATION_ENABLED: ${WARP_REGISTRATION_ENABLED:-false} + WARP_FEDERATION_ENABLED: ${WARP_FEDERATION_ENABLED:-false} + volumes: + - warp-data:/data + ports: + - "${WARP_PORT:-8008}:8008" + - "${WARP_ADMIN_PORT:-8009}:8009" + - "${WARP_WEB_PORT:-8080}:8080" + +volumes: + warp-data: diff --git a/Docker-AIO/docker-compose.postgresql.yml b/Docker-AIO/docker-compose.postgresql.yml new file mode 100644 index 0000000..8933c9d --- /dev/null +++ b/Docker-AIO/docker-compose.postgresql.yml @@ -0,0 +1,44 @@ +# Warp all-in-one on PostgreSQL: the homeserver, the admin panel, the web +# client and PostgreSQL in one container, built from this checkout. +# +# cd Docker-AIO +# WARP_SERVER_NAME=matrix.example.org docker compose -f docker-compose.postgresql.yml up -d --build +# +# PostgreSQL runs inside the container, listening only on a Unix socket +# there, with its data in /data/postgres in the warp-data volume. +# +# Homeserver http://localhost:8008, admin panel http://localhost:8009, web +# client http://localhost:8080. +# +# Create the first administrator once the server is up: +# +# docker compose -f docker-compose.postgresql.yml exec warp warp create-account --username admin --admin + +name: warp-aio-postgresql + +services: + warp: + build: + context: .. + dockerfile: Docker-AIO/Dockerfile + image: warp-aio:latest + restart: unless-stopped + # PostgreSQL's fast shutdown runs after the homeserver's; give both time. + stop_grace_period: 30s + environment: + WARP_SERVER_NAME: ${WARP_SERVER_NAME:-localhost} + WARP_WELL_KNOWN_CLIENT_BASE_URL: ${WARP_PUBLIC_BASEURL:-http://localhost:8008} + WARP_AIO_EMBEDDED_POSTGRES: "true" + WARP_DB_DRIVER: postgres + WARP_DB_CONNECTION_STRING: postgres:///warp?host=/run/postgresql&user=warp&sslmode=disable + WARP_REGISTRATION_ENABLED: ${WARP_REGISTRATION_ENABLED:-false} + WARP_FEDERATION_ENABLED: ${WARP_FEDERATION_ENABLED:-false} + volumes: + - warp-data:/data + ports: + - "${WARP_PORT:-8008}:8008" + - "${WARP_ADMIN_PORT:-8009}:8009" + - "${WARP_WEB_PORT:-8080}:8080" + +volumes: + warp-data: diff --git a/Docker-AIO/docker-compose.sqlite.prod.yml b/Docker-AIO/docker-compose.sqlite.prod.yml new file mode 100644 index 0000000..289a4a5 --- /dev/null +++ b/Docker-AIO/docker-compose.sqlite.prod.yml @@ -0,0 +1,42 @@ +# Warp all-in-one on SQLite: the homeserver, the admin panel and the web +# client in one container, pulled from a registry. +# +# cd Docker-AIO +# WARP_SERVER_NAME=matrix.example.org docker compose -f docker-compose.sqlite.prod.yml up -d +# +# Homeserver http://localhost:8008, admin panel http://localhost:8009, web +# client http://localhost:8080. The database, signing key and media live +# in the warp-data volume. +# +# Create the first administrator once the server is up: +# +# docker compose -f docker-compose.sqlite.prod.yml exec warp warp create-account --username admin --admin +# +# Nothing is built here: the image comes from WARP_REGISTRY (default +# ghcr.io/dariuszjaniak) at tag WARP_VERSION (default latest). Pin +# WARP_VERSION to a release in production, and update with +# +# docker compose -f docker-compose.sqlite.prod.yml pull && docker compose -f docker-compose.sqlite.prod.yml up -d + +name: warp-aio-sqlite + +services: + warp: + image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp-aio:${WARP_VERSION:-latest} + pull_policy: always + restart: unless-stopped + environment: + WARP_SERVER_NAME: ${WARP_SERVER_NAME:-localhost} + WARP_WELL_KNOWN_CLIENT_BASE_URL: ${WARP_PUBLIC_BASEURL:-http://localhost:8008} + WARP_DB_DRIVER: sqlite + WARP_REGISTRATION_ENABLED: ${WARP_REGISTRATION_ENABLED:-false} + WARP_FEDERATION_ENABLED: ${WARP_FEDERATION_ENABLED:-false} + volumes: + - warp-data:/data + ports: + - "${WARP_PORT:-8008}:8008" + - "${WARP_ADMIN_PORT:-8009}:8009" + - "${WARP_WEB_PORT:-8080}:8080" + +volumes: + warp-data: diff --git a/Docker-AIO/docker-compose.sqlite.yml b/Docker-AIO/docker-compose.sqlite.yml new file mode 100644 index 0000000..28a7e01 --- /dev/null +++ b/Docker-AIO/docker-compose.sqlite.yml @@ -0,0 +1,38 @@ +# Warp all-in-one on SQLite: the homeserver, the admin panel and the web +# client in one container, built from this checkout. +# +# cd Docker-AIO +# WARP_SERVER_NAME=matrix.example.org docker compose -f docker-compose.sqlite.yml up -d --build +# +# Homeserver http://localhost:8008, admin panel http://localhost:8009, web +# client http://localhost:8080. The database, signing key and media live +# in the warp-data volume. +# +# Create the first administrator once the server is up: +# +# docker compose -f docker-compose.sqlite.yml exec warp warp create-account --username admin --admin + +name: warp-aio-sqlite + +services: + warp: + build: + context: .. + dockerfile: Docker-AIO/Dockerfile + image: warp-aio:latest + restart: unless-stopped + environment: + WARP_SERVER_NAME: ${WARP_SERVER_NAME:-localhost} + WARP_WELL_KNOWN_CLIENT_BASE_URL: ${WARP_PUBLIC_BASEURL:-http://localhost:8008} + WARP_DB_DRIVER: sqlite + WARP_REGISTRATION_ENABLED: ${WARP_REGISTRATION_ENABLED:-false} + WARP_FEDERATION_ENABLED: ${WARP_FEDERATION_ENABLED:-false} + volumes: + - warp-data:/data + ports: + - "${WARP_PORT:-8008}:8008" + - "${WARP_ADMIN_PORT:-8009}:8009" + - "${WARP_WEB_PORT:-8080}:8080" + +volumes: + warp-data: diff --git a/Docker-AIO/entrypoint.sh b/Docker-AIO/entrypoint.sh new file mode 100644 index 0000000..d6fc32b --- /dev/null +++ b/Docker-AIO/entrypoint.sh @@ -0,0 +1,104 @@ +#!/bin/sh +# warp-aio: runs the homeserver, the admin panel and the web client (and, +# with WARP_AIO_EMBEDDED_POSTGRES=true, PostgreSQL) in one container. +# +# If any of them exits, the others are stopped and the container exits, so +# the restart policy brings the whole set back. SIGTERM stops the clients +# first, then the homeserver, then PostgreSQL. +# +# With arguments, runs them instead: `docker run warp-aio warp version`. +# +# WARP_AIO_ADMIN=false no admin panel +# WARP_AIO_WEB=false no web client +# WARP_AIO_EMBEDDED_POSTGRES=true PostgreSQL in the container, data in +# $PGDATA (/data/postgres); point +# WARP_DB_CONNECTION_STRING at +# postgres:///warp?host=/run/postgresql&user=warp&sslmode=disable + +set -eu + +if [ "$#" -gt 0 ]; then + exec "$@" +fi + +log() { echo "warp-aio: $*" >&2; } + +pg_pid="" +warp_pid="" +admin_pid="" +web_pid="" + +# stop PID...: SIGTERM, then wait for each to exit. +stop() { + for pid in "$@"; do + [ -n "$pid" ] && kill -TERM "$pid" 2>/dev/null || true + done + for pid in "$@"; do + [ -n "$pid" ] && wait "$pid" 2>/dev/null || true + done +} + +shutdown() { + trap '' TERM INT + stop "$web_pid" "$admin_pid" + stop "$warp_pid" + if [ -n "$pg_pid" ]; then + # SIGINT is PostgreSQL's fast shutdown: it does not wait for + # clients, and the homeserver is gone by now anyway. + kill -INT "$pg_pid" 2>/dev/null || true + wait "$pg_pid" 2>/dev/null || true + fi + exit "${1:-0}" +} +trap 'log "stopping"; shutdown 0' TERM INT + +if [ "$WARP_AIO_EMBEDDED_POSTGRES" = true ]; then + export PGDATA="${PGDATA:-/data/postgres}" + if [ ! -s "$PGDATA/PG_VERSION" ]; then + log "initialising PostgreSQL in $PGDATA" + # Trust is safe here: PostgreSQL listens on no TCP address, only on + # a socket inside this container. + initdb -D "$PGDATA" -U warp --auth=trust --encoding=UTF8 --locale=C >/dev/null + fi + postgres -D "$PGDATA" -c listen_addresses='' -c unix_socket_directories=/run/postgresql & + pg_pid=$! + until pg_isready -q -h /run/postgresql -U warp; do + kill -0 "$pg_pid" 2>/dev/null || { log "PostgreSQL failed to start"; exit 1; } + sleep 1 + done + if [ "$(psql -h /run/postgresql -U warp -d postgres -tAc "SELECT 1 FROM pg_database WHERE datname = 'warp'")" != 1 ]; then + createdb -h /run/postgresql -U warp warp + fi +fi + +# The signing key is created on first start and kept in the volume: losing +# it means other servers no longer recognise this one. +if [ ! -f "$WARP_PRIVATE_KEY" ]; then + warp generate-keys --output "$WARP_PRIVATE_KEY" +fi + +warp serve & +warp_pid=$! + +if [ "$WARP_AIO_ADMIN" = true ]; then + warp-admin & + admin_pid=$! +fi +if [ "$WARP_AIO_WEB" = true ]; then + warp-web & + web_pid=$! +fi + +# Busybox sh has no `wait -n`, so check on the processes every second. The +# sleep runs in the background so a signal is handled at once. +while :; do + for entry in "postgres:$pg_pid" "warp:$warp_pid" "warp-admin:$admin_pid" "warp-web:$web_pid"; do + pid="${entry#*:}" + if [ -n "$pid" ] && ! kill -0 "$pid" 2>/dev/null; then + log "${entry%%:*} exited; stopping the rest" + shutdown 1 + fi + done + sleep 1 & + wait $! || true +done diff --git a/Docker/README.md b/Docker/README.md new file mode 100644 index 0000000..547b44b --- /dev/null +++ b/Docker/README.md @@ -0,0 +1,57 @@ +# Docker: one container per component + +The homeserver (`warp`), the admin panel (`warp-admin`) and the web client +(`warp-web`) as separate images, built from `Dockerfile`, +`apps/admin/Dockerfile` and `apps/web/Dockerfile`. + +| File | Database | Images | +| --- | --- | --- | +| `docker-compose.sqlite.yml` | SQLite, in the `warp-data` volume | built here | +| `docker-compose.pocketbase.yml` | PocketBase, embedded in the homeserver, in `warp-data` | built here | +| `docker-compose.postgresql.yml` | PostgreSQL 17, its own container | built here | +| `docker-compose.*.prod.yml` | as above | pulled, never built | + +```sh +cd Docker +WARP_SERVER_NAME=matrix.example.org docker compose -f docker-compose.sqlite.yml up -d --build +docker compose -f docker-compose.sqlite.yml exec warp warp create-account --username admin --admin +``` + +Homeserver on `:8008`, admin panel on `:8009`, web client on `:8080` +(`WARP_PORT`, `WARP_ADMIN_PORT`, `WARP_WEB_PORT` move them). Put a +TLS-terminating reverse proxy in front before exposing them; see +[docs/deployment.md](../docs/deployment.md). + +PocketBase is a database driver inside the homeserver, not a separate +server, so the PocketBase files have no PocketBase container. + +## Prod files + +The `.prod.yml` files pull `$WARP_REGISTRY/warp`, `warp-admin` and +`warp-web` at tag `$WARP_VERSION` (defaults `ghcr.io/dariuszjaniak` and +`latest`). Push the images there first: + +```sh +docker compose -f docker-compose.sqlite.yml build +for i in warp warp-admin warp-web; do + docker tag $i:latest $WARP_REGISTRY/$i:$WARP_VERSION + docker push $WARP_REGISTRY/$i:$WARP_VERSION +done +``` + +`docker-compose.postgresql.prod.yml` refuses to start without +`WARP_POSTGRES_PASSWORD`. + +## Settings + +| Variable | Default | +| --- | --- | +| `WARP_SERVER_NAME` | `localhost` | +| `WARP_PUBLIC_BASEURL` | `http://localhost:8008` | +| `WARP_REGISTRATION_ENABLED` | `false` | +| `WARP_FEDERATION_ENABLED` | `false` | +| `WARP_POSTGRES_PASSWORD` | `warp` (required in prod) | +| `WARP_PB_S3_*` | S3 media for PocketBase, off | + +Any other setting from [docs/configuration.md](../docs/configuration.md) +can be added to the `warp` service's environment. diff --git a/Docker/docker-compose.pocketbase.prod.yml b/Docker/docker-compose.pocketbase.prod.yml new file mode 100644 index 0000000..d233104 --- /dev/null +++ b/Docker/docker-compose.pocketbase.prod.yml @@ -0,0 +1,79 @@ +# Warp on PocketBase: the homeserver, the admin panel and the web client, +# each in its own container, pulled from a registry. +# +# cd Docker +# WARP_SERVER_NAME=matrix.example.org docker compose -f docker-compose.pocketbase.prod.yml up -d +# +# PocketBase is embedded in the homeserver (the pocketbase database driver), +# so it is not a container of its own: its data directory, with media in +# its storage, is /data/pb_data in the warp-data volume. Set the WARP_PB_S3_* +# variables to keep media in an S3 bucket instead (docs/configuration.md). +# +# Homeserver http://localhost:8008, admin panel http://localhost:8009, web +# client http://localhost:8080. +# +# Create the first administrator once the server is up: +# +# docker compose -f docker-compose.pocketbase.prod.yml exec warp warp create-account --username admin --admin +# +# Nothing is built here: the images come from WARP_REGISTRY (default +# ghcr.io/dariuszjaniak) at tag WARP_VERSION (default latest). Pin +# WARP_VERSION to a release in production, and update with +# +# docker compose -f docker-compose.pocketbase.prod.yml pull && docker compose -f docker-compose.pocketbase.prod.yml up -d + +name: warp-pocketbase + +services: + warp: + image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp:${WARP_VERSION:-latest} + pull_policy: always + restart: unless-stopped + # The signing key is created on first start and kept in the volume: + # losing it means other servers no longer recognise this one. + entrypoint: ["/bin/sh", "-c"] + command: + - test -f /data/signing.key || warp generate-keys --output /data/signing.key; exec warp serve + environment: + WARP_SERVER_NAME: ${WARP_SERVER_NAME:-localhost} + WARP_WELL_KNOWN_CLIENT_BASE_URL: ${WARP_PUBLIC_BASEURL:-http://localhost:8008} + WARP_DB_DRIVER: pocketbase + WARP_DB_CONNECTION_STRING: /data/pb_data + WARP_PB_S3_ENABLED: ${WARP_PB_S3_ENABLED:-false} + WARP_PB_S3_BUCKET: ${WARP_PB_S3_BUCKET:-} + WARP_PB_S3_REGION: ${WARP_PB_S3_REGION:-} + WARP_PB_S3_ENDPOINT: ${WARP_PB_S3_ENDPOINT:-} + WARP_PB_S3_ACCESS_KEY: ${WARP_PB_S3_ACCESS_KEY:-} + WARP_PB_S3_SECRET: ${WARP_PB_S3_SECRET:-} + WARP_PB_S3_FORCE_PATH_STYLE: ${WARP_PB_S3_FORCE_PATH_STYLE:-false} + WARP_REGISTRATION_ENABLED: ${WARP_REGISTRATION_ENABLED:-false} + WARP_FEDERATION_ENABLED: ${WARP_FEDERATION_ENABLED:-false} + volumes: + - warp-data:/data + ports: + - "${WARP_PORT:-8008}:8008" + + admin: + image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp-admin:${WARP_VERSION:-latest} + pull_policy: always + restart: unless-stopped + depends_on: + - warp + environment: + WARP_ADMIN_HOMESERVER: http://warp:8008 + ports: + - "${WARP_ADMIN_PORT:-8009}:8009" + + web: + image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp-web:${WARP_VERSION:-latest} + pull_policy: always + restart: unless-stopped + depends_on: + - warp + environment: + WARP_WEB_HOMESERVER: http://warp:8008 + ports: + - "${WARP_WEB_PORT:-8080}:8080" + +volumes: + warp-data: diff --git a/Docker/docker-compose.pocketbase.yml b/Docker/docker-compose.pocketbase.yml new file mode 100644 index 0000000..dc7f892 --- /dev/null +++ b/Docker/docker-compose.pocketbase.yml @@ -0,0 +1,79 @@ +# Warp on PocketBase: the homeserver, the admin panel and the web client, +# each in its own container, built from this checkout. +# +# cd Docker +# WARP_SERVER_NAME=matrix.example.org docker compose -f docker-compose.pocketbase.yml up -d --build +# +# PocketBase is embedded in the homeserver (the pocketbase database driver), +# so it is not a container of its own: its data directory, with media in +# its storage, is /data/pb_data in the warp-data volume. Set the WARP_PB_S3_* +# variables to keep media in an S3 bucket instead (docs/configuration.md). +# +# Homeserver http://localhost:8008, admin panel http://localhost:8009, web +# client http://localhost:8080. +# +# Create the first administrator once the server is up: +# +# docker compose -f docker-compose.pocketbase.yml exec warp warp create-account --username admin --admin + +name: warp-pocketbase + +services: + warp: + build: + context: .. + dockerfile: Dockerfile + image: warp:latest + restart: unless-stopped + # The signing key is created on first start and kept in the volume: + # losing it means other servers no longer recognise this one. + entrypoint: ["/bin/sh", "-c"] + command: + - test -f /data/signing.key || warp generate-keys --output /data/signing.key; exec warp serve + environment: + WARP_SERVER_NAME: ${WARP_SERVER_NAME:-localhost} + WARP_WELL_KNOWN_CLIENT_BASE_URL: ${WARP_PUBLIC_BASEURL:-http://localhost:8008} + WARP_DB_DRIVER: pocketbase + WARP_DB_CONNECTION_STRING: /data/pb_data + WARP_PB_S3_ENABLED: ${WARP_PB_S3_ENABLED:-false} + WARP_PB_S3_BUCKET: ${WARP_PB_S3_BUCKET:-} + WARP_PB_S3_REGION: ${WARP_PB_S3_REGION:-} + WARP_PB_S3_ENDPOINT: ${WARP_PB_S3_ENDPOINT:-} + WARP_PB_S3_ACCESS_KEY: ${WARP_PB_S3_ACCESS_KEY:-} + WARP_PB_S3_SECRET: ${WARP_PB_S3_SECRET:-} + WARP_PB_S3_FORCE_PATH_STYLE: ${WARP_PB_S3_FORCE_PATH_STYLE:-false} + WARP_REGISTRATION_ENABLED: ${WARP_REGISTRATION_ENABLED:-false} + WARP_FEDERATION_ENABLED: ${WARP_FEDERATION_ENABLED:-false} + volumes: + - warp-data:/data + ports: + - "${WARP_PORT:-8008}:8008" + + admin: + build: + context: .. + dockerfile: apps/admin/Dockerfile + image: warp-admin:latest + restart: unless-stopped + depends_on: + - warp + environment: + WARP_ADMIN_HOMESERVER: http://warp:8008 + ports: + - "${WARP_ADMIN_PORT:-8009}:8009" + + web: + build: + context: .. + dockerfile: apps/web/Dockerfile + image: warp-web:latest + restart: unless-stopped + depends_on: + - warp + environment: + WARP_WEB_HOMESERVER: http://warp:8008 + ports: + - "${WARP_WEB_PORT:-8080}:8080" + +volumes: + warp-data: diff --git a/Docker/docker-compose.postgresql.prod.yml b/Docker/docker-compose.postgresql.prod.yml new file mode 100644 index 0000000..b1da0f9 --- /dev/null +++ b/Docker/docker-compose.postgresql.prod.yml @@ -0,0 +1,90 @@ +# Warp on PostgreSQL: the homeserver, the admin panel, the web client and +# PostgreSQL, each in its own container, pulled from a registry. +# +# cd Docker +# WARP_SERVER_NAME=matrix.example.org WARP_POSTGRES_PASSWORD=change-me \ +# docker compose -f docker-compose.postgresql.prod.yml up -d +# +# Homeserver http://localhost:8008, admin panel http://localhost:8009, web +# client http://localhost:8080. PostgreSQL is reachable only on the compose +# network. +# +# Create the first administrator once the server is up: +# +# docker compose -f docker-compose.postgresql.prod.yml exec warp warp create-account --username admin --admin +# +# Nothing is built here: the images come from WARP_REGISTRY (default +# ghcr.io/dariuszjaniak) at tag WARP_VERSION (default latest). Pin +# WARP_VERSION to a release in production, and update with +# +# docker compose -f docker-compose.postgresql.prod.yml pull && docker compose -f docker-compose.postgresql.prod.yml up -d + +name: warp-postgresql + +services: + postgres: + image: postgres:17-alpine + restart: unless-stopped + environment: + POSTGRES_USER: warp + POSTGRES_PASSWORD: ${WARP_POSTGRES_PASSWORD:?set WARP_POSTGRES_PASSWORD} + POSTGRES_DB: warp + # C sorts by byte, which is what room and event IDs are compared by. + POSTGRES_INITDB_ARGS: --encoding=UTF8 --lc-collate=C --lc-ctype=C + volumes: + - postgres-data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U warp -d warp"] + interval: 5s + timeout: 5s + retries: 20 + + warp: + image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp:${WARP_VERSION:-latest} + pull_policy: always + restart: unless-stopped + depends_on: + postgres: + condition: service_healthy + # The signing key is created on first start and kept in the volume: + # losing it means other servers no longer recognise this one. + entrypoint: ["/bin/sh", "-c"] + command: + - test -f /data/signing.key || warp generate-keys --output /data/signing.key; exec warp serve + environment: + WARP_SERVER_NAME: ${WARP_SERVER_NAME:-localhost} + WARP_WELL_KNOWN_CLIENT_BASE_URL: ${WARP_PUBLIC_BASEURL:-http://localhost:8008} + WARP_DB_DRIVER: postgres + WARP_DB_CONNECTION_STRING: postgres://warp:${WARP_POSTGRES_PASSWORD:?set WARP_POSTGRES_PASSWORD}@postgres:5432/warp?sslmode=disable + WARP_REGISTRATION_ENABLED: ${WARP_REGISTRATION_ENABLED:-false} + WARP_FEDERATION_ENABLED: ${WARP_FEDERATION_ENABLED:-false} + volumes: + - warp-data:/data + ports: + - "${WARP_PORT:-8008}:8008" + + admin: + image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp-admin:${WARP_VERSION:-latest} + pull_policy: always + restart: unless-stopped + depends_on: + - warp + environment: + WARP_ADMIN_HOMESERVER: http://warp:8008 + ports: + - "${WARP_ADMIN_PORT:-8009}:8009" + + web: + image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp-web:${WARP_VERSION:-latest} + pull_policy: always + restart: unless-stopped + depends_on: + - warp + environment: + WARP_WEB_HOMESERVER: http://warp:8008 + ports: + - "${WARP_WEB_PORT:-8080}:8080" + +volumes: + postgres-data: + warp-data: diff --git a/Docker/docker-compose.postgresql.yml b/Docker/docker-compose.postgresql.yml new file mode 100644 index 0000000..7f3e467 --- /dev/null +++ b/Docker/docker-compose.postgresql.yml @@ -0,0 +1,90 @@ +# Warp on PostgreSQL: the homeserver, the admin panel, the web client and +# PostgreSQL, each in its own container, built from this checkout. +# +# cd Docker +# WARP_SERVER_NAME=matrix.example.org WARP_POSTGRES_PASSWORD=change-me \ +# docker compose -f docker-compose.postgresql.yml up -d --build +# +# Homeserver http://localhost:8008, admin panel http://localhost:8009, web +# client http://localhost:8080. PostgreSQL is reachable only on the compose +# network. +# +# Create the first administrator once the server is up: +# +# docker compose -f docker-compose.postgresql.yml exec warp warp create-account --username admin --admin + +name: warp-postgresql + +services: + postgres: + image: postgres:17-alpine + restart: unless-stopped + environment: + POSTGRES_USER: warp + POSTGRES_PASSWORD: ${WARP_POSTGRES_PASSWORD:-warp} + POSTGRES_DB: warp + # C sorts by byte, which is what room and event IDs are compared by. + POSTGRES_INITDB_ARGS: --encoding=UTF8 --lc-collate=C --lc-ctype=C + volumes: + - postgres-data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U warp -d warp"] + interval: 5s + timeout: 5s + retries: 20 + + warp: + build: + context: .. + dockerfile: Dockerfile + image: warp:latest + restart: unless-stopped + depends_on: + postgres: + condition: service_healthy + # The signing key is created on first start and kept in the volume: + # losing it means other servers no longer recognise this one. + entrypoint: ["/bin/sh", "-c"] + command: + - test -f /data/signing.key || warp generate-keys --output /data/signing.key; exec warp serve + environment: + WARP_SERVER_NAME: ${WARP_SERVER_NAME:-localhost} + WARP_WELL_KNOWN_CLIENT_BASE_URL: ${WARP_PUBLIC_BASEURL:-http://localhost:8008} + WARP_DB_DRIVER: postgres + WARP_DB_CONNECTION_STRING: postgres://warp:${WARP_POSTGRES_PASSWORD:-warp}@postgres:5432/warp?sslmode=disable + WARP_REGISTRATION_ENABLED: ${WARP_REGISTRATION_ENABLED:-false} + WARP_FEDERATION_ENABLED: ${WARP_FEDERATION_ENABLED:-false} + volumes: + - warp-data:/data + ports: + - "${WARP_PORT:-8008}:8008" + + admin: + build: + context: .. + dockerfile: apps/admin/Dockerfile + image: warp-admin:latest + restart: unless-stopped + depends_on: + - warp + environment: + WARP_ADMIN_HOMESERVER: http://warp:8008 + ports: + - "${WARP_ADMIN_PORT:-8009}:8009" + + web: + build: + context: .. + dockerfile: apps/web/Dockerfile + image: warp-web:latest + restart: unless-stopped + depends_on: + - warp + environment: + WARP_WEB_HOMESERVER: http://warp:8008 + ports: + - "${WARP_WEB_PORT:-8080}:8080" + +volumes: + postgres-data: + warp-data: diff --git a/Docker/docker-compose.sqlite.prod.yml b/Docker/docker-compose.sqlite.prod.yml new file mode 100644 index 0000000..cc8d503 --- /dev/null +++ b/Docker/docker-compose.sqlite.prod.yml @@ -0,0 +1,67 @@ +# Warp on SQLite: the homeserver, the admin panel and the web client, each +# in its own container, pulled from a registry. +# +# cd Docker +# WARP_SERVER_NAME=matrix.example.org docker compose -f docker-compose.sqlite.prod.yml up -d +# +# Homeserver http://localhost:8008, admin panel http://localhost:8009, web +# client http://localhost:8080. The database, signing key and media live +# in the warp-data volume. +# +# Create the first administrator once the server is up: +# +# docker compose -f docker-compose.sqlite.prod.yml exec warp warp create-account --username admin --admin +# +# Nothing is built here: the images come from WARP_REGISTRY (default +# ghcr.io/dariuszjaniak) at tag WARP_VERSION (default latest). Pin +# WARP_VERSION to a release in production, and update with +# +# docker compose -f docker-compose.sqlite.prod.yml pull && docker compose -f docker-compose.sqlite.prod.yml up -d + +name: warp-sqlite + +services: + warp: + image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp:${WARP_VERSION:-latest} + pull_policy: always + restart: unless-stopped + # The signing key is created on first start and kept in the volume: + # losing it means other servers no longer recognise this one. + entrypoint: ["/bin/sh", "-c"] + command: + - test -f /data/signing.key || warp generate-keys --output /data/signing.key; exec warp serve + environment: + WARP_SERVER_NAME: ${WARP_SERVER_NAME:-localhost} + WARP_WELL_KNOWN_CLIENT_BASE_URL: ${WARP_PUBLIC_BASEURL:-http://localhost:8008} + WARP_DB_DRIVER: sqlite + WARP_REGISTRATION_ENABLED: ${WARP_REGISTRATION_ENABLED:-false} + WARP_FEDERATION_ENABLED: ${WARP_FEDERATION_ENABLED:-false} + volumes: + - warp-data:/data + ports: + - "${WARP_PORT:-8008}:8008" + + admin: + image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp-admin:${WARP_VERSION:-latest} + pull_policy: always + restart: unless-stopped + depends_on: + - warp + environment: + WARP_ADMIN_HOMESERVER: http://warp:8008 + ports: + - "${WARP_ADMIN_PORT:-8009}:8009" + + web: + image: ${WARP_REGISTRY:-ghcr.io/dariuszjaniak}/warp-web:${WARP_VERSION:-latest} + pull_policy: always + restart: unless-stopped + depends_on: + - warp + environment: + WARP_WEB_HOMESERVER: http://warp:8008 + ports: + - "${WARP_WEB_PORT:-8080}:8080" + +volumes: + warp-data: diff --git a/Docker/docker-compose.sqlite.yml b/Docker/docker-compose.sqlite.yml new file mode 100644 index 0000000..487b080 --- /dev/null +++ b/Docker/docker-compose.sqlite.yml @@ -0,0 +1,67 @@ +# Warp on SQLite: the homeserver, the admin panel and the web client, each +# in its own container, built from this checkout. +# +# cd Docker +# WARP_SERVER_NAME=matrix.example.org docker compose -f docker-compose.sqlite.yml up -d --build +# +# Homeserver http://localhost:8008, admin panel http://localhost:8009, web +# client http://localhost:8080. The database, signing key and media live +# in the warp-data volume. +# +# Create the first administrator once the server is up: +# +# docker compose -f docker-compose.sqlite.yml exec warp warp create-account --username admin --admin + +name: warp-sqlite + +services: + warp: + build: + context: .. + dockerfile: Dockerfile + image: warp:latest + restart: unless-stopped + # The signing key is created on first start and kept in the volume: + # losing it means other servers no longer recognise this one. + entrypoint: ["/bin/sh", "-c"] + command: + - test -f /data/signing.key || warp generate-keys --output /data/signing.key; exec warp serve + environment: + WARP_SERVER_NAME: ${WARP_SERVER_NAME:-localhost} + WARP_WELL_KNOWN_CLIENT_BASE_URL: ${WARP_PUBLIC_BASEURL:-http://localhost:8008} + WARP_DB_DRIVER: sqlite + WARP_REGISTRATION_ENABLED: ${WARP_REGISTRATION_ENABLED:-false} + WARP_FEDERATION_ENABLED: ${WARP_FEDERATION_ENABLED:-false} + volumes: + - warp-data:/data + ports: + - "${WARP_PORT:-8008}:8008" + + admin: + build: + context: .. + dockerfile: apps/admin/Dockerfile + image: warp-admin:latest + restart: unless-stopped + depends_on: + - warp + environment: + WARP_ADMIN_HOMESERVER: http://warp:8008 + ports: + - "${WARP_ADMIN_PORT:-8009}:8009" + + web: + build: + context: .. + dockerfile: apps/web/Dockerfile + image: warp-web:latest + restart: unless-stopped + depends_on: + - warp + environment: + WARP_WEB_HOMESERVER: http://warp:8008 + ports: + - "${WARP_WEB_PORT:-8080}:8080" + +volumes: + warp-data: