Mười hai bài xây dựng

Một Nextcloud riêng tư trên NVMe với bộ lưu trữ đối tượng phía sau

Nextcloud trên một instance Ryzen với Postgres và Redis trên NVMe cục bộ, mọi tệp người dùng nằm trong một bucket trên một storage node, được kết nối bằng một đường hầm riêng.

Công cụ này tạo ra gì

Hai máy chủ. Một phiên bản Ryzen chạy Nextcloud, PHP-FPM, Postgres và Redis, tất cả đều trên ổ NVMe Gen4 cục bộ, nơi chứa các tác vụ nhạy cảm với độ trễ. Nút lưu trữ bên cạnh chứa nội dung tệp thực tế trong một bucket đối tượng, nơi chứa các terabyte rẻ tiền. Giữa chúng là một đường hầm WireGuard, do đó không có gì trong cấu hình này bị lộ ra ngoài.

Sự tách biệt này quan trọng vì Nextcloud với kho đối tượng chính sẽ ngừng ghi dữ liệu người dùng vào đĩa cục bộ hoàn toàn. Ổ NVMe của bạn giữ cơ sở dữ liệu và mã nguồn; bucket giữ mọi byte mà bất kỳ ai tải lên. Mở rộng từ hai trăm gigabyte lên hai mươi terabyte sau đó trở thành một bản nâng cấp nút lưu trữ thay vì di chuyển dữ liệu.

Trước khi bắt đầu

  • Một R-8 cho ứng dụng và một S-50 cho bucket, lý tưởng nhất là trong cùng một thành phố để thời gian khứ hồi của đường hầm dưới một mili giây.
  • Một đường hầm giữa chúng. Hướng dẫn WireGuard xây dựng chính xác điều này; sử dụng 10.9.0.1 cho ứng dụng và 10.9.0.2 cho nút lưu trữ.
  • Một tên miền trỏ tới phiên bản ứng dụng, cloud.example.com bên dưới.

1. Lưu trữ đối tượng trên nút lưu trữ

MinIO là một tệp nhị phân duy nhất và không cần gì khác. Tải về, xác minh, cài đặt:

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/objects

Tầng dung lượng lớn trên nút lưu trữ được gắn riêng biệt với ổ NVMe. Đặt bucket trên tầng dung lượng lớn và để ổ NVMe cho bộ nhớ đệm ghi, đó là mục đích của nó. Sau đó, đơn vị, tại /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.target

Ràng buộc với địa chỉ đường hầm thay vì với mọi thứ là dòng quan trọng. Kho đối tượng không cần trả lời trên giao diện công cộng, và theo cách này, lỗi tường lửa không thể lộ nó ra ngoài.

systemctl daemon-reload && systemctl enable --now minio
ss -ltn | grep 9000

2. Máy chủ ứng dụng: các gói

Trên phiên bản 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-apcu

3. Cơ sở dữ liệu

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;"

Các cài đặt Postgres mặc định là đủ ở quy mô này. Nếu Nextcloud này phục vụ vài trăm người, hướng dẫn điều chỉnh Postgres áp dụng và các con số trong đó đáng để dành một giờ.

4. Nextcloud, được cấu hình trước khi cài đặt

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/nextcloud

Bây giờ là phần phải làm trước khi chạy trình cài đặt, vì không thể thêm kho đối tượng chính vào một phiên bản hiện có mà không di chuyển mọi tệp bằng tay. Tạo /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 được đặt là false có chủ đích. Lưu lượng truy cập đi qua đường hầm WireGuard đã được xác thực và mã hóa, và việc kết thúc TLS lần thứ hai trên nút lưu trữ không mang lại lợi ích gì ngoài việc tốn chu kỳ CPU và một chứng chỉ để quên gia hạn. Nếu hai máy chủ ở các thành phố khác nhau, hãy bật nó lên.

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. Bộ nhớ đệm, cron và các cài đặt cuối cùng

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:cron

Redis qua unix socket thay vì TCP tiết kiệm một syscall khứ hồi cho mỗi thao tác khóa, và Nextcloud lấy rất nhiều khóa. Thêm www-data vào nhóm redis để nó có thể truy cập socket, sau đó gắn công việc nền vào một bộ hẹn giờ:

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 -

Các cài đặt mặc định của PHP-FPM giả định một máy dùng chung. Máy của bạn không dùng chung, vì vậy trong /etc/php/8.4/fpm/pool.d/www.conf đặt pm = dynamic, pm.max_children = 60, pm.start_servers = 12, pm.min_spare_servers = 8pm.max_spare_servers = 20, và nâng memory_limit lên 1G trong /etc/php/8.4/fpm/php.ini. Upload muốn upload_max_filesizepost_max_size ở mức 16G trừ khi bạn muốn giải thích tại sao một video thất bại ở chín mươi phần trăm.

Xác minh

Điểm của bản dựng này là các tệp người dùng không nằm trên máy chủ ứng dụng. Chứng minh điều đó bằng ba lệnh.

sudo -u www-data php occ status
du -sh /var/www/nextcloud/data

Trạng thái báo cáo đã cài đặt và không ở chế độ bảo trì. Thư mục dữ liệu nên chỉ vài megabyte và giữ nguyên như vậy mãi mãi; nó chứa log và không gì khác khi kho đối tượng là chính.

Bây giờ tải lên một thứ gì đó và xem nó nằm ở đâu:

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/data

Upload thành công, và thư mục dữ liệu không tăng thêm năm mươi megabyte. Trên nút lưu trữ, đối tượng có thể được nhìn thấy trực tiếp:

ls -R /srv/objects/nextcloud | tail -5
du -sh /srv/objects/nextcloud

Các đối tượng được đặt tên urn:oid: theo sau là id tệp, đó là lý do tại sao bucket không phải là một bản sao có thể duyệt của các thư mục người dùng và tại sao bạn sao lưu cơ sở dữ liệu và bucket cùng nhau hoặc không sao lưu gì cả.

Sau đó

Sử dụng tiện ích bổ sung sao lưu ngoài nút cho bản sao Postgres và bucket, hoặc tự chạy đến một trang web thứ ba. Một bucket mà không có cơ sở dữ liệu của nó là một đống các blob được đánh số, và một cơ sở dữ liệu mà không có bucket của nó là một chỉ mục của các tệp không còn tồn tại. Mất một trong hai là mất cả hai.

Sẵn sàng khi bạn cần

Chọn thành phố. Chọn kích thước. Thanh toán bằng coin.

Không có biểu mẫu về bạn là ai, không chờ đợi con người phê duyệt, không gọi điện thoại để xác minh bất cứ điều gì. Hóa đơn được thanh toán và thông tin đăng nhập sẽ vào hộp thư của bạn.