Wat dit bouwt
Twee machines. Een Ryzen instantie draait Nextcloud, PHP-FPM, Postgres en Redis, allemaal op lokale Gen4-NVMe, waar het latentiegevoelige werk zit. De storage node ernaast bevat de daadwerkelijke bestandsinhoud in een objectbucket, waar de goedkope terabytes liggen. Daartussen zit een WireGuard-tunnel, zodat niets in deze opstelling aan iets anders wordt blootgesteld.
De splitsing is belangrijk omdat Nextcloud met een primaire objectstore stopt met het volledig wegschrijven van gebruikersdata naar de lokale schijf. Je NVMe bevat de database en de code; de bucket bevat elke byte die iemand uploadt. Groeien van tweehonderd gigabyte naar twintig terabyte wordt dan een upgrade van de storage node in plaats van een migratie.
Voordat je begint
- Een R-8 voor de applicatie en een S-50 voor de bucket, idealiter in dezelfde stad, zodat de tunnelroundtrip onder een milliseconde blijft.
- Een tunnel ertussen. De WireGuard handleiding bouwt precies dit; gebruik
10.9.0.1voor de app en10.9.0.2voor de storage node. - Een hostname die naar de app-instantie wijst,
cloud.example.comhieronder.
1. Objectopslag op de storage node
MinIO is een enkel binair bestand en heeft niets anders nodig. Haal het op, verifieer het, installeer het:
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/objectsDe bulktier op een storage node wordt apart van de NVMe gemount. Zet de bucket op de bulktier en laat de NVMe voor de writecache, waarvoor die er is. Dan de unit, op /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.targetBinden aan het tunneladres in plaats van aan alles is de belangrijke regel. De objectstore heeft niets te zoeken op de publieke interface, en op deze manier kan een firewallfout het niet blootstellen.
systemctl daemon-reload && systemctl enable --now minio
ss -ltn | grep 90002. Applicatiehost: pakketten
Op de Ryzen-instantie:
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;"Standaard Postgres-instellingen zijn prima op deze schaal. Als deze Nextcloud uiteindelijk een paar honderd mensen bedient, is de Postgres tuning handleiding van toepassing en zijn de getallen daarin een uur waard.
4. Nextcloud, geconfigureerd vóór installatie
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/nextcloudNu het deel dat vóór de installer moet gebeuren, omdat een primaire objectstore niet aan een bestaande instantie kan worden toegevoegd zonder elk bestand handmatig te verplaatsen. Maak /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 is opzettelijk onwaar. Het verkeer gaat door een WireGuard-tunnel die al geverifieerd en versleuteld is, en een tweede keer TLS beëindigen op de storage node levert niets op behalve CPU-cycli en een certificaat om te vergeten te vernieuwen. Mochten de twee machines ooit in verschillende steden staan, zet het dan aan.
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 en de laatste instellingen
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 via een unix socket in plaats van TCP bespaart een syscall roundtrip bij elke lock-operatie, en Nextcloud neemt veel locks. Voeg www-data toe aan de redis-groep zodat deze de socket kan bereiken, koppel vervolgens de achtergrondtaak aan een 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 -PHP-FPM standaardwaarden gaan uit van een gedeelde machine. De jouwe is niet gedeeld, dus stel in /etc/php/8.4/fpm/pool.d/www.conf pm = dynamic, pm.max_children = 60, pm.start_servers = 12, pm.min_spare_servers = 8 en pm.max_spare_servers = 20 in, en verhoog memory_limit naar 1G in /etc/php/8.4/fpm/php.ini. Uploads willen upload_max_filesize en post_max_size op 16G, tenzij je graag uitlegt waarom een video op negentig procent faalde.
Verifieer het
Het punt van deze build is dat gebruikersbestanden niet op de applicatieserver staan. Bewijs dat met drie commando's.
sudo -u www-data php occ status
du -sh /var/www/nextcloud/dataStatus moet "geïnstalleerd" melden en niet in onderhoudsmodus. De datamap moet een handvol megabytes zijn en dat voor altijd blijven; die bevat logs en niets anders zodra objectopslag primair is.
Upload nu iets en kijk waar het terechtkomt:
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/dataDe upload slaagt en de datamap is niet met vijftig megabyte gegroeid. Op de storage node is het object direct zichtbaar:
ls -R /srv/objects/nextcloud | tail -5
du -sh /srv/objects/nextcloudObjecten heten urn:oid: gevolgd door de bestands-id, daarom is de bucket geen doorzoekbare kopie van de mappen van de gebruiker en daarom back-upp je de database en de bucket samen of helemaal niet.
Achteraf
Neem de off-node backup add-on voor de Postgres-dump en de bucket, of voer je eigen backup uit naar een derde locatie. Een bucket zonder zijn database is een stapel genummerde blobs, en een database zonder zijn bucket is een index van bestanden die niet meer bestaan. Verlies je een van beide, dan verlies je beide.