SSD Nodes Learn Hosting plans →
নির্দেশিকা Matt Connorদ্বারা Matt Connor · আপডেট করা হয়েছে 2026-08-28

VPS-এ সেরা self-hosted web analytics টুল নির্বাচন

Plausible, Umami, Matomo, GoatCounter ও GoAccess টুলগুলো ছোট VPS-এ চালানোর উপায় জানুন। RAM-এর চাহিদা, ডাটাবেস নির্বাচন, ডিস্ক স্পেস ও রিভার্স প্রক্সি কনফিগারেশনের বিস্তারিত গাইড।

VPS-এ কোন self-hosted web analytics টুলটি চালানো উচিত?

Self-hosted web analytics মূলত দুটি শ্রেণিতে বিভক্ত। ভুল শ্রেণি নির্বাচন করা ভুল পণ্য নির্বাচনের চেয়েও বেশি ব্যয়বহুল হতে পারে। প্রথম শ্রেণির টুলগুলো ভিজিটরের ব্রাউজারে একটি ছোট স্ক্রিপ্ট চালায় এবং সেই স্ক্রিপ্ট যা রিপোর্ট করে তা সংরক্ষণ করে। দ্বিতীয় শ্রেণির টুলগুলো আপনার ওয়েব সার্ভারের তৈরি করা access log ফাইলটি পড়ে। এরপরের সবকিছু, যেমন ডাটাবেস এবং প্রয়োজনীয় মেমোরি, এই প্রাথমিক সিদ্ধান্তের ওপর নির্ভর করে।

ছোট সার্ভারের জন্য সংক্ষিপ্ত উত্তর হলো: GoatCounter এবং Medama 1 GB RAM-এ চলে, কারণ প্রতিটি টুল একটি ফাইলের ওপর একটি প্রসেস হিসেবে কাজ করে। Umami একটি Postgres কন্টেইনার যোগ করে এবং এমন একটি ড্যাশবোর্ড প্রদান করে যা একজন অ-প্রযুক্তিবিদও বুঝতে পারেন। Plausible Community Edition এবং Rybbit উভয়ই ClickHouse ব্যবহার করে, তাই অন্তত 2 GB বা তার বেশি RAM-এর পরিকল্পনা রাখুন। Matomo একটি পূর্ণাঙ্গ পণ্য এবং এটি আপনার ট্রাফিকের ওপর ভিত্তি করে সার্ভারের আকার নির্ধারণ করতে বলে। GoAccess পেজে কোনো বাড়তি লোড যোগ করে না, কারণ এটি বিদ্যমান লগ ফাইল থেকে তথ্য সংগ্রহ করে।

Script tag নাকি server log: কোনটি কী দেখতে পায়

একটি script tag ব্রাউজার পরিমাপ করে। পেজ লোড হয়, স্ক্রিপ্টটি রান করে এবং এটি আপনার collector-এর কাছে একটি অনুরোধ পাঠায়। এই চেইনটি ভেঙে দেয় এমন যেকোনো কিছুই আপনার কাছে অদৃশ্য: JavaScript বন্ধ থাকা, কোনো filter list যা অনুরোধটি ব্লক করে, collector-এর কাছে ব্যর্থ অনুরোধ, অথবা এমন কোনো crawler যা কখনোই স্ক্রিপ্ট রান করে না।

একটি log parser অনুরোধগুলো পরিমাপ করে। আপনি কিছু ইনস্টল করুন বা না করুন, আপনার web server প্রতিটি অনুরোধের জন্য একটি লাইন লেখে, তাই ডেটা ইতিমধ্যেই ডিস্কে থাকে। এটি প্রতিটি crawler এবং এমন ফাইলের প্রতিটি হিট দেখতে পায় যেখানে কোনো script tag নেই। এটি ব্রাউজারের ভেতরে কী ঘটেছে তা দেখতে পায় না এবং ব্রাউজার cache বা আপনার সার্ভারের সামনে থাকা কোনো CDN (content delivery network) থেকে পরিবেশন করা পেজ দেখতে পায় না, কারণ সেই অনুরোধটি কখনোই আপনার সার্ভারে পৌঁছায় না।

এই দুটি সংখ্যা মিলবে না এবং এর কোনোটিই ভুল নয়। Matomo উভয়ই করতে পারে এবং এটি তার JavaScript tracker-এর পাশাপাশি log import কী কী বাদ দেয় তা নথিবদ্ধ করে: screen resolution এবং page titles, events, content tracking, heatmaps, session recordings এবং form analytics। ব্রাউজারের পরিবর্তে অনুরোধ গণনা করার মূল্য হলো এই তালিকাটি।

Bot traffic হলো এই পার্থক্যের অন্য অর্ধেক। Log-based গণনায় crawler অন্তর্ভুক্ত থাকে যদি না আপনি সেগুলোকে ফিল্টার করেন, এবং সাধারণ সাইটে crawler-এর পরিমাণ এত বেশি থাকে যে তা আপনার সিদ্ধান্তে পরিবর্তন আনতে পারে। GoAccess এবং Matomo-এর log import উভয়ই পরিচিত bot-গুলোকে ফিল্টার করে। কোনোটিই এমন crawler-কে ফিল্টার করতে পারে না যা তার user agent সম্পর্কে মিথ্যা তথ্য দেয়, আর এটিই যেকোনো log-based গণনার সাথে blocking AI crawlers at the server যুক্ত করার এবং ব্লক করার আগে নয় বরং পরে লগ পড়ার একটি ভালো কারণ।

GoAccess: আপনার বিদ্যমান লগ থেকে অ্যানালিটিক্স

প্রজেক্টের নিজস্ব Debian এবং Ubuntu রিপোজিটরি থেকে এটি ইনস্টল করুন, কারণ ডিস্ট্রিবিউশনের প্যাকেজগুলো মূল রিলিজের তুলনায় পিছিয়ে থাকে।

wget -O - https://deb.goaccess.io/gnugpg.key | gpg --dearmor | sudo tee /usr/share/keyrings/goaccess.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/goaccess.gpg arch=$(dpkg --print-architecture)] https://deb.goaccess.io/ $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/goaccess.list
sudo apt-get update
sudo apt-get install goaccess

এরপর এটিকে লগের দিকে নির্দেশ করুন এবং একটি স্ট্যাটিক রিপোর্ট তৈরি করুন।

goaccess /var/log/nginx/access.log -o ~/report.html --log-format=COMBINED

সাধারণ ব্যবহারকারীর ক্ষেত্রে এই কমান্ডটি Permission denied ত্রুটির কারণে ব্যর্থ হয়, কারণ Ubuntu-তে Nginx লগের মালিক হলো root এবং এর গ্রুপ হলো adm। sudo usermod -aG adm $USER ব্যবহার করে নিজেকে সেই গ্রুপে যুক্ত করুন, তারপর লগ আউট করে পুনরায় লগ ইন করুন, কারণ লগ ইন করার সময় গ্রুপের সদস্যপদ যাচাই করা হয়। id চালান এবং পুনরায় চেষ্টা করার আগে নিশ্চিত করুন যে তালিকায় adm দেখা যাচ্ছে।

লাইভ লগের রিপোর্ট শুধুমাত্র সেই অংশটুকুই কভার করে যা logrotate এখনো সরিয়ে নেয়নি। গতকালের অনুরোধগুলো access.log.1-এ থাকে এবং পুরোনো ফাইলগুলো কম্প্রেস করা থাকে, তাই সাপ্তাহিক ভিউ পাওয়ার জন্য রোটেট করা ফাইলগুলোও পড়তে হয়।

zcat /var/log/nginx/access.log.*.gz | goaccess - --log-format=COMBINED -o ~/last-week.html

এখানে একটি লাইভ মোডও আছে, --real-time-html, যা WebSocket-এর মাধ্যমে পেজ আপডেট করে। এর জন্য একটি অতিরিক্ত পোর্ট এবং নিজস্ব প্রক্সি রুল প্রয়োজন। বেশিরভাগ সাইটের জন্য cron দ্বারা তৈরি প্রতি ঘণ্টার রিপোর্টই যথেষ্ট এবং এতে নিরাপত্তার ঝুঁকিও কম থাকে।

GoatCounter: একটি Go বাইনারি এবং একটি SQLite ফাইল

GoatCounter একটি স্ট্যাটিক্যালি কম্পাইল করা বাইনারি হিসেবে রিলিজ করা হয়, তাই আলাদা কোনো রানটাইম ইনস্টল করার প্রয়োজন নেই। রিলিজ পেজ থেকে একটি বিল্ড ডাউনলোড করে চালান অথবা ইমেজ ব্যবহার করুন।

docker run -p 8080:8080 -v goatcounter-data:/home/goatcounter/goatcounter-data arp242/goatcounter

বাইনারি হিসেবে চালালে, goatcounter serve পোর্ট 8080-এ লিসেন করে এবং ./goatcounter-data/db.sqlite3-এ একটি SQLite ফাইল তৈরি করে। যখন ইনস্ট্যান্সটি কোনো প্রক্সির পেছনে থাকে, তখন ওয়েব উইজার্ডের পরিবর্তে কমান্ড লাইন থেকে প্রথম সাইটটি তৈরি করুন।

goatcounter db create site -vhost=stats.example.com -user.email=me@example.com

এটি goatcounter serve -listen=:443 -tls=tls,rdr,acme ব্যবহার করে ACME (automatic certificate management environment)-এর মাধ্যমে নিজস্ব সার্টিফিকেট পরিচালনা করতে পারে, যা এমন সার্ভারের জন্য উপযোগী যেখানে অন্য কিছু চলে না। যেখানে Nginx বা Caddy ইতিমধ্যে পোর্ট 443 ব্যবহার করছে, সেখানে GoatCounter-কে 8080 পোর্টে রেখে প্রক্সি কনফিগার করুন। প্রজেক্টের তথ্য অনুযায়ী ট্র্যাকিং স্ক্রিপ্টটি প্রায় 3.5K সাইজের এবং যেসব পেজে JavaScript নেই, সেগুলোর জন্য একটি ট্র্যাকিং পিক্সেল রয়েছে। যদি কোনো ব্যস্ত সাইটে SQLite সীমাবদ্ধতা তৈরি করে, তবে একই বাইনারি goatcounter serve -db 'postgresql+dbname=goatcounter' ব্যবহার করে Postgres-এর সাথে কাজ করতে পারে। ব্যাকআপ নেওয়ার জন্য কেবল ফাইলটি কপি করলেই হয়, যা এই ধরনের টুলের সবচেয়ে বড় সুবিধা।

Medama: একটি একক কন্টেইনার যা 256 এমবি মেমোরি দাবি করে

Medama হলো এই তালিকার নতুনতম একক বাইনারি বিকল্প। এটি ডিজাইন অনুযায়ী কুকি-মুক্ত এবং প্রজেক্টটির দাবি অনুযায়ী এর ট্র্যাকার 1 কেবি-এর চেয়ে ছোট। এছাড়া 256 এমবি মেমোরিযুক্ত ভার্চুয়াল মেশিনেও ছোট সাইটগুলো চালানো সম্ভব। এগুলো প্রজেক্টটির প্রকাশিত দাবি, এই গাইডের জন্য পরিমাপ করা কোনো সংখ্যা নয়।

docker volume create medama-data
docker run -d -p 127.0.0.1:8080:8080 -v medama-data:/app/data ghcr.io/medama-io/medama:latest

অফিসিয়াল কমান্ডটি পোর্টটিকে 8080:8080 হিসেবে প্রকাশ করে। উপরের লুপব্যাক প্রিফিক্সটি ইচ্ছাকৃতভাবে দেওয়া হয়েছে এবং রিভার্স প্রক্সি সেকশনে এর কারণ ব্যাখ্যা করা হয়েছে। প্রথম লগইন হলো CHANGE_ME_ON_FIRST_LOGIN পাসওয়ার্ডসহ admin, এবং সেই পাসওয়ার্ডের নামটিই হলো নির্দেশনা।

একটি নথিভুক্ত ব্যর্থতার কারণ আপনাকে সমস্যায় ফেলতে পারে। লগইন শুধুমাত্র HTTPS বা localhost-এ কাজ করে, তাই আপনি যদি সার্টিফিকেটের আগে প্রক্সি সেটআপ করেন, তবে ফর্মটি সঠিক পাসওয়ার্ডকেও প্রত্যাখ্যান করবে এবং এর কারণ প্রদর্শন করবে না। প্রথমে TLS (ট্রান্সপোর্ট লেয়ার সিকিউরিটি) সেটআপ সম্পন্ন করুন, তারপর লগইন করুন।

Umami: Postgres এবং পরিচিত ড্যাশবোর্ড

git clone https://github.com/umami-software/umami.git
cd umami
docker compose up -d

এটি পোর্ট 3000-এ অ্যাপ্লিকেশনটি চালু করে এবং এর পাশাপাশি একটি PostgreSQL কন্টেইনার সচল করে। ডকুমেন্টেশন অনুযায়ী ন্যূনতম PostgreSQL v12.14 এবং সোর্স থেকে বিল্ড করলে Node.js 18.18 বা তার পরবর্তী ভার্সন প্রয়োজন। একটি প্রি-বিল্ট ইমেজ docker.umami.is/umami-software/umami:postgresql-latest রয়েছে, যার জন্য DATABASE_URL ব্যবহার করে আপনার চলমান ডাটাবেসের সাথে সংযোগ স্থাপন করতে হয়।

প্রথমবার লগইন করার জন্য ইউজারনেম admin এবং পাসওয়ার্ড umami ব্যবহার করুন। DNS কনফিগার করার আগেই এটি পরিবর্তন করে নিন, কারণ রেকর্ডটি রিজলভ হওয়ার সাথে সাথে এবং প্রক্সি সাড়া দেওয়া শুরু করলেই ইনস্ট্যান্সটি ইন্টারনেট থেকে অ্যাক্সেসযোগ্য হয়ে যায়। Compose-এর বিস্তারিত তথ্য, এনভায়রনমেন্ট ফাইল এবং রিস্টার্ট পলিসির জন্য VPS-এ একটি Docker Compose স্ট্যাক দেখুন; না পড়ে কোনো স্ট্যাক কপি করবেন না।

এর রিসোর্স ব্যবহারের পরিমাণ একটি Node প্রসেস এবং Postgres-এর সমান। এটি একটি সিঙ্গেল বাইনারি ফাইলের চেয়ে ভারী হলেও ClickHouse ব্যবহারকারী যেকোনো কিছুর তুলনায় অনেক হালকা।

Plausible Community Edition: ClickHouse-এর RAM-এর সর্বনিম্ন সীমা নির্ধারণ

git clone -b v3.2.1 --single-branch https://github.com/plausible/community-edition plausible-ce
cd plausible-ce
touch .env
echo "BASE_URL=https://stats.example.com" >> .env
echo "SECRET_KEY_BASE=$(openssl rand -base64 48)" >> .env
docker compose up -d

আগস্ট 2026 অনুযায়ী v3.2.1 সংস্করণটি বর্তমান, এবং clone কমান্ডটি ইচ্ছাকৃতভাবে এই সংস্করণটিকে নির্দিষ্ট করে দেয়। এই স্ট্যাকটি তিনটি অংশে বিভক্ত: অ্যাপ্লিকেশন, অ্যাকাউন্ট ও সেটিংসের জন্য Postgres, এবং ইভেন্ট ডেটার জন্য ClickHouse। SECRET_KEY_BASE অবশ্যই কমপক্ষে 64 বাইটের একটি স্ট্রিং হতে হবে, যা openssl কলটির মাধ্যমে তৈরি হয়।

Plausible-এর নিজস্ব প্রয়োজনীয়তা অনুযায়ী কমপক্ষে 2 GB RAM থাকা আবশ্যক, যাতে ClickHouse এবং অ্যাপ্লিকেশনটি out of memory killer-এর কবলে না পড়ে। এছাড়া ClickHouse-এর জন্য SSE 4.2 বা NEON সমর্থন করে এমন একটি CPU প্রয়োজন। VPS কেনার আগে এই দ্বিতীয় প্রয়োজনীয়তাটি যাচাই করে নেওয়া জরুরি, এবং এটি ARM এবং x86 VPS-এর মধ্যে নির্বাচনের ক্ষেত্রে একটি ব্যবহারিক পার্থক্য। ClickHouse তার উপলব্ধ মেমরির পুরোটা ব্যবহার করার চেষ্টা করে, তাই শেয়ারড সার্ভারের ক্ষেত্রে Compose-এ কন্টেইনারের মেমরি সীমাবদ্ধ করার নিয়ম অনুযায়ী একটি সর্বোচ্চ সীমা নির্ধারণ করে দিন।

BASE_URL অবশ্যই পাবলিক URL-এর সাথে হুবহু মিলতে হবে। যদি তা না হয়, তবে আপনি লগইন করার পর অ্যাপ্লিকেশনটি ভুল হোস্টের দিকে রিডাইরেক্ট করবে এবং সেশন কুকি এমন একটি ডোমেইনে লেখা হবে যেখানে আপনার ব্রাউজার নেই। ফলে কোনো এরর মেসেজ ছাড়াই আপনি পুনরায় লগইন ফর্মে ফিরে আসবেন।

প্রদত্ত compose ফাইলে কোনো পোর্ট পাবলিশ করা থাকে না, কারণ এর সামনে একটি প্রক্সি ব্যবহারের প্রত্যাশা করা হয়। একটি override যোগ করুন যা শুধুমাত্র loopback ইন্টারফেসে ডিফল্ট অ্যাপ্লিকেশন পোর্টটি পাবলিশ করবে।

cat > compose.override.yml << EOF
services:
    plausible:
        ports:
            - 127.0.0.1:8000:8000
EOF

Matomo: সম্পূর্ণ প্রোডাক্ট এবং এর জন্য প্রয়োজনীয় সার্ভার

Matomo PHP এবং MySQL বা MariaDB-তে চলে, যার অর্থ এটি কন্টেইনার স্ট্যাকের পরিবর্তে ক্লাসিক ওয়েব স্ট্যাকের সাথে সামঞ্জস্যপূর্ণ। এটি এই তালিকার একমাত্র টুল যা ট্র্যাফিকের পরিমাণের ওপর ভিত্তি করে হার্ডওয়্যার নির্দেশিকা প্রকাশ করে।

ChartMatomo sizing guidance by monthly pageviews
The data behind this chart
[
  {
    "label": "100K/month",
    "cpu_cores": 2,
    "ram_gb": 2,
    "disk_gb": 50
  },
  {
    "label": "1M/month",
    "cpu_cores": 4,
    "ram_gb": 8,
    "disk_gb": 250
  },
  {
    "label": "10M/month",
    "cpu_cores": 8,
    "ram_gb": 16,
    "disk_gb": 400
  }
]

এগুলো আগস্ট 2026 অনুযায়ী Matomo-এর প্রকাশিত ন্যূনতম প্রয়োজনীয়তা, এই গাইডের জন্য পরিমাপ করা কোনো তথ্য নয়। মাসে 1,00,000 পেজভিউ পর্যন্ত এটি 2 CPU কোর, 2 GB RAM এবং 50 GB SSD দাবি করে এবং একটি সার্ভারেই অ্যাপ্লিকেশন ও ডাটাবেস উভয়ই থাকে। 1M/month-এ এটি 8 GB RAM এবং 250 GB ডিস্কে পরিণত হয়। 10M/month-এ Matomo দুটি সার্ভারের পরামর্শ দেয় এবং শেষ সারিতে ডাটাবেস সার্ভারের তথ্য দেখানো হয়েছে: 16 GB RAM এবং 400 GB ডিস্ক। এই ডিস্কের সংখ্যাগুলো সিঙ্গেল বাইনারি অপশনগুলোর পাশে পড়ুন, যেখানে পুরো ডাটা সেটটি একটি মাত্র SQLite ফাইলে থাকে।

আর্কাইভিং বিষয়টি মানুষকে অবাক করে। ডিফল্টভাবে, কেউ ড্যাশবোর্ড খুললে Matomo তার রিপোর্ট তৈরি করে, তাই ডাটা বাড়ার সাথে সাথে ড্যাশবোর্ড ধীর হয়ে যায় এবং একসময় টাইম-আউট হয়। এর নথিভুক্ত সমাধান হলো জেনারেল সেটিংস থেকে ব্রাউজার-ট্রিগারড আর্কাইভিং বন্ধ করা এবং এর পরিবর্তে cron থেকে আর্কাইভার চালানো। এটি Matomo ডিরেক্টরি থেকে, Matomo ফাইলের মালিক যে ইউজার, তার মাধ্যমে চালাতে হবে।

php console core:archive --url=https://analytics.example.com

Matomo তার প্রসেস করা রিপোর্ট টেবিলের পাশাপাশি র (raw) লগ টেবিলও রাখে এবং এটি একটি নির্দিষ্ট সময়সূচী অনুযায়ী পুরনো র ডাটা ও রিপোর্ট মুছে ফেলতে পারে। ডিস্ক পূর্ণ হওয়ার আগেই ইনস্টলেশনের সময় এই ফিচারটি চালু করুন। Matomo সার্ভার অ্যাক্সেস লগও ইমপোর্ট করতে পারে, যা এটিকে এই তালিকার একমাত্র প্রোডাক্ট করে তোলে যা একই সাথে উভয় ধরনের ডাটা হ্যান্ডেল করতে পারে।

Rybbit এবং নতুন স্ট্যাকসমূহ

git clone https://github.com/rybbit-io/rybbit.git
cd rybbit
chmod +x *.sh
./setup.sh your.domain.name

Rybbit একটি নতুন প্রজেক্ট যার একটি আধুনিক ড্যাশবোর্ড রয়েছে। এর সেটআপ স্ক্রিপ্টটি environment file তৈরি করে এবং Docker Compose ব্যবহার করে স্ট্যাকটি চালু করে। এটি ClickHouse চালায় এবং এর নিজস্ব ওয়েব সার্ভার হিসেবে Caddy ব্যবহার করে, যা 443 পোর্ট দখল করে এবং আপনার দেওয়া ডোমেইনের জন্য সার্টিফিকেট রিকোয়েস্ট করে। যদি সার্ভারে আগে থেকেই nginx 443 পোর্ট ব্যবহার করে থাকে, তবে স্ক্রিপ্টটি পোর্ট বাইন্ড করতে পারবে না। সেক্ষেত্রে প্রজেক্টের ম্যানুয়াল Compose পদ্ধতি ব্যবহার করুন এবং এটিকে আপনার বিদ্যমান প্রক্সির পেছনে রাখুন। ডকুমেন্টেশন অনুযায়ী, ClickHouse-এর জন্য কমপক্ষে 2 GB RAM, Ubuntu 24 LTS এবং ARM আর্কিটেকচারে ARMv8.2-A বা তার পরবর্তী ভার্সন প্রয়োজন।

যেকোনো নতুন প্রজেক্টের ক্ষেত্রে একটি সতর্কমূলক পরামর্শ: এতে দ্রুত নতুন ফিচার যোগ হয় এবং অনেক সময় বড় ধরনের পরিবর্তন (breaking changes) আসে। তাই একটি নির্দিষ্ট ট্যাগ ব্যবহার করুন (pin a tag), নতুন ভার্সন পুল করার আগে রিলিজ নোট পড়ুন এবং সবার আগে ডাটাবেজের ব্যাকআপ নিন।

রিটেনশন এবং ডিস্কের আকার বৃদ্ধি: আপনার নিজের সার্ভারে পরিমাপ করুন

ডিস্কের আকার বৃদ্ধি নির্ভর করে প্রতিটি ইভেন্টের জন্য টুলটি কী পরিমাণ ডেটা সংরক্ষণ করছে তার ওপর। GoatCounter হিটগুলোকে কাউন্টারে একত্রিত করে, তাই এর ফাইলের আকার raw ভলিউমের চেয়ে নির্দিষ্ট পেজ এবং দিনের সংখ্যার ওপর বেশি নির্ভর করে। Umami এবং Matomo প্রতিটি ইভেন্টের জন্য আলাদা সারি (row) সংরক্ষণ করে, এবং Matomo raw টেবিলের পাশাপাশি প্রসেস করা রিপোর্ট টেবিলও সংরক্ষণ করে। ClickHouse ইভেন্টগুলোকে কলাম আকারে সংরক্ষণ করে এবং সেগুলোকে উচ্চমাত্রায় কম্প্রেস করে, যার ফলে Plausible এমন ট্রাফিক ভলিউম সামলাতে পারে যা একটি row store-এর জন্য কঠিন হতো।

এই গাইডে প্রতি মিলিয়ন পেজভিউতে কত মেগাবাইট জায়গা প্রয়োজন তার কোনো নির্দিষ্ট সংখ্যা দেওয়া হয়নি, কারণ এটি আপনার ট্রাফিকের ওপর পরিমাপ করা হয়নি। আপনি নিজেই এই পরিমাপটি করুন। আপনার Compose ফাইলে থাকা সার্ভিস এবং ব্যবহারকারীর নামের সাথে মিলিয়ে কমান্ডগুলো সমন্বয় করুন।

du -h goatcounter-data/db.sqlite3
docker compose exec db psql -U umami -d umami -c "SELECT pg_size_pretty(pg_database_size('umami'));"
docker compose exec plausible_events_db clickhouse-client -q "SELECT formatReadableSize(sum(bytes_on_disk)) FROM system.parts WHERE active"

সংখ্যাটি রেকর্ড করুন, এক সপ্তাহ অপেক্ষা করুন, পুনরায় রেকর্ড করুন এবং প্রাপ্ত পার্থক্যকে সেই সপ্তাহের ড্যাশবোর্ডে দেখানো পেজভিউ সংখ্যা দিয়ে ভাগ করুন। এই সংখ্যাটি আপনার সাইট এবং বট ফিল্টারিংয়ের ওপর ভিত্তি করে তৈরি, তাই যেকোনো প্রকাশিত গড়ের চেয়ে এর গুরুত্ব অনেক বেশি। সংখ্যাটি ছোট থাকতেই একটি রিটেনশন লিমিট সেট করুন। ডিস্ক পূর্ণ হয়ে গেলে শুধু অ্যানালিটিক্স নয়, বরং VPS-এর প্রতিটি সার্ভিস বন্ধ হয়ে যাবে। এটিই সবচেয়ে বড় কারণ কেন ডাটাবেস ভলিউম এমন জায়গায় রাখা উচিত যেখানে df -h আপনাকে সতর্ক করতে পারে। যে সার্ভারে ইতিমধ্যে বড় কোনো ডেটা রয়েছে, সেখানে এই ঝুঁকিটি আরও বেশি গুরুত্বের দাবি রাখে, কারণ একটি সেলফ-হোস্টেড ফটো সার্ভার অ্যানালিটিক্স ডাটাবেস বড় হওয়ার অনেক আগেই ডিস্কের জায়গা শেষ করে ফেলবে।

রিভার্স প্রক্সির পেছনে এটি যেভাবে কাজ করে

কালেক্টরটিকে আপনার সাইটের একটি সাবডোমেইনে রাখুন, যেমন stats.example.com। এটি কালেক্টরের অনুরোধকে ফার্স্ট-পার্টি হিসেবে গণ্য করে, ফলে ব্রাউজারের থার্ড-পার্টি রিকোয়েস্ট ব্লক করার নিয়মগুলো এখানে কার্যকর হয় না।

কনটেইনারের port publish করার সময় application-টিকে loopback-এ bind করুন। Docker, ufw-এর আগে নিজের firewall rule প্রয়োগ করে। তাই `-p 3000:3000 হিসেবে publish করা কনটেইনার Internet থেকে পৌঁছানো যায়, যদিও ufw status দেখায় যে port-টি denied। অন্য একটি machine থেকে curl http://SERVER_IP:3000 দিয়ে পরীক্ষা করলে dashboard পাওয়া যাবে। -p 127.0.0.1:3000:3000 হিসেবে publish করলে একই পরীক্ষায় Connection refused` পাওয়া যাবে, এবং শুধু proxy-ই সেখানে পৌঁছাতে পারবে। এই অভ্যাস শুধু dashboard আড়াল করে না। একই server-এ onion service চালানো-র মূল নীতিও এটি। কারণ public interface-এ এখনও সাড়া দেওয়া যেকোনো service hidden address-টিকে আপনার IP-এর সঙ্গে যুক্ত করে। Collector endpoint-কে open Internet থেকে reachable রাখতে হবে, কিন্তু dashboard-কে নয়। দ্বিতীয় একটি subdomain publish করার বদলে private network-এর মাধ্যমে এটি পড়তে চাইলে subnet router দিয়ে VPS network আপনার tailnet-এ advertise করা port খোলা ছাড়াই কাজটি সম্পন্ন করে।

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

    location / {
        proxy_pass http://127.0.0.1:3000;
        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;
    }
}

এখানে ফরওয়ার্ডিং হেডারগুলো ঐচ্ছিক নয়। X-Forwarded-For ছাড়া প্রতিটি ভিজিট 127.0.0.1 থেকে আসে বলে গণ্য হয়, ফলে কান্ট্রি রিপোর্ট খালি থাকে এবং ইউনিক ভিজিটর সংখ্যা কমে এক হয়ে যায়। প্রতিটি প্রজেক্ট নির্ধারণ করে তারা কোন হেডারকে বিশ্বাস করবে এবং কোন সেটিংসে কাজ করবে, তাই অনুমান না করে একবার তাদের প্রক্সি ডকুমেন্টেশন দেখে নিন। Caddy নিজে থেকেই এই হেডারগুলো সেট করে দেয় এবং একই কাজের জন্য একটি Caddyfile মাত্র দুই লাইনের হয়।

stats.example.com {
    reverse_proxy 127.0.0.1:3000
}

আপনি যদি এখনো কোনো প্রক্সি নির্বাচন না করে থাকেন, তবে nginx, Caddy এবং Traefik-এর তুলনা বিষয়টি পড়ুন, যেখানে অল্প কিছু সাবডোমেইনসহ একটি সিঙ্গেল বক্সের জন্য কোনটি উপযুক্ত তা আলোচনা করা হয়েছে।

নিজস্ব সার্ভারে হোস্ট করলে কি কুকি ব্যানার প্রয়োজন?

নিজস্ব সার্ভারে হোস্ট করলে ডেটা কার কাছে থাকছে তা পরিবর্তিত হয়, কিন্তু ডেটা সংক্রান্ত আইন পরিবর্তিত হয় না। দুটি নিয়ম আলাদাভাবে বিবেচনা করুন। ePrivacy-এর সম্মতি সংক্রান্ত নিয়মটি ভিজিটরের ডিভাইসে কোনো কিছু সংরক্ষণ বা পড়ার ওপর প্রযোজ্য। তাই যে টুল কোনো কুকি সেট করে না এবং লোকাল স্টোরেজে কিছু লেখে না, তা এই নির্দিষ্ট নিয়মের আওতার বাইরে থাকে। GDPR ব্যক্তিগত ডেটা প্রসেসিংয়ের সাথে সম্পর্কিত এবং IP address ব্যক্তিগত ডেটা হিসেবে গণ্য হয়। তাই আপনার কাছে একটি বৈধ ভিত্তি (lawful basis), ডেটা সংরক্ষণের সময়সীমা (retention limit) থাকতে হবে এবং কেউ আপনার কাছে থাকা তাদের তথ্য সম্পর্কে জানতে চাইলে তার উত্তর দেওয়ার প্রস্তুতি থাকতে হবে।

Plausible, Umami, GoatCounter এবং Medama ডিফল্টভাবে কোনো কুকি সেট করে না। প্রতিটি টুল কী ধরনের তথ্য সংগ্রহ করে তা প্রজেক্ট ভেদে ভিন্ন হয় এবং ভার্সন পরিবর্তনের সাথে সাথে পরিবর্তিত হতে পারে। তাই কোনো সারসংক্ষেপের ওপর নির্ভর না করে প্রজেক্টের নিজস্ব প্রাইভেসি ডকুমেন্টেশন পড়ুন। Matomo-তে IP anonymisation এবং একটি opt-out endpoint রয়েছে, যা আপনি অ্যাডমিন ইন্টারফেস থেকে চালু করতে পারেন।

বিভিন্ন দেশের নিয়ন্ত্রক সংস্থা ভিন্ন ভিন্ন সিদ্ধান্তে পৌঁছায়। উদাহরণস্বরূপ, ফ্রান্সের CNIL এমন কিছু শর্ত প্রকাশ করেছে যার অধীনে অডিয়েন্স পরিমাপের টুলগুলো সম্মতির প্রয়োজনীয়তা থেকে অব্যাহতি পেতে পারে। এই অংশটি কেবল তথ্যের সারসংক্ষেপ, কোনো আইনি পরামর্শ নয়। প্রকৃত ব্যবহারকারীসহ কোনো ওয়েবসাইটের ক্ষেত্রে আপনার এখতিয়ারভুক্ত এলাকার একজন আইনজীবীর পরামর্শ নিন।

একটি বিষয় যা অনেকেই এড়িয়ে যান: access log-ও ব্যক্তিগত ডেটা। GoAccess পেজে কোনো স্ক্রিপ্ট যোগ করে না, তবুও এটি IP address প্রসেস করে। তাই লগ-ভিত্তিক অ্যানালিটিক্স স্বয়ংক্রিয়ভাবে নিয়মের বাইরে নয়। কোনো সার্ভিস নিজের সার্ভারে সরিয়ে নিলে ঝুঁকির জায়গা পরিবর্তিত হয়, কিন্তু ঝুঁকি দূর হয় না। ঠিক এই কারণেই একটি self-hosted SearXNG instance আসলে কী গোপন করে বিষয়টি সার্চ ইঞ্জিনের পর্যায়েই সীমাবদ্ধ থাকে, অথচ সার্চ কুয়েরিগুলো আপনার নিজস্ব লগেই জমা হতে থাকে।

Ad blockers এবং কেন আপনার পরিসংখ্যান কমে যাবে

Filter list-গুলো hostname এবং URL pattern-এর ওপর ভিত্তি করে কাজ করে। একটি hosted analytics product-কে শনাক্ত করা সহজ, কারণ সবাই একই পরিচিত hostname থেকে এটি লোড করে। collector-কে আপনার নিজস্ব subdomain-এ সরিয়ে নিলে অনুরোধ থেকে সেই hostname-টি সরে যায় এবং আপনার পছন্দমতো path থেকে script পরিবেশন করলে পরিচিত filename-টিও আর থাকে না। এই দুটি পদক্ষেপই filter list-এর ম্যাচিং প্রক্রিয়াকে বদলে দেয়।

এই পোস্টে কোনো নির্দিষ্ট hit rate-এর দাবি করা হয়নি, কারণ এটি পরিমাপ করা হয়নি। কতজন ভিজিটর আপনার সেটআপ ব্লক করবে তা আপনার অডিয়েন্সের ওপর নির্ভর করে; সাধারণ অডিয়েন্সের তুলনায় ডেভেলপার অডিয়েন্স অনেক বেশি ব্লক করে থাকে। এর পরিবর্তে আপনার নিজের গ্যাপ পরিমাপ করুন। একই সপ্তাহে GoAccess ব্যবহার করে access log থেকে HTML পেজের অনুরোধ গণনা করুন এবং আপনার script-ভিত্তিক টুল যে pageview রিপোর্ট করছে তার সাথে তুলনা করুন। এই পার্থক্যের কারণ হলো blocked visit এবং আপনার সাইটে cache থেকে লোড হওয়া পেজ।

hosted product থেকে সরে আসার দিন মোট পরিসংখ্যানে পরিবর্তন আশা করুন এবং মনে রাখবেন, এই পরিবর্তনের একটি অংশ ব্লক করার সাথে সম্পর্কিত নাও হতে পারে। pageview কী, single page application-এর ভেতরে route পরিবর্তনকে একটি pageview হিসেবে গণ্য করা হবে কি না, এবং কখন একটি session শেষ হয়—এসব বিষয়ে বিভিন্ন product-এর ভিন্ন ভিন্ন মত রয়েছে। ট্রাফিক কমেছে এমন সিদ্ধান্তে পৌঁছানোর আগে কয়েক সপ্তাহ ধরে ট্রেন্ডগুলো তুলনা করে দেখুন।

কোন সাইটের জন্য কোনটি উপযুক্ত

  • ব্যক্তিগত সাইট বা ব্লগ, যেখানে মাসে 50,000-এর কম পেজভিউ হয়: 1 GB VPS-এ GoatCounter বা Medama ব্যবহার করুন, সাথে ফাইল কপি করার মাধ্যমে ব্যাকআপ রাখুন।
  • এমন সাইট যেখানে কোনো স্ক্রিপ্ট যোগ করা সম্ভব নয় বা যেখানে ভিজিটররা অ্যাড-ব্লকার ব্যবহার করে: বিদ্যমান লগ ফাইলের ওপর ভিত্তি করে নির্ধারিত সময়ে GoAccess চালান।
  • ছোট ব্যবসার সাইট যেখানে অন্য কেউ ড্যাশবোর্ড দেখবে: Postgres কন্টেইনারসহ Umami ব্যবহার করুন।
  • এমন সাইট যেখানে গোল (goals) এবং ফানেল (funnels) ট্র্যাকিং প্রয়োজন এবং সার্ভারে 2 GB বা তার বেশি RAM আছে: Plausible Community Edition ব্যবহার করুন, অথবা নতুন ড্যাশবোর্ড চাইলে এবং অপেক্ষাকৃত নতুন প্রজেক্ট ব্যবহারে আপত্তি না থাকলে Rybbit বেছে নিন।
  • অনেকগুলো সাইট, একাধিক ইউজার অ্যাকাউন্ট বা নিজস্ব রিটেনশন পলিসি অনুযায়ী র-ডেটা (raw data) সংরক্ষণের প্রয়োজন হলে: Matomo ব্যবহার করুন, যার সাইজ উপরে উল্লেখিত নির্দেশিকা অনুযায়ী নির্ধারণ করুন।

আপনার প্রকৃত প্রয়োজন মেটাতে পারে এমন সবচেয়ে ছোট টুলটি দিয়ে শুরু করুন। পরবর্তীতে GoatCounter থেকে Plausible-এ স্থানান্তরিত হলে কেবল একটি সাবডোমেইন এবং কিছু পুরনো হিস্ট্রি হারানোর ঝুঁকি থাকে। কিন্তু Matomo থেকে অন্য কোনো টুলে স্থানান্তর করা বেশ কষ্টসাধ্য একটি প্রক্রিয়া। একই সার্ভারে আর কী কী রাখা যায় তা নিয়ে সিদ্ধান্ত নিতে চাইলে, the wider self-hosting roundup-এ বিস্তারিত দেখুন। আর যদি আপনার ভিজিটর গণনার চেয়ে অ্যাপ্লিকেশনের রিকোয়েস্ট লেভেল ট্রেসিং বেশি প্রয়োজন হয়, তবে সেক্ষেত্রে a self-hosted observability service ব্যবহার করাই সঠিক সমাধান।

FAQ

সেলফ-হোস্টেড অ্যানালিটিক্স ব্যবহার করলে কি কুকি ব্যানার আর প্রয়োজন হয় না?

না, এবং এই দুটি বিষয় সম্পূর্ণ আলাদা। ePrivacy-এর অধীনে সম্মতি বা কনসেন্ট নিয়মটি ভিজিটরের ডিভাইসে কোনো কিছু সংরক্ষণ বা পড়ার ক্ষেত্রে প্রযোজ্য। তাই যে টুল কোনো কুকি সেট করে না এবং লোকাল স্টোরেজে কিছু লেখে না, সেটি এই নির্দিষ্ট প্রয়োজনীয়তার আওতার বাইরে থাকে। GDPR একটি ভিন্ন নিয়ম এবং এটি ব্যক্তিগত ডেটা প্রসেস করার ক্ষেত্রে প্রযোজ্য। যেহেতু IP অ্যাড্রেস ব্যক্তিগত ডেটা, তাই কুকি না থাকলেও আপনার একটি বৈধ ভিত্তি এবং ডেটা সংরক্ষণের সময়সীমা নির্ধারণ করা প্রয়োজন। সেলফ-হোস্টিং ডেটাকে আপনার সার্ভারে নিয়ে আসে এবং এর জন্য আপনাকে দায়ী করে তোলে। আপনার স্থানীয় নিয়ন্ত্রক সংস্থার নির্দেশনা দেখুন এবং আপনার নির্দিষ্ট পরিস্থিতির জন্য একজন আইনজীবীর পরামর্শ নিন।

একটি VPS-এ সেলফ-হোস্টেড অ্যানালিটিক্সের জন্য কতটুকু RAM প্রয়োজন?

ড্যাশবোর্ড নয়, বরং ডেটাস্টোরই এটি নির্ধারণ করে। GoatCounter এবং Medama একটি ফাইলের ওপর একটি প্রসেস হিসেবে চলে এবং Medama-এর ডকুমেন্টেশন অনুযায়ী ছোট সাইটগুলো 256 MB RAM-এর মেশিনে চলতে পারে। Umami একটি Node অ্যাপ্লিকেশনের পাশাপাশি একটি Postgres কন্টেইনার যোগ করে। Plausible Community Edition এবং Rybbit উভয়ই ClickHouse ব্যবহার করে এবং উভয় প্রজেক্টই অন্তত 2 GB RAM-এর কথা উল্লেখ করে। Matomo-এর নিজস্ব নির্দেশনা অনুযায়ী প্রতি মাসে 1,00,000 পেজভিউয়ের জন্য 2 টি CPU কোর এবং 2 GB RAM প্রয়োজন।

আমার সেলফ-হোস্টেড অ্যানালিটিক্সের সংখ্যা আগের অ্যানালিটিক্সের চেয়ে কম কেন?

এর দুটি কারণ রয়েছে এবং উভয়ই বাস্তব। ফিল্টার লিস্টগুলো কিছু কালেক্টর রিকোয়েস্ট ব্লক করে দেয়, তাই স্ক্রিপ্ট-ভিত্তিক প্রতিটি টুলই সেই ভিজিটগুলো হারায়। এছাড়া পণ্যগুলো ভিন্নভাবে গণনা করে, কারণ পেজভিউ কী এবং কখন একটি সেশন শেষ হয়, তা একেক টুলে একেক রকম। আপনার অ্যাক্সেস লগ থেকে এক সপ্তাহের HTML পেজ রিকোয়েস্টের সাথে একই সপ্তাহের স্ক্রিপ্ট-ভিত্তিক পেজভিউ তুলনা করুন। এই পার্থক্যের কারণ হলো ব্লক হওয়া ভিজিট এবং ক্যাশ করা পেজ, যা অন্যের প্রকাশিত হারের ওপর নির্ভর না করে আপনার নিজের সাইট থেকেই পরিমাপ করা হয়েছে।

আমি কি ARM VPS-এ Plausible বা Rybbit চালাতে পারব?

উভয়ই ClickHouse ব্যবহার করে এবং ClickHouse-এর জন্য x86-এ SSE 4.2 অথবা ARM-এ NEON প্রয়োজন। Plausible-এর প্রয়োজনীয়তায় ঠিক এটিই বলা হয়েছে এবং Rybbit-এর ডকুমেন্টেশন অনুযায়ী ARM সিস্টেমের জন্য ARMv8.2-A বা তার পরবর্তী সংস্করণ প্রয়োজন। বর্তমানের ARM সার্ভার কোরগুলো এই মানদণ্ড পূরণ করে, কিন্তু পুরনো মডেলগুলো তা করে না। এক্ষেত্রে অ্যাপ্লিকেশন লগে কোনো ত্রুটি না দেখিয়ে ClickHouse ইন্সট্রাকশন সেট এরর (instruction set error) দেখিয়ে চালু হতে অস্বীকার করবে। ছোট ARM বক্সে সিঙ্গেল-ফাইল টুলগুলো ব্যবহার করলে এই সমস্যার সম্মুখীন হতে হয় না, কারণ সেগুলোর কোনোটিই ClickHouse ব্যবহার করে না।

ট্র্যাকিং স্ক্রিপ্ট ব্যবহার না করে আমার কি সার্ভার লগ পার্স করা উচিত?

যখন আপনি কোনো স্ক্রিপ্ট যোগ করতে পারেন না, যখন আপনার অডিয়েন্স ব্যাপকভাবে ট্র্যাকিং ব্লক করে, অথবা যখন আপনি এমন একটি সংখ্যা চান যাতে ক্রলারও অন্তর্ভুক্ত থাকে, তখন লগ পার্সিং ব্যবহার করুন। GoAccess আপনার সার্ভারের লেখা লগ ফাইলটিই পড়ে, তাই এটি কোনো বাড়তি পেজ ওয়েট বা ডেটাবেস যোগ করে না। তবে ব্রাউজারের ভেতরে যা ঘটে তা আপনি জানতে পারবেন না এবং CDN বা ব্রাউজার ক্যাশ থেকে সার্ভ হওয়া কোনো পেজও আপনি মিস করবেন, কারণ সেই রিকোয়েস্ট আপনার সার্ভার পর্যন্ত পৌঁছায় না। অনেক সাইটই উভয় পদ্ধতি ব্যবহার করে এবং সেগুলোকে দুটি ভিন্ন পরিমাপ হিসেবে গণ্য করে।