LinkBreeze কীভাবে নিজের সার্ভারে হোস্ট করবেন
Docker Compose ও Caddy ব্যবহার করে LinkBreeze সেটআপ করার পূর্ণাঙ্গ নির্দেশিকা। এতে পিন করা ইমেজ ট্যাগ, কুকিহীন ট্র্যাকিং এবং একটি মাত্র SQLite ভলিউম দিয়ে সাইট চালানোর উপায় রয়েছে।
LinkBreeze কী
LinkBreeze হলো Linktree-এর একটি self-hosted বিকল্প: এটি একটি Docker container যা একটি public link-in-bio পেজ এবং একটি admin dashboard প্রদান করে, যেখানে সমস্ত ডেটা একটি মাত্র SQLite ফাইলে সংরক্ষিত থাকে। এটি MIT লাইসেন্সপ্রাপ্ত, TypeScript-এ Next.js ব্যবহার করে লেখা এবং ghcr.io/manak-hash/linkbreeze হিসেবে প্রকাশিত। এটি চালানোর জন্য আপনার একটি VPS, একটি domain (যার A record ঐ VPS-এর দিকে নির্দেশ করা), 80 ও 443 port খোলা থাকা এবং Docker Engine-এর সাথে Compose plugin প্রয়োজন।
এই নির্দেশিকাটি এমন একটি deployment কভার করে যা repository-টি সরাসরি সমর্থন করে: একটি reverse proxy-র পেছনে Docker Compose, যা নিজস্ব certificate সংগ্রহ করে। এটি কী কী কারণে অকেজো হতে পারে তাও এখানে আলোচনা করা হয়েছে, কারণ একটি link-in-bio হলো এমন একটি public URL যা অন্যরা ক্লিক করে, এবং এটি অকেজো হলে আপনি ভিজিটর হারাবেন।
এর যেকোনো কিছু শুরু করার আগে, এই প্রজেক্টটি কতটা নতুন সে সম্পর্কে পরিষ্কার ধারণা রাখুন।
LinkBreeze কি পাবলিক প্রোফাইল লিংকের জন্য যথেষ্ট পরিপক্ক?
আগস্ট 2026 পর্যন্ত এই রিপোজিটরিতে 178টি স্টার, 17টি ফর্ক এবং একজন মাত্র মেইনটেইনার রয়েছেন। প্রথম ট্যাগড রিলিজ, v1.0.0, 1 জুলাই 2026-এ প্রকাশিত হয়েছে। এটি কয়েক বছর পুরনো নয়, বরং মাত্র কয়েক সপ্তাহ পুরনো একটি প্রজেক্ট।
The data behind this chart
[
{
"week": "2026-06-29",
"releases": 3,
"cumulative": 3
},
{
"week": "2026-07-06",
"releases": 3,
"cumulative": 6
},
{
"week": "2026-07-13",
"releases": 1,
"cumulative": 7
},
{
"week": "2026-07-20",
"releases": 2,
"cumulative": 9
},
{
"week": "2026-07-27",
"releases": 3,
"cumulative": 12
},
{
"week": "2026-08-03",
"releases": 2,
"cumulative": 14
},
{
"week": "2026-08-10",
"releases": 3,
"cumulative": 17
}
]v1.0.0-এর পর থেকে এই প্রজেক্টটি 17 টি ট্যাগড রিলিজ প্রকাশ করেছে, যা 7 ক্যালেন্ডার সপ্তাহ জুড়ে বিস্তৃত। এই গাইডের লেখা চলাকালীন শেষ সপ্তাহটি চলমান ছিল এবং তাতেই 3 টি রিলিজ ছিল।
এটিকে দুটি আলাদা তথ্য হিসেবে দেখুন। মেইনটেইনার সক্রিয় এবং বাগগুলো কয়েক দিনের মধ্যেই সমাধান করা হয়। তবে স্কিমা এবং ডিফল্ট সেটিংস এখনো পরিবর্তনশীল, তাই আপনি যদি কোনো ইনস্ট্যান্স ডেপ্লয় করে ভুলে যান, তবে তা মূল কোড থেকে অনেক পিছিয়ে পড়বে।
লাইসেন্স আপনাকে সবচেয়ে খারাপ পরিস্থিতি থেকে সুরক্ষা দেয়। MIT লাইসেন্স, একটি কন্টেইনার ইমেজ এবং আপনার নিজের ডিস্কে থাকা একটি SQLite ফাইল থাকার অর্থ হলো, যদি ডেভেলপমেন্ট বন্ধও হয়ে যায়, আপনার বর্তমান সেটআপটি সচল থাকবে। তবে এটি আপনাকে এমন একটি পাবলিক-ফেসিং ওয়েব অ্যাপ থেকে সুরক্ষা দেয় না যা নিরাপত্তা আপডেট পাওয়া বন্ধ করে দিয়েছে, যা সময়ের সাথে সাথে একটি দায়বদ্ধতায় পরিণত হতে পারে। এটিকে এমন কিছু হিসেবে ডেপ্লয় করুন যা আপনি নিয়মিত আপডেট রাখবেন এবং প্রথম দিন থেকেই নিচের ব্যাকআপ রুটিনটি কার্যকর রাখুন।
ইমেজ ট্যাগ পিন করুন এবং latest ব্যবহার করবেন না
রিলিজ ওয়ার্কফ্লো প্রতিটি ভার্সনের জন্য ঠিক দুটি ট্যাগ পুশ করে: latest এবং v বাদ দিয়ে ভার্সন নম্বরটি। তাই v1.2.7 রিলিজের জন্য পিন করা ট্যাগটি হলো ghcr.io/manak-hash/linkbreeze:1.2.7। :v1.2.7 লিখলে কোনো ইমেজ পুল হয় না এবং Docker manifest unknown রিপোর্ট করে, কারণ এই ট্যাগটি কখনোই পুশ করা হয়নি।
এটি পিন করুন কারণ latest পরিবর্তিত হয়। উপরের চার্টের গতি অনুযায়ী, latest-এর বিপরীতে একটি docker compose pull হলো আপনার ব্যবহারকারীদের ব্যবহৃত পেজের একটি অনিরীক্ষিত আপগ্রেড। পিন করা ট্যাগ ব্যবহার করলে, আপনি ফাইলটি এডিট করলেই কেবল আপগ্রেডটি কার্যকর হবে।
ইমেজ সম্পর্কে আরও একটি বিষয়। রিলিজ ওয়ার্কফ্লো কোনো platforms: সেটিং ছাড়াই বিল্ড হয়, তাই প্রকাশিত ইমেজটি শুধুমাত্র linux/amd64। একটি arm64 হোস্ট মেশিনে এটি পুল করলে no matching manifest for linux/arm64/v8 in the manifest list entries এর কারণে ব্যর্থ হবে। আপনি যদি x86 এর পরিবর্তে একটি ARM VPS ব্যবহার করেন, তবে সরাসরি সেই বক্সে ইমেজটি বিল্ড করুন:
git clone --branch v1.2.7 --depth 1 https://github.com/Manak-hash/LinkBreeze.git
cd LinkBreeze
docker build -t linkbreeze:1.2.7 .এরপর নিচের compose ফাইলে ইমেজের নাম হিসেবে linkbreeze:1.2.7 ব্যবহার করুন।
স্বয়ংক্রিয় TLS সহ Caddy-এর পেছনে LinkBreeze ডেপ্লয় করা
Caddy স্বয়ংক্রিয়ভাবে Let's Encrypt থেকে সার্টিফিকেট সংগ্রহ ও নবায়ন করে, তাই TLS (transport layer security)-এর জন্য আলাদা কোনো পদক্ষেপের প্রয়োজন নেই। পুরো ডেপ্লয়মেন্টটি একটি ডিরেক্টরিতে তিনটি ফাইলের মাধ্যমে সম্পন্ন হয়।
প্রথমে সিক্রেট জেনারেট করুন:
mkdir -p ~/linkbreeze && cd ~/linkbreeze
printf 'SECRET_KEY=%s\n' "$(openssl rand -hex 32)" > .env
chmod 600 .envSECRET_KEY অ্যাডমিন সেশন কুকি সাইন করে এবং অ্যানালিটিক্স ভিজিটর হ্যাশ সল্ট করে। রিপোজিটরিতে প্রকাশিত compose ফাইলে এটি ডিফল্টভাবে ${SECRET_KEY:-changeme-in-production} সেট করা থাকে, তাই আপনি যদি এই ধাপটি বাদ দেন, তবে আপনার ইনস্ট্যান্সটি এমন একটি সেশন সাইনিং কি ব্যবহার করবে যা GitHub-এ সবার জন্য উন্মুক্ত। প্রথমবার স্টার্ট করার আগেই এটি সেট করুন, কারণ পরে পরিবর্তন করলে আপনি লগ-আউট হয়ে যাবেন এবং অ্যানালিটিক্স সল্ট রিসেট হয়ে যাবে।
docker-compose.yml লিখুন:
services:
linkbreeze:
image: ghcr.io/manak-hash/linkbreeze:1.2.7
restart: unless-stopped
volumes:
- linkbreeze-data:/app/data
environment:
- DATABASE_PATH=/app/data/linkbreeze.db
- SECRET_KEY=${SECRET_KEY}
- BASE_URL=https://links.example.com
networks:
- linkbreeze-net
caddy:
image: caddy:2-alpine
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
networks:
- linkbreeze-net
networks:
linkbreeze-net:
volumes:
linkbreeze-data:
caddy-data:
caddy-config:BASE_URL ঐচ্ছিক হলেও এটি সেট করা ভালো: এটি অ্যাপটিকে তার প্রকৃত পাবলিক অ্যাড্রেস সম্পর্কে জানায়, যাতে ভুল Host হেডারসহ আসা কোনো অনুরোধ অ্যাপটিকে অন্য কারো ডোমেইনের লিঙ্ক তৈরি করতে বাধ্য করতে না পারে।
এর পাশে আপনার নিজস্ব ডোমেইনসহ Caddyfile লিখুন:
links.example.com {
encode zstd gzip
reverse_proxy linkbreeze:3000
}Caddy ডিফল্টভাবে প্রক্সি করা অনুরোধগুলোতে X-Forwarded-For এবং X-Forwarded-Proto সেট করে, যার ওপর অ্যানালিটিক্স নির্ভর করে। এটি চালু করুন:
docker compose up -d
docker compose ps
docker compose logs -f caddydocker compose ps কমান্ডটি চালালে LinkBreeze কন্টেইনারটিকে healthy হিসেবে দেখানো উচিত। ইমেজটিতে নিজস্ব হেলথচেক wget --spider -q http://127.0.0.1:3000/api/health অন্তর্ভুক্ত আছে, তাই আপনাকে আলাদা করে কিছু যোগ করতে হবে না। রিপোজিটরির নিজস্ব Caddy উদাহরণ থেকে হেলথচেক কপি করবেন না: সেটি curl কল করে, কিন্তু ইমেজটি node:22-alpine-এর ওপর ভিত্তি করে তৈরি, যাতে busybox wget আছে কিন্তু curl নেই। সেই কন্টেইনারটি সঠিকভাবে পেজ সার্ভ করা সত্ত্বেও unhealthy রিপোর্ট করবে।
ব্রাউজারে https://links.example.com খুলুন। প্রথম ভিজিটে আপনি /setup-এ সেটআপ উইজার্ড দেখতে পাবেন, যা একক অ্যাডমিন অ্যাকাউন্ট তৈরি করবে। এরপর ড্যাশবোর্ড থাকবে /dashboard-এ এবং লগইন ফর্ম থাকবে /login-এ। সেই অ্যাকাউন্টটি এই ইনস্ট্যান্সের জন্য লোকাল এবং অ্যাপটিতে কোনো সিঙ্গেল সাইন-অন হুক নেই। তাই আপনি যদি চান যে ড্যাশবোর্ডটি আপনার হোস্ট করা অন্যান্য সার্ভিসের মতো একই লগইন ব্যবহার করুক, তবে আপনাকে এর সামনে একটি ফরওয়ার্ড অথ প্রক্সি ব্যবহার করতে হবে, যেমন একটি self-hosted Authentik।
লক্ষ্য করুন compose ফাইলটি কী করে না: এটি কখনোই port 3000 পাবলিশ করে না। শুধুমাত্র Caddy পাবলিক ইন্টারফেসে লিসেন করে। যদি Compose ফাইলের সিনট্যাক্স আপনার কাছে নতুন হয়, তবে VPS-এর জন্য Docker Compose-এর মৌলিক বিষয়গুলো এই ফাইলের প্রয়োজনীয় অংশগুলো ব্যাখ্যা করে। আর যদি আপনি আগে থেকেই সামনে অন্য কিছু ব্যবহার করে থাকেন, তবে Nginx, Caddy এবং Traefik-এর তুলনা কী কী পরিবর্তন করতে হবে তা ব্যাখ্যা করে। রিপোজিটরিতে Certbot-সহ Nginx, Traefik এবং Cloudflare টানেলের জন্য কার্যকরী উদাহরণ দেওয়া আছে।
আপনার ডেটা যেখানে থাকে এবং ব্যাকআপে যা থাকা আবশ্যক
DATABASE_PATH নির্দেশ করে /app/data/linkbreeze.db-কে। আপলোড করা অবতার এবং লিঙ্কের থাম্বনেইলগুলো এর পাশেই /app/data/uploads-এ লেখা হয়। উভয়ই linkbreeze-data নামক ভলিউমে থাকে, তাই ব্যাকআপের একক হলো ভলিউম, শুধুমাত্র ডেটাবেস ফাইল নয়। আপলোড ডিরেক্টরি ছাড়া ফাইলটি রিস্টোর করলে পৃষ্ঠার প্রতিটি ছবি 404 এরর দেখাবে।
বাকি সবকিছু মূলত সেই একটি ডেটাবেসেই থাকে: পেজ, লিঙ্ক, সেটিংস, থিম, ইমেইল সাবস্ক্রাইবার এবং অ্যানালিটিক্স রো।
কন্টেইনার বন্ধ থাকা অবস্থায় কপি নিন:
docker compose stop linkbreeze
docker compose cp linkbreeze:/app/data ./backup-$(date +%F)
docker compose start linkbreezeপ্রথমে বন্ধ করুন, কারণ কোনো প্রসেস যখন SQLite ডেটাবেসে লিখছে তখন সেটি কপি করলে অসম্পূর্ণ ট্রানজ্যাকশন ক্যাপচার হতে পারে এবং কপিটি তখন করাপ্ট ফাইল হিসেবে ওপেন হবে। কপি চলার সময় পেজটি অফলাইন থাকে। রিস্টোর করার প্রক্রিয়াটি উল্টো:
docker compose stop linkbreeze
docker compose cp ./backup-2026-08-14/. linkbreeze:/app/data
docker compose start linkbreeze
docker compose logs -f linkbreezeড্যাশবোর্ডটি একটি JSON এক্সপোর্টও অফার করে, যা /api/backup থেকে linkbreeze-backup-YYYY-MM-DD.json হিসেবে পরিবেশন করা হয়। এতে প্রোফাইল, লিঙ্ক, সেটিংস এবং সেভ করা থিম থাকে। এটি অ্যানালিটিক্স হিস্ট্রি, ইমেইল সাবস্ক্রাইবার বা আপলোড করা ছবি বহন করে না, এবং এটি রিস্টোর করলে ফাইলটি ইনসার্ট করার আগে ওই চারটি টেবিলের বর্তমান রো মুছে ফেলা হয়। হোস্ট পরিবর্তন বা এডিটিংয়ের ভুল সংশোধনের জন্য এটিকে কনফিগ স্ন্যাপশট হিসেবে বিবেচনা করুন। ভলিউম কপিই হলো আসল ব্যাকআপ।
অন্য যেকোনো জায়গার মতো এখানেও VPS-এ প্রোডাকশনে SQLite চালানোর ক্ষেত্রে দুটি স্টোরেজ নিয়ম প্রযোজ্য। ডেটাবেসটি লোকাল ডিস্কে রাখুন, কারণ নেটওয়ার্ক ফাইলসিস্টেমে SQLite-এর লকিং নির্ভরযোগ্য নয় এবং পেজ করাপ্ট হলে আপনি তা বুঝতে পারবেন। আর যদি আপনি নেমড ভলিউমের পরিবর্তে হোস্ট বাইন্ড মাউন্ট ব্যবহার করেন, তবে আগে হোস্ট ডিরেক্টরিটির মালিকানা পরিবর্তন (chown) করুন: কন্টেইনারটি নন-রুট node ইউজার হিসেবে চলে, যার uid 1000 এবং এটি node:22-alpine-এ থাকে। রুট দ্বারা তৈরি ডিরেক্টরিতে এই ইউজারের লেখার অনুমতি থাকে না, ফলে অ্যাপটি ডেটাবেস খুলতে পারে না এবং স্টার্টআপের সময় কন্টেইনারটি বন্ধ হয়ে যায়। Compose-এ নেমড ভলিউমের বিপরীতে বাইন্ড মাউন্ট বিষয়টি বিস্তারিত আলোচনা করে।
অ্যানালিটিক্স এবং কনসেন্ট ব্যানার, যার প্রয়োজন আপনার নেই
এই ফিচারটিই সেই কারণ, যার জন্য অন্য কোথাও বিনামূল্যে পাওয়া যায় এমন একটি পেজ আপনি নিজে হোস্ট করছেন।
এই অ্যানালিটিক্স কুকি-মুক্ত। কোনো ভিজিটর বা দর্শকের জন্য কোনো কুকি সেট করা হয় না এবং পাবলিক পেজে কোনো থার্ড-পার্টি স্ক্রিপ্ট লোড হয় না। একজন ভিজিটরকে শনাক্ত করা হয় IP অ্যাড্রেস, ইউজার এজেন্ট স্ট্রিং এবং একটি সল্ট (salt)-এর SHA-256 হ্যাশ দিয়ে, যা 16টি হেক্সাডেসিমেল ক্যারেক্টারে ট্রাঙ্কেট বা ছোট করা হয়। সল্টটি নিজেই বর্তমান UTC তারিখ এবং আপনার SECRET_KEY-এর একটি হ্যাশ, তাই এটি প্রতিদিন মধ্যরাত UTC-তে পরিবর্তিত হয় এবং গতকালের হ্যাশের সাথে আজকের হ্যাশের মিল পাওয়া সম্ভব নয়। মূল IP অ্যাড্রেস কখনোই ডাটাবেসে লেখা হয় না।
ক্লিকগুলো সার্ভারে গণনা করা হয়। পাবলিক পেজের প্রতিটি http লিঙ্ক আপনার নিজের ডোমেইনের /go/<id>-এর দিকে নির্দেশ করে, যা ক্লিকটি রেকর্ড করে এবং তারপর প্রকৃত গন্তব্যে একটি 302 রিডাইরেক্ট পাঠায়। ফলে, যেসব পাঠক JavaScript বন্ধ রেখেছেন এবং যারা এমন ইন-অ্যাপ ব্রাউজার ব্যবহার করছেন যা ব্যাকগ্রাউন্ড রিকোয়েস্ট ব্লক করে, তাদের ক্ষেত্রেও গণনা সঠিকভাবে কাজ করে। পেজ ভিউগুলো /api/track-এর মাধ্যমে রেকর্ড করা হয়।
দুটি বিষয় জেনে রাখা জরুরি। একটি বৈধ অ্যাডমিন সেশন বহনকারী রিকোয়েস্ট গণনা করা হয় না, তাই নিজের পেজ এডিট করলে তা ভিউ সংখ্যা বাড়াবে না। পরিচিত ক্রলার ইউজার এজেন্টগুলোকেও বাদ দেওয়া হয়।
কনসেন্ট বা সম্মতির বিষয়ে: পাঠকের ডিভাইসে কিছুই সংরক্ষণ করা হয় না, আর কুকি ব্যানার মূলত পাঠকের ডিভাইসে সংরক্ষিত কুকির জন্যই অনুমতি চায়। আপনার বাধ্যবাধকতাগুলো আপনার পাঠকরা কোথায় বাস করেন তার ওপর নির্ভর করে, তাই সেগুলো যাচাই করে নিন। তবে এখানে প্রকাশ করার মতো কোনো ট্র্যাকিং কুকি নেই এবং কোনো থার্ড-পার্টি এই ডাটা গ্রহণ করছে না।
একটি সতর্কতা যা অনেককে অবাক করে: SECRET_KEY পরিবর্তন করলে দৈনিক সল্টও পরিবর্তিত হয়, তাই সেই মুহূর্ত থেকে প্রতিটি ফিরে আসা ভিজিটরকে নতুন হিসেবে গণনা করা হয়।
অ্যানালিটিক্স-এর কান্ট্রি কলাম কেন খালি থাকে?
আপনার স্ট্যাকের কোনো কিছুই কান্ট্রি হেডার সেট করে না বলে এমনটি হয়। LinkBreeze মূলত cf-ipcountry এবং x-vercel-ip-country-এর মতো প্রক্সি হেডার থেকে দেশের তথ্য শনাক্ত করে। আপনার নিজস্ব Caddy বা Nginx-এর পেছনে থাকা কোনো VPS-এ এই হেডারগুলোর কোনোটিই থাকে না, তাই কান্ট্রি ফিল্ডটি null হিসেবে রেকর্ড হয় এবং ব্রেকডাউনটি খালি থেকে যায়। কন্টেইনারের ভেতরে কোনো GeoIP ডেটাবেস নেই।
এটি পূরণ করার দুটি উপায় আছে। ডোমেইনের সামনে Cloudflare ব্যবহার করুন, যা প্রক্সি করা প্রতিটি অনুরোধে cf-ipcountry যোগ করে। অথবা, লোকাল GeoIP লুকআপ ব্যবহার করে আপনার নিজস্ব রিভার্স প্রক্সিতে এই হেডারগুলোর যেকোনো একটি সেট করুন।
এর সাথে সম্পর্কিত সমস্যাটি আরও গুরুতর, তাই এটি পরীক্ষা করে দেখুন। ক্লিক এবং ভিউ হ্যান্ডলারগুলো প্রথমে X-Forwarded-For থেকে ক্লায়েন্ট অ্যাড্রেস পড়ে, এরপর X-Real-IP দেখে এবং কোনো হেডার না থাকলে 0.0.0.0-এ ফিরে যায়। কোনো প্রক্সি ছাড়া সরাসরি পোর্ট 3000 ইন্টারনেটে উন্মুক্ত করলে প্রতিটি ভিজিটর একই ভ্যালু হিসেবে গণ্য হবে। এর ফলে unique visitors সবসময় 1 দেখাবে এবং প্রতি মিনিটে 60 ইভেন্টের IP-ভিত্তিক রেট লিমিট আপনার পুরো অডিয়েন্সের ওপর একসাথে কার্যকর হবে। উপরে উল্লিখিত reverse_proxy ডিরেক্টিভের পেছনে থাকলে Caddy আপনার জন্য হেডারটি সেট করে দেয় এবং উভয় সমস্যার সমাধান হয়ে যায়।
Linktree থেকে ইমপোর্ট এবং যা যা স্থানান্তরিত হয় না
ড্যাশবোর্ডের মাইগ্রেশন উইজার্ড একটি পাবলিক প্রোফাইল URL অথবা এক্সপোর্ট করা ফাইল গ্রহণ করে। এটি linktr.ee, bento.me, lnk.bio, tap.link, hopp.bio, beacons.ai, solo.to, linkfly, mssg.me এবং LittleLink পেজ, সেইসাথে সাধারণ HTML এবং JSON এক্সপোর্ট শনাক্ত করতে পারে। Linktree বা Bento URL-এর ক্ষেত্রে এটি সেই পেজগুলোতে এমবেড করা __NEXT_DATA__ JSON ফাইলটি পড়ে। স্ট্যাটিক পেজের ক্ষেত্রে এটি অ্যাঙ্কর ট্যাগগুলো পড়ে।
যা যা স্থানান্তরিত হয় তা হলো প্রতিটি লিঙ্কের শিরোনাম, URL, বিবরণ এবং ছবি, লিঙ্কটি কোনো সোশ্যাল প্রোফাইল কি না, এবং আপনার ডিসপ্লে নাম, বায়ো ও অবতার। ডাটাবেসে কোনো কিছু লেখার আগেই আপনি খুঁজে পাওয়া লিঙ্কগুলোর মধ্যে কোনগুলো রাখবেন তা নির্বাচন করতে পারবেন।
যা যা স্থানান্তরিত হয় না তা হলো অ্যানালিটিক্স হিস্ট্রি, থিম ও লেআউট, ইমেইল সাবস্ক্রাইবার, শিডিউল করা পাবলিশের তারিখ এবং পুরনো প্ল্যাটফর্মের লগইনের ভেতরে থাকা যেকোনো তথ্য। সাইটটির লুক বা ডিজাইন আপনাকে হাতে তৈরি করে নিতে হবে এবং এটি মেনে নিতে হবে যে পুরনো ক্লিকের হিস্ট্রি পুরনো সার্ভিসেই থেকে যাবে।
ইমপোর্টার আপনার ব্রাউজারের পরিবর্তে আপনার সার্ভার থেকে URL ফেচ করে, তাই এটি এমন কোনো ঠিকানা গ্রহণ করে না যা পাবলিক নয়। Private/local URLs are not allowed মানে হলো আপনি এমন একটি ঠিকানা দিয়েছেন যা আপনার নিজস্ব নেটওয়ার্কের ভেতরে, এবং এই প্রত্যাখ্যানটি ইচ্ছাকৃত: এটি ছাড়া, ড্যাশবোর্ড অ্যাক্সেস আছে এমন যেকোনো ব্যক্তি আপনার সার্ভার ব্যবহার করে এমন সব মেশিন প্রোব করতে পারত যেখানে কেবল আপনার সার্ভারেরই অ্যাক্সেস আছে। অন্যান্য যে মেসেজগুলো আপনি দেখতে পারেন তা হলো Only http and https URLs are allowed, Request timed out এবং Response too large।
স্ক্র্যাপিং অন্য কারো মার্কআপের ওপর নির্ভর করে। যদি উইজার্ড এমন কোনো পেজে কোনো লিঙ্ক খুঁজে না পায় যেখানে স্পষ্টভাবে লিঙ্ক আছে, তবে বুঝতে হবে পার্সারটি লেখার পর সেই প্ল্যাটফর্ম তাদের HTML পরিবর্তন করেছে। কোনো ফিক্সের জন্য অপেক্ষা না করে লিঙ্কগুলো হাতে যোগ করুন। যদি আপনার প্রোফাইল পেজের পরিবর্তে পরিমাপযোগ্য শর্ট লিঙ্কের প্রয়োজন হয়, তবে Shlink-এর মতো একটি self-hosted URL shortener সেই কাজটি করে এবং একই বক্সে অনায়াসেই চলতে পারে।
একটি পিন করা ডিপ্লয়মেন্ট আপডেট করা
# edit the image tag in docker-compose.yml, then
docker compose pull
docker compose up -d
docker compose logs -f linkbreezeকন্টেইনার চালু হওয়ার সময় schema migration স্বয়ংক্রিয়ভাবে সম্পন্ন হয়। এগুলোকে পূর্বের অবস্থায় ফিরিয়ে নেওয়ার কোনো নথিভুক্ত পদ্ধতি নেই, তাই আগে volume-এর একটি কপি সংরক্ষণ করুন। যে আপগ্রেড আপনি বাতিল করতে পারবেন না, তা কেবল তখনই নিরাপদ যখন আপনি আগের অবস্থায় ফিরে যেতে সক্ষম।
নতুন কোনো রিলিজ থাকলে ড্যাশবোর্ডে একটি ব্যানার দেখা যায়। এটি প্রতি 24 ঘণ্টায় একবার প্রজেক্টের GitHub রিপোজিটরি থেকে একটি ছোট ভার্সন ফাইল সংগ্রহ করে এই তথ্য যাচাই করে এবং আপনার ইনস্ট্যান্স সম্পর্কে কোনো তথ্য পাঠায় না। ট্যাগ পরিবর্তন করার আগে রিলিজ নোটগুলো পড়ুন, কারণ প্রজেক্টের এই পর্যায়ে একটি মাইনর ভার্সন আপনার ব্যবহৃত ডিফল্ট সেটিংস পরিবর্তন করে ফেলতে পারে।
ব্যর্থতার ধরন এবং যে বার্তাগুলো আপনি দেখবেন
manifest unknown যখন pull করছেন। ট্যাগটি :v1.2.7 হিসেবে লেখা হয়েছিল। Registry ট্যাগ কোনো v বহন করে না, তাই :1.2.7 ব্যবহার করুন।
no matching manifest for linux/arm64/v8 in the manifest list entries। প্রকাশিত ইমেজটি শুধুমাত্র amd64 আর্কিটেকচারের জন্য। ট্যাগ করা সোর্স থেকে ARM হোস্টেই এটি বিল্ড করুন।
পেজ লোড ঠিকঠাক হলেও কন্টেইনার unhealthy রিপোর্ট করছে। আপনার compose ফাইলে একটি healthcheck curl কল করছে, যা ইমেজটিতে নেই। এটি মুছে ফেলুন এবং ইমেজটির নিজস্ব wget healthcheck-কে চলতে দিন।
Caddy সার্টিফিকেট এরর দেখাচ্ছে, অথবা কিছুই দেখাচ্ছে না। docker compose logs caddy চেক করুন। সাধারণত এর কারণ হলো, A record এখনো এই VPS-কে নির্দেশ করছে না, অথবা ফায়ারওয়ালে port 80 বন্ধ আছে। এটি Caddy-এর ব্যবহৃত ACME (automatic certificate management environment) HTTP চ্যালেঞ্জকে বাধাগ্রস্ত করে, যার মাধ্যমে Caddy প্রমাণ করে যে ডোমেইনটি তার নিয়ন্ত্রণে আছে।
Unique visitor সংখ্যা 1-এ আটকে আছে। কোনো প্রক্সি X-Forwarded-For সেট করছে না, তাই প্রতিটি ভিজিটরকে একই হিসেবে গণ্য করা হচ্ছে।
গতকাল কাজ করার পরেও কন্টেইনারটি স্টার্টআপের পরপরই বন্ধ হয়ে যাচ্ছে। আপনি যদি named volume থেকে host bind mount-এ সরে এসে থাকেন, তবে ডেটা ডিরেক্টরির মালিকানা root-এর কাছে থাকে এবং অ্যাপটি uid 1000 হিসেবে চলে, তাই এটি ডেটাবেস ফাইলটি খুলতে পারে না। হোস্ট ডিরেক্টরিটিকে sudo chown -R 1000:1000 করুন।
ট্র্যাকিং রিকোয়েস্টের উত্তরে HTTP 429 আসছে। /api/track এবং /go/<id>-এর প্রতি-IP থ্রটল সীমা অতিক্রম করা হয়েছে। ভিজিটররা এখনো তাদের গন্তব্যে রিডাইরেক্ট হচ্ছে, শুধু ক্লিকটি গণনা করা হচ্ছে না।
FAQ
LinkBreeze কি পাবলিক 'link in bio'-এর জন্য প্রস্তুত?
এটি একটি নতুন প্রজেক্ট। আগস্ট 2026 পর্যন্ত এর রিপোজিটরিতে 178টি স্টার, 17টি ফর্ক এবং একজন মেইনটেইনার রয়েছেন, এবং প্রথম রিলিজটি 1 জুলাই 2026-এ প্রকাশিত হয়েছে। গড়ে সপ্তাহে দুইবারের বেশি নতুন রিলিজ আসে, তাই বাগ দ্রুত ঠিক হয় এবং কাজের ধরনেও দ্রুত পরিবর্তন আসে। MIT লাইসেন্স এবং লোকাল SQLite ফাইল থাকার মানে হলো, ডেভেলপমেন্ট বন্ধ হয়ে গেলেও আপনার পেজটি সচল থাকবে। তবে সিকিউরিটি প্যাচ ছাড়া কোনো পাবলিক ওয়েব অ্যাপ ঝুঁকির কারণ হতে পারে, তাই এটিকে এমন সফটওয়্যার হিসেবে দেখুন যা আপনাকে নিয়মিত আপডেট করতে হবে, একবার ইনস্টল করে ফেলে রাখার মতো নয়।
আমার কোন LinkBreeze ইমেজ ট্যাগ চালানো উচিত?
ভার্সন ট্যাগ ব্যবহার করুন, যেমন ghcr.io/manak-hash/linkbreeze:1.2.7, এবং সচেতনভাবে সেটি পরিবর্তন করুন। রিলিজ ওয়ার্কফ্লো শুধুমাত্র latest এবং নির্দিষ্ট ভার্সন নম্বর পুশ করে, তাই v সহ :v1.2.7 ট্যাগটি নেই এবং Docker manifest unknown ত্রুটি দেখাবে। ইমেজটি শুধুমাত্র linux/amd64-এর জন্য তৈরি, তাই arm64 VPS-এ আপনাকে ট্যাগটি ক্লোন করে লোকালি বিল্ড করতে হবে।
LinkBreeze অ্যানালিটিক্সে দেশের তালিকা কেন খালি থাকে?
LinkBreeze ভিজিটর কোন দেশ থেকে আসছে তা cf-ipcountry বা x-vercel-ip-country-এর মতো প্রক্সি হেডার থেকে পড়ে, এর নিজস্ব কোনো GeoIP ডাটাবেস নেই। আপনার Caddy বা Nginx-এর পেছনে থাকা VPS এই হেডারগুলো সেট করে না, তাই দেশ হিসেবে null সংরক্ষিত হয়। ডোমেইনের সামনে Cloudflare ব্যবহার করুন, অথবা আপনার রিভার্স প্রক্সিকে লোকাল GeoIP লুকআপ থেকে এই হেডারগুলোর একটি সেট করতে বলুন।
ঠিক কী ব্যাকআপ নিতে হবে এবং কীভাবে রিস্টোর করব?
শুধুমাত্র ডাটাবেস ফাইল নয়, পুরো linkbreeze-data ভলিউমের ব্যাকআপ নিন। /app/data/linkbreeze.db-এ প্রতিটি লিঙ্ক, পেজ, সেটিংস, সাবস্ক্রাইবার এবং অ্যানালিটিক্স ডেটা থাকে, এবং /app/data/uploads-এ অবতার ও থাম্বনেইল ইমেজ থাকে যা পেজে রেফারেন্স হিসেবে ব্যবহৃত হয়। কন্টেইনারটি থামিয়ে docker compose cp linkbreeze:/app/data ./backup-$(date +%F) কমান্ড চালান, তারপর আবার চালু করুন। রিস্টোর করার জন্য ডিরেক্টরিটি থামানো কন্টেইনারে কপি করে আবার চালু করুন। ড্যাশবোর্ড থেকে নেওয়া JSON এক্সপোর্টটি শুধুমাত্র প্রোফাইল, লিঙ্ক, সেটিংস এবং থিমের একটি কনফিগারেশন স্ন্যাপশট, এতে কোনো অ্যানালিটিক্স বা ইমেজ থাকে না।
Linktree থেকে ইমপোর্ট করলে কি আমার অ্যানালিটিক্স এবং থিম চলে আসবে?
না। মাইগ্রেশন উইজার্ড আপনার পুরনো পাবলিক প্রোফাইল থেকে লিঙ্কের শিরোনাম, URL, বর্ণনা, ইমেজ, ডিসপ্লে নেম, বায়ো এবং অবতার পড়ে। অ্যানালিটিক্স হিস্ট্রি, থিম, ইমেইল সাবস্ক্রাইবার এবং শিডিউল করা পাবলিশ ডেট ইমপোর্ট হয় না। ইমপোর্টের পর থিম এডিটরে গিয়ে নতুন করে সাজিয়ে নিন এবং ধরে নিন যে আপনার ক্লিক হিস্ট্রি পুরনো প্ল্যাটফর্মেই থেকে যাবে।