العودة إلى المدونة

تثبيت Redis وتأمينه على خادم VPS للتخزين المؤقت وطوابير المهام

فريق تحرير IM Host25 أكتوبر 20267 دقائق قراءة
تثبيت Redis وتأمينه على خادم VPS للتخزين المؤقت وطوابير المهام

Redis مخزن بيانات في الذاكرة تستخدمه أغلب تطبيقات الويب في مهمتين: تخزين النتائج المكلفة مؤقتًا، وحفظ طوابير المهام التي تعمل في الخلفية. يتم التثبيت بأمر واحد، لكن الإعداد الآمن يحتاج إلى بعض القرارات: من يستطيع الاتصال، وكم من الذاكرة يُسمح له باستخدامها، وماذا يحدث عندما تمتلئ، وهل يجب أن تبقى البيانات بعد إعادة التشغيل. الإجابات الصحيحة تختلف بين التخزين المؤقت وطوابير المهام، وهذا الدليل يشرح الحالتين.

الخطوة 1: ثبّت Redis

على Ubuntu أو Debian:

sudo apt update
sudo apt install redis-server
redis-server --version
sudo systemctl status redis-server

الحزمة الموجودة في التوزيعة إصدار مستقر يتلقى تحديثات الأمان، وهي مناسبة لأغلب التطبيقات. إذا احتجت إلى إصدار أحدث، فلدى Redis مستودع APT خاص بها. كما أن Valkey، وهو نسخة مفتوحة المصدر متفرعة من Redis، يستخدم توجيهات الإعداد نفسها، فكل ما يلي ينطبق عليه أيضًا.

ملف الإعداد الرئيسي هو /etc/redis/redis.conf. بعد كل تعديل أعد التشغيل وراجع السجل:

sudo systemctl restart redis-server
sudo journalctl -u redis-server -n 50

الخطوة 2: تحكّم في من يستطيع الاتصال (bind وprotected-mode)

خادم Redis مكشوف على الإنترنت دون كلمة مرور من أكثر الطرق شيوعًا لاختراق الخوادم. يتصل المهاجم، ويستخدم CONFIG SET لتغيير المكان الذي يكتب فيه Redis ملف بياناته، ثم يكتب مفتاح SSH أو مهمة cron على القرص. إعدادان يمنعان ذلك:

bind 127.0.0.1 -::1
protected-mode yes
port 6379

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

وإذا كان التطبيق على خادم آخر، فأضف عنوان الشبكة الخاصة، ولا تستخدم 0.0.0.0 على واجهة عامة أبدًا:

bind 127.0.0.1 10.0.0.5

ثم اسمح لخادم التطبيق وحده في الجدار الناري:

sudo ufw allow from 10.0.0.4 to any port 6379 proto tcp

أما protected-mode فهو شبكة أمان. عندما يكون مفعّلًا ولا توجد كلمة مرور للمستخدم الافتراضي، يرفض Redis الاتصالات غير المحلية برسالة تبدأ بـ DENIED Redis is running in protected mode because protected mode is enabled. إذا ظهرت لك هذه الرسالة، فالحل هو ضبط كلمة مرور، لا تعطيل الوضع المحمي.

تحقق مما يستمع عليه Redis فعلًا:

ss -tlnp | grep 6379

الخطوة 3: اشترط المصادقة

حتى على localhost، تمنع كلمة المرور أي عملية أو مستخدم آخر على الخادم من قراءة بياناتك. لديك خياران.

الخيار A: requirepass (تطبيق واحد وكلمة مرور واحدة)

openssl rand -hex 32
requirepass 3f9c...your-64-character-hex-value...

كلمة المرور بصيغة hex تتجنب رموزًا مثل / و+ التي تحتاج إلى ترميز في روابط الاتصال. والعميل الذي لا يرسل كلمة المرور يتلقى NOAUTH Authentication required.

الخيار B: مستخدمو ACL (عدة تطبيقات أو أدوار)

منذ Redis 6، تتيح قوائم التحكم في الوصول إنشاء مستخدمين بأسماء وأوامر وأنماط مفاتيح محددة. وجّه Redis إلى ملف ACL داخل redis.conf:

aclfile /etc/redis/users.acl

ثم أنشئ الملف /etc/redis/users.acl:

user default off
user app on >APP_PASSWORD_HERE ~app:* &app:* +@all -@dangerous
user admin on >ADMIN_PASSWORD_HERE ~* &* +@all
sudo chown redis:redis /etc/redis/users.acl
sudo chmod 640 /etc/redis/users.acl

هذا يعطّل المستخدم الافتراضي الذي لا يملك كلمة مرور، ويسمح للتطبيق بالوصول فقط إلى المفاتيح التي تبدأ بـ app:، ويمنع فئة @dangerous التي تشمل FLUSHALL وCONFIG وKEYS وDEBUG. استخدم طريقة واحدة فقط: عند استخدام ملف ACL، عرّف المستخدمين فيه وليس عبر requirepass.

اختبر مكتبة الطوابير أو التخزين المؤقت بعد تقييد الأوامر. بعض المكتبات تستدعي أوامر من فئة @dangerous مثل INFO، وبعضها يستخدم بادئة مفاتيح خاصة به (BullMQ تستخدم bull: افتراضيًا). عدّل القاعدة، مثلًا بإضافة +info أو نمط مفاتيح آخر، بدلًا من منح التطبيق صلاحيات كاملة.

اختبر تسجيل الدخول:

export REDISCLI_AUTH='APP_PASSWORD_HERE'
redis-cli --user app ping

يجب أن تحصل على PONG. أما كلمة المرور الخاطئة فتعيد WRONGPASS invalid username-password pair or user is disabled. واستخدام REDISCLI_AUTH يبقي كلمة المرور خارج سجل أوامر الطرفية. تمريرها عبر -a يعمل، لكن redis-cli يحذّر من أنه قد لا يكون آمنًا.

تستخدم أدلة قديمة الخيار rename-command لإخفاء الأوامر. قوائم ACL حلّت محل هذه الطريقة، وهي أسهل في المراجعة.

الخطوة 4: حدد سقفًا للذاكرة وسياسة للإخلاء

دون سقف، يكبر Redis حتى يوقفه قاتل الذاكرة (OOM killer) في النواة، أو يوقف شيئًا أهم منه. اضبط maxmemory صراحة:

maxmemory 512mb
maxmemory-policy allkeys-lru

كم تضع؟ كقاعدة تقريبية، إذا كان الحفظ على القرص مفعّلًا، فاجعل maxmemory في حدود نصف إلى ثلاثة أرباع الذاكرة التي تخصصها لـ Redis. فالحفظ على القرص ينسخ العملية (fork)، والصفحات التي تتغير أثناء الحفظ تُنسخ، فيرتفع استهلاك الذاكرة خلال تلك الفترة.

تحدد السياسة ما يحدث عند الوصول إلى السقف:

السياسةالسلوكتُستخدم في
allkeys-lruتحذف المفتاح الأقل استخدامًا مؤخرًاتخزين مؤقت خالص
allkeys-lfuتحذف المفتاح الأقل تكرارًا في الاستخدامتخزين مؤقت بمجموعة ثابتة من المفاتيح الشائعة
volatile-lruتحذف فقط المفاتيح التي لها مدة صلاحية (TTL)مفاتيح مؤقتة مع مفاتيح يجب أن تبقى
noevictionترفض الكتابة وتعيد خطأالطوابير والجلسات وكل ما لا يجوز فقدانه

النقطة المهمة: يجب ألا يفقد الطابور مهامه بصمت. مع noeviction يعيد Redis الممتلئ الخطأ OOM command not allowed when used memory > 'maxmemory'. فيرى تطبيقك خطأً ويستطيع تنبيهك. أما مع سياسة LRU فستختفي المهام دون أثر. ولأن السياسة تنطبق على الخادم كله، فالإعداد الأنظف هو نسختان من Redis: واحدة للتخزين المؤقت بسياسة allkeys-lru، وأخرى للطوابير بسياسة noeviction.

الخطوة 5: اختر طريقة الحفظ على القرص

يحتفظ Redis بالبيانات في الذاكرة، وطريقة الحفظ تحدد ما يبقى بعد إعادة التشغيل.

  • لقطات RDB تكتب البيانات كاملة في dump.rdb على فترات. الملفات مضغوطة وتُستعاد بسرعة، لكنك قد تفقد ما كُتب منذ آخر لقطة.

  • AOF (ملف الإلحاق) يسجل كل عملية كتابة. مع appendfsync everysec تفقد في حالة الانهيار ثانية واحدة تقريبًا من الكتابات كحد أقصى. الملفات أكبر، ويعيد Redis كتابتها في الخلفية.

  • بلا حفظ: لا يُحفظ شيء. مناسب لتخزين مؤقت يستطيع تطبيقك إعادة بنائه من قاعدة البيانات.

للتخزين المؤقت:

save ""
appendonly no

للطوابير والجلسات:

appendonly yes
appendfsync everysec
save 3600 1 300 100 60 10000

تُخزن البيانات في /var/lib/redis. انسخ ملف RDB إلى مكان آخر بشكل دوري، فالملف الموجود على القرص نفسه ليس نسخة احتياطية.

الخطوة 6: عالج تحذيرات النواة

عند الإقلاع يفحص Redis بعض إعدادات النواة. أكثر التحذيرات شيوعًا هو WARNING Memory overcommit must be enabled! ومعناه أن الحفظ في الخلفية قد يفشل عندما تضيق الذاكرة. عالجه هكذا:

echo 'vm.overcommit_memory = 1' | sudo tee /etc/sysctl.d/99-redis.conf
sudo sysctl --system
sudo systemctl restart redis-server

راجع سجل الإقلاع مرة أخرى بعد إعادة التشغيل وعالج أي تحذيرات أخرى يطبعها.

الخطوة 7: اتصل من تطبيقك

احفظ كلمة المرور في متغير بيئة، لا في الكود. رابط الاتصال مع مستخدم ACL يبدو هكذا:

redis://app:[email protected]:6379/0

وفي Node.js باستخدام ioredis:

const Redis = require('ioredis');
const redis = new Redis({
  host: '127.0.0.1',
  port: 6379,
  username: 'app',
  password: process.env.REDIS_PASSWORD,
});

إذا كان التطبيق وRedis في مركزي بيانات مختلفين دون شبكة خاصة بينهما، فلا ترسل بيانات Redis دون تشفير. استخدم TLS المدمج في Redis، أو نفق WireGuard، أو قرّب الخادمين من بعضهما.

راقبه باستمرار

اضبط REDISCLI_AUTH على كلمة مرور المستخدم admin أولًا، ثم نفّذ:

redis-cli --user admin INFO memory
redis-cli --user admin INFO persistence
redis-cli --user admin SLOWLOG GET 10
redis-cli --user admin --latency

راقب used_memory_human مقارنة بالسقف، وevicted_keys في نسخة التخزين المؤقت، وrdb_last_bgsave_status أو aof_last_write_status في النسخة التي تحفظ البيانات. ارتفاع evicted_keys في نسخة التخزين المؤقت أمر طبيعي، أما في نسخة الطوابير فيجب أن يبقى صفرًا دائمًا.

شغّله على IM HOST

يحتاج Redis إلى ذاكرة يمكنك الاعتماد عليها. تبدأ خطط Linux VPS من 5 دولارات شهريًا مع صلاحيات root كاملة على KVM، فتتحكم في redis.conf وإعدادات النواة والجدار الناري. وتمنحك خطط Cloud VPS معالجًا وذاكرة مخصصين بدءًا من 16 دولارًا شهريًا، مع إمكانية الترقية في أي وقت مع نمو بياناتك. وللبيانات الكبيرة في الذاكرة، توفر خوادم AMD المخصصة أجهزة فعلية بذاكرة ECC وأقراص NVMe. مهندسونا متاحون على مدار الساعة، ولا توجد رسوم إعداد.

المزيد من مدونتنا

اكتشف المزيد من الأدلة العملية ورؤى الخدمات من فريق IM Host.

عرض كل المقالات