如何用PHP自动创建Nginx配置并部署Let's Encrypt证书?
Absolutely! You can fully automate the workflow of generating Nginx site configurations, installing Let's Encrypt SSL certificates, and enabling sites using PHP. I’ve broken down the process with code examples and key considerations to make this reliable and secure:
Before diving into code, make sure these are in place:
- Certbot is installed (with the
certbot-nginxplugin for easier integration) - Your Nginx setup uses the standard
sites-available/sites-enableddirectory structure - The PHP process user (typically
www-data) has:- Write access to
/etc/nginx/sites-available - Passwordless sudo privileges for
certbotand Nginx commands (add this via/etc/sudoers.d/php-certbot:www-data ALL=(ALL) NOPASSWD: /usr/bin/certbot, /usr/sbin/nginx)
- Write access to
Create a reusable template for Nginx configs, then populate it with the customer's domain and save it to the sites-available directory.
<?php // Sanitize and validate the customer's domain from the form $customerDomain = filter_input(INPUT_POST, 'domain', FILTER_SANITIZE_URL); if (!$customerDomain || !preg_match('/^[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/', $customerDomain)) { die("Invalid or missing domain"); } // Nginx config template (adjust paths/settings to match your server) $nginxConfig = <<<EOT server { listen 80; server_name $customerDomain; # Temporary redirect to HTTPS (will work once cert is installed) return 301 https://\$server_name\$request_uri; } server { listen 443 ssl; server_name $customerDomain; # SSL paths (will be populated by Certbot) ssl_certificate /etc/letsencrypt/live/$customerDomain/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/$customerDomain/privkey.pem; # Site root (create this directory first if needed) root /var/www/$customerDomain; index index.php index.html; location / { try_files \$uri \$uri/ =404; } # PHP-FPM setup (adjust socket path to match your PHP version) location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.2-fpm.sock; } } EOT; // Save the config to sites-available $configPath = "/etc/nginx/sites-available/$customerDomain.conf"; if (file_put_contents($configPath, $nginxConfig) === false) { die("Failed to create Nginx configuration file"); } echo "Nginx config created at $configPath"; ?>
Use Certbot's --nginx plugin to automatically generate and install the SSL certificate. The plugin will also validate domain ownership via Nginx.
<?php // Certbot command (adjust email and flags to your needs) $certbotCmd = sprintf( "sudo certbot certonly --nginx -d %s --non-interactive --agree-tos --email your-admin@example.com", escapeshellarg($customerDomain) // Critical: escape the domain to prevent injection ); // Execute command and check results exec($certbotCmd, $certbotOutput, $returnCode); if ($returnCode !== 0) { die("Certbot failed: " . implode("\n", $certbotOutput)); } echo "SSL certificate installed successfully for $customerDomain"; ?>
Create a symlink from sites-available to sites-enabled, then test and reload Nginx to apply changes.
<?php $enabledPath = "/etc/nginx/sites-enabled/$customerDomain.conf"; // Create symlink if it doesn't exist if (!file_exists($enabledPath)) { if (!symlink($configPath, $enabledPath)) { die("Failed to enable site"); } } // Test Nginx config for errors exec("sudo nginx -t", $testOutput, $testReturnCode); if ($testReturnCode !== 0) { // Cleanup if config is invalid unlink($enabledPath); die("Nginx config test failed: " . implode("\n", $testOutput)); } // Reload Nginx to apply changes exec("sudo systemctl reload nginx", $reloadOutput, $reloadReturnCode); if ($reloadReturnCode !== 0) { die("Failed to reload Nginx: " . implode("\n", $reloadOutput)); } echo "Site enabled and Nginx reloaded successfully!"; ?>
- Input Validation: Always sanitize user-provided domains (as shown) to prevent command injection attacks.
- Rate Limits: Let's Encrypt has request limits—add retry logic with delays for failed certificate requests.
- Logging: Log every step (config creation, cert installation, Nginx reload) to a file for debugging.
- Dry Runs: Test Certbot commands with
--dry-runfirst to avoid hitting rate limits during development. - Cleanup: If any step fails, roll back changes (e.g., delete the config file, remove symlinks) to keep your Nginx setup consistent.
内容的提问来源于stack exchange,提问作者Luuk F.

