Skip to content

Instantly share code, notes, and snippets.

@victoraguilarc
Created April 10, 2015 14:33
Show Gist options
  • Save victoraguilarc/4eae2350ce324846e6e3 to your computer and use it in GitHub Desktop.
Save victoraguilarc/4eae2350ce324846e6e3 to your computer and use it in GitHub Desktop.
Plantilla Fabric para desplegar una aplicación Django
# -*- encoding: utf8 -*-
#### Django deployment for Debian Based SERVERS ######
from __future__ import unicode_literals
import re
import os
import getpass
from fabric.api import *
from fabric.contrib.files import exists, upload_template
env.proy_repo = '[email protected]:jvacx/owl.git'
# App configuration
app = {
"url": "proyecto.jvacx.com", # dominio del proyecto
"name": "proy_app", # cambiar
"superuser": "victor", # cambiar
"user": "proy_user", # cambiar
"group": "proy_team", # cambiar
"path": "/webapps",
"deps": [ # System's Packages dependencies
"build-essential",
"python",
"python-setuptools",
"python-virtualenv",
"python-pip",
"python-dev",
"nginx",
"gunicorn",
"supervisor",
"postgresql",
"postgresql-contrib",
"libpq-dev",
"git",
"zip",
"rpl",
"libjpeg-dev",
"libfreetype6-dev",
"zlib1g-dev",
],
}
# Database Configuration
DB_NAME = app["name"]
DB_USER = app["user"]
DB_PASS = "123x" # cambiar
# Path configurations.
CONFIG_DIR = './config' # Locally
NGINX_DIR = '/etc/nginx' # Remote
SUPERVISOR_DIR = '/etc/supervisor' # Remote
PROJECT_PATH = "%s/%s/%s"%(app["path"], app["user"], app["name"])
USER_HOME = "%s/%s"%(app["path"], app["user"])
# Servers configuration.
SERVERS = {
"production": {
"domain": "0.0.0.0", #IP or domain
"ssh_port": "22",
"path": "/var/www/owl",
"branch": "master",
},
"stage": {
"domain": "0.0.0.0", #IP or domain
"ssh_port": "2290",
"path": "/var/www/owl",
"branch": "stage",
},
"develop": {
"domain": "localhost",
"ssh_port": "2290",
"path": os.path.dirname(os.path.abspath(__file__)),
"branch": "develop",
},
}
## ~$ UTILS
####---------------------------------------------------------------------
class Server(object):
@staticmethod
def upgrade():
sudo('apt-get update -y')
sudo('apt-get upgrade -y')
@staticmethod
def deps():
sudo('apt-get install -y %s' % ' '.join(app["deps"]))
@staticmethod
def restart_services():
sudo('service nginx restart')
sudo('service supervisor restart')
sudo('supervisorctl restart %s'%app["name"])
@staticmethod
def clean():
sudo('apt-get remove %s' % ' '.join(app["deps"]))
class Conf(object):
@staticmethod
def nginx():
"""
1. Remove default nginx config file
2. Create new config file
3. Copy local config to remote config
4. Setup new symbolic link
5. Restart nginx
"""
if exists('%s/sites-enabled/default'%NGINX_DIR):
sudo('rm %s/sites-enabled/default'%NGINX_DIR)
if exists('%s/sites-enabled/%s'%(NGINX_DIR,app["url"])):
sudo('rm %s/sites-enabled/%s'%(NGINX_DIR,app["url"]))
if exists('%s/sites-available/%s'%(NGINX_DIR,app["url"])):
sudo('rm %s/sites-available/%s'%(NGINX_DIR,app["url"]))
with lcd(CONFIG_DIR):
with cd('%s/sites-available/'%NGINX_DIR):
upload_template(
filename="./nginx.conf",
destination='%s/sites-available/%s'%(NGINX_DIR,app["url"]),
template_dir="./",
context={
"project_name": app["name"],
"project_path": PROJECT_PATH,
"project_url": app["url"],
},
use_sudo=True,
)
sudo('ln -s %s/sites-available/%s \
%s/sites-enabled/'%(NGINX_DIR,app["url"],NGINX_DIR))
# sudo('service nginx restart')
@staticmethod
def gunicorn():
"""
1. Create new gunicorn start script
2. Copy local start script template redered to server
"""
sudo('rm -rf %s/bin'%PROJECT_PATH)
sudo('mkdir -p %s/bin'%PROJECT_PATH)
with lcd(CONFIG_DIR):
with cd('%s/bin'%PROJECT_PATH):
sudo('ls')
upload_template (
filename='./start_prod.sh',
destination='%s/bin/start.sh'%PROJECT_PATH,
template_dir="./",
context={
"project_name": app["name"],
"project_path": PROJECT_PATH,
"app_user": app["user"],
"app_group": app["group"],
},
use_sudo=True,
)
sudo('chmod +x %s/bin/start.sh'%PROJECT_PATH)
@staticmethod
def supervisor():
"""
1. Create new supervisor config file
2. Copy local config to remote config
3. Register new command
"""
if exists('%s/conf.d/%s.conf'%(SUPERVISOR_DIR,app["name"])):
sudo('rm %s/conf.d/%s.conf'%(SUPERVISOR_DIR,app["name"]))
with lcd(CONFIG_DIR):
with cd('%s/conf.d'%SUPERVISOR_DIR):
upload_template(
filename="./supervisor.conf",
destination='./%s.conf'%app["name"],
template_dir="./",
context={
"project_name": app["name"],
"project_path": PROJECT_PATH,
"app_user": app["user"],
},
use_sudo=True,
)
sudo('supervisorctl reread')
sudo('supervisorctl update')
@staticmethod
def git():
"""
1. Setup bare Git repo
2. Create post-receive hook
"""
if exists(app["path"]) is False:
sudo('mkdir %s' % app["path"])
if exists(USER_HOME) is False:
sudo("mkdir %s"%USER_HOME)
if exists(PROJECT_PATH) is False:
sudo("mkdir %s"%PROJECT_PATH)
with cd(USER_HOME):
sudo('mkdir -p %s.git'%app["name"])
with cd('%s.git'%app["name"]):
sudo('git init --bare')
with lcd(CONFIG_DIR):
with cd('hooks'):
upload_template(
filename="post-receive",
destination=PROJECT_PATH+".git/hooks",
template_dir="./",
context={
"project_path": PROJECT_PATH,
},
use_sudo=True,
)
sudo('chmod +x post-receive')
sudo('chown -R %s:%s %s.git'%(app["user"], app["group"], app["name"]))
local('git remote remove %s'%env.remote)
local('git remote add %s %s@%s:%s/%s.git'%(
env.remote,app["user"], env.hosts[0], USER_HOME, app["name"],
))
@staticmethod
def roles():
"""
1. Create app group
2. Create app user
3. Asociate user home
4. Fix Permissions
"""
# Create user and group
sudo('groupadd --system %s'%app["group"])
sudo('useradd --system --gid %s \
--shell /bin/bash --home %s %s'
% (app["group"], USER_HOME, app["user"]))
# Create and asociate home to app user
sudo('adduser %s sudo'%app["user"])
sudo('mkdir -p %s'%USER_HOME)
sudo('chown -R %s %s'%(app["user"],USER_HOME))
sudo('chown -R %s:%s %s'%(
app["user"],app["group"],
PROJECT_PATH,
))
sudo('chmod -R g+w %s'%PROJECT_PATH)
@staticmethod
def postgresql():
"""
1. Create DB user
2. Create DB and assign to user
"""
sudo('psql -c "CREATE USER %s WITH NOCREATEDB NOCREATEUSER \
ENCRYPTED PASSWORD E\'%s\'"' % (DB_USER, DB_PASS), user='postgres')
sudo('psql -c "CREATE DATABASE %s WITH OWNER %s"' % (
DB_NAME, DB_USER), user='postgres')
@staticmethod
def fix_permissions():
sudo('chown -R %s %s'%(app["user"],USER_HOME))
sudo('chown -R %s:%s %s'%(
app["user"], app["group"], PROJECT_PATH,
))
sudo('chmod -R g+w %s'%PROJECT_PATH)
@staticmethod
def clean():
"""
1. Delete app group
2. Delete app user
3. Delete related files
4. Delete config files
5. Delete DB and user DB
"""
sudo('groupdel %s'%app["group"])
sudo('userdel -r %s'%app["user"])
if exists(PROJECT_PATH):
sudo('rm -r %s'%PROJECT_PATH)
if exists('%s/conf.d/%s.conf'%(SUPERVISOR_DIR,app["name"])):
sudo('rm %s/conf.d/%s.conf'%(SUPERVISOR_DIR,app["name"]))
if exists('%s/sites-enabled/%s'%(NGINX_DIR,app["name"])):
sudo('rm %s/sites-enabled/%s'%(NGINX_DIR,app["name"]))
if exists('%s/sites-available/%s'%(NGINX_DIR,app["name"])):
sudo('rm %s/sites-available/%s'%(NGINX_DIR,app["name"]))
sudo('dropuser %s' % DB_USER)
sudo('psql -c "DROP DATABASE %s"' % DB_NAME, user='postgres')
class Project(object):
@staticmethod
def push():
"""Push cambios del repositorio al servidor principal"""
local("git push %s %s" %(env.remote, env.branch) )
@staticmethod
def install():
with cd(PROJECT_PATH):
run("make install")
@staticmethod
def start():
sudo("supervisorctl start %s"%app["name"])
@staticmethod
def restart():
sudo("supervisorctl restart %s"%app["name"])
@staticmethod
def stop():
sudo("supervisorctl stop %s"%app["name"])
@staticmethod
def clean_cache():
with cd("%s/var/cache"%PROJECT_PATH):
run("rm -r *")
@staticmethod
def clean_logs():
with cd("%s/var/log"%PROJECT_PATH):
run("rm -r *")
@staticmethod
def backup_db():
with cd(env.path):
with prefix('source env/bin/activate'):
res = run("python manage.py backup_db")
backup_name = re.search('Backup: (.+)', res).groups(0)[0]
if 'download' in args:
get('var/backup/local/{0}'.format(backup_name), 'var/backup/remote/')
@staticmethod
def test():
pass
def deploy(*args):
"""Deploy application on a server"""
if len(args) <= 0:
servers()
for server in args:
if server in SERVERS.keys():
env.user = app["user"]
env.hosts = [SERVERS[server]["domain"], ]
env.path = SERVERS[server]["path"]
env.remote = server
env.branch = SERVERS[server]["branch"]
with settings(warn_only=True):
execute(Project.push, hosts=[SERVERS[server]["domain"], ])
# execute(Project.clean_logs, hosts=[SERVERS[server]["domain"], ])
execute(Project.clean_cache, hosts=[SERVERS[server]["domain"], ])
execute(Project.install, hosts=[SERVERS[server]["domain"], ])
# execute(Project.restart, hosts=[SERVERS[server]["domain"], ])
else:
servers()
def init(*args):
"""Init base of application on a server"""
if len(args) <= 0:
servers()
for server in args:
if server in SERVERS.keys():
env.user = app["superuser"]
env.hosts = [SERVERS[server]["domain"], ]
env.path = SERVERS[server]["path"]
env.remote = server
with settings(warn_only=True):
HOST = "%s:%s" % (
SERVERS[server]["domain"],
SERVERS[server]["ssh_port"],
)
execute(Conf.clean, hosts=[HOST,])
execute(Server.deps, hosts=[HOST,])
execute(Conf.roles, hosts=[HOST,])
execute(Conf.postgresql, hosts=[HOST,])
execute(Conf.git, hosts=[HOST,])
execute(Conf.nginx, hosts=[HOST,])
execute(Conf.gunicorn, hosts=[HOST,])
execute(Conf.supervisor, hosts=[HOST,])
execute(Conf.fix_permissions, hosts=[HOST,])
else:
servers()
def clean(*args):
"""Clean app and related files od server"""
if len(args) <= 0:
servers()
for server in args:
if server in SERVERS.keys():
env.user = app["superuser"]
env.hosts = [SERVERS[server]["domain"], ]
env.path = SERVERS[server]["path"]
with settings(warn_only=True):
HOST = "%s:%s" % (
SERVERS[server]["domain"],
SERVERS[server]["ssh_port"],
)
execute(Conf.clean, hosts=[HOST,])
else:
servers()
def restart(*args):
"""Clean app and related files od server"""
if len(args) <= 0:
servers()
for server in args:
if server in SERVERS.keys():
env.user = app["superuser"]
env.hosts = [SERVERS[server]["domain"], ]
env.path = SERVERS[server]["path"]
with settings(warn_only=True):
HOST = "%s:%s" % (
SERVERS[server]["domain"],
SERVERS[server]["ssh_port"],
)
execute(Server.restart_services, hosts=[HOST,])
else:
servers()
def help():
print ""
print "-------------------------------------------------------------------------"
print "---------------------------- Deployment Flow ----------------------------"
print "-------------------------------------------------------------------------"
print ""
print " - init:server, [server2, ] Initilize project into selected servers"
print " - config:server, [server2, ] Configure user into selected servers"
print " - deploy:server, [server2, ] Deploy into selected servers"
print " - restart:server, [server2, ] Restart selected servers"
print " - restart:server, [server2, ] Restart selected servers"
print ""
print "-------------------------------------------------------------------------"
def servers():
print ""
print "---------------------------------------------------------------------"
print "---------------------------- Available SERVERS ----------------------"
print "---------------------------------------------------------------------"
print ""
for server in SERVERS.keys():
print " - "+server
print ""
print "---------------------------------------------------------------------"
print ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment