Skip to content

Instantly share code, notes, and snippets.

@willwade
Last active September 5, 2019 06:35
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save willwade/9568199 to your computer and use it in GitHub Desktop.
Save willwade/9568199 to your computer and use it in GitHub Desktop.
VhostMan-Nginx. A small script (and other bits) for creating virtual hosts with Nginx. Use as you wish. Download all the components - put in your path somewhere and run with vhostman-nginx.sh create domain.com app name. It doesn't need the gunicorn_start file if you don't need that.
#!/bin/bash
NAME="appname" # Name of the application
DJANGODIR=/srv/_domain_/appname # Django project directory
SOCKFILE=/srv/_domain_/run/gunicorn.sock # we will communicte using this unix socket
USER=admin # the user to run as
GROUP=admin # the group to run as
NUM_WORKERS=3 # how many worker processes should Gunicorn spawn
DJANGO_SETTINGS_MODULE=appname.settings # which settings file should Django use
DJANGO_WSGI_MODULE=appname.wsgi # WSGI module name
echo "Starting $NAME as `whoami`"
# Activate the virtual environment
cd $DJANGODIR
source ../bin/activate
export DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
export PYTHONPATH=$DJANGODIR:$PYTHONPATH
# Create the run directory if it doesn't exist
RUNDIR=$(dirname $SOCKFILE)
test -d $RUNDIR || mkdir -p $RUNDIR
# Start your Django Unicorn
# Programs meant to be run under supervisor should not daemonize themselves (do not use --daemon)
exec ../bin/gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--log-level=debug \
--bind=unix:$SOCKFILE
upstream appname_server {
# fail_timeout=0 means we always retry an upstream even if it failed
# to return a good HTTP response (in case the Unicorn master nukes a
# single worker for timing out).
server unix:/srv/_domain_/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name _domain_;
client_max_body_size 4G;
access_log /srv/_domain_/logs/nginx-access.log;
error_log /srv/_domain_/logs/nginx-error.log;
location /static/ {
alias /srv/_domain_/static/;
}
location /media/ {
alias /srv/_domain_/media/;
}
location / {
# an HTTP header important enough to have its own Wikipedia entry:
# http://en.wikipedia.org/wiki/X-Forwarded-For
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# enable this if and only if you use HTTPS, this helps Rack
# set the proper protocol for doing redirects:
# proxy_set_header X-Forwarded-Proto https;
# pass the Host: header from the client right along so redirects
# can be set properly within the Rack application
proxy_set_header Host $http_host;
# we don't want nginx trying to do something clever with
# redirects, we set the Host: header above already.
proxy_redirect off;
# set "proxy_buffering off" *only* for Rainbows! when doing
# Comet/long-poll stuff. It's also safe to set if you're
# using only serving fast clients with Unicorn + nginx.
# Otherwise you _want_ nginx to buffer responses to slow
# clients, really.
# proxy_buffering off;
# Try to serve static files from nginx, no point in making an
# *application* server like Unicorn/Rainbows! serve static files.
if (!-f $request_filename) {
proxy_pass http://appname_server;
break;
}
}
# Error pages
error_page 500 502 503 504 /500.html;
location = /500.html {
root /srv/_domain_/static/;
}
}
[program:appname]
command = /srv/_domain_/bin/gunicorn_start ; Command to start app
user = admin ; User to run as
stdout_logfile = /srv/_domain_/logs/gunicorn_supervisor.log ; Where to write log messages
redirect_stderr = true
#!/bin/bash
### Set default parameters
# somewhat follows the conventions from: http://michal.karzynski.pl/blog/2013/10/29/serving-multiple-django-applications-with-nginx-gunicorn-supervisor/
# designed to run on a debian symbiosis box if your interested why its /srv
action=$1
domain=$2
appname=$3
owner=$(who am i | awk '{print $1}')
sitesEnable='/etc/nginx/sites-enabled/'
sitesAvailable='/etc/nginx/sites-available/'
#userDir=$(eval echo ~${SUDO_USER})'/www/'
dataDir='/srv/'
#get cur dir
SCRIPTPATH=$(dirname $(readlink -f "$0"))
if [ "$(whoami)" != 'root' ]; then
echo "You have no permission to run $0 as non-root user. Use sudo !!!"
exit 1;
fi
if [ "$action" != 'create' ] && [ "$action" != 'delete' ]
then
echo "You need to prompt for action (create or delete) -- Lower-case only !!!!!!"
exit 1;
fi
while [ "$domain" == "" ]
do
echo -e "Please provide domain. e.g.dev,staging"
read domain
done
rootdir=${domain}
if [ "$action" == 'create' ]
then
### check if domain already exists
if [ -e $sitesAvailable$domain ]; then
echo -e 'This domain already exists.\nPlease Try Another one'
exit;
fi
### check if directory exists or not
if [ -d $dataDir$rootdir ]; then
echo -e 'Directory already exists !'
exit;
fi
### create the directory
mkdir $dataDir$rootdir
### create the other dirs
cd $dataDir$rootdir
mkdir logs config bin public
cd ${0%/*}
pwd
## copy template to the dir
sudo cp $SCRIPTPATH/nginx-template.txt /etc/nginx/sites-available/${domain}
## now find and replace strings. using sed as im lazy
sed -i "s/_domain_/${domain}/g" $sitesAvailable$domain
sed -i "s/appname/${appname}/g" $sitesAvailable$domain
echo -e '\nNew Virtual Host Created\n'
ln -s $sitesAvailable$domain $dataDir$rootdir/config/vhost
ln -s $sitesEnable$domain $sitesAvailable$domain
# Now do the gunicorn_start file if that exists
if [ -e $SCRIPTPATH/gunicorn_start-template.txt ]; then
sudo cp $SCRIPTPATH/gunicorn_start-template.txt $dataDir$rootdir/config/gunicorn_start
sed -i "s/_domain_/${domain}/g" $dataDir$rootdir/config/gunicorn_start
sed -i "s/appname/${appname}/g" $dataDir$rootdir/config/gunicorn_start
chmod u+x $dataDir$rootdir/config/gunicorn_start
fi
# Now do the supervisor file if that exists
if [ -e $SCRIPTPATH/supervisorconf-template.txt ]; then
sudo cp $SCRIPTPATH/supervisorconf-template.txt /etc/supervisor/conf.d/$domain.conf
sed -i "s/_domain_/${domain}/g" /etc/supervisor/conf.d/$domain.conf
sed -i "s/appname/${appname}/g" /etc/supervisor/conf.d/$domain.conf
sudo supervisorctl reread
sudo supervisorctl update
fi
#Now install a virtualenv
# You may want this. Happily remove or add a flag
virtualenv $dataDir$rootdir
### give permission to root dir
chmod 755 $dataDir$rootdir
### restart Apache
sudo service nginx reload
### write test file in the new domain dir
#if ! echo "<?php echo phpinfo(); ?>" > $dataDir$rootdir/public/htdocs/phpinfo.php
#then
# echo "ERROR: Not able to write in file "$dataDir"/"$rootdir"/public/htdocs/phpinfo.php. Please check permissions."
# exit;
#else
# echo "Added content to "$dataDir$rootdir"/public/htdocs/phpinfo.php."
#fi
if [ "$owner" == "" ]; then
chown -R $(whoami):$(whoami) $dataDir$rootdir
else
chown -R $owner:$owner $dataDir$rootdir
fi
### show the finished message
echo -e "Complete!
You now have a new Virtual Host
Your new host is: http://"$domain"
And its located at "$dataDir$rootdir
exit;
else
### check whether domain already exists
if ! [ -e $sitesAvailable$domain ]; then
echo -e 'This domain dont exists.\nPlease Try Another one'
exit;
fi
### check if directory exists or not
if ! [ -d $dataDir$rootdir ]; then
echo -e 'Directory not exists !'
exit;
fi
## delete the supervisor script
if [ -e /etc/supervisor/conf.d/$domain.conf ]; then
sudo rm /etc/supervisor/conf.d/$domain.conf
sudo supervisorctl reread
sudo supervisorctl update
fi
### Delete the directory
rm -rf $dataDir$rootdir
### Delete virtual host rules file
rm $sitesAvailable$domain
### enable website
rm $sitesEnable$domain
rm $sitesAvailable$domain
### restart Apache
sudo service nginx reload
### show the finished message
echo -e "Complete!
You just removed Virtual Host "$domain
exit 0;
fi
@krzysztofjeziorny
Copy link

krzysztofjeziorny commented Nov 14, 2018

It's a nice idea of starting a new vhost configuration. I just tested it and came to a few points:

  • On line 66 of the the symlinking should go the other way around, from source to destination:
    ln -s $sitesAvailable$domain $sitesEnable$domain
  • Line 2 of supervisorconf-template states where the gunicorn_start lives, it should be not bin but config, as used later.
  • At my system (Debian 9) I came across an error where the _domain_ in template files will be changed, but appname not.
  • Line 146: you want to restart nginx (not Apache), so systemctl restart nginx.service
  • Also, if it's intended to run on Debian, it is recommended to run it as root and drop sudo altogether from the script.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment