Skip to main content

Nextcloud en Debian 13 + Nginx + PHP-FPM 8.4

Documento antialzheimer técnico.
Si estás leyendo esto es porque ya sufriste.

Este cookbook está limpiado (sin retales contradictorios) y orientado a:

  • Debian 13
  • PHP-FPM 8.4.x
  • Nginx (no Apache)
  • MariaDB
  • Redis (caching + file locking)

0) Variables que ustedes definen una vez

Ajusta esto a tu caso y mantégalo consistente:

# Dominio público
NC_DOMAIN="files.example.com"

# Rutas
NC_WEBROOT="/var/www/nextcloud"         # código
NC_DATA="/srv/nextcloud-data"           # datos (recomendado fuera de webroot)

# Base de datos
NC_DB="nextcloud"
NC_DB_USER="nextclouduser"
NC_DB_PASS="CAMBIAR_ESTO"

# Redis
REDIS_PASS="CAMBIAR_ESTO"

1) Base del sistema

sudo apt update
sudo apt -y full-upgrade
sudo apt -y install ca-certificates curl unzip gnupg lsb-release bzip2 vim-tiny

2) MariaDB

sudo apt -y install mariadb-server mariadb-client
sudo systemctl enable --now mariadb
sudo mysql_secure_installation

Crear DB y usuario (utf8mb4):

sudo mysql -u root -p <<SQL
CREATE DATABASE ${NC_DB} CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER '${NC_DB_USER}'@'localhost' IDENTIFIED BY '${NC_DB_PASS}';
GRANT ALL PRIVILEGES ON ${NC_DB}.* TO '${NC_DB_USER}'@'localhost';
FLUSH PRIVILEGES;
SQL

3) PHP 8.4 + PHP-FPM

3.1 Paquetes

sudo apt -y install php8.4-fpm php8.4-cli php8.4-common \
  php8.4-gd php8.4-curl php8.4-zip php8.4-xml php8.4-mbstring \
  php8.4-intl php8.4-bz2 php8.4-bcmath php8.4-gmp \
  php8.4-imagick php8.4-mysql \
  php8.4-redis

Si en su mirror no existe php8.4-*, entonces su Debian no trae esa versión en ese momento y tocará repos alternativo o bajar a la versión disponible. No inventen compatibilidad: miren la matriz PHP/Nextcloud de su release.

3.2 Ajustes PHP-FPM

Recomendación práctica: no toquen php.ini a mano para todo. Creen un override propio.

Crear /etc/php/8.4/fpm/conf.d/99-nextcloud.ini:

; === Nextcloud sane defaults ===
memory_limit = 512M
upload_max_filesize = 2G
post_max_size = 2G
max_execution_time = 360
max_input_time = 360
output_buffering = Off
expose_php = Off

; Ajusten a su zona
date.timezone = Atlantic/Canary

; OPcache (básico)
opcache.enable=1
opcache.enable_cli=1
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.memory_consumption=256
opcache.save_comments=1
opcache.revalidate_freq=60

Reiniciar y habilitar:

sudo systemctl enable --now php8.4-fpm
sudo systemctl restart php8.4-fpm

4) Redis (caché + file locking)

sudo apt -y install redis-server
sudo systemctl enable --now redis-server

Endurecer mínimo (local only + contraseña):

Editar /etc/redis/redis.conf:

bind 127.0.0.1 ::1
protected-mode yes
requirepass CAMBIAR_ESTO

Reiniciar:

sudo systemctl restart redis-server

5) Nginx + TLS (Let’s Encrypt)

5.1 Instalar Nginx y Certbot

sudo apt -y install nginx
sudo systemctl enable --now nginx

sudo apt -y install certbot python3-certbot-nginx

5.2 Certificado

sudo certbot --nginx -d "${NC_DOMAIN}"

6) Descargar Nextcloud (fuente oficial)

sudo install -d -m 0755 /var/www
cd /var/www

curl -L -o nextcloud.tar.bz2 https://download.nextcloud.com/server/releases/latest.tar.bz2

sudo tar -xjf nextcloud.tar.bz2
sudo chown -R www-data:www-data nextcloud
sudo chmod -R 0750 nextcloud

Data directory fuera del webroot:

sudo install -d -o www-data -g www-data -m 0770 "${NC_DATA}"

7) Nginx vhost base (genérico)

Crear /etc/nginx/sites-available/nextcloud.conf:

upstream php-handler {
    server unix:/run/php/php8.4-fpm.sock;
}

server {
    listen 80;
    listen [::]:80;
    server_name files.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name files.example.com;

    root /var/www/nextcloud;

    ssl_certificate     /etc/letsencrypt/live/files.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/files.example.com/privkey.pem;

    # Ajusten tamaño según su realidad
    client_max_body_size 2G;
    fastcgi_buffers 64 4K;

    add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;

    index index.php index.html /index.php$request_uri;

    access_log /var/log/nginx/nextcloud.access.log;
    error_log  /var/log/nginx/nextcloud.error.log;

    location = /robots.txt { allow all; log_not_found off; access_log off; }
    location = /.well-known/carddav { return 301 $scheme://$host/remote.php/dav; }
    location = /.well-known/caldav  { return 301 $scheme://$host/remote.php/dav; }

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

    location ~ \.php(?:$|/) {
        rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(/.*)$ /index.php$request_uri;

        include fastcgi_params;
        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param HTTPS on;
        fastcgi_param modHeadersAvailable true;
        fastcgi_param front_controller_active true;
        fastcgi_pass php-handler;
        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }

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

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

Activar:

sudo ln -sf /etc/nginx/sites-available/nextcloud.conf /etc/nginx/sites-enabled/nextcloud.conf
sudo nginx -t
sudo systemctl reload nginx

8) Instalación de Nextcloud por CLI (repetible)

sudo -u www-data php -d memory_limit=512M /var/www/nextcloud/occ maintenance:install \
  --database "mysql" \
  --database-name "${NC_DB}" \
  --database-user "${NC_DB_USER}" \
  --database-pass "${NC_DB_PASS}" \
  --database-host "localhost" \
  --admin-user "admin" \
  --admin-pass "CAMBIAR_ESTO" \
  --data-dir "${NC_DATA}"

Dominio y URL:

sudo -u www-data php /var/www/nextcloud/occ config:system:set trusted_domains 0 --value="${NC_DOMAIN}"
sudo -u www-data php /var/www/nextcloud/occ config:system:set overwrite.cli.url --value="https://${NC_DOMAIN}"

9) Cron (lo correcto)

sudo -u www-data crontab -e

Añadan:

*/5 * * * * php -f /var/www/nextcloud/cron.php

10) Redis en config.php (sin APCu)

Editar /var/www/nextcloud/config/config.php y meter esto dentro del array:

'memcache.distributed' => '\OC\Memcache\Redis',
'memcache.locking' => '\OC\Memcache\Redis',
'redis' => [
  'host' => '127.0.0.1',
  'port' => 6379,
  'password' => 'CAMBIAR_ESTO',
  'timeout' => 1.5,
],

Quitar APCu es una decisión válida si ustedes quieren simplificar. El precio es que pierden el “caché local” rápido. Redis sigue resolviendo lo importante: locking y cache distribuida.


11) Permisos

Código:

sudo chown -R www-data:www-data /var/www/nextcloud
sudo find /var/www/nextcloud/ -type d -exec chmod 750 {} \;
sudo find /var/www/nextcloud/ -type f -exec chmod 640 {} \;

Data dir:

sudo chown -R www-data:www-data "${NC_DATA}"
sudo chmod -R 770 "${NC_DATA}"

12) Checklist post-instalación

sudo -u www-data php /var/www/nextcloud/occ status
sudo -u www-data php /var/www/nextcloud/occ db:add-missing-indices
sudo -u www-data php /var/www/nextcloud/occ maintenance:repair