Instalación previa

Para poder realizar la instalación de la aplicación web, vamos a necesitar una serie de herramientas y servicios que vamos a instalar en el servidor. Pero primero lo realizaremos en un escenario local para poder realizar las pruebas necesarias.

El escenario contará con dos máquinas:

  • Servidor web: conectada a una red pública.
  • Servidor de base de datos: conectado a una red privada, conectada a la máquina anterior.

Creamos el LAMP

Una pila LAMP es un conjunto de software libre que proporciona una plataforma de servidor web. Está formado por los siguientes componentes:

  • Debian-like Linux: sistema operativo.
  • Apache: servidor web.
  • MySQL: sistema de gestión de bases de datos.
  • PHP: lenguaje de programación.

Para crear el LAMP, vamos a utilizar una máquina virtual con Debian 11 Bullseye. Para ello, vamos a utilizar vmware:

$ sudo apt update
$ sudo apt install -y apache2
$ sudo apt install -y mariadb-server
$ sudo apt install -y php

Modulos PHP

Para que las herramientas que instalaremos funcionen correctamente, vamos a instalar una serie de módulos PHP:

sudo apt install php-imagick php7.4-common php7.4-curl php7.4-gd php7.4-imap php7.4-intl php7.4-json php7.4-ldap php7.4-mbstring php7.4-mysql php7.4-xml php7.4-zip

Configuración mariadb

En cuanto a mysql, se recomienda retirar ajustes predeterminados que son poco seguros y bloquearán el acceso a la base de datos. Para ello, vamos a ejecutar el siguiente comando:

sudo mysql_secure_installation

Creamos la base de datos para Nextcloud:

mysql -u root -p
CREATE DATABASE owncloud;
CREATE USER 'maria1'@'10.0.100.1';
GRANT ALL PRIVILEGES ON owncloud.* TO 'maria1'@'localhost' IDENTIFIED BY 'admin';
FLUSH PRIVILEGES;

OWNCLOUD

Owncloud es un servidor de archivos que permite el almacenamiento, la colaboración y el uso compartido seguros. Es conveniente almacenar archivos en la nube, por lo que están disponibles en cualquier dispositivo y se pueden compartir con unos pocos clics.

Ayuda a los usuarios a recuperar su soberanía digital. También proporciona muchas funciones convenientes, pero también almacena archivos de forma segura y eficiente. No hay puertas traseras, puedes comprobarlo. Los usuarios pueden instalar ownCloud ellos mismos o alquilar una instancia administrada.

Descargamos Owncloud

Descargamos la aplicación web desde la página oficial de Nextcloud:

wget https://download.owncloud.com/server/stable/owncloud-complete-latest.zip

Y la descomprimimos en el directorio /var/www/:

sudo unzip owncloud-complete-latest.zip /var/www/

Creamos el virtualhost para la aplicación web

Creamos el virtualhost en el fichero /etc/apache2/sites-available/owncloud.conf con el siguiente contenido:

<VirtualHost *:80>
    ServerName www.maria.org
    ServerAlias maria.org
    DocumentRoot /var/www/owncloud
    ErrorLog /var/log/apache2/cms-error.log
    CustomLog /var/log/apache2/cms-access.log combined
</VirtualHost>

Y lo activamos:

$ sudo a2ensite owncloud.conf

Modificamos el fichero de configuración de owncloud

$ sudo nano /var/www/owncloud/config/config.php
---
<?php
$CONFIG = array (
  'instanceid' => 'ocb5j2nyqboj',
  'passwordsalt' => '0+8FRHWahLRZ/Gv9OlXNLB8alnnPop',
  'secret' => 'X/kjusk8xkH7PHSmSb+T9LjlfKZgeTvqVsHoJ3l56CmdbiLM',
  'trusted_domains' => 
  array (
    0 => 'www.maria.org',
  ),
  'datadirectory' => '/var/www/owncloud/data',
  'overwrite.cli.url' => 'http://www.maria.org',
  'dbtype' => 'mysql',
  'version' => '10.11.0.6',
  'dbname' => 'owncloud',
  'dbhost' => '[IP de la máquina]',
  'dbtableprefix' => 'oc_',
  'mysql.utf8mb4' => true,
  'dbuser' => '[usuario de la base de datos]',
  'dbpassword' => '[contraseña de la base de datos]',
  'allow_user_to_change_mail_address' => '',
  'logtimezone' => 'UTC',
  'apps_paths' => 
  array (
    0 => 
    array (
      'path' => '/var/www/owncloud/apps',
      'url' => '/apps',
      'writable' => false,
    ),
    1 => 
    array (
      'path' => '/var/www/owncloud/apps-external',
      'url' => '/apps-external',
      'writable' => true,
    ),
  ),
  'installed' => true,
);

Reiniciamos el servicio apache

$ sudo systemctl restart apache2

Y modificamos el fichero /etc/hosts para añadir la IP de la máquina y el nombre de dominio:

$ sudo nano /etc/hosts
---
[IP de la máquina] maria.org  www.maria.org

Comprobamos que la aplicación web funciona correctamente:

Y en mi caso he instalado módulos de galería y música para poder probarlos:

NEXTCLOUD

Nextcloud es un software de código abierto, desarrollado por primera vez en 2016, que le permite ejecutar un servicio de almacenamiento en la nube personal. Tiene características que son comparables a otros servicios como Dropbox.

El software del servidor Nextcloud se puede instalar de forma gratuita en Linux, y el software del cliente se puede instalar en computadoras con Windows, OS X o Linux. Las aplicaciones móviles también están disponibles para Android e iOS.

Descargamos Nextcloud

Descargamos la aplicación web desde la página oficial de Nextcloud:

$ wget https://download.nextcloud.com/server/releases/nextcloud-22.0.2.zip

Creamos el virtualhost para la aplicación web

Creamos el virtualhost en el fichero /etc/apache2/sites-available/owncloud.conf con el siguiente contenido:

<VirtualHost *:80>
    ServerName www.cloud.maria.org
    ServerAlias cloud.maria.org
    DocumentRoot /var/www/cms/nextcloud
    ErrorLog /var/log/apache2/cms-error.log
    CustomLog /var/log/apache2/cms-access.log combined
</VirtualHost>

Modificamos el fichero de configuración de Nextcloud

$ sudo nano /var/www/cms/nextcloud/config/config.php
---
<?php
$CONFIG = array (
  'instanceid' => 'ocg57xu3tev6',
  'passwordsalt' => 'z3kK/NjSDcqfrEvfLi6PoZAbnL4gYk',
  'secret' => 'OswK3Xxvl7YzGtVbtpf/brvT/niZD4NIziidcWtWG5nqd/ny',
  'trusted_domains' =>
  array (
    0 => 'www.maria.org',
    1 => 'cloud.maria.org',
  ),
  'datadirectory' => '/var/www/cms/nextcloud/data',
  'dbtype' => 'mysql',
  'version' => '20.0.2.2',
  'overwrite.cli.url' => 'http://www.maria.org',
  'dbname' => 'nextcloud',
  'dbhost' => '[IP de la máquina]',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'mysql.utf8mb4' => true,
  'dbuser' => '[usuario de la base de datos]',
  'dbpassword' => '[contraseña de la base de datos]',
  'installed' => true,
);

Reiniciamos el servicio apache

$ sudo systemctl restart apache2

Ya no es necesario modificar el fichero /etc/hosts ya que lo hemos hecho en el anterior virtualhost.

Comprobamos que la aplicación web funciona correctamente:

Preparando la migración

  1. Realizamos una copia de seguridad de la base de datos.
#nextcloud
mysqldump -v --opt --events --routines --triggers --default-character-set=utf8 -u maria -p nextcloud > db_backup_nextcloud`date +%Y%m%d_%H%M%S`.sql
---
#owncloud
mysqldump -v --opt --events --routines --triggers --default-character-set=utf8 -u maria1 -p ouncloud > db_backup_owncloud`date +%Y%m%d_%H%M%S`.sql
  1. Comprimimos el directorio de la copia de la base de datos.
zip -r owncloud owncloud
zip -r nextcloud nextcloud
  1. Copiamos los ficheros de las aplicaciones web y las copias de seguridad de las bases de datos a la nueva máquina.
#aplicaciones web
scp -r owncloud.zip nextcloud.zip maria@asir.mariatec.es:/home/maria
#copias de seguridad de las bases de datos
scp -r db_backup_nextcloud20221123_220950.sql maria@mariatec.es:/home/maria
scp -r db_backup_owncloud20221123_220959.sql maria@mariatec.es:/home/maria
  1. Creamos la base de datos en el nuevo servidor.
mysql -u root -p
CREATE DATABASE nextcloud;
CREATE USER 'maria'@'localhost';
GRANT ALL PRIVILEGES ON nextcloud.* TO 'maria'@'localhost' IDENTIFIED BY '****';
FLUSH PRIVILEGES;
---
CREATE DATABASE owncloud;
CREATE USER 'maria1'@'localhost';
GRANT ALL PRIVILEGES ON owncloud.* TO 'maria1'@'localhost' IDENTIFIED BY '****';
FLUSH PRIVILEGES;
  1. Realizamos la restauración de la base de datos.
mysql -u maria --password=**** nextcloud < db_backup_nextcloud20221123_220950.sql
mysql -u maria1 --password=**** owncloud < db_backup_owncloud20221123_220959.sql
  1. Descomprimimos los ficheros de las aplicaciones web.
unzip owncloud.zip -d /var/www/
unzip nextcloud.zip -d /var/www/

Migración de ambas aplicaciones a un mismo virtualhost

La migración es un proceso que consiste en pasar de un sistema a otro, en este caso, de un servidor a otro. Para ello, vamos a realizar una serie de pasos que nos permitirán realizar la migración de la aplicación web.

En este caso, vamos a realizar la migración, pero vamos a realizarlo en un LEMP. Pero, ¿que es un LEMP? Para simplificar, es exactamente lo mismo que un LAMP, pero con Nginx en lugar de Apache.

Preparando el nuevo servidor

Instalamos el LEMP:

$ sudo apt update
$ sudo apt install -y nginx
$ sudo apt install -y mariadb-server
$ sudo apt install -y php

Nota: A veces, cuando instalamos php no debería de instalarse apache2, pero en ocasiones, si que lo hace. Si es así, lo desinstalamos o lo deshabilitamos.

Nextcloud

  • Primero crearemos el fichero para configurar el virtualhost en el servidor web. Lo haremos de forma en la que podamos acceder a través de www.maria.es/cloud.
sudo nano /etc/nginx/sites-available/nextcloud.conf
server {
        listen 80;
        listen [::]:80;

        server_name www.mariatec.es;

        root /var/www;

        index index.html index.htm index.php;

        location =/ {
                return 301 $scheme://www.mariatec.es/cloud;
                try_files $uri $uri/ =404;
        }

        location @rewrite {
                rewrite ^/(.*)$ /index.php?q=$1;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        }

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

        location /.well-known {
                rewrite ^/\.well-known/host-meta\.json  /cloud/public.php?service=host-meta-json    last;
                rewrite ^/\.well-known/host-meta        /cloud/public.php?service=host-meta         last;
                rewrite ^/\.well-known/webfinger        /cloud/public.php?service=webfinger         last;
                rewrite ^/\.well-known/nodeinfo         /cloud/public.php?service=nodeinfo          last;

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

                try_files $uri $uri/ =404;
        }

#Nextcloud Configuration

        location ^~ /cloud {
                client_max_body_size 512M;
                fastcgi_buffers 64 4K;

                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 a$

                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                         "none"          always;
                add_header X-XSS-Protection                     "1; mode=block" always;

                fastcgi_hide_header X-ed-By;
                index index.php index.html /cloud/index.php$request_uri;

                expires 1m;

        	location = /cloud {
            		if ( $http_user_agent ~ ^DavClnt ) {
                		return 302 /cloud/remote.php/webdav/$is_args$args;
            		}
        	}

        	location ~ ^/cloud/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)    { return 404; }
        	location ~ ^/cloud/(?:\.|autotest|occ|issue|indie|db_|console)                { return 404; }

        	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 modHeadersAvailable true;
            		fastcgi_param front_controller_active true;
            		fastcgi_pass unix:/run/php/php7.4-fpm.sock;

            		fastcgi_intercept_errors on;
            		fastcgi_request_buffering off;
        	}

        	location ~ \.(?:css|js|svg|gif)$ {
            		try_files $uri /cloud/index.php$request_uri;
            		expires 6M;
            		access_log off;
        	}

        	location ~ \.woff2?$ {
            		try_files $uri /cloud/index.php$request_uri;
            		expires 7d;
            		access_log off;
        	}

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

   	}
}

Modificamos el fichero de configuración de Nextcloud

$ sudo nano /var/www/cloud/config/config.php
---
<?php
$CONFIG = array (
  'instanceid' => 'ocg57xu3tev6',
  'passwordsalt' => 'z3kK/NjSDcqfrEvfLi6PoZAbnL4gYk',
  'secret' => 'OswK3Xxvl7YzGtVbtpf/brvT/niZD4NIziidcWtWG5nqd/ny',
  'trusted_domains' =>
  array (
    0 => 'www.mariatec.es',
    1 => 'maria.es',
  ),
  'datadirectory' => '/var/www/cloud/data',
  'dbtype' => 'mysql',
  'version' => '20.0.2.2',
  'overwrite.cli.url' => 'http://www.mariatec.es/cloud',
  'dbname' => 'nextcloud',
  'dbhost' => '[IP de la máquina]',
  'dbport' => '',
  'dbtableprefix' => 'oc_',
  'mysql.utf8mb4' => true,
  'dbuser' => '[usuario de la base de datos]',
  'dbpassword' => '[contraseña de la base de datos]',
  'installed' => true,
);
  1. Realizamos el enlace simbólico para activar el virtualhost.

    ln -s /etc/nginx/sites-available/nextcloud.conf /etc/apache2/sites-enabled/nextcloud.conf
    
  2. Reiniciamos el servicio de nginx.

    $ sudo systemctl restart nginx
    
  3. Y comprobamos que todo funciona correctamente.

    www.mariatec.es/cloud (FUERA DE SERVIVIO)

Owncloud

Configuramos de nuevo el virtualhost

Esta vez lo vamos a configurar para que Owncloud esté disponible en la ruta /portal. Al acceder a www.mariatec.es nos redirigirá a www.mariatec.es/portal. (FUERA DE SERVICIO)

El fichero de configuración de nginx quedaría de la siguiente forma:

# Default server configuration
#
server {
        listen 80;
        listen [::]:80;

        server_name www.mariatec.es;

        root /var/www;

        index index.html index.htm index.php;

        location =/ {
                return 301 $scheme://www.mariatec.es/portal;
                try_files $uri $uri/ =404;
        }

        location @rewrite {
                rewrite ^/(.*)$ /index.php?q=$1;
        }

        location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.4-fpm.sock;
        }

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

        location /.well-known {
                rewrite ^/\.well-known/host-meta\.json  /cloud/public.php?service=host-meta-json    last;
                rewrite ^/\.well-known/host-meta        /cloud/public.php?service=host-meta         last;
                rewrite ^/\.well-known/webfinger        /cloud/public.php?service=webfinger         last;
                rewrite ^/\.well-known/nodeinfo         /cloud/public.php?service=nodeinfo          last;

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

                try_files $uri $uri/ =404;
        }

#Nextcloud Configuration

        location ^~ /cloud {
                client_max_body_size 512M;
                fastcgi_buffers 64 4K;

                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 a$

                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                         "none"          always;
                add_header X-XSS-Protection                     "1; mode=block" always;

                fastcgi_hide_header X-ed-By;
                index index.php index.html /cloud/index.php$request_uri;

                expires 1m;

        	location = /cloud {
            		if ( $http_user_agent ~ ^DavClnt ) {
                		return 302 /cloud/remote.php/webdav/$is_args$args;
            		}
        	}

        	location ~ ^/cloud/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)    { return 404; }
        	location ~ ^/cloud/(?:\.|autotest|occ|issue|indie|db_|console)                { return 404; }

        	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 modHeadersAvailable true;
            		fastcgi_param front_controller_active true;
            		fastcgi_pass unix:/run/php/php7.4-fpm.sock;

            		fastcgi_intercept_errors on;
            		fastcgi_request_buffering off;
        	}

        	location ~ \.(?:css|js|svg|gif)$ {
            		try_files $uri /cloud/index.php$request_uri;
            		expires 6M;
            		access_log off;
        	}

        	location ~ \.woff2?$ {
            		try_files $uri /cloud/index.php$request_uri;
            		expires 7d;
            		access_log off;
        	}

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

   	}

#OwnCloud Configuration

        location ^~ /portal {
                client_max_body_size 512M;
                fastcgi_buffers 64 4K;

                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 a$

                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                         "none"          always;
                add_header X-XSS-Protection                     "1; mode=block" always;

                fastcgi_hide_header X-ed-By;
                index index.php index.html /portal/index.php$request_uri;

                expires 1m;

        	location = /portal {
            		if ( $http_user_agent ~ ^DavClnt ) {
                		return 302 /portal/remote.php/webdav/$is_args$args;
            		}
        	}

        	location ~ ^/portal/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)    { return 404; }
        	location ~ ^/portal/(?:\.|autotest|occ|issue|indie|db_|console)                { return 404; }

        	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 modHeadersAvailable true;
            		fastcgi_param front_controller_active true;
            		fastcgi_pass unix:/run/php/php7.4-fpm.sock;

            		fastcgi_intercept_errors on;
            		fastcgi_request_buffering off;
        	}

        	location ~ \.(?:css|js|svg|gif)$ {
            		try_files $uri /portal/index.php$request_uri;
            		expires 6M;
            		access_log off;
        	}

        	location ~ \.woff2?$ {
            		try_files $uri /portal/index.php$request_uri;
            		expires 7d;
            		access_log off;
        	}

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

   	}


}

Modificamos el fichero de configuración de Owncloud

$ sudo nano /var/www/portal/config/config.php
---
<?php
$CONFIG = array (
  'instanceid' => 'ocb5j2nyqboj',
  'passwordsalt' => '0+8FRHWahLRZ/Gv9OlXNLB8alnnPop',
  'secret' => 'X/kjusk8xkH7PHSmSb+T9LjlfKZgeTvqVsHoJ3l56CmdbiLM',
  'trusted_domains' => 
  array (
    0 => '0.0.0.0',
    1 => 'mariatec.es/portal',
    2 => 'www.mariatec.es/portal',
    3 => 'mariatec.es',
    4 => 'www.mariatec.es',
  ),
  'datadirectory' => '/var/www/portal/data',
  'overwrite.cli.url' => 'http://www.mariatec.es/portal',
  'dbtype' => 'mysql',
  'version' => '10.11.0.6',
  'dbname' => 'owncloud',
  'dbhost' => 'localhost',
  'dbtableprefix' => 'oc_',
  'mysql.utf8mb4' => true,
  'dbuser' => 'maria1',
  'dbpassword' => 'admin',
  'allow_user_to_change_mail_address' => '',
  'logtimezone' => 'UTC',
  'apps_paths' => 
  array (
    0 => 
    array (
      'path' => '/var/www/portal/apps',
      'url' => '/apps',
      'writable' => false,
    ),
    1 => 
    array (
      'path' => '/var/www/portal/apps-external',
      'url' => '/apps-external',
      'writable' => true,
    ),
  ),
  'installed' => true,
);

Reiniciamos servicios

$ sudo systemctl restart nginx
$ sudo systemctl restart mariadb

Y comprobamos que todo funciona correctamente.

Instalación de cliente Nextcloud en otro cliente