feat: unify Workshop experience

This commit is contained in:
Thomas Camlong committed 2026-07-14 01:21:53 +02:00
1 parent 066090d99e
commit 9f979f683a
27 files changed
+1184 -483

No files matched your search

+31 -4
View File
@@ -1,4 +1,26 @@
FROM alpine:3.22 AS download
# syntax=docker/dockerfile:1.10
FROM node:24.18.0-alpine AS website
WORKDIR /app
RUN corepack enable pnpm
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json turbo.json ./
COPY patches ./patches
RUN --mount=type=cache,id=workshop-pnpm-store,target=/pnpm/store \
pnpm config set store-dir /pnpm/store && \
pnpm --config.node-linker=isolated fetch --ignore-scripts && \
rm -rf node_modules
COPY apps/docs ./apps/docs
COPY packages/definitions ./packages/definitions
COPY packages/validation ./packages/validation
COPY packages/workshop ./packages/workshop
COPY tooling/typescript ./tooling/typescript
RUN --mount=type=cache,id=workshop-pnpm-store,target=/pnpm/store \
pnpm install --recursive --offline --frozen-lockfile && \
CI=true SKIP_ENV_VALIDATION=true pnpm turbo build --filter=@homarr/docs
FROM alpine:3.22 AS pocketbase
ARG TARGETARCH
ARG POCKETBASE_VERSION=0.39.6
@@ -20,10 +42,15 @@ RUN case "${TARGETARCH}" in \
FROM alpine:3.22
RUN apk add --no-cache ca-certificates tzdata && addgroup -S pocketbase && adduser -S -G pocketbase pocketbase
COPY --from=download /out/pocketbase /usr/local/bin/pocketbase
COPY entrypoint.sh /usr/local/bin/workshop-entrypoint
COPY --from=pocketbase /out/pocketbase /usr/local/bin/pocketbase
COPY --from=website /app/apps/docs/build /pb_public
COPY apps/workshop/entrypoint.sh /usr/local/bin/workshop-entrypoint
COPY apps/workshop/pb_hooks /pb_hooks
COPY apps/workshop/pb_migrations /pb_migrations
RUN chmod +x /usr/local/bin/workshop-entrypoint && mkdir -p /pb_data /pb_hooks /pb_migrations && chown -R pocketbase:pocketbase /pb_data /pb_hooks /pb_migrations
RUN chmod +x /usr/local/bin/workshop-entrypoint && \
mkdir -p /pb_data && \
chown -R pocketbase:pocketbase /pb_data /pb_hooks /pb_migrations /pb_public
USER pocketbase
EXPOSE 8090
+19
View File
@@ -0,0 +1,19 @@
**
!package.json
!pnpm-lock.yaml
!pnpm-workspace.yaml
!turbo.json
!patches/**
!apps/docs/**
!apps/workshop/entrypoint.sh
!apps/workshop/pb_hooks/**
!apps/workshop/pb_migrations/**
!packages/definitions/**
!packages/validation/**
!packages/workshop/**
!tooling/typescript/**
**/node_modules
**/.docusaurus
**/build
**/dist
**/.turbo
+8 -7
View File
@@ -1,21 +1,21 @@
# Homarr Workshop backend
# Homarr Workshop service
PocketBase provides the central Workshop API at `workshop.homarr.dev`. It is not a per-instance Homarr service. Local deployment is for development and integration testing.
The Workshop image serves the compiled Homarr documentation and the PocketBase community API from one origin: `https://homarr.dev`. It is not a per-instance Homarr service. Local deployment is for development and integration testing.
## Local startup
1. Copy the repository-root `.env.example` to `.env` and create a GitHub OAuth app.
2. Set its callback URL to `http://localhost:<PB_EXPOSE_PORT>/api/oauth2-redirect` (port `8090` by default).
3. Set `GITHUB_CLIENT_ID`, `GITHUB_CLIENT_SECRET`, `PB_SUPERUSER_EMAIL`, and `PB_SUPERUSER_PASSWORD`.
4. Run `pnpm dev:workshop` from the repository root. It starts PocketBase and the Docusaurus Workshop together and removes obsolete Compose containers.
4. Run `pnpm dev:workshop` from the repository root. It builds the single Workshop image, starts it, and removes obsolete Compose containers.
Open the Workshop at `http://localhost:3003/workshop`. The API is at `http://localhost:<PB_EXPOSE_PORT>` and the emergency PocketBase dashboard is at `http://localhost:<PB_EXPOSE_PORT>/_/` (port `8090` by default). `0.0.0.0` in PocketBase's server log is its container bind address, not a browser URL. Day-to-day moderation belongs in `/workshop/admin`, not the PocketBase dashboard.
Open the Workshop at `http://localhost:<PB_EXPOSE_PORT>/workshop`. The API is at `/api` on the same origin and the emergency PocketBase dashboard is at `/_/` (port `8090` by default). `0.0.0.0` in PocketBase's server log is its container bind address, not a browser URL. Day-to-day moderation belongs in `/workshop/admin`, not the PocketBase dashboard.
Use `pnpm dev:workshop:backend` when only the API is needed. All Workshop configuration is read from the repository-root `.env`; there is no app-specific environment file. If port 8090 is unavailable, set `PB_EXPOSE_PORT` there. The website derives its local API URL from that port unless `WORKSHOP_API_URL` is explicitly set.
All Workshop configuration is read from the repository-root `.env`; there is no app-specific environment file. If port 8090 is unavailable, set `PB_EXPOSE_PORT` there. `pnpm dev:workshop:website` remains available for Docusaurus HMR and connects to the local container through `WORKSHOP_API_URL`.
The image downloads the official PocketBase `0.39.6` release and verifies it against that release's `checksums.txt`. Migrations and hooks are mounted read-only.
The multi-stage image builds Docusaurus, downloads the official PocketBase `0.39.6` release, verifies it against that release's `checksums.txt`, and copies the versioned migrations, hooks, and static website into the runtime image.
GitHub OAuth configuration is synchronized from the environment on every boot, including for an existing development volume. Local CORS is restricted to the documented Homarr and Docusaurus origins in `PB_ALLOWED_ORIGINS`; production must set it to `https://homarr.dev`.
GitHub OAuth configuration is synchronized from the environment on every boot, including for an existing development volume. `PB_ALLOWED_ORIGINS` defaults to `*` because arbitrary self-hosted Homarr origins consume the central API. PocketBase authenticates writes with bearer tokens and does not use cookies; CORS is not an authorization boundary.
## Roles and account states
@@ -41,6 +41,7 @@ Restore only into the same PocketBase version after preserving the current volum
## Production checklist
- Run `ghcr.io/homarr-labs/workshop:dev` behind the `homarr.dev` TLS endpoint; the image owns both the website and `/api`.
- Terminate TLS at the reverse proxy and forward the real client IP.
- Keep superuser credentials outside Compose and rotate them after bootstrap.
- Restrict the dashboard path to operators; GitHub users never need it.
+5 -6
View File
@@ -3,24 +3,23 @@ name: homarr-workshop
services:
workshop:
build:
context: .
context: ../..
dockerfile: apps/workshop/Dockerfile
args:
POCKETBASE_VERSION: 0.39.6
image: homarr/workshop-pocketbase:0.39.6
image: homarr/workshop:0.39.6
restart: unless-stopped
environment:
GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID:-}
GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET:-}
PB_SUPERUSER_EMAIL: ${PB_SUPERUSER_EMAIL:-}
PB_SUPERUSER_PASSWORD: ${PB_SUPERUSER_PASSWORD:-}
PB_PUBLIC_URL: http://localhost:${PB_EXPOSE_PORT:-8090}
PB_ALLOWED_ORIGINS: ${PB_ALLOWED_ORIGINS:-http://localhost:3000,http://127.0.0.1:3000,http://localhost:3003,http://127.0.0.1:3003,http://localhost:7575,http://127.0.0.1:7575}
PB_PUBLIC_URL: ${PB_PUBLIC_URL:-http://localhost:${PB_EXPOSE_PORT:-8090}}
PB_ALLOWED_ORIGINS: ${PB_ALLOWED_ORIGINS:-*}
ports:
- "127.0.0.1:${PB_EXPOSE_PORT:-8090}:8090"
volumes:
- workshop_data:/pb_data
- ./pb_hooks:/pb_hooks:ro
- ./pb_migrations:/pb_migrations:ro
security_opt:
- no-new-privileges:true
+6 -4
View File
@@ -5,12 +5,14 @@ if [ -n "${PB_SUPERUSER_EMAIL:-}" ] && [ -n "${PB_SUPERUSER_PASSWORD:-}" ]; then
pocketbase superuser upsert "${PB_SUPERUSER_EMAIL}" "${PB_SUPERUSER_PASSWORD}" --dir=/pb_data
fi
echo "Workshop API: ${PB_PUBLIC_URL:-http://localhost:8090}"
echo "Workshop website: http://localhost:3003/workshop"
echo "Workshop: ${PB_PUBLIC_URL:-http://localhost:8090}/workshop"
echo "Workshop API: ${PB_PUBLIC_URL:-http://localhost:8090}/api"
exec pocketbase serve \
--http=0.0.0.0:8090 \
--origins="${PB_ALLOWED_ORIGINS:-http://localhost:3000,http://127.0.0.1:3000,http://localhost:3003,http://127.0.0.1:3003,http://localhost:7575,http://127.0.0.1:7575}" \
--origins="${PB_ALLOWED_ORIGINS:-*}" \
--dir=/pb_data \
--hooksDir=/pb_hooks \
--migrationsDir=/pb_migrations
--migrationsDir=/pb_migrations \
--publicDir=/pb_public \
--indexFallback=true