#### Check does system use upstart | |
echo '' && whereis upstart | grep -q 'upstart: /' && echo 'You can use UPSTART' || echo 'There is no upstart in your system. Use SUPERVISORCTL instead' | |
#### CHECK AND UPDATE LANGUAGE | |
env | grep LANG | |
export LANG=en_US.UTF-8 | |
export LANGUAGE=en_US.UTF-8 | |
dpkg-reconfigure locales | |
#### DOWNLOADS... | |
### PACKAGES | |
apt-get update && \ | |
apt-get upgrade -y && \ | |
apt-get install -y git python-pip htop postgresql sudo moreutils tree && \ | |
apt-get install -y emacs23-nox && \ | |
echo '' && whereis upstart | grep -q 'upstart: /' && echo 'using upstart'|| ( apt-get install supervisor && echo 'supervisor installed' ) | |
## pip | |
pip install psycogreen | |
pip install rotate-backups | |
### SOURCE | |
mkdir /usr/local/src/odoo-addons -p | |
cd /usr/local/src/odoo-addons/ | |
git clone https://github.com/odoo-russia/odoo-russia.git &&\ | |
git clone https://github.com/yelizariev/pos-addons.git &&\ | |
git clone https://github.com/yelizariev/addons-yelizariev.git &&\ | |
git clone https://github.com/OCA/web.git &&\ | |
git clone https://github.com/OCA/server-tools.git &&\ | |
cd /usr/local/src/ &&\ | |
git clone https://github.com/odoo/odoo.git | |
cd /usr/local/src/odoo-addons/ | |
mkdir addons-extra | |
cd addons-extra | |
ln -s ../odoo-russia/addons/l10n_ru/ . | |
### DEPS | |
python --version # should be 2.7 or higher | |
cd /usr/local/src/odoo | |
echo "y" | (wget -q -O- https://raw.githubusercontent.com/odoo/odoo/master/odoo.py | python) | |
#@@@@@@@@@@@@@@@@@@@@ NEED MANUAL WORK HERE (FIXME) | |
## wkhtmltopdf | |
cd /usr/local/src | |
lsb_release -a | |
uname -i | |
# check version of your OS and download appropriate package | |
# http://wkhtmltopdf.org/downloads.html | |
# e.g. | |
apt-get install xfonts-base xfonts-75dpi | |
apt-get -f install | |
wget http://downloads.sourceforge.net/project/wkhtmltopdf/0.12.2.1/wkhtmltox-0.12.2.1_linux-trusty-amd64.deb | |
dpkg -i wkhtmltox-*.deb | |
#@@@@@@@@@@@@@@@@@@@@ NEED MANUAL WORK HERE (FIXME) | |
#### DOWNLOADS done. | |
### SETTINGS | |
## gist url -- update it if you've forked this gist | |
export GIST="yelizariev/2abdd91d00dddc4e4fa4" | |
## from http://stackoverflow.com/questions/2914220/bash-templating-how-to-build-configuration-files-from-templates-with-bash | |
export PERL_UPDATE_ENV="perl -p -e 's/\{\{([^}]+)\}\}/defined \$ENV{\$1} ? \$ENV{\$1} : \$&/eg' " | |
export ODOO_DOMAIN=EDIT-ME.example.com | |
export ODOO_DATABASE=DATABASE_EDIT_ME | |
export ODOO_USER=odoo | |
export ODOO_BRANCH=8.0 | |
export ODOO_PASS=`< /dev/urandom tr -dc A-Za-z0-9 | head -c${1:-32};echo;` | |
adduser --system --home=/opt/${ODOO_USER} --group ${ODOO_USER} | |
# psql --version | |
# pg_createcluster 9.3 main --start | |
sudo -iu postgres createuser -s ${ODOO_USER} | |
### BRANCH | |
cd /usr/local/src/odoo | |
git checkout -b ${ODOO_BRANCH} origin/${ODOO_BRANCH} | |
### CONFIGS | |
## /var/log/odoo/ | |
mkdir /var/log/odoo/ | |
chown ${ODOO_USER}:${ODOO_USER} /var/log/odoo | |
## /etc/odoo/odoo-server.conf | |
mkdir /etc/odoo | |
cd /etc/odoo/ | |
wget -q https://gist.githubusercontent.com/${GIST}/raw/odoo-server.conf -O odoo-server.conf | |
eval "${PERL_UPDATE_ENV} < odoo-server.conf" | sponge odoo-server.conf | |
chown ${ODOO_USER}:${ODOO_USER} odoo-server.conf | |
chmod 600 odoo-server.conf | |
### CONTROL SCRIPTS - upstart | |
if whereis upstart | grep -q 'upstart: /' ###################################### IF | |
then | |
cd /etc/init/ | |
wget -q https://gist.githubusercontent.com/${GIST}/raw/odoo-init.conf -O odoo.conf | |
eval "${PERL_UPDATE_ENV} < odoo.conf" | sponge odoo.conf | |
wget -q https://gist.githubusercontent.com/${GIST}/raw/odoo-longpolling-init.conf -O odoo-longpolling.conf | |
eval "${PERL_UPDATE_ENV} < odoo-longpolling.conf" | sponge odoo-longpolling.conf | |
### START - upstart | |
start odoo && start odoo-longpolling | |
# stop odoo && stop odoo-longpolling | |
# restart odoo && restart odoo-longpolling | |
### CONTROL SCRIPTS - supervisor | |
else ###################################################### ELSE | |
cd /etc/supervisor/conf.d/ | |
wget -q https://gist.githubusercontent.com/${GIST}/raw/odoo-supervisor.conf -O odoo.conf | |
eval "${PERL_UPDATE_ENV} < odoo.conf" | sponge odoo.conf | |
wget -q https://gist.githubusercontent.com/${GIST}/raw/odoo-longpolling-supervisor.conf -O odoo-longpolling.conf | |
eval "${PERL_UPDATE_ENV} < odoo-longpolling.conf" | sponge odoo-longpolling.conf | |
### START - supervisor | |
supervisorctl reread | |
supervisorctl update | |
supervisorctl restart odoo && supervisorctl restart odoo-longpolling | |
fi #################################################### END IF | |
### CONTROL SCRIPTS - /etc/init.d/* | |
# Such scripts are not recommended, because you will not get supervision features. | |
# Use this link to find ones: https://gist.github.com/yelizariev/2abdd91d00dddc4e4fa4/d0ac3bd971e81213d17332647d9a74a580cfde6b | |
### BACKUP | |
mkdir -p /opt/${ODOO_USER}/backups/ | |
chown ${ODOO_USER}:${ODOO_USER} /opt/${ODOO_USER}/backups/ | |
cd /usr/local/bin/ | |
wget -q https://gist.githubusercontent.com/${GIST}/raw/odoo-backup.py -O odoo-backup.py | |
chmod +x odoo-backup.py | |
echo -e "#6 6\t* * *\t${ODOO_USER} odoo-backup.py -d ${ODOO_DATABASE} -p /opt/${ODOO_USER}/backups/ --no-save-filestore --daily 8 --weekly 0 --monthly 0 --yearly 0" >> /etc/crontab | |
echo -e "#4 4\t* * 7\t${ODOO_USER} odoo-backup.py -d ${ODOO_DATABASE} -p /opt/${ODOO_USER}/backups/" >> /etc/crontab | |
## to test run: | |
# sudo su - ${ODOO_USER} -s /bin/bash -c "odoo-backup.py -d ${ODOO_DATABASE} -p /opt/${ODOO_USER}/backups/" | |
### NGINX | |
/etc/init.d/apache2 stop && \ | |
apt-get remove apache2 -y && \ | |
apt-get install nginx -y && \ | |
echo "nginx installed" | |
cd /etc/nginx && \ | |
wget -q https://gist.githubusercontent.com/${GIST}/raw/nginx_odoo_params -O odoo_params && \ | |
eval "${PERL_UPDATE_ENV} < odoo_params" | sponge odoo_params | |
cd /etc/nginx/sites-available/ && \ | |
wget -q https://gist.githubusercontent.com/${GIST}/raw/nginx_odoo.conf -O odoo.conf && \ | |
eval "${PERL_UPDATE_ENV} < odoo.conf" | sponge odoo.conf | |
cd /etc/nginx/sites-enabled/ && \ | |
rm default && \ | |
ln -s ../sites-available/odoo.conf odoo.conf | |
service nginx restart | |
### DEBUG | |
## show settings (admin password, addons path) | |
head /etc/odoo/odoo-server.conf | |
## show odoo version | |
grep '^version_info ' /usr/local/src/odoo/openerp/release.py | |
## log | |
tail -f -n 100 /var/log/odoo/odoo-server.log | |
## start from console (for ODOO_USER=odoo): | |
# sudo su - odoo -s /bin/bash -c "/usr/local/src/odoo/openerp-server -c /etc/odoo/odoo-server.conf" | |
## psql (use name of your database) | |
# sudo -u odoo psql DATABASE | |
## some common issues: | |
## https://www.odoo.com/forum/help-1/question/dataerror-new-encoding-utf8-is-incompatible-with-the-encoding-of-the-template-database-sql-ascii-52124 |
server { | |
listen 80 default_server; | |
#server_name {{ODOO_DOMAIN}}; | |
include odoo_params; | |
location /longpolling { | |
proxy_pass http://127.0.0.1:8072; | |
} | |
location / { | |
proxy_pass http://127.0.0.1:8069; | |
} | |
} |
charset utf-8; | |
location = /favicon.ico { | |
return 404; | |
} | |
# increase proxy buffer to handle some OpenERP web requests | |
proxy_buffers 16 64k; | |
proxy_buffer_size 128k; | |
proxy_set_header Host $host; | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |
proxy_set_header X-Forwarded-Proto $scheme; | |
#proxy_redirect http:// https://; | |
proxy_read_timeout 600s; | |
client_max_body_size 100m; | |
#!/usr/bin/env python | |
### depends on https://github.com/xolox/python-rotate-backups -- check this url for understanding rotating parameters | |
import argparse | |
import os | |
import subprocess | |
import shutil | |
import zipfile | |
import datetime | |
import tempfile | |
from contextlib import contextmanager | |
### READ INPUT | |
parser = argparse.ArgumentParser(description='Odoo backup tool.') | |
parser.add_argument('-d', '--database', dest='database', nargs='+', help='database for backup') | |
parser.add_argument('--no-save-filestore', dest='save_filestore', action='store_false', help='skip filestore to save disk space') | |
parser.add_argument('--no-rotate', dest='rotate', action='store_false', help='skip backups rotating') | |
parser.add_argument('-p', '--path', dest='path', default='/tmp/', help='path to save backup') | |
parser.add_argument('-c', '--odoo-config', dest='odoo_config', default='/etc/odoo/odoo-server.conf', help='odoo config file') | |
parser.add_argument('--hourly', dest='hourly', default='24', help='how many hourly backups to preserve') | |
parser.add_argument('--daily', dest='daily', default='7', help='how many daily backups to preserve') | |
parser.add_argument('--weekly', dest='weekly', default='4', help='how many weekly backups to preserve') | |
parser.add_argument('--monthly', dest='monthly', default='12', help='how many monthly backups to preserve') | |
parser.add_argument('--yearly', dest='yearly', default='always', help='how many yearly backups to preserve') | |
#parser.add_argument('--odoo-source', dest='odoo_source', default='/usr/local/src/odoo/', help='odoo source dir') | |
args = parser.parse_args() | |
def get_odoo_config(): | |
import ConfigParser | |
p = ConfigParser.ConfigParser() | |
p.read(args.odoo_config) | |
res = {} | |
for (name,value) in p.items('options'): | |
if value=='True' or value=='true': | |
value = True | |
if value=='False' or value=='false': | |
value = False | |
res[name] = value | |
return res | |
odoo_config = get_odoo_config() | |
### EXECUTE | |
#@_set_pg_password_in_environment # see openerp/service/db.py | |
def dump_sql(db, dump_file): | |
cmd = ['pg_dump', '--format=p', '--no-owner', '--file=' + dump_file] | |
if odoo_config.get('db_user'): | |
cmd.append('--username=' + odoo_config.get('db_user')) | |
if odoo_config.get('db_host'): | |
cmd.append('--host=' + odoo_config.get('db_host')) | |
if odoo_config.get('db_port'): | |
cmd.append('--port=' + str(odoo_config.get('db_port'))) | |
cmd.append(db) | |
if exec_pg_command(*cmd): | |
print ' '.join(cmd) | |
raise Exception("Couldn't dump database") | |
def backup(db, dump_dir): | |
odoo_data_dir = odoo_config.get('data_dir', '~/.local/share/Odoo/') | |
filestore = os.path.join(odoo_data_dir, 'filestore', db) | |
if args.save_filestore: | |
os.symlink(filestore, os.path.join(dump_dir, 'filestore')) | |
dump_file = os.path.join(dump_dir, 'dump.sql') | |
dump_sql(db, dump_file) | |
dump_archive = "%(db)s_%(timestamp)s_%(mark)s.dump" % { | |
'db': db, | |
'timestamp': datetime.datetime.utcnow().strftime("%Y-%m-%d_%H-%M-%SZ"), | |
'mark': 'full' if args.save_filestore else 'quick', | |
} | |
with open(dump_archive, 'w') as stream: | |
zip_dir(dump_dir, stream, include_dir=False) | |
return dump_archive | |
def rotate(backup_dir): | |
cmd = ['rotate-backups'] | |
for period in ('hourly', 'daily', 'weekly', 'monthly', 'yearly'): | |
cmd.extend(['--%s' % period, getattr(args, period) ] ) | |
cmd.append(backup_dir) | |
cmd.extend(['2>', '/dev/null']) | |
os.system(' '.join(cmd)) | |
def main(): | |
for db in args.database: | |
backup_dir = os.path.join(args.path, db, 'full' if args.save_filestore else 'quick') | |
if not os.path.exists(backup_dir): | |
os.system('mkdir -p %s' % backup_dir) | |
with tempdir() as dump_dir: | |
dump_archive = backup(db, dump_dir) | |
shutil.move(dump_archive, os.path.join(backup_dir, dump_archive)) | |
if args.rotate: | |
rotate(backup_dir) | |
### TOOLS | |
def find_pg_tool(name): | |
path = None | |
#if config['pg_path'] and config['pg_path'] != 'None': | |
# path = config['pg_path'] | |
try: | |
return which(name, path=path) | |
except IOError: | |
return None | |
def exec_pg_command(name, *args): | |
prog = find_pg_tool(name) | |
if not prog: | |
raise Exception('Couldn\'t find %s' % name) | |
args2 = (prog,) + args | |
with open(os.devnull) as dn: | |
return subprocess.call(args2, stdout=dn, stderr=subprocess.STDOUT) | |
def zip_dir(path, stream, include_dir=True): # TODO add ignore list | |
path = os.path.normpath(path) | |
len_prefix = len(os.path.dirname(path)) if include_dir else len(path) | |
if len_prefix: | |
len_prefix += 1 | |
with zipfile.ZipFile(stream, 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=True) as zipf: | |
for dirpath, dirnames, filenames in os.walk(path, followlinks=True): | |
for fname in filenames: | |
bname, ext = os.path.splitext(fname) | |
ext = ext or bname | |
if ext not in ['.pyc', '.pyo', '.swp', '.DS_Store']: | |
path = os.path.normpath(os.path.join(dirpath, fname)) | |
if os.path.isfile(path): | |
zipf.write(path, path[len_prefix:]) | |
@contextmanager | |
def tempdir(): | |
tmpdir = tempfile.mkdtemp() | |
try: | |
yield tmpdir | |
finally: | |
shutil.rmtree(tmpdir) | |
import sys | |
from os import access, defpath, pathsep, environ, F_OK, R_OK, W_OK, X_OK | |
from os.path import exists, dirname, split, join | |
windows = sys.platform.startswith('win') | |
defpath = environ.get('PATH', defpath).split(pathsep) | |
if windows: | |
defpath.insert(0, '.') # can insert without checking, when duplicates are removed | |
# given the quite usual mess in PATH on Windows, let's rather remove duplicates | |
seen = set() | |
defpath = [dir for dir in defpath if dir.lower() not in seen and not seen.add(dir.lower())] | |
del seen | |
defpathext = [''] + environ.get('PATHEXT', | |
'.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC').lower().split(pathsep) | |
else: | |
defpathext = [''] | |
def which_files(file, mode=F_OK | X_OK, path=None, pathext=None): | |
""" Locate a file in a path supplied as a part of the file name, | |
or the user's path, or a supplied path. | |
The function yields full paths (not necessarily absolute paths), | |
in which the given file name matches an existing file in a directory on the path. | |
>>> def test_which(expected, *args, **argd): | |
... result = list(which_files(*args, **argd)) | |
... assert result == expected, 'which_files: %s != %s' % (result, expected) | |
... | |
... try: | |
... result = [ which(*args, **argd) ] | |
... except IOError: | |
... result = [] | |
... assert result[:1] == expected[:1], 'which: %s != %s' % (result[:1], expected[:1]) | |
>>> if windows: cmd = environ['COMSPEC'] | |
>>> if windows: test_which([cmd], 'cmd') | |
>>> if windows: test_which([cmd], 'cmd.exe') | |
>>> if windows: test_which([cmd], 'cmd', path=dirname(cmd)) | |
>>> if windows: test_which([cmd], 'cmd', pathext='.exe') | |
>>> if windows: test_which([cmd], cmd) | |
>>> if windows: test_which([cmd], cmd, path='<nonexistent>') | |
>>> if windows: test_which([cmd], cmd, pathext='<nonexistent>') | |
>>> if windows: test_which([cmd], cmd[:-4]) | |
>>> if windows: test_which([cmd], cmd[:-4], path='<nonexistent>') | |
>>> if windows: test_which([], 'cmd', path='<nonexistent>') | |
>>> if windows: test_which([], 'cmd', pathext='<nonexistent>') | |
>>> if windows: test_which([], '<nonexistent>/cmd') | |
>>> if windows: test_which([], cmd[:-4], pathext='<nonexistent>') | |
>>> if not windows: sh = '/bin/sh' | |
>>> if not windows: test_which([sh], 'sh') | |
>>> if not windows: test_which([sh], 'sh', path=dirname(sh)) | |
>>> if not windows: test_which([sh], 'sh', pathext='<nonexistent>') | |
>>> if not windows: test_which([sh], sh) | |
>>> if not windows: test_which([sh], sh, path='<nonexistent>') | |
>>> if not windows: test_which([sh], sh, pathext='<nonexistent>') | |
>>> if not windows: test_which([], 'sh', mode=W_OK) # not running as root, are you? | |
>>> if not windows: test_which([], 'sh', path='<nonexistent>') | |
>>> if not windows: test_which([], '<nonexistent>/sh') | |
""" | |
filepath, file = split(file) | |
if filepath: | |
path = (filepath,) | |
elif path is None: | |
path = defpath | |
elif isinstance(path, str): | |
path = path.split(pathsep) | |
if pathext is None: | |
pathext = defpathext | |
elif isinstance(pathext, str): | |
pathext = pathext.split(pathsep) | |
if not '' in pathext: | |
pathext.insert(0, '') # always check command without extension, even for custom pathext | |
for dir in path: | |
basepath = join(dir, file) | |
for ext in pathext: | |
fullpath = basepath + ext | |
if exists(fullpath) and access(fullpath, mode): | |
yield fullpath | |
def which(file, mode=F_OK | X_OK, path=None, pathext=None): | |
""" Locate a file in a path supplied as a part of the file name, | |
or the user's path, or a supplied path. | |
The function returns full path (not necessarily absolute path), | |
in which the given file name matches an existing file in a directory on the path, | |
or raises IOError(errno.ENOENT). | |
>>> # for doctest see which_files() | |
""" | |
try: | |
return iter(which_files(file, mode, path, pathext)).next() | |
except StopIteration: | |
try: | |
from errno import ENOENT | |
except ImportError: | |
ENOENT = 2 | |
raise IOError(ENOENT, '%s not found' % (mode & X_OK and 'command' or 'file'), file) | |
if __name__ == '__main__': | |
main() |
description "odoo" | |
setuid {{ODOO_USER}} | |
start on startup | |
respawn | |
respawn limit 2 5 | |
exec /usr/local/src/odoo/openerp-server --config=/etc/odoo/odoo-server.conf --logfile=/var/log/odoo/odoo-server.log |
description "odoo-longpolling" | |
setuid {{ODOO_USER}} | |
start on startup | |
respawn | |
respawn limit 2 5 | |
exec /usr/local/src/odoo/openerp-gevent --config=/etc/odoo/odoo-server.conf --logfile=/var/log/odoo/odoo-server-longpolling.log |
[program:odoo-longpolling] | |
command=/usr/local/src/odoo/openerp-gevent --config=/etc/odoo/odoo-server.conf --logfile=/var/log/odoo/odoo-server-longpolling.log | |
autostart=true | |
autorestart=true | |
user={{ODOO_USER}} | |
directory=/opt/{{ODOO_USER}}/ | |
environment = HOME="/opt/{{ODOO_USER}}/",USER="{{ODOO_USER}}" | |
[options] | |
addons_path = /usr/local/src/odoo-addons/addons-extra,/usr/local/src/odoo/addons,/usr/local/src/odoo/openerp/addons,/usr/local/src/odoo-addons/addons-yelizariev,/usr/local/src/odoo-addons/pos-addons,/usr/local/src/odoo-addons/web,/usr/local/src/odoo-addons/server-tools | |
admin_passwd = {{ODOO_PASS}} | |
data_dir=/opt/{{ODOO_USER}}/.local/share/Odoo | |
dbfilter = .* # will show database selector if there are more than one database | |
#dbfilter = ^%h$ # select database automatically by domain. E.g. http://portal.example.com will show "portal.example.com" database | |
#dbfilter = ^%d$ # select database automatically by first subdomain (www is ignored). E.g. http://my.portal.example.com and http://www.my.portal.example.com will show "my" database | |
db_user = {{ODOO_USER}} | |
db_template = template1 | |
db_host = False | |
db_maxconn = 64 | |
db_name = False | |
db_password = False | |
db_port = False | |
auto_reload = False | |
csv_internal_sep = , | |
debug_mode = False | |
demo = {} | |
email_from = False | |
import_partial = | |
limit_memory_hard = 805306368 | |
limit_memory_soft = 671088640 | |
limit_request = 8192 | |
limit_time_cpu = 60 | |
limit_time_real = 120 | |
list_db = True | |
log_handler = ['["[\':INFO\']"]'] | |
log_level = info | |
#logfile = /var/log/odoo/odoo-server.log | |
login_message = False | |
logrotate = True | |
longpolling_port = 8072 | |
max_cron_threads = 2 | |
netrpc = False | |
netrpc_interface = | |
netrpc_port = 8070 | |
osv_memory_age_limit = 1.0 | |
osv_memory_count_limit = False | |
pg_path = None | |
pidfile = False | |
proxy_mode = False | |
reportgz = False | |
secure_cert_file = server.cert | |
secure_pkey_file = server.pkey | |
server_wide_modules = None | |
smtp_password = False | |
smtp_port = 25 | |
smtp_server = localhost | |
smtp_ssl = False | |
smtp_user = False | |
static_http_document_root = None | |
static_http_enable = False | |
static_http_url_prefix = None | |
syslog = False | |
test_commit = False | |
test_enable = False | |
test_file = False | |
test_report_directory = False | |
timezone = False | |
translate_modules = ['all'] | |
unaccent = False | |
without_demo = False | |
workers = 0 | |
xmlrpc = True | |
xmlrpc_interface = | |
xmlrpc_port = 8069 | |
xmlrpcs = True | |
xmlrpcs_interface = | |
xmlrpcs_port = 8071 |
[program:odoo] | |
command=/usr/local/src/odoo/openerp-server --config=/etc/odoo/odoo-server.conf --logfile=/var/log/odoo/odoo-server.log | |
autostart=true | |
autorestart=true | |
user={{ODOO_USER}} | |
directory=/opt/{{ODOO_USER}}/ | |
environment = HOME="/opt/{{ODOO_USER}}/",USER="{{ODOO_USER}}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment