-
-
Save tsuyukimakoto/3411186 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
{ | |
"secret_key":"$secret_key" | |
"akismet_api_key":"$akismet_api_key" | |
"db_default_user":$mysqluser | |
"db_default_password":$mysqlpassword | |
"db_default_host":"$host" | |
"db_default_port":"$port" | |
} |
This file contains hidden or 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
# -*- coding: utf-8 -*- | |
import os | |
import socket | |
import getpass | |
from string import Template | |
from fabric.api import local, run, sudo, cd, env, settings | |
from fabric.state import env | |
from fabric.contrib.files import sed, exists, append, contains, uncomment | |
from fabric.network import join_host_strings, normalize | |
from fabric.context_managers import settings | |
""" | |
Fab settings | |
""" | |
env.hosts = ['djangoproject.vir'] | |
env.git_code_url = 'git://github.com/django-ja/djangoproject.jp.git' | |
env.git_docs_url = 'git://github.com/django-docs-ja/django-docs-ja.git' | |
env.mysqluser = env.user | |
env.mysqlpassword = 'enterpassword' | |
env.dbname = 'djangoprojectjp' | |
env.secret_key = 'entersecretkey' | |
env.akismet_api_key = 'enterakismetkey' | |
def change_ssh_port(after=22): | |
""" | |
For security changing the default ssh port. | |
""" | |
host = normalize(env.host_string)[1] | |
before = str(env.port) | |
host_string=join_host_strings(env.user,host,before) | |
with settings(host_string=host_string, user=env.user): | |
print("{0} CHANGING SSH PORT TO: {1}".format(env.host, str(after))) | |
sed('/etc/ssh/sshd_config','Port '+ str(before),'Port '+str(after),use_sudo=True) | |
sudo('/etc/init.d/ssh restart') | |
def upload_ssh_key(rollback=False): | |
""" | |
Upload your ssh key for passwordless logins | |
""" | |
auth_keys = '/home/{0}/.ssh/authorized_keys'.format(env.user) | |
if not rollback: | |
local_user = getpass.getuser() | |
host = socket.gethostname() | |
u = '@'.join([local_user,host]) | |
u = 'ssh-key-uploaded-{0}'.format(u) | |
sudo('mkdir -p /home/{0}'.format(env.user)) | |
# determine local .ssh dir | |
home = os.path.expanduser('~') | |
ssh_key = None | |
ssh_dsa = os.path.join(home,'.ssh/id_dsa.pub') | |
ssh_rsa = os.path.join(home,'.ssh/id_rsa.pub') | |
if os.path.exists(ssh_dsa): | |
ssh_key = ssh_dsa | |
elif os.path.exists(ssh_rsa): | |
ssh_key = ssh_rsa | |
if ssh_key: | |
with open(ssh_key, 'r') as f: | |
ssh_file = f.read() | |
print("{0} UPLOADING SSH KEY".format(env.host)) | |
append(auth_keys,ssh_file, use_sudo=True) | |
def restrict_ssh(): | |
""" | |
Restrict password login, and root login. | |
""" | |
sshd_config = '/etc/ssh/sshd_config' | |
if not exists('/home/{0}/.ssh/authorized_keys'.format(env.user)): | |
print('{0} You need to upload_ssh_key first.'.format(env.host)) | |
return False | |
sed(sshd_config, 'PermitRootLogin yes', 'PermitRootLogin no', use_sudo=True) | |
uncomment(sshd_config,'#(\s?)PermitRootLogin(\s*)no',use_sudo=True) | |
sed(sshd_config, 'PermitEmptyPassword yes', 'PermitEmptyPassword no', use_sudo=True) | |
uncomment(sshd_config,'#(\s?)PermitEmptyPassword(\s*)no',use_sudo=True) | |
sed(sshd_config, 'PasswordAuthentication yes', 'PasswordAuthentication no', use_sudo=True) | |
uncomment(sshd_config,'#(\s?)PasswordAuthentication(\s*)no',use_sudo=True) | |
sudo('/etc/init.d/ssh restart') | |
def setup_ufw_rules(sshport): | |
""" | |
Setup ufw app rules. | |
""" | |
firewall_rules = ['default deny', 'allow 80/tcp', 'allow 443/tcp', 'allow {0}/tcp'.format(sshport)] | |
print('deleting all rules') | |
sudo('ufw reset') | |
print('enable ufw') | |
sudo('ufw enable') | |
for rule in firewall_rules: | |
with settings(warn_only=True): | |
print('ufw {0}'.format(rule)) | |
sudo('ufw {0}'.format(rule)) | |
output = sudo('ufw reload') | |
print(output) | |
def disable_services(): | |
""" | |
For performance, disable unnecesaly daemon. | |
""" | |
disables = ['acpid', 'apmd', 'atd', 'dns-clean', 'pppd-dns'] | |
for d in disables: | |
if exists('/etc/init.d/{0}'.format(d)): | |
sudo('update-rc.d {0} disable'.format(d)) | |
def install_packages(): | |
""" | |
Install a set of baseline packages and configure where necessary | |
""" | |
base_packages = ['nginx', 'mysql-server', 'python-setuptools', 'python-dev', 'libmysqlclient-dev', 'build-essential', 'git'] | |
python_packages = ['virtualenv', 'pip'] | |
sudo('apt-get update') | |
for p in base_packages: | |
sudo('apt-get install {0}'.format(p)) | |
with cd('/tmp'): | |
for p in python_packages: | |
sudo('easy_install {0}'.format(p)) | |
def deploy_code(): | |
""" | |
Update code on the servers from Git. | |
""" | |
if not exists('~/djangoproject.jp/'): | |
with cd('~'): | |
print("cloning djangoproject.jp: {0}".format(env.git_code_url)) | |
run('git clone {0}'.format(env.git_code_url)) | |
with cd('/home/{0}/djangoproject.jp/'.format(env.user)): | |
run('git fetch && git reset --hard origin/master') | |
def update_virtualenv(env_name, packages, reqs=None): | |
""" | |
Update virtualenv for the project, and update depencies. | |
""" | |
if not exists('~/envs/{0}'.format(env_name)): | |
run('mkdir -p ~/envs') | |
with cd('~/envs'): | |
run('virtualenv {0}'.format(env_name)) | |
with prefix('source ~/envs/{0}/bin/activate'.format(env_name)): | |
run('export PIP_RESPECT_VIRTUALENV=true') | |
for p in packages: | |
sudo('pip install "{0}"'.format(p)) | |
if reqs: | |
sudo('pip install -r {0}'.format(reqs)) | |
def deploy_doc(doc_version): | |
""" | |
Update docs on the servers from Git. | |
""" | |
with prefix('source ~/envs/djangoproject.jp/bin/activate'): | |
run('export PIP_RESPECT_VIRTUALENV=true') | |
# ドキュメントのバージョンに応じたvirtualenvを作成 | |
if doc_version == "1.0": | |
update_virtualenv('1.0', ['Sphinx==0.4.3']) | |
else: | |
sudo('pip install Sphinx') | |
if not exists('~/doc/{0}/'.format(doc_version)): | |
run('mkdir -p ~/doc') | |
with cd('~/doc'): | |
run('git clone {0} {1}'.format(env.git_docs_url, doc_version)) | |
with cd('~/doc/{0}'.format(doc_version)): | |
with prefix('source ~/envs/{0}/bin/activate'.format(doc_version)): | |
run('git fetch && git reset --hard {0}'.format(doc_version)) | |
run('make html') | |
def setup_mysql(): | |
""" | |
Setup mysql | |
""" | |
create_user_sql = """grant select,insert,delete,update,create,drop,file,alter,index on *.* to '{user}'@'localhost' identified by '{password}';""".format(user=env.mysqluser, password=env.mysqlpassword) | |
run('echo "{grant_sql}" | mysql --user=root --password'.format(grant_sql=create_user_sql)) | |
run('mysqladmin -u {0} -p{1} create {2}'.format(env.mysqluser, env.mysqlpassword, env.dbname)) | |
def setup_gunicorn(): | |
""" | |
Setup gunicorn, and start daemon. | |
""" | |
run('source ~/envs/djangoproject.jp/bin/activate && python djangoproject.jp/manage.py run_gunicorn -w 1 -b 127.0.0.1:5000 -D && ps -aux | grep gunicorn') | |
run('ps -aux | grep gunicorn') | |
def setup_nginx(): | |
""" | |
Setup nginx. | |
""" | |
# plain_defaultからdefaultを生成しアップロード | |
local('cp ./plain_default ./default') | |
local('sed -i -e "s/{{ username }}/{0}/g" ./default'.format(env.user)) | |
put('./default', '/etc/nginx/sites-available/default', use_sudo=True) | |
sudo('nginx -t') | |
sudo('/etc/init.d/nginx reload') | |
def setup_environments(): | |
""" | |
Update enviroments.json which to set secret informetions. | |
""" | |
tmpl_file = os.path.join(os.path.dirname(__file__),'environments.json') | |
real_file = os.path.join(os.path.dirname(__file__),'environments.json_mod') | |
with cd('~/djangoproject.jp'): | |
with open(tmpl_file, 'r') as f: | |
json = Template(f.read()).substitute(secret_key=$env.secret_key, akismet_api_key = env.akismet_api_key, | |
db_default_user=env.mysqluser, db_default_password=env.mysqlpassword, | |
db_default_host='localhost',db_default_port='3306') | |
with open(real_file, 'w') as f: | |
f.write(json) | |
put(real_file, '/home/{0}/djangoproject.jp/environments.json'.format(env.user)) | |
local('rm -f {0}'.format(real_file)) | |
def managepy(cmd): | |
""" | |
Helper: run a management command remotely. | |
""" | |
with prefix('source ~/envs/djangoproject.jp/bin/activate'): | |
with cd('~/djangoproject.jp'): | |
run('python manage.py {0}'.format(cmd)) | |
def syncdb(): | |
""" | |
Run syncdb. | |
""" | |
managepy('syncdb') | |
def base_deploy(sshport): | |
""" | |
Base deploy: secure login, firewall, disable unnecessaly searvicies. | |
""" | |
change_ssh_port(sshport) | |
upload_ssh_key() | |
restrict_ssh() | |
setup_ufw_rules(sshport) | |
disable_services() | |
sudo('reboot') | |
def full_deploy(): | |
""" | |
Full deploy: new code, update dependencies, migrate, and restart services. | |
""" | |
install_packages() | |
deploy_code() | |
setup_environments() | |
update_virtualenv('djangoproject.jp', ['MySQL-python'], '~/djangoproject.jp/requirement.txt') | |
deploy_doc('1.0') | |
setup_mysql() | |
syncdb() | |
setup_gunicorn() | |
setup_nginx() |
This file contains hidden or 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
upstream djangoja-website { | |
server 127.0.0.1:5000; | |
} | |
server { | |
listen 80; | |
server_name localhost; | |
access_log /var/log/nginx/localhost.access.log; | |
error_log /var/log/nginx/localhost.error.log debug; | |
location ^~ /doc/ja/1.0 { | |
alias /home/{{ username }}/doc/1.0/_build/html; | |
index index.html; | |
break; | |
} | |
location ^~ /m { | |
alias /home/{{ username }}/djangoproject.jp/media; | |
break; | |
} | |
location / { | |
if (!-f $request_filename){ | |
proxy_pass http://djangoja-website; | |
break; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment