Production-Grade Virtual Host Manager for Apache & Nginx on Ubuntu/Debian
Bash scripts to safely create and manage Apache/Nginx virtual hosts on Ubuntu/Debian servers with professional features like SSL/HTTPS, Let's Encrypt, logging, dry-run mode, validation, JSON output, and comprehensive documentation.
- β Create Virtual Hosts β Automated setup with best practices
- β Delete Virtual Hosts β Safe removal with backup options
- β List All Hosts β View all active virtual hosts
- β DNS Management β Automatic /etc/hosts entries
- β Domain Validation β Strict input validation
- β Permission Management β Proper ownership and permissions
- β Test Files β Auto-generated phpinfo.php and index.html
- π SSL/HTTPS Support β Let's Encrypt (
-l) and self-signed (--self-signed) certificates - π HTTPβHTTPS Redirect β Force all traffic to HTTPS with
--force-https - π www Alias β Create ServerAlias with www. prefix via
--with-www - β‘ Non-Interactive Mode β Skip prompts with
--forceflag - π JSON Output β Machine-readable output for
list --json - π¨ Colored Output β Color-coded messages (disable with
--no-color) - π§© Shared Library β DRY codebase with
lib/virtualhost-lib.sh - π PHP-FPM Auto-Detection (Nginx) β Automatically detects installed PHP versions
- π« Skip Options β
--no-indexand--no-hostsfor fine-grained control
- π Security Hardened β Deny hidden files, proper permissions, SSL security headers
- π Comprehensive Logging β All operations logged to
/var/log/virtualhost/ - π Verbose Mode β Detailed output with
-vflag - π― Dry-Run Mode β Preview changes with
-dflag without executing - πΎ Backups β Automatic backups of modified system files
- β‘ Performance β Gzip compression, caching headers, static file optimization
- π Error Handling β Graceful error messages and recovery
- π Help System β Full
--helpand--versioncommands
mod_rewriteenabled by default- Framework-ready configuration (Laravel, WordPress, Drupal)
- Gzip compression enabled
- Deny access to hidden files
- Error/Access logging per domain
- SSL virtual host with HSTS and security headers
- PHP-FPM socket support (TCP & Unix)
- Auto-detection of installed PHP-FPM versions
- Static file caching with 30-day expiry
- Security hardening (deny hidden files)
- Fastcgi parameters optimization
- Per-domain error/access logging
- SSL server block with HTTP/2 support
- π Reverse Proxy β Proxy pass to any backend server (Node.js, React, Next.js, Vue, etc.)
- π WebSocket Support β WebSocket proxy with
--proxy-websocketflag - π Framework Ready β Works with Express, Next.js, Nuxt, React dev server, Vite, and more
- β‘ Performance Optimized β Proper proxy buffers, timeouts, and header forwarding
- π SSL with Proxy β Full SSL/HTTPS support for proxied backends
- π§© Backend Health Check β Validates backend is reachable before creating config
- π Auto Module Detection β Warns if required proxy modules are missing (Apache)
- Ubuntu 18.04+ or Debian 9+
- Apache 2.4+ or Nginx 1.14+
- PHP 7.0+ (optional, for phpinfo test)
- Sudo access (root privileges)
- Bash 4.0+
- OpenSSL (for self-signed certificates)
- Certbot (optional, for Let's Encrypt)
sudo apt-get install apache2 apache2-utils php libapache2-mod-php
sudo a2enmod rewrite ssl headerssudo apt-get install nginx php-fpmgit clone https://github.com/shuvo-halder/virtualhost-automation.git
cd virtualhost-automation
chmod +x bin/virtualhost.sh bin/virtualhost-nginx.sh lib/virtualhost-lib.sh
# Optional: Link to PATH
sudo ln -s $(pwd)/bin/virtualhost.sh /usr/local/bin/virtualhost
sudo ln -s $(pwd)/bin/virtualhost-nginx.sh /usr/local/bin/virtualhost-nginx# Download and install both scripts globally
cd /usr/local/bin
# Apache
sudo wget https://raw.githubusercontent.com/shuvo-halder/virtualhost-automation/master/bin/virtualhost.sh
sudo chmod +x virtualhost.sh
sudo ln -s virtualhost.sh virtualhost
# Nginx
sudo wget https://raw.githubusercontent.com/shuvo-halder/virtualhost-automation/master/bin/virtualhost-nginx.sh
sudo chmod +x virtualhost-nginx.sh
sudo ln -s virtualhost-nginx.sh virtualhost-nginx
# Shared library
sudo mkdir -p /usr/local/lib
sudo wget -O /usr/local/lib/virtualhost-lib.sh https://raw.githubusercontent.com/shuvo-halder/virtualhost-automation/master/lib/virtualhost-lib.sh- Download
bin/virtualhost.shorbin/virtualhost-nginx.shandlib/virtualhost-lib.sh - Make executable:
chmod +x /path/to/script.sh - Run with:
sudo /path/to/script.sh [options] command domain
# Create virtual host
sudo virtualhost create example.dev
# Create with custom directory
sudo virtualhost create example.dev /var/www/mysite
# Create with Let's Encrypt SSL
sudo virtualhost -l create example.dev
# Delete virtual host
sudo virtualhost delete example.dev
# List all hosts
sudo virtualhost list
# Get help
sudo virtualhost --help# Create virtual host
sudo virtualhost-nginx create example.dev
# Create with custom directory
sudo virtualhost-nginx create example.dev /var/www/mysite
# Create with Let's Encrypt SSL
sudo virtualhost-nginx -l create example.dev
# Delete virtual host
sudo virtualhost-nginx delete example.dev
# List all hosts
sudo virtualhost-nginx list
# Get help
sudo virtualhost-nginx --helpsudo virtualhost [OPTIONS] COMMAND DOMAIN [ROOTDIR]
sudo virtualhost-nginx [OPTIONS] COMMAND DOMAIN [ROOTDIR]sudo virtualhost create example.dev
sudo virtualhost create example.dev /var/www/custom_dirWhat it does:
- Creates web root directory with proper permissions
- Generates Apache/Nginx configuration
- Enables the site
- Adds entry to /etc/hosts
- Creates phpinfo.php and index.html test files
- Reloads web server
- Logs all operations
sudo virtualhost delete example.devWhat it does:
- Disables the site
- Removes configuration
- Removes /etc/hosts entry (with backup)
- Prompts to delete web root (or auto-deletes with
--force) - Reloads web server
- Logs all operations
sudo virtualhost list
sudo virtualhost-nginx list --jsonShows all enabled virtual hosts with their paths. Use --json for machine-readable output.
sudo virtualhost --help
sudo virtualhost-nginx --helpShows comprehensive help and usage examples.
sudo virtualhost --version
sudo virtualhost-nginx --versionDisplays script version information.
| Option | Description | Example |
|---|---|---|
-h, --help |
Show help message | sudo virtualhost -h |
-V, --version |
Show version info | sudo virtualhost --version |
-v, --verbose |
Enable verbose output | sudo virtualhost -v create example.dev |
-d, --dry-run |
Preview without changes | sudo virtualhost -d create example.dev |
-s, --skip-reload |
Skip web server reload | sudo virtualhost -s create example.dev |
-e, --email (Apache) |
Set admin email | sudo virtualhost -e admin@example.com create example.dev |
-p, --php-socket (Nginx) |
PHP-FPM socket | sudo virtualhost-nginx -p unix:/run/php/php8.1-fpm.sock create example.dev |
-l, --letsencrypt |
Obtain Let's Encrypt SSL | sudo virtualhost -l create example.dev |
--self-signed |
Generate self-signed SSL | sudo virtualhost --self-signed create example.dev |
--force-https |
Redirect HTTP to HTTPS | sudo virtualhost --force-https create example.dev |
--with-www |
Add www. ServerAlias | sudo virtualhost --with-www create example.dev |
--force |
Non-interactive mode | sudo virtualhost --force delete example.dev |
--no-index |
Skip test files | sudo virtualhost --no-index create example.dev |
--no-hosts |
Skip /etc/hosts edit | sudo virtualhost --no-hosts create example.dev |
--json |
JSON output format | sudo virtualhost list --json |
--no-color |
Disable colored output | sudo virtualhost --no-color create example.dev |
# Create with Let's Encrypt SSL certificate
sudo virtualhost -l create example.dev
sudo virtualhost-nginx -l create example.dev# Create with self-signed SSL certificate
sudo virtualhost --self-signed create example.dev# Create with SSL and force HTTPS
sudo virtualhost --self-signed --force-https create example.devTest what would happen without making actual changes:
sudo virtualhost -d create example.devOutput shows all planned operations but doesn't modify anything.
See detailed step-by-step execution:
sudo virtualhost -v create example.devShows detailed logs of each operation.
Skip all confirmation prompts:
sudo virtualhost --force delete example.devMachine-readable output for automation:
sudo virtualhost list --json
# {"status":"success","message":"Virtual hosts listed","data":[{"domain":"example.dev","type":"apache"}]}Use Unix socket instead of TCP:
# TCP socket (default)
sudo virtualhost-nginx create example.dev
# Unix socket
sudo virtualhost-nginx -p unix:/run/php/php8.1-fpm.sock create example.devSet server admin email:
sudo virtualhost -e webmaster@company.com create example.devProxy pass to any backend server running on your machine:
# Node.js / Express app running on port 3000
sudo virtualhost --proxy-pass http://localhost:3000 create myapp.dev
# React / Vite dev server running on port 5173
sudo virtualhost-nginx --proxy-pass http://localhost:5173 create reactapp.dev
# Next.js app running on port 3000
sudo virtualhost --proxy-pass http://localhost:3000 create nextapp.dev
# Vue / Nuxt app with WebSocket support (HMR)
sudo virtualhost-nginx --proxy-pass http://localhost:3000 --proxy-websocket create nuxtapp.devWhat it does:
- Creates a reverse proxy configuration instead of a document root
- All requests to
myapp.devare forwarded to your backend server - Properly forwards real IP, host, and protocol headers
- Skips test file creation (phpinfo.php, index.html)
- Works with SSL/HTTPS when combined with
--self-signedor-l
# Node.js app with self-signed SSL
sudo virtualhost --self-signed --proxy-pass http://localhost:3000 create myapp.dev
# Node.js app with Let's Encrypt SSL
sudo virtualhost -l --proxy-pass http://localhost:3000 create myapp.dev
# With HTTPS redirect
sudo virtualhost --self-signed --force-https --proxy-pass http://localhost:3000 create myapp.devFor apps that need WebSocket connections (Nuxt, Socket.io, Laravel Echo, etc.):
# Apache
sudo virtualhost --proxy-pass http://localhost:3000 --proxy-websocket create myapp.dev
# Nginx
sudo virtualhost-nginx --proxy-pass http://localhost:3000 --proxy-websocket create myapp.devCreate multiple hosts without reloading:
sudo virtualhost -s create site1.dev
sudo virtualhost -s create site2.dev
sudo virtualhost -s create site3.dev
sudo systemctl reload apache2 # One reload at the endApache sites-available: /etc/apache2/sites-available/
Apache sites-enabled: /etc/apache2/sites-enabled/
Nginx sites-available: /etc/nginx/sites-available/
Nginx sites-enabled: /etc/nginx/sites-enabled/
Web root: /var/www/
Logs: /var/log/virtualhost/
SSL certificates: /etc/letsencrypt/live/ (Let's Encrypt)
/etc/ssl/ (self-signed)
All operations are logged to: /var/log/virtualhost/virtualhost-*.log
View logs:
tail -f /var/log/virtualhost/virtualhost-*.log# Set custom log directory
export LOG_DIR="/custom/log/path"
sudo virtualhost create example.dev
# Set custom admin email (Apache)
export EMAIL="admin@example.com"
sudo virtualhost create example.dev
# Set custom PHP-FPM socket (Nginx)
export PHP_FPM_SOCKET="unix:/run/php/php8.1-fpm.sock"
sudo virtualhost-nginx create example.devEach virtual host gets:
- ServerAdmin email
- ServerName and optional www alias
- DocumentRoot configuration
- mod_rewrite enabled for frameworks
- Gzip compression
- Error/Access logging
- Security headers for hidden files
- SSL virtual host (if enabled) with HSTS, X-Content-Type-Options, X-Frame-Options
Each virtual host gets:
- Server name configuration with optional www
- PHP-FPM fastcgi configuration (auto-detected)
- Static file caching (30 days)
- Security hardening
- Per-domain logging
- Framework-ready rewrites
- SSL server block (if enabled) with HTTP/2, TLSv1.2/TLSv1.3
sudo virtualhost create mysite.dev
# Creates: /var/www/mysite/
# Visit: http://mysite.devsudo virtualhost --self-signed --force-https create mysite.dev
# Creates: /var/www/mysite/
# Visit: https://mysite.dev (auto-redirects from HTTP)sudo virtualhost create api.example.dev /var/www/projects/api
# Creates: /var/www/projects/api/
# Visit: http://api.example.dev# Create multiple dev sites
sudo virtualhost -s create project1.dev
sudo virtualhost -s create project2.dev
sudo virtualhost -s create project3.dev
sudo systemctl reload apache2# Preview without making changes
sudo virtualhost -d create example.dev
# Dry-run with verbose output
sudo virtualhost -dv create example.devSolution: Always prefix commands with sudo
sudo virtualhost create example.devSolution: Double-check the domain name or create it first
sudo virtualhost create example.dev # Create first
sudo virtualhost delete example.dev # Then deleteSolution: Check web server configuration syntax
# Apache
apache2ctl configtest
# Nginx
nginx -tSolution: Verify /etc/hosts entry
grep example.dev /etc/hosts
# Should see: 127.0.0.1 example.devSolution: Check directory ownership
ls -la /var/www/example/
# Should be owned by your user or www-dataSolution: Check PHP-FPM is running and properly configured
# Nginx
sudo systemctl status php-fpm
# or
sudo systemctl status php8.1-fpm
# Apache
apache2ctl -t # Test configurationSolution: Check what's using port 80
sudo lsof -i :80
# Kill the process or use different portSolution: Ensure port 80 is accessible from the internet
# For local development, use --self-signed instead
sudo virtualhost --self-signed create example.dev# View today's logs
tail -f /var/log/virtualhost/virtualhost-apache-*.log
tail -f /var/log/virtualhost/virtualhost-nginx-*.log
# View all logs
ls -la /var/log/virtualhost/# Apache
tail -f /var/log/apache2/example.dev_error.log
tail -f /var/log/apache2/example.dev_access.log
# Nginx
tail -f /var/log/nginx/example.dev_error.log
tail -f /var/log/nginx/example.dev_access.log# Create
sudo virtualhost create testsite.dev
# Verify /etc/hosts entry
grep testsite.dev /etc/hosts
# Verify site enabled
ls -l /etc/apache2/sites-enabled/ | grep testsite
# Verify directory
ls -la /var/www/testsite/
# Check in browser
curl http://testsite.dev
# View logs
tail -f /var/log/virtualhost/*.log- Scripts require sudo (root privileges)
- Domain validation prevents invalid characters
- Permissions set to 755 for directories, 644 for files
- Backups created for /etc/hosts modifications
- Hidden files denied access in Apache/Nginx
- Proper user/group ownership enforced
- No SQL injection or command injection possible
- SSL configurations include HSTS, X-Content-Type-Options, X-Frame-Options
- Self-signed certificates use 2048-bit RSA keys
- HTTPS configurations use TLSv1.2 and TLSv1.3 only
# Run Apache tests
bash tests/test-virtualhost.sh
# Run Nginx tests
bash tests/test-virtualhost-nginx.shFound a bug? Have a feature request? Contributions welcome!
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
For issues, questions, or suggestions:
- Open an GitHub Issue
- Check Troubleshooting Section
- Review Examples
- β¨ SSL/HTTPS support (Let's Encrypt & self-signed)
- β¨ HTTPβHTTPS redirect (
--force-https) - β¨ www alias support (
--with-www) - β¨ Non-interactive mode (
--force) - β¨ JSON output for
listcommand - β¨ Colored output with
--no-coloroption - β¨ PHP-FPM auto-detection (Nginx)
- β¨ Shared library (
lib/virtualhost-lib.sh) - β¨ Skip options (
--no-index,--no-hosts) - β¨ GitHub Actions CI workflow
- β¨ Test suite for both Apache and Nginx
- β¨ CHANGELOG.md for version tracking
- π§ Fixed Apache ownership bug (owner:group)
- π Complete documentation overhaul
- β¨ Added comprehensive help system (
--help,--version) - β¨ Added dry-run mode (
-d) for safe testing - β¨ Added verbose logging (
-v) for debugging - β¨ Added centralized logging system
- β¨ Added domain validation and error handling
- β¨ Added list command to show all virtual hosts
- β¨ Added skip-reload option for batch operations
- β¨ Added custom PHP-FPM socket support (Nginx)
- β¨ Added custom admin email support (Apache)
- π Complete documentation overhaul
- π Enhanced security features
- β‘ Performance improvements
- Initial release
- Basic create/delete functionality
- Apache and Nginx support
Shuvo Halder - GitHub
Made with β€οΈ for Linux Developers & System Administrators