- install.sh: prompt for license key as first step, validate against makeyourown.website/api/validate before any system changes - setup.sh: secondary key check (format-only if .license-key exists, server validation if missing) - Remove website/ directory — marketing site, keyserver, and deploy scripts migrated to the websites repo (git.constantprojects.xyz/ tankadmin/websites.git) for independent deployment - Update CLAUDE.md, guide.md, .gitignore to reflect migration Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
125 lines
7.2 KiB
Markdown
125 lines
7.2 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Critical Rules
|
|
|
|
- **NEVER build, test, or run anything locally.** Always use Docker for all build/test/run operations.
|
|
- **`websitebox-brief (2).md` is the source of truth** for all project decisions and specifications. Always defer to it.
|
|
- **Do not load `websitebox-diagram (1).jsx`** unless the user explicitly asks for it — it is reference material only.
|
|
- **Keep `guide.md` in sync.** Any change that alters the user-facing flow — new commands, renamed scripts, changed setup wizard prompts, added/removed steps, new dependencies, modified ports, updated troubleshooting — **must** also be reflected in `guide.md`. This is a beginner-facing deployment guide in ProjectPublic markup format. If you're unsure whether a change affects the guide, check. Treat guide.md as a living document that must always match the actual codebase.
|
|
|
|
## Project Overview
|
|
|
|
WebsiteBox is a Docker-based, self-hosted WordPress deployment system. Users provision a VPS, run an install script, and get a working SSL-secured WordPress portfolio site with `docker compose up -d`. The project prioritizes zero-trust transparency, minimal CLI interaction, and VPS-agnostic deployment.
|
|
|
|
## Architecture
|
|
|
|
Four-container Docker Compose stack on a single Docker network (`websitebox_internal`):
|
|
|
|
- **nginx** (custom `nginx:alpine`) — Reverse proxy, SSL termination via Let's Encrypt. Only container exposing ports (80, 443). Entrypoint auto-acquires SSL certs on first boot.
|
|
- **wordpress** (custom `wordpress:php8.2-fpm-alpine`) — PHP-FPM with WP-CLI bundled. First-boot entrypoint installs WordPress core, GeneratePress theme, child theme, and plugins (Age Gate, Wordfence, UpdraftPlus) via WP-CLI.
|
|
- **db** (`mariadb:11`) — Internal only, never exposed to host.
|
|
- **certbot** (`certbot/certbot`) — Renewal loop every 12h, signals nginx via shared volume file trigger (no Docker socket mount).
|
|
|
|
All persistent data uses **bind mounts** under `./websitebox-data/` (not named Docker volumes):
|
|
- `wordpress/`, `database/`, `certs/`, `certbot-webroot/`, `certbot-signal/`, `backups/`
|
|
|
|
## Key Design Decisions
|
|
|
|
- **Restart policy**: `restart: unless-stopped` on all containers (not `always`).
|
|
- **SSL bootstrap**: Handled entirely in nginx entrypoint — no separate ssl-init.sh script. Nginx detects missing certs, serves HTTP for ACME challenge, acquires certs, reloads with SSL.
|
|
- **Certbot-to-nginx reload**: Certbot writes trigger file to shared `certbot-signal/` volume; nginx background loop detects and reloads. No Docker socket mounting.
|
|
- **WordPress setup**: All via WP-CLI in container entrypoint, not the mu-plugin. Uses marker files (`.websitebox-setup-complete` / `.websitebox-setup-partial`) for idempotency.
|
|
- **Backup path**: UpdraftPlus writes to `/var/backups/websitebox` (mapped to `./websitebox-data/backups/`), deliberately outside `/var/www/html` to avoid nested bind mount conflicts.
|
|
- **XML-RPC disable**: In mu-plugin via `add_filter('xmlrpc_enabled', '__return_false')`, NOT in wp-config.php (plugin API not loaded at wp-config time).
|
|
- **WP-CLI**: Bundled in WordPress Docker image. Run commands as `www-data`, never use `--allow-root`.
|
|
- **Table prefix**: `wbox_` (not default `wp_`).
|
|
- **wp-config**: Sets `DISALLOW_FILE_EDIT` (blocks theme/plugin editor) but NOT `DISALLOW_FILE_MODS` (would prevent plugin/theme updates via admin GUI).
|
|
|
|
## User Flow
|
|
|
|
1. `curl -fsSL <url>/install.sh | bash` — installs Docker, clones repo, runs setup wizard
|
|
2. `setup.sh` — interactive wizard, generates `.env`, creates `websitebox-data/` structure
|
|
3. User configures DNS A record
|
|
4. `docker compose up -d` — everything self-configures
|
|
|
|
## File Structure Conventions
|
|
|
|
- `nginx/entrypoint.sh` — SSL auto-bootstrap logic
|
|
- `wordpress/entrypoint.sh` — First-boot WP-CLI setup (theme/plugin install, site config)
|
|
- `wordpress/wp-content/mu-plugins/websitebox-setup.php` — Lightweight status checker + XML-RPC disable (not the installer)
|
|
- `wordpress/wp-content/themes/websitebox/` — Child theme (parent: GeneratePress)
|
|
- `scripts/` — `backup.sh`, `update.sh`, `ssl-renew.sh`, `healthcheck.sh`
|
|
- `.env` / `.env.example` — Configuration (gitignored / template)
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
# Start the stack
|
|
docker compose up -d
|
|
|
|
# Rebuild after Dockerfile changes
|
|
docker compose up -d --build
|
|
|
|
# View logs
|
|
docker compose logs -f [service]
|
|
|
|
# Restart a specific service
|
|
docker compose restart wordpress
|
|
|
|
# Re-run first-boot setup (force clean)
|
|
docker compose exec wordpress rm /var/www/html/.websitebox-setup-complete /var/www/html/.websitebox-setup-partial
|
|
docker compose restart wordpress
|
|
|
|
# Update WebsiteBox
|
|
./scripts/update.sh
|
|
|
|
# Manual backup
|
|
./scripts/backup.sh
|
|
```
|
|
|
|
## Healthchecks
|
|
|
|
| Service | Check | Retries |
|
|
|---------|-------|---------|
|
|
| nginx | `curl -f http://localhost/nginx-health` | 3 |
|
|
| wordpress | `php-fpm-healthcheck` | 3 |
|
|
| db | `healthcheck --su-mysql --connect --innodb_initialized` | 5 |
|
|
|
|
WordPress depends on db with `condition: service_healthy`.
|
|
|
|
## Error Handling Patterns
|
|
|
|
- WordPress entrypoint: MariaDB retry loop (30 attempts, 2s apart). On partial failure, creates `.websitebox-setup-partial` marker and starts PHP-FPM anyway. All WP-CLI commands are idempotent — safe to re-run entire sequence.
|
|
- nginx entrypoint: On SSL failure, serves HTTP placeholder explaining DNS isn't ready. User retries with `docker compose restart nginx`.
|
|
- install.sh: Uses `sg docker` for immediate Docker group activation without logout/login.
|
|
|
|
## Marketing Site & License Keys (separate repo)
|
|
|
|
The marketing site (makeyourown.website) and license key validation server live in a **separate repository**: `https://git.constantprojects.xyz/tankadmin/websites.git` (local: `~/claude/projects/websites`). This is business infrastructure that runs on its own VPS, independent of any WebsiteBox test/product deployments.
|
|
|
|
### License key validation (client-side)
|
|
- `install.sh` prompts for a license key as the very first step (before any system changes)
|
|
- `setup.sh` has a secondary check (format-only if `.license-key` file exists, server validation if missing)
|
|
- **Endpoint:** `POST https://makeyourown.website/api/validate` with body `key=WBOX-XXXX-XXXX-XXXX-XXXX`
|
|
- **Key format:** `WBOX-XXXX-XXXX-XXXX-XXXX` (uppercase alphanumeric, no ambiguous chars 0/O/1/I/L)
|
|
- **Behavior:** Burn-on-use — keys are consumed on first activation
|
|
- **Storage:** `.license-key` file in project root (gitignored, chmod 600)
|
|
|
|
### What lives where
|
|
| Concern | Location |
|
|
|---------|----------|
|
|
| Key check in install flow | This repo: `install.sh`, `setup.sh` |
|
|
| Keyserver, key generation, marketing site | `websites` repo: `services/keyserver/`, `scripts/generate-keys.sh`, `sites/makeyourown.website/` |
|
|
| Key storage (keys.txt) | `websites` VPS: `services/keyserver/keys.txt` |
|
|
|
|
### Business rules
|
|
- WebsiteBox is **not free** and **not "open source"** — code is auditable, buyers can read every line before purchasing
|
|
- Do not say "free" or "open source" in marketing content
|
|
- Pricing tiers: Standard $49 one-time, Lifetime Updates $149 one-time, Managed $25/month (all placeholder amounts)
|
|
|
|
## Non-Goals (v1)
|
|
|
|
Payment processing, multi-site WordPress, automatic VPS provisioning, built-in CDN, email server (SMTP relay config only).
|