Skip to content

Instantly share code, notes, and snippets.

@Danisan
Forked from yelizariev/install-odoo.sh
Last active August 29, 2015 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Danisan/24edea2a72a9c7d04478 to your computer and use it in GitHub Desktop.
Save Danisan/24edea2a72a9c7d04478 to your computer and use it in GitHub Desktop.
#### 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