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

Instalación de Nextcloud 28 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.11, PHP 8.2 (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.11

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.11/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]
# performance_schema=ON
basedir = /usr
bind-address = 127.0.0.1
binlog_format = ROW
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci
datadir = /var/lib/mysql
default_storage_engine = InnoDB
expire_logs_days = 2
general_log_file = /var/log/mysql/mysql.log
innodb_buffer_pool_size = 2G
innodb_log_buffer_size = 32M
innodb_log_file_size = 512M
innodb_read_only_compressed=OFF
join_buffer_size = 2M
key_buffer_size = 512M
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_connections = 100
max_heap_table_size = 64M
myisam_sort_buffer_size = 512M
port = 3306
pid-file = /var/run/mysqld/mysqld.pid
query_cache_limit = 0
query_cache_size = 0 
read_buffer_size = 2M
read_rnd_buffer_size = 2M
skip-name-resolve
socket = /var/run/mysqld/mysqld.sock
sort_buffer_size = 2M
table_open_cache = 400
table_definition_cache = 800
tmp_table_size = 32M
tmpdir = /tmp
transaction_isolation = READ-COMMITTED
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.2

add-apt-repository -y ppa:ondrej/php
apt install -y redis-server redis-server libapache2-mod-php8.2 php-common \
php8.2-{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.2/fpm/pool.d/www.conf /etc/php/8.2/fpm/pool.d/www.conf.bak
cp /etc/php/8.2/fpm/php-fpm.conf /etc/php/8.2/fpm/php-fpm.conf.bak
cp /etc/php/8.2/cli/php.ini /etc/php/8.2/cli/php.ini.bak
cp /etc/php/8.2/fpm/php.ini /etc/php/8.2/fpm/php.ini.bak
cp /etc/php/8.2/mods-available/apcu.ini /etc/php/8.2/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.2/fpm/pool.d/www.conf
sed -i "s/;env\[TMP\] = /env[TMP] = /" /etc/php/8.2/fpm/pool.d/www.conf
sed -i "s/;env\[TMPDIR\] = /env[TMPDIR] = /" /etc/php/8.2/fpm/pool.d/www.conf
sed -i "s/;env\[TEMP\] = /env[TEMP] = /" /etc/php/8.2/fpm/pool.d/www.conf
sed -i "s/;env\[PATH\] = /env[PATH] = /" /etc/php/8.2/fpm/pool.d/www.conf

sed -i 's/pm.max_children =.*/pm.max_children = 200/' /etc/php/8.2/fpm/pool.d/www.conf
sed -i 's/pm.start_servers =.*/pm.start_servers = 100/' /etc/php/8.2/fpm/pool.d/www.conf
sed -i 's/pm.min_spare_servers =.*/pm.min_spare_servers = 60/' /etc/php/8.2/fpm/pool.d/www.conf
sed -i 's/pm.max_spare_servers =.*/pm.max_spare_servers = 140/' /etc/php/8.2/fpm/pool.d/www.conf
sed -i "s/;pm.max_requests =.*/pm.max_requests = 1000/" /etc/php/8.2/fpm/pool.d/www.conf
sed -i "s/allow_url_fopen =.*/allow_url_fopen = 1/" /etc/php/8.2/fpm/php.ini

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

sed -i "s/memory_limit = 128M/memory_limit = 1G/" /etc/php/8.2/fpm/php.ini
sed -i "s/output_buffering =.*/output_buffering = Off/" /etc/php/8.2/fpm/php.ini
sed -i "s/max_execution_time =.*/max_execution_time = 3600/" /etc/php/8.2/fpm/php.ini
sed -i "s/max_input_time =.*/max_input_time = 3600/" /etc/php/8.2/fpm/php.ini
sed -i "s/post_max_size =.*/post_max_size = 10G/" /etc/php/8.2/fpm/php.ini
sed -i "s/upload_max_filesize =.*/upload_max_filesize = 10G/" /etc/php/8.2/fpm/php.ini
sed -i "s/;date.timezone.*/date.timezone = Europe\/\Berlin/" /etc/php/8.2/fpm/php.ini
sed -i "s/;cgi.fix_pathinfo.*/cgi.fix_pathinfo=0/" /etc/php/8.2/fpm/php.ini
sed -i "s/;session.cookie_secure.*/session.cookie_secure = True/" /etc/php/8.2/fpm/php.ini
sed -i "s/;opcache.enable=.*/opcache.enable=1/" /etc/php/8.2/fpm/php.ini
sed -i "s/;opcache.validate_timestamps=.*/opcache.validate_timestamps=1/" /etc/php/8.2/fpm/php.ini
sed -i "s/;opcache.enable_cli=.*/opcache.enable_cli=1/" /etc/php/8.2/fpm/php.ini
sed -i "s/;opcache.memory_consumption=.*/opcache.memory_consumption=256/" /etc/php/8.2/fpm/php.ini
sed -i "s/;opcache.interned_strings_buffer=.*/opcache.interned_strings_buffer=64/" /etc/php/8.2/fpm/php.ini
sed -i "s/;opcache.max_accelerated_files=.*/opcache.max_accelerated_files=100000/" /etc/php/8.2/fpm/php.ini
sed -i "s/;opcache.revalidate_freq=.*/opcache.revalidate_freq=0/" /etc/php/8.2/fpm/php.ini
sed -i "s/;opcache.save_comments=.*/opcache.save_comments=1/" /etc/php/8.2/fpm/php.ini

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

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

sed -i 's/opcache.jit=off/; opcache.jit=off/' /etc/php/8.2/mods-available/opcache.ini
sed -i '$aopcache.jit=1255' /etc/php/8.2/mods-available/opcache.ini
sed -i '$aopcache.jit_buffer_size=256M' /etc/php/8.2/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

sed -i '$a[mysql]' /etc/php/8.2/mods-available/mysqli.ini
sed -i '$amysql.allow_local_infile=On' /etc/php/8.2/mods-available/mysqli.ini
sed -i '$amysql.allow_persistent=On' /etc/php/8.2/mods-available/mysqli.ini
sed -i '$amysql.cache_size=2000' /etc/php/8.2/mods-available/mysqli.ini
sed -i '$amysql.max_persistent=-1' /etc/php/8.2/mods-available/mysqli.ini
sed -i '$amysql.max_links=-1' /etc/php/8.2/mods-available/mysqli.ini
sed -i '$amysql.default_port=3306' /etc/php/8.2/mods-available/mysqli.ini
sed -i '$amysql.connect_timeout=60' /etc/php/8.2/mods-available/mysqli.ini
sed -i '$amysql.trace_mode=Off' /etc/php/8.2/mods-available/mysqli.ini

Ahora reinicie los servicios

systemctl restart php8.2-fpm
a2dismod php8.2 && a2dismod mpm_prefork
a2enmod proxy_fcgi setenvif mpm_event http2
systemctl restart apache2.service
a2enconf php8.2-fpm
systemctl restart apache2.service php8.2-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
sysctl -p
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 128000
[...]
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
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.2-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.2-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.

11 comentarios en “Guía de instalación de Nextcloud en Ubuntu 22.04 (Apache / MariaDB / PHP 8.2)

  1. 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.

    1. 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

    2. 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. 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.

    1. 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.

  3. 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…

  4. Buenos días,

    He seguido la guía paso a paso, y no hay forma de que funcione bien. Por un lado tengo un mensaje en los avisos de configuración diciendo:

    Tu servidor web todavía no está configurado correctamente para permitir la sincronización de archivos, porque la interfaz WebDAV parece estar rota.
    54 errores en los registros desde 8 de febrero de 2024
    No se pudo hacer el chequeo del soporte JavaScript. Por favor haga el chequeo manual de si su servidor web sirve archivos `.mjs` utilizando el tipo MIME JavaScript.
    Su servidor no está configurado correctamente para resolver «/.well-known/caldav». Se puede encontrar más información en la documentación ↗.
    Su servidor no está configurado correctamente para resolver «/.well-known/carddav». Se puede encontrar más información en la documentación ↗.

    Por otro lado, no deja subir ningún archivo. El botón de añadir está en «grayed out» y no deja hacer nada, ni me enseña los típicos archivos de demo.

    Por otro lado, si instalo la suite de Office, se vuelve lento no, lo siguiente, y no hay forma de abrir la interfaz de administración durante más de 5 minutos. En el log, figura esto, tapo la URL:

    Error richdocuments
    ConnectException
    cURL error 28: Connection timed out after 45001 milliseconds (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://«URL»/richdocumentscode/proxy.php?req=/hosting/capabilities
    Failed to fetch the Collabora capabilities endpoint: cURL error 28: Connection timed out after 45001 milliseconds (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://«URL»/richdocumentscode/proxy.php?req=/hosting/capabilities

    Si miro el registro de errores de PHP o Apache, salen cosas como estas, tapo la IP por «IP»:

    [Thu Feb 15 17:22:36.856343 2024] [proxy_fcgi:error] [pid 921:tid 139787448469056] [remote IP:64938] AH01071: Got error ‘Access to the script ‘redirect:/index.php/v1/user_status’ has been denied (see security.limit_extensions)’
    [Thu Feb 15 17:22:36.937543 2024] [proxy_fcgi:error] [pid 921:tid 139787557582400] [remote IP:64938] AH01071: Got error ‘Access to the script ‘redirect:/index.php/’ has been denied (see security.limit_extensions)’
    [Thu Feb 15 17:22:36.938468 2024] [proxy_fcgi:error] [pid 921:tid 139787507226176] [remote IP:64938] AH01071: Got error ‘Access to the script ‘redirect:/index.php/’ has been denied (see security.limit_extensions)’
    [Thu Feb 15 17:22:37.002490 2024] [proxy_fcgi:error] [pid 921:tid 139787532404288] [remote IP:64938] AH01071: Got error ‘Access to the script ‘redirect:/index.php/v2/notifications’ has been denied (see security.limit_extensions)’
    [Thu Feb 15 17:22:37.322607 2024] [proxy_fcgi:error] [pid 921:tid 139787565975104] [remote IP:64938] AH01071: Got error ‘Access to the script ‘redirect:/index.php/groups/details’ has been denied (see security.limit_extensions)’
    [Thu Feb 15 17:23:51.099625 2024] [proxy_fcgi:error] [pid 923:tid 139787381196352] [remote IP:65158] AH01071: Got error ‘Access to the script ‘redirect:/index.php/providers’ has been denied (see security.limit_extensions)’

    Ni idea de por donde seguir, porque he seguido paso a paso la guía y son muchos fallos distintos. Ubuntu 22.04 LTS Server actualizado, instalado desde cero, y con paso a paso la guía.

    Gracias

    1. Cabe la posibilidad que no tengas comentada la linea
      ;security.limit_extensions = .php .php3 .php4 .php5 .php7
      dentro del archivo /etc/php//fpm/pool.d/www.conf

      Yo empezaría por ahí.

      1. Buenas tardes, enhorabuena lo primero, la verdad que muy claro y facil de seguir.
        Yo tengo el mismo problema y tengo comentada la línea que comentas.
        Ademas al intentar cambiar cualquier parámetro desde la web de NC no permite hacerlo. Por ejemplo,
        Si quiero cambiar el estado me indica: Ha habido un error al guardar el nuevo estado
        Si quiero cambiar el nombre al usuario: Imposible actualizar nombre completo
        Y la opción de subir archivos aparece deshabilitada
        Es como si no hubiera permisos para escribir en la base de datos
        ¿Alguna idea?

        1. Por hacer una respuesta rápida sin comprobar… ¿Es posible que la carpeta donde se guarden los datos de usuario no tenga el propietario correcto?.. Debería ser www-data
          Para conocer cual es la carpeta donde se guardan los datos ve al fichero ubicado en /var/www/nextcloud/config/config.php y verás el directorio de datos en ‘datadirectory’ => ‘/var/nc_data’,
          Puedes cambiar el propietario de dicha carpeta con chown -R www-data:www-data /var/nc_data

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.