Private
Public Access
1
0

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>
This commit is contained in:
constantprojects
2026-02-20 15:24:23 -07:00
commit a440026701
32 changed files with 3397 additions and 0 deletions

104
docker-compose.yml Normal file
View File

@@ -0,0 +1,104 @@
services:
nginx:
build:
context: ./nginx
container_name: websitebox-nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./websitebox-data/certs:/etc/letsencrypt
- ./websitebox-data/certbot-webroot:/var/www/certbot
- ./websitebox-data/certbot-signal:/var/run/certbot-signal
- ./websitebox-data/wordpress:/var/www/html:ro
environment:
- DOMAIN=${DOMAIN}
- ADMIN_EMAIL=${ADMIN_EMAIL}
depends_on:
wordpress:
condition: service_started
restart: unless-stopped
networks:
- websitebox_internal
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/nginx-health"]
interval: 30s
timeout: 10s
retries: 3
wordpress:
build:
context: ./wordpress
container_name: websitebox-wordpress
volumes:
- ./websitebox-data/wordpress:/var/www/html
- ./websitebox-data/backups:/var/backups/websitebox
environment:
- DOMAIN=${DOMAIN}
- SITE_TITLE=${SITE_TITLE}
- ADMIN_USER=${ADMIN_USER}
- ADMIN_EMAIL=${ADMIN_EMAIL}
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
- WORDPRESS_DB_HOST=db
- WORDPRESS_DB_NAME=${DB_NAME}
- WORDPRESS_DB_USER=${DB_USER}
- WORDPRESS_DB_PASSWORD=${DB_PASSWORD}
- WORDPRESS_TABLE_PREFIX=wbox_
- WORDPRESS_CONFIG_EXTRA=
- AGE_GATE_ENABLED=${AGE_GATE_ENABLED}
- AGE_GATE_MIN_AGE=${AGE_GATE_MIN_AGE}
- BACKUP_RETENTION_DAYS=${BACKUP_RETENTION_DAYS}
- WORDPRESS_AUTH_KEY=${AUTH_KEY}
- WORDPRESS_SECURE_AUTH_KEY=${SECURE_AUTH_KEY}
- WORDPRESS_LOGGED_IN_KEY=${LOGGED_IN_KEY}
- WORDPRESS_NONCE_KEY=${NONCE_KEY}
- WORDPRESS_AUTH_SALT=${AUTH_SALT}
- WORDPRESS_SECURE_AUTH_SALT=${SECURE_AUTH_SALT}
- WORDPRESS_LOGGED_IN_SALT=${LOGGED_IN_SALT}
- WORDPRESS_NONCE_SALT=${NONCE_SALT}
depends_on:
db:
condition: service_healthy
restart: unless-stopped
networks:
- websitebox_internal
healthcheck:
test: ["CMD", "php-fpm-healthcheck"]
interval: 30s
timeout: 10s
retries: 3
db:
image: mariadb:11
container_name: websitebox-db
volumes:
- ./websitebox-data/database:/var/lib/mysql
environment:
- MARIADB_DATABASE=${DB_NAME}
- MARIADB_USER=${DB_USER}
- MARIADB_PASSWORD=${DB_PASSWORD}
- MARIADB_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
restart: unless-stopped
networks:
- websitebox_internal
healthcheck:
test: ["CMD", "healthcheck", "--su-mysql", "--connect", "--innodb_initialized"]
interval: 30s
timeout: 10s
retries: 5
certbot:
image: certbot/certbot
container_name: websitebox-certbot
volumes:
- ./websitebox-data/certs:/etc/letsencrypt
- ./websitebox-data/certbot-webroot:/var/www/certbot
- ./websitebox-data/certbot-signal:/var/run/certbot-signal
entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew --deploy-hook \"touch /var/run/certbot-signal/reload\"; sleep 12h & wait $${!}; done;'"
restart: unless-stopped
networks:
- websitebox_internal
networks:
websitebox_internal:
driver: bridge