mirror of
https://github.com/myronblair/novacpx
synced 2026-06-30 17:50:41 -05:00
feat: feature registry, auto-deploy, IP management, Docker support
Feature Manager (70+ features across 20 categories): - Web servers: Apache2, nginx, OpenLiteSpeed, Varnish - PHP: 7.4/8.1/8.2/8.3 multi-version, Composer - Databases: MySQL 8, MariaDB, PostgreSQL, Redis, Memcached, phpMyAdmin, phpPgAdmin - Email: Postfix, Dovecot, Roundcube, RainLoop, SpamAssassin, Rspamd, DKIM - DNS: BIND9, PowerDNS - FTP: ProFTPD, vsftpd, Pure-FTPd - SSL: Certbot/Let's Encrypt, acme.sh - Security: Fail2Ban, ModSecurity WAF, ImunifyAV, ClamAV, UFW, CrowdSec - Containers: Docker Engine, Docker Compose, Portainer CE, per-account Docker hosting - IP Management: Shared IPs (SNI), Dedicated IPs, IPv6 - Monitoring: Netdata, AWStats, GoAccess, Grafana+Prometheus - Backup: BorgBackup, rclone (S3/B2/GCS), Duplicati - CDN: Cloudflare API, PageSpeed Module - Dev: Gitea, Phusion Passenger, JupyterHub - One-click apps: WordPress+WP-CLI, auto-installer (50+ apps) - Billing: WHMCS bridge, BoxBilling - Reseller: White label, custom nameservers - Notifications: Email, Slack, Telegram - Compliance: Auditd, OSSEC HIDS Auto-deploy pipeline (deploy/): - webhook.php: HMAC-verified GitHub push webhook - deploy-runner.sh: PHP syntax validation → git pull → rsync → DB migrations → PHP-FPM reload - setup-deploy.sh: one-shot setup script, outputs GitHub webhook config - Runs every minute via cron; locked to prevent concurrent deploys Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* NovaCPX Auto-Deploy Webhook Handler
|
||||
* Place at: https://<panel-ip>:2083/deploy/webhook.php
|
||||
* GitHub webhook: push to main branch → this endpoint
|
||||
* Secret set in /etc/novacpx/config.ini [deploy] webhook_secret
|
||||
*/
|
||||
|
||||
$configFile = '/etc/novacpx/config.ini';
|
||||
$cfg = is_file($configFile) ? parse_ini_file($configFile, true) : [];
|
||||
$secret = $cfg['deploy']['webhook_secret'] ?? '';
|
||||
$repoPath = $cfg['deploy']['repo_path'] ?? '/opt/novacpx-src';
|
||||
$webRoot = $cfg['deploy']['web_root'] ?? '/srv/novacpx/public';
|
||||
$branch = $cfg['deploy']['branch'] ?? 'main';
|
||||
$logFile = '/var/log/novacpx/deploy.log';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
function log_deploy(string $msg): void {
|
||||
global $logFile;
|
||||
file_put_contents($logFile, date('[Y-m-d H:i:s] ') . $msg . "\n", FILE_APPEND | LOCK_EX);
|
||||
}
|
||||
|
||||
// Verify HMAC signature
|
||||
$rawBody = file_get_contents('php://input');
|
||||
$hubSig = $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? '';
|
||||
if ($secret) {
|
||||
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $secret);
|
||||
if (!hash_equals($expected, $hubSig)) {
|
||||
http_response_code(403);
|
||||
log_deploy('BLOCKED: invalid signature');
|
||||
echo json_encode(['error' => 'Invalid signature']);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$payload = json_decode($rawBody, true);
|
||||
$pushedBranch = basename($payload['ref'] ?? '');
|
||||
|
||||
if ($pushedBranch !== $branch) {
|
||||
echo json_encode(['status' => 'skipped', 'reason' => "Not target branch ($branch)"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$commit = $payload['after'] ?? 'unknown';
|
||||
$pusher = $payload['pusher']['name'] ?? 'unknown';
|
||||
$message = $payload['head_commit']['message'] ?? '';
|
||||
|
||||
log_deploy("Deploy triggered by $pusher | commit $commit | $message");
|
||||
|
||||
// Queue the deploy (non-blocking)
|
||||
$queueFile = '/tmp/novacpx-deploy-queue.txt';
|
||||
file_put_contents($queueFile, "$repoPath|$webRoot|$commit\n", FILE_APPEND | LOCK_EX);
|
||||
|
||||
http_response_code(200);
|
||||
echo json_encode(['status' => 'queued', 'commit' => $commit]);
|
||||
Reference in New Issue
Block a user