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:
90
wordpress/wp-content/mu-plugins/websitebox-setup.php
Normal file
90
wordpress/wp-content/mu-plugins/websitebox-setup.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: WebsiteBox Setup Status
|
||||
* Description: Displays setup status notices and dashboard widget. Disables XML-RPC.
|
||||
* Version: 1.0.0
|
||||
* Author: WebsiteBox
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Disable XML-RPC
|
||||
add_filter('xmlrpc_enabled', '__return_false');
|
||||
|
||||
// Admin notices based on setup status
|
||||
add_action('admin_notices', function () {
|
||||
$complete = ABSPATH . '.websitebox-setup-complete';
|
||||
$partial = ABSPATH . '.websitebox-setup-partial';
|
||||
|
||||
if (file_exists($complete)) {
|
||||
return; // Normal operation
|
||||
}
|
||||
|
||||
if (file_exists($partial)) {
|
||||
echo '<div class="notice notice-warning"><p>';
|
||||
echo '<strong>WebsiteBox:</strong> Initial setup completed with errors. ';
|
||||
echo 'Some plugins or themes may not have installed correctly. ';
|
||||
echo 'To retry, run: <code>docker compose restart wordpress</code>';
|
||||
echo '</p></div>';
|
||||
return;
|
||||
}
|
||||
|
||||
echo '<div class="notice notice-info"><p>';
|
||||
echo '<strong>WebsiteBox:</strong> Initial setup is still in progress. ';
|
||||
echo 'The container may still be installing themes and plugins. Please wait a moment and refresh this page.';
|
||||
echo '</p></div>';
|
||||
});
|
||||
|
||||
// Dashboard widget
|
||||
add_action('wp_dashboard_setup', function () {
|
||||
wp_add_dashboard_widget(
|
||||
'websitebox_status',
|
||||
'WebsiteBox Status',
|
||||
'websitebox_dashboard_widget'
|
||||
);
|
||||
});
|
||||
|
||||
function websitebox_dashboard_widget() {
|
||||
$complete = file_exists(ABSPATH . '.websitebox-setup-complete');
|
||||
$partial = file_exists(ABSPATH . '.websitebox-setup-partial');
|
||||
|
||||
echo '<table class="widefat" style="border:0">';
|
||||
|
||||
// Setup status
|
||||
echo '<tr><td><strong>Setup Status</strong></td><td>';
|
||||
if ($complete) {
|
||||
echo '<span style="color:green">✓ Complete</span>';
|
||||
} elseif ($partial) {
|
||||
echo '<span style="color:orange">⚠ Partial — retry with: <code>docker compose restart wordpress</code></span>';
|
||||
} else {
|
||||
echo '<span style="color:blue">⌛ In progress...</span>';
|
||||
}
|
||||
echo '</td></tr>';
|
||||
|
||||
// Age Gate status
|
||||
if (is_plugin_active('age-gate/age-gate.php')) {
|
||||
$min_age = get_option('age_gate_min_age', '18');
|
||||
$restrict_all = get_option('age_gate_restrict_all', '0');
|
||||
echo '<tr><td><strong>Age Gate</strong></td><td>';
|
||||
echo $restrict_all ? "Enabled (minimum age: {$min_age})" : 'Installed but not restricting all content';
|
||||
echo '</td></tr>';
|
||||
} else {
|
||||
echo '<tr><td><strong>Age Gate</strong></td><td>Not active</td></tr>';
|
||||
}
|
||||
|
||||
// Backup status
|
||||
if (is_plugin_active('updraftplus/updraftplus.php')) {
|
||||
$last_backup = get_option('updraft_last_backup', []);
|
||||
echo '<tr><td><strong>Backups</strong></td><td>';
|
||||
if (!empty($last_backup['backup_time'])) {
|
||||
echo 'Last backup: ' . date('Y-m-d H:i', $last_backup['backup_time']);
|
||||
} else {
|
||||
echo 'No backups yet';
|
||||
}
|
||||
echo '</td></tr>';
|
||||
}
|
||||
|
||||
echo '</table>';
|
||||
}
|
||||
37
wordpress/wp-content/themes/websitebox/functions.php
Normal file
37
wordpress/wp-content/themes/websitebox/functions.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* WebsiteBox Child Theme Functions
|
||||
*/
|
||||
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Enqueue parent theme styles
|
||||
add_action('wp_enqueue_scripts', function () {
|
||||
wp_enqueue_style(
|
||||
'generatepress-parent',
|
||||
get_template_directory_uri() . '/style.css',
|
||||
[],
|
||||
wp_get_theme('generatepress')->get('Version')
|
||||
);
|
||||
wp_enqueue_style(
|
||||
'websitebox-child',
|
||||
get_stylesheet_uri(),
|
||||
['generatepress-parent'],
|
||||
wp_get_theme()->get('Version')
|
||||
);
|
||||
});
|
||||
|
||||
// Remove GeneratePress footer branding
|
||||
add_filter('generate_copyright', function () {
|
||||
return '';
|
||||
});
|
||||
|
||||
// Set portfolio-friendly defaults
|
||||
add_action('after_setup_theme', function () {
|
||||
add_theme_support('post-thumbnails');
|
||||
set_post_thumbnail_size(1200, 800, true);
|
||||
add_image_size('portfolio-thumb', 600, 400, true);
|
||||
add_image_size('portfolio-full', 1920, 1080, false);
|
||||
});
|
||||
13
wordpress/wp-content/themes/websitebox/index.php
Normal file
13
wordpress/wp-content/themes/websitebox/index.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
// Silence is golden. GeneratePress handles all template rendering.
|
||||
// This file exists only because WordPress requires index.php in every theme.
|
||||
get_header();
|
||||
if (have_posts()) :
|
||||
while (have_posts()) : the_post();
|
||||
get_template_part('content', get_post_type());
|
||||
endwhile;
|
||||
the_posts_navigation();
|
||||
else :
|
||||
get_template_part('content', 'none');
|
||||
endif;
|
||||
get_footer();
|
||||
12
wordpress/wp-content/themes/websitebox/style.css
Normal file
12
wordpress/wp-content/themes/websitebox/style.css
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Theme Name: WebsiteBox
|
||||
Theme URI: https://github.com/websitebox/websitebox
|
||||
Description: A clean portfolio child theme for WebsiteBox, built on GeneratePress.
|
||||
Author: WebsiteBox
|
||||
Author URI: https://github.com/websitebox/websitebox
|
||||
Template: generatepress
|
||||
Version: 1.0.0
|
||||
License: GNU General Public License v3 or later
|
||||
License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
||||
Text Domain: websitebox
|
||||
*/
|
||||
66
wordpress/wp-content/themes/websitebox/theme.json
Normal file
66
wordpress/wp-content/themes/websitebox/theme.json
Normal file
@@ -0,0 +1,66 @@
|
||||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/theme.json",
|
||||
"version": 3,
|
||||
"settings": {
|
||||
"color": {
|
||||
"palette": [
|
||||
{
|
||||
"slug": "primary",
|
||||
"color": "#1a1a2e",
|
||||
"name": "Primary"
|
||||
},
|
||||
{
|
||||
"slug": "secondary",
|
||||
"color": "#16213e",
|
||||
"name": "Secondary"
|
||||
},
|
||||
{
|
||||
"slug": "accent",
|
||||
"color": "#e94560",
|
||||
"name": "Accent"
|
||||
},
|
||||
{
|
||||
"slug": "light",
|
||||
"color": "#f8f9fa",
|
||||
"name": "Light"
|
||||
},
|
||||
{
|
||||
"slug": "dark",
|
||||
"color": "#0f0f1a",
|
||||
"name": "Dark"
|
||||
}
|
||||
]
|
||||
},
|
||||
"typography": {
|
||||
"fontSizes": [
|
||||
{
|
||||
"slug": "small",
|
||||
"size": "0.875rem",
|
||||
"name": "Small"
|
||||
},
|
||||
{
|
||||
"slug": "medium",
|
||||
"size": "1rem",
|
||||
"name": "Medium"
|
||||
},
|
||||
{
|
||||
"slug": "large",
|
||||
"size": "1.5rem",
|
||||
"name": "Large"
|
||||
},
|
||||
{
|
||||
"slug": "x-large",
|
||||
"size": "2.25rem",
|
||||
"name": "Extra Large"
|
||||
}
|
||||
]
|
||||
},
|
||||
"spacing": {
|
||||
"units": ["px", "em", "rem", "%", "vh", "vw"]
|
||||
},
|
||||
"layout": {
|
||||
"contentSize": "1200px",
|
||||
"wideSize": "1400px"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user