Che cosa costruisce questa guida
Due macchine. Una istanza Ryzen esegue Nextcloud, PHP-FPM, Postgres e Redis, tutto su NVMe Gen4 locale, dove vive il lavoro sensibile alla latenza. Il nodo di storage accanto contiene il contenuto dei file vero e proprio in un bucket a oggetti, dove vivono i terabyte economici. Tra i due si trova un tunnel WireGuard, quindi nulla nella configurazione è esposto a nient'altro.
La separazione è importante perché Nextcloud con un object store primario smette del tutto di scrivere i dati utente sul disco locale. La tua NVMe contiene il database e il codice; il bucket contiene ogni byte caricato da chiunque. Passare da duecento gigabyte a venti terabyte diventa allora un upgrade del nodo di storage, non una migrazione.
Prima di iniziare
- Una R-8 per l'applicazione e una S-50 per il bucket, idealmente nella stessa città così il round-trip del tunnel è sotto il millisecondo.
- Un tunnel tra di loro. La guida WireGuard costruisce esattamente questo; usa
10.9.0.1per l'app e10.9.0.2per il nodo di storage. - Un hostname che punta all'istanza dell'app,
cloud.example.comsotto.
1. Object storage sul nodo di storage
MinIO è un singolo binario e non serve altro. Scaricalo, verificalo, installalo:
cd /usr/local/bin
wget https://dl.min.io/server/minio/release/linux-amd64/minio
wget https://dl.min.io/server/minio/release/linux-amd64/minio.sha256sum
sha256sum -c minio.sha256sum
chmod +x minio
useradd -r -s /sbin/nologin minio
install -d -o minio -g minio /srv/objectsIl livello bulk su un nodo di storage è montato separatamente dalla NVMe. Metti il bucket sul livello bulk e lascia la NVMe per la cache di scrittura, che è il suo scopo. Poi la unit, a /etc/systemd/system/minio.service:
[Unit]
Description=MinIO
After=network-online.target [email protected]
Wants=network-online.target
[Service]
User=minio
Group=minio
Environment=MINIO_ROOT_USER=nextcloud
Environment=MINIO_ROOT_PASSWORD=<forty random characters>
ExecStart=/usr/local/bin/minio server /srv/objects --address 10.9.0.2:9000
Restart=always
LimitNOFILE=65535
NoNewPrivileges=yes
ProtectSystem=strict
ReadWritePaths=/srv/objects
[Install]
WantedBy=multi-user.targetIl binding all'indirizzo del tunnel invece che a tutto è la riga importante. L'object store non deve rispondere sull'interfaccia pubblica, e così un errore di firewall non può esporlo.
systemctl daemon-reload && systemctl enable --now minio
ss -ltn | grep 90002. Host dell'applicazione: pacchetti
Sull'istanza Ryzen:
apt update && apt install -y nginx postgresql redis-server unzip \
php8.4-fpm php8.4-pgsql php8.4-gd php8.4-curl php8.4-zip php8.4-xml \
php8.4-mbstring php8.4-intl php8.4-bcmath php8.4-gmp php8.4-imagick \
php8.4-redis php8.4-apcu3. Database
sudo -u postgres psql -c "CREATE USER nextcloud WITH PASSWORD '<a long password>';"
sudo -u postgres psql -c "CREATE DATABASE nextcloud OWNER nextcloud TEMPLATE template0 ENCODING UTF8;"Le impostazioni predefinite di Postgres vanno bene a questa scala. Se questo Nextcloud finisce per servire qualche centinaio di persone, la guida alla ottimizzazione di Postgres si applica e i numeri che contiene valgono un'ora.
4. Nextcloud, configurato prima dell'installazione
cd /var/www
wget https://download.nextcloud.com/server/releases/latest.zip
unzip -q latest.zip && rm latest.zip
chown -R www-data:www-data /var/www/nextcloudOra la parte che deve avvenire prima che l'installer giri, perché un object store primario non può essere aggiunto a un'istanza esistente senza spostare ogni file a mano. Crea /var/www/nextcloud/config/config.php:
<?php
$CONFIG = array(
"objectstore" => array(
"class" => "\\OC\\Files\\ObjectStore\\S3",
"arguments" => array(
"bucket" => "nextcloud",
"autocreate" => true,
"key" => "nextcloud",
"secret" => "<the same forty characters>",
"hostname" => "10.9.0.2",
"port" => 9000,
"use_ssl" => false,
"use_path_style" => true,
"region" => "local",
),
),
);use_ssl è falso di proposito. Il traffico attraversa un tunnel WireGuard che è già autenticato e cifrato, e terminare TLS una seconda volta sul nodo di storage non compra nulla se non cicli di CPU e un certificato da dimenticare di rinnovare. Se le due macchine mai si trovassero in città diverse, attivalo.
chown www-data:www-data /var/www/nextcloud/config/config.php
chmod 640 /var/www/nextcloud/config/config.php
cd /var/www/nextcloud
sudo -u www-data php occ maintenance:install --database pgsql \
--database-name nextcloud --database-user nextcloud \
--database-pass "<a long password>" \
--admin-user admin --admin-pass "<another long password>"5. Cache, cron e le ultime impostazioni
sudo -u www-data php occ config:system:set memcache.local --value "\\OC\\Memcache\\APCu"
sudo -u www-data php occ config:system:set memcache.distributed --value "\\OC\\Memcache\\Redis"
sudo -u www-data php occ config:system:set memcache.locking --value "\\OC\\Memcache\\Redis"
sudo -u www-data php occ config:system:set redis host --value /run/redis/redis-server.sock
sudo -u www-data php occ config:system:set redis port --value 0
sudo -u www-data php occ config:system:set trusted_domains 0 --value cloud.example.com
sudo -u www-data php occ config:system:set overwrite.cli.url --value https://cloud.example.com
sudo -u www-data php occ background:cronRedis su un socket unix invece che su TCP risparmia un round trip di syscall su ogni operazione di lock, e Nextcloud prende un sacco di lock. Aggiungi www-data al gruppo redis così può raggiungere il socket, poi collega il job in background a un timer:
usermod -aG redis www-data
systemctl restart php8.4-fpm redis-server
echo "*/5 * * * * php -f /var/www/nextcloud/cron.php" | crontab -u www-data -I predefiniti di PHP-FPM assumono una macchina condivisa. La tua non lo è, quindi in /etc/php/8.4/fpm/pool.d/www.conf imposta pm = dynamic, pm.max_children = 60, pm.start_servers = 12, pm.min_spare_servers = 8 e pm.max_spare_servers = 20, e alza memory_limit a 1G in /etc/php/8.4/fpm/php.ini. Gli upload vogliono upload_max_filesize e post_max_size a 16G a meno che non ti diverta spiegare perché un video è fallito al novanta percento.
Verifica
Il punto di questa build è che i file utente non sono sul server dell'applicazione. Dimostralo, con tre comandi.
sudo -u www-data php occ status
du -sh /var/www/nextcloud/dataLo stato deve riportare installato e non in modalità manutenzione. La directory dati deve essere una manciata di megabyte e restare tale per sempre; contiene log e nient'altro una volta che l'object storage è primario.
Ora carica qualcosa e guarda dove finisce:
head -c 50M /dev/urandom > /tmp/test.bin
curl -u admin -T /tmp/test.bin https://cloud.example.com/remote.php/dav/files/admin/test.bin
du -sh /var/www/nextcloud/dataL'upload ha successo, e la directory dati non è cresciuta di cinquanta megabyte. Sul nodo di storage, l'oggetto è visibile direttamente:
ls -R /srv/objects/nextcloud | tail -5
du -sh /srv/objects/nextcloudGli oggetti sono nominati urn:oid: seguito dall'id del file, che è il motivo per cui il bucket non è una copia navigabile delle cartelle dell'utente e perché fai il backup del database e del bucket insieme o per niente.
Dopo
Prendi il componente aggiuntivo di backup fuori nodo per il dump di Postgres e il bucket, o esegui il tuo verso un terzo sito. Un bucket senza il suo database è una pila di blob numerati, e un database senza il suo bucket è un indice di file che non esistono più. Perdere l'uno perde entrambi.