ما الذي سنبنيه؟
في هذا المقال سنبني بنية تحتية كاملة تعمل على VPS واحد باستخدام Docker Compose. هذه البنية تتضمن 6 خدمات متكاملة تعمل معاً بسلاسة:
Traefik — بروكسي عكسي يدير كل حركة المرور ويوفر شهادات SSL تلقائية من Let's Encrypt.
n8n — منصة أتمتة مفتوحة المصدر لبناء سير عمل بدون كود.
PostgreSQL — قاعدة بيانات n8n.
Redis — طابور المهام لتشغيل n8n في وضع الـ queue.
n8n Worker — عامل منفصل لتنفيذ المهام المُجدولة.
Landing Page — صفحة هبوط بسيطة تُقدَّم عبر Nginx.
FastMCP — خادم MCP بسيط يوفر أدوات حسابية يمكن لـ Claude استخدامها.
المتطلبات الأساسية
قبل البدء تحتاج إلى: خادم VPS يعمل بنظام Ubuntu 22+ مع ذاكرة 4GB على الأقل، واسم نطاق (domain) مُوجَّه إلى IP الخادم، وتثبيت Docker و Docker Compose على الخادم. إذا لم يكن لديك VPS بعد، ننصحك بـ Hostinger — أسعار ممتازة وأداء موثوق - يمكنك الحصول على خصم خاص بمنصتنا من خلال الرابط في البطاقة التالية:
Hostinger
✨ استخدم هذا الرابط للحصول على خصم يبلغ 20% عند إتمام عملية الشراء.
رابط إحالة (قد نربح عمولة عند الشراء)
هيكل المشروع
هذا هو الهيكل الذي سنبنيه على الخادم:
project/
├── docker-compose.yml
├── .env
├── landing/
│ └── index.html
└── mcp/
├── Dockerfile
└── server.py
الخطوة 1: ملف المتغيرات البيئية (.env)
أنشئ ملف
.env
في المجلد الرئيسي للمشروع. هذا الملف يحتوي على جميع الإعدادات الحساسة مثل كلمات المرور وأسماء النطاقات. تأكد من تغيير جميع القيم الافتراضية قبل الاستخدام في الإنتاج!
# ============================================
# 🔐 Environment Variables — Docker Compose
# ============================================
# --- Domain & SSL ---
DOMAIN_NAME=example.com
SUBDOMAIN=n8n
[email protected]
# --- PostgreSQL Database ---
DB_NAME=n8n_db
DB_USER=n8n_user
DB_PASSWORD=SuperSecretP@ssw0rd!2026
# --- Redis ---
REDIS_PASSWORD=R3d1s_S3cur3_K3y!xyz
# --- n8n ---
N8N_ENCRYPTION_KEY=a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
GENERIC_TIMEZONE=Asia/Amman
ملاحظة مهمة: استبدل
example.com
باسم نطاقك الحقيقي، وغيّر جميع كلمات المرور إلى قيم قوية وفريدة. يمكنك توليد مفتاح التشفير بالأمر:
openssl rand -hex 16
الخطوة 2: خادم FastMCP للعمليات الحسابية
سنبدأ ببناء أبسط جزء — خادم MCP يوفر أدوات حسابية بسيطة. هذا الخادم يعمل ببروتوكول Model Context Protocol (MCP) مما يتيح لنماذج الذكاء الاصطناعي مثل Claude استخدامه كأداة خارجية.
أنشئ الملف
mcp/server.py
:
"""
FastMCP Math Server — خادم MCP بسيط للعمليات الحسابية
يعمل مع Claude عبر بروتوكول MCP (Model Context Protocol)
"""
from fastmcp import FastMCP
import math
mcp = FastMCP(
"Math Tools",
description="أدوات حسابية بسيطة عبر بروتوكول MCP",
)
@mcp.tool()
def add(a: float, b: float) -> float:
"""جمع رقمين — Add two numbers together."""
return a + b
@mcp.tool()
def subtract(a: float, b: float) -> float:
"""طرح رقم من آخر — Subtract b from a."""
return a - b
@mcp.tool()
def multiply(a: float, b: float) -> float:
"""ضرب رقمين — Multiply two numbers."""
return a * b
@mcp.tool()
def divide(a: float, b: float) -> float:
"""قسمة رقم على آخر — Divide a by b."""
if b == 0:
raise ValueError("لا يمكن القسمة على صفر!")
return a / b
@mcp.tool()
def square_root(n: float) -> float:
"""حساب الجذر التربيعي — Calculate the square root."""
if n < 0:
raise ValueError("لا يمكن حساب الجذر التربيعي لعدد سالب!")
return math.sqrt(n)
@mcp.tool()
def power(base: float, exponent: float) -> float:
"""رفع رقم لأس معين — Raise base to the power of exponent."""
return math.pow(base, exponent)
if __name__ == "__main__":
mcp.run(transport="sse", host="0.0.0.0", port=8000)
النقاط الأساسية في هذا الكود: نستخدم مكتبة
fastmcp
لإنشاء خادم MCP بأقل كود ممكن. كل دالة مُزينة بـ
@mcp.tool()
تصبح أداة متاحة لنماذج AI. الخادم يعمل على المنفذ 8000 باستخدام بروتوكول SSE (Server-Sent Events).
الخطوة 3: ملف Dockerfile لخادم MCP
أنشئ الملف
mcp/Dockerfile
:
FROM python:3.12-slim
WORKDIR /app
RUN pip install --no-cache-dir fastmcp
COPY server.py .
EXPOSE 8000
CMD ["python", "server.py"]
ملف Dockerfile بسيط جداً: نبدأ من صورة Python 3.12 المصغرة، نثبت مكتبة
fastmcp
، ننسخ الكود، ونشغل الخادم.
الخطوة 4: صفحة الهبوط (Landing Page)
أنشئ الملف
landing/index.html
. هذه صفحة بسيطة وأنيقة تُعرض على النطاق الرئيسي:
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>شبّك — منصة الأتمتة الذكية</title>
<link href="https://fonts.googleapis.com/css2?family=Tajawal:wght@400;700;900&display=swap" rel="stylesheet">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Tajawal', sans-serif;
background: #0a0e17;
color: #e2e8f0;
min-height: 100vh;
}
.hero {
min-height: 100vh;
display: flex; flex-direction: column;
align-items: center; justify-content: center;
text-align: center; padding: 2rem;
}
.logo {
font-size: 4rem; font-weight: 900;
background: linear-gradient(135deg, #00A8A8, #FFB703);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 1rem;
}
.tagline { font-size: 1.4rem; color: #94a3b8; max-width: 500px; line-height: 1.8; }
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
gap: 1.5rem; max-width: 900px; width: 100%;
margin-top: 3rem;
}
.card {
background: rgba(255,255,255,0.03);
border: 1px solid rgba(255,255,255,0.06);
border-radius: 16px; padding: 2rem;
transition: transform 0.3s, border-color 0.3s;
}
.card:hover { transform: translateY(-4px); border-color: #00A8A8; }
.card h3 { font-size: 1.2rem; color: #00A8A8; margin-bottom: 0.5rem; }
.card p { color: #64748b; font-size: 0.95rem; line-height: 1.6; }
</style>
</head>
<body>
<section class="hero">
<div class="logo">شبّك</div>
<p class="tagline">منصة أتمتة ذكية تجمع بين n8n و FastMCP و Traefik.</p>
<div class="cards">
<div class="card">
<h3>⚡ n8n</h3>
<p>أتمتة سير العمل بدون كود مع دعم لمئات التطبيقات.</p>
</div>
<div class="card">
<h3>🧠 FastMCP</h3>
<p>خادم MCP بسيط يوفر أدوات حسابية لـ Claude.</p>
</div>
<div class="card">
<h3>🔒 Traefik</h3>
<p>بروكسي عكسي مع شهادات SSL تلقائية.</p>
</div>
</div>
</section>
</body>
</html>
الخطوة 5: ملف Docker Compose الكامل
هذا هو قلب المشروع — ملف
docker-compose.yml
الذي يربط جميع الخدمات معاً. كل خدمة تعمل في حاوية منفصلة وTraefik يوزع حركة المرور بناءً على اسم النطاق:
version: "3.9"
services:
# 🔹 Reverse Proxy with Traefik
traefik:
image: "traefik"
container_name: traefik
restart: always
command:
- "--api=true"
- "--api.insecure=true"
- "--log.level=DEBUG"
- "--accesslog=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
- "--entrypoints.web.http.redirections.entryPoint.to=websecure"
- "--entrypoints.web.http.redirections.entryPoint.scheme=https"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.mytlschallenge.acme.httpchallenge=true"
- "--certificatesresolvers.mytlschallenge.acme.httpchallenge.entrypoint=web"
- "--certificatesresolvers.mytlschallenge.acme.email=${SSL_EMAIL}"
- "--certificatesresolvers.mytlschallenge.acme.storage=/letsencrypt/acme.json"
ports:
- "80:80"
- "443:443"
volumes:
- traefik_data:/letsencrypt
- /var/run/docker.sock:/var/run/docker.sock:ro
# 🔹 n8n Main Application
n8n:
image: docker.n8n.io/n8nio/n8n:next
container_name: n8n
restart: always
ports:
- "127.0.0.1:5678:5678"
labels:
- "traefik.enable=true"
- "traefik.http.routers.n8n.rule=Host(`${SUBDOMAIN}.${DOMAIN_NAME}`)"
- "traefik.http.routers.n8n.tls=true"
- "traefik.http.routers.n8n.entrypoints=web,websecure"
- "traefik.http.routers.n8n.tls.certresolver=mytlschallenge"
- "traefik.http.middlewares.n8n.headers.SSLRedirect=true"
- "traefik.http.middlewares.n8n.headers.STSSeconds=315360000"
- "traefik.http.middlewares.n8n.headers.browserXSSFilter=true"
- "traefik.http.middlewares.n8n.headers.contentTypeNosniff=true"
- "traefik.http.middlewares.n8n.headers.forceSTSHeader=true"
- "traefik.http.middlewares.n8n.headers.STSIncludeSubdomains=true"
- "traefik.http.middlewares.n8n.headers.STSPreload=true"
- "traefik.http.routers.n8n.middlewares=n8n@docker"
environment:
- N8N_HOST=${SUBDOMAIN}.${DOMAIN_NAME}
- N8N_PORT=5678
- N8N_PROTOCOL=https
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=${DB_NAME}
- DB_POSTGRESDB_USER=${DB_USER}
- DB_POSTGRESDB_PASSWORD=${DB_PASSWORD}
- NODE_ENV=production
- WEBHOOK_URL=https://${SUBDOMAIN}.${DOMAIN_NAME}/
- GENERIC_TIMEZONE=${GENERIC_TIMEZONE}
- N8N_PROXY_HOPS=1
- N8N_RUNNERS_ENABLED=true
- EXECUTIONS_MODE=queue
- QUEUE_BULL_REDIS_HOST=redis
- QUEUE_BULL_REDIS_PORT=6379
- QUEUE_BULL_REDIS_PASSWORD=${REDIS_PASSWORD}
- OFFLOAD_MANUAL_EXECUTIONS_TO_WORKERS=true
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
depends_on:
- redis
- postgres
volumes:
- n8n_data:/home/node/.n8n
- /local-files:/files
# 🔹 Redis (Job Queue)
redis:
image: redis:6
container_name: redis
restart: always
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- redis_data:/data
# 🔹 PostgreSQL Database
postgres:
image: postgres:15
container_name: n8n-postgres
restart: always
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_NAME}
volumes:
- pgdata:/var/lib/postgresql/data
# 🔹 n8n Worker
n8n-worker:
image: n8nio/n8n
container_name: n8n-worker
restart: always
command: worker
depends_on:
- redis
- postgres
environment:
- EXECUTIONS_MODE=queue
- QUEUE_BULL_REDIS_HOST=redis
- QUEUE_BULL_REDIS_PORT=6379
- QUEUE_BULL_REDIS_PASSWORD=${REDIS_PASSWORD}
- DB_TYPE=postgresdb
- DB_POSTGRESDB_HOST=postgres
- DB_POSTGRESDB_PORT=5432
- DB_POSTGRESDB_DATABASE=${DB_NAME}
- DB_POSTGRESDB_USER=${DB_USER}
- DB_POSTGRESDB_PASSWORD=${DB_PASSWORD}
- N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
# 🔹 Static Landing Page
landing:
image: nginx:alpine
container_name: landing
restart: always
volumes:
- ./landing:/usr/share/nginx/html:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.landing.rule=Host(`${DOMAIN_NAME}`) || Host(`www.${DOMAIN_NAME}`)"
- "traefik.http.routers.landing.entrypoints=web,websecure"
- "traefik.http.routers.landing.tls=true"
- "traefik.http.routers.landing.tls.certresolver=mytlschallenge"
- "traefik.http.services.landing.loadbalancer.server.port=80"
# 🔹 FastMCP Server
mcp:
build:
context: ./mcp
dockerfile: Dockerfile
container_name: fastmcp
restart: always
expose:
- "8000"
labels:
- "traefik.enable=true"
- "traefik.http.routers.mcp.rule=Host(`mcp.${DOMAIN_NAME}`)"
- "traefik.http.routers.mcp.entrypoints=web,websecure"
- "traefik.http.routers.mcp.tls=true"
- "traefik.http.routers.mcp.tls.certresolver=mytlschallenge"
- "traefik.http.services.mcp.loadbalancer.server.port=8000"
- "traefik.http.middlewares.mcp-cors.headers.accesscontrolallowmethods=GET,POST,OPTIONS"
- "traefik.http.middlewares.mcp-cors.headers.accesscontrolalloworiginlist=https://claude.ai,https://api.claude.ai"
- "traefik.http.middlewares.mcp-cors.headers.accesscontrolallowheaders=*"
- "traefik.http.middlewares.mcp-cors.headers.accesscontrolmaxage=100"
- "traefik.http.routers.mcp.middlewares=mcp-cors@docker"
environment:
- PYTHONUNBUFFERED=1
- LOG_LEVEL=INFO
# 🔸 Volumes
volumes:
traefik_data:
n8n_data:
pgdata:
redis_data:
شرح البنية: كيف تعمل الخدمات معاً؟
دعونا نفهم كيف تتواصل هذه الخدمات:
Traefik يستمع على المنفذين 80 و 443 ويوزع الطلبات حسب اسم النطاق. فعندما يصل طلب إلى
example.com
يذهب لصفحة الهبوط، و
n8n.example.com
يذهب لـ n8n، و
mcp.example.com
يذهب لخادم FastMCP. كل ذلك مع شهادات SSL تلقائية.
n8n يتصل بـ PostgreSQL لتخزين البيانات وبـ Redis لإدارة طابور المهام. العامل (Worker) يقرأ المهام من Redis وينفذها بشكل مستقل، مما يحسن الأداء عند وجود أتمتات ثقيلة.
FastMCP يعمل كخادم مستقل يقدم أدوات عبر بروتوكول SSE. إعدادات CORS تسمح لـ Claude.ai بالاتصال مباشرة.
الخطوة 6: التشغيل والاختبار
بعد إنشاء جميع الملفات، شغّل المشروع بالأوامر التالية:
# بناء صورة FastMCP
docker compose build mcp
# تشغيل جميع الخدمات
docker compose up -d
# التحقق من حالة الخدمات
docker compose ps
# مشاهدة السجلات
docker compose logs -f
بعد التشغيل، تحقق من عمل الخدمات بزيارة:
https://example.com
لصفحة الهبوط،
https://n8n.example.com
لواجهة n8n، و
https://mcp.example.com/sse
لخادم MCP.
ربط FastMCP مع Claude
بعد تشغيل الخادم، يمكنك ربطه مع Claude عبر إعدادات MCP. اذهب إلى إعدادات Claude واختر إضافة خادم MCP جديد، ثم أدخل العنوان:
https://mcp.example.com/sse
بعد الربط، يمكن لـ Claude استخدام الأدوات الحسابية مباشرة. جرّب أن تطلب منه: "احسب لي الجذر التربيعي لـ 144" أو "اجمع 3.14 مع 2.71" وسيستخدم خادم MCP الخاص بك للإجابة!
نصائح للإنتاج
قبل نشر هذه البنية في بيئة إنتاج حقيقية، تأكد من: تغيير جميع كلمات المرور في ملف
.env
إلى قيم قوية وفريدة، وإعداد نسخ احتياطي دوري لقاعدة بيانات PostgreSQL، ومراقبة استخدام الموارد خاصة الذاكرة، وتقييد الوصول إلى Traefik Dashboard في الإنتاج بحذف
--api.insecure=true
.
إذا كنت تبحث عن VPS موثوق بأداء ممتاز لتشغيل هذه البنية:
Hostinger
✨ استخدم هذا الرابط للحصول على خصم يبلغ 20% عند إتمام عملية الشراء.
رابط إحالة (قد نربح عمولة عند الشراء)
الخلاصة
في هذا المقال بنينا بنية تحتية كاملة من 7 خدمات تعمل على VPS واحد باستخدام Docker Compose. الجميل في هذا النهج أنه قابل للتوسع — يمكنك إضافة خدمات جديدة بسهولة بمجرد إضافة تعريف جديد في ملف docker-compose.yml مع labels الخاصة بـ Traefik.
خادم FastMCP يفتح لك باباً واسعاً لبناء أدوات مخصصة يمكن لنماذج AI استخدامها. يمكنك توسيعه ليشمل الوصول إلى قواعد بيانات أو APIs خارجية أو أي منطق أعمال تريده.
ملفات مشروع بناء منظومة متكاملة من n8n و صفحة هبوط و خادم mcp
all_n8n_-_files.zip