feat: implement dynamic Nginx project configuration and IPC service management for PHP environments

This commit is contained in:
Ümit Tunç
2026-03-30 08:19:15 +03:00
parent 039d0a2782
commit c5d6635f01
2 changed files with 25 additions and 17 deletions
+17 -11
View File
@@ -1,25 +1,31 @@
location ^~ /{{HOST}}/ { location ^~ /{{HOST}}/ {
alias "{{PATH}}/"; alias "{{PATH}}";
index index.php index.html; index index.php index.html;
autoindex on; autoindex on;
# Try the literal URI, then directory (checks for index), then fallback to root index.php # Use a named location for reliable alias fallback
try_files $uri $uri/ /{{HOST}}/index.php?$query_string; try_files $uri $uri/ @{{HOST}};
# PHP handling nested INSIDE the alias location to maintain context # PHP handling nested INSIDE the alias location to maintain context
location ~ \.php$ { location ~ \.php$ {
fastcgi_pass 127.0.0.1:{{PHP_PORT}}; fastcgi_pass 127.0.0.1:{{PHP_PORT}};
fastcgi_index index.php; fastcgi_index index.php;
# Split path info to handle subdirectories correctly
fastcgi_split_path_info ^/{{HOST}}(.+\.php)(.*)$;
include "{{CONF_DIR}}/fastcgi_params"; include "{{CONF_DIR}}/fastcgi_params";
# Bulletproof SCRIPT_FILENAME: combine base path with relative script name from split_path_info # Normal files matched correctly by URI don't suffer the try_files bug
# On Windows + Alias, $request_filename can be flaky during try_files redirects fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_param SCRIPT_FILENAME "{{PATH}}$fastcgi_script_name";
fastcgi_param DOCUMENT_ROOT "{{PATH}}";
fastcgi_param PATH_INFO $fastcgi_path_info;
} }
} }
# The named location handles requests that don't match physical files
location @{{HOST}} {
# Directly execute PHP without URI mutation to preserve framework routing paths
fastcgi_pass 127.0.0.1:{{PHP_PORT}};
include "{{CONF_DIR}}/fastcgi_params";
# Hardcode the essential execution parameters
fastcgi_param SCRIPT_FILENAME "{{PATH}}index.php";
fastcgi_param SCRIPT_NAME "/{{HOST}}/index.php";
fastcgi_param DOCUMENT_ROOT "{{PATH}}";
}
+8 -6
View File
@@ -61,21 +61,23 @@ async function rebuildNginxConfig(forceProjects: boolean = false): Promise<{ bin
// If file exists, check if it was manually edited // If file exists, check if it was manually edited
if (!shouldGenerate && fs.existsSync(projectConfPath)) { if (!shouldGenerate && fs.existsSync(projectConfPath)) {
const currentContent = fs.readFileSync(projectConfPath, 'utf8') const currentContent = fs.readFileSync(projectConfPath, 'utf8')
if (currentContent.includes('# MANUAL_EDIT')) { if (!currentContent.includes('# MANUAL_EDIT')) {
shouldGenerate = false // Never overwrite manual edits during auto-rebuild // Overwrite old, broken configs that don't have the marker
} else if (forceProjects) {
shouldGenerate = true shouldGenerate = true
} }
} }
if (shouldGenerate) { if (shouldGenerate) {
const phpPort = portMappingService.getPhpPort(p.phpVersion) const phpPort = portMappingService.getPhpPort(p.phpVersion)
const normalizedPath = p.path.replace(/\\/g, '/')
// Ensure path ends with a slash for alias compatibility // Ensure path ends with a slash for alias compatibility
const pathWithSlash = normalizedPath.endsWith('/') ? normalizedPath : `${normalizedPath}/` let normalizedPath = p.path.replace(/\\/g, '/')
if (!normalizedPath.endsWith('/')) {
normalizedPath += '/'
}
await configService.generateConfig('nginx_project.conf.template', `projects/${p.host}.conf`, { await configService.generateConfig('nginx_project.conf.template', `projects/${p.host}.conf`, {
HOST: p.host, HOST: p.host,
PATH: pathWithSlash, PATH: normalizedPath,
PHP_PORT: phpPort.toString(), PHP_PORT: phpPort.toString(),
CONF_DIR: confDir.replace(/\\/g, '/') CONF_DIR: confDir.replace(/\\/g, '/')
}) })