اثنا عشر بناءً

Nextcloud خاص على NVMe مع تخزين كائنات خلفه

Nextcloud على مثيل Ryzen مع Postgres و Redis على NVMe محلي، وكل ملف مستخدم يعيش في حاوية على عقدة تخزين، مرتبطين بنفق خاص.

ما يبنيه هذا الدليل

جهازان. مثيل Ryzen يشغّل Nextcloud وPHP-FPM وPostgres وRedis، كلها على NVMe محلي من الجيل الرابع، حيث يعيش العمل الحساس لزمن الاستجابة. عقدة التخزين المجاورة تحمل محتوى الملفات الفعلي في دلو كائنات، حيث تعيش التيرابايتات الرخيصة. بينهما نفق WireGuard، بحيث لا يكون أي شيء في هذا الترتيب مكشوفًا لأي شيء آخر.

الانقسام مهم لأن Nextcloud مع مخزن كائنات أساسي يتوقف عن كتابة بيانات المستخدم على القرص المحلي تمامًا. NVMe الخاص بك يحمل قاعدة البيانات والكود؛ الدلو يحمل كل بايت يرفعه أي شخص. النمو من مئتي غيغابايت إلى عشرين تيرابايت يصبح بعدها ترقية لعقدة التخزين بدلاً من ترحيل.

قبل أن تبدأ

  • R-8 للتطبيق وS-50 للدلو، ويفضل في نفس المدينة بحيث يكون زمن رحلة النفق أقل من ميلي ثانية.
  • نفق بينهما. دليل WireGuard يبني هذا بالضبط؛ استخدم 10.9.0.1 للتطبيق و10.9.0.2 لعقدة التخزين.
  • اسم مضيف يشير إلى مثيل التطبيق، cloud.example.com أدناه.

1. تخزين الكائنات على عقدة التخزين

MinIO هو ملف ثنائي واحد ولا يحتاج إلى أي شيء آخر. اجلبه، تحقق منه، ثبّته:

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

الطبقة السائبة على عقدة التخزين تُركب بشكل منفصل عن NVMe. ضع الدلو على الطبقة السائبة واترك NVMe لذاكرة الكتابة المؤقتة، فهذا ما هو موجود من أجله. ثم الوحدة، في /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

الربط بعنوان النفق بدلاً من كل شيء هو السطر المهم. لا يحق لمخزن الكائنات أن يجيب على الواجهة العامة، وبهذه الطريقة لا يمكن لخطأ في جدار الحماية كشفه.

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

2. مضيف التطبيق: الحزم

على مثيل 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. قاعدة البيانات

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

إعدادات Postgres الافتراضية جيدة في هذا الحجم. إذا انتهى هذا Nextcloud في خدمة بضع مئات من الأشخاص، فإن دليل ضبط Postgres ينطبق والأرقام فيه تستحق ساعة.

4. Nextcloud، مكوّن قبل التثبيت

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

الآن الجزء الذي يجب أن يحدث قبل تشغيل المثبت، لأنه لا يمكن إضافة مخزن كائنات أساسي إلى مثيل موجود دون نقل كل ملف يدويًا. أنشئ /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 خطأ عن قصد. فالتدفق يعبر نفق WireGuard الذي هو مصادق عليه ومشفّر بالفعل، وإنهاء TLS مرة ثانية على عقدة التخزين لا يشتري شيئًا سوى دورات CPU وشهادة تنسى تجديدها. إذا جلس الجهازان يومًا في مدينتين مختلفتين، فشغّله.

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. الكاش، cron، والإعدادات الأخيرة

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 عبر مقبس unix بدلاً من TCP يوفر استدعاء نظام ذهابًا وإيابًا في كل عملية قفل، وNextcloud يأخذ الكثير من الأقفال. أضف www-data إلى مجموعة redis ليتمكن من الوصول إلى المقبس، ثم اربط المهمة الخلفية بمؤقت:

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 تفترض جهازًا مشتركًا. جهازك ليس مشتركًا، لذا في /etc/php/8.4/fpm/pool.d/www.conf عيّن pm = dynamic وpm.max_children = 60 وpm.start_servers = 12 وpm.min_spare_servers = 8 وpm.max_spare_servers = 20، وارفع memory_limit إلى 1G في /etc/php/8.4/fpm/php.ini. الرفعات تريد upload_max_filesize وpost_max_size عند 16G إلا إذا كنت تستمتع بشرح سبب فشل فيديو عند تسعين بالمئة.

التحقق

الهدف من هذا البناء هو أن ملفات المستخدم ليست على خادم التطبيق. أثبت ذلك، في ثلاثة أوامر.

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

يجب أن تبلغ الحالة بأنه مثبت وليس في وضع الصيانة. يجب أن يكون دليل البيانات حفنة من الميغابايتات ويبقى كذلك إلى الأبد؛ فهو يحمل السجلات ولا شيء آخر بمجرد أن يصبح تخزين الكائنات أساسيًا.

الآن ارفع شيئًا وشاهد أين يهبط:

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

ينجح الرفع، ودليل البيانات لم ينم بخمسين ميغابايتًا. على عقدة التخزين، يظهر الكائن مباشرةً:

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

تُسمى الكائنات urn:oid: متبوعًا بمعرف الملف، ولهذا فإن الدلو ليس نسخة قابلة للتصفح من مجلدات المستخدم، ولهذا تنسخ قاعدة البيانات والدلو معًا أو لا تنسخ شيئًا.

بعد ذلك

خذ إضافة النسخ الاحتياطي خارج العقدة لتفريغ Postgres والدلو، أو شغّل نسختك الخاصة إلى موقع ثالث. دلو بدون قاعدة بياناته هو كومة من الكتل المرقمة، وقاعدة بيانات بدون دلوها هي فهرس لملفات لم تعد موجودة. فقدان أي منهما يفقد كليهما.

جاهز عندما تكون

اختر مدينة. اختر الحجم. ادفع بالعملة الرقمية.

لا نماذج عن هويتك، ولا انتظار لموافقة بشرية، ولا مكالمة للتحقق من أي شيء. بمجرد تصفية الفاتورة، تصل بيانات الدخول إلى بريدك الإلكتروني.