Prácticas con Odoo

Configuración del sistema

En resumidas cuentas:

  • Odoo (antiguo OpenERP) como sw de gestión/ERP
  • Docker como sistema de contenedores
  • postgresql como SGBDR
  • haproxy como proxy inverso https
  • CentOS 7 como SO Linux

Menos Odoo todos los demás productos vienen de serie en las versiones modernas de las distros CentOS y Fedora.

En este caso usaremos una aproximación de operación con contenedores Docker. La tecnología de contenedores permite configuraciones semejantes a las que se pueden hacer con máquinas virtuales pero con menos coste de memoria y CPU. Eso no significa que un contenedor pueda sustituir a una máquina virtual (corriendo sobre kvm, Xen, VirtualBox o VMWare) en todos los casos o que sea superior a estas en todas las circunstancias. Sin embargo es una aproximación de moda que cuenta con varias comodidades.

Odoo ha sido elegido por varios motivos:

  • es software libre (v8 tiene licencia AGPL)
  • corre en Linux con toda normalidad
  • es un producto con solera y con una comunidad importante de usuarios, desarrolladores y proveedores en todo el mundo
  • la oferta de módulos y añadidos es importante y cubre la reglamentación española
  • es muy maduro, aun con los cambios que se le están realizando desde las versiones v5
  • es el que debe implantar este que suscribe para sostener las actividades de la asociación Club de Cacharreo

La elección de postgresql es obvia. Es un producto magnífico y está perfectamente integrado con Odoo.

haproxy es un añadido necesario. Por algún extraño motivo que escapa a nuestra comprensión Odoo no implementa en su servidor web el soporte TLS (https). Como en nuestra instalación eran inevitables los accesos desde internet con navegador web se hacía intolerable cualquier riesgo de interceptación de información y una de las alternativas más asequibles consiste en levantar un proxy inverso TLS ligero que cifre las comunicaciones web desde el exterior.

Sobre CentOS la pregunta no es por qué lo hemos elegido nosotros sino por qué no lo habéis elegido los demás.

Preparación del sistema

Instalamos las dependencias docker:

dnf install -y docker-io fig    # instalamos los paquetes que vamos a necesitar con todas sus dependencias
systemctl enable docker.service # activamos el servicio docker desde el arranque del sistema
systemctl start docker.service  # ponemos en ejecución el servicio docker

En general, para usar docker es necesario tener permisos de superusuario, pero podemos evitarlo añadiendo nuestro usuario al grupo adecuado del sistema:

usermod usuario -G docker

Configuración de los contenedores

Podemos levantar una configuración de contenedores docker de varias maneras pero aquí usaremos la herramienta fig porque su fichero de configuración es muy expresivo. Ojo: las versiones más recientes de fig ahora se desarrollan como docker compose.

Buena parte de las ventajas de usar Docker consiste en la biblioteca de imágenes que mantiene el proyecto. Usaremos varias de llas

También usamos imágenes publicadas en el registro público de docker.

En particular, y tras varios intentos no demasiado exitosos descubrimos a un alma gemela que por días nos llevaba ventaja en su propia configuración de un sistema equivalente. Yajo estaba creando casi en paralelo el mismo sistema en el que nosotros hemos estado trabajando pero, realmente, lo estaba haciendo mejor.

Algo muy remarcable y que casi reduce al mínimo la complejidad de la instalación es el uso de la herramienta de «orquestación» de contenedores fig (aunque Yajo ya se refiere a ella con el nombre actual docker composer). Más adelante resumimos la configuración de orquestación elegida.

Pasos para la configuración

Creamos el directorio para el proyecto. El nombre es arbitrario pero, ojo, será usado por fig para nombrar los contenedores a crear.

mkdir odoo-cacharreo.club
cd odoo-cacharreo.club

A continuación creamos un fichero fig.yml que expresará la configuración de la orquestación docker con los siguientes contenidos:

# Odoo server itself
app:
    image: yajo/odoo:latest
    environment:
        # Default values (you **must** change ADMIN_PASSWORD)
        ADMIN_PASSWORD: ********
        DATABASE: odoo
        ODOO_SERVER: odoo.py
        UNACCENT: True
        WDB_NO_BROWSER_AUTO_OPEN: True
        WDB_SOCKET_SERVER: wdb
        WDB_WEB_PORT: 1984
        WDB_WEB_SERVER: localhost
    # If you are going to use the HTTPS proxy for production,
    # don't expose any ports
    ports:
        - "8069:8069"
        - "8072:8072"
    volumes:
        # Assuming you have an addons subfolder in the working tree
        - addons:/opt/odoo/extra-addons:ro
    volumes_from:
        - appdata
    links:
        - db
        - wdb # Debugger, only for development
    command: launch

# Hold separately the volumes of Odoo variable data
appdata:
    image: yajo/odoo:data

# PostgreSQL server
db:
    image: postgres:9.2
    environment:
        # You **must** change these
        POSTGRES_USER: odoo
        POSTGRES_PASSWORD: *************
    volumes_from:
        - dbdata

# PostgreSQL data files
dbdata:
    image: postgres:9.2
    command: "true"

# For development, add a debugger
wdb:
    image: yajo/wdb-server
    ports:
        - "1984:1984"

# For production, you will likely use HTTPS
https:
    image: yajo/https-proxy
    ports:
        - "800:80"
        - "4433:443"
    links:
        - app:www
    environment:
        PORT: 8069
        # In case you have your SSL key & certs, put them here:
        KEY: |
            -----BEGIN RSA PRIVATE KEY-----
            MIIEowIBAAKCAQEAvxDL6GSCI5rIU7MT92gqwk05TlXalYd3QOuDiAULf/1M3HaA
            YcpgK6M9KIFDUKrG3OXmbOFa8vE0mFHsYXEX+cSyu4oBkyJNufe6oyywg3FJj+Q8
            -----END RSA PRIVATE KEY-----
        CERT: |
            -----BEGIN CERTIFICATE-----
            MIIDcDCCAlgCCQC73VZzsoPIyTANBgkqhkiG9w0BAQUFADB6MQswCQYDVQQGEwJF
            UzEVMBMGA1UEBwwMRGVmYXVsdCBDaXR5MRowGAYDVQQKDBFDbHViIGRlIENhY2hh
            cnJlbzENMAsGA1UEAwwEb2RvbzEpMCcGCSqGSIb3DQEJARYaaXNtYWVsLm9sZWFA
            -----END CERTIFICATE-----

La sintaxis es YAML.

Puede observarse que el fichero fig.yml es bastante explícito. Define seis contenedores diferentes y las respectivas propiedades docker de los mismos:

  • app: con el código de Odoo
  • appdata: datos de trabvajo de Odoo alojados fuera de la bbdd
  • db: con el ejecutable de postgresql
  • dbdata: con, exclusivamente, los ficheros de la bbdd usada por Postgresql
  • wdb: consoola de depuración de aplicaciones de Odoo
  • https: proxy TLS inverso

PORHACER: explicar la configuración fig PORHACER: explicar el procedimiento de creación de la orquestación (pasos intermedios)

Para saber si docker está operativo en nuestro sistema podemos usar la orden docker info que dará un resultado semejante a :

$ docker info
Containers: 0
Images: 158
Storage Driver: devicemapper
 Pool Name: docker-253:1-1970278-pool
 Pool Blocksize: 65.54 kB
 Data file: /var/lib/docker/devicemapper/devicemapper/data
 Metadata file: /var/lib/docker/devicemapper/devicemapper/metadata
 Data Space Used: 6.67 GB
 Data Space Total: 107.4 GB
 Metadata Space Used: 9.781 MB
 Metadata Space Total: 2.147 GB
 Library Version: 1.02.93 (2015-01-21)
Execution Driver: native-0.2
Kernel Version: 3.17.4-301.fc21.x86_64
Operating System: Fedora 21 (Twenty One)
CPUs: 4
Total Memory: 11.73 GiB
Name: torlpedo.local
ID: AWLT:ZWM2:TPPM:6ORZ:V4RH:LSYM:ZSTX:JUJP:HRRP:U4WS:YGGJ:MY2G

Y verificamos que no hay contenedores instalados usando docker ps -a:

$ docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

Entonces, desde el mismo subdirectorio en el que nos encontramos, podemos usar la orden fig para levantar la configuración de los tres contenedores:

$ fig up -d
Creating odoocacharreoclub_dbdata_1...
Creating odoocacharreoclub_db_1...
Creating odoocacharreoclub_appdata_1...
Creating odoocacharreoclub_app_1...
Creating odoocacharreoclub_https_1...
Creating odoocacharreoclub_wdb_1...

Obsérvese:

  • que la opción -d (por detach) que levanta los contenedores corriendo como proceso de fondo;
  • que docker busca las imágenes preconfiguradas que indicamos en fig.yml primero entre las que están operativas en el sistema, después entre las descargadas en su caché interna y finalmente las descarga del registro público y que todo el proceso es completamente automático y transparente;
  • que fig ha añadido el prefijo odoocacharreoclub* a cada nombre que elegimos para los contenedores.

A continuación podemos comprobar que realmente nuestros contenedores están operativos.

Vistos desde fig:

    $ fig ps
               Name                          Command               State                        Ports
    ----------------------------------------------------------------------------------------------------------------------
    odoocacharreoclub_app_1       launch                           Up       0.0.0.0:8069->8069/tcp, 0.0.0.0:8072->8072/tcp
    odoocacharreoclub_appdata_1   /bin/sh -c true                  Exit 0
    odoocacharreoclub_db_1        /docker-entrypoint.sh postgres   Up       5432/tcp
    odoocacharreoclub_dbdata_1    /docker-entrypoint.sh true       Exit 0
    odoocacharreoclub_https_1     /usr/local/sbin/launch.sh        Up       0.0.0.0:4433->443/tcp, 0.0.0.0:800->80/tcp
    odoocacharreoclub_wdb_1       /bin/sh -c wdb.server.py - ...   Up       0.0.0.0:1984->1984/tcp, 19840/tcp

La misma configuración vista desde docker

$ docker ps
CONTAINER ID        IMAGE                     COMMAND                CREATED             STATUS              PORTS                                            NAMES
5cb46e82bb98        yajo/https-proxy:latest   "/usr/local/sbin/lau   10 days ago         Up 36 hours         0.0.0.0:800->80/tcp, 0.0.0.0:4433->443/tcp       odoocacharreoclub_https_1
b3d96cf39863        yajo/odoo:latest          "launch"               10 days ago         Up 36 hours         0.0.0.0:8069->8069/tcp, 0.0.0.0:8072->8072/tcp   odoocacharreoclub_app_1
f52a733241cd        postgres:9.2              "/docker-entrypoint.   10 days ago         Up 36 hours         5432/tcp                                         odoocacharreoclub_db_1
3f5891cf1bc0        yajo/wdb-server:latest    "/bin/sh -c 'wdb.ser   10 days ago         Up 36 hours         0.0.0.0:1984->1984/tcp, 19840/tcp                odoocacharreoclub_wdb_1

¿Por qué las diferencias? Fácil, porque invocar docker ps sólo muestra los contenedores que están en ejecución y tanto odoocacharreoclub_dbdata_1 como odoocacharreoclub_appdata_1 no son contenedores que ejecutan código sino que sirven como almacenes de datos.

Para poder entender la complejidad de esta configuración obsérvese la relación entre las diferentes versiones del ciclo de vida de las imágenes docker:

Finalmente la aplicación Odoo queda accesible desde el puerto 4433, con cifrado TLS. En nuestro caso la dirección final es https://olea.wtf.im:4433, que utiliza un DNS dinámico ya que se aloja edentro de la red de un usuario de banda ancha de consumo.

Pendientes:

  • instalar whtmltopdf
  • El ajuste final de la orquestación aún está pendiente: básicamente cerrar algunos puertos que realmente no van a usarse
  • desactivar el módulo de depuración de Odoo
  • tal vez crear un nuevo certifacdo X509 para el proxy inverso para hacer más cómodo el uso en el navegador de certificados autofirmados
  • mejorar la configuración de haproxy para evitar el uso de algoritmos inseguros como SSLv3
  • arreglar ERROR del cron:https://www.odoo.com/forum/help-1/question/could-not-obtain-lock-on-row-in-relation-ir-cron-74519
  • arreglar «WARNING club-de-cacharreo openerp.modules.registry: The option --unaccent was given but no unaccent() function was found in database»,

    • mirar aquí por si acaso.
    • app_1     | Trying to install unaccent extension
      app_1     | CREATE EXTENSION
      app_1     | NOTICE:  extension "unaccent" already exists, skipping
      app_1     | Executing 'odoo.py --config /etc/odoo/openerp-server.conf'