Nextcloud sobre nginx y postgreSQL + fulltextsearch + paquetes ofimáticos collabora o onlyoffice-ds sobre docker

Hoy les traigo un manual de éstos tochos o al menos para llegar hasta aquí ya que hay mucha documentación pero ninguna que lo englobe todo, así que os voy a mostrar mi experiencia y los pasos seguidos.

Primero de todo, la política ha sido de instalar cada servicio en un contenedor o máquina virtual. La instalación de nextcloud va a estar instalada sobre un contenedor lxc y los paquetes ofimáticos, que los vamos a instalar usando docker, sobre las máquinas virtuales kvm. El motivo es que docker no funciona muy bien sobre contenedores lxc.

La otra cosa que tenemos que tener en cuenta, es que para hacer funcionar los paquetes ofimáticos, vamos a usar proxys de nginx, las máquinas van a requerir que se vean correctamente entre ellas y el usuario a las maquinas. Ésto lo comento porque la idea inicial era montar todo el sistema sobre un mismo servidor compartiendo la misma IP y repartir en el host que alberga las maquinas virtuales con iptables a los puertos correspondientes. Ésto me ha dado problemas, así que la mejor opción es servicios preparados.
En éste post me hubiese gustado documentar elasticsearch para poder buscar entre los ficheros, pero aún lo tengo a medio instalar y no he conseguido aún la comunicación. Espero que en unos días pueda publicar otro post en éste mismo blog de como hacer la integración nextcloud-fulltextsearch-elasticsearch.

Así que vamos a empezar! :)

Nextcloud
Partimos de un contenedor lxc, ésto quiere decir que el procedimiento se puede repetir en máquina física o otros tipos de máquinas virtuales. El sistema operativo, debian10. Cuidado que la debian estable actual, es la 9. He actualizado el sistema a Debian 10 para poder disponer de PHP7.3.2, ya que algunos plugins de nextcloud requieren PHP7.3 o superior. Más adelante voy a contar los truquillos usados para poder tener varias cosas que no funcionaban con PHP7.0.33 de debian9.

Lo primero es configurar el sistema, actualizarlo e instalar las dependencias necesarias para la instalación de nextcloud actual:

root@electra10-nextcloud:~# dpkg-reconfigure locales
root@electra10-nextcloud:~# dpkg-reconfigure tzdata
root@electra10-nextcloud:~# apt update && apt -y upgrade && apt -y dist-upgrade
root@electra10-nextcloud:~# apt install -y postgresql php-pgsql php-zip php-dompdf php-xml php-mbstring php-gd php-curl php-fpm php-intl php-common php-imagick php-ldap nginx unzip

Descargamos nextcloud y lo guardamos en /var/www:

root@electra10-nextcloud:~# cd /var/www
root@electra10-nextcloud:/var/www# wget https://download.nextcloud.com/server/releases/nextcloud-15.0.5.zip
root@electra10-nextcloud:/var/www# unzip nextcloud-15.0.5.zip

Tendremos que crear también el directorio donde se van a almacenar los datos de los usuarios de la instancia de nextcloud que estamos instalando. Aprovechamos para asignar los dos directorios creados al usuario www-data:

root@electra10-nextcloud:/var/www# mkdir ownclouddata
root@electra10-nextcloud:/var/www# chown -R www-data:www-data nextcloud
root@electra10-nextcloud:/var/www# chown -R www-data:www-data ownclouddata

El directorio que estoy usando se llama ownclouddata porque es una carpeta que arrastro desde hace años. Owncloud es el antecesor de Nextcloud. Comentar que la instalación que hice la hice copiando la carpeta ownclouddata de otra instancia de nextcloud en la misma versión que estamos instalando, también aproveché para cambiar la base de datos, así que partí de una instalación limpia y datos antiguos, la sorpresa fué que al crear los usuarios en la nueva instancia, al existir un directorio con ficheros existentes, internamente ejecuta ./occ files:scan -p “/files/” y aparecen por arte de magia todos los ficheros antiguos en la nueva instancia :)

Configuramos la base de datos PostgreSQL:

root@electra10-nextcloud:~# su - postgres
postgres@electra-nextcloud:~$ createuser nextcloud_capa8
postgres@electra-nextcloud:~$ createdb -O nextcloud_capa8 nextcloud_db
postgres@electra-nextcloud:~$ psql nextcloud_db

nextcloud_db=# alter user nextcloud_capa8 with encrypted password 'xxxxxxxxxxxxxxxxxxxxxxxx';
ALTER ROLE
nextcloud_db=# grant all privileges on database nextcloud_db to nextcloud_capa8;
GRANT

Creamos los certificados para https:

root@electra10-nextcloud:~# apt -y install python-certbot-nginx
root@electra10-nextcloud:~# certbot --nginx certonly -d cloud.capa8.net

Configuramos nginx:

root@electra10-nextcloud:~# vi /etc/nginx/sites-available/nextcloud
upstream php-handler {
    #server 127.0.0.1:9000;
    #server unix:/var/run/php/php7.4-fpm.sock;
    server unix:/var/run/php/php7.3-fpm.sock;	
}

server {
    listen 80;
    listen [::]:80;
    server_name cloud.capa8.net;

    # Enforce HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443      ssl http2;
    listen [::]:443 ssl http2;
    server_name cloud.capa8.net;

    # Use Mozilla's guidelines for SSL/TLS settings
    # https://mozilla.github.io/server-side-tls/ssl-config-generator/
    #ssl_certificate     /etc/ssl/nginx/cloud.example.com.crt;
    #ssl_certificate_key /etc/ssl/nginx/cloud.example.com.key;
    ssl_certificate /etc/letsencrypt/live/cloud.capa8.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/cloud.capa8.net/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_trusted_certificate /etc/letsencrypt/live/cloud.capa8.net/chain.pem;

    # HSTS settings
    # WARNING: Only add the preload option once you read about
    # the consequences in https://hstspreload.org/. This option
    # will add the domain to a hardcoded list that is shipped
    # in all major browsers and getting removed from this list
    # could take several months.
    add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload;" always;

    # set max upload size
    client_max_body_size 512M;
    fastcgi_buffers 64 4K;

    # Enable gzip but do not remove ETag headers
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;

    # Pagespeed is not supported by Nextcloud, so if your server is built
    # with the `ngx_pagespeed` module, uncomment this line to disable it.
    #pagespeed off;

    # HTTP response headers borrowed from Nextcloud `.htaccess`
    add_header Referrer-Policy                      "no-referrer"   always;
    add_header X-Content-Type-Options               "nosniff"       always;
    add_header X-Download-Options                   "noopen"        always;
    add_header X-Frame-Options                      "SAMEORIGIN"    always;
    add_header X-Permitted-Cross-Domain-Policies    "none"          always;
    add_header X-Robots-Tag                         "noindex, nofollow"          always;
    add_header X-XSS-Protection                     "1; mode=block" always;

    # Remove X-Powered-By, which is an information leak
    fastcgi_hide_header X-Powered-By;

    # Path to the root of your installation
    root /var/www/nextcloud;

    # Specify how to handle directories -- specifying `/index.php$request_uri`
    # here as the fallback means that Nginx always exhibits the desired behaviour
    # when a client requests a path that corresponds to a directory that exists
    # on the server. In particular, if that directory contains an index.php file,
    # that file is correctly served; if it doesn't, then the request is passed to
    # the front-end controller. This consistent behaviour means that we don't need
    # to specify custom rules for certain paths (e.g. images and other assets,
    # `/updater`, `/ocm-provider`, `/ocs-provider`), and thus
    # `try_files $uri $uri/ /index.php$request_uri`
    # always provides the desired behaviour.
    index index.php index.html /index.php$request_uri;

    # Default Cache-Control policy
    expires 1m;

    # Rule borrowed from `.htaccess` to handle Microsoft DAV clients
    location = / {
        if ( $http_user_agent ~ ^DavClnt ) {
            return 302 /remote.php/webdav/$is_args$args;
        }
    }

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location = /.well-known/webfinger {
      return 301 /index.php$uri;
    }

    location = /.well-known/nodeinfo {
      return 301 /index.php$uri;
    }

    # Make a regex exception for `/.well-known` so that clients can still
    # access it despite the existence of the regex rule
    # `location ~ /(\.|autotest|...)` which would otherwise handle requests
    # for `/.well-known`.
    location ^~ /.well-known {
        # The following 6 rules are borrowed from `.htaccess`

        rewrite ^/\.well-known/host-meta\.json  /public.php?service=host-meta-json  last;
        rewrite ^/\.well-known/host-meta        /public.php?service=host-meta       last;

        location = /.well-known/carddav     { return 301 /remote.php/dav/; }
        location = /.well-known/caldav      { return 301 /remote.php/dav/; }

        try_files $uri $uri/ =404;
    }

    # Rules borrowed from `.htaccess` to hide certain paths from clients
    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)  { return 404; }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console)              { return 404; }

    # Ensure this block, which passes PHP files to the PHP process, is above the blocks
    # which handle static assets (as seen below). If this block is not declared first,
    # then Nginx will encounter an infinite rewriting loop when it prepends `/index.php`
    # to the URI, resulting in a HTTP 500 error response.
    location ~ \.php(?:$|/) {
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        set $path_info $fastcgi_path_info;

        try_files $fastcgi_script_name =404;

        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $path_info;
        fastcgi_param HTTPS on;

        fastcgi_param modHeadersAvailable true;         # Avoid sending the security headers twice
        fastcgi_param front_controller_active true;     # Enable pretty urls
        fastcgi_pass php-handler;

        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }

    location ~ \.(?:css|js|svg|gif)$ {
        try_files $uri /index.php$request_uri;
        expires 6M;         # Cache-Control policy borrowed from `.htaccess`
        access_log off;     # Optional: Don't log access to assets
    }

    location ~ \.woff2?$ {
        try_files $uri /index.php$request_uri;
        expires 7d;         # Cache-Control policy borrowed from `.htaccess`
        access_log off;     # Optional: Don't log access to assets
    }

    location / {
        try_files $uri $uri/ /index.php$request_uri;
    }
}


root@electra10-nextcloud:~# ln -s /etc/nginx/sites-available/nextcloud /etc/nginx/sites-enabled/nextcloud
root@electra10-nextcloud:~# nginx -t
root@electra10-nextcloud:~# service nginx restart

Tuneamos un poco el php (cambiamos y añadimos las líneas)

root@electra10-nextcloud:/etc/php/7.3/fpm# vi php.ini
upload_max_filesize = 128M
max_file_uploads = 100

[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.memory_consumption=128
opcache.save_comments=1
opcache.revalidate_freq=1

root@electra10-nextcloud:/etc/php/7.3/fpm# cd pool.d/
root@electra10-nextcloud:/etc/php/7.3/fpm/pool.d# vi www.conf 
pm.max_children = 240
pm.start_servers = 24
pm.min_spare_servers = 12
pm.max_spare_servers = 36

; Default Value: clean env
env[HOSTNAME] = $HOSTNAME
env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp

root@electra10-nextcloud:/etc/php/7.3/fpm/pool.d# service php7.3-fpm restart

Reiniciamos nginx y php-fpm y accedemos por https a nuestro servidor para configurar nextcloud.

Una cosa muy interesante que podemos hacer a partir de aquí para mejorar la respuesta de nuestro servidor es instalar un servicio de caché, en la documentación nos ofrecen acpu o redis. Por versiones de los programas que hay en los repositorios de debian, nos decantaremos por redis. Para ello lo instalamos y lo configuramos en el fichero de configuración de nextcloud:

root@electra10-nextcloud:~# apt -y install redis-server php-redis
root@electra10-nextcloud:~# vi /var/www/nextcloud/config/config.php
$CONFIG = array (
  [...]
  'memcache.distributed' => '\OC\Memcache\Redis',
  //'memcache.local' => '\OC\Memcache\APCu',
  'memcache.locking' => '\OC\Memcache\Redis',
  'redis' => [
     'host' => 'localhost',
     'port' => 6379,
  ],
  [...]
);

En mi instalación he tenido problemas con systemd y lxc con partes del sistema compartido, es algo de debian10 con lxc y redis no me arranca directamente por systemd, así que le he hecho una chapuza que al levantar las interfaces de red, levante redis. Igualmente si quieres avanzar sin redis, memcached o lo que sea puedes usar la cache local

root@electra10-nextcloud:~# vi /var/www/nextcloud/config/config.php
$CONFIG = array (
  [...]
  'memcache.local' => '\OC\Memcache\APCu',
  [...]
);
root@electra10-nextcloud:~# vi /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
        address 192.168.1.6
        netmask 255.255.255.0
        gateway 192.168.1.1
        post-up /usr/bin/redis-server /etc/redis/redis.conf

Para comprobar que las configuraciones que hemos aplicado funcionan correctamente, ejecutaremos en la interfaz web la comprobación del sistema, en mi caso en la url https://cloud.capa8.net/index.php/settings/admin/overview.

Una vez instalado y configurado nextcloud, es posible que queramos activar plugins a cascoporro, algunos de ellos muy interesantes como el antivirus, para hacerlo funcionar deberemos instalar clamav:

root@electra10-nextcloud:~# apt -y install clamav

Si en algunos días notas que de repente webdav va lento, es culpa del antivirus, en mi caso de momento lo he desactivado, pero creo que la solución va por tunear un poco el clamav e indicarle a nextcloud el tamaño de los ficheros a analizar.

Otro plugin interesante y que requiere atención especial es mail. Es posible que en unos días éste párrafo quede obsoleto por la actualización del software. En el momento de hacer éste manual, la versión disponible del plugin mail de nextcloud era la 0.11, pero ésta no es compatible con la versión PHP7.3.2, así que traté de bajarme la master, pero no funcionaba, finalmente con la 0.12-RC2 si que me funcionó y tengo el mail funcionando :) Detallo como hacer la instalación que no está de menos ver como se instala manualmente un plugin de nextcloud:

Recomiendo que antes de realizar éste paso, desactives y desinstales la versión actual de mail.

root@electra10-nextcloud:/var/www# cd nextcloud/apps/
root@electra10-nextcloud:/var/www/nextcloud/apps# wget https://github.com/nextcloud/mail/releases/download/v0.12.0-RC2/mail.tar.gz
root@electra10-nextcloud:/var/www/nextcloud/apps# rm -R mail
root@electra10-nextcloud:/var/www/nextcloud/apps# tar xvzf mail.tar.gz

Otros plugins que son interesantes son fulltextsearch, que te permite indexar dentro el contenido de los ficheros (siempre y cuando no tengas el cifrado de los archivos activado). Gracias a la gente de sysadminsdecuba.com con los cuales empiezo compartiendo éste post publicándolo también en su blog :) doy las gracias especialmente a Alexminator por su orientación ;D

Elasticsearch
Aquí cojo un poco las indicaciones de Alexminator pero con algunas modificaciones ya que vamos a requerir la instalación y configuración de un par de plugins de elasticsearch.

Vamos a hacer la instalación en un contenedor lxc con 60Gb de disco, minimo 4Gb de RAM. Recomienda 4Gb de swap, aunque prefiero ampliar la RAM :P

Actualizamos el sistema e instalamos las dependencias

root@elasticsearch:~# apt update && apt -y upgrade && apt -y dist-upgrade && apt -y install vim mtr glances net-tools dnsutils mc curl htop
root@elasticsearch:~# apt install default-jre

A continuación, podríamos estar tentados de instalar la última versión, pero al hacerlo me ha dado un error, así que vamos a instalar la versión 6.6 que es la que se usa en la documentación de fulltextsearch (nextcloud).

root@elasticsearch:~# wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.6.2.deb
root@elasticsearch:~# dpkg -i elasticsearch-6.6.2.deb
root@elasticsearch:~# systemctl enable elasticsearch.service
root@elasticsearch:~# service elasticsearch start

Comprobamos que funciona (atención! es un programa de java, le lleva unos segunditos arrancar a la criatura…). Hay un plugin en fase beta sobre solr, otro indexador, otra bestia…

root@elasticsearch:~# netstat -lnap |grep 'LISTEN '
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      3979/sshd           
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      3834/master         
tcp6       0      0 :::9200                 :::*                    LISTEN      11151/java          
tcp6       0      0 127.0.0.1:9300          :::*                    LISTEN      11151/java          
tcp6       0      0 ::1:9300                :::*                    LISTEN      11151/java          
tcp6       0      0 :::22                   :::*                    LISTEN      3979/sshd           
tcp6       0      0 ::1:25                  :::*                    LISTEN      3834/master         
root@elasticsearch:~# curl http://127.0.0.1:9200
{
  "name" : "D5sOrBB",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "xxxxxxxxxxxxxxxxxxxxx",
  "version" : {
    "number" : "6.6.2",
    "build_flavor" : "default",
    "build_type" : "deb",
    "build_hash" : "xxxxxxx",
    "build_date" : "2019-03-06T15:16:26.864148Z",
    "build_snapshot" : false,
    "lucene_version" : "7.6.0",
    "minimum_wire_compatibility_version" : "5.6.0",
    "minimum_index_compatibility_version" : "5.0.0"
  },
  "tagline" : "You Know, for Search"
}
root@elasticsearch:~# curl http://localhost:9200/_nodes/process?pretty
{
  "_nodes" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "cluster_name" : "elasticsearch",
  "nodes" : {
    "xxxxxxxxxxxxxxxxxxxxx" : {
      "name" : "elasticsearch",
      "transport_address" : "127.0.0.1:9300",
      "host" : "127.0.0.1",
      "ip" : "127.0.0.1",
      "version" : "7.0.0",
      "build_flavor" : "default",
      "build_type" : "deb",
      "build_hash" : "xxxxxxx",
      "roles" : [
        "master",
        "data",
        "ingest"
      ],
      "attributes" : {
        "ml.machine_memory" : "25270226944",
        "xpack.installed" : "true",
        "ml.max_open_jobs" : "20"
      },
      "process" : {
        "refresh_interval_in_millis" : 1000,
        "id" : 9764,
        "mlockall" : true
      }
    }
  }
}

Y lo tuneamos para optimizar el uso de RAM

root@elasticsearch:~# vi /etc/default/elasticsearch
MAX_LOCKED_MEMORY=unlimited

root@elasticsearch:~# systemctl edit elasticsearch
[Service] 
LimitMEMLOCK=infinity

root@elasticsearch:~# systemctl daemon-reload
root@elasticsearch:~# service elasticsearch restart

Y volvemos a comprobar el nodo con los comandos de antes

root@elasticsearch:~# !?netstat
root@elasticsearch:~# curl http://127.0.0.1:9200
root@elasticsearch:~# curl http://localhost:9200/_nodes/process?pretty

Lo siguiente será preparar el entorno para que se pueda conectar nuestro servidor de nextcloud

root@elasticsearch:~# vi /etc/elasticsearch/elasticsearch.yml
node.name: elasticsearch-1

http.host: 0.0.0.0
http.cors.allow-origin: "*"
http.cors.enabled: true

root@elasticsearch:~# systemctl daemon-reload
root@elasticsearch:~# service elasticsearch restart

Instalamos el plugin ingest-attachment

root@elasticsearch:~# cd /var/lib/elasticsearch/bin
root@elasticsearch:/usr/share/elasticsearch/bin# ./elasticsearch-plugin install ingest-attachment
-> Downloading ingest-attachment from elastic
[=================================================] 100%?? 
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@     WARNING: plugin requires additional permissions     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
* java.lang.RuntimePermission accessClassInPackage.sun.java2d.cmm.kcms
* java.lang.RuntimePermission accessDeclaredMembers
* java.lang.RuntimePermission getClassLoader
* java.lang.reflect.ReflectPermission suppressAccessChecks
* java.security.SecurityPermission createAccessControlContext
* java.security.SecurityPermission insertProvider
* java.security.SecurityPermission putProviderProperty.BC
See http://docs.oracle.com/javase/8/docs/technotes/guides/security/permissions.html
for descriptions of what these permissions allow and the associated risks.

Continue with installation? [y/N]y
-> Installed ingest-attachment

Configuramos el x-pack para proteger elasticsearch bajo un usuario y contraseña y reiniciamos el servicio. Con la versión 6.6 x-pack viene por defecto, en caso de no estar instalado sigue éstas instrucciones.
Bueno, pues siguiendo un poco el hilo, parece que xpack es un módulo de pago, así que tendremos que buscar otra forma de proteger el servidor por ejemplo así

##### TODO
  114  iptables -I INPUT -p tcp -s 195.154.214.201 --dport 9200 -j ACCEPT
  115  iptables -I INPUT -p tcp -s 195.154.214.201 --dport 9300 -j ACCEPT
  116  iptables -I INPUT -p tcp -s 0.0.0.0/0 --dport 9200 -j DROP
  117  iptables -I INPUT -p tcp -s 0.0.0.0/0 --dport 9300 -j DROP
  
  121  iptables -L --line-numbers
  122  iptables -D INPUT 4
  123  iptables -D INPUT 3
  124  iptables -D INPUT 2
  125  iptables -D INPUT 1

Ésto aún está en pruebas

A continuación en la interfaz de administrador de nextcloud activamos las 3 aplicaciones Full text search, Full text search – Files y Full text search – Elasticsearch Platform, luego la configuramos en los parámetros y le indicamos la dirección de nuestro servidor en el puerto 9200. Si vamos a compartir el servidor de elasticsearch con otros nextcloud o otros servicios, recomiendo definir un nombre para éste indexador.

Ahora para verificar que todo está funcionando correctamente, entramos al servidor de nextcloud por ssh y en ./occ fulltextsearch:help podremos ver todas las opciones. Lo mejor es dejar que trabaje solo, para comprobar que está todo ok usamos el comando “test”

www-data@electra10-nextcloud:~/nextcloud$ ./occ fulltextsearch:test
 
.Testing your current setup:  
Creating mocked content provider. ok  
Testing mocked provider: get indexable documents. (2 items) ok  
Loading search platform. (Elasticsearch) ok  
Testing search platform. ok  
Locking process ok  
Removing test. ok  
Pausing 3 seconds 1 2 3 ok  
Initializing index mapping. ok  
Indexing generated documents. ok  
Pausing 3 seconds 1 2 3 ok  
Retreiving content from a big index (license). (size: 32386) ok  
Comparing document with source. ok  
Searching basic keywords:  
 - 'test' (result: 1, expected: ["simple"]) ok  
 - 'document is a simple test' (result: 2, expected: ["simple","license"]) ok  
 - '"document is a test"' (result: 0, expected: []) ok  
 - '"document is a simple test"' (result: 1, expected: ["simple"]) ok  
 - 'document is a simple -test' (result: 1, expected: ["license"]) ok  
 - 'document is a simple +test' (result: 1, expected: ["simple"]) ok  
 - '-document is a simple test' (result: 0, expected: []) ok  
Updating documents access. ok  
Pausing 3 seconds 1 2 3 ok  
Searching with group access rights:  
 - 'license' - [] -  (result: 0, expected: []) ok  
 - 'license' - ["group_1"] -  (result: 1, expected: ["license"]) ok  
 - 'license' - ["group_1","group_2"] -  (result: 1, expected: ["license"]) ok  
 - 'license' - ["group_3","group_2"] -  (result: 1, expected: ["license"]) ok  
 - 'license' - ["group_3"] -  (result: 0, expected: []) ok  
Searching with share rights:  
 - 'license' - notuser -  (result: 0, expected: []) ok  
 - 'license' - user2 -  (result: 1, expected: ["license"]) ok  
 - 'license' - user3 -  (result: 1, expected: ["license"]) ok  
Removing test. ok  
Unlocking process ok 

Ahora a esperar y a cruzar los dedos de que indexe dentro de los documentos! esto puede tardar un poco mas o un poco menos dependiendo del numero de ficheros que tiene tu instancia de nextcloud.

Y ahora ya vamos para los plugins tochos, tochos, tochos, mas bien plugin, en singular. Voy a mostrar como se instalan ambos plugins, pero sólo uno de los dos puede estar activo al mismo tiempo, hablamos de collabora o collaboraoffice y onlyoffice.

Empezamos por el que inicialmente tenía previsto y seguiremos con otro que no está de mal pegarle una ojeadilla :)

Collabora o Collaboraoffice
Lo primero, no te lies, docker hehe. He probado varias formas de instalarlo, al igual que el onlyoffice y el elasticsearch y recomiendo hacer un pequeño esfuerzo para mirar en serio docker, si aún no tocas docker como me pasaba a mi hace unos días, espero que éste manual te sirva como breve introducción a docker… vas a ver el mundo de otra forma!

Tal como he comentado al principio, docker y lxc mal, así que partimos de una debian 9 instalada dentro de un KVM, con su propia IP pública y su propio nombre de dominio.

Primero, instalamos docker:

root@collabora:~# apt update && apt-get -y upgrade && apt-get -y dist-upgrade && apt -y install vim mtr glances net-tools curl nginx
root@collabora:~# vi /etc/apt/sources.list
# docker
deb [arch=amd64] https://download.docker.com/linux/debian stretch stable
# deb-src [arch=amd64] https://download.docker.com/linux/debian stretch stable

root@collabora:~# apt -y install apt-transport-https ca-certificates curl gnupg2 software-properties-common
root@collabora:~# curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - && apt-key fingerprint 0EBFCD88 

root@collabora:~# apt update 
root@collabora:~# apt -y remove docker docker-engine docker.io containerd runc
root@collabora:~# apt -y install docker-ce --allow-unauthenticated

Una vez instalado, vamos a descargar la imagen de collabora del repositorio de docker:

root@collabora:~# docker run -t -d -p 127.0.0.1:9980:9980 -e "domain=cloud\.capa8\.net" -e "username=admin" -e "password=xxxxx" -e "extra_params=--o:net.post_allow.host=172\.17\.0\.1 --o:net.proto=IPv4" --restart always collabora/code

Con mucho cuidado con éste comando, primero de todo, tendremos que indicarle el dominio que va a comunicar con éste servidor, en mi caso, el servidor de nextcloud lo tengo bajo cloud.capa8.net, y el que estoy instalando se llama collabora.capa8.net, otro es permitir sólo IPv4 (en resumen hehe) y que se encienda siempre que se reinicie la máquina host. Le indicaremos usuario y contraseña para poder acceder al panel administrativo:

https://collabora.capa8.net/loleaflet/dist/admin/adminSettings.html

Ahora lo siguiente será configurar nginx

Creamos los certificados para https:

root@collabora:~# vi /etc/apt/sources.list
# debian backports
deb http://ftp.de.debian.org/debian stretch-backports main

root@collabora:~# apt update && apt -y install python-certbot-nginx -t stretch-backports
root@collabora:~# certbot --nginx certonly

Configuramos nginx:

root@collabora:~# vi /etc/nginx/sites-available/collabora
server {
    listen               443 ssl http2;
    server_name          collabora.capa8.net;
    ssl_certificate /etc/letsencrypt/archive/collabora.capa8.net/fullchain1.pem;
    ssl_certificate_key /etc/letsencrypt/archive/collabora.capa8.net/privkey1.pem;
    client_max_body_size 10G;
    proxy_set_header     X-Forwarded-Proto 'https';
    underscores_in_headers on;
    add_header           Strict-Transport-Security "max-age=31536000";

    location /.well-known/ {
        root   /var/lib/nginx/letsencrypt/;
        index  index.html index.htm;
    }

    # static files
    location ^~ /loleaflet {
        proxy_pass        https://127.0.0.1:9980;
        proxy_set_header Host $http_host;
        proxy_ssl_verify              off;
    }

    # WOPI discovery URL
    location ^~ /hosting/discovery {
        proxy_pass        https://127.0.0.1:9980;
        proxy_set_header Host $http_host;
        proxy_ssl_verify              off;
        
        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    # Main websocket
    location ~ /lool/(.*)/ws$ {
        proxy_pass        https://127.0.0.1:9980;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $http_host;
        proxy_read_timeout 36000s;
        proxy_ssl_verify              off;
        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

    }

    # Admin Console websocket
    location ^~ /lool/adminws {
        proxy_pass        https://127.0.0.1:9980;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header Host $http_host;
        proxy_read_timeout 36000s;
        proxy_ssl_verify              off;
        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

    }

    # download, presentation and image upload
    location ^~ /lool {
        proxy_pass        https://127.0.0.1:9980;
        proxy_set_header Host $http_host;
        proxy_ssl_verify              off;
        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

    }

    location / {
        proxy_pass        https://127.0.0.1:9980;
        proxy_set_header Host $http_host;
        proxy_ssl_verify              off;

        # WebSocket support
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

}

root@collabora:~# ln -s /etc/nginx/sites-available/collabora /etc/nginx/sites-enabled/collabora
root@collabora:~# nginx -t
root@collabora:~# service nginx restart

Vamos ahora a nextcloud y le indicamos la ubicación del servidor de collabora.

Onlyoffice

El otro cabroncete, pero aquí tenéis la solución de como hacerlo rápido y sencillo. Partimos tal como he dicho de una maquina virtual kvm, evidentemente con debian9.

Primero de todo y realmente muy importante de tener en cuenta, queremos onlyoffice para conectarlo con nuestro nextcloud, pero no lo queremos entero, sólo un trozo! con ésta instalación queda otro software tocho que es interesante echarle una ojeadilla, y más que he conseguido instalarlo hehe. Post en breve :P

Empezamos, actualización de sistema e instalación de docker:

root@onlyofficeds:~# apt update && apt-get -y upgrade && apt-get -y dist-upgrade && apt -y install vim mtr glances net-tools 
root@onlyofficeds:~# vi /etc/apt/sources.list
# docker
deb [arch=amd64] https://download.docker.com/linux/debian stretch stable
# deb-src [arch=amd64] https://download.docker.com/linux/debian stretch stable

root@onlyofficeds:~# apt -y install apt-transport-https ca-certificates curl gnupg2 software-properties-common
root@onlyofficeds:~# curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add - && apt-key fingerprint 0EBFCD88 

root@onlyofficeds:~# apt update 
root@onlyofficeds:~# apt -y remove docker docker-engine docker.io containerd runc
root@onlyofficeds:~# apt -y install docker-ce --allow-unauthenticated

Una vez instalado, vamos a descargar la imagen de onlyoffice del repositorio de docker:

root@onlyofficeds:~# docker run -i -t -d -p 80:80 --restart=always onlyoffice/documentserver

Ésto. ¿Cómo, si ya? Vamos a arrancarlo sólo por http, el https lo gestionamos con nginx fuera del contenedor de docker.

Ahora lo siguiente será configurar nginx

Creamos los certificados para https:

root@onlyofficeds:~# vi /etc/apt/sources.list
# debian backports
deb http://ftp.de.debian.org/debian stretch-backports main

root@onlyofficeds:~# apt update && apt -y install python-certbot-nginx -t stretch-backports
root@onlyofficeds:~# certbot --nginx certonly

Configuramos nginx:

root@onlyofficeds:~# vi /etc/nginx/sites-available/onlyofficeds
server {
    include snippets/certbot.conf;

    listen 443 ssl http2;
    listen [::]:8443 ssl http2;
    ssl_certificate /etc/letsencrypt/live/onlyofficeds.capa8.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/onlyofficeds.capa8.net/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_trusted_certificate /etc/letsencrypt/live/onlyofficeds.capa8.net/chain.pem;

    #server_name onlyoffice.capa8.net;

    location / {
        proxy_pass http://localhost:80;
        include proxy_params;
    }
}
root@onlyofficeds:~# mkdir /etc/nginx/snippets
root@onlyofficeds:~# vi /etc/nginx/snippets/certbot.conf
# set client body size to 2M #
client_max_body_size 20M;

location ~ /.well-known {
    allow all;
    root /var/www/html;
}
root@onlyofficeds:~# ln -s /etc/nginx/sites-available/onlyofficeds /etc/nginx/sites-enabled/onlyofficeds
root@onlyofficeds:~# nginx -t
root@onlyofficeds:~# service nginx restart

Vamos ahora a nextcloud y le indicamos la ubicación del servidor de onlyoffice. Si nos encontramos que no funciona, mi recomendación es entrar en el contenedor y revisar los logs. Si te encuentras con problemas de permisos de acceso, te recomiendo entrar en el contenedor y añadir las ips en el fichero /etc/loolwsd/loolwsd.xml.
Todos los signos punto en la configuración, deben ser escapados, es decir, . tiene que ser \.

Y hasta aquí la configuración de los servicios. Unos breves y útiles apuntes de docker:

Listar los contenedores de docker existentes, con -a muestra los apagados

root@onlyofficeds:~# docker ps
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS              PORTS                         NAMES
xxxxxxxxxxxx        onlyoffice/documentserver   "/bin/sh -c /app/onl…"   3 hours ago         Up 3 hours          0.0.0.0:80->80/tcp, 443/tcp   flamboyant_goodall
root@onlyofficeds:~# docker ps -a
CONTAINER ID        IMAGE                       COMMAND                  CREATED             STATUS                     PORTS                         NAMES
xxxxxxxxxxxx        onlyoffice/documentserver   "/bin/sh -c /app/onl…"   3 hours ago         Up 3 hours                 0.0.0.0:80->80/tcp, 443/tcp   flamboyant_goodall
xxxxxxxxxxxx        onlyoffice/documentserver   "/bin/sh -c /app/onl…"   22 hours ago        Exited (137) 3 hours ago                                 sleepy_shamir

Entrar por shell a un contenedor

root@onlyofficeds:~# docker exec -i -t flamboyant_goodall /bin/bash

Ver los logs del contendedor, usar -f para salida continua

root@onlyofficeds:~# docker logs flamboyant_goodall
root@onlyofficeds:~# docker logs flamboyant_goodall -f

Se recomienda no manipular los contenedores, a menos que sea aplicar algunas configuraciones.

4 Comments

  1. Hola Blackhold, un post genial como siempre. A ver si tomo ejemplo y publico más cosas, jaja. Aunque últimamente lo único que subo es código a GitLab.

    Quería comentarte que es más securo sacar el directorio ownclouddata fuera del DocumentRoot, pues al estar sobre PHP el usuario www-data puede acceder a cualquier directorio del servidor al que tenga permiso, por lo que el intérprete de PHP también.

    Veo que estás empezando a usar Docker, lo cual es súper bueno y es algo que todos tendremos que saber, yo empecé a jugar con Docker cuando estaba en Gaueko. Si quieres automatizar este despliegue o simplificar cuando levantes varios contenedores diferentes, te recomiendo que le eches un ojo a Docker Compose: https://docs.docker.com/compose/

    Yéndonos a algo más grande, podrías plantearte usar OpenShift (Que también se ofrece en versión gratuita) e incluso puedes usar la versión enterprise de Red Hat si es sólo para desarrollo en: https://developers.redhat.com. Lo que pasa es que ahí deberías replantearte la arquitectura porque es una bestia un poco grande que incluye Jenkins, Docker, Kubernetes, etc. Te serviría para tener todo en el mismo host tal y como querías pero no podías por LXC.

    En cuanto a LXC, sí, es problemático con Docker pues (purismos a parte) usan una tecnología más o menos similar. La arquitectura que yo sigo en mi local es KVM con virt-manager (En un server puedes usar OVirt, pues usa KVM por dentro), creo una máquina virtual con Docker y allá despliego mis containers. También sería interesante que tuvieses tu propio registro privado de imágenes Docker en tu infraestructura de servicios locales para ahorrar ancho de banda y tiempo en el despliegue de las mismas.

    Estas son algunas sugerencias que me vienen a la mente así de repente. Con Elasticsearch no puedo ayudarte mucho pues nunca tuve la oportunidad de pegarle directamente pero si ves que se te complica podemos hacer una conferencia on-line en algún momento a ver si lo resolvemos. Te debo una por la gran ayuda que nos brindaste en una instalación de guifi.net hace algunos años.

    Estoy súper contento de ver que sigues imparable. Besarkada estu-estu bat.

    Respon
  2. para el error “El mòdul php-imagick d’aquesta instància no té suport per SVG. Es recomana instal·lar-lo per una millor compatibilitat.” instalar esto:

    apt -y install libmagickcore-6.q16-6-extra

    Respon

Deixa un comentari

L'adreça electrònica no es publicarà. Els camps necessaris estan marcats amb *

Aquest lloc utilitza Akismet per reduir els comentaris brossa. Apreneu com es processen les dades dels comentaris.