O que isto constrói
Duas máquinas. Uma instância Ryzen executa Nextcloud, PHP-FPM, Postgres e Redis, tudo em NVMe Gen4 local, que é onde fica o trabalho sensível à latência. O nó de armazenamento ao lado mantém o conteúdo real dos arquivos em um bucket de objetos, que é onde ficam os terabytes baratos. Entre eles há um túnel WireGuard, então nada na configuração fica exposto a mais nada.
A separação importa porque o Nextcloud com armazenamento de objetos primário para de gravar dados de usuário no disco local por completo. Sua NVMe mantém o banco de dados e o código; o bucket mantém cada byte que alguém envia. Crescer de duzentos gigabytes para vinte terabytes torna-se uma atualização do nó de armazenamento em vez de uma migração.
Antes de começar
- Um R-8 para o aplicativo e um S-50 para o bucket, idealmente na mesma cidade para que o round-trip do túnel fique abaixo de um milissegundo.
- Um túnel entre eles. O guia WireGuard constrói exatamente isso; use
10.9.0.1para o aplicativo e10.9.0.2para o nó de armazenamento. - Um hostname apontando para a instância do aplicativo,
cloud.example.comabaixo.
1. Armazenamento de objetos no nó de armazenamento
MinIO é um único binário e não precisa de mais nada. Baixe, verifique, instale:
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/objectsO tier em massa em um nó de armazenamento é montado separadamente do NVMe. Coloque o bucket no tier em massa e deixe o NVMe para o cache de escrita, que é para isso que ele serve. Então a unit, em /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.targetVincular ao endereço do túnel em vez de tudo é a linha importante. O armazenamento de objetos não tem motivo para responder na interface pública, e assim um erro de firewall não pode expô-lo.
systemctl daemon-reload && systemctl enable --now minio
ss -ltn | grep 90002. Host do aplicativo: pacotes
Na instância 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. Banco de dados
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;"As configurações padrão do Postgres são suficientes nessa escala. Se este Nextcloud acabar servindo algumas centenas de pessoas, o guia de ajuste do Postgres se aplica e os números nele valem uma hora.
4. Nextcloud, configurado antes da instalação
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/nextcloudAgora a parte que tem que acontecer antes de o instalador rodar, porque um armazenamento de objetos primário não pode ser adicionado a uma instância existente sem mover cada arquivo manualmente. Crie /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 de propósito. O tráfego cruza um túnel WireGuard que já é autenticado e criptografado, e encerrar TLS uma segunda vez no nó de armazenamento não compra nada exceto ciclos de CPU e um certificado para esquecer de renovar. Caso as duas máquinas algum dia fiquem em cidades diferentes, ligue-o.
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 as últimas configurações
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 em um soquete unix em vez de TCP economiza uma chamada de sistema round trip em cada operação de lock, e o Nextcloud usa muitos locks. Adicione www-data ao grupo redis para que ele possa alcançar o soquete, então conecte o job de segundo plano a um 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 -Os padrões do PHP-FPM assumem uma máquina compartilhada. A sua não é compartilhada, então em /etc/php/8.4/fpm/pool.d/www.conf defina pm = dynamic, pm.max_children = 60, pm.start_servers = 12, pm.min_spare_servers = 8 e pm.max_spare_servers = 20, e aumente memory_limit para 1G em /etc/php/8.4/fpm/php.ini. Uploads querem upload_max_filesize e post_max_size em 16G a menos que você goste de explicar por que um vídeo falhou aos noventa por cento.
Verificar
O objetivo desta construção é que os arquivos do usuário não ficam no servidor do aplicativo. Prove isso, em três comandos.
sudo -u www-data php occ status
du -sh /var/www/nextcloud/dataO status deve reportar instalado e não em modo de manutenção. O diretório de dados deve ter alguns megabytes e permanecer assim para sempre; ele mantém logs e nada mais uma vez que o armazenamento de objetos é primário.
Agora envie algo e veja onde vai parar:
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/dataO upload é bem-sucedido, e o diretório de dados não cresceu cinquenta megabytes. No nó de armazenamento, o objeto é visível diretamente:
ls -R /srv/objects/nextcloud | tail -5
du -sh /srv/objects/nextcloudOs objetos são nomeados urn:oid: seguido pelo id do arquivo, que é por que o bucket não é uma cópia navegável das pastas do usuário e por que você faz backup do banco de dados e do bucket juntos ou não faz de jeito nenhum.
Depois
Pegue o complemento de backup off-node para o dump do Postgres e o bucket, ou execute o seu próprio para um terceiro site. Um bucket sem seu banco de dados é uma pilha de blobs numerados, e um banco de dados sem seu bucket é um índice de arquivos que não existem mais. Perder um perde ambos.