Docker Compose-এ VPS-এ Planka self-host করুন
Docker Compose দিয়ে VPS-এ Planka deploy করুন: Postgres, Traefik, admin bootstrap variables এবং লগইন ভাঙা BASE_URL সেটিং ঠিকভাবে কনফিগার করার ধাপ দেখুন।
Self-hosting Planka ব্যবহার করলে যা পাবেন
Self-hosting Planka-এর মাধ্যমে আপনার দল এমন একটি Kanban board পাবে, যেখানে Trello-তে পরিচিত card, list এবং label model থাকবে এবং এটি আপনার নিয়ন্ত্রণাধীন VPS-এ চলবে। এখানে seat limit বা প্রতি-user billing নেই, কারণ একমাত্র খরচ হলো server। এই নির্দেশিকায় Docker Compose ব্যবহার করে Traefik-এর পেছনে এটি deploy করা হবে। ডেটার জন্য Postgres এবং ব্যবহারকারীদের upload করা প্রতিটি file-এর জন্য একটি named volume ব্যবহার করা হবে।
এই নির্দেশিকাটি এমন দুই থেকে পাঁচ সদস্যের দলের জন্য, যারা Trello-এর free tier ছাড়ছে। আপনি এখনও কোন board চালাবেন তা নির্ধারণ না করে থাকলে, আগে self-hosted Trello বিকল্পগুলোর তুলনা পড়ুন। এই নির্দেশিকায় ধরে নেওয়া হয়েছে যে সিদ্ধান্ত ইতিমধ্যে নেওয়া হয়েছে এবং এখানে শুধু deploy প্রক্রিয়া দেখানো হবে।
আপনার এমন একটি VPS প্রয়োজন যেখানে Compose plugin-সহ Docker Engine চলছে এবং VPS-টির দিকে নির্দেশ করা একটি DNS A record আছে। ওই server-এ TLS (transport layer security) termination করার জন্য একটি Traefik instance-ও আগে থেকেই চালু থাকতে হবে। Traefik এখনও সেট up না করা থাকলে, আগে বেশ কয়েকটি Compose app-এর সামনে একটি Traefik reverse proxy সেট up করুন। নিচের file অপরিচিত মনে হলে VPS-এর জন্য Docker Compose-এর মৌলিক বিষয়গুলো পড়ুন।
Planka-এর জন্য কতটা VPS প্রয়োজন?
প্রকল্পটি কোনো ন্যূনতম হার্ডওয়্যার নির্দিষ্ট করেনি। তাই আপনি যে সংখ্যাই পড়ুন, সেটিকে পরিমাপ করা প্রয়োজনীয়তা নয়, বরং শুরুর বিন্দু হিসেবে ধরুন। Hosting page-গুলোতে বারবার দেখা 2 vCPU এবং 4 GB configuration provider-এর আরামদায়ক default, প্রকল্পের পরিমাপ করা requirement নয়। পাঁচজন ব্যবহারকারী যে board-এ কাজ করেন, তার জন্য এটি যথেষ্ট উদার configuration।
আসলে অল্প কয়েকটি process-ই চলে: API এবং build করা frontend পরিবেশনের জন্য একটি Node.js process, এবং data সংরক্ষণের জন্য একটি Postgres process। Planka container-এর ভেতরে outgoing request filter করার জন্য আরও একটি ছোট proxy process চলে। 1 vCPU এবং 2 GB plan-এ দুই থেকে পাঁচজন ব্যবহারকারীর board চলতে পারে। অব্যবহৃত memory-এর বেশিরভাগই Postgres cache হিসেবে ব্যবহৃত হয়।
Memory নির্ধারণের আগে disk-এর আকার নির্ধারণ করুন, কারণ attachment-ই সবচেয়ে বেশি বাড়ে। এই paragraph-এর ওপর নির্ভর না করে নিজের instance পরিমাপ করুন:
docker stats --no-stream
docker system df -vপ্রথম command-টি প্রতিটি container-এর বর্তমান memory ও CPU ব্যবহার দেখায়। দ্বিতীয়টি প্রতিটি volume-এ কতটা space রয়েছে তা দেখায়। উভয় পরিমাপ স্বাভাবিক একটি working week শেষ হওয়ার পরে নিন, install করার দিন নয়। কারণ নিষ্ক্রিয় board আপনার team সম্পর্কে কোনো তথ্য দেয় না।
Compose ফাইল লিখুন
ডিরেক্টরিটি তৈরি করে সেটির ownership নিন, যাতে কখনো sudo-এর মাধ্যমে এই ফাইলগুলো সম্পাদনা করতে না হয়।
sudo mkdir -p /opt/planka
sudo chown "$USER":"$USER" /opt/planka
cd /opt/plankaCompose ফাইলের পাশে একটি .env ফাইলে secrets তৈরি করুন। Compose এই ফাইলটি স্বয়ংক্রিয়ভাবে পড়ে এবং মানগুলো প্রতিস্থাপন করে।
umask 077
{
printf 'SECRET_KEY=%s\n' "$(openssl rand -hex 64)"
printf 'POSTGRES_PASSWORD=%s\n' "$(openssl rand -hex 24)"
printf 'ADMIN_PASSWORD=%s\n' "$(openssl rand -hex 12)"
} > .env
chmod 600 .envopenssl rand -hex ইচ্ছাকৃতভাবে ব্যবহার করা হয়েছে। একটি hex string-এ শুধু digit এবং a থেকে f পর্যন্ত অক্ষর থাকে। তাই যে DATABASE_URL connection string-এ এটি বসানো হয়, সেটি নষ্ট করতে পারে না। slash বা at sign-যুক্ত base64 password connection error তৈরি করতে পারে, যার বার্তা দেখে ভুল hostname মনে হয়। এতে আপনার এক ঘণ্টা সময় নষ্ট হতে পারে। বৃহত্তর পদ্ধতিটি Compose ফাইলের বাইরে secrets রাখা-এ ব্যাখ্যা করা হয়েছে।
এখন docker-compose.yml। যেখানে যেখানে kanban.example.com আছে, উভয় জায়গায় সেটিকে আপনার নিজের hostname দিয়ে প্রতিস্থাপন করুন।
services:
planka:
image: ghcr.io/plankanban/planka:2.1.1
restart: unless-stopped
volumes:
- planka-data:/app/data
environment:
- BASE_URL=https://kanban.example.com
- DATABASE_URL=postgresql://planka:${POSTGRES_PASSWORD}@postgres/planka
- SECRET_KEY=${SECRET_KEY}
- TRUST_PROXY=true
- DEFAULT_ADMIN_EMAIL=you@example.com
- DEFAULT_ADMIN_PASSWORD=${ADMIN_PASSWORD}
- DEFAULT_ADMIN_NAME=Your Name
- DEFAULT_ADMIN_USERNAME=admin
networks:
- proxy
- internal
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.planka.rule=Host(`kanban.example.com`)"
- "traefik.http.routers.planka.entrypoints=websecure"
- "traefik.http.routers.planka.tls.certresolver=default"
- "traefik.http.services.planka.loadbalancer.server.port=1337"
depends_on:
postgres:
condition: service_healthy
postgres:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=planka
- POSTGRES_USER=planka
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
networks:
- internal
healthcheck:
test: ["CMD-SHELL", "pg_isready -U planka -d planka"]
interval: 10s
timeout: 5s
retries: 5
volumes:
planka-data:
db-data:
networks:
proxy:
external: true
internal:ওই ফাইলের চারটি সিদ্ধান্ত ব্যাখ্যা করা দরকার। কারণ সাধারণত মানুষ এগুলো পরিবর্তন করে পরে সমস্যায় পড়ে।
- Planka service-এ কোনো
ports:block নেই। Traefikproxynetwork-এর মাধ্যমে container-এ পৌঁছায়। তাই host-এ port 1337 কখনো publish করা হয় না। এটি publish করলে যে কেউ আপনার proxy ও certificate এড়িয়ে সরাসরি service-এ পৌঁছাতে পারত। loadbalancer.server.port=1337container-এর ভেতরের port নির্ধারণ করে। Planka port 1337-এ listen করে। Upstream example কেবল port-এ পৌঁছায়, কারণ সেটি port-টিকে host-এ map করে। এখানে কোনো host mapping নেই। তাই Traefik-কে container port জানিয়ে দিতে হয়।condition: service_healthyPostgres healthcheck-এর সঙ্গে কাজ করে। এটি না থাকলে database connection গ্রহণ করার আগে Planka start হয়, প্রথম query ব্যর্থ হয় এবং process বন্ধ হয়ে যায়। এতে crash loop-এর মতো দেখা যায়। এর কার্যপ্রণালি Compose healthcheck এবং startup ordering-এ ব্যাখ্যা করা হয়েছে।- Database service-এর নাম ইচ্ছাকৃতভাবে
postgresরাখা হয়েছে। Planka 2 নিজের outgoing request একটি internal filter-এর মাধ্যমে পাঠায়, যার default block list হলোlocalhost,postgres। Service-এর নাম পরিবর্তন করলে অজান্তেই সেই তালিকা থেকে আপনার database বাদ পড়বে।
কিছু start করার আগে Compose আপনার secrets দেখতে পাচ্ছে কি না পরীক্ষা করুন:
docker compose config | grep -E 'image:|BASE_URL|POSTGRES_USER'এতে .env-এর মান ইতিমধ্যে প্রতিস্থাপিত অবস্থায় ফাইলটি দেখাবে। কোনো মান খালি থাকলে Compose .env ফাইলটি পড়ছে না। সাধারণত আপনি অন্য কোনো directory থেকে command চালালে এমন হয়।
অ্যাডমিন bootstrap variable-গুলো আসলে কী করে
Planka 1.13 থেকে আপনার জন্য কোনো administrator তৈরি করা হয় না। তাই নতুন database-এ লগ ইন করার মতো কেউ থাকে না। DEFAULT_ADMIN_* group এটি সমাধানের দুটি উপায়ের একটি।
শুরু হওয়ার সময় Planka DEFAULT_ADMIN_EMAIL-এর সঙ্গে মিলে এমন user খোঁজে। এমন user না থাকলে, এর সঙ্গে দেওয়া password, display name এবং username ব্যবহার করে একটি user তৈরি করে। খালি database-এ প্রথম boot-এর সময় এটি ঘটে। তাই এই variable-গুলো account manage করে না; বরং একটি account bootstrap করে।
DEFAULT_ADMIN_EMAIL আরও একটি কাজ করে, যা অনেকের নজর এড়ায়। এই variable সেট থাকা অবস্থায়, এটি যে account-কে নির্দেশ করে, সেটি interface থেকে কেউ edit বা delete করতে পারে না। এটি lock-out প্রতিরোধ করে। এই কারণেই UI-তে ওই account-এর নাম বা email address পরিবর্তন করা যায় না। Variable-টি সরিয়ে restart করলে account-টি সাধারণ admin হয়ে যায়। তখন অন্য যেকোনো account-এর মতো এটি edit করা যায়।
Password-এর লাইনটিই সবচেয়ে সতর্কতার বিষয়। environment:-এর অধীনে থাকা যেকোনো কিছু এমন ব্যক্তি পড়তে পারে, যিনি container-এ docker inspect চালাতে পারেন। তাই DEFAULT_ADMIN_PASSWORD সেখানে স্থায়ীভাবে রাখা উচিত নয়। লগ ইন করুন, interface-এ password পরিবর্তন করুন, ওই লাইনটি মুছে দিন, তারপর আবার docker compose up -d চালান।
আরও পরিষ্কার পদ্ধতিতে variable-গুলো পুরোপুরি বাদ দেওয়া হয়। সম্পূর্ণ DEFAULT_ADMIN_* group-টি comment out করুন, তারপর ইন্টার্যাক্টিভভাবে account তৈরি করুন:
docker compose run --rm planka npm run db:create-admin-userএটি email, password, display name এবং ঐচ্ছিক username-এর জন্য prompt দেখায়। এরপর user-টিকে সরাসরি database-এ লিখে। Password কখনো Compose file বা container environment-এ যায় না। VPS-এ একাধিক ব্যক্তির shell access থাকলে এই পদ্ধতি ব্যবহার করুন। depends_on-এর কারণে command-টি আগে Postgres start করে। তাই আগে কখনো চালু না হওয়া stack-এও এটি কাজ করে।
দুটি পদ্ধতির যেকোনোটি ব্যবহার করলে Planka-এর password আপনাকেই হাতে manage করতে হবে। আপনার team যদি ইতিমধ্যে চতুর্থ set of credentials সংগ্রহ করে থাকে, তাহলে Planka-এর login একটি OIDC provider-এর কাছে অর্পণ করতে পারেন। যেমন নিজস্ব single sign-on server হিসেবে চলমান Authentik ব্যবহার করা যায়। Provider বন্ধ থাকলে ব্যবহারের জন্য bootstrap admin-কে break-glass account হিসেবে রেখে দিন।
hostname-এর সঙ্গে না মিললে কেন BASE_URL login নষ্ট করে
BASE_URL হলো scheme-সহ এবং শেষে slash ছাড়া browser-এ ব্যবহারকারীরা যে সম্পূর্ণ address লেখেন। এই stack-এর জন্য সেটি হলো https://kanban.example.com। Planka এই value থেকে নিজস্ব link এবং WebSocket connection তৈরি করে। তাই ভুল BASE_URL হলে স্পষ্ট কোনো error দেখা যায় না। বরং page load হয়, কিন্তু loading কখনো শেষ হয় না।
সাধারণ ঘটনাটি এমন: আপনি upstream example copy করেন, BASE_URL=http://localhost:3000 অপরিবর্তিত রাখেন, এবং নিজের প্রকৃত domain-এ HTTPS দিয়ে site-এ প্রবেশ করেন। Login form submit হয় এবং credentials গ্রহণ করা হয়। কিন্তু board দেখা যায় না। Browser developer console খুললে /socket.io/-এর request ব্যর্থ হতে দেখবেন। কারণ client-কে localhost:3000-এ live connection খুলতে বলা হয়েছে, কিন্তু আপনার laptop-এ সেই address-এর কোনো অস্তিত্ব নেই।
TRUST_PROXY=true একই সমস্যার অন্য অংশ। Planka-এর সামনে Traefik রয়েছে। তাই Docker network-এর ভেতরে প্রতিটি request proxy-এর address থেকে plain HTTP-তে Planka-এ পৌঁছায়। TRUST_PROXY ছাড়া app Traefik সেট করা X-Forwarded-Proto এবং X-Forwarded-For header উপেক্ষা করে। ফলে connection-কে insecure মনে হয় এবং প্রতিটি client-কে একই shared IP address হিসেবে গণ্য করা হয়। এটি সেট করা থাকলে app ওই header পড়ে এবং browser-এর সঙ্গে scheme নিয়ে সামঞ্জস্য রাখে।
Traefik কোনো অতিরিক্ত configuration ছাড়াই WebSocket proxy করে। এই setup-এ Traefik বেছে নেওয়ার এটি একটি কারণ। nginx-এ socket.io-এর জন্য proxy_set_header Upgrade $http_upgrade এবং proxy_set_header Connection "upgrade" বহনকারী নিজস্ব location block প্রয়োজন। তা না হলে ভিন্ন কারণে একইভাবে spinner আটকে থাকে।
পরে board-টি নতুন hostname-এ সরালে দুটি বিষয় একসঙ্গে পরিবর্তন করতে হবে: BASE_URL value এবং Traefik-এর Host() rule। একটিতে পরিবর্তন করে অন্যটি ভুলে গেলে আবার spinner আটকে যাবে। https://example.com/planka-এর মতো subpath থেকে Planka চালানো version 2.1.0 থেকে সমর্থিত, যা March 2026-এ প্রকাশিত হয়েছে। পুরোনো tag-এ Planka-এর জন্য আলাদা subdomain ব্যবহার করুন।
Planka কোথায় attachment ও avatar সংরক্ষণ করে
Planka 2 ব্যবহারকারী upload করা সবকিছু container-এর ভেতরের একটি path-এর অধীনে সংরক্ষণ করে: /app/data। Attachment, user avatar এবং board background image—সবই এখানে থাকে। Version 1-এ তিনটি আলাদা directory ব্যবহার করা হতো। তাই পুরোনো লেখা থেকে কপি করা Compose file এমন path mount করে, যেগুলো আর নেই। ফলে প্রকৃত data directory unmounted থেকে যায়।
এই একটি mount-ই upgrade-এর পর board টিকে থাকা এবং বড় ধরনের সমস্যায় পড়ার মধ্যে পার্থক্য তৈরি করে। /app/data কোনো volume-এ না থাকলে upload করা file container-এর writable layer-এ যায়। Container পুনরায় তৈরি হলে সেই layer নষ্ট হয়ে যায়। Image tag পরিবর্তন করলেই container পুনরায় তৈরি হয়। Board দেখতে স্বাভাবিক থাকে, সব card-ও থাকে, কিন্তু প্রতিটি attachment link কাজ করে না। কারণ database row-গুলো এমন file-এর দিকে নির্দেশ করে, যেগুলো আর নেই।
উপরের Compose file-এর named volume এই সমস্যা প্রতিরোধ করে। Bind mount-ও ব্যবহার করা যায়। এতে সাধারণ tool দিয়ে file backup করা সহজ হয়। তবে এর জন্য একটি অতিরিক্ত ধাপ প্রয়োজন। Container-এর ভেতরের Node process UID 1000 হিসেবে চলে। তাই root-এর মালিকানাধীন host directory ব্যবহার করলে প্রথম upload-এর সময় permission error দেখা যায়:
sudo chown -R 1000:1000 /opt/planka/dataদুটি পদ্ধতির পার্থক্য bind mount ও named volume-এর তুলনা-এ বিস্তারিত ব্যাখ্যা করা হয়েছে।
আপনার plan-এ attachment-এর পরিমাণ disk-এর সীমা ছাড়িয়ে গেলে Planka S3-compatible storage-এও এগুলো লিখতে পারে। এর জন্য S3_ENDPOINT, S3_BUCKET এবং সংশ্লিষ্ট key variable ব্যবহার করতে হয়। এটি hosted bucket অথবা অন্য একটি server-এ থাকা self-hosted MinIO object store-এর দিকে নির্দেশ করতে পারে। Team board পূরণ করা শুরু করার আগে এই সিদ্ধান্ত নিন, কারণ এই setting শুধু নতুন upload-এর ক্ষেত্রে প্রযোজ্য।
স্ট্যাক চালু করে কাজ করেছে কি না পরীক্ষা করুন
docker compose pull
docker compose up -d
docker compose psdocker compose ps-তে postgres হিসেবে healthy এবং planka হিসেবে running দেখা উচিত। Planka যদি বারবার restart হয়, তাহলে প্রথমে database connection পরীক্ষা করুন, app নয়।
docker compose logs -f plankaপ্রথম boot সফল হলে database migration চলে এবং এরপর server port 1337-এ listening করছে বলে জানায়। Log-এর ওপর নির্ভর না করে সরাসরি Postgres-কে জিজ্ঞাসা করে schema সত্যিই তৈরি হয়েছে কি না নিশ্চিত করুন:
docker compose exec postgres psql -U planka -d planka -c '\dt'Table list-এ board এবং card থাকলে বোঝা যায় migration চলেছে। "Did not find any relations" অর্থ Planka কখনও database-এ connect করতে পারেনি। তাই আপনার .env-এর POSTGRES_USER এবং POSTGRES_PASSWORD মানের সঙ্গে DATABASE_URL তুলনা করুন।
এরপর VPS থেকে নয়, নিজের machine থেকে route পরীক্ষা করুন:
curl -I https://kanban.example.comHTTP/2 200 অর্থ Traefik একটি certificate ধরে রেখেছে এবং container-এ পৌঁছাতে পারছে। Traefik থেকে 404 এলে বোঝায় router label মেলেনি। এর সবচেয়ে সাধারণ কারণ হলো container-টি proxy network-এ যুক্ত নয়। এখন site খুলে admin account দিয়ে log in করুন।
প্রতিটি version bump-এর আগে pg_dump নিন
আপনার board-এর ডেটা দুটি আলাদা store-এ থাকে। তাই backup-এ উভয়টিই অন্তর্ভুক্ত করতে হবে: Postgres database এবং planka-data volume। Stack চালু থাকা অবস্থায় database dump নিন।
docker compose exec -T postgres pg_dump -U planka -d planka > "planka-db-$(date +%F).sql"-T ঐচ্ছিক নয়। এটি না থাকলে Compose একটি pseudo-terminal বরাদ্দ করে। Terminal layer stream-এর line ending পুনর্লিখন করে। ফলে এমন একটি dump file তৈরি হয়, যা restore করার সময় মাঝপথে ব্যর্থ হয়। এই ব্যর্থতা কয়েক সপ্তাহ পরে দেখা দিতে পারে। সেটিই সবচেয়ে খারাপ সময়।
এরপর uploads-এর backup নিন। প্রথমে প্রকৃত volume name খুঁজে নিন। কারণ Compose project directory name-এর সঙ্গে prefix যোগ করে volume name তৈরি করে।
docker volume ls | grep planka
docker run --rm -v planka_planka-data:/data -v "$PWD":/backup alpine \
tar czf /backup/planka-files-$(date +%F).tgz -C /data .Project-এর repository-তে docker-backup.sh এবং docker-restore.sh-ও আছে। Official documentation-এ এগুলো nightly cron job-এ চালানোর নির্দেশ দেওয়া হয়েছে। যেকোনো একটি পদ্ধতি ব্যবহার করতে পারেন। তবে এমন backup রাখা ঠিক নয়, যা কখনো restore করে পরীক্ষা করা হয়নি। তাই একবার এটি একটি scratch VPS-এ restore করুন। তারপর নিশ্চিত করুন যে আপনি লগ ইন করতে এবং একটি attachment খুলতে পারছেন।
প্রতিটি version change-এর ঠিক আগে dump চালান। গত রাতের backup এবং যে migration চালাতে যাচ্ছেন তার ঠিক আগের backup এক জিনিস নয়।
ট্যাগ নির্দিষ্ট করে দিন এবং release notes পড়ুন
ওই ফাইলে থাকা দুটি image tag ইচ্ছাকৃতভাবে নির্দিষ্ট করা হয়েছে।
ghcr.io/plankanban/planka:2.1.1 একটি নির্দিষ্ট release, যা August 2026 অনুযায়ী বর্তমান। latest upstream নতুন release প্রকাশ করলে পরিবর্তিত হয়। তাই নিয়মিত docker compose pull-এর মাধ্যমে এমন সময়ে schema migration চলে আসতে পারে, যখন আপনি তা বেছে নেননি। ওই সংখ্যাটি পরিবর্তন করার আগে release notes পড়ুন। Breaking change এবং security fix সেখানেই বর্ণনা করা হয়। Version 2.0.3 একটি security release হিসেবে প্রকাশিত হয়েছিল। এ ধরনের পরিবর্তন দুর্ঘটনাক্রমে গ্রহণ না করে আগে পড়ে নেওয়াই উচিত।
postgres:16-alpine-কে major version-এ pin করার কারণ আরও গুরুত্বপূর্ণ। Postgres তার data directory এমন একটি format-এ লেখে, যা major version-এর সঙ্গে যুক্ত। অন্য major version দিয়ে লেখা directory server খুলতে অস্বীকার করে। postgres:latest লিখে tag-কে 17-এ যেতে দিলে container start হবে না:
FATAL: database files are incompatible with server
DETAIL: The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 17.কোনো data হারায় না, এবং restart করলেও সমস্যার সমাধান হয় না। নতুন Postgres major version-এ যেতে হলে পুরোনো version থেকে dump নিতে হবে এবং নতুন version-এর fresh data directory-তে restore করতে হবে। এটি stack বন্ধ রেখে পরিকল্পনা করে করতে হয়। এটি image pull-এর পার্শ্বপ্রতিক্রিয়া নয়।
আপনি যদি নতুন করে শুরু না করে কোনো বিদ্যমান Planka 1.x install স্থানান্তর করেন, তাহলে সেই upgrade-এর জন্য project documentation-এ আলাদা documented procedure রয়েছে। আগে নেওয়া backup ছাড়া version 1-এ ফিরে যাওয়ার কোনো উপায় নেই।
ব্যর্থতার ধরন এবং যে বার্তাগুলো দেখবেন
Planka বারবার restart হয় এবং log-এ database-এর নাম দেখা যায়। DATABASE_URL-এর credentials Postgres environment-এর সঙ্গে মেলে না। মনে রাখুন, POSTGRES_PASSWORD শুধু data directory প্রথমবার initialize করার সময় প্রয়োগ করা হয়। তাই প্রথম boot ব্যর্থ হওয়ার পরে variable ঠিক করলেও কোনো পরিবর্তন হবে না। db-data volume সরিয়ে আবার শুরু করতে হবে।
Login সফল হয়, কিন্তু board কখনো load হয় না। BASE_URL browser bar-এ থাকা address-এর সঙ্গে মেলে না, অথবা TRUST_PROXY অনুপস্থিত। Browser console-এ /socket.io/-এ ব্যর্থ request দেখা যায়।
অন্য সবকিছু কাজ করলেও upload ব্যর্থ হয়। Bind mount-এর মালিক root। Host-এর directory-তে sudo chown -R 1000:1000 চালিয়ে container restart করুন।
Upgrade-এর পরে attachment হারিয়ে গেছে। /app/data কোনো volume-এ ছিল না। তাই file-গুলো container layer-এ ছিল, যা upgrade-এর সময় প্রতিস্থাপিত হয়েছে। Backup থেকে file restore করুন। এরপর image tag আবার পরিবর্তন করার আগে volume যোগ করুন।
Traefik 404 ফেরত দেয়। Container-টি proxy network-এ নেই, অথবা Host() rule আপনার DNS record-এর সঙ্গে মেলে না। Substitution-এর পরে label দেখতে docker compose config ব্যবহার করুন। এখানেই সাধারণত typo দেখা যায়।
Notification বা webhook কখনো পৌঁছায় না। Planka 2 outgoing HTTP request একটি internal filter-এর মাধ্যমে পাঠায়। Default block list-এ localhost এবং postgres অন্তর্ভুক্ত থাকে। একই host-এর অন্য container-এ পাঠানো webhook নকশা অনুযায়ী blocked হতে পারে। Filter সরিয়ে না দিয়ে OUTGOING_ALLOWED_HOSTS সমন্বয় করুন।
চালু হওয়ার পরে পরিচালনাগত কাজ কম। Release note পর্যবেক্ষণ করুন এবং প্রতিটি upgrade-এর আগে database dump নিন। restart: unless-stopped-এর কারণে reboot-এর পরে stack নিজে থেকেই ফিরে আসে, যদি Docker service-টি boot-এর সময় enabled থাকে। তা না হলে reboot-এর পরে ফিরে আসা Compose stack অংশে সংশ্লিষ্ট পরিস্থিতিগুলো ব্যাখ্যা করা হয়েছে।
FAQ
লগ ইন করার পর Planka অনির্দিষ্টকাল লোড হতে থাকে কেন?
প্রমাণপত্র গ্রহণ করা হয়েছে, কিন্তু live connection তৈরি হয়নি। Planka BASE_URL থেকে তার WebSocket URL তৈরি করে। তাই সাইটে https://kanban.example.com ঠিকানায় প্রবেশ করার সময়ও যদি ওই variable-এ http://localhost:3000 লেখা থাকে, browser এমন একটি address-এ socket খোলার চেষ্টা করে, যা আপনার মেশিনে নেই। Developer console-এ /socket.io/-এর ব্যর্থ request দেখা যায়। BASE_URL-এ trailing slash ছাড়া সঠিক public address নির্ধারণ করুন। Reverse proxy থেকে আসা X-Forwarded-Proto header যেন app গ্রহণ করে, সে জন্য TRUST_PROXY=true যোগ করুন। এরপর docker compose up -d চালান।
প্রথম Planka admin user কীভাবে তৈরি করব?
Version 1.13 থেকে কোনো administrator স্বয়ংক্রিয়ভাবে তৈরি হয় না। হয় সংশ্লিষ্ট password, name এবং username variable-সহ DEFAULT_ADMIN_EMAIL নির্ধারণ করে stack চালু করুন, অথবা docker compose run --rm planka npm run db:create-admin-user চালিয়ে prompt-এর উত্তর দিন। Shared server-এ interactive command ব্যবহার করাই নিরাপদ, কারণ password কখনও container environment-এ প্রবেশ করে না, যেখানে docker inspect সেটি পড়তে পারে। পরে DEFAULT_ADMIN_EMAIL নির্ধারণ করে রাখলে interface থেকে ওই account পরিবর্তন বা মুছে ফেলা বন্ধ থাকে।
Planka attachment এবং avatar কোথায় সংরক্ষণ করে?
Planka 2-এ attachment, user avatar এবং board background-সহ সব uploaded file container-এর ভিতরে /app/data-এর অধীনে থাকে। ওই path-টি একটি named volume-এ mount করুন। এটি unmount করা থাকলে file-গুলো container-এর writable layer-এ থাকে। পরেরবার container পুনরায় তৈরি হলে সেগুলো মুছে যায়। প্রতিটি image upgrade-এর সময় container পুনরায় তৈরি হয়। Bind mount-ও ব্যবহার করা যায়। তবে Node process UID 1000 হিসেবে চলে। তাই host-এর directory-তে sudo chown -R 1000:1000 চালান, নইলে permission error-এর কারণে upload ব্যর্থ হবে।
একটি self-hosted Planka-এর কত RAM প্রয়োজন?
Project কোনো নির্দিষ্ট hardware floor প্রকাশ করে না। Hosting page-গুলোতে বারবার দেখা 2 vCPU এবং 4 GB figure provider-এর default, কোনো পরিমাপের ফল নয়। ছোট board-এর জন্য এটি প্রয়োজনের চেয়ে বেশি। একটি Node process এবং একটি Postgres process-ই পুরো workload। তাই 1 vCPU এবং 2 GB plan-এ দুই থেকে পাঁচজনের team চলতে পারে। স্বাভাবিক এক সপ্তাহ ব্যবহারের পর docker stats --no-stream চালান এবং নিজের পরিমাপ অনুযায়ী আকার নির্ধারণ করুন। Memory-এর চেয়ে disk বেশি মনিটর করুন, কারণ attachment-ই দ্রুত বাড়ে।
Data না হারিয়ে Planka কীভাবে upgrade করব?
Upgrade-এর ঠিক আগে database dump করুন এবং uploads volume archive করুন। গত রাতের schedule-এর backup-এর ওপর নির্ভর করবেন না। docker compose exec -T postgres pg_dump -U planka -d planka > planka-db.sql ব্যবহার করুন এবং -T রেখে দিন, যাতে pseudo-terminal redirected output নষ্ট না করে। যে version-গুলো বাদ পড়ছে, প্রতিটির release notes পড়ুন। Image tag latest না রেখে নির্দিষ্ট release tag নির্ধারণ করুন। এরপর docker compose pull এবং docker compose up -d চালিয়ে migration-এর log monitor করুন। Postgres tag তার major version-এ pinned রাখুন, কারণ অন্য major version-এ লেখা data directory server খুলতে অস্বীকার করে।