Last active
November 15, 2015 21:10
-
-
Save panchr/035fb3c81b5cd4cd579e to your computer and use it in GitHub Desktop.
Server initialization script, oriented towards Python servers.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Rushy Panchal | |
# configure.py | |
# Initializes the server | |
import subprocess | |
def main(): | |
'''Main process''' | |
with open("nginx.conf", "w") as nginx_conf: | |
nginx_conf.write('''{{ nginx_conf }}''') | |
with open("init.sh", "w") as init_file: | |
init_file.write('''{{ init_data }}''') | |
with open("upstart-app.conf", "w") as upstart_file: | |
upstart_file.write('''{{ upstart_script }}''') | |
{% if https %} | |
with open("bundle.crt", "w") as bundle_file: | |
bundle_file.write('''{{ ssl_bundle }}''') | |
with open("private.key", "w") as key_file: | |
key_file.write('''{{ private_key }}'') | |
{% endif %} | |
subprocess.call("chmod a+x init.sh && ./init.sh", shell = True) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Rushy Panchal | |
# packageInit.py | |
# Packages the initialization scripts into one Python file | |
import sys | |
import os | |
sys.path.append(os.path.join(os.path.realpath(".."), "app")) | |
import config | |
import jinja2 | |
CONFIG = { | |
"https": config.PROTOCOL == "https://", | |
} | |
CONFIG.update(config.__dict__) | |
jinja_loader = jinja2.FileSystemLoader(searchpath = ".") | |
jinja_env = jinja2.Environment(trim_blocks = True, lstrip_blocks = True, loader = jinja_loader) | |
def main(): | |
'''Main process''' | |
nginx_conf = formatFile("nginx.conf") | |
init_data = formatFile("init") | |
upstart_script = formatFile("upstart-app.conf") | |
ssl_bundle = formatFile("ssl/bundle.crt") | |
ssl_key = formatFile("ssl/private.key") | |
configure_py_template = jinja_env.get_template("package.py") | |
# with open("package.py", "r") as configure_data: | |
# configure_py_template = jinja_env.get_template(configure_data) | |
packageData = { | |
"nginx_conf": nginx_conf, | |
"init_data": init_data, | |
"upstart_script": upstart_script, | |
"ssl_bundle": ssl_bundle, | |
"ssl_key": ssl_key, | |
} | |
packageData.update(CONFIG) | |
packagedCode = configure_py_template.render(**packageData) | |
with open("configure.py", "w") as python_init: | |
python_init.write(packagedCode) | |
def formatFile(filePath, dictConfig = None): | |
'''Formats the file data with the configuration data''' | |
if not dictConfig: | |
dictConfig = CONFIG | |
# with open(filePath, 'r') as fileObject: | |
# fileTemplate = jinja2.Template(fileObject.read()) | |
fileTemplate = jinja_env.get_template(filePath) | |
return fileTemplate.render(**dictConfig) | |
if __name__ == '__main__': | |
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Rushy Panchal | |
# Install all dependencies and setup the environment | |
# Options | |
CWD="$PWD" | |
# Add the new user | |
sudo adduser "{{ SERVER.user }}" | |
sudo gpasswd -a "{{ SERVER.user }}" sudo | |
# Update repositories | |
sudo apt-get update && sudo apt-get upgrade -y | |
# Necessary packages | |
sudo apt-get install -y git curl ufw fail2ban vnstat | |
# Python packages | |
sudo apt-get install -y build-essential # this is for compiling most C programs and C-based Python packages | |
sudo apt-get install -y python python-pip python-dev libffi-dev | |
sudo pip install pip --upgrade | |
sudo pip install virtualenv Fabric # Fabric is a Python task runner | |
sudo apt-get -y install fabric | |
# Install Nginx | |
sudo apt-get install -y nginx | |
# Install MongoDB | |
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10 | |
echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list | |
sudo apt-get update | |
sudo apt-get install -y mongodb-org build-essential openssl libssl-dev pkg-config | |
sudo mkdir -p /data/db # Database directory for MongoDB | |
# Create the /var/www/ directory for the application | |
sudo chown -R "{{ SERVER.user }}":"{{ SERVER.user }}" /var/www | |
sudo mkdir -p "/var/www/{{ SERVER.service }}" | |
sudo chown -R "{{ SERVER.user }}":www-data "/var/www/{{ SERVER.service }}" | |
sudo chmod 755 /var/www | |
sudo usermod -a -G www-data "{{ SERVER.user }}" | |
# Create NginX directories and add the configuration | |
sudo mkdir -p /var/cache/nginx | |
sudo rm /etc/nginx/sites-available/default | |
sudo rm /etc/nginx/sites-enabled/default | |
sudo mv nginx.conf "/etc/nginx/sites-available/{{ DOMAIN }}" | |
sudo ln -s "/etc/nginx/sites-available/{{ DOMAIN }}" "/etc/nginx/sites-enabled/{{ DOMAIN }}" | |
{% if https %} | |
# NginX SSL configuration | |
sudo mkdir -p "/etc/nginx/ssl/{{ DOMAIN }}" | |
cd ~/ | |
sudo mv bundle.crt "/etc/nginx/ssl/{{ DOMAIN }}.bundle.crt" | |
sudo mv private.key "/etc/nginx/ssl/{{ DOMAIN }}.private.key" | |
{% endif %} | |
# Create the Git repository and add the post-receive hook | |
sudo mkdir -p "/var/repo/{{ SERVER.service }}.git" | |
cd "/var/repo/{{ SERVER.service }}.git" | |
sudo git init --bare | |
sudo cat <<EOT >> "hooks/post-receive" | |
#!/bin/sh | |
git --work-tree=/var/www/{{ SERVER.service }} --git-dir=/var/repo/{{ SERVER.service }}.git checkout -f | |
EOT | |
sudo chmod +x hooks/post-receive | |
sudo rm hooks/*.sample | |
cd /var/repo | |
sudo chown -R {{ SERVER.user }}:{{ SERVER.user }} "/var/repo/{{ SERVER.service }}.git" | |
cd ~/ | |
# Firewall configuration | |
sudo ufw allow ssh # make sure to enable SSH access BEFORE enabling the firewall | |
sudo ufw allow http | |
{% if https %} | |
sudo ufw allow https | |
{% endif %} | |
sudo ufw allow from 127.0.0.1 to any port "{{ PORT }}" # Application | |
sudo ufw allow from 127.0.0.1 to any port "{{ DB_PORT }}" # MongoDB | |
sudo ufw --force enable # force start UFW - no prompt | |
# Disable logging into root via SSH | |
sudo sed -i '/^#/!{s/PermitRootLogin .*/PermitRootLogin no/}' /etc/ssh/sshd_config | |
sudo service ssh restart | |
# Start services | |
cd "$CWD" | |
sudo service nginx start | |
sudo service mongod start | |
# Installing Upstart script | |
cd ~/ | |
sudo mv upstart-app.conf "/etc/init/{{ SERVER.service }}.conf" | |
sudo mkdir -p "/var/log/{{ SERVER.service }}" # Cryptosana log directory | |
sudo chown -R "{{ SERVER.user }}":"{{ SERVER.user }}" "/var/log/{{ SERVER.service }}" | |
sudo touch "/var/log/upstart/{{ SERVER.service }}.log" # create the initial log item for upstart | |
sudo ln -s "/var/log/upstart/{{ SERVER.service }}.log" "/var/log/{{ SERVER.service }}/service.log" # make link to the Upstart log | |
sudo ln -s "/var/log/{{ SERVER.service}}" "/var/www/{{ SERVER.service }}/log" | |
# Installing Memory Swap | |
sudo fallocate -l "{{ SERVER.swapSize }}" /swapfile | |
sudo chmod 600 /swapfile | |
sudo mkswap /swapfile | |
sudo swapon /swapfile | |
echo "/swapfile none swap sq 0 0" >> /etc/fstab | |
# Create environment variable, {{ SERVER.service }} for the app directory | |
# for both the root and the {{ SERVER.user }} | |
echo "export APP=/var/www/{{ SERVER.service }}" >> ~/.profile | |
sudo -H -u {{ SERVER.user }} bash -c 'echo "export APP=/var/www/{{ SERVER.service }}" >> ~/.profile' | |
# Cleanup | |
sudo apt-get autoremove -y | |
sudo apt-get clean | |
cd ~/ | |
rm init.sh configure.py # delete the configuration programs | |
# Final messages | |
echo "You might also want to add a pre-receive hook, /var/repo/{{ SERVER.service }}.git/hooks/pre-receive, to run unit tests before accepting a push." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Rushy Panchal | |
# /etc/nginx/sites-available/{{ DOMAIN }} | |
# Configuration for Nginx | |
{% if https %} | |
server { | |
# redirect to SSL | |
listen 80; | |
server_name {{ DOMAIN}}; | |
return 301 https://$server_name$request_uri; | |
} | |
{% endif %} | |
server { | |
{% if SERVER.cloudflare %} | |
# CloudFlare forwarded IP | |
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; | |
{% endif %} | |
{% if https %} | |
listen 443 ssl; | |
{% else %} | |
listen 80; | |
{% endif %} | |
root /var/www/{{ SERVER.service }}; | |
{% if https %} | |
# SSL configuration | |
ssl_certificate /etc/nginx/ssl/{{ DOMAIN }}.bundle.crt; | |
ssl_certificate_key /etc/nginx/ssl/{{ DOMAIN }}.private.key; | |
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; | |
ssl_prefer_server_ciphers on; | |
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS +RC4 RC4"; | |
{% endif %} | |
server_name {{ DOMAIN }} www.{{ DOMAIN }}; | |
autoindex off; | |
# Gzip configuration, to compress responses | |
gzip on; | |
gzip_comp_level 5; | |
gzip_vary on; | |
gzip_min_length 1000; | |
gzip_buffers 16 8k; | |
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript; # text/html is already added by default | |
# Error pages | |
error_page 403 /static/errors/403.html; | |
error_page 404 /static/errors/404.html; | |
error_page 500 /static/errors/500.html; | |
error_page 502 /static/errors/502.html; | |
error_page 503 /static/errors/503.html; | |
error_page 504 /static/errors/504.html; | |
location / { | |
# Forward to the application server via uWSGI | |
include uwsgi_params; | |
uwsgi_param HTTP_X_Real_IP $remote_addr; | |
uwsgi_param HTTP_X_Forwarded_For $proxy_add_x_forwarded_for; | |
uwsgi_param HTTP_X_Forwarded_Proto $scheme; | |
uwsgi_param HTTP_Host $http_host; | |
uwsgi_param HTTP_X_NginX_Proxy true; | |
uwsgi_pass unix:/app/app.sock; | |
} | |
location ^~ /static { | |
# Static files | |
alias /var/www/{{ SERVER.service }}/static; | |
access_log off; | |
etag on; | |
expires max; | |
add_header Cache-Control "public, must-revalidate, proxy-revalidate"; | |
add_header Access-Control-Allow-Origin *; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
while read oldrev newrev refname | |
do | |
# only run this script for the master branch | |
if [ "$refname" == "refs/heads/master" ]; then | |
echo "Preparing to run unit tests for $newrev" | |
# store the revision as a physical file | |
mkdir -p "git-tmp/$newrev" | |
git archive $newrev | tar -x -C "git-tmp/$newrev" | |
echo "Running unit tests for $newrev" | |
cd "git-tmp/$newrev" | |
nosetests --where=app --with-coverage --cover-package=app --cover-min-percentage=25 # Python unit tests | |
TEST_RESULTS=$? | |
if [ $TEST_RESULTS -ne 0 ]; then | |
# A non-zero return code means an error occurred, so tell the user and exit | |
echo "Unit tests failed on rev $newrev - push denied. Run tests locally and confirm they pass before pushing again." && exit 1 | |
fi | |
fi | |
done | |
echo "Unit tests passed! Proceeding with push..." && exit 0 # all unit tests passed, so proceed with the push |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Rushy Panchal | |
virtualenv venv | |
source venv/bin/activate | |
pip install pip --upgrade | |
pip install -r app/requirements.txt | |
deactivate |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Rushy Panchal | |
# Application upstart configuration | |
description "uWSGI server instance configured for {{ SERVER.service }}" | |
start on runlevel [2345] | |
stop on runlevel [!2345] | |
# Respawn the process if it exits | |
# However, if it crashes more than 10 times in 5 seconds, do not restart | |
respawn limit 10 5 | |
setuid {{ SERVER.user }} | |
setgid www-data | |
env PATH=/var/www/{{ SERVER.service }}/venv/bin | |
chdir /var/www/{{ SERVER.service }}/app | |
exec uwsgi --ini uwsgi.ini |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
With a proper configuration, these files can be used to bootstrap a Flask/MongoDB-based web server.
Running
createConfigure.py
(with proper dependencies and config setup) will outputconfigure.py
. This can then be uploaded to your server and run, and it will handle the rest.