Guía de instalación de Nextcloud en Ubuntu 22.04 (Apache / MariaDB / PHP 8.1)

Instalación de Nextcloud 26 con Nextcloud Office y Ubuntu 22.04 LTS con Apache2, MariaDB, PHP 8.1, Let’s Encrypt, Redis, Fail2ban y ufw (Apache 2 fast track)

Este artículo está basado mayoritariamente en la guía que puedes encontrar en https://www.c-rieger.de/nextcloud-installationsanleitung-apache2-fast-track/

Esta guía de instalación de Nextcloud describe la instalación, configuración y endurecimiento, así como algunas posibilidades de extensión de Nextcloud Hub III en un servidor Ubuntu Server 22.04. La instalación se basa en los componentes Apache2, opcionalmente Let’s Encrypt TLS 1.3, MariaDB 10.6.x, PHP 8.1 (php-fpm), Redis, Fail2ban y ufw y finalmente recibe una calificación de seguridad A + de Nextcloud y Qualys SSL Labs. En el transcurso de esta guía, solo necesita reemplazar los valores su.dominio.es o 192.168.2.x y /var/nc-data, con los valores correspondientes de su sistema.

Requisitos

sudo -s
apt update && apt upgrade -y
apt install -y \
apt-transport-https bash-completion bzip2 ca-certificates cron curl dialog \
dirmngr ffmpeg ghostscript git gpg gnupg gnupg2 htop jq libfile-fcntllock-perl \
libfontconfig1 libfuse2 locate lsb-release net-tools rsyslog screen smbclient \
socat software-properties-common ssl-cert tree ubuntu-keyring unzip wget zip
systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target
reboot now
sudo -s
apt update && apt upgrade -y && apt autoremove -y && apt autoclean -y

Cree los directorios necesarios (supongamos que /var/nc_data será el directorio de datos de Nextcloud):

mkdir -p /var/www /var/nc_data
chown -R www-data:www-data /var/nc_data /var/www

Instalación de la base de datos MariaDB 10.8

wget -O- https://mariadb.org/mariadb_release_signing_key.asc \
| gpg --dearmor | sudo tee /usr/share/keyrings/mariadb-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/mariadb-keyring.gpg] \
https://mirror.kumi.systems/mariadb/repo/10.8/ubuntu $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/mariadb.list
apt update && apt install -y mariadb-server

Ahora vamos a endurecer el servidor de base de datos utilizando la herramienta incluida «mysql_secure_installation». Durante una instalación inicial, no hay contraseña raíz, por lo que puede confirmar la consulta con ENTER. Se recomienda establecer una contraseña directamente, el cuadro de diálogo correspondiente aparece automáticamente:

mysql_secure_installation
Enter current password for root (enter for none): <ENTER> or type the password
Switch to unix_socket authentication [Y/n] Y
Set root password? [Y/n] Y
Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] Y
Remove test database and access to it? [Y/n] Y
Reload privilege tables now? [Y/n] Y

Configuración de la base de datos MariaDB

service mariadb stop && mv /etc/mysql/my.cnf /etc/mysql/my.cnf.bak && nano /etc/mysql/my.cnf

Introduzca todas las líneas en el archivo vacío:

[client]
default-character-set = utf8mb4
port = 3306
socket = /var/run/mysqld/mysqld.sock
[mysqld_safe]
log_error=/var/log/mysql/mysql_error.log
nice = 0
socket = /var/run/mysqld/mysqld.sock
[mysqld]
basedir = /usr
bind-address = 127.0.0.1
binlog_format = ROW
bulk_insert_buffer_size = 16M
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
concurrent_insert = 2
connect_timeout = 5
datadir = /var/lib/mysql
default_storage_engine = InnoDB
expire_logs_days = 2
general_log_file = /var/log/mysql/mysql.log
general_log = 0
innodb_buffer_pool_size = 2G
innodb_buffer_pool_instances = 1
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 32M
innodb_max_dirty_pages_pct = 90
innodb_file_per_table = 1
innodb_open_files = 400
innodb_io_capacity = 4000
innodb_flush_method = O_DIRECT
innodb_read_only_compressed=OFF
key_buffer_size = 128M
lc_messages_dir = /usr/share/mysql
lc_messages = en_US
log_bin = /var/log/mysql/mariadb-bin
log_bin_index = /var/log/mysql/mariadb-bin.index
log_error = /var/log/mysql/mysql_error.log
log_slow_verbosity = query_plan
log_warnings = 2
long_query_time = 1
max_allowed_packet = 16M
max_binlog_size = 100M
max_connections = 200
max_heap_table_size = 64M
myisam_recover_options = BACKUP
myisam_sort_buffer_size = 512M
port = 3306
pid-file = /var/run/mysqld/mysqld.pid
query_cache_limit = 2M
query_cache_size = 64M
query_cache_type = 1
query_cache_min_res_unit = 2k
read_buffer_size = 2M
read_rnd_buffer_size = 1M
skip-external-locking
skip-name-resolve
slow_query_log_file = /var/log/mysql/mariadb-slow.log
slow-query-log = 1
socket = /var/run/mysqld/mysqld.sock
sort_buffer_size = 4M
table_open_cache = 400
thread_cache_size = 128
tmp_table_size = 64M
tmpdir = /tmp
transaction_isolation = READ-COMMITTED
#unix_socket=OFF
user = mysql
wait_timeout = 600
[mysqldump]
max_allowed_packet = 16M
quick
quote-names
[isamchk]
key_buffer = 16M

Reinicie la base de datos MariaDB:

service mariadb restart

Cree la base de datos Nextcloud y el usuario de MySQL. Cambielos por los de su elección.

Nombre de la base de datos: nextcloud_database
Nombre del usuario mysql: nextcloud_user
Contraseña del usuario mysql: nextcloud_password

mysql -uroot -p -e "CREATE DATABASE nextcloud_database CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; CREATE USER nextcloud_user@localhost identified by 'nextcloud_password'; GRANT ALL PRIVILEGES on nextcloud_database.* to nextcloud_user@localhost; FLUSH privileges;"

Instalación de Redis y PHP 8.1

apt install -y redis-server libapache2-mod-php8.1 php-common \
php8.1-{fpm,gd,curl,xml,zip,intl,mbstring,bz2,ldap,apcu,bcmath,gmp,imagick,igbinary,mysql,redis,smbclient,cli,common,opcache,readline} \
imagemagick --allow-change-held-packages

Establecer el formato de fecha correcto (por ejemplo, Europa/Madrid)

timedatectl set-timezone Europe/Madrid

Antes de comenzar con las optimizaciones de PHP, hagamos una copia de seguridad de los archivos de configuración:

cp /etc/php/8.1/fpm/pool.d/www.conf /etc/php/8.1/fpm/pool.d/www.conf.bak
cp /etc/php/8.1/fpm/php-fpm.conf /etc/php/8.1/fpm/php-fpm.conf.bak
cp /etc/php/8.1/cli/php.ini /etc/php/8.1/cli/php.ini.bak
cp /etc/php/8.1/fpm/php.ini /etc/php/8.1/fpm/php.ini.bak
cp /etc/php/8.1/fpm/php-fpm.conf /etc/php/8.1/fpm/php-fpm.conf.bak
cp /etc/php/8.1/mods-available/apcu.ini /etc/php/8.1/mods-available/apcu.ini.bak
cp /etc/ImageMagick-6/policy.xml /etc/ImageMagick-6/policy.xml.bak

Para adaptar PHP a su sistema, se calculan algunos parámetros, simplemente ejecute las siguientes líneas:

AvailableRAM=$(awk '/MemAvailable/ {printf "%d", $2/1024}' /proc/meminfo)
AverageFPM=$(ps --no-headers -o 'rss,cmd' -C php-fpm8.1 | awk '{ sum+=$1 } END { printf ("%d\n", sum/NR/1024,"M") }')
FPMS=$((AvailableRAM/AverageFPM))
PMaxSS=$((FPMS*2/3))
PMinSS=$((PMaxSS/2))
PStartS=$(((PMaxSS+PMinSS)/2))
sed -i "s/;env\[HOSTNAME\] = /env[HOSTNAME] = /" /etc/php/8.1/fpm/pool.d/www.conf
sed -i "s/;env\[TMP\] = /env[TMP] = /" /etc/php/8.1/fpm/pool.d/www.conf
sed -i "s/;env\[TMPDIR\] = /env[TMPDIR] = /" /etc/php/8.1/fpm/pool.d/www.conf
sed -i "s/;env\[TEMP\] = /env[TEMP] = /" /etc/php/8.1/fpm/pool.d/www.conf
sed -i "s/;env\[PATH\] = /env[PATH] = /" /etc/php/8.1/fpm/pool.d/www.conf
sed -i 's/pm.max_children =.*/pm.max_children = '$FPMS'/' /etc/php/8.1/fpm/pool.d/www.conf
sed -i 's/pm.start_servers =.*/pm.start_servers = '$PStartS'/' /etc/php/8.1/fpm/pool.d/www.conf
sed -i 's/pm.min_spare_servers =.*/pm.min_spare_servers = '$PMinSS'/' /etc/php/8.1/fpm/pool.d/www.conf
sed -i 's/pm.max_spare_servers =.*/pm.max_spare_servers = '$PMaxSS'/' /etc/php/8.1/fpm/pool.d/www.conf
sed -i "s/;pm.max_requests =.*/pm.max_requests = 1000/" /etc/php/8.1/fpm/pool.d/www.conf
sed -i "s/allow_url_fopen =.*/allow_url_fopen = 1/" /etc/php/8.1/fpm/php.ini
sed -i "s/;cgi.fix_pathinfo.*/cgi.fix_pathinfo=1/" /etc/php/8.1/fpm/php.ini

sed -i "s/output_buffering =.*/output_buffering = 'Off'/" /etc/php/8.1/cli/php.ini
sed -i "s/max_execution_time =.*/max_execution_time = 3600/" /etc/php/8.1/cli/php.ini
sed -i "s/max_input_time =.*/max_input_time = 3600/" /etc/php/8.1/cli/php.ini
sed -i "s/post_max_size =.*/post_max_size = 10240M/" /etc/php/8.1/cli/php.ini
sed -i "s/upload_max_filesize =.*/upload_max_filesize = 10240M/" /etc/php/8.1/cli/php.ini
sed -i "s/;date.timezone.*/date.timezone = Europe\/\Madrid/" /etc/php/8.1/cli/php.ini
sed -i "s/;cgi.fix_pathinfo.*/cgi.fix_pathinfo=1/" /etc/php/8.1/cli/php.ini

sed -i "s/memory_limit = 128M/memory_limit = 1024M/" /etc/php/8.1/fpm/php.ini
sed -i "s/output_buffering =.*/output_buffering = 'Off'/" /etc/php/8.1/fpm/php.ini
sed -i "s/max_execution_time =.*/max_execution_time = 3600/" /etc/php/8.1/fpm/php.ini
sed -i "s/max_input_time =.*/max_input_time = 3600/" /etc/php/8.1/fpm/php.ini
sed -i "s/post_max_size =.*/post_max_size = 10240M/" /etc/php/8.1/fpm/php.ini
sed -i "s/upload_max_filesize =.*/upload_max_filesize = 10240M/" /etc/php/8.1/fpm/php.ini
sed -i "s/;date.timezone.*/date.timezone = Europe\/\Madrid/" /etc/php/8.1/fpm/php.ini
sed -i "s/;session.cookie_secure.*/session.cookie_secure = True/" /etc/php/8.1/fpm/php.ini

sed -i "s/;opcache.enable=.*/opcache.enable=1/" /etc/php/8.1/fpm/php.ini
sed -i "s/;opcache.validate_timestamps=.*/opcache.validate_timestamps=1/" /etc/php/8.1/fpm/php.ini
sed -i "s/;opcache.enable_cli=.*/opcache.enable_cli=1/" /etc/php/8.1/fpm/php.ini
sed -i "s/;opcache.memory_consumption=.*/opcache.memory_consumption=256/" /etc/php/8.1/fpm/php.ini
sed -i "s/;opcache.interned_strings_buffer=.*/opcache.interned_strings_buffer=64/" /etc/php/8.1/fpm/php.ini
sed -i "s/;opcache.max_accelerated_files=.*/opcache.max_accelerated_files=100000/" /etc/php/8.1/fpm/php.ini
sed -i "s/;opcache.revalidate_freq=.*/opcache.revalidate_freq=0/" /etc/php/8.1/fpm/php.ini
sed -i "s/;opcache.save_comments=.*/opcache.save_comments=1/" /etc/php/8.1/fpm/php.ini

sed -i "s|;emergency_restart_threshold.*|emergency_restart_threshold = 10|g" /etc/php/8.1/fpm/php-fpm.conf
sed -i "s|;emergency_restart_interval.*|emergency_restart_interval = 1m|g" /etc/php/8.1/fpm/php-fpm.conf
sed -i "s|;process_control_timeout.*|process_control_timeout = 10|g" /etc/php/8.1/fpm/php-fpm.conf

sed -i '$aapc.enable_cli=1' /etc/php/8.1/mods-available/apcu.ini

sed -i '$aopcache.jit=1255' /etc/php/8.1/mods-available/opcache.ini
sed -i '$aopcache.jit_buffer_size=256M' /etc/php/8.1/mods-available/opcache.ini

sed -i "s/rights=\"none\" pattern=\"PS\"/rights=\"read|write\" pattern=\"PS\"/" /etc/ImageMagick-6/policy.xml
sed -i "s/rights=\"none\" pattern=\"EPS\"/rights=\"read|write\" pattern=\"EPS\"/" /etc/ImageMagick-6/policy.xml
sed -i "s/rights=\"none\" pattern=\"PDF\"/rights=\"read|write\" pattern=\"PDF\"/" /etc/ImageMagick-6/policy.xml
sed -i "s/rights=\"none\" pattern=\"XPS\"/rights=\"read|write\" pattern=\"XPS\"/" /etc/ImageMagick-6/policy.xml

Ahora reinicie los servicios

systemctl restart php8.1-fpm
a2dismod php8.1 && a2dismod mpm_prefork
a2enmod proxy_fcgi setenvif mpm_event http2
systemctl restart apache2.service
a2enconf php8.1-fpm
systemctl restart apache2.service php8.1-fpm

Descargar la última versión de Nextcloud

wget https://download.nextcloud.com/server/releases/latest.zip
unzip latest.zip && mv nextcloud/ /var/www/ && chown -R www-data:www-data /var/www/nextcloud && rm -f latest.zip

Ajustes Redis

cp /etc/redis/redis.conf /etc/redis/redis.conf.bak

Cambia el valor de PasswordRedis por una contraseña de tu eleccción

sed -i "s/port 6379/port 0/" /etc/redis/redis.conf
sed -i s/\#\ unixsocket/\unixsocket/g /etc/redis/redis.conf
sed -i "s/unixsocketperm 700/unixsocketperm 770/" /etc/redis/redis.conf 
sed -i "s/# maxclients 10000/maxclients 10240/" /etc/redis/redis.conf
sed -i 's/# requirepass foobared/requirepass PasswordRedis/' /etc/redis/redis.conf
usermod -aG redis www-data
cp /etc/sysctl.conf /etc/sysctl.conf.bak
sed -i '$avm.overcommit_memory = 1' /etc/sysctl.conf
reboot now

Ajustes Apache2

sudo -s
a2enmod rewrite headers env dir mime
nano /etc/apache2/mods-available/http2.conf
# mod_http2 doesn't work with mpm_prefork
<IfModule !mpm_prefork>
Protocols h2 h2c http/1.1
H2Direct on
H2StreamMaxMemSize 5120000000
[...]
systemctl restart apache2.service
cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/001-nextcloud.conf
a2dissite 000-default.conf
nano /etc/apache2/sites-available/001-nextcloud.conf

Adapte el archivo y especialmente los valores marcados a su sistema

<VirtualHost *:80>
ServerName su.dominio.es
ServerAlias su.dominio.es
ServerAdmin correo@dominio.es
DocumentRoot /var/www/nextcloud
ErrorLog /var/log/apache2/error.log
CustomLog /var/log/apache2/access.log combined
RewriteEngine on
RewriteCond %{SERVER_NAME} =su.dominio.es
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

Habilite vHost:

a2ensite 001-nextcloud.conf && systemctl restart apache2.service

Instale Certbot y solicite certificados de Let’s Encrypt:

apt install -y certbot python3-certbot-apache
certbot --apache

Nextcloud vHost: aplique todas las filas y ajuste los valores marcados a su sistema

mv /etc/apache2/sites-available/001-nextcloud-le-ssl.conf /etc/apache2/sites-available/001-nextcloud-le-ssl.conf.bak
nano /etc/apache2/sites-available/001-nextcloud-le-ssl.conf
<IfModule mod_ssl.c>
SSLUseStapling on
SSLStaplingCache shmcb:/var/run/ocsp(128000)
<VirtualHost *:443>
SSLCertificateFile /etc/letsencrypt/live/su.dominio.es/fullchain.pem
SSLCACertificateFile /etc/letsencrypt/live/su.dominio.es/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/su.dominio.es/privkey.pem
#######################################################################
# For self-signed-certificates only!
# SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
# SSLCACertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
# SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
#######################################################################
Protocols h2 h2c http/1.1
Header add Strict-Transport-Security: "max-age=15552000;includeSubdomains"
ServerAdmin correo@dominio.es
ServerName su.dominio.es
ServerAlias su.dominio.es
SSLEngine on
SSLCompression off
SSLOptions +StrictRequire
SSLProtocol -all +TLSv1.3 +TLSv1.2
#SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLCipherSuite TLS-CHACHA20-POLY1305-SHA256:TLS-AES-256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
SSLSessionTickets off
ServerSignature off
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off
SSLOpenSSLConfCmd Curves X448:secp521r1:secp384r1:prime256v1
SSLOpenSSLConfCmd ECDHParameters secp384r1
LogLevel warn
CustomLog /var/log/apache2/access.log combined
ErrorLog /var/log/apache2/error.log
DocumentRoot /var/www/nextcloud
<Directory /var/www/nextcloud/>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
Satisfy Any
</Directory>
<IfModule mod_dav.c>
Dav off
</IfModule>
<Directory /var/nc_data/>
Require all denied
</Directory>
<Files ".ht*">
Require all denied
</Files>
TraceEnable off
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^TRACK
RewriteRule .* - [R=405,L]
SetEnv HOME /var/www/nextcloud
SetEnv HTTP_HOME /var/www/nextcloud
<IfModule mod_reqtimeout.c>
RequestReadTimeout body=0
</IfModule>
</VirtualHost>
</IfModule>

Amplíe y habilite la seguridad

openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096
cat /etc/ssl/certs/dhparam.pem >> /etc/letsencrypt/live/su.dominio.es/fullchain.pem

#######################################################################
Optional: Self-Signed-Zertifikate
cat /etc/ssl/certs/dhparam.pem >> /etc/ssl/certs/ssl-cert-snakeoil.pem
#######################################################################

Para editar el archivo de configuración de Apache2:

nano /etc/apache2/apache2.conf

Establezca los valores marcados su.dominio.es, Options, FollowSymLinks, MultiViews y AllowOverride All

ServerName su.dominio.es
[...]
<Directory /var/www/>
Options FollowSymLinks MultiViews
AllowOverride All
Require all granted
</Directory>
systemctl restart apache2.service

Instalación de Nextcloud

sudo -u www-data php /var/www/nextcloud/occ maintenance:install --database "mysql" --database-name "nextcloud_database" --database-user "nextcloud_user" --database-pass "nextcloud_password" --admin-user "Nextcloud-Admin" --admin-pass "Nextcloud-Admin-Passsword" --data-dir "/var/nc_data"

Edite config.php correctamente – agregue las líneas:

sudo -u www-data nano /var/www/nextcloud/config/config.php

[...]
),
'datadirectory' => '/var/nc_data',
'overwrite.cli.url' => 'https://su.dominio.es/',
'htaccess.RewriteBase' => '/',
[...]

Arreglar Nextcloud .htaccess

sudo -u www-data php /var/www/nextcloud/occ maintenance:update:htaccess

Personalizaciones de Nextcloud

mkdir -p /var/log/nextcloud/
chown -R www-data:www-data /var/log/nextcloud
sudo -u www-data cp /var/www/nextcloud/config/config.php /var/www/nextcloud/config/config.php.bak
sudo -u www-data sed -i 's/^[ ]*//' /var/www/nextcloud/config/config.php
sudo -u www-data sed -i '/);/d' /var/www/nextcloud/config/config.php

Antes de rellenar el archivo con el texto siguiente modifica PasswordRedis con la contraseña que has elegido anteriormente.

sudo -u www-data cat <<EOF >>/var/www/nextcloud/config/config.php
'activity_expire_days' => 14,
'allow_local_remote_servers' => true,
'auth.bruteforce.protection.enabled' => true,
'blacklisted_files' => 
array (
0 => '.htaccess',
1 => 'Thumbs.db',
2 => 'thumbs.db',
),
'cron_log' => true,
'default_phone_region' => 'ES',
'defaultapp' => 'files,dashboard',
'enable_previews' => true,
'enabledPreviewProviders' => 
array (
0 => 'OC\Preview\PNG',
1 => 'OC\Preview\JPEG',
2 => 'OC\Preview\GIF',
3 => 'OC\Preview\BMP',
4 => 'OC\Preview\XBitmap',
5 => 'OC\Preview\Movie',
6 => 'OC\Preview\PDF',
7 => 'OC\Preview\MP3',
8 => 'OC\Preview\TXT',
9 => 'OC\Preview\MarkDown',
),
'filesystem_check_changes' => 0,
'filelocking.enabled' => 'true',
'htaccess.RewriteBase' => '/',
'integrity.check.disabled' => false,
'knowledgebaseenabled' => false,
'logfile' => '/var/log/nextcloud/nextcloud.log',
'loglevel' => 2,
'logtimezone' => 'Europe/Madrid',
'log_rotate_size' => '104857600',
'maintenance' => false,
'maintenance_window_start' => 1,
'memcache.local' => '\OC\Memcache\APCu',
'memcache.locking' => '\OC\Memcache\Redis',
'overwriteprotocol' => 'https',
'preview_max_x' => 1024,
'preview_max_y' => 768,
'preview_max_scale_factor' => 1,
'profile.enabled' => false,
'redis' => 
array (
'host' => '/var/run/redis/redis-server.sock',
'port' => 0,
'password' => 'PasswordRedis',
'timeout' => 0.5,
'dbindex' => 1,
),
'quota_include_external_storage' => false,
'skeletondirectory' => '',
'theme' => '',
'trashbin_retention_obligation' => 'auto, 7',
'updater.release.channel' => 'stable',
);
EOF
sudo -u www-data php /var/www/nextcloud occ config:system:set remember_login_cookie_lifetime --value="1800"
sudo -u www-data php /var/www/nextcloud occ config:system:set simpleSignUpLink.shown --type=bool --value=false
sudo -u www-data php /var/www/nextcloud occ config:system:set versions_retention_obligation --value="auto, 365"
sudo -u www-data php /var/www/nextcloud occ config:system:set loglevel --value=2
sudo -u www-data php /var/www/nextcloud/occ config:system:set trusted_domains 1 --value=su.dominio.es
sudo -u www-data php /var/www/nextcloud/occ config:app:set settings profile_enabled_by_default --value="0"

Oficina Nextcloud opcional (tenga paciencia – descargar desde ~ 400MB):

sudo -u www-data /usr/bin/php /var/www/nextcloud/occ app:install richdocuments
sudo -u www-data /usr/bin/php /var/www/nextcloud/occ app:install richdocumentscode
a2enmod ssl && a2ensite 001-nextcloud.conf 001-nextcloud-le-ssl.conf
systemctl restart php8.1-fpm.service redis-server.service apache2.service

Cronjob

crontab -u www-data -e

Agregue esta línea al final

*/5 * * * * php -f /var/www/nextcloud/cron.php > /dev/null 2>&1

Activar el cronjob dentro de Nextcloud

sudo -u www-data php /var/www/nextcloud/occ background:cron

Endurecimiento adicional

a2dismod status
nano /etc/apache2/conf-available/security.conf
[...]
ServerTokens Prod
[...]
ServerSignature Off
[...]
TraceEnable Off
[...]
systemctl restart php8.1-fpm.service redis-server.service apache2.service

Instalar fail2ban

apt install -y fail2ban ufw
touch /etc/fail2ban/filter.d/nextcloud.conf
cat <<EOF >/etc/fail2ban/filter.d/nextcloud.conf
[Definition]
_groupsre = (?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)
failregex = ^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Login failed:
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Trusted domain error.
datepattern = ,?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?"
EOF

Ahora cree un nuevo archivo jail

nano /etc/fail2ban/jail.d/nextcloud.local

Copie todas las siguientes líneas en él:

[nextcloud]
backend = auto
enabled = true
port = 80,443
protocol = tcp
filter = nextcloud
maxretry = 5
bantime = 3600
findtime = 36000
logpath = /var/log/nextcloud/nextcloud.log
service fail2ban restart

Habilite el firewall y ajuste el puerto SSH 22 si es necesario

ufw allow 80/tcp comment "LetsEncrypt" && ufw allow 443/tcp comment "TLS" && ufw allow 22/tcp comment "SSH"
ufw logging medium
ufw enable
service ufw restart
En caso de que desees donar algo a Carsten Rieger IT-Services por su trabajo aqui tienes su Paypal.

7 comentarios sobre “Guía de instalación de Nextcloud en Ubuntu 22.04 (Apache / MariaDB / PHP 8.1)

  1. Hanns Valles Contestar

    Buen dia, he instalado el servicio sobre un servidor ubuntu 22.04, la pagina carga, y puedo ingresar, pero al ingresar al URL demora 5 minutos aprox, una vez que ingresa, y selecciono alguna opcion, demora otros 5 minutos en actualizar y asi por cada item.

    Mi servidor tiene 8 core y 4 gigas de RAM por lo cual no es un problema de hardware.

    • Hanns Valles Contestar

      Este mensaje se presenta a cada momento en el log de nextcloud:

      {«reqId»:»b6zMLgDkHUkhLuyNpUDp»,»level»:3,»time»:»2022-11-17T00:26:27+01:00″,»remoteAddr»:»38.25.11.165″,»user»:»Nextcloud-Admin»,»app»:»richdocuments»,»method»:»GET»,»url»:»/ocs/v2.php/apps/notifications/api/v2/notifications»,»message»:»Failed to fetch the Collabora capabilities endpoint: cURL error 28: Operation timed out after 45000 milliseconds with 0 bytes received (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://drive.vdtecsolutions.com/apps/richdocumentscode/proxy.php?req=/hosting/capabilities«,»userAgent»:»Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36″,»version»:»25.0.1.1″,»exception»:{«Exception»:»GuzzleHttp\\Exception\\ConnectException»,»Message»:»cURL error 28: Operation timed out after 45000 milliseconds with 0 bytes received (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://drive.vdtecsolutions.com/apps/richdocumentscode/proxy.php?req=/hosting/capabilities«,»Code»:0,»Trace»:[{«file»:»/var/www/nextcloud/3rdparty/guzzlehttp/guzzle/src/Handler/CurlFactory.php»,»line»:158,»function»:»createRejection»,»class»:»GuzzleHttp\\Handler\\CurlFactory»,»type»:»::»},{«file»:»/var/www/nextcloud/3rdparty/guzzlehttp/guzzle/src/Handler/CurlFactory.php»,»line»:110,»function»:»finishError»,»class»:»GuzzleHttp\\Handler\\CurlFactory»,»type»:»::»},{«file»:»/var/www/nextcloud/3rdparty/guzzlehttp/guzzle/src/Handler/CurlHandler.php»,»line»:47,»function»:»finish»,»class»:»GuzzleHttp\\Handler\\CurlFactory»,»type»:»::»},{«file»:»/var/www/nextcloud/lib/private/Http/Client/DnsPinMiddleware.php»,»line»:113,»function»:»__invoke»,»class»:»GuzzleHttp\\Handler\\CurlHandler»,»type»:»->»},{«file»:»/var/www/nextcloud/3rdparty/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php»,»line»:35,»function»:»OC\\Http\\Client\\{closure}»,»class»:»OC\\Http\\Client\\DnsPinMiddleware»,»type»:»->»,»args»:[«*** sensitive parameters replaced ***»]},{«file»:»/var/www/nextcloud/3rdparty/guzzlehttp/guzzle/src/Middleware.php»,»line»:31,»function»:»__invoke»,»class»:»GuzzleHttp\\PrepareBodyMiddleware»,»type»:»->»},{«file»:»/var/www/nextcloud/3rdparty/guzzlehttp/guzzle/src/RedirectMiddleware.php»,»line»:71,»function»:»GuzzleHttp\\{closure}»,»class»:»GuzzleHttp\\Middleware»,»type»:»::»,»args»:[«*** sensitive parameters replaced ***»]},{«file»:»/var/www/nextcloud/3rdparty/guzzlehttp/guzzle/src/Middleware.php»,»line»:63,»function»:»__invoke»,»class»:»GuzzleHttp\\RedirectMiddleware»,»type»:»->»},{«file»:»/var/www/nextcloud/3rdparty/guzzlehttp/guzzle/src/HandlerStack.php»,»line»:75,»function»:»GuzzleHttp\\{closure}»,»class»:»GuzzleHttp\\Middleware»,»type»:»::»,»args»:[«*** sensitive parameters replaced ***»]},{«file»:»/var/www/nextcloud/3rdparty/guzzlehttp/guzzle/src/Client.php»,»line»:331,»function»:»__invoke»,»class»:»GuzzleHttp\\HandlerStack»,»type»:»->»},{«file»:»/var/www/nextcloud/3rdparty/guzzlehttp/guzzle/src/Client.php»,»line»:168,»function»:»transfer»,»class»:»GuzzleHttp\\Client»,»type»:»->»},{«file»:»/var/www/nextcloud/3rdparty/guzzlehttp/guzzle/src/Client.php»,»line»:187,»function»:»requestAsync»,»class»:»GuzzleHttp\\Client»,»type»:»->»},{«file»:»/var/www/nextcloud/lib/private/Http/Client/Client.php»,»line»:218,»function»:»request»,»class»:»GuzzleHttp\\Client»,»type»:»->»},{«file»:»/var/www/nextcloud/apps/richdocuments/lib/Service/CapabilitiesService.php»,»line»:131,»function»:»get»,»class»:»OC\\Http\\Client\\Client»,»type»:»->»},{«file»:»/var/www/nextcloud/apps/richdocuments/lib/Service/CapabilitiesService.php»,»line»:74,»function»:»refetch»,»class»:»OCA\\Richdocuments\\Service\\CapabilitiesService»,»type»:»->»},{«file»:»/var/www/nextcloud/apps/richdocuments/lib/AppInfo/Application.php»,»line»:80,»function»:»getCapabilities»,»class»:»OCA\\Richdocuments\\Service\\CapabilitiesService»,»type»:»->»},{«file»:»/var/www/nextcloud/lib/private/AppFramework/Bootstrap/FunctionInjector.php»,»line»:67,»function»:»OCA\\Richdocuments\\AppInfo\\{closure}»,»class»:»OCA\\Richdocuments\\AppInfo\\Application»,»type»:»->»,»args»:[«*** sensitive parameters replaced ***»]},{«file»:»/var/www/nextcloud/lib/private/AppFramework/Bootstrap/BootContext.php»,»line»:51,»function»:»injectFn»,»class»:»OC\\AppFramework\\Bootstrap\\FunctionInjector»,»type»:»->»},{«file»:»/var/www/nextcloud/apps/richdocuments/lib/AppInfo/Application.php»,»line»:135,»function»:»injectFn»,»class»:»OC\\AppFramework\\Bootstrap\\BootContext»,»type»:»->»},{«file»:»/var/www/nextcloud/lib/private/AppFramework/Bootstrap/Coordinator.php»,»line»:190,»function»:»boot»,»class»:»OCA\\Richdocuments\\AppInfo\\Application»,»type»:»->»},{«file»:»/var/www/nextcloud/lib/private/legacy/OC_App.php»,»line»:208,»function»:»bootApp»,»class»:»OC\\AppFramework\\Bootstrap\\Coordinator»,»type»:»->»},{«file»:»/var/www/nextcloud/lib/private/legacy/OC_App.php»,»line»:141,»function»:»loadApp»,»class»:»OC_App»,»type»:»::»},{«file»:»/var/www/nextcloud/ocs/v1.php»,»line»:57,»function»:»loadApps»,»class»:»OC_App»,»type»:»::»},{«file»:»/var/www/nextcloud/ocs/v2.php»,»line»:23,»args»:[«/var/www/nextcloud/ocs/v1.php»],»function»:»require_once»}],»File»:»/var/www/nextcloud/3rdparty/guzzlehttp/guzzle/src/Handler/CurlFactory.php»,»Line»:210,»message»:»Failed to fetch the Collabora capabilities endpoint: cURL error 28: Operation timed out after 45000 milliseconds with 0 bytes received (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://drive.vdtecsolutions.com/apps/richdocumentscode/proxy.php?req=/hosting/capabilities«,»exception»:{},»CustomMessage»:»Failed to fetch the Collabora capabilities endpoint: cURL error 28: Operation timed out after 45000 milliseconds with 0 bytes received (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://drive.vdtecsolutions.com/apps/richdocumentscode/proxy.php?req=/hosting/capabilities«}}
      ^C

    • GiO Autor del artículoContestar

      Yo en primera instancia eliminaría completamente la aplicación «Collabora Online – Built-in CODE Server» y «Nextcloud Office». Si funciona bien en ese caso volvería a instalarlas y esperaría unos minutos a que el servidor de Collabora termine de iniciarse.

  2. Pingback: Recuperación de un backup de NextCloud – Akirah

  3. Aníbal Contestar

    Muchísimas gracias por el sobresaliente trabajo que hiciste con este tutorial. Simplemente extraordinario. Luego de seguir los pasos con mucho cuidado, instalé el servidor Nextcloud sin ningún tipo de problemas.

    • GiO Autor del artículoContestar

      El artículo no es mío. Tal como menciono al principio es de Carlsten Riegen, yo simplemente lo he traducido y he añadido algunos detalles. Muchas gracias por tu comentario. Me alegra que haya sido de utilidad.

  4. Andrés Díaz Contestar

    Muchas gracias por esta fantástica traducción y trabajo, ha funcionado todo perfecto a la primera, se nota que está pensado para montar en uno o varios scripts para el despliegue automático o semiautomático, que es lo que yo he hecho.

    La donación está en curso…

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.