Files
NextChair/README.md
T
Stefan Lazic 479cefd085
CI / ci (push) Canceled after 0s
Update README.md
2026-09-06 13:02:20 +01:00

172 lines
5.9 KiB
Markdown

# NextChair
Booking app as an alternative to Booksy
## VPS deployment (multi-business)
Everything below runs on a fresh VPS with Docker and the Compose plugin
already installed — no other prerequisite (no host Node.js/npm needed;
every command either uses Docker itself or plain shell tools). Every code
block is meant to be pasted as-is, in order.
### 0. One-time: clone the repo and generate your secrets
```bash
# STACKS_DIR later on must be this exact absolute path — every stack
# shells `docker compose` back out to the HOST's dockerd via a mounted
# socket, so the path only resolves to the same thing on both sides if
# it's cloned here and never moved.
git clone <your-repo-url> /opt/nextchair
cd /opt/nextchair
```
Generate the secrets you'll paste into the `.env` files in the steps
below. Run these now and keep the output somewhere safe (a password
manager) — you'll need each value again in a moment.
```bash
# MYSQL_ROOT_PASSWORD — goes into BOTH stacks/infra/.env and manager/.env
# (the same value in both places).
echo "MYSQL_ROOT_PASSWORD=$(openssl rand -hex 24)"
# MANAGER_SESSION_SECRET — manager/.env only.
echo "MANAGER_SESSION_SECRET=$(openssl rand -hex 32)"
# MANAGER_SETTINGS_ENCRYPTION_KEY — manager/.env only. Encrypts the
# SMTP/VAPID secrets you'll enter in the Manager's Settings page later.
# Losing/rotating this makes any already-saved secret there undecryptable,
# so store it as carefully as the other secrets on this page.
echo "MANAGER_SETTINGS_ENCRYPTION_KEY=$(openssl rand -hex 32)"
```
```bash
# MANAGER_PASSWORD_HASH — manager/.env only. Replace "your-password" with
# your chosen Manager login password first. Run via a throwaway container
# so this works with nothing but Docker installed on the host.
docker run --rm node:22-alpine sh -c \
"mkdir -p /tmp/gen && cd /tmp/gen && npm install bcryptjs --no-audit --no-fund >/dev/null 2>&1 && \
node -e \"console.log('MANAGER_PASSWORD_HASH=' + require('/tmp/gen/node_modules/bcryptjs').hashSync('your-password', 12))\""
```
### 1. Shared infrastructure — network, MySQL, Caddy, Dockge
```bash
docker network create next-chair-edge
cp .env.infra.example stacks/infra/.env
```
Edit `stacks/infra/.env`:
- `MYSQL_ROOT_PASSWORD` — the first secret you generated above.
- `ACME_EMAIL` — a real address you check (Let's Encrypt renewal notices).
- `STACKS_DIR` — the absolute clone path, e.g. `/opt/nextchair/stacks`.
```bash
docker compose -f stacks/infra/compose.yaml --env-file stacks/infra/.env up -d
```
### 2. Build the shared application image
Every business (and no other step in this guide) runs this same image —
you only rebuild it here, once, and again whenever you ship a code
update (see "Updating" below).
```bash
docker build -t nextchair-app:latest .
```
### 3. The management UI (Manager)
This is what you'll use to add every business from here on.
```bash
cp manager/.env.example stacks/manager/.env
```
Edit `stacks/manager/.env`:
- `MANAGER_EMAIL` — the email you'll log in with.
- `MANAGER_PASSWORD_HASH` — the bcrypt hash generated in step 0.
- `MANAGER_SESSION_SECRET` and `MANAGER_SETTINGS_ENCRYPTION_KEY` — the two
other values generated in step 0.
- `MANAGER_PUBLIC_URL` — `https://` + the domain you'll point at this app
in the next step.
- `MYSQL_ROOT_PASSWORD` — same value as `stacks/infra/.env`.
- `STACKS_DIR` — same absolute path as step 1.
```bash
docker compose -f stacks/manager/compose.yaml --env-file stacks/manager/.env up -d --build
```
Point your chosen Manager domain's DNS (A/AAAA record) at the VPS, then
give it a Caddy site and reload:
```bash
cat > stacks/infra/sites/manager.caddy << 'EOF'
manager.example.com {
reverse_proxy next-chair-manager:3000
}
EOF
docker exec next-chair-caddy caddy reload --config /etc/caddy/Caddyfile
```
(Replace `manager.example.com` with your real domain — Caddy issues its
TLS certificate automatically on first request.)
### 4. Configure platform-wide settings (once)
Log into the Manager at `https://<your-manager-domain>` and open
**Settings**. Both sections are optional to fill in now, but doing it
before adding your first business means that business never needs its
own SMTP/push setup:
- **Email / SMTP** — your SMTP relay's host/port/username/password and a
from-address. Use **Send Test Email** to confirm it before saving for
real, then **Save Changes** to apply it to every business.
- **Push Notifications** — click **Generate VAPID Keys** once (a contact
email is enough to start). This is a one-time, platform-wide key pair —
see that section's own copy for what happens if you ever regenerate it.
### 5. Add your first business
Still in the Manager: **Add Business** → name, slug, domain. This creates
its database, generates its secrets, starts its container, and runs its
migrations for you — no manual per-business `.env` editing needed.
Point that business's own domain's DNS at the VPS (the Manager doesn't do
this for you), then finish its setup by visiting
`https://<business-domain>/install`.
Repeat this step for each additional business, whenever you want one.
## Updating after a code change
```bash
cd /opt/nextchair
git pull
# Rebuild the one shared image every business uses.
docker build -t nextchair-app:latest .
```
Then, for **each** business: use its **Update** button in the Manager UI,
or run this directly:
```bash
cd stacks/<slug>
docker compose --env-file .env up -d --force-recreate
```
Either way this recreates that business's container against the freshly
built image — and its own startup automatically runs
`prisma migrate deploy`, so any new database migration is applied on the
same step. No separate migration command needed.
If the code change touched the **Manager app itself** (anything under
`manager/`), update it the same way — this one does rebuild, since unlike
a business it doesn't share a prebuilt image:
```bash
cd /opt/nextchair
docker compose -f stacks/manager/compose.yaml --env-file stacks/manager/.env up -d --build
```