Private
Public Access
1
0
Files
websitebox/CLAUDE.md
constantprojects a440026701 Initial commit: complete WebsiteBox project
Docker-based self-hosted WordPress deployment system with:
- Four-container stack (nginx, wordpress/php-fpm, mariadb, certbot)
- Automatic SSL via Let's Encrypt with self-signed fallback
- First-boot WordPress setup via WP-CLI (GeneratePress + child theme, plugins)
- Interactive setup wizard and one-line install script
- Backup, update, healthcheck, and SSL renewal scripts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 15:24:23 -07:00

5.1 KiB

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.

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

# 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.

Non-Goals (v1)

Payment processing, multi-site WordPress, automatic VPS provisioning, built-in CDN, email server (SMTP relay config only).