2
0
mirror of https://github.com/frappe/bench.git synced 2025-01-10 00:37:51 +00:00

Merge branch 'master' into minor

This commit is contained in:
Ameya Shenoy 2018-04-11 13:23:58 +05:30 committed by GitHub
commit 2ff1dabf2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
159 changed files with 2330 additions and 2074 deletions

143
.gitignore vendored
View File

@ -1,8 +1,139 @@
*.pyc
*.py~
*.swp
# MAC OS
.DS_Store
build/
dist/
*.egg-info/
# Vim Gitignore
## Swap
[._]*.s[a-v][a-z]
[._]*.sw[a-p]
[._]s[a-v][a-z]
[._]sw[a-p]
## Session
Session.vim
## Temporary
.netrwhist
*~
## Auto-generated tag files
tags
# Python Gitignore
## Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
## C extensions
*.so
## Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
## PyInstaller
## Usually these files are written by a python script from a template
## before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
## Installer logs
pip-log.txt
pip-delete-this-directory.txt
## Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
## Translations
*.mo
*.pot
## Django stuff:
*.log
.static_storage/
.media/
local_settings.py
## Flask stuff:
instance/
.webassets-cache
## Scrapy stuff:
.scrapy
## Sphinx documentation
docs/_build/
## PyBuilder
target/
## Jupyter Notebook
.ipynb_checkpoints
## pyenv
.python-version
## celery beat schedule file
celerybeat-schedule
## SageMath parsed files
*.sage.py
## Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
## Spyder project settings
.spyderproject
.spyproject
## Rope project settings
.ropeproject
## mkdocs documentation
/site
## mypy
.mypy_cache/
# Packer Gitignore
## Cache objects
packer_cache/
*.checksum
## For built virtualmachines
*.ova
*.iso
## For built boxes
*.box

View File

@ -7,6 +7,7 @@ python:
- "2.7"
install:
- sudo rm /etc/apt/sources.list.d/mongodb*.list
- sudo rm /etc/apt/sources.list.d/docker.list
- sudo pip install urllib3 pyOpenSSL ndg-httpsclient pyasn1
- sudo apt-get purge -y mysql-common mysql-server mysql-client

View File

@ -3,3 +3,5 @@ include *.py
recursive-include bench *.conf
recursive-include bench *.py
recursive-include bench *.txt
recursive-include bench *.json
recursive-include bench/templates *

View File

@ -1,8 +1,12 @@
# Bench
<div align="center">
<img src="https://github.com/frappe/design/blob/master/logos/bench-logo.svg" height="128">
<h2>Frappe Bench</h2>
</div>
[![Build Status](https://travis-ci.org/frappe/bench.svg?branch=master)](https://travis-ci.org/frappe/bench)
The bench is a command-line utility that helps you to install apps, manage multiple sites and update Frappe / ERPNext apps on */nix (CentOS 6, Debian 7, Ubuntu, etc) for development and production. Bench will also create nginx and supervisor config files, setup backups and much more.
The bench is a command-line utility that helps you to install apps, manage multiple sites and update Frappe / ERPNext apps on */nix (CentOS, Debian, Ubuntu, etc) for development and production. Bench will also create nginx and supervisor config files, setup backups and much more.
If you are using on a VPS make sure it has >= 1Gb of RAM or has swap setup properly.
@ -12,26 +16,40 @@ If you have questions, please ask them on the [forum](https://discuss.erpnext.co
## Installation
## Manual Install
### Installation Requirements
To manually install frappe/erpnext here are the steps
You will need a computer/server. Options include:
- A Normal Computer/VPS/Baremetal Server: This is strongly recommended. Frappe/ERPNext installs properly and works well on these
- A Raspberry Pi, SAN Appliance, Network Router, Gaming Console, etc.: Although you may be able to install Frappe/ERPNext on specialized hardware, it is unlikely to work well and will be difficult for us to support. Strongly consider using a normal computer/VPS/baremetal server instead. **We do not support specialized hardware**.
- A Toaster, Car, Firearm, Thermostat, etc.: Yes, many modern devices now have embedded computing capability. We live in interesting times. However, you should not install Frappe/ERPNext on these devices. Instead, install it on a normal computer/VPS/baremetal server. **We do not support installing on noncomputing devices**.
To install the Frappe/ERPNext server software, you will need an operating system on your normal computer which is not Windows. Note that the command line interface does work on Windows, and you can use Frappe/ERPNext from any operating system with a web browser. However, the server software does not run on Windows. It does run on other operating systems, so choose one of these instead:
- Linux: Debian, Ubuntu, CentOS are the preferred distros and are well tested. [Arch Linux](https://github.com/frappe/bench/wiki/Install-ERPNext-on-ArchLinux) can also be used
- Mac OS X
### Manual Install
To manually install frappe/erpnext, you can follow this [this wiki](https://github.com/frappe/frappe/wiki/The-Hitchhiker's-Guide-to-Installing-Frapp%C3%A9-on-Linux-OS) for Linux and [this wiki](https://github.com/frappe/frappe/wiki/The-Hitchhiker's-Guide-to-Installing-Frapp%C3%A9-on-Mac-OS-X) for MacOS. It gives an excellent explanation about the stack. You can also follow the steps mentioned below:
#### 1. Install Pre-requisites
- Python 2.7
- Python 2.7 [Python3.5+ also supported, but not recommended for production]
- MariaDB 10+
- Nginx (for production)
- Nodejs
- yarn
- Redis
- cron (crontab is required)
- wkhtmltopdf with patched Qt (for pdf generation)
- wkhtmltopdf with patched Qt (version 0.12.3) (for pdf generation)
#### 2. Install Bench
Install bench as a *non root* user,
git clone https://github.com/frappe/bench bench-repo
sudo pip install -e bench-repo
pip install --user -e bench-repo
Note: Please do not remove the bench directory the above commands will create
@ -80,11 +98,12 @@ Note: Please do not remove the bench directory the above commands will create
## Easy Install
- This is an opinionated setup so it is best to setup on a blank server.
- Works on Ubuntu 14.04 to 16.04, CentOS 7+, Debian 7 to 8 and MacOS X.
- Works on Ubuntu 16.04, CentOS 7+, Debian 8+
- You may have to install Python 2.7 (eg on Ubuntu 16.04+) by running `apt-get install python-minimal`
- You may also have to install build-essential and python-setuptools by running `apt-get install build-essential python-setuptools`
- This script will install the pre-requisites, install bench and setup an ERPNext site
- Passwords for Frappe Administrator and MariaDB (root) will be asked
- MariaDB (root) password may be `password` on a fresh server
- You can then login as **Administrator** with the Administrator password
- If you find any problems, post them on the forum: [https://discuss.erpnext.com](https://discuss.erpnext.com)
@ -96,16 +115,6 @@ For Linux:
wget https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py
For Mac OSX:
Install X Code (from App store) and HomeBrew (http://brew.sh/) first
brew install python
brew install git
Download the Script
curl "https://raw.githubusercontent.com/frappe/bench/master/playbooks/install.py" -o install.py
#### 2. Run the install script
@ -126,12 +135,12 @@ For production:
- Install all the pre-requisites
- Install the command line `bench`
- Create a new bench (a folder that will contain your entire frappe/erpnext setup)
- Create a new site on the bench
- Create a new ERPNext site on the bench
#### How do I start ERPNext
1. For development: Go to your bench folder (`frappe-bench` by default) and start the bench with `bench start`
2. For production: Your process will be setup and managed by `nginx` and `supervisor`. [Setup Production](https://frappe.github.io/frappe/user/en/bench/guides/setup-production.html)
2. For production: Your process will be setup and managed by `nginx` and `supervisor`. [Setup Production](https://frappe.io/docs/user/en/bench/guides/setup-production.html)
---
@ -169,19 +178,19 @@ You can also run the parts of the bench selectively.
Guides
=======
- [Configuring HTTPS](https://frappe.github.io/frappe/user/en/bench/guides/configuring-https.html)
- [Using Let's Encrypt to setup HTTPS](https://frappe.github.io/frappe/user/en/bench/guides/lets-encrypt-ssl-setup.html)
- [Diagnosing the Scheduler](https://frappe.github.io/frappe/user/en/bench/guides/diagnosing-the-scheduler.html)
- [Change Hostname](https://frappe.github.io/frappe/user/en/bench/guides/adding-custom-domains)
- [Manual Setup](https://frappe.github.io/frappe/user/en/bench/guides/manual-setup.html)
- [Setup Production](https://frappe.github.io/frappe/user/en/bench/guides/setup-production.html)
- [Setup Multitenancy](https://frappe.github.io/frappe/user/en/bench/guides/setup-multitenancy.html)
- [Configuring HTTPS](https://frappe.io/docs/user/en/bench/guides/configuring-https.html)
- [Using Let's Encrypt to setup HTTPS](https://frappe.io/docs/user/en/bench/guides/lets-encrypt-ssl-setup.html)
- [Diagnosing the Scheduler](https://frappe.io/docs/user/en/bench/guides/diagnosing-the-scheduler.html)
- [Change Hostname](https://frappe.io/docs/user/en/bench/guides/adding-custom-domains)
- [Manual Setup](https://frappe.io/docs/user/en/bench/guides/manual-setup.html)
- [Setup Production](https://frappe.io/docs/user/en/bench/guides/setup-production.html)
- [Setup Multitenancy](https://frappe.io/docs/user/en/bench/guides/setup-multitenancy.html)
- [Stopping Production](https://github.com/frappe/bench/wiki/Stopping-Production-and-starting-Development)
Resources
=======
- [Background Services](https://frappe.github.io/frappe/user/en/bench/resources/background-services.html)
- [Bench Commands Cheat Sheet](https://frappe.github.io/frappe/user/en/bench/resources/bench-commands-cheatsheet.html)
- [Bench Procfile](https://frappe.github.io/frappe/user/en/bench/resources/bench-procfile.html)
- [Background Services](https://frappe.io/docs/user/en/bench/resources/background-services.html)
- [Bench Commands Cheat Sheet](https://frappe.io/docs/user/en/bench/resources/bench-commands-cheatsheet.html)
- [Bench Procfile](https://frappe.io/docs/user/en/bench/resources/bench-procfile.html)

View File

@ -10,4 +10,4 @@ def set_frappe_version(bench_path='.'):
from .app import get_current_frappe_version
global FRAPPE_VERSION
if not FRAPPE_VERSION:
FRAPPE_VERSION = get_current_frappe_version(bench_path=bench_path)
FRAPPE_VERSION = get_current_frappe_version(bench_path=bench_path)

View File

@ -48,10 +48,40 @@ def write_appstxt(apps, bench_path='.'):
with open(os.path.join(bench_path, 'sites', 'apps.txt'), 'w') as f:
return f.write('\n'.join(apps))
def check_url(url, raise_err = True):
try:
from urlparse import urlparse
except ImportError:
from urllib.parse import urlparse
parsed = urlparse(url)
if not parsed.scheme:
if raise_err:
raise TypeError('{url} Not a valid URL'.format(url = url))
else:
return False
return True
def get_app(git_url, branch=None, bench_path='.', build_asset_files=True, verbose=False):
#less verbose app install
if '/' not in git_url:
git_url = 'https://github.com/frappe/' + git_url
# from bench.utils import check_url
try:
from urlparse import urljoin
except ImportError:
from urllib.parse import urljoin
if not check_url(git_url, raise_err = False):
orgs = ['frappe', 'erpnext']
for org in orgs:
url = 'https://api.github.com/repos/{org}/{app}'.format(org = org, app = git_url)
res = requests.get(url)
if res.ok:
data = res.json()
if 'name' in data:
if git_url == data['name']:
git_url = 'https://github.com/{org}/{app}'.format(org = org, app = git_url)
break
#Gets repo name from URL
repo_name = git_url.rsplit('/', 1)[1].rsplit('.', 1)[0]
logger.info('getting app {}'.format(repo_name))
@ -142,6 +172,7 @@ def pull_all_apps(bench_path='.', reset=False):
app_dir = get_repo_dir(app, bench_path=bench_path)
if os.path.exists(os.path.join(app_dir, '.git')):
out = subprocess.check_output(["git", "status"], cwd=app_dir)
out = out.decode('utf-8')
if not re.search(r'nothing to commit, working (directory|tree) clean', out):
print('''
@ -184,7 +215,7 @@ def is_version_upgrade(app='frappe', bench_path='.', branch=None):
local_version = get_major_version(get_current_version(app, bench_path=bench_path))
upstream_version = get_major_version(upstream_version)
if upstream_version - local_version > 0:
return (True, local_version, upstream_version)
@ -204,6 +235,7 @@ def get_remote(app, bench_path='.'):
repo_dir = get_repo_dir(app, bench_path=bench_path)
contents = subprocess.check_output(['git', 'remote', '-v'], cwd=repo_dir,
stderr=subprocess.STDOUT)
contents = contents.decode('utf-8')
if re.findall('upstream[\s]+', contents):
remote = 'upstream'
else:
@ -232,14 +264,20 @@ def get_current_version(app, bench_path='.'):
with open(os.path.join(repo_dir, 'setup.py')) as f:
return get_version_from_string(f.read(), field='version')
def get_develop_version(app, bench_path='.'):
repo_dir = get_repo_dir(app, bench_path=bench_path)
with open(os.path.join(repo_dir, os.path.basename(repo_dir), 'hooks.py')) as f:
return get_version_from_string(f.read(), field='develop_version')
def get_upstream_version(app, branch=None, bench_path='.'):
repo_dir = get_repo_dir(app, bench_path=bench_path)
if not branch:
branch = get_current_branch(app, bench_path=bench_path)
try:
contents = subprocess.check_output(['git', 'show', 'upstream/{branch}:{app}/__init__.py'.format(branch=branch, app=app)], cwd=repo_dir, stderr=subprocess.STDOUT)
contents = contents.decode('utf-8')
except subprocess.CalledProcessError as e:
if "Invalid object" in e.output:
if b"Invalid object" in e.output:
return None
else:
raise
@ -253,7 +291,7 @@ def get_repo_dir(app, bench_path='.'):
return os.path.join(bench_path, 'apps', app)
def switch_branch(branch, apps=None, bench_path='.', upgrade=False, check_upgrade=True):
from .utils import update_requirements, update_npm_packages, backup_all_sites, patch_sites, build_assets, pre_upgrade, post_upgrade
from .utils import update_requirements, update_node_packages, backup_all_sites, patch_sites, build_assets, pre_upgrade, post_upgrade
from . import utils
apps_dir = os.path.join(bench_path, 'apps')
version_upgrade = (False,)
@ -293,7 +331,7 @@ def switch_branch(branch, apps=None, bench_path='.', upgrade=False, check_upgrad
if version_upgrade[0] and upgrade:
update_requirements()
update_npm_packages()
update_node_packages()
pre_upgrade(version_upgrade[1], version_upgrade[2])
reload(utils)
backup_all_sites()
@ -304,10 +342,10 @@ def switch_branch(branch, apps=None, bench_path='.', upgrade=False, check_upgrad
def switch_to_branch(branch=None, apps=None, bench_path='.', upgrade=False):
switch_branch(branch, apps=apps, bench_path=bench_path, upgrade=upgrade)
def switch_to_master(apps=None, bench_path='.', upgrade=False):
def switch_to_master(apps=None, bench_path='.', upgrade=True):
switch_branch('master', apps=apps, bench_path=bench_path, upgrade=upgrade)
def switch_to_develop(apps=None, bench_path='.', upgrade=False):
def switch_to_develop(apps=None, bench_path='.', upgrade=True):
switch_branch('develop', apps=apps, bench_path=bench_path, upgrade=upgrade)
def get_version_from_string(contents, field='__version__'):

View File

@ -47,10 +47,12 @@ def check_uid():
sys.exit(1)
def cmd_requires_root():
if len(sys.argv) > 2 and sys.argv[2] in ('production', 'sudoers', 'lets-encrypt', 'fonts', 'reload-nginx', 'firewall', 'ssh-port'):
return True
if len(sys.argv) >= 2 and sys.argv[1] in ('patch', 'renew-lets-encrypt', 'disable-production'):
return True
if len(sys.argv) > 2 and sys.argv[2] in ('production', 'sudoers', 'lets-encrypt', 'fonts',
'print', 'firewall', 'ssh-port', 'role', 'fail2ban'):
return True
if len(sys.argv) >= 2 and sys.argv[1] in ('patch', 'renew-lets-encrypt', 'disable-production',
'install'):
return True
def change_dir():
if os.path.exists('config.json') or "init" in sys.argv:
@ -93,7 +95,9 @@ def get_frappe_commands(bench_path='.'):
if not os.path.exists(sites_path):
return []
try:
return json.loads(get_cmd_output("{python} -m frappe.utils.bench_helper get-frappe-commands".format(python=python), cwd=sites_path))
output = get_cmd_output("{python} -m frappe.utils.bench_helper get-frappe-commands".format(python=python), cwd=sites_path)
# output = output.decode('utf-8')
return json.loads(output)
except subprocess.CalledProcessError:
return []

View File

@ -1,5 +1,16 @@
import click
import os, shutil
import os.path as osp
import logging
from datetime import datetime
from bench.utils import which, exec_cmd
log = logging.getLogger(__name__)
log.setLevel(logging.DEBUG)
def print_bench_version(ctx, param, value):
"""Prints current bench version"""
if not value or ctx.resilient_parsing:
@ -14,7 +25,6 @@ def print_bench_version(ctx, param, value):
def bench_command(bench_path='.'):
"""Bench manager for Frappe"""
import bench
from bench.app import get_current_frappe_version
from bench.utils import setup_logging
bench.set_frappe_version(bench_path=bench_path)
@ -67,3 +77,107 @@ from bench.commands.git import remote_set_url, remote_reset_url, remote_urls
bench_command.add_command(remote_set_url)
bench_command.add_command(remote_reset_url)
bench_command.add_command(remote_urls)
from bench.commands.install import install
bench_command.add_command(install)
from bench.config.common_site_config import get_config
try:
from urlparse import urlparse
except ImportError:
from urllib.parse import urlparse
@click.command('migrate-env')
@click.argument('python', type = str)
@click.option('--no-backup', default = False, help = 'Do not backup the existing Virtual Environment')
def migrate_env(python, no_backup = False):
"""
Migrate Virtual Environment to desired Python Version.
"""
try:
# Clear Cache before Bench Dies.
config = get_config(bench_path = os.getcwd())
rredis = urlparse(config['redis_cache'])
redis = '{redis} -p {port}'.format(
redis = which('redis-cli'),
port = rredis.port
)
log.debug('Clearing Redis Cache...')
exec_cmd('{redis} FLUSHALL'.format(redis = redis))
log.debug('Clearing Redis DataBase...')
exec_cmd('{redis} FLUSHDB'.format(redis = redis))
except Exception:
log.warn('Please ensure Redis Connections are running or Daemonized.')
try:
# This is with the assumption that a bench is set-up within path.
path = os.getcwd()
# I know, bad name for a flag. Thanks, Ameya! :| - <achilles@frappe.io>
if not no_backup:
# Back, the f*ck up.
parch = osp.join(path, 'archived_envs')
if not osp.exists(parch):
os.mkdir(parch)
# Simply moving. Thanks, Ameya.
# I'm keen to zip.
source = osp.join(path, 'env')
target = parch
log.debug('Backing up Virtual Environment')
stamp = datetime.now().strftime('%Y%m%d_%H%M%S')
dest = osp.join(path, str(stamp))
# WARNING: This is an archive, you might have to use virtualenv --relocate
# That's because virtualenv creates symlinks with shebangs pointing to executables.
# shebangs, shebangs - ricky martin.
# ...and shutil.copytree is a f*cking mess.
os.rename(source, dest)
shutil.move(dest, target)
log.debug('Setting up a New Virtual {python} Environment'.format(
python = python
))
# Path to Python Executable (Basically $PYTHONPTH)
python = which(python)
virtualenv = which('virtualenv')
nvenv = 'env'
pvenv = osp.join(path, nvenv)
exec_cmd('{virtualenv} --python {python} {pvenv}'.format(
virtualenv = virtualenv,
python = python,
pvenv = pvenv
), cwd = path)
pip = osp.join(pvenv, 'bin', 'pip')
exec_cmd('{pip} install --upgrade pip'.format(pip=pip))
exec_cmd('{pip} install --upgrade setuptools'.format(pip=pip))
# TODO: Options
papps = osp.join(path, 'apps')
apps = ['frappe', 'erpnext'] + [app for app in os.listdir(papps) if app not in ['frappe', 'erpnext']]
for app in apps:
papp = osp.join(papps, app)
if osp.isdir(papp) and osp.exists(osp.join(papp, 'setup.py')):
exec_cmd('{pip} install -e {app}'.format(
pip = pip, app = papp
))
log.debug('Migration Successful to {python}'.format(
python = python
))
except:
log.debug('Migration Error')
raise
bench_command.add_command(migrate_env)

74
bench/commands/install.py Normal file
View File

@ -0,0 +1,74 @@
import os, sys, json, click
from bench.utils import run_playbook, setup_sudoers, is_root
extra_vars = {"production": True}
@click.group()
def install():
"Install system dependancies"
pass
@click.command('prerequisites')
def install_prerequisites():
run_playbook('site.yml', tag='common, redis')
@click.command('mariadb')
@click.option('--mysql_root_password')
def install_maridb(mysql_root_password=''):
if mysql_root_password:
extra_vars.update({"mysql_root_password": mysql_root_password})
run_playbook('site.yml', extra_vars=extra_vars, tag='mariadb')
@click.command('wkhtmltopdf')
def install_wkhtmltopdf():
run_playbook('site.yml', extra_vars=extra_vars, tag='wkhtmltopdf')
@click.command('nodejs')
def install_nodejs():
run_playbook('site.yml', extra_vars=extra_vars, tag='nodejs')
@click.command('psutil')
def install_psutil():
run_playbook('site.yml', extra_vars=extra_vars, tag='psutil')
@click.command('supervisor')
@click.option('--user')
def install_supervisor(user=None):
run_playbook('site.yml', extra_vars=extra_vars, tag='supervisor')
if user:
setup_sudoers(user)
@click.command('nginx')
@click.option('--user')
def install_nginx(user=None):
run_playbook('site.yml', extra_vars=extra_vars, tag='nginx')
if user:
setup_sudoers(user)
@click.command('virtualbox')
def install_virtualbox():
run_playbook('vm_build.yml', tag='virtualbox')
@click.command('packer')
def install_packer():
run_playbook('vm_build.yml', tag='packer')
@click.command('fail2ban')
@click.option('--maxretry', default=6, help="Number of matches (i.e. value of the counter) which triggers ban action on the IP.")
@click.option('--bantime', default=600, help="The counter is set to zero if no match is found within 'findtime' seconds.")
@click.option('--findtime', default=600, help='Duration (in seconds) for IP to be banned for. Negative number for "permanent" ban.')
def install_failtoban(**kwargs):
extra_vars.update(kwargs)
run_playbook('site.yml', extra_vars=extra_vars, tag='fail2ban')
install.add_command(install_prerequisites)
install.add_command(install_maridb)
install.add_command(install_wkhtmltopdf)
install.add_command(install_nodejs)
install.add_command(install_psutil)
install.add_command(install_supervisor)
install.add_command(install_nginx)
install.add_command(install_failtoban)
install.add_command(install_virtualbox)
install.add_command(install_packer)

View File

@ -2,6 +2,8 @@ import click
@click.command()
@click.argument('path')
@click.option('--python', type = str, default = 'python', help = 'Path to Python Executable.')
@click.option('--ignore-exist', is_flag = True, default = False, help = "Ignore if Bench instance exists.")
@click.option('--apps_path', default=None, help="path to json files with apps to install after init")
@click.option('--frappe-path', default=None, help="path to frappe repo")
@click.option('--frappe-branch', default=None, help="path to frappe repo")
@ -9,19 +11,23 @@ import click
@click.option('--no-procfile', is_flag=True, help="Pull changes in all the apps in bench")
@click.option('--no-backups',is_flag=True, help="Run migrations for all sites in the bench")
@click.option('--no-auto-update',is_flag=True, help="Build JS and CSS artifacts for the bench")
@click.option('--verbose',is_flag=True, help="Verbose output during install")
@click.option('--skip-bench-mkdir', is_flag=True, help="Skip mkdir frappe-bench")
@click.option('--skip-redis-config-generation', is_flag=True, help="Skip redis config generation if already specifying the common-site-config file")
@click.option('--verbose',is_flag=True, help="Verbose output during install")
def init(path, apps_path, frappe_path, frappe_branch, no_procfile, no_backups,
no_auto_update, clone_from, verbose, skip_bench_mkdir, skip_redis_config_generation):
"Create a new bench"
no_auto_update, clone_from, verbose, skip_redis_config_generation,
ignore_exist = False,
python = 'python'): # Let's change we're ready. - <achilles@frappe.io>
'''
Create a New Bench Instance.
'''
from bench.utils import init
init(path, apps_path=apps_path, no_procfile=no_procfile, no_backups=no_backups,
no_auto_update=no_auto_update, frappe_path=frappe_path, frappe_branch=frappe_branch,
verbose=verbose, clone_from=clone_from, skip_bench_mkdir=skip_bench_mkdir, skip_redis_config_generation=skip_redis_config_generation)
verbose=verbose, clone_from=clone_from, skip_redis_config_generation=skip_redis_config_generation,
ignore_exist = ignore_exist,
python = python)
click.echo('Bench {} initialized'.format(path))
@click.command('get-app')
@click.argument('name', nargs=-1) # Dummy argument for backward compatibility
@click.argument('git-url')

View File

@ -1,3 +1,4 @@
from bench.utils import exec_cmd
import click, sys, json
@click.group()
@ -5,7 +6,6 @@ def setup():
"Setup bench"
pass
@click.command('sudoers')
@click.argument('user')
def setup_sudoers(user):
@ -13,7 +13,6 @@ def setup_sudoers(user):
from bench.utils import setup_sudoers
setup_sudoers(user)
@click.command('nginx')
@click.option('--yes', help='Yes to regeneration of nginx config file', default=False, is_flag=True)
def setup_nginx(yes=False):
@ -47,13 +46,19 @@ def setup_fonts():
from bench.utils import setup_fonts
setup_fonts()
@click.command('production')
@click.option('--yes', is_flag=True, default=False, help='Dont prompt for confirmation')
@click.argument('user')
@click.option('--yes', help='Yes to regeneration config', is_flag=True, default=False)
def setup_production(user, yes=False):
"setup bench for production"
from bench.config.production_setup import setup_production
from bench.utils import run_playbook
# Install prereqs for production
exec_cmd("sudo pip install ansible")
exec_cmd("bench setup role fail2ban")
exec_cmd("bench setup role nginx")
exec_cmd("bench setup role supervisor")
setup_production(user=user, yes=yes)
@ -71,30 +76,42 @@ def setup_backups():
setup_backups()
@click.command('env')
def setup_env():
@click.option('--python', type = str, default = 'python', help = 'Path to Python Executable.')
def setup_env(python='python'):
"Setup virtualenv for bench"
from bench.utils import setup_env
setup_env()
setup_env(python=python)
@click.command('firewall')
def setup_firewall():
@click.option('--ssh_port')
@click.option('--force')
def setup_firewall(ssh_port=None, force=False):
"Setup firewall"
from bench.utils import run_playbook
click.confirm('Setting up the firewall will block all ports except 80, 443 and 22\n'
'Do you want to continue?',
abort=True)
run_playbook('production/setup_firewall.yml')
if not force:
click.confirm('Setting up the firewall will block all ports except 80, 443 and 22\n'
'Do you want to continue?',
abort=True)
if not ssh_port:
ssh_port = 22
run_playbook('roles/bench/tasks/setup_firewall.yml', {"ssh_port": ssh_port})
@click.command('ssh-port')
@click.argument('port')
def set_ssh_port(port):
@click.option('--force')
def set_ssh_port(port, force=False):
"Set SSH Port"
from bench.utils import run_playbook
click.confirm('This will change your SSH Port to {}\n'
'Do you want to continue?'.format(port),
abort=True)
run_playbook('production/change_ssh_port.yml', {"ssh_port": port})
if not force:
click.confirm('This will change your SSH Port to {}\n'
'Do you want to continue?'.format(port),
abort=True)
run_playbook('roles/bench/tasks/change_ssh_port.yml', {"ssh_port": port})
@click.command('lets-encrypt')
@click.argument('site')
@ -118,12 +135,24 @@ def setup_socketio():
from bench.utils import setup_socketio
setup_socketio()
@click.command('requirements')
def setup_requirements():
@click.command('requirements', help="Update Python and Node packages")
@click.option('--node', help="Update only Node packages", default=False, is_flag=True)
@click.option('--python', help="Update only Python packages", default=False, is_flag=True)
def setup_requirements(node=False, python=False):
"Setup python and node requirements"
from bench.utils import update_requirements, update_npm_packages
if not node:
setup_python_requirements()
if not python:
setup_node_requirements()
def setup_python_requirements():
from bench.utils import update_requirements
update_requirements()
update_npm_packages()
def setup_node_requirements():
from bench.utils import update_node_packages
update_node_packages()
@click.command('config')
def setup_config():
@ -181,6 +210,30 @@ def sync_domains(domain=None, site=None):
# if changed, success, else failure
sys.exit(0 if changed else 1)
@click.command('role')
@click.argument('role')
@click.option('--admin_emails', default='')
@click.option('--mysql_root_password')
def setup_roles(role, **kwargs):
"Install dependancies via roles"
from bench.utils import run_playbook
extra_vars = {"production": True}
extra_vars.update(kwargs)
if role:
run_playbook('site.yml', extra_vars=extra_vars, tag=role)
else:
run_playbook('site.yml', extra_vars=extra_vars)
@click.command('fail2ban')
@click.option('--maxretry', default=6, help="Number of matches (i.e. value of the counter) which triggers ban action on the IP. Default is 6 seconds" )
@click.option('--bantime', default=600, help="The counter is set to zero if no match is found within 'findtime' seconds. Default is 600 seconds")
@click.option('--findtime', default=600, help='Duration (in seconds) for IP to be banned for. Negative number for "permanent" ban. Default is 600 seconds')
def setup_nginx_proxy_jail(**kwargs):
from bench.utils import run_playbook
run_playbook('roles/fail2ban/tasks/configure_nginx_jail.yml', extra_vars=kwargs)
setup.add_command(setup_sudoers)
setup.add_command(setup_nginx)
setup.add_command(reload_nginx)
@ -201,3 +254,5 @@ setup.add_command(remove_domain)
setup.add_command(sync_domains)
setup.add_command(setup_firewall)
setup.add_command(set_ssh_port)
setup.add_command(setup_roles)
setup.add_command(setup_nginx_proxy_jail)

View File

@ -3,7 +3,7 @@ import sys, os
from bench.config.common_site_config import get_config
from bench.app import pull_all_apps, is_version_upgrade
from bench.utils import (update_bench, validate_upgrade, pre_upgrade, post_upgrade, before_update,
update_requirements, update_npm_packages, backup_all_sites, patch_sites, build_assets, restart_supervisor_processes)
update_requirements, update_node_packages, backup_all_sites, patch_sites, build_assets, restart_supervisor_processes)
from bench import patches
#TODO: Not DRY
@ -15,11 +15,10 @@ from bench import patches
@click.option('--requirements',is_flag=True, help="Update requirements")
@click.option('--restart-supervisor',is_flag=True, help="restart supervisor processes after update")
@click.option('--auto',is_flag=True)
@click.option('--upgrade',is_flag=True, help="Required for major version updates")
@click.option('--no-backup',is_flag=True)
@click.option('--force',is_flag=True)
@click.option('--reset', is_flag=True, help="Hard resets git branch's to their new states overriding any changes and overriding rebase on pull")
def update(pull=False, patch=False, build=False, bench=False, auto=False, restart_supervisor=False, requirements=False, no_backup=False, upgrade=False, force=False, reset=False):
def update(pull=False, patch=False, build=False, bench=False, auto=False, restart_supervisor=False, requirements=False, no_backup=False, force=False, reset=False):
"Update bench"
if not (pull or patch or build or bench or requirements):
@ -40,7 +39,6 @@ def update(pull=False, patch=False, build=False, bench=False, auto=False, restar
'requirements': requirements,
'no-backup': no_backup,
'restart-supervisor': restart_supervisor,
'upgrade': upgrade,
'reset':reset
})
@ -50,27 +48,21 @@ def update(pull=False, patch=False, build=False, bench=False, auto=False, restar
version_upgrade = is_version_upgrade()
if version_upgrade[0] and not upgrade:
if version_upgrade[0]:
print()
print()
print("This update will cause a major version change in Frappe/ERPNext from {0} to {1}.".format(*version_upgrade[1:]))
print("This would take significant time to migrate and might break custom apps. Please run `bench update --upgrade` to confirm.")
print()
print("You can stay on the latest stable release by running `bench switch-to-master` or pin your bench to {0} by running `bench switch-to-v{0}`".format(version_upgrade[1]))
sys.exit(1)
_update(pull, patch, build, bench, auto, restart_supervisor, requirements, no_backup, upgrade, force=force, reset=reset)
print("This would take significant time to migrate and might break custom apps.")
click.confirm('Do you want to continue?', abort=True)
_update(pull, patch, build, bench, auto, restart_supervisor, requirements, no_backup, force=force, reset=reset)
def _update(pull=False, patch=False, build=False, update_bench=False, auto=False, restart_supervisor=False,
requirements=False, no_backup=False, upgrade=False, bench_path='.', force=False, reset=False):
requirements=False, no_backup=False, bench_path='.', force=False, reset=False):
conf = get_config(bench_path=bench_path)
version_upgrade = is_version_upgrade(bench_path=bench_path)
if version_upgrade[0] and not upgrade:
raise Exception("Major Version Upgrade")
if upgrade and (version_upgrade[0] or (not version_upgrade[0] and force)):
if version_upgrade[0] or (not version_upgrade[0] and force):
validate_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path)
before_update(bench_path=bench_path, requirements=requirements)
@ -80,9 +72,9 @@ def _update(pull=False, patch=False, build=False, update_bench=False, auto=False
if requirements:
update_requirements(bench_path=bench_path)
update_npm_packages(bench_path=bench_path)
update_node_packages(bench_path=bench_path)
if upgrade and (version_upgrade[0] or (not version_upgrade[0] and force)):
if version_upgrade[0] or (not version_upgrade[0] and force):
pre_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path)
import bench.utils, bench.app
print('Reloading bench...')
@ -98,7 +90,7 @@ def _update(pull=False, patch=False, build=False, update_bench=False, auto=False
patch_sites(bench_path=bench_path)
if build:
build_assets(bench_path=bench_path)
if upgrade and (version_upgrade[0] or (not version_upgrade[0] and force)):
if version_upgrade[0] or (not version_upgrade[0] and force):
post_upgrade(version_upgrade[1], version_upgrade[2], bench_path=bench_path)
if restart_supervisor or conf.get('restart_supervisor_on_update'):
restart_supervisor_processes(bench_path=bench_path)
@ -108,7 +100,6 @@ def _update(pull=False, patch=False, build=False, update_bench=False, auto=False
print("Open source depends on your contributions, so please contribute bug reports, patches, fixes or cash and be a part of the community")
print()
@click.command('retry-upgrade')
@click.option('--version', default=5)
def retry_upgrade(version):
@ -117,12 +108,10 @@ def retry_upgrade(version):
build_assets()
post_upgrade(version-1, version)
def restart_update(kwargs):
args = ['--'+k for k, v in list(kwargs.items()) if v]
os.execv(sys.argv[0], sys.argv[:2] + args)
@click.command('switch-to-branch')
@click.argument('branch')
@click.argument('apps', nargs=-1)
@ -134,26 +123,20 @@ def switch_to_branch(branch, apps, upgrade=False):
print('Switched to ' + branch)
print('Please run `bench update --patch` to be safe from any differences in database schema')
@click.command('switch-to-master')
@click.option('--upgrade',is_flag=True)
def switch_to_master(upgrade=False):
def switch_to_master():
"Switch frappe and erpnext to master branch"
from bench.app import switch_to_master
switch_to_master(upgrade=upgrade, apps=['frappe', 'erpnext'])
switch_to_master(apps=['frappe', 'erpnext'])
print()
print('Switched to master')
print('Please run `bench update --patch` to be safe from any differences in database schema')
@click.command('switch-to-develop')
@click.option('--upgrade',is_flag=True)
def switch_to_develop(upgrade=False):
"Switch frappe and erpnext to develop branch"
from bench.app import switch_to_develop
switch_to_develop(upgrade=upgrade, apps=['frappe', 'erpnext'])
switch_to_develop(apps=['frappe', 'erpnext'])
print()
print('Switched to develop')
print('Please run `bench update --patch` to be safe from any differences in database schema')

View File

@ -13,7 +13,8 @@ def setup_procfile(bench_path, yes=False):
procfile = bench.env.get_template('Procfile').render(
node=find_executable("node") or find_executable("nodejs"),
use_rq=use_rq(bench_path),
webserver_port=config.get('webserver_port'))
webserver_port=config.get('webserver_port'),
CI=os.environ.get('CI'))
with open(procfile_path, 'w') as f:
f.write(procfile)

View File

@ -56,8 +56,8 @@ def write_redis_config(template_name, context, bench_path):
f.write(template.render(**context))
def get_redis_version():
version_string = subprocess.check_output('redis-server --version', shell=True).strip()
version_string = subprocess.check_output('redis-server --version', shell=True)
version_string = version_string.decode('utf-8').strip()
# extract version number from string
version = re.findall("\d+\.\d+", version_string)
if not version:

View File

@ -4,12 +4,14 @@ redis_queue: redis-server config/redis_queue.conf
web: bench serve {% if webserver_port -%} --port {{ webserver_port }} {%- endif %}
socketio: {{ node }} apps/frappe/socketio.js
{% if not CI %}
watch: bench watch
{% endif %}
{% if use_rq -%}
schedule: bench schedule
worker_short: bench worker --queue short
worker_long: bench worker --queue long
worker_default: bench worker --queue default
worker_short: bench worker --queue short --quiet
worker_long: bench worker --queue long --quiet
worker_default: bench worker --queue default --quiet
{% else %}
workerbeat: sh -c 'cd sites && exec ../env/bin/python -m frappe.celery_app beat -s scheduler.schedule'
worker: sh -c 'cd sites && exec ../env/bin/python -m frappe.celery_app worker -n jobs@%h -Ofair --soft-time-limit 360 --time-limit 390'

View File

@ -17,4 +17,3 @@ text = True
# Uncomment to use the standalone authenticator on port 443
authenticator = standalone
standalone-supported-challenges = tls-sni-01

View File

@ -1,18 +0,0 @@
{
"name": "frappe",
"description": "Default package.json for frappe apps",
"dependencies": {
"babel-core": "^6.24.1",
"babel-preset-babili": "0.0.12",
"babel-preset-es2015": "^6.24.1",
"babel-preset-es2016": "^6.24.1",
"babel-preset-es2017": "^6.24.1",
"chokidar": "^1.7.0",
"cookie": "^0.3.1",
"express": "^4.15.3",
"less": "^2.7.2",
"redis": "^2.7.1",
"socket.io": "^2.0.1",
"superagent": "^3.5.2"
}
}

View File

@ -3,4 +3,4 @@ bench.patches.v3.celery_to_rq
bench.patches.v3.redis_bind_ip
bench.patches.v4.update_node
bench.patches.v4.update_socketio
bench.patches.v4.install_yarn #2

View File

@ -0,0 +1,5 @@
import os
from bench.utils import exec_cmd
def execute(bench_path):
exec_cmd('npm install yarn', os.path.join(bench_path, 'apps/frappe'))

View File

@ -24,6 +24,7 @@ github_password = None
def release(bench_path, app, bump_type, from_branch='develop', to_branch='master',
remote='upstream', owner='frappe', repo_name=None):
confirm_testing()
config = get_config(bench_path)
if not config.get('release_bench'):
@ -53,10 +54,20 @@ def validate(bench_path, config):
r = requests.get('https://api.github.com/user', auth=HTTPBasicAuth(github_username, github_password))
r.raise_for_status()
def confirm_testing():
print('')
print('================ CAUTION ==================')
print('Never miss this, even if it is a really small release!!')
print('Manual Testing Checklisk: https://github.com/frappe/bench/wiki/Testing-Checklist')
print('')
print('')
click.confirm('Is manual testing done?', abort = True)
def bump(bench_path, app, bump_type, from_branch, to_branch, remote, owner, repo_name=None):
assert bump_type in ['minor', 'major', 'patch', 'stable', 'prerelease']
repo_path = os.path.join(bench_path, 'apps', app)
push_branch_for_old_major_version(bench_path, bump_type, app, repo_path, from_branch, to_branch, remote, owner)
update_branches_and_check_for_changelog(repo_path, from_branch, to_branch, remote=remote)
message = get_release_message(repo_path, from_branch=from_branch, to_branch=to_branch, remote=remote)
@ -299,3 +310,24 @@ def create_github_release(repo_path, tag_name, message, remote='upstream', owner
raise
return r
def push_branch_for_old_major_version(bench_path, bump_type, app, repo_path, from_branch, to_branch, remote, owner):
if bump_type != 'major':
return
current_version = get_current_version(repo_path)
old_major_version_branch = "v{major}.x.x".format(major=current_version.split('.')[0])
click.confirm('Do you want to push {branch}?'.format(branch=old_major_version_branch), abort=True)
update_branch(repo_path, to_branch, remote=remote)
g = git.Repo(repo_path).git
g.checkout(b=old_major_version_branch)
args = [
'{old_major_version_branch}:{old_major_version_branch}'.format(old_major_version_branch=old_major_version_branch),
]
print("Pushing {old_major_version_branch} ".format(old_major_version_branch=old_major_version_branch))
print(g.push(remote, *args))

View File

@ -212,7 +212,9 @@ class TestBenchInit(unittest.TestCase):
self.assert_exists(python_path, "site-packages", "pip")
site_packages = os.listdir(os.path.join(python_path, "site-packages"))
self.assertTrue(any(package.startswith("mysqlclient-1.3.10") for package in site_packages))
# removing test case temporarily
# as develop and master branch havin differnt version of mysqlclient
#self.assertTrue(any(package.startswith("mysqlclient-1.3.12") for package in site_packages))
def assert_config(self, bench_name):
for config, search_key in (

View File

@ -1,6 +1,7 @@
import os, sys, shutil, subprocess, logging, itertools, requests, json, platform, select, pwd, grp, multiprocessing, hashlib
from distutils.spawn import find_executable
import bench
import semantic_version
from bench import env
from six import iteritems
@ -15,6 +16,13 @@ logger = logging.getLogger(__name__)
folders_in_bench = ('apps', 'sites', 'config', 'logs', 'config/pids')
def safe_decode(string, encoding = 'utf-8'):
try:
string = string.decode(encoding)
except Exception:
pass
return string
def get_frappe(bench_path='.'):
frappe = get_env_cmd('frappe', bench_path=bench_path)
if not os.path.exists(frappe):
@ -27,31 +35,33 @@ def get_env_cmd(cmd, bench_path='.'):
def init(path, apps_path=None, no_procfile=False, no_backups=False,
no_auto_update=False, frappe_path=None, frappe_branch=None, wheel_cache_dir=None,
verbose=False, clone_from=None, skip_bench_mkdir=False, skip_redis_config_generation=False):
verbose=False, clone_from=None, skip_redis_config_generation=False,
ignore_exist = False,
python = 'python'): # Let's change when we're ready. - <achilles@frappe.io>
from .app import get_app, install_apps_from_path
from .config.common_site_config import make_config
from .config import redis
from .config.procfile import setup_procfile
from bench.patches import set_all_patches_executed
if(skip_bench_mkdir):
pass
import os.path as osp
if osp.exists(path):
if not ignore_exist:
raise ValueError('Bench Instance {path} already exists.'.format(path = path))
else:
if os.path.exists(path):
print('Directory {} already exists!'.format(path))
raise Exception("Site directory already exists")
os.makedirs(path)
for dirname in folders_in_bench:
try:
os.makedirs(os.path.join(path, dirname))
except OSError, e:
except OSError as e:
if e.errno != os.errno.EEXIST:
pass
setup_logging()
setup_env(bench_path=path)
setup_env(bench_path=path, python = python)
make_config(path)
@ -69,7 +79,7 @@ def init(path, apps_path=None, no_procfile=False, no_backups=False,
bench.set_frappe_version(bench_path=path)
if bench.FRAPPE_VERSION > 5:
update_npm_packages(bench_path=path)
update_node_packages(bench_path=path)
set_all_patches_executed(bench_path=path)
build_assets(bench_path=path)
@ -89,8 +99,10 @@ def clone_apps_from(bench_path, clone_from):
print('Copying apps from {0}...'.format(clone_from))
subprocess.check_output(['cp', '-R', os.path.join(clone_from, 'apps'), bench_path])
print('Copying node_modules from {0}...'.format(clone_from))
subprocess.check_output(['cp', '-R', os.path.join(clone_from, 'node_modules'), bench_path])
node_modules_path = os.path.join(clone_from, 'node_modules')
if os.path.exists(node_modules_path):
print('Copying node_modules from {0}...'.format(clone_from))
subprocess.check_output(['cp', '-R', node_modules_path, bench_path])
def setup_app(app):
# run git reset --hard in each branch, pull latest updates and install_app
@ -139,8 +151,21 @@ def exec_cmd(cmd, cwd='.'):
if return_code > 0:
raise CommandFailedError(cmd)
def setup_env(bench_path='.'):
exec_cmd('virtualenv -q {} -p {}'.format('env', sys.executable), cwd=bench_path)
def which(executable, raise_err = False):
from distutils.spawn import find_executable
exec_ = find_executable(executable)
if not exec_ and raise_err:
raise ValueError('{executable} not found.'.format(
executable = executable
))
return exec_
def setup_env(bench_path='.', python = 'python'):
python = which(python, raise_err = True)
exec_cmd('virtualenv -q {} -p {}'.format('env', python), cwd=bench_path)
exec_cmd('./env/bin/pip -q install --upgrade pip', cwd=bench_path)
exec_cmd('./env/bin/pip -q install wheel', cwd=bench_path)
# exec_cmd('./env/bin/pip -q install https://github.com/frappe/MySQLdb1/archive/MySQLdb-1.2.5-patched.tar.gz', cwd=bench_path)
@ -203,13 +228,14 @@ def setup_backups(bench_path='.'):
def add_to_crontab(line):
current_crontab = read_crontab()
line = str.encode(line)
if not line in current_crontab:
cmd = ["crontab"]
if platform.system() == 'FreeBSD':
cmd = ["crontab", "-"]
s = subprocess.Popen(cmd, stdin=subprocess.PIPE)
s.stdin.write(current_crontab)
s.stdin.write(line + '\n')
s.stdin.write(line + b'\n')
s.stdin.close()
def read_crontab():
@ -251,9 +277,10 @@ def setup_sudoers(user):
'nginx': find_executable('nginx'),
'bench': find_executable('bench')
})
frappe_sudoers = safe_decode(frappe_sudoers)
with open(sudoers_file, 'w') as f:
f.write(frappe_sudoers.encode('utf-8'))
f.write(frappe_sudoers)
os.chmod(sudoers_file, 0o440)
@ -302,7 +329,9 @@ def check_cmd(cmd, cwd='.'):
def get_git_version():
'''returns git version from `git --version`
extracts version number from string `get version 1.9.1` etc'''
version = get_cmd_output("git --version").strip().split()[2]
version = get_cmd_output("git --version")
version = safe_decode(version)
version = version.strip().split()[2]
version = '.'.join(version.split('.')[0:2])
return float(version)
@ -323,12 +352,22 @@ def check_git_for_shallow_clone():
def get_cmd_output(cmd, cwd='.'):
try:
return subprocess.check_output(cmd, cwd=cwd, shell=True, stderr=open(os.devnull, 'wb')).strip()
output = subprocess.check_output(cmd, cwd=cwd, shell=True, stderr=open(os.devnull, 'wb')).strip()
output = output.decode('utf-8')
return output
except subprocess.CalledProcessError as e:
if e.output:
print(e.output)
raise
def safe_encode(what, encoding = 'utf-8'):
try:
what = what.encode(encoding)
except Exception:
pass
return what
def restart_supervisor_processes(bench_path='.', web_workers=False):
from .config.common_site_config import get_config
conf = get_config(bench_path=bench_path)
@ -340,7 +379,8 @@ def restart_supervisor_processes(bench_path='.', web_workers=False):
else:
supervisor_status = subprocess.check_output(['sudo', 'supervisorctl', 'status'], cwd=bench_path)
supervisor_status = safe_decode(supervisor_status)
if web_workers and '{bench_name}-web:'.format(bench_name=bench_name) in supervisor_status:
group = '{bench_name}-web: '.format(bench_name=bench_name)
@ -380,8 +420,35 @@ def update_requirements(bench_path='.'):
req_file = os.path.join(apps_dir, app, 'requirements.txt')
install_requirements(pip, req_file)
def update_node_packages(bench_path='.'):
print('Updating node packages...')
from bench.app import get_develop_version
from distutils.version import LooseVersion
v = LooseVersion(get_develop_version('frappe', bench_path = bench_path))
# After rollup was merged, frappe_version = 10.1
# if develop_verion is 11 and up, only then install yarn
if v < LooseVersion('11.x.x-develop'):
update_npm_packages(bench_path)
else:
update_yarn_packages(bench_path)
def update_yarn_packages(bench_path='.'):
apps_dir = os.path.join(bench_path, 'apps')
if not find_executable('yarn'):
print("Please install yarn using below command and try again.")
print("`npm install -g yarn`")
return
for app in os.listdir(apps_dir):
app_path = os.path.join(apps_dir, app)
if os.path.exists(os.path.join(app_path, 'package.json')):
exec_cmd('yarn install', cwd=app_path)
def update_npm_packages(bench_path='.'):
print('Updating node libraries...')
apps_dir = os.path.join(bench_path, 'apps')
package_json = {}
@ -412,6 +479,7 @@ def update_npm_packages(bench_path='.'):
exec_cmd('npm install', cwd=bench_path)
def install_requirements(pip, req_file):
if os.path.exists(req_file):
exec_cmd("{pip} install -q -r {req_file}".format(pip=pip, req_file=req_file))
@ -732,11 +800,16 @@ def set_git_remote_url(git_url, bench_path='.'):
if os.path.exists(os.path.join(app_dir, '.git')):
exec_cmd("git remote set-url upstream {}".format(git_url), cwd=app_dir)
def run_playbook(playbook_name, extra_vars=None):
def run_playbook(playbook_name, extra_vars=None, tag=None):
if not find_executable('ansible'):
print("Ansible is needed to run this command, please install it using 'pip install ansible'")
sys.exit(1)
args = ['ansible-playbook', '-c', 'local', playbook_name]
if extra_vars:
args.extend(['-e', json.dumps(extra_vars)])
if tag:
args.extend(['-t', tag])
subprocess.check_call(args, cwd=os.path.join(os.path.dirname(bench.__path__[0]), 'playbooks'))

View File

@ -36,4 +36,6 @@ Usage: bench release [OPTIONS] APP BUMP_TYPE
* --to-branch git master branch, default is master
* --remote git remote, default is upstream
* --owner git owner, default is frappe
* --repo-name git repo name if different from app name
* --repo-name git repo name if different from app name
* When updating major version, update `develop_version` in hooks.py, e.g. `9.x.x-develop`

View File

@ -1,483 +0,0 @@
#!/bin/bash
set -e
## Utils
print_msg() {
echo "Frappe password: $FRAPPE_USER_PASS"
echo "MariaDB root password: $MSQ_PASS"
echo "Administrator password: $ADMIN_PASS"
}
get_passwd() {
echo `cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1`
}
set_opts () {
OPTS=`getopt -o v --long verbose,mysql-root-password:,frappe-user:,bench-branch:,setup-production,skip-install-bench,skip-setup-bench,help -n 'parse-options' -- "$@"`
if [ $? != 0 ] ; then echo "Failed parsing options." >&2 ; exit 1 ; fi
eval set -- "$OPTS"
VERBOSE=false
HELP=false
FRAPPE_USER=false
BENCH_BRANCH="master"
SETUP_PROD=false
INSTALL_BENCH=true
SETUP_BENCH=true
if [ -f ~/frappe_passwords.sh ]; then
source ~/frappe_passwords.sh
else
FRAPPE_USER_PASS=`get_passwd`
MSQ_PASS=`get_passwd`
ADMIN_PASS=`get_passwd`
echo "FRAPPE_USER_PASS=$FRAPPE_USER_PASS" > ~/frappe_passwords.sh
echo "MSQ_PASS=$MSQ_PASS" >> ~/frappe_passwords.sh
echo "ADMIN_PASS=$ADMIN_PASS" >> ~/frappe_passwords.sh
fi
while true; do
case "$1" in
-v | --verbose ) VERBOSE=true; shift ;;
-h | --help ) HELP=true; shift ;;
--mysql-root-password ) MSQ_PASS="$2"; shift; shift ;;
--frappe-user ) FRAPPE_USER="$2"; shift; shift ;;
--setup-production ) SETUP_PROD=true; shift;;
--bench-branch ) BENCH_BRANCH="$2"; shift;;
--skip-setup-bench ) SETUP_BENCH=false; shift;;
--skip-install-bench ) INSTALL_BENCH=false; shift;;
-- ) shift; break ;;
* ) break ;;
esac
done
}
get_distro() {
ARCH=$(uname -m | sed 's/x86_/amd/;s/i[3-6]86/x86/')
if [ $ARCH == "amd64" ]; then
T_ARCH="x86_64"
WK_ARCH="amd64"
else
T_ARCH="i386"
WK_ARCH="i386"
fi
if [ -f /etc/redhat-release ]; then
OS="centos"
OS_VER=`cat /etc/redhat-release | sed 's/Linux\ //g' | cut -d" " -f3 | cut -d. -f1`
elif [ -f /etc/lsb-release ]; then
. /etc/lsb-release
OS=$DISTRIB_ID
OS_VER=$DISTRIB_CODENAME
elif [ -f /etc/debian_version ]; then
. /etc/os-release
OS="debian" # XXX or Ubuntu??
OS_VER=$VERSION_ID
fi
export OS=$OS
export OS_VER=$OS_VER
export ARCH=$ARCH
export T_ARCH=$T_ARCH
export WK_ARCH=$WK_ARCH
echo Installing for $OS $OS_VER $ARCH
echo "In case you encounter an error, you can post on https://discuss.frappe.io"
echo
}
run_cmd() {
if $VERBOSE; then
"$@"
else
# $@
"$@" > /tmp/cmdoutput.txt 2>&1 || (cat /tmp/cmdoutput.txt && exit 1)
fi
}
## add repos
add_centos6_mariadb_repo() {
echo "
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.0/centos$OS_VER-$ARCH
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
" > /etc/yum.repos.d/mariadb.repo
}
add_ubuntu_mariadb_repo() {
run_cmd sudo apt-get update
run_cmd sudo apt-get install -y software-properties-common python-software-properties
run_cmd sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xcbcb082a1bb943db
run_cmd sudo add-apt-repository "deb http://ams2.mirrors.digitalocean.com/mariadb/repo/10.0/ubuntu $OS_VER main"
}
add_debian_mariadb_repo() {
if [ $OS_VER == "7" ]; then
CODENAME="wheezy"
elif [ $OS_VER == "6" ]; then
CODENAME="squeeze"
elif [ $OS_VER == "8" ]; then
CODENAME="jessie"
else
echo Unsupported Debian Version
exit 1
fi
run_cmd sudo apt-get update
run_cmd sudo apt-get install -y software-properties-common python-software-properties
run_cmd sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xcbcb082a1bb943db
$repo_test=$(apt-cache search --names-only 'mariadb-server')
if [ -z "$repo_test" ]; then
run_cmd sudo add-apt-repository "deb http://ams2.mirrors.digitalocean.com/mariadb/repo/10.0/debian $CODENAME main"
fi
}
add_ius_repo() {
if [ $OS_VER -eq "6" ]; then
wget http://dl.iuscommunity.org/pub/ius/stable/CentOS/$OS_VER/$T_ARCH/epel-release-6-5.noarch.rpm
wget http://dl.iuscommunity.org/pub/ius/stable/CentOS/$OS_VER/$T_ARCH/ius-release-1.0-14.ius.centos6.noarch.rpm
rpm --quiet -q epel-release || rpm -Uvh epel-release-6-5.noarch.rpm
rpm --quiet -q ius-release || rpm -Uvh ius-release-1.0-14.ius.centos6.noarch.rpm
fi
}
add_epel_centos7() {
yum install -y epel-release
}
add_maria_db_repo() {
if [ "$OS" == "Ubuntu" ] && [ $OS_VER == "utopic" ]; then
return
elif [ "$OS" == "centos" ]; then
echo Adding centos mariadb repo
add_centos6_mariadb_repo
elif [ "$OS" == "debian" ]; then
echo Adding debian mariadb repo
add_debian_mariadb_repo
elif [ "$OS" == "Ubuntu" ]; then
echo Adding ubuntu mariadb repo
add_ubuntu_mariadb_repo
else
echo Unsupported Distribution
exit 1
fi
}
## install
install_packages() {
if [ $OS == "centos" ]; then
run_cmd sudo yum install wget -y
run_cmd sudo yum groupinstall -y "Development tools"
if [ $OS_VER == "6" ]; then
run_cmd add_ius_repo
run_cmd sudo yum install -y git MariaDB-server MariaDB-client MariaDB-compat python-setuptools nginx \
zlib-devel bzip2-devel openssl-devel postfix python27-devel python27 \
libxml2 libxml2-devel libxslt libxslt-devel redis MariaDB-devel libXrender libXext \
python27-setuptools cronie sudo which xorg-x11-fonts-Type1 xorg-x11-fonts-75dpi nodejs npm \
libtiff-devel libjpeg-devel libzip-devel freetype-devel lcms2-devel libwebp-devel tcl-devel tk-devel
elif [ $OS_VER == "7" ]; then
run_cmd add_epel_centos7
run_cmd sudo yum install -y git mariadb-server mariadb-devel python-setuptools nginx \
zlib-devel bzip2-devel openssl-devel postfix python-devel \
libxml2 libxml2-devel libxslt libxslt-devel redis libXrender libXext \
supervisor cronie sudo which xorg-x11-fonts-75dpi xorg-x11-fonts-Type1 nodejs npm \
libtiff-devel libjpeg-devel libzip-devel freetype-devel lcms2-devel libwebp-devel tcl-devel tk-devel
fi
echo "Installing wkhtmltopdf"
install_wkhtmltopdf_centos
run_cmd easy_install-2.7 -U pip
elif [ $OS == "debian" ] || [ $OS == "Ubuntu" ]; then
export DEBIAN_FRONTEND=noninteractive
setup_debconf
run_cmd bash -c "curl -sL https://deb.nodesource.com/setup_0.12 | sudo bash -"
run_cmd sudo apt-get update
run_cmd sudo apt-get install -y python-dev python-setuptools build-essential python-mysqldb git \
ntp vim screen htop mariadb-server mariadb-common libmariadbclient-dev \
libxslt1.1 libxslt1-dev redis-server libssl-dev libcrypto++-dev postfix nginx \
supervisor python-pip fontconfig libxrender1 libxext6 xfonts-75dpi xfonts-base nodejs
if [ $OS_VER == "precise" ]; then
run_cmd sudo apt-get install -y libtiff4-dev libjpeg8-dev zlib1g-dev libfreetype6-dev \
liblcms2-dev libwebp-dev tcl8.5-dev tk8.5-dev python-tk
elif [ $OS_VER == "8" ]; then
run_cmd sudo apt-get install -y libtiff5-dev libjpeg62-turbo-dev zlib1g-dev libfreetype6-dev \
liblcms2-dev libwebp-dev tcl8.5-dev tk8.5-dev python-tk npm
else
run_cmd sudo apt-get install -y libtiff5-dev libjpeg8-dev zlib1g-dev libfreetype6-dev \
liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python-tk
fi
echo "Installing wkhtmltopdf"
install_wkhtmltopdf_deb
else
echo Unsupported Distribution
exit 1
fi
}
install_wkhtmltopdf_centos () {
if [[ $OS == "centos" && $OS_VER == "7" && $T_ARCH == "i386" ]]; then
echo "Cannot install wkhtmltodpdf. Skipping..."
return 0
fi
RPM="wkhtmltox-0.12.2.1_linux-$OS$OS_VER-$WK_ARCH.rpm"
run_cmd wget http://download.gna.org/wkhtmltopdf/0.12/0.12.2.1/$RPM
rpm --quiet -q wkhtmltox || run_cmd rpm -Uvh $RPM
}
install_wkhtmltopdf_deb () {
WK_VER=$OS_VER
if [[ $OS_VER == "utopic" || $OS_VER == "vivid" || $OS_VER == "wily" ]]; then
echo "Installing wkhtmltox package for trusty (Ubuntu 14.4) even if you are using $OS_VER."
WK_VER="trusty"
fi
if [[ $OS == "debian" && $OS_VER == "7" ]]; then
WK_VER="wheezy"
elif [[ $OS == "debian" && $OS_VER == "8" ]]; then
WK_VER="jessie"
fi
run_cmd wget http://download.gna.org/wkhtmltopdf/0.12/0.12.2.1/wkhtmltox-0.12.2.1_linux-$WK_VER-$WK_ARCH.deb
run_cmd dpkg -i wkhtmltox-0.12.2.1_linux-$WK_VER-$WK_ARCH.deb
}
install_supervisor_centos6() {
run_cmd easy_install supervisor
curl -Ss https://raw.githubusercontent.com/pdvyas/supervisor-initscripts/master/redhat-init-jkoppe > /etc/init.d/supervisord
curl -Ss https://raw.githubusercontent.com/pdvyas/supervisor-initscripts/master/redhat-sysconfig-jkoppe > /etc/sysconfig/supervisord
curl -Ss https://raw.githubusercontent.com/pdvyas/supervisor-initscripts/master/supervisord.conf > /etc/supervisord.conf
run_cmd mkdir /etc/supervisor.d
run_cmd chmod +x /etc/init.d/supervisord
bash -c "service supervisord start || true"
}
### config
get_mariadb_password() {
get_password "MariaDB root" MSQ_PASS
}
get_site_admin_password() {
get_password "Admin password" ADMIN_PASS
}
get_password() {
if [ -z "$2" ]; then
read -t 1 -n 10000 discard || true
echo
read -p "Enter $1 password to set:" -s TMP_PASS1
echo
read -p "Re enter $1 password to set:" -s TMP_PASS2
echo
if [ $TMP_PASS1 == $TMP_PASS2 ]; then
export $2=$TMP_PASS1
else
echo Passwords do not match
get_password $1 $2
fi
fi
}
configure_mariadb_centos() {
# Required only for CentOS, Ubuntu and Debian will show dpkg configure screen to set the password
if [ $OS == "centos" ]; then
mysqladmin -u root password $MSQ_PASS
fi
}
start_services_centos6() {
run_cmd service nginx start
run_cmd service mysql start
run_cmd service redis start
}
configure_services_centos6() {
run_cmd chkconfig --add supervisord
run_cmd chkconfig redis on
run_cmd chkconfig mysql on
run_cmd chkconfig nginx on
run_cmd chkconfig supervisord on
}
configure_services_centos7() {
run_cmd systemctl enable nginx
run_cmd systemctl enable mysql
run_cmd systemctl enable redis
run_cmd systemctl enable supervisord
}
start_services_centos7() {
run_cmd systemctl start nginx
run_cmd systemctl start mysql
run_cmd systemctl start redis
run_cmd systemctl start supervisord
}
configure_mariadb() {
config="
[mysqld]
innodb-file-format=barracuda
innodb-file-per-table=1
innodb-large-prefix=1
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
[mysql]
default-character-set = utf8mb4
"
deb_cnf_path="/etc/mysql/conf.d/barracuda.cnf"
centos_cnf_path="/etc/my.cnf.d/barracuda.cnf"
if [ $OS == "centos" ]; then
echo "$config" > $centos_cnf_path
if [ $OS_VER == "6" ]; then
run_cmd sudo service mysql restart
elif [ $OS_VER == "7" ]; then
run_cmd sudo systemctl restart mysql
fi
elif [ $OS == "debian" ] || [ $OS == "Ubuntu" ]; then
echo "$config" > $deb_cnf_path
sudo service mysql restart
fi
}
setup_debconf() {
debconf-set-selections <<< "postfix postfix/mailname string `hostname`"
debconf-set-selections <<< "postfix postfix/main_mailer_type string 'Internet Site'"
debconf-set-selections <<< "mariadb-server-5.5 mysql-server/root_password password $MSQ_PASS"
debconf-set-selections <<< "mariadb-server-5.5 mysql-server/root_password_again password $MSQ_PASS"
}
install_bench() {
run_cmd sudo su $FRAPPE_USER -c "cd /home/$FRAPPE_USER && git clone https://github.com/frappe/bench --branch $BENCH_BRANCH bench-repo"
if hash pip-2.7 &> /dev/null; then
PIP="pip-2.7"
elif hash pip2.7 &> /dev/null; then
PIP="pip2.7"
elif hash pip2 &> /dev/null; then
PIP="pip2"
elif hash pip &> /dev/null; then
PIP="pip"
else
echo PIP not installed
exit 1
fi
run_cmd sudo $PIP install --upgrade pip
run_cmd sudo $PIP install -e /home/$FRAPPE_USER/bench-repo
}
setup_bench() {
echo Installing frappe-bench
FRAPPE_BRANCH="develop"
ERPNEXT_APPS_JSON="https://raw.githubusercontent.com/frappe/bench/master/install_scripts/erpnext-apps.json"
if $SETUP_PROD; then
FRAPPE_BRANCH="master"
ERPNEXT_APPS_JSON="https://raw.githubusercontent.com/frappe/bench/master/install_scripts/erpnext-apps-master.json"
fi
run_cmd sudo su $FRAPPE_USER -c "cd /home/$FRAPPE_USER && bench init frappe-bench --frappe-branch $FRAPPE_BRANCH --apps_path $ERPNEXT_APPS_JSON"
echo Setting up first site
echo /home/$FRAPPE_USER/frappe-bench > /etc/frappe_bench_dir
run_cmd sudo su $FRAPPE_USER -c "cd /home/$FRAPPE_USER/frappe-bench && bench new-site site1.local --mariadb-root-password $MSQ_PASS --admin-password $ADMIN_PASS"
run_cmd sudo su $FRAPPE_USER -c "cd /home/$FRAPPE_USER/frappe-bench && bench install-app erpnext"
run_cmd bash -c "cd /home/$FRAPPE_USER/frappe-bench && bench setup sudoers $FRAPPE_USER"
if $SETUP_PROD; then
run_cmd bash -c "cd /home/$FRAPPE_USER/frappe-bench && bench setup production $FRAPPE_USER"
fi
chown $FRAPPE_USER /home/$FRAPPE_USER/frappe-bench/logs/*
}
add_user() {
# Check if script is running as root and is not running as sudo. We want to skip
# this step if the user is already running this script with sudo as a non root
# user
if [ "$FRAPPE_USER" == "false" ]; then
if [[ $SUDO_UID -eq 0 ]] && [[ $EUID -eq 0 ]]; then
export FRAPPE_USER="frappe"
else
export FRAPPE_USER="$SUDO_USER"
fi
fi
USER_EXISTS=`bash -c "id $FRAPPE_USER > /dev/null 2>&1 && echo true || (echo false && exit 0)"`
if [ $USER_EXISTS == "false" ]; then
useradd -m -d /home/$FRAPPE_USER -s $SHELL $FRAPPE_USER
echo $FRAPPE_USER:$FRAPPE_USER_PASS | chpasswd
chmod o+x /home/$FRAPPE_USER
chmod o+r /home/$FRAPPE_USER
fi
}
main() {
set_opts $@
get_distro
add_maria_db_repo
echo Installing packages for $OS\. This might take time...
install_packages
if [ $OS == "centos" ]; then
if [ $OS_VER == "6" ]; then
echo "Installing supervisor"
install_supervisor_centos6
echo "Configuring CentOS services"
configure_services_centos6
echo "Starting services"
start_services_centos6
elif [ $OS_VER == "7" ]; then
echo "Configuring CentOS services"
configure_services_centos7
echo "Starting services"
start_services_centos7
fi
configure_mariadb_centos
fi
configure_mariadb
echo "Adding frappe user"
add_user
if $INSTALL_BENCH; then
install_bench
if $SETUP_BENCH; then
setup_bench
fi
fi
echo
RUNNING=""
if $SETUP_PROD; then
RUNNING=" and is running on port 80"
fi
echo "Frappe/ERPNext is installed successfully$RUNNING."
print_msg > ~/frappe_passwords.txt
print_msg
echo
echo "The passwords are also stored at ~/frappe_passwords.txt"
echo "You can remove this file after making a note of the passwords."
}
main $@

1
patches.txt Normal file
View File

@ -0,0 +1 @@
bench.patches.v3.deprecate_old_config

10
playbooks/README.md Normal file
View File

@ -0,0 +1,10 @@
# Deploying a, developer/production-ready ERPNext website with Ansible
## Supported Platforms
- Debian 8, 9
- Ubuntu 14.04, 16.04
- CentOS 7
## Notes for maintainers
- For MariaDB playbooks refer https://github.com/PCextreme/ansible-role-mariadb
- Any changes made in relation to a role should be dont inside the role and not outside it

View File

View File

@ -1,4 +1,5 @@
---
- hosts: localhost
tasks:
- name: Create user
@ -30,4 +31,8 @@
owner: '{{ frappe_user }}'
group: '{{ frappe_user }}'
recurse: yes
when: ansible_distribution == 'Ubuntu' or ansible_distribution == 'CentOS' or ansible_distribution == 'Debian'
when: ansible_distribution == 'Ubuntu' or ansible_distribution == 'CentOS' or ansible_distribution == 'Debian'
- name: Change default shell to bash
shell: "chsh {{ frappe_user }} -s $(which bash)"
...

View File

@ -1,86 +0,0 @@
---
- hosts: localhost
vars:
bench_repo_path: "/home/{{ ansible_user_id }}/.bench"
bench_path: "/home/{{ ansible_user_id }}/frappe-bench"
mysql_config_template: "templates/simple_mariadb_config.cnf"
mysql_conf_dir: /etc/my.cnf.d/
tasks:
- name: development tools package
yum: name="@Development tools" state=present
become: yes
become_user: root
- name: install prequisites
yum: pkg={{ item }} state=present
with_items:
# basic installs
- redis
# for mariadb
- libselinux-python
- mysql-devel
- mysql-libs
# for wkhtmltopdf
- libXrender
- libXext
- xorg-x11-fonts-75dpi
- xorg-x11-fonts-Type1
# for Pillow
- libjpeg-devel
- zlib-devel
- libzip-devel
- freetype-devel
- lcms2-devel
- libwebp-devel
- libtiff-devel
- tcl-devel
- tk-devel
# Python LDAP
- openldap-devel
become: yes
become_user: root
- name: Import Node source RPM key
rpm_key:
key: https://rpm.nodesource.com/pub/el/NODESOURCE-GPG-SIGNING-KEY-EL
state: present
become: yes
become_user: root
- name: Add Node Repo
yum:
name: 'https://rpm.nodesource.com/pub_6.x/el/{{ ansible_distribution_major_version }}/{{ ansible_architecture }}/nodesource-release-el{{ ansible_distribution_major_version }}-1.noarch.rpm'
state: present
become: yes
become_user: root
- name: Install nodejs
yum:
name: nodejs
state: present
become: yes
become_user: root
# install MariaDB
- include: includes/mariadb_centos.yml
# install WKHTMLtoPDF
- include: includes/wkhtmltopdf.yml
# setup MariaDB
- include: includes/setup_mariadb.yml
# setup frappe-bench
- include: includes/setup_bench.yml
when: not run_travis and not without_bench_setup
# setup development environment
- include: includes/setup_dev_env.yml
when: not run_travis and not production

View File

@ -1,126 +0,0 @@
---
- hosts: localhost
vars:
bench_repo_path: "/home/{{ ansible_user_id }}/.bench"
bench_path: "/home/{{ ansible_user_id }}/frappe-bench"
mysql_config_template: "templates/simple_mariadb_config.cnf"
mysql_conf_dir: /etc/mysql/conf.d/
tasks:
- name: Add dotdeb apt repository key for Debian < 8
apt_key:
url: http://www.dotdeb.org/dotdeb.gpg
state: present
become: yes
become_user: root
when: ansible_distribution == 'Debian' and ansible_distribution_version | version_compare('8', 'lt')
- name: Add dotdeb apt repository for redis-server for Debian < 8
apt_repository:
repo: 'deb http://packages.dotdeb.org wheezy all'
state: present
become: yes
become_user: root
when: ansible_distribution == 'Debian' and ansible_distribution_version | version_compare('8', 'lt')
# install pre-requisites
- name: install prequisites
apt: pkg={{ item }} state=present
with_items:
# basic installs
- build-essential
- redis-server
# for mariadb
- software-properties-common
# for wkhtmltopdf
- libxrender1
- libxext6
- xfonts-75dpi
- xfonts-base
# for Pillow
- zlib1g-dev
- libfreetype6-dev
- liblcms2-dev
- libwebp-dev
- python-tk
# Ensure apt-transport-https
- apt-transport-https
# Python LDAP
- libsasl2-dev
- libldap2-dev
become: yes
become_user: root
- name: install pillow prerequisites for Debian < 8
apt: pkg={{ item }} state=present
with_items:
- libjpeg8-dev
- libtiff4-dev
- tcl8.5-dev
- tk8.5-dev
when: ansible_distribution_version | version_compare('8', 'lt')
become: yes
become_user: root
- name: install pillow prerequisites for Debian >= 8
apt: pkg={{ item }} state=present
with_items:
- libjpeg62-turbo-dev
- libtiff5-dev
- tcl8.5-dev
- tk8.5-dev
when: ansible_distribution_version | version_compare('8', 'ge')
become: yes
become_user: root
- name: Add apt key for node repo
apt_key:
url: https://keyserver.ubuntu.com/pks/lookup?op=get&fingerprint=on&search=0x1655A0AB68576280
id: "68576280"
state: present
become: yes
become_user: root
- name: Add repo
apt_repository:
repo: "deb [arch=amd64,i386] https://deb.nodesource.com/node_6.x {{ ansible_distribution_release }} main"
state: present
update_cache: yes
become: yes
become_user: root
- name: Install nodejs 6.x
apt:
name: nodejs
state: present
update_cache: yes
force: yes
become: yes
become_user: root
# install MariaDB
- include: includes/mariadb_debian.yml
# install WKHTMLtoPDF
- include: includes/wkhtmltopdf.yml
# setup MariaDB
- include: includes/setup_mariadb.yml
- debug:
var: run_travis
# setup frappe-bench
- include: includes/setup_bench.yml
when: not run_travis
# setup development environment
- include: includes/setup_dev_env.yml
when: not production and not run_travis

View File

@ -1,13 +0,0 @@
---
- name: Add repository
template: src=templates/mariadb_centos.repo dest=/etc/yum.repos.d/MariaDB.repo owner=root mode=0644
become: yes
become_user: root
- name: Install MariaDB
yum: pkg={{ item }} state=present
with_items:
- MariaDB-server
- MariaDB-client
become: yes
become_user: root

View File

@ -1,27 +0,0 @@
---
- name: Add apt key for mariadb for Debian <= 8
apt_key: keyserver=hkp://keyserver.ubuntu.com:80 id=0xcbcb082a1bb943db state=present
become: yes
become_user: root
when: ansible_distribution_major_version | version_compare('8', 'le')
- name: Add apt repository
apt_repository:
repo: 'deb [arch=amd64,i386] http://nyc2.mirrors.digitalocean.com/mariadb/repo/10.1/debian {{ ansible_distribution_release }} main'
state: present
become: yes
become_user: root
- name: Unattended package installation
shell: export DEBIAN_FRONTEND=noninteractive
- name: apt-get install
apt: pkg={{ item }} update_cache=yes state=present
with_items:
- mariadb-server
- mariadb-client
- mariadb-common
- libmariadbclient-dev
become: yes
become_user: root

View File

@ -1,32 +0,0 @@
---
- name: Add apt key for mariadb for Ubuntu < 16.04
apt_key: keyserver=hkp://keyserver.ubuntu.com:80 id=0xcbcb082a1bb943db state=present
become: yes
become_user: root
when: ansible_distribution_version | version_compare('16.04', 'lt')
- name: Add apt key for mariadb for Ubuntu >= 16.04
apt_key: keyserver=hkp://keyserver.ubuntu.com:80 id=0xF1656F24C74CD1D8 state=present
become: yes
become_user: root
when: ansible_distribution_version | version_compare('16.04', 'ge')
- name: Add apt repository
apt_repository:
repo: 'deb [arch=amd64,i386] http://nyc2.mirrors.digitalocean.com/mariadb/repo/10.1/ubuntu {{ ansible_distribution_release }} main'
state: present
become: yes
become_user: root
- name: Unattended package installation
shell: export DEBIAN_FRONTEND=noninteractive
- name: apt-get install
apt: pkg={{ item }} update_cache=yes state=present
with_items:
- mariadb-server
- mariadb-client
- mariadb-common
- libmariadbclient-dev
become: yes
become_user: root

View File

@ -1,16 +0,0 @@
---
# Setup Procfile
- name: setup procfile
command: bench setup procfile
args:
creates: "{{ bench_path }}/Procfile"
chdir: "{{ bench_path }}"
# Setup Redis env for RQ
- name: setup redis
command: bench setup redis
args:
creates: "{{ bench_path }}/config/redis_socketio.conf"
chdir: "{{ bench_path }}"

View File

@ -1,40 +0,0 @@
---
- name: Install MySQLdb in global env
pip: name=mysql-python version=1.2.5
become: yes
become_user: root
- name: Add configuration
template: src={{ mysql_config_template }} dest={{ mysql_conf_dir }}/frappe.cnf owner=root mode=0644
become: yes
become_user: root
- name: restart mysql linux
service: name=mysql state=restarted
become: yes
become_user: root
when: ansible_os_family == 'RedHat' or ansible_os_family == 'Debian'
- name: Set root Password
command: mysqladmin -u root password {{ mysql_root_password }}
become: yes
become_user: root
when: mysql_root_password is defined
# incase root password is already set
ignore_errors: yes
- name: add launchagents folder mac
file: path=~/Library/LaunchAgents state=directory
when: ansible_distribution == 'MacOSX'
- name: add mysql to mac startup
file: src=/usr/local/opt/mariadb/homebrew.mxcl.mariadb.plist path=~/Library/LaunchAgents/homebrew.mxcl.mariadb.plist state=link force=yes
when: ansible_distribution == 'MacOSX'
- name: stop mysql mac
command: launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.mariadb.plist
when: ansible_distribution == 'MacOSX'
- name: start mysql mac
command: launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mariadb.plist
when: ansible_distribution == 'MacOSX'

View File

@ -1,38 +0,0 @@
---
- hosts: localhost
tasks:
- name: Install SELinux for CentOS
yum: name="{{item}}" state=present
with_items:
- policycoreutils-python
- selinux-policy-devel
become: yes
become_user: root
when: ansible_distribution == 'CentOS'
- name: Install SELinux for Ubuntu
apt: name={{ item }} state=present
with_items:
- selinux
- selinux-policy-dev
become: yes
become_user: root
when: ansible_distribution == 'Ubuntu'
- name: Check enabled SELinux modules
shell: semanage module -l
register: enabled_modules
- name: Copy frappe_selinux policy
copy: src=templates/frappe_selinux.te dest=/root/frappe_selinux.te
register: dest_frappe_selinux_te
become: yes
become_user: root
- name: Compile frappe_selinux policy
shell: "make -f /usr/share/selinux/devel/Makefile frappe_selinux.pp && semodule -i frappe_selinux.pp"
args:
chdir: /root/
become: yes
become_user: root
when: "enabled_modules.stdout.find('frappe_selinux') == -1 or dest_frappe_selinux_te.changed"

View File

@ -1,19 +0,0 @@
---
- name: download wkthmltox linux
get_url: url=https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-{{ "amd64" if ansible_architecture == "x86_64" else "i386"}}.tar.xz dest=/tmp/wkhtmltox.tar.xz
- name: Creates directory
file: path=/tmp/wkhtmltox state=directory
- name: unarchive wkhtmltopdf
unarchive: src=/tmp/wkhtmltox.tar.xz dest=/tmp
- name: copy to /usr/local/bin
copy: src="/tmp/wkhtmltox/bin/wkhtmltopdf" dest="/usr/local/bin/wkhtmltopdf"
become: true
become_user: root
- name: make wkhtmltopdf executable
file: path=/usr/local/bin/wkhtmltopdf mode="o+x"
become: true
become_user: root

View File

@ -1,14 +0,0 @@
---
- hosts: localhost
- include: macosx.yml
when: ansible_distribution == 'MacOSX'
- include: ubuntu.yml
when: ansible_distribution == 'Ubuntu'
- include: centos.yml
when: ansible_distribution == 'CentOS'
- include: debian.yml
when: ansible_distribution == 'Debian'

View File

@ -1,34 +0,0 @@
---
- hosts: localhost
vars:
bench_repo_path: "/Users/{{ ansible_user_id }}/.bench"
bench_path: "/Users/{{ ansible_user_id }}/frappe-bench"
mysql_config_template: "templates/simple_mariadb_config.cnf"
mysql_conf_dir: /usr/local/etc/my.cnf.d
tasks:
# install pre-requisites
- name: install prequisites
homebrew: name={{ item }} state=present
with_items:
- cmake
- redis
- mariadb
- nodejs
# install wkhtmltopdf
- name: cask installs
homebrew_cask: name={{ item }} state=present
with_items:
- wkhtmltopdf
# setup MariaDB
- include: includes/setup_mariadb.yml
# setup frappe-bench
- include: includes/setup_bench.yml
# setup development environment
- include: includes/setup_dev_env.yml
when: not production

View File

@ -1,7 +0,0 @@
# MariaDB 10.1 CentOS repository list - created 2016-03-18 09:56 UTC
# http://mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.1/centos{{ ansible_lsb.major_release }}-{{ "amd64" if ansible_architecture == "x86_64" else "x86"}}
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1

View File

@ -1,109 +0,0 @@
---
- hosts: localhost
vars:
bench_repo_path: "/home/{{ ansible_user_id }}/.bench"
bench_path: "/home/{{ ansible_user_id }}/frappe-bench"
mysql_config_template: "templates/simple_mariadb_config.cnf"
mysql_conf_dir: /etc/mysql/conf.d/
tasks:
# install pre-requisites
- name: install prequisites
apt: pkg={{ item }} state=present
with_items:
# basic installs
- build-essential
- redis-server
# for mariadb
- software-properties-common
# for wkhtmltopdf
- libxrender1
- libxext6
- xfonts-75dpi
- xfonts-base
# for Pillow
- libjpeg8-dev
- zlib1g-dev
- libfreetype6-dev
- liblcms2-dev
- libwebp-dev
- python-tk
# Ensure apt-transport-https
- apt-transport-https
# Python LDAP
- libsasl2-dev
- libldap2-dev
become: yes
become_user: root
- name: install pillow prerequisites for Ubuntu < 14.04
apt: pkg={{ item }} state=present
with_items:
- libtiff4-dev
- tcl8.5-dev
- tk8.5-dev
when: ansible_distribution_version | version_compare('14.04', 'lt')
become: yes
become_user: root
- name: install pillow prerequisites for Ubuntu >= 14.04
apt: pkg={{ item }} state=present
with_items:
- libtiff5-dev
- tcl8.6-dev
- tk8.6-dev
when: ansible_distribution_version | version_compare('14.04', 'ge')
become: yes
become_user: root
- name: Add apt key for node repo
apt_key:
url: https://keyserver.ubuntu.com/pks/lookup?op=get&fingerprint=on&search=0x1655A0AB68576280
id: "68576280"
state: present
become: yes
become_user: root
- name: Add repo
apt_repository:
repo: "deb [arch=amd64,i386] https://deb.nodesource.com/node_6.x {{ ansible_distribution_release }} main"
state: present
register: node_repo
become: yes
become_user: root
- name: Install nodejs 6.x
apt:
name: nodejs
state: present
update_cache: yes
force: yes
become: yes
become_user: root
# install MariaDB
- include: includes/mariadb_ubuntu.yml
# install WKHTMLtoPDF
- include: includes/wkhtmltopdf.yml
# setup MariaDB
- include: includes/setup_mariadb.yml
- debug:
var: run_travis
# setup frappe-bench
- include: includes/setup_bench.yml
when: not without_bench_setup and not run_travis
# setup development environment
- include: includes/setup_dev_env.yml
when: not production and not run_travis and not without_bench_setup

41
playbooks/install.py Executable file → Normal file
View File

@ -58,8 +58,6 @@ def install_bench(args):
'pip': 'sudo pip install --upgrade pip setuptools',
})
# Restricting ansible version due to following bug in ansible 2.1
# https://github.com/ansible/ansible-modules-core/issues/3752
success = run_os_command({
'pip': "sudo pip install ansible"
})
@ -84,6 +82,14 @@ def install_bench(args):
if args.user == 'root':
raise Exception('Please run this script as a non-root user with sudo privileges, but without using sudo or pass --user=USER')
# Python executable
if not args.production:
dist_name, dist_version = get_distribution_info()
if dist_name=='centos':
args.python = 'python3.6'
else:
args.python = 'python3'
# create user if not exists
extra_vars = vars(args)
extra_vars.update(frappe_user=args.user)
@ -95,7 +101,7 @@ def install_bench(args):
repo_path = os.path.join(os.path.expanduser('~'), 'bench')
extra_vars.update(repo_path=repo_path)
run_playbook('develop/create_user.yml', extra_vars=extra_vars)
run_playbook('create_user.yml', extra_vars=extra_vars)
extra_vars.update(get_passwords(args))
if args.production:
@ -103,18 +109,22 @@ def install_bench(args):
branch = 'master' if args.production else 'develop'
extra_vars.update(branch=branch)
bench_name = 'frappe-bench' if not args.bench_name else args.bench_name
extra_vars.update(bench_name=bench_name)
if args.develop:
run_playbook('develop/install.yml', sudo=True, extra_vars=extra_vars)
# Will install ERPNext production setup by default
run_playbook('site.yml', sudo=True, extra_vars=extra_vars)
elif args.production:
run_playbook('production/install.yml', sudo=True, extra_vars=extra_vars)
# # Will do changes for production if --production flag is passed
# if args.production:
# run_playbook('production.yml', sudo=True, extra_vars=extra_vars)
if os.path.exists(tmp_bench_repo):
shutil.rmtree(tmp_bench_repo)
def check_distribution_compatibility():
supported_dists = {'ubuntu': [14, 15, 16], 'debian': [7, 8],
supported_dists = {'ubuntu': [14, 15, 16], 'debian': [8, 9],
'centos': [7], 'macos': [10.9, 10.10, 10.11, 10.12]}
dist_name, dist_version = get_distribution_info()
@ -146,7 +156,7 @@ def install_python27():
# install python 2.7
success = run_os_command({
'apt-get': 'sudo apt-get install -y python2.7',
'apt-get': 'sudo apt-get install -y python-dev',
'yum': 'sudo yum install -y python27',
'brew': 'brew install python'
})
@ -261,7 +271,7 @@ def get_passwords(args):
mysql_root_password = getpass.unix_getpass(prompt='Please enter mysql root password: ')
conf_mysql_passwd = getpass.unix_getpass(prompt='Re-enter mysql root password: ')
if mysql_root_password != conf_mysql_passwd:
if mysql_root_password != conf_mysql_passwd or mysql_root_password == '':
mysql_root_password = ''
continue
@ -270,7 +280,7 @@ def get_passwords(args):
admin_password = getpass.unix_getpass(prompt='Please enter the default Administrator user password: ')
conf_admin_passswd = getpass.unix_getpass(prompt='Re-enter Administrator password: ')
if admin_password != conf_admin_passswd:
if admin_password != conf_admin_passswd or admin_password == '':
admin_password = ''
continue
@ -340,6 +350,9 @@ def parse_commandline_args():
parser.add_argument('--site', dest='site', action='store', default='site1.local',
help='Specifiy name for your first ERPNext site')
parser.add_argument('--without-site', dest='without_site', action='store_true',
default=False)
parser.add_argument('--verbose', dest='verbosity', action='store_true', default=False,
help='Run the script in verbose mode')
@ -364,6 +377,12 @@ def parse_commandline_args():
# set passwords
parser.add_argument('--mysql-root-password', dest='mysql_root_password', help='Set mysql root password')
parser.add_argument('--admin-password', dest='admin_password', help='Set admin password')
parser.add_argument('--bench-name', dest='bench_name', help='Create bench with specified name. Default name is frappe-bench')
# Python interpreter to be used
parser.add_argument('--python', dest='python', default='python',
help=argparse.SUPPRESS
)
args = parser.parse_args()

39
playbooks/macosx.yml Normal file
View File

@ -0,0 +1,39 @@
---
- hosts: localhost
become: yes
become_user: root
vars:
bench_repo_path: "/Users/{{ ansible_user_id }}/.bench"
bench_path: "/Users/{{ ansible_user_id }}/frappe-bench"
tasks:
# install pre-requisites
- name: install prequisites
homebrew: name={{ item }} state=present
with_items:
- cmake
- redis
- mariadb
- nodejs
# install wkhtmltopdf
- name: cask installs
homebrew_cask: name={{ item }} state=present
with_items:
- wkhtmltopdf
- name: configure mariadb
include: roles/mariadb/tasks/main.yml
vars:
mysql_conf_tpl: roles/mariadb/files/mariadb_config.cnf
- name: Install MySQLdb in global env
pip: name=mysql-python version=1.2.5
# setup frappe-bench
- include: includes/setup_bench.yml
# setup development environment
- include: includes/setup_dev_env.yml
when: not production
...

View File

@ -1,63 +0,0 @@
---
- hosts: localhost
vars:
bench_path: "/home/{{ ansible_user_id }}/frappe-bench"
tasks:
# In case we are re-running the script, we would like to skip the site creation
- name: Check whether a site exists
stat: path="{{ bench_path }}/sites/{{ site }}"
register: site_folder
- name: Create new site
command: bench new-site {{ site }} --admin-password {{ admin_password }} --mariadb-root-password {{ mysql_root_password }}
args:
chdir: "{{ bench_path }}"
when: not site_folder.stat.exists
- name: Check ERPNext App exists
stat: path="{{ bench_path }}/apps/erpnext"
register: app
# In case we are re-running the script, we would like to skip getting ERPNext App
- name: Get-app erpnext app
command: bench get-app erpnext https://github.com/frappe/erpnext.git --branch {{ branch }}
args:
chdir: '{{ bench_path }}'
when: not app.stat.exists
- name: Install erpnext app
command: bench --site {{ site }} install-app erpnext
args:
chdir: '{{ bench_path }}'
- name: Change permissions for frappe home folder
become: yes
become_user: root
file:
dest: '{{ ansible_env.HOME }}'
owner: '{{ ansible_user_id }}'
group: '{{ ansible_user_id }}'
mode: 0755
recurse: yes
state: directory
- name: Setup production
become: yes
become_user: root
command: bench setup production {{ ansible_user_id }}
args:
chdir: '{{ bench_path }}'
- name: Setup Sudoers
become: yes
become_user: root
command: bench setup sudoers {{ ansible_user_id }}
args:
chdir: '{{ bench_path }}'
- name: Restart the bench
command: bench restart
args:
chdir: '{{ bench_path }}'

View File

@ -1,157 +0,0 @@
---
- hosts: localhost
tasks:
- name: Add nginx apt repository key for Debian < 8
apt_key:
url: http://nginx.org/keys/nginx_signing.key
state: present
become: yes
become_user: root
when: ansible_distribution == 'Debian' and ansible_distribution_version | version_compare('8', 'lt')
- name: Add nginx apt repository for Debian < 8
apt_repository:
repo: 'deb [arch=amd64,i386] http://nginx.org/packages/debian/ {{ ansible_distribution_release }} nginx'
state: present
become: yes
become_user: root
when: ansible_distribution == 'Debian' and ansible_distribution_version | version_compare('8', 'lt')
#####################################
# Ubuntu Production Environment Setup
- name: Install production pre-requisites
become: yes
become_user: root
apt: pkg={{ item }} state=present
with_items:
- nginx
- screen
- vim
- htop
- git
- postfix
- supervisor
when: ansible_distribution == 'Ubuntu' or ansible_distribution == 'Debian'
#####################################
# CentOS Production Environment Setup
- name: Install production pre-requisites
become: yes
become_user: root
yum: pkg={{ item }} state=present
with_items:
- nginx
- screen
- vim
- htop
- git
- postfix
- MySQL-python
when: ansible_distribution == 'CentOS'
- name: Install supervisor using yum for Centos 7
yum: pkg=supervisor state=present
become: yes
become_user: root
when: ansible_distribution == 'CentOS' and ansible_lsb.major_release == '7'
####################################################
# Replace default nginx config with nginx template
- name: Rename default nginx.conf to nginx.conf.old
command: mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.old
become: yes
become_user: root
- name: Copy the nginx_config template
template:
src: ../templates/default_nginx.j2
dest: /etc/nginx/nginx.conf
become: yes
become_user: root
- name: Reload the nginx service
service:
name: nginx
state: restarted
become: yes
become_user: root
######################################################
# Set InnoDB Buffer Pool size to half of total RAM
- name: Set InnoDB buffer pool
lineinfile: >
dest=/etc/my.cnf.d/frappe.cnf
regexp="^\[mysqld\]$"
line="[mysqld]\ninnodb_buffer_pool_size={{ (ansible_memtotal_mb/2)|round|int }}M"
state=present
when: ansible_distribution == 'CentOS'
become: yes
become_user: root
- name: Set InnoDB buffer pool
lineinfile: >
dest=/etc/mysql/conf.d/frappe.cnf
regexp="^\[mysqld\]$"
line="[mysqld]\ninnodb_buffer_pool_size={{ (ansible_memtotal_mb/2)|round|int }}M"
state=present
when: ansible_distribution == 'Ubuntu' or ansible_distribution == 'Debian'
become: yes
become_user: root
####################################################
# Enable nginx, mysql, redis and supevisord services
- name: Enable nginx, mysql, and redis
service:
name: '{{ item }}'
enabled: yes
with_items:
- nginx
- mysql
become: yes
become_user: root
- name: Enable redis.service on centos
service:
name: redis
enabled: yes
become: yes
become_user: root
when: ansible_distribution == 'CentOS'
- name: Enable redis-server.service on ubuntu
service:
name: redis-server
enabled: yes
become: yes
become_user: root
when: ansible_distribution == 'Ubuntu' or ansible_distribution == 'Debian'
- name: Check whether default supervisor.conf exists
service:
name: supervisord
state: started
enabled: yes
become: yes
become_user: root
when: ansible_distribution == 'CentOS'
- name: Check whether default supervisor.conf exists
service:
name: supervisor
state: started
enabled: yes
become: yes
become_user: root
when: ansible_distribution == 'Ubuntu' or ansible_distribution == 'Debian'
- name: insert/update inputrc for history
blockinfile:
dest: "/home/{{ ansible_user_id }}/.inputrc"
create: yes
block: |
## arrow up
"\e[A":history-search-backward
## arrow down
"\e[B":history-search-forward

View File

@ -1,15 +0,0 @@
---
- hosts: localhost
# Install the common pre-requisites for the setting up bench
- include: ../develop/install.yml
# Install the production environment
- include: includes/setup_prod_env.yml
# Setup Bench for production environment
- include: includes/setup_bench_production.yml
when: not run_travis
# Setup SELinux Policy, Optional can be done later
# - include: includes/setup_selinux_policy.yml

View File

@ -1,42 +0,0 @@
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
{% if ansible_distribution == 'Ubuntu' or ansible_distribution == 'Debian' %}
{% set nginx_user = 'www-data'%}
{% elif ansible_distribution == 'CentOS' %}
{% set nginx_user = 'nginx '%}
{% else %}
{% set nginx_user = 'nobody' %}
{% endif %}
user {{ nginx_user }};
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
events {
worker_connections {{ max_worker_connections }};
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf;
}

View File

@ -0,0 +1,8 @@
if [ $TERM != 'screen' ]
then
PS1='HEY! USE SCREEN '$PS1
fi
sw() {
screen -x $1 || screen -S $1
}

View File

@ -0,0 +1,4 @@
---
- name: Setup bash screen wall
copy: src=screen_wall.sh dest=/etc/profile.d/screen_wall.sh
...

View File

@ -1,14 +1,20 @@
- name: Change ssh port
gather_facts: false
hosts: localhost
user: root
tasks:
- name: change sshd config
lineinfile: >
dest=/etc/ssh/sshd_config
regexp="^Port"
line="Port {{ ssh_port }}"
state=present
- name: restart ssh
service: name=sshd state=reloaded
---
- name: Change ssh port
gather_facts: false
hosts: localhost
user: root
tasks:
- name: change sshd config
lineinfile: >
dest=/etc/ssh/sshd_config
regexp="^Port"
line="Port {{ ssh_port }}"
state=present
- name: restart ssh
service: name=sshd state=reloaded
- name: Change ansible ssh port to 2332
set_fact:
ansible_ssh_port: '{{ ssh_port }}'
...

View File

@ -28,11 +28,17 @@
stat: path="{{ bench_path }}"
register: bench_stat
- name: init bench
- name: python3 bench init for develop
command: bench init {{ bench_path }} --frappe-branch {{ branch }} --python {{ python }}
args:
creates: "{{ bench_path }}"
when: not bench_stat.stat.exists and not production
- name: python2 bench init for production
command: bench init {{ bench_path }} --frappe-branch {{ branch }}
args:
creates: "{{ bench_path }}"
when: not bench_stat.stat.exists
when: not bench_stat.stat.exists and production
# setup common_site_config
- name: setup config
@ -41,8 +47,29 @@
creates: "{{ bench_path }}/sites/common_site_config.json"
chdir: "{{ bench_path }}"
- name: install frappe app
command: bench get-app frappe https://github.com/frappe/frappe
- include_tasks: setup_inputrc.yml
# Setup Procfile
- name: Setup Procfile
command: bench setup procfile
args:
creates: "{{ bench_path }}/apps/frappe"
creates: "{{ bench_path }}/Procfile"
chdir: "{{ bench_path }}"
# Setup Redis env for RQ
- name: Setup Redis
command: bench setup redis
args:
creates: "{{ bench_path }}/config/redis_socketio.conf"
chdir: "{{ bench_path }}"
# Setup an ERPNext site
- include_tasks: setup_erpnext.yml
when: not run_travis
# Setup Bench for production environment
- include_tasks: setup_bench_production.yml
vars:
bench_path: "/home/{{ frappe_user }}/{{ bench_name }}"
when: not run_travis and production
...

View File

@ -0,0 +1,20 @@
---
- name: Setup production
become: yes
become_user: root
command: bench setup production {{ frappe_user }}
args:
chdir: '{{ bench_path }}'
- name: Setup Sudoers
become: yes
become_user: root
command: bench setup sudoers {{ frappe_user }}
args:
chdir: '{{ bench_path }}'
- name: Restart the bench
command: bench restart
args:
chdir: '{{ bench_path }}'
...

View File

@ -0,0 +1,27 @@
---
- name: Check if ERPNext App exists
stat: path="{{ bench_path }}/apps/erpnext"
register: app
- name: Get the ERPNext app
command: bench get-app erpnext https://github.com/frappe/erpnext --branch {{ branch }}
args:
creates: "{{ bench_path }}/apps/erpnext"
chdir: "{{ bench_path }}"
when: not app.stat.exists
- name: Check whether the site already exists
stat: path="{{ bench_path }}/sites/{{ site }}"
register: site_folder
- name: Create a new site
command: "bench new-site {{ site }} --admin-password {{ admin_password }} --mariadb-root-password {{ mysql_root_password }}"
args:
chdir: "{{ bench_path }}"
when: not site_folder.stat.exists
- name: Install ERPNext to default site
command: "bench --site {{ site }} install-app erpnext"
args:
chdir: "{{ bench_path }}"
...

View File

@ -1,9 +1,14 @@
---
- name: Setup Firewall
user: root
hosts: localhost
tasks:
# For CentOS
- name: Enable SELinux
selinux: policy=targeted state=permissive
when: ansible_distribution == 'CentOS'
- name: Install firewalld
yum: name=firewalld state=present
when: ansible_distribution == 'CentOS'
@ -17,7 +22,7 @@
with_items:
- 80
- 443
- 22
- "{{ ssh_port }}"
when: ansible_distribution == 'CentOS'
- name: Restart Firewall
@ -26,7 +31,10 @@
# For Ubuntu / Debian
- name: Install ufw
apt: name=ufw state=present
apt: name={{ item }} state=present force=yes
with_items:
- python-selinux
- ufw
when: ansible_distribution == 'Ubuntu' or ansible_distribution == 'Debian'
- name: Enable Firewall
@ -38,6 +46,6 @@
with_items:
- 80
- 443
- 22
- "{{ ssh_port }}"
when: ansible_distribution == 'Ubuntu' or ansible_distribution == 'Debian'
...

View File

@ -0,0 +1,11 @@
---
- name: insert/update inputrc for history
blockinfile:
dest: "/home/{{ frappe_user }}/.inputrc"
create: yes
block: |
## arrow up
"\e[A":history-search-backward
## arrow down
"\e[B":history-search-forward
...

View File

@ -0,0 +1,24 @@
---
- name: Setup OpenSSL dependancy
pip: name=pyOpenSSL version=16.2.0
- name: install pillow prerequisites for Debian < 8
apt: pkg={{ item }} state=present
with_items:
- libjpeg8-dev
- libtiff4-dev
- tcl8.5-dev
- tk8.5-dev
when: ansible_distribution_version | version_compare('8', 'lt')
- name: install pillow prerequisites for Debian >= 8
apt: pkg={{ item }} state=present
with_items:
- libjpeg62-turbo-dev
- libtiff5-dev
- tcl8.5-dev
- tk8.5-dev
when: ansible_distribution_version | version_compare('8', 'ge')
...

View File

@ -0,0 +1,42 @@
---
- name: Install prerequisites using apt-get
become: yes
become_user: root
apt: pkg={{ item }} state=present force=yes
with_items:
- dnsmasq
- fontconfig
- git # Version control
- htop # Server stats
- libcrypto++-dev
- libfreetype6-dev
- liblcms2-dev
- libssl-dev
- libwebp-dev
- libxext6
- libxrender1
- libxslt1-dev
- libxslt1.1
- libffi-dev
- ntp # Clock synchronization
- postfix # Mail Server
- python-dev # Installing python developer suite
- python3-dev # For python3 compatibility
- python-tk
- screen # To aid ssh sessions with connectivity problems
- vim # Is that supposed to be a question!?
- xfonts-75dpi
- xfonts-base
- zlib1g-dev
- apt-transport-https
- libsasl2-dev
- libldap2-dev
- include_tasks: debian.yml
when: ansible_distribution == 'Debian'
- include_tasks: ubuntu.yml
when: ansible_distribution == 'Ubuntu'
...

View File

@ -0,0 +1,37 @@
---
- hosts: localhost
become: yes
become_user: root
vars:
bench_repo_path: "/Users/{{ ansible_user_id }}/.bench"
bench_path: "/Users/{{ ansible_user_id }}/frappe-bench"
tasks:
# install pre-requisites
- name: install prequisites
homebrew: name={{ item }} state=present
with_items:
- cmake
- redis
- mariadb
- nodejs
# install wkhtmltopdf
- name: cask installs
homebrew_cask: name={{ item }} state=present
with_items:
- wkhtmltopdf
- name: configure mariadb
include_tasks: roles/mariadb/tasks/main.yml
vars:
mysql_conf_tpl: roles/mariadb/files/mariadb_config.cnf
# setup frappe-bench
- include_tasks: includes/setup_bench.yml
# setup development environment
- include_tasks: includes/setup_dev_env.yml
when: not production
...

View File

@ -0,0 +1,9 @@
---
# Install's prerequisites, like fonts, image libraries, vim, screen, python-dev
- include_tasks: debian_family.yml
when: ansible_os_family == 'Debian'
- include_tasks: redhat_family.yml
when: ansible_os_family == "RedHat"
...

View File

@ -0,0 +1,50 @@
---
- name: Install IUS repo for python 3.6
become: yes
become_user: root
yum:
name: https://centos7.iuscommunity.org/ius-release.rpm
state: present
- name: "Setup prerequisites using yum"
become: yes
become_user: root
yum: name={{ item }} state=present
with_items:
- bzip2-devel
- cronie
- dnsmasq
- freetype-devel
- git
- htop
- lcms2-devel
- libjpeg-devel
- libtiff-devel
- libffi-devel
- libwebp-devel
- libXext
- libXrender
- libzip-devel
- libffi-devel
- ntp
- openssl-devel
- postfix
- python36u
- python-devel
- python-setuptools
- python-pip
- redis
- screen
- sudo
- tcl-devel
- tk-devel
- vim
- which
- xorg-x11-fonts-75dpi
- xorg-x11-fonts-Type1
- zlib-devel
- openssl-devel
- openldap-devel
...

View File

@ -0,0 +1,21 @@
---
- name: install pillow prerequisites for Ubuntu < 14.04
apt: pkg={{ item }} state=present force=yes
with_items:
- libjpeg8-dev
- libtiff4-dev
- tcl8.5-dev
- tk8.5-dev
when: ansible_distribution_version | version_compare('14.04', 'lt')
- name: install pillow prerequisites for Ubuntu >= 14.04
apt: pkg={{ item }} state=present force=yes
with_items:
- libjpeg8-dev
- libtiff5-dev
- tcl8.6-dev
- tk8.6-dev
when: ansible_distribution_version | version_compare('14.04', 'ge')
...

View File

@ -0,0 +1,4 @@
---
- name: Restart network manager
service: name=NetworkManager state=restarted
...

View File

@ -0,0 +1,20 @@
---
- name: Check NetworkManager.conf exists
stat:
path: /etc/NetworkManager/NetworkManager.conf
register: result
- name: Unmask NetworkManager service
command: systemctl unmask NetworkManager
when: result.stat.exists
- name: Add dnsmasq to network config
lineinfile: >
dest=/etc/NetworkManager/NetworkManager.conf
regexp="dns="
line="dns=dnsmasq"
state=present
when: result.stat.exists
notify:
- restart network manager
...

View File

@ -0,0 +1,5 @@
---
fail2ban_nginx_access_log: /var/log/nginx/access.log
maxretry: 6
bantime: 600
findtime: 600

View File

@ -0,0 +1,3 @@
---
- name: restart fail2ban
service: name=fail2ban state=restarted

View File

@ -0,0 +1,11 @@
- name: Configure fail2ban jail options
hosts: localhost
become: yes
become_user: root
vars_files:
- ../defaults/main.yml
tasks:
- name: Setup jail
template: src="../templates/nginx-proxy-jail.conf.j2" dest="/etc/fail2ban/jail.d/nginx-proxy.conf"
- name: restart service
service: name=fail2ban state=restarted

View File

@ -0,0 +1,28 @@
---
- name: Install fail2ban
yum: name=fail2ban state=present
when: ansible_distribution == 'CentOS'
- name: Install fail2ban
apt: name=fail2ban state=present
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
- name: Enable fail2ban
service: name=fail2ban enabled=yes
- name: Create jail.d
file: path=/etc/fail2ban/jail.d state=directory
- name: Setup filters
template: src="{{item}}-filter.conf.j2" dest="/etc/fail2ban/filter.d/{{item}}.conf"
with_items:
- nginx-proxy
notify:
- restart fail2ban
- name: setup jails
template: src="{{item}}-jail.conf.j2" dest="/etc/fail2ban/jail.d/{{item}}.conf"
with_items:
- nginx-proxy
notify:
- restart fail2ban

View File

@ -0,0 +1,10 @@
# Block IPs trying to use server as proxy.
[Definition]
failregex = <HOST>.*\" 400
<HOST>.*"[A-Z]* /(cms|muieblackcat|db|cpcommerce|cgi-bin|wp-login|joomla|awstatstotals|wp-content|wp-includes|pma|phpmyadmin|myadmin|mysql|mysqladmin|sqladmin|mypma|admin|xampp|mysqldb|pmadb|phpmyadmin1|phpmyadmin2).*" 4[\d][\d]
<HOST>.*".*supports_implicit_sdk_logging.*" 4[\d][\d]
<HOST>.*".*activities?advertiser_tracking_enabled.*" 4[\d][\d]
<HOST>.*".*/picture?type=normal.*" 4[\d][\d]
<HOST>.*".*/announce.php?info_hash=.*" 4[\d][\d]
ignoreregex =

View File

@ -0,0 +1,9 @@
## block hosts trying to abuse our server as a forward proxy
[nginx-proxy]
enabled = true
filter = nginx-proxy
logpath = {{ fail2ban_nginx_access_log }}
action = iptables-multiport[name=NoNginxProxy, port="http,https"]
maxretry = {{ maxretry }}
bantime = {{ bantime }}
findtime = {{ findtime }}

View File

@ -29,4 +29,4 @@ allow httpd_t user_home_t:file open;
allow httpd_t user_home_t:file read;
#!!!! This avc is allowed in the current policy
allow httpd_t user_home_t:lnk_file read;
allow httpd_t user_home_t:lnk_file read;

View File

@ -0,0 +1,24 @@
---
- name: Install deps
yum: name="{{item}}" state=present
with_items:
- policycoreutils-python
- selinux-policy-devel
when: ansible_distribution == 'CentOS'
- name: Check enabled SELinux modules
shell: semanage module -l
register: enabled_modules
when: ansible_distribution == 'CentOS'
- name: Copy frappe_selinux policy
copy: src=frappe_selinux.te dest=/root/frappe_selinux.te
register: dest_frappe_selinux_te
when: ansible_distribution == 'CentOS'
- name: Compile frappe_selinux policy
shell: "make -f /usr/share/selinux/devel/Makefile frappe_selinux.pp && semodule -i frappe_selinux.pp"
args:
chdir: /root/
when: "ansible_distribution == 'CentOS' and enabled_modules.stdout.find('frappe_selinux') == -1 or dest_frappe_selinux_te.changed"
...

View File

@ -0,0 +1,4 @@
---
locale_keymap: us
locale_lang: en_US.utf8
...

View File

@ -0,0 +1,21 @@
---
- name: Check current locale
shell: localectl
register: locale_test
when: ansible_distribution == 'Centos' or ansible_distribution == 'Ubuntu'
- name: Set Locale
command: "localectl set-locale LANG={{ locale_lang }}"
when: (ansible_distribution == 'Centos' or ansible_distribution == 'Ubuntu') and locale_test.stdout.find('LANG=locale_lang') == -1
- name: Set keymap
command: "localectl set-keymap {{ locale_keymap }}"
when: "(ansible_distribution == 'Centos' or ansible_distribution == 'Ubuntu') and locale_test.stdout.find('Keymap:locale_keymap') == -1"
- name: Set Locale as en_US
lineinfile: dest=/etc/environment backup=yes line="{{ item }}"
with_items:
- "LC_ALL=en_US.UTF-8"
- "LC_CTYPE=en_US.UTF-8"
- "LANG=en_US.UTF-8"
...

View File

@ -0,0 +1,4 @@
---
logwatch_emails: "{{ admin_emails }}"
logwatch_detail: High
...

View File

@ -0,0 +1,13 @@
---
- name: Install logwatch
yum: name=logwatch state=present
when: ansible_distribution == 'CentOS'
- name: Install logwatch on Ubuntu or Debian
apt: name=logwatch state=present
when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu'
- name: Copy logwatch config
template: src=logwatch.conf.j2 dest=/etc/logwatch/conf/logwatch.conf backup=yes
when: admin_emails is defined
...

View File

@ -0,0 +1,2 @@
MailTo = {{ logwatch_emails }}
Detail = {{ logwatch_detail }}

View File

@ -1,7 +1,8 @@
---
mariadb_version: 10.0
mariadb_version: 10.2
mysql_conf_tpl: change_me
mysql_conf_file: settings.cnf
mysql_secure_installation: false
...

View File

@ -5,7 +5,10 @@ innodb-large-prefix=1
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
max_allowed_packet=64M
max_allowed_packet=256M
[mysql]
default-character-set = utf8mb4
[mysqldump]
max_allowed_packet=256M

View File

@ -11,7 +11,7 @@ key-buffer-size = 32M
myisam-recover = FORCE,BACKUP
# SAFETY #
max-allowed-packet = 16M
max-allowed-packet = 256M
max-connect-errors = 1000000
innodb = FORCE
@ -23,6 +23,9 @@ log-bin = /var/lib/mysql/mysql-bin
expire-logs-days = 14
sync-binlog = 1
# REPLICATION #
server-id = 1
# CACHES AND LIMITS #
tmp-table-size = 32M
max-heap-table-size = 32M
@ -46,6 +49,7 @@ innodb-large-prefix = 1
collation-server = utf8mb4_unicode_ci
character-set-server = utf8mb4
character-set-client-handshake = FALSE
max_allowed_packet = 256M
# LOGGING #
log-error = /var/lib/mysql/mysql-error.log
@ -56,3 +60,5 @@ slow-query-log-file = /var/lib/mysql/mysql-slow.log
[mysql]
default-character-set = utf8mb4
[mysqldump]
max_allowed_packet=256M

View File

@ -1,3 +1,4 @@
---
- name: restart mysql
service: name=mysql state=restarted
...

View File

@ -6,7 +6,5 @@
yum: name={{ item }} enablerepo=mariadb state=present
with_items:
- MariaDB-server
- MariaDB-client
- MySQL-python
- MariaDB-devel
- MySQL-python # required for secure_install
...

View File

@ -0,0 +1,31 @@
---
- name: Add apt key for mariadb for Debian <= 8
apt_key: keyserver=hkp://keyserver.ubuntu.com:80 id=0xcbcb082a1bb943db state=present
when: ansible_distribution_major_version | version_compare('8', 'le')
- name: Add apt key for mariadb for Debian > 8
apt_key: keyserver=hkp://keyserver.ubuntu.com:80 id=0xF1656F24C74CD1D8 state=present
when: ansible_distribution_major_version | version_compare('8', 'gt')
- name: Add apt repository
apt_repository:
repo: 'deb [arch=amd64,i386] http://ams2.mirrors.digitalocean.com/mariadb/repo/{{ mariadb_version }}/debian {{ ansible_distribution_release }} main'
state: present
- name: Add apt repository
apt_repository:
repo: 'deb-src [arch=amd64,i386] http://ams2.mirrors.digitalocean.com/mariadb/repo/{{ mariadb_version }}/debian {{ ansible_distribution_release }} main'
state: present
- name: Unattended package installation
shell: export DEBIAN_FRONTEND=noninteractive
- name: apt-get install
apt: pkg={{ item }} update_cache=yes state=present
with_items:
- mariadb-server
- mariadb-client
- mariadb-common
- libmariadbclient18
- python-mysqldb
...

View File

@ -0,0 +1,56 @@
---
- include_tasks: centos.yml
when: ansible_distribution == 'CentOS'
- include_tasks: ubuntu.yml
when: ansible_distribution == 'Ubuntu'
- name: Add configuration
template: src={{ mysql_conf_tpl }} dest={{ mysql_conf_dir[ansible_distribution] }}/{{ mysql_conf_file }} owner=root group=root mode=0644
when: mysql_conf_tpl != 'change_me' and ansible_distribution != 'Debian'
notify: restart mysql
- include_tasks: debian.yml
when: ansible_distribution == 'Debian'
- name: Add configuration
template: src={{ mysql_conf_tpl }} dest={{ mysql_conf_dir[ansible_distribution] }}/{{ mysql_conf_file }} owner=root group=root mode=0644
when: mysql_conf_tpl != 'change_me' and ansible_distribution == 'Debian'
notify: restart mysql
- name: Add additional conf for MariaDB 10.2 in mariadb.conf.d
blockinfile:
path: /etc/mysql/conf.d/settings.cnf
block: |
# Import all .cnf files from configuration directory
!includedir /etc/mysql/mariadb.conf.d/
become: yes
become_user: root
when: ansible_distribution == 'Ubuntu' or ansible_distribution == 'Debian'
- name: Add additional conf for MariaDB 10.2 in mariadb.conf.d
blockinfile:
path: /etc/mysql/mariadb.conf.d/erpnext.cnf
block: |
[mysqld]
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
create: yes
become: yes
become_user: root
when: ansible_distribution == 'Ubuntu' or ansible_distribution == 'Debian'
- name: Start and enable service
service: name=mysql state=started enabled=yes
- debug:
msg: "{{ mysql_root_password }}"
- include_tasks: mysql_secure_installation.yml
when: mysql_root_password is defined
- debug: var=mysql_secure_installation
when: mysql_secure_installation and mysql_root_password is defined
...

View File

@ -3,44 +3,52 @@
# UPDATE mysql.user SET Password=PASSWORD('mysecret') WHERE User='root';
# FLUSH PRIVILEGES;
- debug:
msg: "{{ mysql_root_password }}"
- name: Set root Password
mysql_user: name=root host={{ item }} password={{ mysql_root_password }} state=present
with_items:
- localhost
ignore_errors: yes
- name: Add .my.cnf
template: src=my.cnf.j2 dest=/root/.my.cnf owner=root group=root mode=0600
- name: display .my.cnf
command: cat /root/.my.cnf
register: details
- debug:
msg: "{{ details.stdout_lines }}"
- name: Set root Password
mysql_user: name=root host={{ item }} password={{ mysql_root_password }} state=present
with_items:
- 127.0.0.1
- ::1
when: run_travis is not defined
- name: Reload privilege tables
command: 'mysql -ne "{{ item }}"'
with_items:
- FLUSH PRIVILEGES
changed_when: False
- name: Reload privilege tables
command: 'mysql -ne "{{ item }}"'
with_items:
- FLUSH PRIVILEGES
changed_when: False
when: run_travis is not defined
- name: Remove anonymous users
command: 'mysql -ne "{{ item }}"'
with_items:
- DELETE FROM mysql.user WHERE User=''
changed_when: False
when: run_travis is not defined
- name: Disallow root login remotely
command: 'mysql -ne "{{ item }}"'
with_items:
- DELETE FROM mysql.user WHERE User='root' AND Host NOT IN ('localhost', '127.0.0.1', '::1')
changed_when: False
when: run_travis is not defined
- name: Remove test database and access to it
command: 'mysql -ne "{{ item }}"'
@ -48,10 +56,28 @@
- DROP DATABASE if exists test
- DELETE FROM mysql.db WHERE Db='test' OR Db='test\\_%'
changed_when: False
ignore_errors: True
when: run_travis is not defined
- name: Reload privilege tables
command: 'mysql -ne "{{ item }}"'
with_items:
- FLUSH PRIVILEGES
changed_when: False
when: run_travis is not defined
- name: add launchagents folder mac
file: path=~/Library/LaunchAgents state=directory
when: ansible_distribution == 'MacOSX'
- name: add mysql to mac startup
file: src=/usr/local/opt/mariadb/homebrew.mxcl.mariadb.plist path=~/Library/LaunchAgents/homebrew.mxcl.mariadb.plist state=link force=yes
when: ansible_distribution == 'MacOSX'
- name: stop mysql mac
command: launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.mariadb.plist
when: ansible_distribution == 'MacOSX'
- name: start mysql mac
command: launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mariadb.plist
when: ansible_distribution == 'MacOSX'
...

View File

@ -6,6 +6,12 @@
- name: Add repo key
apt_key: id=1BB943DB url=http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xCBCB082A1BB943DB state=present
register: mariadb_key
when: ansible_distribution_version | version_compare('16.04', 'lt')
- name: Add apt key for mariadb for Ubuntu >= 16.04
apt_key: id=C74CD1D8 url=http://keyserver.ubuntu.com/pks/lookup?op=get&search=0xF1656F24C74CD1D8 state=present
register: mariadb_key
when: ansible_distribution_version | version_compare('16.04', 'ge')
- name: Update apt cache
apt: update_cache=yes
@ -19,5 +25,5 @@
apt: pkg={{ item }} state=present
with_items:
- mariadb-server
- mariadb-client
- python-mysqldb
- python-mysqldb # required to set the MySQL password using ansible
...

View File

@ -1,4 +1,4 @@
# MariaDB CentOS {{ ansible_distribution_major_version|int }} repository list
# MariaDB {{ mariadb_version }} CentOS {{ ansible_distribution_major_version|int }} repository list
# http://mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB

View File

@ -0,0 +1,4 @@
# MariaDB {{ mariadb_version }} Debian {{ ansible_distribution_release | title }} repository list
# http://mariadb.org/mariadb/repositories/
deb http://ams2.mirrors.digitalocean.com/mariadb/repo/{{ mariadb_version }}/debian {{ ansible_distribution_release | lower }} main
deb-src http://ams2.mirrors.digitalocean.com/mariadb/repo/{{ mariadb_version }}/debian {{ ansible_distribution_release | lower }} main

View File

@ -1,4 +1,4 @@
# MariaDB Ubuntu {{ ansible_distribution_release | title }} repository list
# MariaDB {{ mariadb_version }} Ubuntu {{ ansible_distribution_release | title }} repository list
# http://mariadb.org/mariadb/repositories/
deb http://ams2.mirrors.digitalocean.com/mariadb/repo/{{ mariadb_version }}/ubuntu {{ ansible_distribution_release | lower }} main
deb-src http://ams2.mirrors.digitalocean.com/mariadb/repo/{{ mariadb_version }}/ubuntu {{ ansible_distribution_release | lower }} main

View File

@ -0,0 +1,9 @@
---
mysql_conf_dir:
"CentOS": /etc/my.cnf.d
"Ubuntu": /etc/mysql/conf.d
"Debian": /etc/mysql/conf.d
"MacOSX": /usr/local/etc/my.cnf.d
mysql_conf_tpl: files/mariadb_config.cnf
mysql_secure_installation: True
...

View File

@ -44,4 +44,5 @@ nginx_upstreams: []
# "srv3.example.com"
# }
# }
nginx_conf_file: nginx.conf.j2
nginx_conf_file: nginx.conf.j2
setup_www_redirect: false

View File

@ -9,10 +9,15 @@
when: nginx_user is not defined
# Setup/install tasks.
- include: setup-RedHat.yml
- include_tasks: setup-RedHat.yml
when: ansible_os_family == 'RedHat'
- include: setup-Debian.yml
- include_tasks: setup-Debian.yml
when: ansible_os_family == 'Debian'
# Replace default nginx config with nginx template
- name: Rename default nginx.conf to nginx.conf.old
command: mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.old
when: ansible_os_family == 'Debian'
# Nginx setup.
@ -25,7 +30,22 @@
mode: 0644
notify: restart nginx
- name: Setup www redirect
template:
src: ../files/www_redirect.conf
dest: /etc/nginx/conf.d/
owner: root
group: root
mode: 0644
notify: restart nginx
when: setup_www_redirect
- name: Enable SELinux
selinux: policy=targeted state=permissive
when: ansible_distribution == 'CentOS'
- name: Ensure nginx is started and enabled to start at boot.
service: name=nginx state=started enabled=yes
- include: vhosts.yml
- include_tasks: vhosts.yml
...

View File

@ -0,0 +1,18 @@
---
- name: Add nginx apt repository key for Debian < 8
apt_key:
url: http://nginx.org/keys/nginx_signing.key
state: present
when: ansible_distribution == 'Debian' and ansible_distribution_version | version_compare('8', 'lt')
- name: Add nginx apt repository for Debian < 8
apt_repository:
repo: 'deb [arch=amd64,i386] http://nginx.org/packages/debian/ {{ ansible_distribution_release }} nginx'
state: present
when: ansible_distribution == 'Debian' and ansible_distribution_version | version_compare('8', 'lt')
- name: Ensure nginx is installed.
apt:
pkg: nginx
state: installed
default_release: "{{ nginx_default_release }}"

View File

@ -0,0 +1,76 @@
user {{ nginx_user }};
worker_processes auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections {{ nginx_worker_connections or 2048 }};
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"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
# keepalive_timeout 10;
# keepalive_requests 10;
gzip on;
gzip_disable "msie6";
gzip_http_version 1.1;
gzip_comp_level 5;
gzip_min_length 256;
gzip_proxied any;
gzip_vary on;
gzip_types
application/atom+xml
application/javascript
application/json
application/rss+xml
application/vnd.ms-fontobject
application/x-font-ttf
application/font-woff
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/svg+xml
image/x-icon
text/css
text/plain
text/x-component
;
server_names_hash_max_size 4096;
open_file_cache max=65000 inactive=1m;
open_file_cache_valid 5s;
open_file_cache_min_uses 1;
open_file_cache_errors on;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers ECDHE-RSA-AES256-SHA384:AES256-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM;
ssl_prefer_server_ciphers on;
client_max_body_size 50m;
large_client_header_buffers 4 32k;
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=web-cache:8m max_size=1000m inactive=600m;
include /etc/nginx/conf.d/*.conf;
}

Some files were not shown because too many files have changed in this diff Show More