الأمن السيبراني الأدلة التقنية

Authelia: دخول موحد SSO ومصادقة ثنائية 2FA أمام تطبيقاتك

نضع Authelia خلف Caddy أمام تطبيقين، فيدخل الفريق بكلمة المرور ولا يصل إلى لوحة الإدارة إلا من أضاف رمز TOTP.

Authelia: دخول موحد SSO ومصادقة ثنائية 2FA أمام تطبيقاتك

لنفرض أن لديك على سيرفر واحد أداة داخلية يستخدمها الفريق كل يوم، ولوحة إدارة لا يجب أن يفتحها إلا شخصان، وكلتاهما بلا نظام دخول جيد، فالأولى بلا حسابات أصلاً، والثانية بكلمة مرور واحدة يعرفها الجميع. وفي دليل كل الطرق لحماية صفحة أو أداة داخلية رأينا أن أفضل درجة لهذه الحالة هي Proxy يعرف هوية المستخدم عبر Forward Auth، وجربنا ذلك هناك مع Authelia بقاعدة واحدة وعامل واحد. وفي هذا الدليل سوف نكمل الطريق: نثبت Authelia كما يثبت في بيئة الإنتاج Production، ونضع خلفه تطبيقين بسياستين مختلفتين، ونفرض على لوحة الإدارة المصادقة الثنائية 2FA برمز TOTP.

وفي هذا المقال سوف نتناول:

  • ما هو Authelia، وما الذي يميزه عن مزودات الهوية الكبيرة، ومتى لا يناسبك.
  • تثبيته مع Redis وCaddy باستخدام Docker Compose، والأسرار Secrets في ملفات منفصلة.
  • قواعد الوصول Access Control: عامل واحد للفريق، وعاملان للإدارة، والرفض لكل ما عدا ذلك.
  • تسجيل جهاز TOTP خطوة خطوة، ولماذا يطلب Authelia رمزاً يصل بالبريد قبل ذلك.
  • الحماية من التخمين Regulation، والجلسات Sessions بعد إعادة التشغيل، والعربية في الواجهة.
  • الموارد المقيسة، والنسخ الاحتياطي والاستعادة، والتحديث، والمشكلات الشائعة.

وإذا كنت تقارن بين الأدوات فهذه الأدلة تشرح البدائل والمفاهيم التي نبني عليها:

دليلكل الطرق لحماية صفحة أو أداة داخليةمن إخفاء الأداة عن الإنترنت إلى تسجيل الدخول داخلها، متى تكفي كل طريقة، وأين تفشل، وكيف تجمع بينها.دليلكيف تحمي أي تطبيق ويب بصفحة دخول authentik عبر Forward Authكيف تضع صفحة دخول authentik مع المصادقة الثنائية أمام أي أداة داخلية دون أن تعدل في التطبيق نفسه.دليلتثبيت Keycloak مزود الهوية IdP الأشهر في المؤسساتنثبت Keycloak مع PostgreSQL، ونربط به تطبيقاً عبر OIDC، ونفرض المصادقة الثنائية على الجميع، ونقيس ما يحتاجه من ذاكرة.دليلالدخول دون كلمة مرور: شرح Passkeys وWebAuthnلماذا لا تحميك رموز SMS وTOTP من التصيد الحديث، وكيف تحل Passkeys المشكلة بمفتاح خاص لا يغادر جهازك.

ما هو Authelia؟

Authelia خادم مصادقة Authentication Server مكتوب بلغة Go، برخصة Apache 2.0، ويعمل في Container واحد حجم الـ Image فيه 110 MB. ووظيفته الأساسية أن يجيب الـ Reverse Proxy عن سؤال واحد في كل طلب: هل يسمح لهذا الطلب بالمرور أم لا؟ فإذا كانت للمتصفح جلسة صالحة وتسمح القواعد بالطلب مرره الـ Proxy إلى التطبيق ومعه اسم المستخدم ومجموعاته في ترويسات Headers، وإلا حوله إلى بوابة الدخول، وهذا ما يسمى Forward Auth. ويستطيع Authelia أيضاً أن يعمل مزود OpenID Connect للتطبيقات التي تدعمه، ولكن قوته الحقيقية في الحماية عبر الـ Proxy.

والفرق بينه وبين authentik أو Keycloak أنه لا يملك لوحة إدارة للمستخدمين، فالمستخدمون في ملف YAML أو في LDAP، والقواعد في ملف إعداد، وكل تعديل يمر عبر ملف تحفظه في Git. وهذا مناسب جداً لمن يدير سيرفراته بالملفات، وغير مناسب إطلاقاً لمؤسسة تريد أن يضيف موظف الموارد البشرية الحسابات من المتصفح.

والمشروع نشط، فقد صدر منه 13 إصداراً في 2026 حتى الآن، وآخرها 4.39.28 في 17 سبتمبر 2026، ونشر في صفحة التنبيهات الأمنية ثلاثة تنبيهات في 2026 درجتها منخفضة ومتوسطة، آخرها في مايو عن قاعدة وصول قد لا تطابق النطاق في حالة حدية لأن الاسم لم يوحد Canonicalization.

والشكل التالي يبين ما يحدث في كل طلب إلى تطبيق محمي، والقواعد التي سوف نكتبها:

المتصفح يطلب التطبيق من Caddy، فيسأل Caddy خدمة Authelia أولاً، ويرد Authelia بالسماح مع ترويسات Remote أو بالتحويل إلى بوابة الدخول أو بالرفض 403، وجدول قواعد الوصول
Caddy يسأل Authelia عن كل طلب، والقواعد تحدد عدد العوامل المطلوبة لكل تطبيق

المتطلبات

  • سيرفر Linux صغير يكفي، فقد استهلك Authelia في حالة الخمول بين 60 و99 MiB من الذاكرة RAM، ووصل إلى 232 MiB بعد سلسلة من عمليات الدخول، والسبب أن هاش كلمات المرور argon2id يحجز 64 MiB في كل عملية تحقق، وأما Redis فاستهلك 6 MiB وCaddy أقل من 26 MiB.
  • نطاق رئيسي Root Domain مثل example.com تكون كل التطبيقات المحمية تحته، والسبب أن كوكي Cookie الجلسة يكتب على هذا النطاق حتى يراه كل تطبيق، وبالتالي لا يستطيع Authelia حماية تطبيقين على نطاقين مختلفين بنفس الجلسة.
  • بوابة الدخول على HTTPS دائماً، حيث يرفض Authelia أن يكون authelia_url بـ HTTP.
  • حساب SMTP، وهو هنا إلزامي فعلياً، والسبب أن Authelia يرسل رمزاً بالبريد قبل أن يسمح للمستخدم بتسجيل جهاز المصادقة، كما سيأتي.

وفي المختبر استخدمنا أسماء تحت lab.localhost، لأن المتصفحات توجه أي اسم ينتهي بـ .localhost إلى الجهاز نفسه، فلا نحتاج إلى DNS، واستخدمنا شهادة داخلية من Caddy عبر tls internal على المنفذ 18818.

التثبيت

الأسرار في ملفات منفصلة

يحتاج Authelia إلى ثلاثة أسرار: مفتاح الجلسات، ومفتاح تشفير قاعدة البيانات Storage Encryption Key الذي تشفر به أسرار TOTP، ومفتاح روابط استعادة كلمة المرور. ولا تكتبها في ملف الإعداد، وإنما في ملفات تقرؤها الحاوية عبر متغيرات تنتهي بـ _FILE، والسبب أن ملف الإعداد سوف تحفظه في Git وتشاركه، أما الأسرار فلا:

sudo mkdir -p /opt/authelia/{config,secrets}
cd /opt/authelia
for f in session_secret storage_encryption_key jwt_secret; do openssl rand -hex 32 > secrets/$f; done
chmod 600 secrets/*
🛑
من يملك ملف قاعدة البيانات ومفتاح storage_encryption_key يستطيع أن يستخرج أسرار TOTP لكل المستخدمين بأمر واحد هو authelia storage user totp export uri، وقد فعلنا ذلك على نسخة احتياطية مستعادة فظهر رابط otpauth:// كاملاً. لذلك احفظ المفتاح بعيداً عن النسخة الاحتياطية لقاعدة البيانات، وإذا فقدته فلن تفتح النسخة وسوف يعيد كل المستخدمين تسجيل أجهزتهم.

ملف المستخدمين وهاش كلمات المرور

نولد هاش كلمة المرور بأداة Authelia نفسها، وهي تستخدم argon2id افتراضياً:

docker run --rm authelia/authelia:4.39.28 authelia crypto hash generate argon2 --password 'كلمة-مرور-قوية'
Digest: $argon2id$v=19$m=65536,t=3,p=4$...

ثم نضع الهاش في config/users.yml، وفيه مستخدمان: alice في مجموعتي admins وdev، وbob في dev فقط:

users:
  alice:
    displayname: 'Alice Admin'
    password: '$argon2id$v=19$m=65536,t=3,p=4$...'
    email: '[email protected]'
    groups: ['admins', 'dev']
  bob:
    displayname: 'Bob Dev'
    password: '$argon2id$v=19$m=65536,t=3,p=4$...'
    email: '[email protected]'
    groups: ['dev']

ولاحظ أن القيم m=65536,t=3,p=4 تعني 64 MiB من الذاكرة وثلاث دورات وأربعة خيوط Threads لكل عملية تحقق، وهذا مقصود حتى يكون تخمين كلمات المرور مكلفاً على المخترق، ولكنه مكلف عليك أيضاً، فعلى سيرفر مشغول بأعمال أخرى وصل زمن الدخول الواحد إلى عدة ثوان في تجربتنا، لذلك لا تضع Authelia على سيرفر معالجه مشغول دائماً.

ملف الإعداد configuration.yml

server:
  address: 'tcp://:9091/'
log:
  level: 'info'
totp:
  issuer: 'example.com'
authentication_backend:
  file:
    path: '/config/users.yml'
access_control:
  default_policy: 'deny'
  rules:
    - domain: 'admin.lab.localhost'
      subject: 'group:admins'
      policy: 'two_factor'
    - domain: 'app.lab.localhost'
      subject:
        - 'group:dev'
        - 'group:admins'
      policy: 'one_factor'
session:
  redis:
    host: 'redis'
    port: 6379
  cookies:
    - domain: 'lab.localhost'
      authelia_url: 'https://auth.lab.localhost:18818'
      default_redirection_url: 'https://app.lab.localhost:18818'
regulation:
  max_retries: 3
  find_time: '2 minutes'
  ban_time: '5 minutes'
storage:
  local:
    path: '/data/db.sqlite3'
notifier:
  filesystem:
    filename: '/data/notification.txt'

في الإعداد أعلاه لاحظ التالي:

  • default_policy: 'deny' يرفض كل ما لم تذكره القواعد، وهذا هو الإعداد الصحيح الوحيد، والسبب أنك عندما تضيف تطبيقاً جديداً خلف الـ Proxy وتنسى قاعدته فسوف يرفض بدل أن يفتح للجميع. والقواعد تقرأ من الأعلى، وأول قاعدة تطابق الطلب هي التي تطبق.
  • two_factor على لوحة الإدارة وone_factor على أداة الفريق، فلا تزعج الجميع برمز TOTP في كل مرة، وإنما تطلبه حيث يكون الضرر كبيراً.
  • session.redis يحفظ الجلسات في Redis بدل ذاكرة Authelia، والتفصيل في قسم الجلسات.
  • notifier.filesystem يكتب الرسائل في ملف بدل البريد، وهو للتجربة فقط، وفي بيئة الإنتاج تستخدم SMTP كما في القسم الخاص به.
  • التخزين في SQLite يكفي لنسخة واحدة من Authelia، فإذا أردت أكثر من نسخة فانتقل إلى PostgreSQL.

ملف docker-compose.yml

services:
  authelia:
    image: authelia/authelia:4.39.28
    restart: unless-stopped
    environment:
      AUTHELIA_SESSION_SECRET_FILE: /secrets/session_secret
      AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE: /secrets/storage_encryption_key
      AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE: /secrets/jwt_secret
    volumes:
      - ./config:/config
      - ./secrets:/secrets:ro
      - data:/data
  redis:
    image: redis:8.2.2-alpine
    restart: unless-stopped
    command: redis-server --save 60 1
    volumes:
      - redis:/data
  caddy:
    image: caddy:2.10.2-alpine
    restart: unless-stopped
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
    ports:
      - "127.0.0.1:18818:443"
  whoami:
    image: node:22.23.4-alpine
    restart: unless-stopped
    command: node /app/server.js
    volumes:
      - ./whoami:/app:ro
volumes:
  redis:
  data:
  caddy_data:

ولاحظ أن Authelia لا ينشر أي منفذ، فلا يصل إليه أحد إلا عبر Caddy، وأن الـ Image الرسمية فيها فحص صحة Health Check جاهز، فتظهر الخدمة بحالة healthy دون أن تضيفه. والخدمة whoami تطبيق صغير بـ Node.js يطبع الترويسات التي تصله، حتى نرى ما يعطيه Authelia للتطبيق:

// Echoes the request line and the Remote-* headers that the proxy adds after Authelia allows the request.
require('node:http').createServer((req, res) => {
  const h = Object.fromEntries(Object.entries(req.headers).filter(([k]) => k.startsWith('remote-')));
  res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' });
  res.end(`${req.method} ${req.headers.host}${req.url}\n` + Object.entries(h).map(([k, v]) => `${k}: ${v}`).join('\n') + '\n');
}).listen(3000);

ملف Caddyfile

نتبع دليل Authelia لـ Caddy، حيث يمرر Caddy بوابة الدخول كما هي، ويضع أمام التطبيقين الأمر forward_auth:

auth.lab.localhost {
	tls internal
	reverse_proxy authelia:9091
}

app.lab.localhost, admin.lab.localhost {
	tls internal
	forward_auth authelia:9091 {
		uri /api/authz/forward-auth
		copy_headers Remote-User Remote-Groups Remote-Email Remote-Name
	}
	reverse_proxy whoami:3000
}

والأمر copy_headers مهم من ناحية الأمان، والسبب أن Caddy يأخذ هذه الترويسات من رد Authelia ويكتبها فوق أي ترويسة بنفس الاسم أرسلها المتصفح، فلا يستطيع مستخدم أن يرسل Remote-User: alice بنفسه. وفي بيئة الإنتاج تحذف tls internal فيصدر Caddy شهادة حقيقية، وتغير الأسماء إلى نطاقك.

التشغيل

docker compose up -d
docker compose logs authelia
level=info msg="Authelia v4.39.28 is starting"
level=info msg="Storage schema migration from 0 to 29 is being attempted"
level=info msg="Storage schema migration from 0 to 29 is complete"
level=info msg="Startup complete"
level=info msg="Listening for non-TLS connections on '[::]:9091' path '/'" server=main service=server

وكان التشغيل الأول كله في ثلاث ثوان، ومنه إنشاء جداول قاعدة البيانات. والآن نجرب الطلب دون جلسة:

curl -sk -o /dev/null -w '%{http_code} %{redirect_url}\n' https://app.lab.localhost:18818/
302 https://auth.lab.localhost:18818/?rd=https%3A%2F%2Fapp.lab.localhost%3A18818%2F&rm=GET

لم يصل الطلب إلى التطبيق، وإنما حوله Caddy إلى بوابة الدخول ومعه عنوان العودة في المعامل rd.

الفريق: عامل واحد

عند فتح التطبيق في المتصفح ظهرت بوابة الدخول بالعربية، لأن Authelia يختار اللغة من إعدادات المتصفح:

صفحة دخول Authelia بالعربية بحقلي اسم المستخدم وكلمة المرور وزر تسجيل الدخول، مع اتجاه من اليسار إلى اليمين
بوابة الدخول بالعربية، ولاحظ أن الاتجاه بقي من اليسار إلى اليمين

ودخل bob بكلمة مروره فوصل إلى التطبيق، وهذا ما طبعه التطبيق:

GET app.lab.localhost:18818/
remote-email: [email protected]
remote-groups: dev
remote-name: Bob Dev
remote-user: bob

ثم فتح bob لوحة الإدارة بنفس الجلسة فكان الرد 403 Forbidden، والسبب أن القاعدة الأولى تطلب مجموعة admins، ولا تنطبق عليه القاعدة الثانية لأنها لنطاق آخر، فوصل إلى default_policy وهي الرفض، وفي السجل:

level=info msg="Access to 'https://admin.lab.localhost:18818/' is forbidden to user 'bob'" method=GET path=/api/authz/forward-auth

وهذا السطر هو ما تحتاجه عند التدقيق Audit: من حاول الوصول إلى ماذا، ولماذا رفض.

الإدارة: عاملان وتسجيل جهاز TOTP

عندما دخلت alice إلى لوحة الإدارة بكلمة مرورها قبلها Authelia في الخطوة الأولى، ولكنه لم يحولها إلى اللوحة، وكتب في السجل https://admin.lab.localhost:18818/ requires 2FA, cannot be redirected yet، وعرض عليها صفحة العامل الثاني، وفيها رابط لتسجيل أول جهاز لأنها لم تسجل أي جهاز بعد:

صفحة العامل الثاني في Authelia تقول إن المورد يتطلب المصادقة بعاملين مع رابط تسجيل الجهاز
لوحة الإدارة تطلب عاملاً ثانياً، ولا يوجد جهاز مسجل بعد

لماذا يطلب رمزاً بالبريد قبل تسجيل الجهاز؟

عند الضغط على «إضافة» لم يعرض Authelia رمز QR مباشرة، وإنما فتح نافذة «التحقق من الهوية» وأرسل رمزاً من ثمانية أحرف إلى بريد المستخدم. وقد يتساءل البعض: لماذا هذه الخطوة وقد أدخلت كلمة المرور قبل ثوان؟ والإجابة أن كلمة المرور وحدها قد تكون مسروقة، فلو سمح Authelia لمن يعرفها بتسجيل جهازه هو، لصار المخترق صاحب العامل الثاني أيضاً، وبالتالي يطلب Authelia إثباتاً من قناة ثانية هي البريد، وهذا ما يسميه الجلسة المرتفعة Elevated Session.

نافذة التحقق من الهوية في Authelia تطلب الرمز الذي أرسل إلى البريد
رمز لمرة واحدة يصل بالبريد قبل أي تعديل على أجهزة المصادقة

وفي المختبر وصلت الرسالة إلى الملف /data/notification.txt، وهذا جزء منها:

Subject: Confirm your identity
A ONE-TIME CODE HAS BEEN GENERATED TO COMPLETE A REQUESTED ACTION
Hi Alice Admin,
This notification has been sent to you in order to verify your identity to change security details for your account at lab.localhost.
----------------------------------------
WKKT6EHP
----------------------------------------
If you did not initiate the process your credentials may have been compromised and you should:
 1. Revoke this code using the provided links below

وبعد إدخال الرمز ظهر معالج التسجيل بثلاث خطوات: الخيارات (SHA1 وستة أرقام وثلاثون ثانية)، ثم رمز QR، ثم إدخال أول رمز من التطبيق للتأكيد:

معالج تسجيل TOTP في Authelia في الخطوة الثانية مع رمز QR وروابط تطبيق المصادقة
الخطوة الثانية: رمز QR، ولاحظ الترجمة «مؤلف جوجل» لـ Google Authenticator
الخطوة الثالثة في معالج TOTP بستة حقول لإدخال الرمز
الخطوة الثالثة: أول رمز من التطبيق يؤكد أن الجهاز سجل بشكل صحيح

ثم عادت alice إلى صفحة العامل الثاني، فأدخلنا رمزاً خاطئاً عمداً فظهرت رسالة «كلمة المرور لمرة واحدة قد تكون خاطئة»، ثم الرمز الصحيح فوصلت إلى اللوحة:

صفحة إدخال رمز TOTP في Authelia مع رسالة أن الرمز قد يكون خاطئاً
رمز خاطئ في صفحة العامل الثاني
GET admin.lab.localhost:18818/
remote-email: [email protected]
remote-groups: admins,dev
remote-name: Alice Admin
remote-user: alice

ماذا يحدث إذا كرر المستخدم طلب الرمز؟

أثناء التجربة طلبنا رمز التحقق عدة مرات في دقائق قليلة، فظهرت في الواجهة رسالة «Failed to generate the One-Time Code. Please try again»، وفي السجل:

level=warning msg="Rate Limit Exceeded" bucket=1 delay=106.320172943 method=POST path=/api/user/session/elevation

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

الحماية من التخمين Regulation

الإعداد regulation يوقف المستخدم بعد ثلاث محاولات خاطئة خلال دقيقتين لمدة خمس دقائق. وجربنا ذلك بأربع كلمات خاطئة ثم الكلمة الصحيحة:

for p in w1 w2 w3 w4 'كلمة-المرور-الصحيحة'; do
  curl -sk -H 'Content-Type: application/json' \
    -d "{\"username\":\"bob\",\"password\":\"$p\",\"keepMeLoggedIn\":false}" \
    https://auth.lab.localhost:18818/api/firstfactor; echo
done
{"status":"KO","message":"Authentication failed. Check your credentials."}
{"status":"KO","message":"Authentication failed. Check your credentials."}
{"status":"KO","message":"Authentication failed. Check your credentials."}
{"status":"KO","message":"Authentication failed. Check your credentials."}
{"status":"KO","message":"Authentication failed. Check your credentials."}

الرد الخامس، وهو بكلمة المرور الصحيحة، مثل الردود السابقة تماماً، فلا يعرف المهاجم أن الحساب توقف، أما السجل فيقول الحقيقة:

level=error msg="Unsuccessful 1FA authentication attempt by user 'bob'"
level=error msg="Unsuccessful 1FA authentication attempt by user 'bob' and they are banned until 9:27:32PM on October 25 2026 (+00:00)"

وإذا كان الموظف هو من أخطأ فعلاً فترفع الإيقاف من سطر الأوامر:

docker compose exec authelia authelia storage bans user list --config /config/configuration.yml
docker compose exec authelia authelia storage bans user revoke bob --config /config/configuration.yml
ID Username Expires             Source     Reason
1  bob      2026-10-25 21:27:32 regulation Exceeding Maximum Retries
ID Username Result  Information
1  bob      SUCCESS N/A

الجلسات بعد إعادة التشغيل: لماذا Redis؟

بدأنا التجربة دون Redis، فكانت الجلسات في ذاكرة Authelia، ثم سجلنا الدخول بـ curl وأعدنا تشغيل Authelia وطلبنا التطبيق بنفس الكوكي، فتغير الرد من 200 إلى 302، أي أن كل المستخدمين خرجوا. وبعد إضافة Redis كررنا نفس الخطوات فبقي الرد 200 بعد إعادة التشغيل:

{"status":"OK"}
before: 200
after restart: 200

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

العربية في الواجهة

في Authelia ترجمة عربية ar-SA ضمن أكثر من 60 لغة، وتظهر تلقائياً لمن لغة متصفحه العربية، ولكن هناك ثلاث ملاحظات قبل أن تعتمد عليها:

  • الاتجاه بقي من اليسار إلى اليمين LTR، فالنص عربي ولكن الحقول ومربع «تذكر لي» على اليسار.
  • بعض النصوص بقيت بالإنجليزية، مثل «Hi Alice Admin» و«SWITCH USER» و«One-Time Code».
  • بعض الترجمات حرفية، مثل «مؤلف جوجل» بدل Google Authenticator، و«كلمة المرور لمرة واحدة» بدل رمز التحقق.

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

ما يتغير في بيئة الإنتاج

إرسال البريد عبر SMTP

نستبدل قسم notifier بإعداد SMTP، وكلمة المرور في ملف سر مثل بقية الأسرار عبر المتغير AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE:

notifier:
  smtp:
    address: 'submission://smtp.example.com:587'
    username: '[email protected]'
    sender: 'Authelia <[email protected]>'

ولم نرسل بريداً حقيقياً في المختبر، لذلك جرب الإعداد بنفسك، فإذا كان المنفذ محجوباً أو البيانات خاطئة فسوف يرفض Authelia الإقلاع ويكتب السبب في السجل، والسبب أنه يفحص اتصال SMTP عند التشغيل.

النطاقات

نغير في configuration.yml النطاق في الكوكي إلى example.com، وauthelia_url إلى https://auth.example.com، وأسماء القواعد إلى app.example.com وadmin.example.com، وكذلك في Caddyfile مع حذف tls internal. وإذا كبر عدد المستخدمين أو كان في الشركة دليل مستخدمين Directory فانقل authentication_backend من الملف إلى LDAP.

التحقق من النجاح

  • docker compose ps يعرض authelia بحالة healthy.
  • طلب التطبيق دون جلسة يعيد 302 إلى auth.example.com ومعه rd.
  • مستخدم من خارج المجموعات يحصل على 403، ويظهر سطر is forbidden to user في السجل.
  • لوحة الإدارة تطلب رمز TOTP بعد كلمة المرور، ورسالة التحقق تصل إلى البريد.
  • بعد إعادة تشغيل Authelia يبقى المستخدم داخلاً، أي أن Redis يعمل.
  • لا يوجد منفذ منشور لـ Authelia، والطريق الوحيد إليه عبر Caddy.

النسخ الاحتياطي Backup والاستعادة Restore

ما تحتاج إلى نسخه: مجلد config (الإعداد وملف المستخدمين)، ومجلد secrets في مكان منفصل، والـ Volume الذي فيه قاعدة SQLite وأجهزة TOTP وWebAuthn وسجل الدخول. ونوقف Authelia أثناء نسخ قاعدة SQLite حتى لا ننسخها في منتصف كتابة، ونستخدم الـ Image نفسها لأنها تضم الأمر tar:

docker compose stop authelia
docker run --rm --entrypoint sh -v authelia_data:/data:ro -v "$PWD":/backup authelia/authelia:4.39.28 \
  -c 'tar czf /backup/authelia-data.tgz -C /data .'
docker compose start authelia

وكان حجم النسخة 14 KB. وللتأكد أنها تصلح استعدناها في Volume جديد، ثم شغلنا عليها أمر تصدير TOTP مع مفتاح التشفير، فظهر جهاز alice كاملاً، وهذا يثبت أن النسخة ومعها المفتاح كافيتان، وأن النسخة دون المفتاح لا فائدة منها:

otpauth://totp/example.com:alice?algorithm=SHA1&digits=6&issuer=example.com&period=30&secret=...
Successfully exported 1 TOTP configurations as TOTP URI's and printed them to the console

التحديث Upgrade إلى إصدار أحدث

  1. اقرأ ملاحظات الإصدار في GitHub، وخاصة عند الانتقال بين إصدارات فرعية مثل 4.38 إلى 4.39، والسبب أن بعض الإصدارات تغير أسماء خيارات الإعداد، وAuthelia يرفض الإقلاع إذا وجد خياراً قديماً أزيل.
  2. خذ نسخة احتياطية كما في القسم السابق.
  3. غير الوسم في ملف Compose، ثم docker compose pull authelia && docker compose up -d authelia.
  4. تابع السجل حتى Startup complete، وإذا كانت هناك ترحيلات Migrations لقاعدة البيانات فسوف تراها فيه، ثم جرب الدخول بحساب فيه TOTP.

مشكلات شائعة وحلولها

Authelia لا يقلع ويشكو من authelia_url

العنوان يجب أن يبدأ بـ https://، وأن يكون تحت النطاق المكتوب في domain نفسه، فإذا كان الكوكي على example.com والبوابة على login.other.com فلن يقبله.

حلقة تحويل Redirect Loop بين التطبيق والبوابة

الكوكي لا يصل إلى التطبيق، وغالباً لأن التطبيق ليس تحت النطاق المكتوب في session.cookies.domain، أو لأنك تفتحه عبر HTTP، والكوكي مكتوب بالخاصية Secure فلا يرسله المتصفح إلا عبر HTTPS.

403 لمستخدم يجب أن يدخل

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

«Failed to generate the One-Time Code»

إما أن البريد لم يرسل، فتجد الخطأ في السجل، وإما أن المستخدم تجاوز حد الطلبات فتجد Rate Limit Exceeded ومعه عدد ثواني الانتظار.

الدخول بطيء أو يظهر «database is locked»

الهاش argon2id يحتاج إلى معالج وذاكرة، فعلى سيرفر مشغول قد يستغرق الدخول ثوان، وقد ظهر لنا في هذه الحالة خطأ database is locked مرة واحدة من SQLite. فإذا كان السيرفر مشتركاً مع أعمال ثقيلة فخصص لـ Authelia معالجاً كافياً، وإذا كان المستخدمون كثيرين فانقل التخزين إلى PostgreSQL.

كم تدفع لو اخترت خدمة تجارية؟

أقرب خدمة تجارية لما يفعله Authelia هي Cloudflare Access، وبحسب صفحتها بتاريخ 25 أكتوبر 2026 فهي مجانية للفرق الأقل من 50 مستخدماً، ثم 7 دولارات لكل مستخدم شهرياً تدفع سنوياً، وتشترط أن يمر الطلب عبر شبكة Cloudflare. أما Authelia فلا يكلف إلا السيرفر الذي يعمل عليه، ويبقى كل شيء عندك، ولكنك أنت من يحدثه ويراقبه.

الخلاصة

وصلنا لنهاية الموضوع، وأهم ما فيه:

  • Authelia يحمي التطبيقات عبر الـ Reverse Proxy بخدمة واحدة خفيفة استهلكت أقل من 100 MiB في الخمول، ويناسب من يدير سيرفراته بالملفات، ولا يناسب من يحتاج إلى لوحة إدارة للمستخدمين.
  • ابدأ بـ default_policy: 'deny'، واطلب two_factor حيث يكون الضرر كبيراً فقط.
  • تسجيل جهاز TOTP يحتاج إلى رمز يصل بالبريد، لذلك فإعداد SMTP شرط للإنتاج وليس إضافة.
  • أضف Redis حتى لا يخرج الجميع مع كل إعادة تشغيل، واحفظ مفتاح التشفير بعيداً عن نسخة قاعدة البيانات.
  • الترجمة العربية موجودة ولكن الاتجاه LTR وبعض النصوص إنجليزية، فراجعها قبل عرضها على الموظفين.

وفي مقالات قادمة بإذن الله سوف نقارن Authelia مع authentik وKeycloak وZITADEL، ونشرح متى تختار كل واحد منها.

سجل التحديثات

  • أكتوبر 2026: كتابة الدليل واختباره على Authelia 4.39.28 مع Caddy 2.10.2 وRedis 8.2.2.
نشرة عرب رووت | ArabRoot

معرفة تستحق مكاناً في بريدك.

مقالات مختارة وأدوات مفيدة وأفكار لمشروعك القادم، في رسالة واحدة كل أسبوع.

يمكنك إلغاء الاشتراك متى شئت. الخصوصية

تم استلام طلبك. افتح بريدك واضغط رابط التأكيد لإتمام الاشتراك.