SSD Nodes Learn
راهنماها Matt Connorتوسط Matt Connor · به‌روزرسانی شده 2026-07-24

نصب n8n روی VPS با Docker و HTTPS

آموزش نصب n8n با Docker Compose و Postgres. رفع خطاهای تنظیم WEBHOOK_URL و encryption-key برای برقراری اتصال امن HTTPS و پایداری سیستم.

آنچه در حال ساخت آن هستید

n8n یک ابزار اتوماسیون گردش کار است: یک ویرایشگر بصری که در آن یک Trigger — مانند یک Webhook، یک Schedule یا ارسال یک Form — زنجیره‌ای از Nodeها را اجرا می‌کند که APIها را فراخوانی کرده، داده‌ها را تغییر شکل می‌دهند و در سیستم‌های دیگر می‌نویسند. این ابزار به دلیل قابلیت اتصال به تمامی مدل‌ها و پایگاه‌های داده بدون نیاز به نوشتن سرویس، به ابزار اصلی برای گردش کارهای AI-agent تبدیل شده است. یک docker run می‌تواند در عرض 2 دقیقه به یک ویرایشگر آماده دسترسی پیدا کند. این راهنما درباره 90 درصد باقی‌مانده است: پایدار کردن آن با استفاده از Postgres به جای فایل پیش‌فرض SQLite، در دسترس قرار دادن آن از طریق HTTPS، و — بخشی که تقریباً همه در آن اشتباه می‌کنند — تنظیم Webhookها به گونه‌ای که یک URL قابل دسترسی برای دنیای خارج ارائه دهند.

مجموعه نهایی شامل 2 Container در یک Docker network است: خودِ n8n و یک پایگاه داده Postgres که Workflowها و Credentials را نگه می‌دارد. یک Reverse Proxy روی Host، اتصال TLS را برقرار کرده و درخواست‌ها را به n8n در localhost ارسال می‌کند؛ بنابراین هیچ چیزی مستقیماً در معرض اینترنت قرار نمی‌گیرد و همه چیز از طریق آن Proxy عبور می‌کند. این ابزار در کنار سایر سرویس‌ها در لیست کوتاه 2026 برای self-hosting قرار دارد.

پیش‌نیازها و محدودیت‌های واقعی

شما به یک VPS با حداقل 1 GB RAM نیاز دارید؛ زمانی که گردش‌های کاری (workflows) شروع به پردازش‌های سنگین کردند، برای 2 GB برنامه‌ریزی کنید، زیرا فرآیندهای اجرایی به همراه runtime مربوط به Node.js حافظه زیادی مصرف می‌کنند و توقف ناگهانی container توسط out-of-memory killer تجربه ناخوشایندی خواهد بود. برای شروع، یک vCPU کافی است.

شما به یک دامنه یا زیردامنه — مثلاً n8n.example.com — نیاز دارید که دارای یک A record متصل به IP عمومی VPS باشد و قبل از درخواست certificate، به درستی resolve شود. پورت‌های 80 و 443 باید برای proxy باز باشند؛ پورت 5678 مربوط به n8n نباید مستقیماً در معرض اینترنت باشد. شما به Docker Engine و plugin مربوط به Compose نیاز دارید؛ اگر docker compose version با خطای docker: 'compose' is not a docker command مواجه شد، یعنی از نسخه قدیمی standalone binary استفاده می‌کنید و plugin شما sudo apt install docker-compose-plugin است.

SQLite برای تست مناسب است، اما برای موارد حیاتی از Postgres استفاده کنید

دیتابیس پیش‌فرض n8n یک فایل SQLite در مسیر /home/node/.n8n/database.sqlite است. برای تست اولیه و بررسی عملکرد، این گزینه مناسب است؛ اما اگر Volume را mount نکنید، با اولین بازسازی (recreate) کانتینر، تمام داده‌ها از دست می‌روند که خود یک درس مهم است. دلیل مهاجرت به Postgres صرفاً سرعت خام نیست؛ بلکه SQLite تنها یک نویسنده (single writer) را پشتیبانی می‌کند. بنابراین، اگر نمونه‌ای داشته باشید که چندین workflow را همزمان اجرا می‌کند، یا زمانی که به حالت queue mode نیاز پیدا کنید، در شرایط همزمایی (concurrency) با خطای SQLITE_BUSY: database is locked مواجه خواهید شد. Postgres هیچ محدودیتی در این زمینه ندارد، با استفاده از pg_dump به راحتی پشتیبان‌گیری می‌شود و مستندات رسمی n8n نیز برای سرورهای عملیاتی، استفاده از آن را توصیه می‌کنند. تغییر دیتابیس در مراحل بعدی مستلزم مهاجرت دستی داده‌ها است؛ بنابراین اگر این سرور برای شما اهمیت دارد، کار را با Postgres شروع کنید.

DNS and the firewall

ابتدا رکورد را تنظیم و پورت‌ها را باز کنید تا مرحله دریافت گواهینامه (certificate) در آینده، به دلیل عدم شناسایی نام (resolve)، با خطا مواجه نشود.

dig +short n8n.example.com
curl -s ifconfig.me
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw allow OpenSSH
sudo ufw enable

پورت 5678 را باز نکنید. فایل compose، سرویس n8n را به 127.0.0.1:5678 متصل می‌کند؛ بنابراین فقط reverse proxy میزبان می‌تواند به آن دسترسی داشته باشد. باز کردن یک ufw allow 5678 این جداسازی را از بین می‌برد.

فایل Compose

یک دایرکتوری کاری و یک docker-compose.yml ایجاد کنید. این کل پشته (stack) است — شامل دو سرویس، یک شبکه خصوصی و دو volume نام‌گذاری شده.

services:
  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: n8n
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: n8n
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - n8n_net
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U n8n -d n8n"]
      interval: 10s
      timeout: 5s
      retries: 5

  n8n:
    image: docker.n8n.io/n8nio/n8n:2.29.10
    restart: unless-stopped
    ports:
      - "127.0.0.1:5678:5678"
    environment:
      - N8N_HOST=n8n.example.com
      - N8N_PORT=5678
      - N8N_PROTOCOL=https
      - WEBHOOK_URL=https://n8n.example.com/
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - N8N_PROXY_HOPS=1
      - GENERIC_TIMEZONE=Europe/London
      - DB_TYPE=postgresdb
      - DB_POSTGRESDB_HOST=postgres
      - DB_POSTGRESDB_PORT=5432
      - DB_POSTGRESDB_DATABASE=n8n
      - DB_POSTGRESDB_USER=n8n
      - DB_POSTGRESDB_PASSWORD=${POSTGRES_PASSWORD}
    volumes:
      - n8n_data:/home/node/.n8n
    networks:
      - n8n_net
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  postgres_data:
  n8n_data:

networks:
  n8n_net:

چند تصمیم که باید مستقیماً بیان شوند. DB_POSTGRESDB_HOST=postgres نام سرویس است که Docker در شبکه مشترک آن را شناسایی می‌کند — نه localhost که در داخل کانتینر n8n به خودِ n8n اشاره دارد. استفاده از depends_on به همراه condition: service_healthy مانع از رقابت n8n و Postgres هنگام بالا آمدن سیستم می‌شود؛ بدون این تنظیم، n8n اجرا می‌شود، دیتابیس را پیدا نمی‌کند و خارج می‌شود. volume نام‌گذاری شده n8n_data در مسیر /home/node/.n8n، کلید رمزنگاری و در صورت استفاده از SQLite، دیتابیس را نگه می‌دارد — این تنها دایرکتوری است که نباید آن را از دست بدهید. نسخه ایمیج را روی یک نسخه دقیق فیکس کنید و هرگز از latest استفاده نکنید؛ دلایل این کار در بخش upgrade در ادامه آمده است.

فایل secrets

هرگز رمز عبورها را در فایل compose قرار ندهید. آن‌ها را در یک فایل .env در کنار آن قرار دهید تا Compose به‌طور خودکار آن‌ها را بخواند؛ همچنین برای امنیت بیشتر، این رمزها را به‌صورت تصادفی تولید کنید.

printf 'POSTGRES_PASSWORD=%s\n'  "$(openssl rand -hex 24)" >  .env
printf 'N8N_ENCRYPTION_KEY=%s\n' "$(openssl rand -hex 32)" >> .env
chmod 600 .env

رشته N8N_ENCRYPTION_KEY حیاتی‌ترین بخش در اینجا است — این همان کلیدی است که تمام اعتبارنامه‌های ذخیره شده با آن رمزگذاری می‌شوند. به‌جای اینکه اجازه دهید n8n یک کلید بسازد، آن را به‌صورت صریح تنظیم کنید؛ زیرا مقداری که خودتان تولید کرده‌اید را می‌توانید یادداشت و بازیابی کنید. زمانی که n8n اولین اعتبارنامه خود را با این کلید رمزگذاری کرد، تغییر آن باعث می‌شود تمام اعتبارنامه‌ها غیرقابل رمزگشایی شوند — بنابراین، آن را یک‌بار تنظیم کنید و دیگر هرگز به آن خط دست نزنید.

متغیرهای محیطی که عملکرد Webhooks را تعیین می‌کنند

چهار متغیر نحوه معرفی n8n به دنیای خارج را کنترل می‌کنند. تنظیم نادرست این متغیرها، دلیل اصلی اکثر سوالات پشتیبانی n8n است.

  • N8N_HOST همان Hostname عمومی است، یعنی n8n.example.com. اگر در پشت یک Proxy آن را روی مقدار پیش‌فرض localhost رها کنید، Editor سعی می‌کند API خود را از localhost در مرورگر شما بارگذاری کند که با شکست مواجه می‌شود.
  • N8N_PROTOCOL=https به n8n اطلاع می‌دهد که سرویس از طریق TLS ارائه می‌شود؛ بنابراین کوکی نشست (Session Cookie) را با علامت Secure مشخص کرده و URLهای https:// را می‌سازد.
  • N8N_PORT=5678 پورتی است که n8n داخل کانتینر به آن گوش می‌دهد. این پورت، پورت عمومی نیست؛ پورت 443 متعلق به Proxy است.
  • WEBHOOK_URL=https://n8n.example.com/ متغیری است که باعث بروز مشکل می‌شود. n8n آدرس‌های Webhook را که در Stripe، GitHub یا هر فراخوان‌کننده خارجی کپی می‌کنید، با ترکیب این مقادیر می‌سازد. اگر این متغیر تنظیم نشده باشد یا اشتباه باشد، n8n به سراغ N8N_HOST:N8N_PORT می‌رود و آدرس https://n8n.example.com:5678/webhook/... یا بدتر از آن، http://localhost:5678/webhook/... را به شما می‌دهد. این آدرس‌ها بدون هیچ خطایی چاپ می‌شوند، معتبر به نظر می‌رسند، اما از طریق اینترنت قابل دسترسی نیستند؛ بنابراین درخواست‌های فراخوان‌کننده بدون هیچ اثری از دست می‌روند. این متغیر را دقیقاً روی Base URL عمومی همراه با اسلش انتهایی (Trailing Slash) تنظیم کنید، سپس بررسی کنید که نود Webhook، آدرسی بدون پورت را نمایش دهد.

N8N_PROXY_HOPS=1 به سرور Express در n8n می‌گوید که به یک Proxy در مقابل خود اعتماد کند؛ با این کار، محدودیت نرخ (Rate-limiting) و هر قابلیتی که IP کلاینت را می‌خواند، به جای IP پروکسی، آدرس واقعی را مشاهده می‌کنند. یک متغیری که ما آگاهانه در اینجا تنظیم نمی‌کنیم، N8N_RUNNERS_ENABLED است: Task runners (اجراکننده‌های وظیفه) — که منطق Code-node را در یک فرآیند جداگانه و Sandboxed اجرا می‌کنند — از نسخه 1.69 به صورت پیش‌فرض فعال شده‌اند و در سری 2.x که این راهنما بر آن تمرکز دارد، اجباری هستند؛ بنابراین روش قدیمی (Opt-in) منسوخ شده است. اگر آن را تنظیم کنید، n8n فقط یک اعلان (Notice) ثبت می‌کند که از شما می‌خواهد آن را حذف کنید.

First start

docker compose up -d
docker compose ps
docker compose logs -f n8n

یک بوت اولیه موفق با یک خط Editor is now accessible via: و یک خط n8n ready on ..., port 5678 در بالای آن پایان می‌یابد. docker compose ps باید وضعیت Up هر دو کانتینر را نشان دهد، در حالی که postgres با وضعیت (healthy) علامت‌گذاری شده است. اگر n8n در یک حلقه Restarting قرار گرفت، لاگ‌ها را بررسی کنید؛ این مشکل تقریباً همیشه به دلیل اتصال دیتابیس یا مجوزهای volume است که در ادامه بررسی شده است.

TLS با یک reverse proxy

خودِ n8n از پروتکل plain HTTP روی پورت 5678 استفاده می‌کند؛ یک سرویس در لایه جلویی، HTTPS را مدیریت می‌کند. دو انتخاب ساده وجود دارد.

اگر از قبل چندین container را اجرا می‌کنید، n8n را پشت یک Traefik reverse proxy که گواهی‌های TLS را به صورت خودکار صادر می‌کند قرار دهید و از چند label استفاده کنید؛ Traefik درخواست‌ها و تمدید گواهی را برای شما انجام می‌دهد.

اگر این تنها اپلیکیشن روی سرور است، استفاده از یک nginx virtual host با گواهی Let's Encrypt ساده‌تر است. از تنظیمات Certbot و nginx TLS برای Ubuntu 24.04 برای دریافت گواهی استفاده کنید، سپس این server block را اعمال کنید:

server {
    listen 443 ssl;
    server_name n8n.example.com;

    ssl_certificate     /etc/letsencrypt/live/n8n.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/n8n.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:5678;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 3600;
        client_max_body_size 16m;
    }
}

هدرهای Upgrade و Connection "upgrade" اختیاری نیستند. n8n به‌روزرسانی‌های لحظه‌ای اجرا را از طریق WebSocket به editor ارسال می‌کند؛ بدون این دو خط، صفحه ورود بارگذاری شده و سپس با بنر lost-connection متوقف می‌شود. proxy_read_timeout 3600 مانع از قطع شدن اجراهای طولانی‌مدت در محدودیت پیش‌فرض 60 ثانیه‌ای nginx می‌شود. هدر X-Forwarded-Proto $scheme مکمل N8N_PROXY_HOPS=1 است: این هدر به n8n اطلاع می‌دهد که درخواست اصلی HTTPS بوده است، حتی اگر پروکسی از طریق HTTP معمولی به آن متصل شود؛ به این ترتیب n8n اتصال را ناامن تشخیص نداده و کوکی خود را رد نمی‌کند.

اولین گردش کار شما برای شروع عملی

https://n8n.example.com/ را باز کنید، حساب کاربری مالک را بسازید (بخش بعدی) و کوچک‌ترین گردش کار ممکن را برای تست مسیر ایجاد کنید: یک Webhook ورودی، یک فراخوانی HTTP و یک پاسخ خروجی.

  1. یک نود Webhook اضافه کنید. متد را روی POST و مسیر را روی چیزی مانند hello تنظیم کنید. دو URL نمایش داده می‌شود: یک Test URL و یک Production URL؛ ناتوانی در کارکرد Webhook اغلب به دلیل عدم درک تفاوت این دو است. Test URL فقط به یک فراخوانی پاسخ می‌دهد و تنها زمانی فعال است که روی Listen for test event کلیک کرده باشید؛ سپس منقضی می‌شود. Production URL هر زمان که گردش کار در حالت Active باشد، پاسخ می‌دهد.
  2. یک نود HTTP Request بعد از آن اضافه کنید و آن را به یک JSON API عمومی متصل کنید — یک درخواست GET به https://api.github.com/zen یک رشته تک‌خطی برمی‌گرداند که برای تست کافی است.
  3. یک نود Respond to Webhook اضافه کنید و گزینه Respond در نود Webhook را روی "Using Respond to Webhook node" تنظیم کنید تا خروجی نود HTTP به فراخواننده بازگردانده شود.
  4. گردش کار را در بالا سمت راست روی حالت Active قرار دهید و آن را فراخوانی کنید: curl -X POST https://n8n.example.com/webhook/hello. شما باید همان رشته متنی را دریافت کنید — ورودی POST، فراخوانی API و پاسخ خروجی؛ این ساختار، پایه اکثر اتوماسیون‌های واقعی است.

در یک حالت زمان‌بندی شده، نود Webhook با یک Schedule Trigger جایگزین می‌شود و به جای آن، یک endpoint مدل فراخوانی می‌شود — استفاده از Ollama running on the same VPS روشی ساده برای ساخت یک خلاصه‌ساز شبانه است.

مدیریت کاربر، نه basic auth

راهنماهای قدیمی n8n شما را به تنظیم N8N_BASIC_AUTH_ACTIVE=true راهنمایی می‌کنند. این متغیرها در نسخه n8n 1.0 حذف شده‌اند و اکنون هیچ تأثیری ندارند. روش احراز هویت امروزی، owner account است: اولین باری که editor را بارگذاری می‌کنید، n8n شما را مجبور به ساخت یک owner با email-and-password می‌کند؛ این مرحله اجباری است و هیچ حالت anonymous وجود ندارد. بلافاصله پس از اولین اجرا، و قبل از اینکه URL را در اختیار کسی قرار دهید، آن را بسازید: در فاصله زمانی بین docker compose up تا اولین ارسال فرم، instance می‌تواند توسط هر کسی که زودتر به آن دسترسی پیدا کند، تصاحب شود. استفاده از یک لایه reverse-proxy basic-auth به عنوان یک قفل اضافی، اقدامی منطقی است، اما این یک عامل دوم (second factor) است، نه احراز هویت اصلی.

Backups: ابتدا کلید رمزنگاری، سپس پایگاه داده

دو مورد نیاز به پشتیبان‌گیری دارند که قابلیت جایگزینی یکسان ندارند.

N8N_ENCRYPTION_KEY. تمام اطلاعات هویتی که در n8n ذخیره می‌کنید — از جمله API tokens، رمزهای عبور پایگاه داده و OAuth secrets — با این کلید در حالت استراحت (at rest) رمزنگاری می‌شوند. گردش‌های کاری (workflows) در Postgres بدون این کلید بلااستفاده هستند: اگر پایگاه داده را روی سرور جدیدی با کلیدی متفاوت بازیابی کنید، n8n قادر به رمزگشایی حتی یک مورد از اطلاعات هویتی نخواهد بود و امکان بازیابی یا بازنشانی وجود ندارد. فایل .env کلید را در خود نگه می‌دارد؛ در همان روزی که آن را ایجاد می‌کنید، آن را در جایی خارج از سرور کپی کنید — استفاده از یک مدیریت‌پسورد (password-manager) ایده‌آل است. این مهم‌ترین نسخه پشتیبان شماست.

پایگاه داده Postgres، برای گردش‌های کاری، تاریخچه اجرا و خودِ اطلاعات هویتی رمزنگاری شده:

docker compose exec -T postgres pg_dump -U n8n -d n8n \
  | gzip > n8n-db-$(date +%F).sql.gz

این دستور را در یک برنامه زمان‌بندی شده اجرا کنید و فایل dump را از سرور خارج کنید. برای بازیابی در یک VPS جدید: ابتدا stack را اجرا کنید تا پایگاه داده ایجاد شود، سپس n8n را متوقف کنید، dump را با استفاده از psql بارگذاری کنید، همان N8N_ENCRYPTION_KEY را در .env قرار دهید و n8n را اجرا کنید. ترکیب کلید مشابه و فایل dump، یک نسخه فعال و سالم ایجاد می‌کند؛ اما کلید جدید باعث می‌شود گردش‌های کاری نتوانند از هیچ اطلاعات هویتی استفاده کنند.

Upgrades: pin the tag

فایل compose به عمد از n8nio/n8n:2.29.10 به جای latest استفاده می‌کند. n8n تقریباً هر هفته یک نسخه minor جدید منتشر می‌کند و گاهی اوقات بین این نسخه‌ها، ساختار database یا رفتار nodeها را تغییر می‌دهد. بنابراین latest به این معناست که یک pull خودکار می‌تواند نسخه‌ای را به شما تحویل دهد که بلافاصله پس از اجرا، database شما را migrate کند. یک نسخه مشخص را pin کنید، پیش از ارتقا release notes را بخوانید (n8n تغییرات breaking را در آنجا ذکر می‌کند) و ارتقا را آگاهانه انجام دهید:

docker compose exec -T postgres pg_dump -U n8n -d n8n | gzip > pre-upgrade.sql.gz
# edit the image tag in docker-compose.yml, then:
docker compose pull n8n
docker compose up -d n8n
docker compose logs -f n8n

پرش‌های نسخه اصلی (major-version) مهم‌ترین زمان برای این کار هستند. برای مثال، سری 2.0 به صورت پیش‌فرض N8N_BLOCK_ENV_ACCESS_IN_NODE را به true تغییر داد؛ بنابراین هر Code node که process.env را می‌خواند، تا زمانی که آن را دوباره روی false تنظیم نکنید، دسترسی خود را از دست می‌دهد. همچنین در همان نسخه، اعمال محدودیت‌های سخت‌گیرانه (strict permissions) روی settings file شروع شد. پیش از عبور از یک مرز major، صفحه 2.0 breaking-changes را مطالعه کنید. n8n تمام migrationهای مورد نیاز database را هنگام شروع به صورت خودکار اجرا می‌کند؛ دقیقاً به همین دلیل است که pg_dump پیش از ارتقا، اختیاری نیست. از آنجایی که credentials با یک key در .env به صورت رمزنگاری شده ذخیره می‌شوند و داده‌ها در Postgres قرار دارند، کانتینرها disposable هستند: شما با جایگزین کردن آن‌ها ارتقا پیدا می‌کنید و با pin کردن تگ قبلی و restore کردن dump، به حالت قبل باز می‌گردید.

Failure modes, with the strings you will see

The requested webhook "POST hello" is not registered. A 404 from calling a webhook whose workflow is not Active, or from calling the test path when nobody is listening. Test paths (/webhook-test/...) answer only while you have clicked "Listen for test event"; production paths (/webhook/...) answer only when the workflow toggle is on. The sibling This webhook is not registered for GET requests. Did you mean to make a POST request? means the method is wrong — the node expects POST and you sent GET.

The webhook URL shows a :5678 or localhost. The node displays https://n8n.example.com:5678/webhook/... or http://localhost:5678/.... WEBHOOK_URL is unset or wrong, so n8n built the address from N8N_HOST:N8N_PORT instead of your public base. Set WEBHOOK_URL=https://n8n.example.com/, recreate the container with docker compose up -d, and the port disappears.

There was a problem loading init data in the browser. The editor loaded but cannot reach its own backend API. Behind a proxy this is almost always a wrong N8N_HOST or WEBHOOK_URL, a proxy missing the WebSocket Upgrade headers, or N8N_PROTOCOL not matching how you connect. Confirm the four public-facing variables and that the proxy forwards Upgrade and Connection.

password authentication failed for user "n8n" in the logs, with the container restarting. The password n8n sends does not match what the database was initialised with. The trap: Postgres reads POSTGRES_PASSWORD only when it initialises an empty data directory. Start the stack once, then change POSTGRES_PASSWORD in .env, and the existing postgres_data volume still holds the old password. Set it back to the original, or, if you have no data to keep, docker compose down and docker volume rm the postgres volume, then bring it up fresh.

EACCES: permission denied, open '/home/node/.n8n/config' on start. n8n runs as the node user (UID 1000) and cannot write its config directory. This bites people who bind-mount a host folder (./n8n_data:/home/node/.n8n) owned by root. Use the named volume shown above, or if you insist on a bind mount, sudo chown -R 1000:1000 ./n8n_data first.

Permissions 0644 for n8n settings file /home/node/.n8n/config are too wide. Changing permissions to 0600.. From the 2.x line n8n enforces 0600 on that settings file by default and fixes it itself on boot — this log line means it already corrected the mode, commonly after a bind mount or after a restore copied the file back with loose permissions. No action is needed; set N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=false only if your filesystem genuinely cannot support permissions.

Mismatching encryption keys — the fuller line says the encryption key in the settings file /home/node/.n8n/config does not match the N8N_ENCRYPTION_KEY in your environment. The key in your environment differs from the one n8n wrote into its data volume on a previous run — most often because n8n generated a random key on an earlier boot when the variable was unset, and you then set a different one. Put the original key back in .env, or, only if you truly have no stored credentials worth keeping, delete the config file inside the n8n_data volume and let n8n regenerate it — accepting that existing credentials become unreadable.

A login banner about secure cookies: Your n8n server is configured to use a secure cookie, however you are either visiting this via an insecure URL, or using Safari. You set N8N_PROTOCOL=https but reached n8n over plain HTTP — usually by hitting the IP and port directly instead of the HTTPS proxy. Reach it via https://n8n.example.com/. Only if you genuinely cannot use HTTPS should you set N8N_SECURE_COOKIE=false, and never on an internet-facing box.

To put a language model inside those workflows, see building AI workflows with Claude and n8n.

FAQ

آیا برای n8n از SQLite استفاده کنم یا Postgres؟

SQLite (حالت پیش‌فرض) برای امتحان کردن n8n و برای یک نمونه شخصی که در هر لحظه فقط یک workflow را اجرا می‌کند، مناسب است. برای هر موردی که به آن وابسته هستید، به Postgres مهاجرت کنید: قفل تک‌نویسنده (single writer lock) در SQLite باعث بروز database is locked در هنگام هم‌روندی (concurrency) می‌شود، در حالی که Postgres با استفاده از pg_dump پشتیبانی کامل از backup را ارائه می‌دهد. مهاجرت در مراحل بعدی به صورت دستی انجام می‌شود، بنابراین اگر سرور برای شما اهمیت دارد، کار را با Postgres شروع کنید.

چرا webhookهای n8n من هرگز اجرا نمی‌شوند؟

تقریباً همیشه به دلیل WEBHOOK_URL است. اگر N8N_HOST:N8N_PORT تنظیم نشده باشد یا اشتباه باشد، n8n آدرس‌های webhook را بر اساس آن می‌سازد — که اغلب شامل :5678 یا localhost هستند — این آدرس‌ها معتبر به نظر می‌رسند اما از طریق اینترنت قابل دسترسی نیستند، بنابراین درخواست‌های فرستنده هرگز نمی‌رسند. WEBHOOK_URL=https://n8n.example.com/ را تنظیم کنید و مطمئن شوید که node یک URL بدون port نمایش می‌دهد. دلیل دوم، فراخوانی webhookی است که workflow آن در حالت Active قرار ندارد، که منجر به خطای The requested webhook ... is not registered. می‌شود.

چه مواردی را باید در n8n backup بگیرم؟

دو مورد. N8N_ENCRYPTION_KEY از فایل .env شما، زیرا تمام credentials ذخیره شده با آن رمزنگاری می‌شوند و از دست دادن آن باعث می‌شود آن‌ها برای همیشه غیرقابل رمزگشایی شوند — همان روزی که فایل را ایجاد کردید، آن را از سرور کپی کنید. و یک pg_dump از دیتابیس Postgres برای workflowها، تاریخچه و credentials. برای بازیابی (restore) به هر دو نیاز دارید: همان کلید به همراه dump.

چگونه n8n را پشت HTTPS قرار دهم؟

n8n روی پورت 5678 پروتکل HTTP ساده را ارائه می‌دهد؛ یک reverse proxy در جلو، TLS را پایان می‌دهد (terminate می‌کند). n8n را به 127.0.0.1:5678 متصل کنید تا فقط proxy بتواند به آن دسترسی داشته باشد، سپس از Traefik با گواهی‌های خودکار یا nginx با گواهی Let's Encrypt استفاده کنید. N8N_PROTOCOL=https و WEBHOOK_URL=https://your-host/ را تنظیم کنید و مطمئن شوید که proxy هدرهای WebSocket یعنی Upgrade را فوروارد می‌کند، در غیر این صورت editor هنگ می‌کند.

چگونه n8n را به صورت ایمن ارتقا (upgrade) دهم؟

به جای استفاده از latest، یک image tag مشخص را ثابت (pin) کنید، ابتدا یک pg_dump تهیه کنید زیرا n8n هنگام شروع به صورت خودکار migrations را اجرا می‌کند، یادداشت‌های انتشار (release notes) را برای تغییرات ساختاری (breaking changes) بخوانید، سپس tag را تغییر دهید و docker compose pull n8n && docker compose up -d n8n را اجرا کنید. کانتینر قابل جایگزینی است، بنابراین برای بازگشت به حالت قبل (roll back)، tag قبلی را ثابت کنید و dump قبل از ارتقا را بازیابی کنید.