মূলত আমার ব্লগ সেটআপটি WireGuard-এর মাধ্যমে একটি বিশুদ্ধ IPv6-প্রকল্প হিসেবে পরিকল্পনা করা হয়েছিল, কারণ এটি একটি হোম সার্ভারে চালানো হয় (যাইহোক, আপনি route64.org থেকে বিনামূল্যে IPv6 অ্যাড্রেস পেতে পারেন)। অ্যাক্সেসযোগ্যতা বাড়ানোর জন্য, আমি এখন একটি এক্সটার্নাল IPv4 প্রক্সি যুক্ত করেছি (ধন্যবাদ @Larvitz)।
তবে, এতে সাথে সাথেই SSL সমস্যা দেখা দেয়: যেহেতু মূলত A এবং AAAA উভয় রেকর্ডই প্রক্সির মাধ্যমে চলছিল, তাই আমার সার্ভারে Let's Encrypt ভ্যালিডেশন ব্যর্থ হয়েছিল।
সমাধান: "IPv6-হ্যাঁক"
সমাধানটি ছিল AAAA-এন্ট্রি সরাসরি আমার সার্ভারের WireGuard IP-তে পয়েন্ট করা, প্রক্সির মাধ্যমে পাঠানোর পরিবর্তে।
- ডোমেইন:
blog.burningboard.org
- A-রেকর্ড (প্রক্সি):
194.28.98.217
- AAAA-রেকর্ড (সার্ভার):
2a11:6c7:f05:a8::2 (WireGuard)
আমার WireGuard IP-তে এই সরাসরি AAAA-এন্ট্রির মাধ্যমে Let’s Encrypt সরাসরি IPv6-এর মাধ্যমে আমার সার্ভারে পৌঁছাতে পারে (যেহেতু ডিফল্টভাবে AAAA-রেকর্ডকে অগ্রাধিকার দেওয়া হয়) এবং SSL সার্টিফিকেট ইস্যু করে। IPv4 ট্রাফিক প্রক্সি দ্বারা এনক্রিপ্ট করা অবস্থায় আমার কাছে পৌঁছে দেওয়া হয়।
চূড়ান্ত কনফিগারেশন
যোগাযোগ যাতে নির্বিঘ্নে সম্পন্ন হয়, সেজন্য আমাদের Caddy সার্ভারগুলো অ্যাডজাস্ট করতে হয়েছে:
১. আমার সার্ভারে (NixOS, blog.nix)
যাতে ভিজিটরদের আসল IP সঠিকভাবে পৌঁছায় এবং প্রক্সির IP দ্বারা ওভাররাইট না হয়, তাই প্রক্সিটিকে বিশ্বস্ত (trusted) হিসেবে চিহ্নিত করতে হবে:
services.caddy.globalConfig = ''
servers {
trusted_proxies static 2a06:9801:1c:1000::10
}
'';
২. এক্সটার্নাল প্রক্সিতে (Caddy)
প্রক্সি যাতে HTTPS-এর মাধ্যমে আমার সার্ভারের সাথে সঠিকভাবে যোগাযোগ করতে পারে, তাই তাকে হোস্টনেম (SNI) পাঠাতে হবে:
reverse_proxy [https://[2a11:6c7:f05:a8::2]:443](https://[2a11:6c7:f05:a8::2]:443) {
header_up Host {host}
transport http {
tls_server_name blog.burningboard.org
}
}
ব্লগটি এখন IPv4 এবং IPv6 উভয় মাধ্যমেই অ্যাক্সেসযোগ্য, সুরক্ষিতভাবে এনক্রিপ্ট করা এবং আমার হোম IP গোপন থাকছে! 🚀
শুরুতেই সবচেয়ে গুরুত্বপূর্ণ বিষয়টি জানিয়ে রাখি: পরিচিত Markdown ফাইলগুলোই ভিত্তি হিসেবে থাকছে – আমি এই সহজ সমাধানের একজন বড় ভক্ত। তবে পর্দার আড়ালে অনেক কিছু বদলে গেছে:
আমি সেটআপে বেশ কিছু পরিবর্তন এনেছি:
📂 MD-Files: ব্লগের গঠন আগের মতোই সহজ এবং মার্কডাউন ভিত্তিক থাকছে।
🌍 আগের চেয়েও বেশি গ্লোবাল: আমার ব্লগ এখন ৪৩টি ভাষায় অনুবাদ সমর্থন করে। হ্যাঁ, ক্লিংগন (Klingon) ভাষাসহ! 🖖 (Qapla'!)

পরিকল্পনা ছিল ব্রাউজারের ভাষা শনাক্তকরণের ওপর ভিত্তি করে একটি সম্পূর্ণ স্বয়ংক্রিয় রিয়েল-টাইম অনুবাদ ব্যবস্থা তৈরি করা। স্পয়লার: এটি কেবল আংশিকভাবে কাজ করেছে। বোঝা যাচ্ছে যে: এআই (AI) চিত্তাকর্ষক হলেও, আমরা ঠিক যেখানে এটি দেখতে চাই সেখানে এখনও পৌঁছায়নি।
সমাধান: আমি এখন প্রতিটি পোস্ট আগে থেকেই নির্ধারিত সবগুলো ভাষায় অনুবাদ করে রাখছি, যা সার্চ ইঞ্জিনের (SEO) জন্যও অনেক ভালো। যদি স্বয়ংক্রিয় শনাক্তকরণ কাজ না করে, তবে আপনারা গ্লোব আইকনের মাধ্যমে ম্যানুয়ালি আপনার পছন্দের ভাষা সেট করতে পারেন, যা কুকির (Cookie) মাধ্যমে খুব সহজেই সংরক্ষিত হবে।
অনুবাদগুলো এখন Gemini 3 Flash দিয়ে করা হচ্ছে, যা আশ্চর্যজনকভাবে ভালো ফলাফল দিচ্ছে। তবে এআই-এর কাজের ওপর কড়া নজর রাখা উচিত: প্রথম বাল্ক রান-এ ভুলবশত ট্যাগগুলোও অনুবাদ হয়ে গিয়েছিল, যা অবশ্যই পরিকল্পনায় ছিল না।
কোডটি এখনও পাওয়া যাচ্ছে (আগ্রহী হলে আমাকে মেসেজ দিন) 👍 তবে মনে রাখবেন যে, সিস্টেমটির জন্য এখন একটি নিজস্ব Gemini API Key 🔑 প্রয়োজন।
আমি হঠাৎ করেই আমার ব্লগকে WriteFreely থেকে নিজের তৈরি একটি সিস্টেমে পরিবর্তন করেছি: MD-Blog (এখানে MD অবশ্যই Markdown-কে বোঝায়)। এর সূত্রপাত হয়েছিল পুরনো সিস্টেমের একটি ব্যর্থ আপডেটের মাধ্যমে – তবে শেষ পর্যন্ত এটি সবকিছুকে আমূল সহজ করার এবং ডিজাইনের ওপর পূর্ণ নিয়ন্ত্রণ পাওয়ার জন্য একটি উপযুক্ত সুযোগ হয়ে দাঁড়িয়েছে।
এর মূল ভিত্তি হলো data/ ফোল্ডারে থাকা সাধারণ Markdown ফাইলগুলো, যা রানটাইমে আধুনিক HTML-এ রূপান্তরিত হয়। এর ফলাফল অত্যন্ত দ্রুতগতির, কোনো ডাটাবেসের প্রয়োজন হয় না এবং নিজস্ব ডিজাইন সিস্টেমের (ডার্ক মোডসহ) কারণে এটি এখন ঠিক তেমনই দেখাচ্ছে যেমনটি আমি কল্পনা করেছিলাম। এমনকি একটি আধুনিক Mastodon-Share-Button-ও এখন সরাসরি এতে যুক্ত করা হয়েছে।
কোড বা এই ছিমছাম সেটআপ সম্পর্কে আপনাদের আগ্রহ থাকলে, নির্দ্বিধায় Mastodon-এর মাধ্যমে আমার সাথে যোগাযোগ করুন!
আসলে #Winboat-এর পেছনের ধারণাটি চমৎকার, কিন্তু এর বাস্তবায়ন বর্তমানে কিছুটা অস্থিতিশীল বলে মনে হচ্ছে। বছরের শুরুতে ইনস্টল করার পর থেকে সিস্টেমটি ঠিকঠাক চললেও, আজ সফটওয়্যারটি পুরোপুরি কাজ করা বন্ধ করে দিয়েছে।
ইমেজটি হঠাৎ করে অপর্যাপ্ত মেমোরি (RAM)-এর ত্রুটি দেখাতে শুরু করে। আমি ম্যানুয়ালি সমস্যাটি সমাধান করার চেষ্টা করেছিলাম, কিন্তু দুর্ভাগ্যবশত সেটি সিস্টেমটিকে পুরোপুরি অকেজো করে দেয়। ত্রুটি খুঁজে বের করার পেছনে আরও সময় নষ্ট না করে, আমি সরাসরি Dockurr Windows-Image-এ চলে এসেছি – যা মূলত Winboat-এর প্রযুক্তিগত ভিত্তি।

১. প্রস্তুতি
যেহেতু আমি Podman ব্যবহার করি, তাই প্রথমে আমি আমার হোস্ট সিস্টেমে প্রয়োজনীয় ডিরেক্টরিগুলো তৈরি করে নিয়েছি। এর ফলে কন্টেইনারটি পুনরায় তৈরি করার প্রয়োজন হলেও ডেটার অখণ্ডতা বজায় থাকবে:
mkdir -p $HOME/Windows/System
mkdir -p $HOME/Windows/Shared
২. স্টার্ট কমান্ড
গুরুত্বপূর্ণ নোট: -e USERNAME এবং -e PASSWORD ভেরিয়েবলগুলোতে আপনার ব্যক্তিগত লগইন তথ্য দিয়ে প্লেসহোল্ডারগুলো পরিবর্তন করুন।
podman run -d \
--name windows \
-p 8006:8006 \
--device=/dev/kvm \
--cap-add NET_ADMIN \
-e RAM_SIZE="8G" \
-e USERNAME="Carsten" \
-e PASSWORD="1234" \
-e LANGUAGE="German" \
-v $HOME/Windows/System:/storage:Z \
-v $HOME/Windows/Shared:/shared:Z \
--stop-timeout 120 \
dockurr/windows
কন্টেইনারটি সক্রিয় হয়ে গেলে, আপনি সরাসরি আপনার ব্রাউজারের মাধ্যমে উইন্ডোজ ইনস্ট্যান্সটি অ্যাক্সেস করতে পারবেন:
http://127.0.0.1:8006

৩. সারসংক্ষেপ
উপরের কমান্ডটি আমাকে কেবল একবারই রান করতে হয়েছে। দৈনন্দিন ব্যবহারের ক্ষেত্রে এখন এই শর্টকাট কমান্ডগুলোর মাধ্যমে খুব সহজেই উইন্ডোজ এনভায়রনমেন্ট নিয়ন্ত্রণ করা যায়:
- চালু করা:
podman start windows
- বন্ধ করা:
podman stop windows (অথবা সরাসরি উইন্ডোজের ভেতর থেকে শাটডাউন করুন)
- স্ট্যাটাস চেক করা:
podman ps -a
আরও কিছু প্রয়োজনীয় লিঙ্ক:
আমি আমার নিজস্ব একটি ব্লগ ইনস্টল করেছি — মূলত #NixOS সম্পর্কে আরও ভালোভাবে জানার জন্য। আশ্চর্যজনকভাবে, পুরো বিষয়টি বেশ সহজ ছিল।
WriteFreely এর জন্য দারুণ উপযোগী: এটি মিনিমালিস্টিক, দ্রুত সেটআপ করা যায় এবং এতে বাড়তি কোনো ঝামেলা নেই। কাজ শুরু করার এবং পাশাপাশি কিছু শেখার জন্য এটি উপযুক্ত। এর কনফিগারেশন বেশ গোছানো। কয়েকটি অপশন সেট করা, ডিরেক্টরি প্রস্তুত করা, সামনে একটি রিভার্স প্রক্সি রাখা — ব্যাস, কাজ শেষ।
এর জন্য আমার বর্তমান NixOS কনফিগারেশনটি দেখতে এইরকম:
{ config, pkgs, ... }:
{
services.writefreely = {
enable = true;
host = "blog.burningboard.org";
settings = {
server = {
port = 8080;
min_log_level = "debug";
};
app = {
host = "https://blog.burningboard.org";
single_user = true;
landing = "/read";
wf_modesty = true;
federation = true;
public_stats = true;
theme = "write";
};
};
stateDir = "/opt/writefreely";
};
# ActivityPub কী জেনারেশনের জন্য ফিক্স: ফেডারেশনের জন্য openssl প্রয়োজন
systemd.services.writefreely.path = [ pkgs.openssl ];
# সঠিক পারমিশন সহ ডেটা ডিরেক্টরি স্বয়ংক্রিয়ভাবে তৈরি করা
systemd.tmpfiles.rules = [
"d /opt/writefreely 0700 writefreely writefreely -"
];
services.caddy.virtualHosts."blog.burningboard.org".extraConfig = ''
reverse_proxy 127.0.0.1:8080 {
header_up Host {host}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
'';
}
মূলত এটাই ছিল সব। NixOS এই ধরনের সার্ভিসগুলোকে সুন্দরভাবে কনফিগার করা এবং রিপ্রোডিউসিবল রাখা সত্যিই সহজ করে দেয়।