Setup Nginx as reverse proxy for Apache with Virtualmin support
We know that Nginx is more faster than Apache and most of us prefer to replace Apache with Nginx as their web server.
Nginx is known to serve faster static content and run with less RAM. As of this writing, Virtualmin supports Apache as its web server.
To take advantage of Nginx, we will install it as reverse proxy for Apache and continue using Virtualmin to manage your domains. Nginx configurations for virtual host are tailored for Drupal site and microcache is used here.
The following procedures are tested on my Linode server running Centos 7 64-bit Linux distribution.
Install Nginx
If you need to install Nginx with Pagespeed module please follow the steps here instead and jump to configure Nginx section.
In able to install the latest Nginx server we will need to register Nginx repository:
vi /etc/yum.repos.d/nginx.repo
Have the following codes as its content:
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=0
priority=1
enabled=0
Note: if just in case the nginx does not install try to hard code the $releasever with value of 7
Install Nginx using yum:
yum –enablerepo=nginx -y install nginx
Make Nginx auto-start upon reboot:
chkconfig nginx on
Configure Nginx
Edit the main Nginx file “/etc/nginx/nginx.conf” to match the following:
user nginx;
# This number should be, at maximum, the number of CPU cores on your system.
# (since nginx doesn’t benefit from more than one worker per CPU.)
worker_processes auto;
error_log /var/log/nginx/error.log error;
pid /var/run/nginx.pid;
# Number of file descriptors used for Nginx. This is set in the OS with ‘ulimit -n 200000’
# or using /etc/security/limits.conf
worker_rlimit_nofile 200000;
events {
# Determines how many clients will be served by each worker process.
# (Max clients = worker_connections * worker_processes)
worker_connections 1024;
# Accept as many connections as possible,
# after nginx gets notification about a new connection.
# May flood worker_connections, if that option is set too low.
multi_accept on;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main ‘$remote_addr – $remote_user [$time_local] “$request” ‘
‘$status $body_bytes_sent “$http_referer” ‘
‘”$http_user_agent” “$http_x_forwarded_for”‘;
## Use sendfile() syscall to speed up I/O operations and speed up
## static file serving.
# Sendfile copies data between one FD and other from within the kernel.
# More efficient than read() + write(), since the requires transferring
# data to and from the user space.
sendfile on;
## Handling of IPs in proxied and load balancing situations.
set_real_ip_from 0.0.0.0/32; # all addresses get a real IP.
real_ip_header X-Forwarded-For; # the ip is forwarded from the load balancer/proxy
## If you are using CloudFlare, uncomment the lines below
## CloudFlare IPs https://www.cloudflare.com/ips
#set_real_ip_from 199.27.128.0/21;
#set_real_ip_from 173.245.48.0/20;
#set_real_ip_from 103.21.244.0/22;
#set_real_ip_from 103.22.200.0/22;
#set_real_ip_from 103.31.4.0/22;
#set_real_ip_from 141.101.64.0/18;
#set_real_ip_from 108.162.192.0/18;
#set_real_ip_from 190.93.240.0/20;
#set_real_ip_from 188.114.96.0/20;
#set_real_ip_from 197.234.240.0/22;
#set_real_ip_from 198.41.128.0/17;
#set_real_ip_from 162.158.0.0/15;
#set_real_ip_from 104.16.0.0/12;
#set_real_ip_from 172.64.0.0/13;
#set_real_ip_from 2400:cb00::/32;
#set_real_ip_from 2606:4700::/32;
#set_real_ip_from 2803:f800::/32;
#set_real_ip_from 2405:b500::/32;
#set_real_ip_from 2405:8100::/32;
#real_ip_header CF-Connecting-IP;
## Timeouts.
client_body_timeout 60;
client_header_timeout 60;
# Timeout for keep-alive connections. Server will close connections after this time.
keepalive_timeout 10 10;
send_timeout 60;
## Reset lingering timed out connections. Deflect DDoS.
reset_timedout_connection on;
## Body size.
client_max_body_size 10m;
## TCP options.
# don’t buffer data-sends (disable Nagle algorithm).
# Good for sending frequent small bursts of data in real time.
tcp_nodelay on;
## Optimization of socket handling when using sendfile.
# Tcp_nopush causes nginx to attempt to send its HTTP response head in one packet,
# instead of using partial frames. This is useful for prepending headers
# before calling sendfile, or for throughput optimization.
tcp_nopush on;
## Compression.
# Reduces the amount of data that needs to be transferred over the network
gzip on;
gzip_buffers 16 8k;
gzip_comp_level 1;
gzip_http_version 1.1;
gzip_min_length 10;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/x-icon application/vnd.ms-fontobject font/opentype application/x-javascript application/x-font-ttf text/x-js;
gzip_vary on;
gzip_proxied any; # Compression for all requests.
gzip_disable “MSIE [1-6]\.(?!.*SV1)”;
## Hide the Nginx version number.
server_tokens off;
## Use a SSL/TLS cache for SSL session resume. This needs to be
## here (in this context, for session resumption to work. See this
## thread on the Nginx mailing list:
## http://nginx.org/pipermail/nginx/2010-November/023736.html.
ssl_session_cache shared:SSL:30m;
ssl_session_timeout 1d;
## The server dictates the choice of cipher suites.
ssl_prefer_server_ciphers on;
## No SSL2 support.
## No SSLv3 support (SSLv3 POODLE Vulnerability)
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
## Pregenerated Diffie-Hellman parameters.
ssl_dhparam /etc/nginx/dh_param.pem;
## Curve to use for ECDH.
ssl_ecdh_curve secp521r1;
## Enable OCSP stapling. A better way to revocate server certificates.
ssl_stapling on;
## Enable verification of OCSP stapling responses by the server.
ssl_stapling_verify on;
## Use Google’s DNS
resolver 8.8.4.4 8.8.8.8;
## Enable the builtin cross-site scripting (XSS) filter available
## in modern browsers. Usually enabled by default we just
## reinstate in case it has been somehow disabled for this
## particular server instance.
## https://www.owasp.org/index.php/List_of_useful_HTTP_headers.
add_header X-XSS-Protection ‘1; mode=block’;
## Enable this if using HTTPS
#add_header Strict-Transport-Security “max-age=7200″;
## Block MIME type sniffing on IE.
add_header X-Content-Options nosniff;
## Add a cache miss/hit status header
add_header X-Micro-Cache $upstream_cache_status;
## Block HTTP methods.
map $request_method $not_allowed_method {
default 1;
GET 0;
HEAD 0;
POST 0;
}
## Add as many servers as needed.
## Cf. http://wiki.nginx.org/HttpUpstreamModule.
## Note that this configuration assumes by default that keepalive
## upstream connections are supported and that you have a Nginx
## version with the fair load balancer.
upstream phpapache {
## Use the least connection algorithm for load balancing
least_conn;
server 127.0.0.1:8000;
keepalive 5;
}
## Configuration for reverse proxy. Passing the necessary headers to
## the backend. Nginx doesn’t tunnel the connection, it opens a new
## one. Hence whe need to send these headers to the backend so that
## the client(s) IP is available to them. The host is also sent.
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
## Hide the Drupal headers
proxy_hide_header ‘X-Drupal-Cache’;
proxy_hide_header ‘X-Generator’;
## Include blacklist for bad bot and referer blocking.
include blacklist.conf;
## Include the caching setup. Needed for using Drupal with an external cache.
include apps/drupal/drupal_map.conf;
## Defining the proxy cache zone for the microcache as presented at:
## http://fennb.com/microcaching-speed-your-app-up-250x-with-no-n.
proxy_cache_path /var/cache/nginx/microcache levels=1:2 keys_zone=microcache:5M max_size=1G loader_threshold=2592000000 loader_sleep=1 loader_files=100000;
## To build optimal server_names_hash
server_names_hash_bucket_size 72;
## Include all vhosts.
include /etc/nginx/sites-enabled/*;
}
Create the file /etc/nginx/dh_param.pem and add the following to it:
—–BEGIN DH PARAMETERS—–
MIIBCAKCAQEAkD39jm2I+Sr1j1+YPB5TbgUvIWUv3Gzj1s1rtpuZJUhCQ8MElafR
XrjrNXtgN8yjX6J5+Nuj0G9SytrvtKU9T3pLDVjZiV2l0m+/pvzaW3qCSlegpA/S
bkIQPg4n7CP/dhs7JcQD0Ny6TX9iYioDz5/kGfrBHTfAW8A6gPinAiC/+8Osz6mP
UghuQPkFVxJmleIdGU7ll3tAKARJpe8HyHNMNoRGbWTCH1mc8Z/la0E7xjs5R2mh
rYxofg/TMFJyvnnjtTLRQ9edvdA+K9JNsF23t8qvY78ppHNEP7u1PA7ORtePagJk
vcSF5yMYeDzUQLWpOuK5B0yHtltZzANH6wIBAg==
—–END DH PARAMETERS—–
Create the file /etc/nginx/blacklist.conf and add the following to it:
## Add here all user agents that are to be blocked.
map $http_user_agent $bad_bot {
default 0;
~*^Lynx 0; # Let Lynx go through
libwww-perl 1;
~(?i)(httrack|htmlparser|libwww) 1;
}
## Add here all referrers that are to blocked.
map $http_referer $bad_referer {
default 0;
~(?i)(adult|babes|click|diamond|forsale|girl|jewelry|love|nudit|organic|poker|porn|poweroversoftware|sex|teen|webcam|zippo|casino|replica) 1;
}
## Add here all hosts that should be spared any referrer checking.
geo $bad_referer {
127.0.0.1 0;
192.168.1.0/24 0;
}
Create the file /etc/nginx/drupal_map.conf and add the following to it:
## Let Ajax calls go through
map $uri $no_cache_ajax {
default 0;
/system/ajax 1;
}
## Check session cookie being present
map $http_cookie $no_cache_cookie {
default 0;
~SESS 1; # PHP session cookie
}
## Combine both results to get the cache bypassing mapping
map $no_cache_ajax$no_cache_cookie $no_cache {
default 1;
00 0;
}
## Cache bypassing mapping (auth).
map $no_cache_ajax $no_auth_cache {
default 0;
1 1;
}
## Set a cache_uid variable for authenticated users.
map $http_cookie $cache_uid {
default nil;
~SESS[[:alnum:]]+=(?[[:graph:]]+) $session_id;
}
Create the file /etc/nginx/drupal.conf and add the following to it:
location / {
## Let Drupal handle 404
error_page 404 /index.php;
## Regular private file serving (i.e. handled by Drupal).
location ^~ /system/files/ {
proxy_pass http://phpapache;
proxy_http_version 1.1; # keep alive to the Apache upstream
proxy_set_header Connection ”;
## Rewrite the ‘Host’ header to the value in the client request,
## or primary server name
proxy_set_header Host $host;
## For not signaling a 404 in the error log whenever the
## system/files directory is accessed add the line below.
## Note that the 404 is the intended behavior.
log_not_found off;
}
## Trying to access private files directly returns a 404.
location ^~ /sites/[\.\-[:alnum:]]+/files/private/ {
internal;
}
## Support for the file_force module
## http://drupal.org/project/file_force.
location ^~ /system/files_force/ {
proxy_pass http://phpapache;
proxy_http_version 1.1; # keep alive to the Apache upstream
proxy_set_header Connection ”;
## Rewrite the ‘Host’ header to the value in the client request,
## or primary server name
proxy_set_header Host $host;
## For not signaling a 404 in the error log whenever the
## system/files directory is accessed add the line below.
## Note that the 404 is the intended behavior.
log_not_found off;
}
## If accessing an image generated by Drupal imagecache, serve it
## directly if available, if not relay the request to Drupal to (re)generate
## the image.
location ~* /imagecache/ {
## Image hotlinking protection. If you want hotlinking
## protection for your images uncomment the following line.
include hotlinking_protection.conf;
access_log off;
expires 30d;
try_files $uri $uri/ @drupal-noexp;
}
## Drupal generated image handling, i.e., imagecache in core. See:
## http://drupal.org/node/371374.
location ~* /files/styles/ {
## Image hotlinking protection. If you want hotlinking
## protection for your images uncomment the following line.
include hotlinking_protection.conf;
access_log off;
expires 30d;
try_files $uri $uri/ @drupal-noexp;
}
## Advanced Aggregation module CSS/JS
## support. http://drupal.org/project/advagg.
location ~ ^/sites/[\.\-[:alnum:]]+/files/advagg_(?:css|js)/ {
expires max;
gzip_static on;
add_header ETag ”;
add_header Accept-Ranges ”;
# Set a far future Cache-Control header to 52 weeks.
add_header Cache-Control ‘max-age=31449600, no-transform, public’;
location ~* (?:css|js)[_\-[:alnum:]]+\.(?:css|js)(\.gz)?$ {
access_log off;
try_files $uri $uri/ @drupal-noexp;
}
}
## All static files will be served directly.
location ~* ^.+\.(?:css|cur|js|jpe?g|gif|htc|ico|png|htm|html|xml|txt|otf|ttf|eot|woff|svg|webp|webm|zip|gz|tar|rar)$ {
access_log off;
expires 30d;
## No need to bleed constant updates. Send the all shebang in one
## fell swoop.
tcp_nodelay off;
## Set the OS file cache.
open_file_cache max=3000 inactive=120s;
open_file_cache_valid 45s;
open_file_cache_min_uses 2;
open_file_cache_errors off;
try_files $uri $uri/ @drupal-noexp;
}
## PDFs and powerpoint files handling.
location ~* ^.+\.(?:pdf|pptx?)$ {
access_log off;
expires 30d;
## No need to bleed constant updates. Send the all shebang in one
## fell swoop.
tcp_nodelay off;
try_files $uri $uri/ @drupal-noexp;
}
## MP3 and Ogg/Vorbis files are served using AIO when supported. Your OS must support it.
location ~ ^/sites/[\.\-[:alnum:]]+/files/audio/mp3 {
location ~* .*\.mp3$ {
access_log off;
directio 4k; # for XFS
## If you’re using ext3 or similar uncomment the line below and comment the above.
#directio 512; # for ext3 or similar (block alignments)
tcp_nopush off;
aio on;
output_buffers 1 2M;
try_files $uri $uri/ @drupal;
}
}
location ~ ^/sites/[\.\-[:alnum:]]+/files/audio/ogg {
location ~* .*\.ogg$ {
access_log off;
directio 4k; # for XFS
## If you’re using ext3 or similar uncomment the line below and comment the above.
#directio 512; # for ext3 or similar (block alignments)
tcp_nopush off;
aio on;
output_buffers 1 2M;
try_files $uri $uri/ @drupal;
}
}
## Pseudo streaming of FLV files:
## http://wiki.nginx.org/HttpFlvStreamModule.
## If pseudo streaming isn’t working, try to comment
## out in nginx.conf line with:
## add_header X-Frame-Options SAMEORIGIN;
location ~ ^/sites/[\.\-[:alnum:]]+/files/video/flv {
location ~* .*\.flv$ {
access_log off;
flv;
try_files $uri $uri/ @drupal;
}
}
## Pseudo streaming of H264/AAC files. This requires an Nginx
## version greater or equal to 1.0.7 for the stable branch and
## greater or equal to 1.1.3 for the development branch.
## Cf. http://nginx.org/en/docs/http/ngx_http_mp4_module.html.
location ~ ^/sites/[\.\-[:alnum:]]+/files/video/mp4 { # videos
location ~* .*\.(?:mp4|mov)$ {
access_log off;
mp4;
mp4_buffer_size 1M;
mp4_max_buffer_size 5M;
try_files $uri $uri/ @drupal;
}
}
location ~ ^/sites/[\.\-[:alnum:]]+/files/audio/m4a { # audios
location ~* .*\.m4a$ {
access_log off;
mp4;
mp4_buffer_size 1M;
mp4_max_buffer_size 5M;
try_files $uri $uri/ @drupal;
}
}
## Advanced Help module makes each module provided README available.
location ^~ /help/ {
location ~* ^/help/[^/]*/README\.txt$ {
access_log off;
proxy_pass http://phpapache;
proxy_http_version 1.1; # keep alive to the Apache upstream
proxy_set_header Connection ”;
## Rewrite the ‘Host’ header to the value in the client request,
## or primary server name
proxy_set_header Host $host;
}
}
## Replicate the Apache directive of Drupal standard
## .htaccess. Disable access to any code files. Return a 404 to curtail
## information disclosure. Hide also the text files.
location ~* ^(?:.+\.(?:htaccess|make|txt|engine|inc|info|install|module|profile|po|pot|sh|.*sql|test|theme|tpl(?:\.php)?|xtmpl)|code-style\.pl|/Entries.*|/Repository|/Root|/Tag|/Template)$ {
return 404;
}
## First we try the URI and relay to the upstream server if not found.
try_files $uri $uri/ @drupal;
}
## Restrict access to the strictly necessary PHP files. Reducing the
## scope for exploits. Handling of PHP code and the Drupal event loop.
location @drupal {
proxy_pass http://phpapache;
proxy_http_version 1.1; # keep alive to the Apache upstream
proxy_set_header Connection ”;
## Rewrite the ‘Host’ header to the value in the client request,
## or primary server name
proxy_set_header Host $host;
## Proxy microcache
include microcache_proxy.conf;
## The Cache-Control and Expires headers should be delivered untouched
## from the upstream to the client.
proxy_ignore_headers Cache-Control Expires;
## To avoid any interaction with the cache control headers we expire
## everything on this location immediately.
expires epoch;
}
## Restrict access to the strictly necessary PHP files. Reducing the
## scope for exploits. Handling of PHP code and the Drupal event loop.
location @drupal-noexp {
proxy_pass http://phpapache;
proxy_http_version 1.1; # keep alive to the Apache upstream
proxy_set_header Connection ”;
## Rewrite the ‘Host’ header to the value in the client request,
## or primary server name
proxy_set_header Host $host;
## Proxy microcache.
include microcache_proxy.conf;
}
## Disallow access to .bzr, .git, .hg, .svn, .cvs directories
## Return 404 as not to disclose information.
location ^~ /.bzr {
return 404;
}
location ^~ /.git {
return 404;
}
location ^~ /.hg {
return 404;
}
location ^~ /.svn {
return 404;
}
location ^~ /.cvs {
return 404;
}
## Disallow access to patches directory.
location ^~ /patches {
return 404;
}
## Disallow access to drush backup directory.
location ^~ /backup {
return 404;
}
## Disable access logs for robots.txt.
location = /robots.txt {
access_log off;
## Add support for the robotstxt module
## http://drupal.org/project/robotstxt.
try_files $uri $uri/ @drupal;
}
## RSS feed support.
location = /rss.xml {
try_files $uri $uri/ @drupal;
}
## XML Sitemap support.
location = /sitemap.xml {
try_files $uri $uri/ @drupal;
}
## Support for favicon.
## Return an 1×1 transparent GIF if it doesn’t exist.
location = /favicon.ico {
expires 30d;
try_files /favicon.ico @empty;
}
## Return an in memory 1×1 transparent GIF.
location @empty {
expires 30d;
empty_gif;
}
## Any other attempt to access PHP files returns a 404.
location ~* ^.+\.php$ {
return 404;
}
Create the file /etc/nginx/microcache_proxy.conf and add the following to it:
## The cache zone referenced.
proxy_cache microcache;
## The cache key.
proxy_cache_key $cache_uid@$scheme$host$request_uri;
## For 200 and 301 make the cache valid for 5 seconds.
proxy_cache_valid 200 301 5s;
## For 302 make it valid for 1 minute.
proxy_cache_valid 302 1m;
## For 404 make it valid 1 second.
proxy_cache_valid 404 1s;
## If there are any upstream errors or the item has expired use
## whatever it is available.
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504 off;
proxy_pass_header Set-Cookie;
proxy_pass_header Cookie;
## Bypass the cache.
proxy_cache_bypass $no_auth_cache;
proxy_no_cache $no_auth_cache;
## Add a cache miss/hit status header.
add_header X-Micro-Cache $upstream_cache_status;
## Block MIME type sniffing on IE.
add_header X-Content-Options nosniff;
## Cache locking mechanism for protecting the backendof too many
## simultaneous requests.
proxy_cache_lock on;
Create the file /etc/nginx/hotlinking_protection.conf and add the following to it:
## Hotlinking protection for images. Include it in any context you
## want. Adjust the list of allowed referers to your liking.
valid_referers none blocked
www.yahoo.com
www.google.com.ph
www.google.com;
if ($invalid_referer) {
return 200 “No hotlinking allowed\n”;
}
Create the folders /etc/nginx/sites-available and /etc/nginx/sites-enabled:
mkdir /etc/nginx/sites-available /etc/nginx/sites-enabled
chown nginx. /etc/nginx/sites-available /etc/nginx/sites-enabled
In /etc/nginx/sites-available contains the physical file Nginx configurations for your virtual hosts and to enable a virtual host Nginx configuration just create a soft link if this configuration file from /etc/nginx/sites-available to /etc/nginx/sites-enabled. This is easy and good approach to disable and enable a virtual host.
Restart Nginx:
systemctl restart nginx.service
Setup Nginx requirements
In this tutorial the Apache will use port 8000 and lets open this port to become accessible:
iptables -I INPUT -p tcp -m tcp –dport 8000 -j ACCEPT
iptables –line -vnL
service iptables save
service iptables restart
Create the Nginx cache path folder:
mkdir /var/cache/nginx/microcache
chown nginx:root /var/cache/nginx/microcache
chmod 700 /var/cache/nginx/microcache
Create Nginx logrotate script:
vi /etc/logrotate.d/websites_nginx_logs.conf
Content:
/var/log/virtualmin/*nginx_access_log /var/log/virtualmin/*nginx_error_log {
rotate 10
missingok
daily
compress
postrotate
service httpd graceful ; sleep 5
endscript
sharedscripts
}
Configure Apache
Since Nginx is reverse proxy to Apache, the IP address that Apache will get is the IP of the server and we need to correct that. Apache 2.4 and above do have mod_remoteip and we will use that module. Open mod_remoteip’s configuration file:
vi /etc/httpd/conf.d/remoteip.conf
Add the following codes:
# mod_remoteip settings
RemoteIPHeader X-Real-IP
RemoteIPInternalProxy 127.0.0.1
RemoteIPInternalProxy 188.8.8.8
Note: change 188.8.8.8 to your server’s IP address.
Change the port of Apache:
vi /etc/httpd/conf/httpd.conf
Look for:
Listen 80
… and change to:
Listen 8000
Restart Apache:
systemctl restart httpd.service
Configure Virtualmin
Set the virtual server template to listen to 8000. Login to Virtualmin, go to “System Settings” -> “Server Templates” -> “Default Settings” and select from the dropdown “Apache Website”. Change the “Port number for virtual hosts” from 80 to 8000. Restart webmin:
systemctl restart webmin.service
Lets build the necessary scripts that will automate the creation of Nginx virtual host file each time Virtualmin created a new server. First the Nginx virtual host template:
vi /etc/nginx/sites-available/template.conf
The content:
## Configuration for {DOM}.
server {
## Replace XXX.XXX.XXX.XXX with your server’s IPv4 address
listen XXX.XXX.XXX.XXX:80;
## Replace XXXX:XXXX::XXXX:XXXX:XXXX:XXXX with your server’s IPv6 address
listen [XXXX:XXXX::XXXX:XXXX:XXXX:XXXX]:80;
server_name {DOM};
## Redirect permanently to domain with www
return 301 $scheme://www.{DOM}$request_uri;
}
server {
## Replace XXX.XXX.XXX.XXX with your server’s IPv4 address
listen XXX.XXX.XXX.XXX:80;
## Replace XXXX:XXXX::XXXX:XXXX:XXXX:XXXX with your server’s IPv6 address
listen [XXXX:XXXX::XXXX:XXXX:XXXX:XXXX]:80;
server_name www.{DOM};
## Access and error logs.
access_log /var/log/virtualmin/{DOM}_nginx_access_log;
error_log /var/log/virtualmin/{DOM}_nginx_error_log error;
## Root of the site and index.
root {HOME}/public_html;
index index.php;
## Deny access based on the User-Agent header.
if ($bad_bot) {
return 444;
}
## Deny access based on the Referer header.
if ($bad_referer) {
return 444;
}
## Protection against illegal HTTP methods. Only HEAD,
## GET and POST are allowed.
if ($not_allowed_method) {
return 405;
}
## Configuration for Drupal site
include drupal.conf;
}
vi /usr/local/bin/virtualmin.sh
#!/bin/sh
NGINX_CONF_FILE=”/etc/nginx/sites-available/${VIRTUALSERVER_DOM}.conf ”
if [ “$VIRTUALSERVER_ACTION” = “CREATE_DOMAIN” ]; then
if [ “${VIRTUALSERVER_WEB}” = “1” ];
then
cp /etc/nginx/sites-available/template.conf $NGINX_CONF_FILE
perl -pi -e “s#{DOM}#$VIRTUALSERVER_DOM#g” $NGINX_CONF_FILE
perl -pi -e “s#{SITE_IP}#$VIRTUALSERVER_IP#g” $NGINX_CONF_FILE
perl -pi -e “s#{HOME}#$VIRTUALSERVER_HOME#g” $NGINX_CONF_FILE
ln -s $NGINX_CONF_FILE /etc/nginx/sites-enabled/${VIRTUALSERVER_DOM}.conf
nginx -s reload
fi
elif [ “$VIRTUALSERVER_ACTION” = “DELETE_DOMAIN” ]; then
if [ “${VIRTUALSERVER_WEB}” = “1” ];
then
rm /etc/nginx/sites-enabled/${VIRTUALSERVER_DOM}.conf
rm /etc/nginx/sites-available/${VIRTUALSERVER_DOM}.conf
rm /var/log/virtualmin/${VIRTUALSERVER_DOM}_nginx_*
nginx -s reload
fi
elif [ “$VIRTUALSERVER_ACTION” = “MODIFY_DOMAIN” ]; then
if [ “${VIRTUALSERVER_WEB}” = “1” ];
then
if [ ! -f $NGINX_CONF_FILE ]; then
cp /etc/nginx/sites-available/template.conf $NGINX_CONF_FILE
perl -pi -e “s#{DOM}#$VIRTUALSERVER_DOM#g” $NGINX_CONF_FILE
perl -pi -e “s#{SITE_IP}#$VIRTUALSERVER_IP#g” $NGINX_CONF_FILE
perl -pi -e “s#{HOME}#$VIRTUALSERVER_HOME#g” $NGINX_CONF_FILE
ln -s $NGINX_CONF_FILE /etc/nginx/sites-enabled/${VIRTUALSERVER_DOM}.conf
fi
fi
if [ “$VIRTUALSERVER_DOM” != “$VIRTUALSERVER_OLDSERVER_DOM” ]; then
if [ “${VIRTUALSERVER_WEB}” = “1” ];
then
OLD_NGINX_CONF_FILE=/etc/nginx/sites-available/${VIRTUALSERVER_OLDSERVER_DOM}.conf
mv $OLD_NGINX_CONF_FILE $NGINX_CONF_FILE
rm /etc/nginx/sites-enabled/${VIRTUALSERVER_OLDSERVER_DOM}.conf
perl -pi -e “s#$VIRTUALSERVER_OLDSERVER_DOM#$VIRTUALSERVER_DOM#g” $NGINX_CONF_FILE
perl -pi -e “s#$VIRTUALSERVER_OLDSERVER_IP#$VIRTUALSERVER_IP#g” $NGINX_CONF_FILE
perl -pi -e “s#$VIRTUALSERVER_OLDSERVER_HOME#$VIRTUALSERVER_HOME#g” $NGINX_CONF_FILE
ln -s /etc/nginx/sites-available/${VIRTUALSERVER_DOM}.conf /etc/nginx/sites-enabled/${VIRTUALSERVER_DOM}.conf
fi
fi
if [ “${VIRTUALSERVER_WEB}” = “1” ];
then
nginx -s reload
fi
fi
Make the script executable:
chmod u+x /usr/local/bin/virtualmin.sh
Let Virtualmin know about the virtualmin.sh. Login to Virtualmin, go to “System Settings” -> “Virtualmin Configuration” and select from dropdown “Actions upon server and user creation”. Populate the “Command to run after making changes to a server” field with:
/usr/local/bin/virtualmin.sh
Recent Comments