A simple bash script to easily setup and remove Nginx configurations automatically for Laravel, WordPress, and Node.js projects, including local SSL support using mkcert.
π Multi-OS Support: Works seamlessly on both macOS (Homebrew) and Linux (Ubuntu/Debian) with automatic OS detection and appropriate configuration paths.
- π§ Auto-generate Nginx configurations for:
- Laravel
- WordPress
- Symfony
- HTML/SPA (React, Vue, Angular)
- Node.js
- π Cross-platform compatibility (macOS & Linux)
- π Local SSL support via
mkcert - π§Ή Easy uninstall configurations including SSL certificates
- β‘ Run from anywhere with a single
setup-sitecommand - π Organized SSL certificate storage in
~/.local/ssl-certs/ - π Smart symlink management for Linux (sites-available β sites-enabled)
- Homebrew
- Nginx (
brew install nginx) - mkcert (
brew install mkcert) - nss (for Firefox trust store,
brew install nss)
-
Nginx
sudo apt install nginx -y
-
mkcert
sudo apt install libnss3-tools -y wget https://github.com/FiloSottile/mkcert/releases/latest/download/mkcert-v1.4.4-linux-amd64 sudo mv mkcert-v1.4.4-linux-amd64 /usr/local/bin/mkcert sudo chmod +x /usr/local/bin/mkcert mkcert -install
The script automatically detects your operating system and uses the appropriate Nginx configuration paths:
| OS | Folder Config | Include Default | Notes |
|---|---|---|---|
| macOS (Homebrew) | /usr/local/etc/nginx/servers/ |
include servers/*; |
Direct configuration files |
| Linux (Ubuntu/Debian) | /etc/nginx/sites-available/ & /etc/nginx/sites-enabled/ |
include /etc/nginx/sites-enabled/*; |
Uses symlinks from sites-available to sites-enabled |
- Configuration files are created in
/etc/nginx/sites-available/ - Symlinks are automatically created in
/etc/nginx/sites-enabled/ - When removing configurations, both the original file and symlink are deleted
-
Save the
setup-site.shfile to your home directory:# Move script to home directory mv setup-site.sh ~/setup-site.sh
-
Grant execution permissions:
# Give permission to execute the script chmod +x ~/setup-site.sh
-
Add to global PATH for access from anywhere:
# Create symbolic link to /usr/local/bin for global access sudo ln -sf ~/setup-site.sh /usr/local/bin/setup-site
-
Verify installation:
# Test if script can be run from anywhere setup-siteIf you see the menu:
=== βοΈ Setup / Remove Web Project === 1) Create new configuration 2) Remove existing configuration
Installation successful! π
# Run the setup-site script
setup-siteSelect option 1) Create new configuration, then enter:
β’ Project type (Laravel / WordPress / Symfony / HTML / Node.js) β’ Project folder path (absolute path)
- For HTML projects: Additional question about SPA (React/Vue/Angular) or static HTML
β’ Local domain (example:
project.local) β’ Is this a local project (y/n) β’ Add SSL support (y/n)
The script will:
β’ Create Nginx configuration file in /usr/local/etc/nginx/servers/
β’ Create SSL certificates in ~/.local/ssl-certs/$domain/ (for local projects)
β’ Automatically reload Nginx
# Run the setup-site script
setup-siteSelect option 2) Remove existing configuration, then enter:
β’ Domain of the project to remove (example: project.local)
The script will:
β’ Remove Nginx configuration file for that domain
β’ Remove SSL certificates (if any) by reading paths from Nginx config
β’ Remove domain entry from /etc/hosts
β’ Reload Nginx
| File Type | Location |
|---|---|
| Nginx Configuration | /usr/local/etc/nginx/servers/ |
| SSL Certificates (Local) | ~/.local/ssl-certs/$domain/ |
| SSL Certificates (Production) | /etc/letsencrypt/live/$domain/ |
For local development, SSL certificates are organized as follows:
~/.local/ssl-certs/
βββ myapp.local/
β βββ myapp.local.pem
β βββ myapp.local-key.pem
βββ wpstore.local/
β βββ wpstore.local.pem
β βββ wpstore.local-key.pem
βββ api.local/
βββ api.local.pem
βββ api.local-key.pem
If the
serversdirectory doesn't exist, the script will automatically create it.
For Laravel, WordPress, and Symfony projects, the script automatically detects available PHP versions and lets you choose:
-
Scans for PHP versions in system paths:
- macOS:
/usr/local/bin/php*and/opt/homebrew/bin/php* - Linux:
/usr/bin/php*
- macOS:
-
Checks PHP-FMP availability for each version:
- macOS: Looks for sockets in
/usr/local/var/run/or running processes - Linux: Checks systemd services (
php8.1-fpm,php8.2-fpm, etc.)
- macOS: Looks for sockets in
-
Presents available options to user:
π Choose PHP version to use: 1) PHP 8.1 2) PHP 8.2 (default) 3) PHP 8.3
The script automatically configures the appropriate PHP-FPM endpoint:
| OS | PHP Version | Preferred Method | Fallback |
|---|---|---|---|
| macOS | 8.1 | unix:/usr/local/var/run/php-fpm-8.1.sock |
127.0.0.1:9081 |
| macOS | 8.2 | unix:/usr/local/var/run/php-fpm-8.2.sock |
127.0.0.1:9082 |
| Linux | 8.1 | unix:/run/php/php8.1-fpm.sock |
127.0.0.1:9081 |
| Linux | 8.2 | unix:/run/php/php8.2-fpm.sock |
127.0.0.1:9082 |
- β No more hardcoded PHP-FPM ports
- β Automatic version detection
- β Cross-platform compatibility
- β Socket prioritization for better performance
- β Fallback to ports if sockets unavailable
- β SPA support with proper routing (for React, Vue, Angular)
- β Static HTML optimization with caching and gzip
The script now supports static HTML and Single Page Application (SPA) projects with optimized Nginx configurations.
- Static HTML: Traditional multi-page websites
- SPA (Single Page Applications): React, Vue, Angular applications
- Standard file serving with
try_files $uri $uri/ =404 - Returns 404 for non-existent files
- Optimized for traditional multi-page websites
- Automatic fallback to
index.htmlfor all routes - Enables client-side routing (React Router, Vue Router, Angular Router)
- Configuration:
try_files $uri $uri/ /index.html
Both HTML and SPA configurations include:
-
Gzip Compression: Reduces file sizes for faster loading
gzip on; gzip_types text/plain text/css text/xml text/javascript application/javascript application/json;
-
Static Asset Caching: 1-year cache for images, fonts, and styles
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; }
-
Security Headers: Protection against common vulnerabilities
add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always;
setup-site
# Choose: 4) HTML
# Enter project path: /Users/john/Projects/my-react-app
# Enter domain: myapp.local
# Is this a SPA (React/Vue/Angular)? y β Important for client-side routing
# Local project? y
# Add SSL? yFull support for Symfony projects with proper directory structure and PHP-FPM integration.
Symfony projects use the web/ directory as document root:
/path/to/symfony-project/
βββ app/
βββ src/
βββ web/ β Document Root
β βββ index.php
β βββ app.php
βββ vendor/
βββ composer.json
The script automatically:
- Sets document root to
{project_path}/web - Configures PHP-FPM with selected PHP version
- Sets up proper routing for Symfony controllers
- Enables
.htaccessprotection
Like Laravel and WordPress, Symfony projects benefit from:
- Automatic PHP version detection
- Interactive PHP version selection
- Smart PHP-FPM socket/port configuration
- Multi-version PHP support (7.4, 8.0, 8.1, 8.2, 8.3+)
setup-site
# Choose: 3) Symfony
# Enter project path: /Users/john/Projects/symfony-blog
# Choose PHP version: 2) PHP 8.2
# Enter domain: symfony.local
# Local project? y
# Add SSL? yserver {
listen 443 ssl;
server_name symfony.local;
root /Users/john/Projects/symfony-blog/web;
index index.php index.html;
ssl_certificate ~/.local/ssl-certs/symfony.local/symfony.local.pem;
ssl_certificate_key ~/.local/ssl-certs/symfony.local/symfony.local-key.pem;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/usr/local/var/run/php-fpm-8.2.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
include fastcgi.conf;
}
location ~ /\.ht {
deny all;
}
}β’ Run the script with a user that has access to Nginx directories.
β’ If nginx -t fails, ensure SSL paths and project folders are correct.
β’ For Symfony projects: The script uses web/ as document root (Symfony 2/3). If using Symfony 4+, manually edit the config to use public/ instead.
β’ For SPA projects: Make sure to answer 'y' when asked "Is this a SPA?" to enable proper client-side routing.
β’ For static HTML: Answer 'n' to SPA question if you have traditional multi-page website.
β’ For Firefox, run:
# Install mkcert for Firefox to trust local certificates
mkcert -installto trust local certificates.
| Problem | Solution |
|---|---|
| Permission denied when creating SSL | Ensure you have write access to ~/.local/ssl-certs/ |
| Nginx fails to reload | Check nginx -t to ensure no configuration errors |
| Domain not recognized | Add domain to /etc/hosts, example: 127.0.0.1 myapp.local |
| Firefox doesn't recognize local SSL | Run mkcert -install again |
| SSL certificates not found during removal | Script reads paths from Nginx config, ensure config file exists |
| No PHP versions detected | Install PHP: brew install php (macOS) or sudo apt install php-fpm (Linux) |
| PHP-FPM not running | Start service: brew services start php (macOS) or sudo systemctl start php8.2-fpm (Linux) |
| Socket connection failed | Check if PHP-FPM socket exists or use port fallback |
| SPA routing not working | Ensure you answered 'y' when asked "Is this a SPA?" during setup |
| Static assets not cached | Check nginx config has proper location ~* block for static files |
| Symfony 404 errors | Verify project uses web/ directory (older Symfony) or public/ directory (Symfony 4+) |
| Domain | Project Type | Project Path |
|---|---|---|
laravel.test |
Laravel | /Users/john/Projects/laravel-app |
wpstore.local |
WordPress | /Users/john/Projects/wordpress |
symfony.local |
Symfony | /Users/john/Projects/symfony-app |
myapp.local |
HTML/SPA | /Users/john/Projects/react-app |
nodeapi.local |
Node.js | Port 3000 |
- β Multi-OS Support: Automatic detection and support for macOS and Linux
- β Smart Path Detection: Uses appropriate Nginx paths for each OS
- β Linux Symlink Management: Automatic symlink creation/deletion for sites-available/sites-enabled
- β Cross-Platform Commands: Compatible sed commands for both macOS and Linux
- β Directory Auto-Creation: Creates necessary Nginx directories if they don't exist
- β
Organized SSL Storage: SSL certificates now stored in
~/.local/ssl-certs/$domain/ - β Fixed Node.js SSL Bug: Node.js projects can now use SSL without project path dependency
- β Smart Certificate Removal: Reads actual certificate paths from Nginx config for safe removal
- β Auto Directory Creation: Automatically creates SSL certificate directories
- β Clean Directory Management: Removes empty directories after certificate deletion
- β Dynamic PHP Detection: Automatically detects available PHP versions and lets you choose
- β Smart PHP-FPM Configuration: Uses appropriate socket/port based on PHP version and OS
- β Multi-Version PHP Support: Supports multiple PHP versions (7.4, 8.0, 8.1, 8.2, 8.3+)
- β Symfony Support: Full support for Symfony framework with proper web directory configuration
- β HTML/SPA Support: Optimized configurations for static HTML and Single Page Applications
- β SPA Routing: Automatic fallback to index.html for React, Vue, and Angular applications
- β Static Asset Optimization: Cache headers and gzip compression for HTML projects
This project is licensed under the MIT License - see the LICENSE file for details.
- β Commercial use allowed
- β Modification allowed
- β Distribution allowed
- β Private use allowed
- β No warranty provided
- β No liability assumed
Made with β€οΈ by Afif Saja