n8n বারবার অফলাইন হয়ে যাওয়ার কারণ ও সমাধান
n8n কেন অফলাইন হয় তা জানুন। websocket সংযোগ বিচ্ছিন্ন হওয়া, কন্টেইনার রিস্টার্ট লুপ, OOM killer দ্বারা প্রসেস কিল হওয়া এবং শিডিউল ব্যর্থতা চিহ্নিত করার সঠিক উপায় এখানে দেওয়া হলো।
কেন n8n বারবার অফলাইন হয়ে যায়: চারটি ব্যর্থতা, একটি লক্ষণ
"n8n বারবার অফলাইন হয়ে যায়" বাক্যটি চারটি ভিন্ন ধরনের ব্যর্থতাকে নির্দেশ করে এবং প্রতিটির সমাধান ভিন্ন। কন্টেইনার স্বাভাবিকভাবে চলতে থাকা সত্ত্বেও এডিটরে connection lost ব্যানার দেখা দিতে পারে। কন্টেইনার নিজে থেকেই রিস্টার্ট হতে পারে। অতিরিক্ত মেমরি ব্যবহারের কারণে কার্নেল Node.js প্রসেসটিকে বন্ধ করে দিতে পারে। অথবা প্রসেসে কোনো সমস্যা না থাকলেও একটি সক্রিয় workflow হয়তো কখনোই কার্যকর হচ্ছে না। ভুল সেটিং পরিবর্তন করলে আপনি এমন একটি সমস্যার পেছনে সপ্তাহান্ত নষ্ট করবেন যা আসলে ছিলই না।
তাই কোনো কনফিগারেশন পরিবর্তন করার আগে আপনার সমস্যাটি কোনটি তা খুঁজে বের করুন। n8n সাধারণত একটি Docker কন্টেইনারের ভেতরে একক Node.js প্রসেস হিসেবে চলে, যা TLS (transport layer security) টার্মিনেট করে এমন একটি reverse proxy-এর পেছনে থাকে। এই প্রতিটি স্তরের ব্যর্থতার ধরন আলাদা, কিন্তু ব্রাউজার সবগুলোকে একই বার্তার মাধ্যমে রিপোর্ট করে।
এই ক্রমে সমস্যা নির্ণয় করুন
VPS (virtual private server)-এ এই কমান্ডগুলো চালান এবং আপনার মেশিনে যে মানগুলো দেখাচ্ছে তা পড়ুন। কোনো ফোরাম থ্রেডের সংখ্যার সাথে এগুলো তুলনা করবেন না। এখানে গুরুত্বপূর্ণ মানগুলো আপনার সার্ভারের অবস্থা নির্দেশ করে, অন্য কারো নয়।
docker ps -a --filter name=n8n
docker logs --tail 200 --timestamps n8n
docker inspect n8n | grep -iE 'Status|Running|RestartCount|OOMKilled|ExitCode'
docker stats --no-streamdocker ps -a-এর STATUS কলামটি নির্দেশ করে কন্টেইনারটি তার বর্তমান অবস্থায় কতক্ষণ ধরে আছে। আপনার সমস্যাটি যখন শুরু হয়েছিল, সেই সময়ের সাথে এটি তুলনা করুন। যদি ব্যানারটি আসার অনেক আগে থেকেই কন্টেইনারটি চালু থাকে, তবে n8n কখনো অফলাইন হয়নি। যা ভেঙেছে তা হলো আপনার ব্রাউজার এবং ব্যাকএন্ডের মধ্যকার সংযোগ, যা পরবর্তী সেকশনে আলোচিত websocket পাথ।
RestartCount হলো ডকার কতবার এই কন্টেইনারটি রিস্টার্ট করেছে তার সংখ্যা। সংখ্যাটি লিখে রাখুন, এক মিনিট অপেক্ষা করুন, তারপর আবার দেখুন। আপনি দেখার সময় যদি সংখ্যাটি বাড়তে থাকে, তবে এটি একটি রিস্টার্ট লুপ। প্রতিটি রিস্টার্টের ঠিক আগের লগ লাইনগুলোতে এর কারণ লেখা থাকে।
OOMKilled হলো একটি true বা false ফ্ল্যাগ। True মানে হলো লিনাক্স কার্নেল প্রসেসটিকে বন্ধ করে দিয়েছে কারণ এটি মেমোরি লিমিট অতিক্রম করেছিল, যা হতে পারে কন্টেইনারের নিজস্ব লিমিট অথবা পুরো মেশিনের লিমিট। এই একটি ফিল্ডই মেমোরি কিল এবং অন্য সব ধরনের এক্সিটকে আলাদা করে, তাই কোনো অনুমান করার আগেই এটি পড়ে দেখুন।
ExitCode হলো আপনার কন্টেইনার সর্বশেষ কী কোড নিয়ে এক্সিট হয়েছে। প্রতিটি কোডের অর্থ মুখস্থ করার প্রয়োজন নেই। আপনার কোডটি পড়ুন, তারপর একই টাইমস্ট্যাম্প থেকে docker logs-এর শেষ অংশটি দেখুন। লগ টেইল এবং আউট অফ মেমোরি ফ্ল্যাগ একত্রে আপনাকে জানাবে কী ঘটেছে, এবং এদের যেকোনো একটি একা আপনাকে ভুল পথে পরিচালিত করতে পারে।
docker stats বর্তমান মেমোরি ব্যবহারের সাথে কার্যকর লিমিটটি দেখায়। এটিকে একটি দ্বিতীয় টার্মিনালে চালু রাখুন, যে ওয়ার্কফ্লোটি সমস্যা তৈরি করছে তা ট্রিগার করুন এবং ব্যর্থতা ঘটার সময় সংখ্যাটি কীভাবে পরিবর্তিত হচ্ছে তা পর্যবেক্ষণ করুন।
সংযোগ বিচ্ছিন্ন হওয়ার ব্যানারটি সাধারণত আপনার রিভার্স প্রক্সির কারণে আসে
n8n এডিটর ব্যাকএন্ডের সাথে একটি দীর্ঘস্থায়ী পুশ কানেকশন খোলা রাখে, যাতে এটি ক্যানভাসে এক্সিকিউশনের অগ্রগতি স্ট্রিম করতে পারে। ডিফল্টভাবে এই কানেকশনটি একটি WebSocket, যা N8N_PUSH_BACKEND নির্বাচন করে এবং এর ডিফল্ট মান হলো websocket। একটি WebSocket সাধারণ HTTP রিকোয়েস্ট হিসেবে শুরু হয়, যাতে Connection: Upgrade এবং Upgrade: websocket হেডার থাকে। সার্ভার 101 Switching Protocols উত্তর দেয় এবং এরপর থেকে উভয় পক্ষই একই TCP সকেট ব্যবহার করে উভয় দিকে যোগাযোগ চালায়।
দুটি কারণে এটি বাধাগ্রস্ত হয় এবং উভয় সমস্যাই n8n-এর পরিবর্তে প্রক্সিতে থাকে। প্রক্সি আপস্ট্রিম হিসেবে HTTP/1.0 ব্যবহার করে অথবা আপগ্রেড হেডারগুলো মুছে ফেলে, ফলে আপগ্রেড কখনোই সম্পন্ন হয় না এবং এডিটর বারবার রিকানেক্ট করতে থাকে। অথবা আপগ্রেড সফল হয় কিন্তু প্রক্সি পরবর্তীতে সকেটটি বন্ধ করে দেয় কারণ এটি নিষ্ক্রিয় ছিল, যেহেতু কোনো মেসেজ আদান-প্রদান না হওয়া WebSocket দেখতে একদম অলস কানেকশনের মতো। উভয় ক্ষেত্রেই কন্টেইনারটি সুস্থ থাকে। ব্যানারটি হলো ব্রাউজারের একটি বার্তা যা আপনাকে জানায় যে এটি তার চ্যানেল হারিয়েছে।
কোনো কিছু এডিট করার আগে ব্রাউজারে এটি নিশ্চিত করুন। ডেভেলপার টুলস খুলুন, Network ট্যাবে যান, WS ফিল্টার করুন এবং এডিটর রিলোড করুন। পুশ রিকোয়েস্টটি 101 Switching Protocols-এ পৌঁছানো উচিত এবং খোলা থাকা উচিত। যদি কোনো পুশ রিকোয়েস্ট সাধারণ স্ট্যাটাস কোড রিটার্ন করে অথবা প্রতি কয়েক সেকেন্ড পরপর পুনরায় দেখা দেয়, তবে বুঝতে হবে সমস্যাটি প্রক্সিতে।
এডিটরকে সংযুক্ত রাখার জন্য Nginx সেটিংস
Nginx-কে নির্দেশ না দিলে এটি upgrade রিকোয়েস্ট ফরোয়ার্ড করে না। proxy_pass ডিফল্টভাবে ব্যাকএন্ডের সাথে HTTP/1.0 প্রোটোকলে যোগাযোগ করে এবং Connection ও Upgrade হলো hop-by-hop হেডার যা Nginx ট্রাফিক পার হওয়ার সময় মুছে ফেলে। আপনাকে এই দুটি হেডারই পুনরায় যোগ করতে হবে। map ব্লকটি server-এর ভেতরে নয়, বরং http কনটেক্সটে রাখতে হবে।
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}server {
listen 443 ssl;
http2 on;
server_name n8n.example.com;
location / {
proxy_pass http://127.0.0.1:5678;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_buffering off;
}
}proxy_read_timeout হলো সেই লাইন যা মানুষ প্রায়ই বাদ দিয়ে দেয়। এর ডিফল্ট সময়সীমা 60 সেকেন্ড এবং এটি আপগ্রেড করা WebSocket-এর ক্ষেত্রেও প্রযোজ্য। ফলে কোনো এডিটর ট্যাব যদি অলস অবস্থায় থাকে, তবে শেষ মেসেজ আদান-প্রদানের এক মিনিট পরেই সংযোগ বিচ্ছিন্ন হয়ে যায়। এই সময়সীমা বাড়িয়ে দিলে ট্যাবটি পুনরায় খোলার সময় যে ব্যানারটি দেখা যায়, তা আর আসবে না।
sudo nginx -t && sudo systemctl reload nginx
sudo nginx -T | grep -iE 'proxy_http_version|upgrade|proxy_read_timeout'nginx -T কমান্ডটি একটি ফাইলের পরিবর্তে পুরো রানিং কনফিগারেশন প্রদর্শন করে, যা নিশ্চিত করে যে আপনার করা পরিবর্তনটি লোড হয়েছে কি না। অনেক সময় সঠিক কনফিগারেশন ফাইল থাকা সত্ত্বেও কোনো include লাইন সেটি অন্তর্ভুক্ত না করলে পরিবর্তনটি কার্যকর হয় না।
এরপর n8n-কে জানান যে এটি একটি প্রক্সির পেছনে চলছে, কারণ এটি এই ভ্যালুগুলো ব্যবহার করেই URL তৈরি করে।
environment:
- N8N_HOST=n8n.example.com
- N8N_PROTOCOL=https
- N8N_PORT=5678
- N8N_PROXY_HOPS=1
- N8N_WEBHOOK_URL=https://n8n.example.com/N8N_PROXY_HOPS-এর ডিফল্ট মান 0, যার অর্থ n8n কানেক্ট হওয়া অ্যাড্রেসকেই ক্লায়েন্ট অ্যাড্রেস হিসেবে গণ্য করে এবং X-Forwarded-For-কে উপেক্ষা করে। এটিকে কন্টেইনারের সামনে থাকা প্রক্সির সংখ্যার সমান সেট করুন। আগস্ট 2026 অনুযায়ী, N8N_WEBHOOK_URL হলো বর্তমান নাম এবং পুরনো WEBHOOK_URL এখনো কাজ করলেও স্টার্টআপের সময় একটি deprecation ওয়ার্নিং দেখায়।
Traefik ওয়েব-সকেট ফরওয়ার্ড করে, তারপর টাইম-আউট করে
Traefik কোনো middleware বা অতিরিক্ত label ছাড়াই WebSocket upgrade ফরওয়ার্ড করে। তাই Traefik ব্যবহারকারী যদি এই ব্যানারটি দেখেন, তবে সাধারণত সেটি কোনো missing header-এর কারণে নয়, বরং টাইম-আউটের কারণে ঘটে। এর নিয়ন্ত্রণগুলো entryPoint-এ থাকে। 2026 সালের আগস্ট মাস অনুযায়ী Traefik v3-এ, idleTimeout-এর ডিফল্ট মান 180 সেকেন্ড এবং readTimeout-এর ডিফল্ট মান 60 সেকেন্ড।
entryPoints:
websecure:
address: ":443"
transport:
respondingTimeouts:
readTimeout: 0
idleTimeout: 3600sCaddy স্বয়ংক্রিয়ভাবে reverse_proxy-এ আপগ্রেড হ্যান্ডেল করে এবং এর জন্য কোনো অতিরিক্ত directive-এর প্রয়োজন হয় না। যদি আপনি প্রক্সি পরিবর্তন করতে না পারেন, কারণ সেটির নিয়ন্ত্রণ অন্য কারো কাছে, তবে N8N_PUSH_BACKEND=sse ব্যবহার করে পুশ চ্যানেল পরিবর্তন করুন। SSE (server-sent events) হলো একটি সাধারণ HTTP রেসপন্স যা ওপেন রাখা হয়, তাই এটি এমন প্রক্সিতেও কাজ করে যা আপগ্রেড গ্রহণ করে না; যদিও অতিরিক্ত idle timeout-এর কারণে সংযোগ বিচ্ছিন্ন হতে পারে। প্রক্সি নির্বাচন করা একটি আলাদা সিদ্ধান্ত, এবং Nginx, Caddy এবং Traefik-এর তুলনা অংশে প্রতিটি ব্যবহারের খরচ ও সুবিধা আলোচনা করা হয়েছে।
যখন কন্টেইনারটি বারবার রিস্টার্ট হয়
যদি RestartCount বাড়তে থাকে, তবে কন্টেইনারটি ব্যর্থ হচ্ছে এবং Docker সেটিকে বারবার চালু করার চেষ্টা করছে। লগের টাইমস্ট্যাম্পের সাথে রিস্টার্টের সময় মিলিয়ে দেখুন এবং রিস্টার্টের ঠিক আগের অংশটি পড়ুন। চারটি কারণে সাধারণত এমনটি ঘটে: স্টার্টআপে বাধা দেয় এমন কনফিগারেশন ত্রুটি, n8n সংযোগ করতে পারে না এমন ডাটাবেস, চলার পথে ক্র্যাশ করা এবং মেমরি ফুরিয়ে যাওয়া (memory kill)।
ভলিউম দিয়ে শুরু করুন, কারণ পারমিশন সংক্রান্ত সমস্যাগুলো সহজে ধরা পড়ে না। অফিসিয়াল ইমেজটি node নামক unprivileged ব্যবহারকারী হিসেবে চলে এবং এর ডাটা /home/node/.n8n ডিরেক্টরিতে রাখে। root ব্যবহারকারীর তৈরি করা bind mount-এ ওই ব্যবহারকারীর লেখার অনুমতি থাকে না, ফলে প্রতিবার স্টার্টআপের সময় প্রসেসটি বন্ধ হয়ে যায় এবং রিস্টার্ট পলিসির কারণে বিষয়টি লুপের আড়ালে থেকে যায়।
docker compose config
docker run --rm -it --entrypoint sh docker.n8n.io/n8nio/n8n -c 'id'
docker exec n8n ls -ld /home/node/.n8nএকটি named volume ব্যবহার করলে এই সমস্যা পুরোপুরি এড়ানো যায়, কারণ Docker নিজেই সঠিক মালিকানা (ownership) দিয়ে এটি তৈরি করে। যদি আপনার bind mount প্রয়োজন হয়, তবে প্রথম কমান্ডে যে numeric user id দেখা গেছে, তাতে হোস্ট ডিরেক্টরিটিকে chown করুন। হোস্ট এবং কন্টেইনারের মধ্যে মালিকানা ম্যাপিং বিষয়টি একবার বুঝে নেওয়া জরুরি, এবং PUID এবং PGID সংক্রান্ত ব্যাখ্যা অংশে এই ইমেজগুলো কীভাবে ফাইল রাইটার নির্ধারণ করে তা বিস্তারিত আলোচনা করা হয়েছে।
আউট অফ মেমরি কিল যা ক্র্যাশের মতো দেখায়
একটি n8n প্রসেসের উপরে দুটি আলাদা মেমরি সিলিং থাকে এবং এগুলোর ব্যর্থতার ধরন ভিন্ন। কন্টেইনার কন্ট্রোল গ্রুপ লিমিট কার্নেল দ্বারা কার্যকর করা হয়: এটি অতিক্রম করলে প্রসেসটি তাৎক্ষণিকভাবে কিল হয়ে যায়, কোনো কিছু লেখার সুযোগ থাকে না এবং OOMKilled এর মান true হয়। V8 হিপ লিমিট Node.js-এর ভেতরে কার্যকর করা হয়: এটি অতিক্রম করলে Node একটি হিপ এরর এবং স্ট্যাক ট্রেসসহ নিজে থেকেই এক্সিট করে, তাই OOMKilled এর মান false হয়। ব্রাউজার থেকে এগুলোকে একই রকম মনে হয়। docker inspect থেকে দেখলে এগুলো মাত্র একটি ফিল্ডের পার্থক্যে থাকে।
Node হিপ সিলিংকে কন্টেইনার লিমিটের নিচে সেট করুন। যদি হিপ সিলিং দুটির মধ্যে উচ্চতর হয়, তবে V8 কার্নেলের হস্তক্ষেপের পয়েন্ট ছাড়িয়েও মেমরি বরাদ্দ করতে থাকে। ফলে এর গার্বেজ কালেক্টর কখনোই নিজের লিমিটে পৌঁছায় না এবং আপনি সবসময়ই কঠোর ব্যর্থতার সম্মুখীন হন, যেখানে পড়ার মতো কোনো লগ থাকে না।
services:
n8n:
image: docker.n8n.io/n8nio/n8n
restart: unless-stopped
environment:
- NODE_OPTIONS=--max-old-space-size=<MiB, below the container limit>
deploy:
resources:
limits:
memory: <your container limit>আপনার VPS-এ প্রকৃতপক্ষে যতটুকু মেমরি আছে তা থেকে উভয় সংখ্যা নির্বাচন করুন, যাতে ডাটাবেস, প্রক্সি এবং অপারেটিং সিস্টেমের জন্য পর্যাপ্ত জায়গা থাকে। docker stats --no-stream কার্যকর থাকা লিমিটের পাশে বর্তমান ব্যবহার প্রদর্শন করে, তাই আপনি যাচাই করতে পারেন যে আপনি যে লিমিটটি লিখেছেন তা Docker প্রয়োগ করেছে কি না। Compose মেমরি লিমিট কীভাবে প্রয়োগ করা হয় অংশে একাধিক লিমিট সেট করা থাকলে কোন কি (key) কার্যকর হয় তা বিস্তারিত আলোচনা করা হয়েছে।
এক্সিকিউশন ডেটা আপনার অজান্তেই বাড়তে থাকে
একটি রান চলাকালীন প্রতিটি নোডের আউটপুট একটি সিঙ্গেল এক্সিকিউশনে জমা থাকে এবং n8n পরবর্তীতে সেই ডেটা সংরক্ষণ করে। এর দুটি ফলাফল রয়েছে। একটি রানের সর্বোচ্চ মেমরি ব্যবহারের পরিমাণ নির্ভর করে আপনি এর মধ্য দিয়ে কত বড় ব্যাচের ডেটা পাঠাচ্ছেন তার ওপর। তাই যে ওয়ার্কফ্লো একসাথে দশ হাজার সারি হ্যান্ডেল করে, সেটি দুইশ সারি হ্যান্ডেল করা একই ওয়ার্কফ্লো থেকে সম্পূর্ণ আলাদা একটি প্রোগ্রাম। আর সংরক্ষিত কপিটি ততক্ষণ পর্যন্ত বাড়তে থাকে যতক্ষণ না কেউ তা মুছে ফেলে।
প্রুনিং (Pruning) দ্বিতীয় সমস্যাটি সমাধান করে। আগস্ট 2026 অনুযায়ী, ডিফল্ট সেটিংসে প্রুনিং সক্রিয় থাকে, যেখানে EXECUTIONS_DATA_MAX_AGE 336 ঘণ্টা (14 দিন) এবং EXECUTIONS_DATA_PRUNE_MAX_COUNT 10000-এ সেট করা থাকে। SQLite চালিত ছোট VPS-এর জন্য এগুলো বেশ উদার সীমা, যেখানে একটি ফাইল সবকিছু ধারণ করে এবং যে প্রসেসটি এডিটর সার্ভ করে, তাকেই এটি পড়তে ও লিখতে হয়।
environment:
- EXECUTIONS_DATA_PRUNE=true
- EXECUTIONS_DATA_MAX_AGE=72
- EXECUTIONS_DATA_PRUNE_MAX_COUNT=1000
- EXECUTIONS_DATA_SAVE_ON_SUCCESS=none
- EXECUTIONS_DATA_SAVE_MANUAL_EXECUTIONS=falseEXECUTIONS_DATA_SAVE_ON_SUCCESS=none হলো একটি আক্রমণাত্মক সেটিং। এটি ডিবাগিংয়ের জন্য ব্যর্থ এক্সিকিউশনগুলো রেখে দেয় এবং সফলগুলো মুছে ফেলে। এটি ভেবেচিন্তে নির্ধারণ করুন, কারণ যে ওয়ার্কফ্লো কোনো এরর না দেখিয়েই ভুল আউটপুট তৈরি করেছে, সেটি পরে আর পরীক্ষা করার সুযোগ থাকবে না। প্রুনিং প্রথমে সারিগুলোকে মুছে ফেলা হিসেবে চিহ্নিত করে এবং পরবর্তী কোনো ধাপে সেগুলো সরিয়ে ফেলে। এছাড়া SQLite খালি হওয়া পেজগুলো ডিস্কে ফেরত না পাঠিয়ে পুনরায় ব্যবহার করে, তাই সেটিং পরিবর্তনের সাথে সাথেই ডিস্কের ফাইলের আকার ছোট হয় না।
মোট সংরক্ষিত ডেটার পরিবর্তে সর্বোচ্চ মেমরি ব্যবহার কমাতে, প্রতি রানে কম ডেটা প্রসেস করুন। বড় কাজগুলোকে ছোট ছোট সাব-ওয়ার্কফ্লোতে ভাগ করুন যা প্যারেন্ট ওয়ার্কফ্লোতে ছোট ফলাফল পাঠাবে, Loop Over Items নোড ব্যবহার করে ব্যাচ করুন এবং পুরো ডেটাসেটকে Code নোডের বাইরে রাখুন।
বাইনারি ফাইল মেমোরির মধ্য দিয়ে প্রবাহিত হওয়া উচিত নয়
N8N_DEFAULT_BINARY_DATA_MODE ডিফল্টভাবে default ব্যবহার করে, যা চলমান প্রসেসের মেমরিতে বাইনারি ডেটা জমা রাখে। একটি নোড যে ফাইল ডাউনলোড করে এবং পরবর্তী নোডকে যে কপি প্রদান করে, তা রান শেষ না হওয়া পর্যন্ত সেখানেই থাকে। একটি ওয়ার্কফ্লো যদি কয়েকটি বড় অ্যাটাচমেন্ট নিয়ে কাজ করে, তবে তা প্রসেসটিকে এমন সীমার বাইরে নিয়ে যেতে পারে যা সাধারণ JSON কাজের ক্ষেত্রে কখনোই ঘটে না। এই কারণেই ক্র্যাশটি সময়ের ওপর নির্ভর না করে একটি নির্দিষ্ট ওয়ার্কফ্লোর ওপর নির্ভর করে ঘটে।
environment:
- N8N_DEFAULT_BINARY_DATA_MODE=filesystemfilesystem ব্যবহার করলে, বাইনারি ডেটা N8N_BINARY_DATA_STORAGE_PATH-এর অধীনে লেখা হয়, যা ডিফল্টভাবে n8n ইউজার ফোল্ডারের ভেতরে থাকে এবং তাই অন্য সবকিছুর মতোই একই ভলিউমে জমা হয়। পরিবর্তন করার আগে ভলিউমে পর্যাপ্ত জায়গা আছে কি না তা যাচাই করুন। N8N_PAYLOAD_SIZE_MAX ইনকামিং ওয়েবহুক পেলোডের সর্বোচ্চ আকার MiB (মেবিবাইট)-এ নির্ধারণ করে এবং এর ডিফল্ট মান 16। এটি বৃদ্ধি করলে বড় রিকোয়েস্ট গ্রহণ করা সম্ভব হয়, তবে এটি মেমরির ওপর বাড়তি চাপ সৃষ্টি করে যা আপনাকে মেনে নিতে হবে।
সার্ভারে থাকা অন্য যেকোনো কিছু একই RAM-এর জন্য প্রতিযোগিতা করে। যদি ডাটাবেস কন্টেইনার যোগ করার পর থেকেই OOM কিল শুরু হয়ে থাকে, তবে ডাটাবেসটি ডকারে বা হোস্ট মেশিনে চালানো হলো সেই আপস যা আপনাকে এখন করতে হচ্ছে।
Restart policy এবং রিবুটের পরে পুনরায় চালু হওয়া
কোনো restart policy না থাকলে একটি কন্টেইনার বন্ধ হওয়ার পর বা হোস্ট রিবুট হওয়ার পর আর চালু হয় না। restart: unless-stopped উভয় ক্ষেত্রেই এটিকে পুনরায় চালু করে, তবে আপনি নিজে থেকে কোনো কন্টেইনার বন্ধ করলে সেটি আর চালু করবে না। restart: always ব্যবহার করলে আপনি নিজে থেকে বন্ধ করা কন্টেইনারটিও Docker পুনরায় চালু হওয়ার সাথে সাথে চালু হয়ে যাবে।
n8n একটি health endpoint প্রদান করে, যার নাম N8N_ENDPOINT_HEALTH এবং এর ডিফল্ট মান হলো healthz। আপনার ইনস্ট্যান্সে পাথটি সঠিক কি না তা নিশ্চিত হতে প্রথমে হোস্ট থেকে এটি পরীক্ষা করে দেখুন।
curl -fsS http://127.0.0.1:5678/healthz
docker exec n8n which wget curl
sudo systemctl is-enabled dockerশুধুমাত্র একটি healthcheck কোনো কিছু রিস্টার্ট করে না। Compose কন্টেইনারটিকে unhealthy হিসেবে চিহ্নিত করে সেখানেই থেমে যায়, তাই কোনো কার্যকর ফলাফল পেতে healthcheck-এর সাথে একটি restart policy অথবা একটি external watcher থাকা প্রয়োজন। কার্যকর healthcheck লেখা এবং রিবুটের পরে স্ট্যাক পুনরায় চালু করা অংশে এই দুটি বিষয় বিস্তারিত আলোচনা করা হয়েছে।
যে workflow কখনোই কার্যকর হয় না অথচ n8n ঠিকঠাক কাজ করছে
এই ক্ষেত্রে কোনো ব্যানার বা রিস্টার্টের প্রয়োজন হয় না। কন্টেইনারটি সচল থাকে, এডিটর কাজ করে, কিন্তু এক্সিকিউশন তালিকায় আপনার প্রত্যাশিত রানটি দেখা যায় না। এর পেছনে প্রধানত চারটি কারণ থাকে।
- workflow-টি active নয়। একটি Schedule Trigger শুধুমাত্র production পাথে চলে, তাই ক্যানভাসে এটি টেস্ট করলে কোনো শিডিউল কার্যকর হয় না।
- timezone আপনার অঞ্চলের নয়।
GENERIC_TIMEZONEডিফল্টভাবেAmerica/New_Yorkসেট করা থাকে, তাই আপনিGENERIC_TIMEZONEএবংTZআপনার নিজের টাইমজোনে সেট না করা পর্যন্ত 09:00-এর শিডিউল সেই টাইমজোন অনুযায়ীই চলবে। - ডাউনটাইমের সময় মিস হওয়া রানগুলো পরে আর কার্যকর হয় না। n8n স্টার্ট হওয়ার সময় ট্রিগারগুলো রেজিস্টার হয়, তাই কন্টেইনার রিস্টার্ট হওয়ার সময় কোনো শিডিউল মিস হলে তা পরে আর চলে না। স্টার্টআপের পর পরবর্তী নির্ধারিত সময়েই কেবল রানটি কার্যকর হবে।
- workflow-টি আপনার অজান্তেই ডিঅ্যাক্টিভেট হয়ে গেছে।
N8N_WORKFLOW_AUTODEACTIVATION_ENABLEDডিফল্টভাবে বন্ধ থাকে, আর এটি চালু থাকলে কোনো workflow বারবার ক্র্যাশ করলে তা unpublished হয়ে যায়। এরপর সেটিকে এমন দেখায় যেন কেউ কখনোই সেটি অ্যাক্টিভেট করেনি।
এক্সিকিউশন তালিকা খুলুন এবং নির্দিষ্ট workflow-টির জন্য ফিল্টার করুন। যদি কোনো এন্ট্রি ব্যর্থ হয়, তবে সেটি workflow-এর সমস্যা। যদি কোনো এন্ট্রিই না থাকে, তবে সেটি ট্রিগারের সমস্যা এবং উপরের চারটি কারণ যাচাই করে দেখুন।
প্রথমে যা পরিবর্তন করতে হবে
- কোনো ফাইল এডিট করার আগে আপনার নিজস্ব কন্টেইনারে
STATUS,RestartCountএবংOOMKilledপড়ুন। - যদি কন্টেইনারটি কখনো বন্ধ না হয়ে থাকে, তবে প্রক্সি আপগ্রেড হেডার এবং আইডল টাইমআউট ঠিক করুন।
- যদি
OOMKilledসত্য (true) হয়, তবে আপনার পছন্দমতো একটি কন্টেইনার লিমিট সেট করুন, Node হিপ সিলিং তার নিচে রাখুন এবং বাইনারি ডেটাকেfilesystem-এ পরিবর্তন করুন। - যদি কোনোটিই কার্যকর না হয়, তবে ওয়ার্কফ্লোটি সক্রিয় আছে কি না এবং ইনস্ট্যান্সের টাইমজোন আপনার টাইমজোনের সাথে মিলছে কি না তা যাচাই করুন।
এর বেশিরভাগই এমন কনফিগারেশন যা একটি কার্যকর ইনস্টলেশনের ওপর একবার সেট করে রাখলেই হয়। আপনি যদি এখনো ইনস্টলেশন সম্পন্ন না করে থাকেন, তবে Docker-এ HTTPS সহ n8n সেটআপের নির্দেশিকা হলো সেই ভিত্তি যেখানে এই সেটিংসগুলো প্রয়োগ করতে হয়।
FAQ
কন্টেইনার চলমান থাকা সত্ত্বেও n8n এডিটর কেন connection lost ব্যানার দেখায়?
এডিটর এক্সিকিউশনের অগ্রগতি স্ট্রিম করার জন্য একটি WebSocket খোলা রাখে। যদি আপনার reverse proxy Connection: Upgrade এবং Upgrade: websocket হেডারগুলো ফরোয়ার্ড না করে, অথবা upstream-এ HTTP/1.1 ব্যবহার না করে, তবে upgrade সম্পন্ন হয় না এবং ব্রাউজার বারবার রিকানেক্ট করতে থাকে, যদিও n8n সঠিকভাবে চলতে থাকে। Nginx-এর ক্ষেত্রে আপনার proxy_http_version 1.1 এবং উভয় proxy_set_header লাইন প্রয়োজন, সেইসাথে ডিফল্ট 60 সেকেন্ডের চেয়ে বেশি একটি proxy_read_timeout প্রয়োজন যাতে নিষ্ক্রিয় ট্যাব বিচ্ছিন্ন না হয়। আপনি যে ফাইলটি এডিট করেছেন তা না দেখে sudo nginx -T ব্যবহার করে চলমান কনফিগারেশন যাচাই করুন।
সাধারণ ক্র্যাশ থেকে আউট অফ মেমোরি (OOM) কিল কীভাবে আলাদা করব?
docker inspect n8n | grep -iE 'OOMKilled|ExitCode|RestartCount' চালান এবং OOMKilled ফ্ল্যাগটি দেখুন। True মানে হলো মেমোরি লিমিট অতিক্রম করার কারণে কার্নেল প্রসেসটিকে কিল করেছে, এবং কন্টেইনার লগে কোনো কার্যকর তথ্য থাকবে না কারণ প্রসেসটি কিছু লেখার সুযোগ পায়নি। False এবং docker logs-এর শেষে heap error ও stack trace থাকা মানে হলো Node.js তার নিজস্ব V8 heap সীমাতে পৌঁছেছে এবং নিজে থেকেই এক্সিট করেছে। NODE_OPTIONS=--max-old-space-size-কে আপনার কন্টেইনার লিমিটের নিচে সেট করুন যাতে আপনি দ্বিতীয় ধরনের ব্যর্থতা পান, যা প্রমাণ রেখে যায়।
এক্সিকিউশন ডেটা মুছে ফেললে কি সাথে সাথে ডিস্ক স্পেস খালি হয়?
না। EXECUTIONS_DATA_PRUNE পুরনো এক্সিকিউশনগুলোকে মুছে ফেলার জন্য চিহ্নিত করে এবং EXECUTIONS_DATA_PRUNE_HARD_DELETE_INTERVAL-এ নির্ধারিত সময়সূচী অনুযায়ী পরবর্তী ধাপে সেগুলো মুছে ফেলা হয়। SQLite-এর ক্ষেত্রে ফাইলটি খালি হওয়া পেজগুলোকে পুনরায় ব্যবহার করে, ডিস্কের স্পেস অপারেটিং সিস্টেমকে ফেরত দেয় না, তাই সারিগুলো মুছে ফেলার পরেও ডিস্কের আকার কিছু সময়ের জন্য একই থাকে। EXECUTIONS_DATA_MAX_AGE এবং EXECUTIONS_DATA_PRUNE_MAX_COUNT আপনার সার্ভারের জন্য উপযুক্ত মানে সেট করুন এবং সাথে সাথে না দেখে পরের দিন আবার চেক করুন।
n8n রিস্টার্ট হওয়ার সময় আমার নির্ধারিত (scheduled) ওয়ার্কফ্লো কেন চলেনি?
n8n প্রসেস শুরু হওয়ার সময় ট্রিগার রেজিস্টার করে এবং ডাউনটাইমের সময় মিস হয়ে যাওয়া শিডিউলগুলো পুনরায় চালায় না। তাই রিস্টার্ট লুপের কারণে কোনো মিস হওয়া রান একসাথে কার্যকর হয় না, বরং স্টার্টআপের পর পরবর্তী নির্ধারিত সময়েই ওয়ার্কফ্লোটি চলে। যদি আপনার এমন রান প্রয়োজন হয় যা কোনোভাবেই মিস করা যাবে না, তবে একটি এক্সটারনাল কলারের মাধ্যমে webhook হিট করে ওয়ার্কফ্লোটি চালান, যাতে retry লজিকটি n8n-এর বাইরে থাকে।
n8n সাড়া দেওয়া বন্ধ করলে healthcheck কি এটি রিস্টার্ট করবে?
এটি নিজে থেকে তা করবে না। একটি Compose healthcheck শুধুমাত্র কন্টেইনারকে healthy বা unhealthy হিসেবে চিহ্নিত করে। রিস্টার্ট করার কাজটি restart policy-এর, তাই restart: unless-stopped হলো সেই সেটিংস যা কন্টেইনার এক্সিট করার পর সেটিকে ফিরিয়ে আনে, এবং Docker সার্ভিস এনাবল থাকলে হোস্ট রিবুটের পরেও এটি কাজ করে। sudo systemctl is-enabled docker দিয়ে তা নিশ্চিত করুন। নির্দিষ্টভাবে unhealthy অবস্থার ওপর ব্যবস্থা নিতে হলে Docker-এর বাইরে একটি watcher প্রয়োজন যা স্ট্যাটাস পড়ে সার্ভিসটি রিস্টার্ট করবে।