OpenAnalytics को VPS पर कैसे इंस्टॉल करें
OpenAnalytics को self-host करने के लिए 4 GB RAM, 25 GB डिस्क और चार DNS रिकॉर्ड्स की आवश्यकता होती है। ClickHouse, Postgres और Valkey के साथ इस स्टैक को सेटअप करने का तरीका जानें।
शुरुआत से पहले की आवश्यकताएं
OpenAnalytics को self-host करने के लिए आपको लगभग 4 GB RAM, 25 GB खाली डिस्क स्पेस, Docker (Compose plugin के साथ) और चार DNS रिकॉर्ड्स वाले एक Linux VPS की आवश्यकता होगी जो पहले से ही आपके सर्वर को पॉइंट कर रहे हों। यह एक स्पष्ट जानकारी है, जिसे पहले कमांड से पहले ही जान लेना आवश्यक है।
यह स्टैक छह एप्लिकेशन सर्विसेज और तीन डेटा स्टोर्स से मिलकर बना है। Postgres कंट्रोल प्लेन को संभालता है: अकाउंट्स, साइट्स, API कीज़ और शेयर लिंक्स। ClickHouse रॉ इवेंट्स और उन रोलअप्स को स्टोर करता है जिन्हें डैशबोर्ड पढ़ता है। Valkey दो बार चलता है: एक बार एक ड्यूरेबल इवेंट क्यू के रूप में और दूसरी बार एक ऐसे कैश के रूप में जिसे सिस्टम खो सकता है, क्योंकि इन दोनों कार्यों के लिए अलग-अलग इविक्शन पॉलिसी की आवश्यकता होती है। केवल एक प्रोसेस, क्वेरी गेटवे, को ClickHouse पढ़ने की अनुमति है, और यह किसी भी क्वेरी को चलाने से पहले उसके हर क्वेरी एनवेलप पर Ed25519 सिग्नेचर को सत्यापित करता है।
यदि आप एक सिंगल बाइनरी और एक कॉन्फ़िगरेशन फ़ाइल वाला समाधान ढूंढ रहे हैं, तो यह वह नहीं है। GoatCounter इस श्रेणी में सिंगल-बाइनरी विकल्प है: एक Go निष्पादन योग्य फ़ाइल, डिफ़ॉल्ट रूप से SQLite, और कोई बाहरी डेटाबेस नहीं। यह भारी स्टैक आपको फनल्स, वेब वाइटल्स, आपके अपने Stripe अकाउंट से रेवेन्यू एट्रिब्यूशन और एक MCP (मॉडल कॉन्टेक्स्ट प्रोटोकॉल) सर्वर की सुविधा देता है। Self-hosted एनालिटिक्स टूल्स के बीच चयन वह पोस्ट है जो इन विकल्पों के बीच के अंतर को स्पष्ट करती है। यह गाइड मानती है कि आपने पहले ही निर्णय ले लिया है।
सबसे पहले DNS records को सर्वर पर point करें
कुछ भी शुरू करने से पहले चार subdomains का सर्वर के public IP पर resolve होना आवश्यक है। Caddy पहली बार launch होने पर Let's Encrypt certificates के लिए अनुरोध करता है, और यदि नाम resolve नहीं हो रहा है तो challenge विफल हो जाता है।
app.example.comdashboard को serve करता है।api.example.comAPI और OAuth callbacks को serve करता है।c.example.comcollector और tracker script को serve करता है।rt.example.comrealtime stream को serve करता है।
चार A records का उपयोग करें, या एक A record और तीन CNAMEs का उपयोग करें जो उसी पर point करते हों। आगे बढ़ने से पहले dig +short app.example.com के साथ पुष्टि करें। आपके द्वारा अभी-अभी जोड़ा गया नाम किसी भी resolver द्वारा NXDOMAIN के रूप में cache किया जा सकता है जिसका उपयोग Let's Encrypt करता है। इसलिए, यदि पहला certificate प्रयास विफल हो जाता है, तो प्रतीक्षा करना और Caddy logs को पढ़ना उचित है। इंस्टॉलेशन को दोबारा चलाने से DNS propagation की गति नहीं बढ़ती है।
Docker Compose के साथ OpenAnalytics को self-host कैसे करें
एक tagged release को checkout करें। Default branch पर development होता है, जबकि release tag उन images से मेल खाता है जो वास्तव में publish की गई हैं। नीचे दिए गए commands यह मानकर चलते हैं कि Docker और Compose plugin पहले से installed हैं, जिसे VPS पर Docker Compose services चलाना में कवर किया गया है।
git clone https://github.com/OpenLabs-so/openanalytics
cd openanalytics
git checkout "$(git tag -l 'v*' --sort=-v:refname | sed '/-/d' | head -1)"
cd infra/selfhost
./generate-secrets.sh --domain example.com --email you@example.com --with-geoip
docker compose pull && docker compose up -dCheckout line में मौजूद sed '/-/d' pre-release tags को हटा देता है, जिससे आप release candidate के बजाय सबसे नए stable version पर पहुँच जाते हैं। --with-geoip generation के दौरान DB-IP city database को fetch करता है। यदि आप इसे छोड़ देते हैं, तो हर event में country null रहेगा, जिससे geography view में कुछ भी दिखाई नहीं देगा। आप इसे बाद में infra/selfhost/geoip/fetch-dbip.sh चलाकर, env/collector.env में GEOIP_DB_PATH=/geoip/dbip-city-lite.mmdb सेट करके, और फिर docker compose up -d --force-recreate collector के साथ collector को recreate करके जोड़ सकते हैं। वह database हर महीने refresh होता है, इसलिए fetch प्रक्रिया को मासिक रूप से दोहराएँ, अन्यथा आपका city data पुराना हो जाएगा।
आगे बढ़ने से पहले जनरेट किए गए secrets का बैकअप लें
Generator तीन चीजें लिखता है। .env में डोमेन नाम और इमेज रेफरेंस होते हैं। env/*.env में प्रत्येक सर्विस के लिए secrets की एक फाइल होती है। docker-compose.override.yml में YAML ब्लॉक स्केलर्स के रूप में तीन Ed25519 की-पेयर्स (key pairs) होते हैं, क्योंकि मल्टी-लाइन PEM को env फाइल में नहीं रखा जा सकता। यह सब git-ignored है, और इनमें से किसी को भी उन्हीं वैल्यूज के साथ दोबारा जनरेट नहीं किया जा सकता।
इन फाइलों को अभी मशीन से बाहर कॉपी कर लें। प्रत्येक नुकसान की एक विशिष्ट कीमत चुकानी पड़ती है:
- स्टोर पासवर्ड खोने पर आप Postgres और ClickHouse से बाहर हो जाएंगे, जिसे केवल कंटेनर्स के अंदर से ही रीसेट किया जा सकता है।
OA_CREDENTIAL_KEYRINGखोने पर सभी स्टोर्ड थर्ड-पार्टी क्रेडेंशियल्स रिकवर नहीं किए जा सकते, इसलिए जिस किसी ने भी Stripe अकाउंट कनेक्ट किया है, उसे इसे दोबारा कनेक्ट करना होगा।ANONYMOUS_IDENTITY_SECRETखोने पर विजिटर की पहचान री-बेसलाइन हो जाती है: कल के सभी विजिटर्स नए गिने जाएंगे, और यह बदलाव चार्ट्स में दिखाई देगा।AUTH_SECRETखोने पर हर सेशन इनवैलिडेट हो जाता है, इसलिए सभी को दोबारा साइन इन करना होगा।- साइनिंग प्राइवेट की खोने पर आप पेयर को रोटेट कर देते हैं। इसमें कुछ भी खोता नहीं है।
दो secrets को दो फाइलों में बाइट-आइडेंटिकल (byte-identical) होना चाहिए। ANONYMOUS_IDENTITY_SECRET, collector.env और worker.env दोनों में दिखाई देता है, क्योंकि कलेक्टर विजिटर हैश की गणना करता है और वर्कर इसे लिखता है। OA_CREDENTIAL_KEYRING, api.env और worker.env दोनों में दिखाई देता है। बाकी सब कुछ जानबूझकर केवल एक सर्विस तक सीमित रखा गया है, और यदि किसी सर्विस को ऐसा secret दिया जाता है जिसे उसे नहीं रखना चाहिए, तो वह स्टार्ट होने के बजाय एग्जिट (exit) हो जाती है।
स्टैक को चालू करें और जाँचें
grep OA_IMAGE .env
docker compose pull
docker compose up -d
docker compose logs -f migrate
docker compose psmigrate, Postgres और ClickHouse schemas को लागू करता है और फिर बंद हो जाता है, इसलिए एक रुका हुआ migrate container ही सही अंतिम स्थिति है। tracker-build, oa.js को एक volume में compile करता है जिसे Caddy serve करता है और फिर यह भी बंद हो जाता है। बाकी सभी सेवाओं की स्थिति docker compose ps में healthy होनी चाहिए। यदि कोई service बार-बार restart हो रही है, तो इसका मतलब है कि वह environment validation में विफल हो रही है। log हर समस्या को एक ही सूची में दिखाता है, न कि हर restart पर एक। इसके दो सामान्य कारण हैं: एक variable का खाली रह जाना, जिसे unset मानने के बजाय reject कर दिया जाता है, और एक secret का गलत service file में रखा जाना।
arm64 पर, या किसी branch से, कोई published images उपलब्ध नहीं होती हैं, इसलिए आपको docker compose up -d --build के साथ स्थानीय रूप से build करना होगा। 4 GB RAM वाला host इस build के दौरान memory की कमी के कारण रुक सकता है। पहले swap जोड़ें, जिसकी आवश्यकता केवल build के दौरान होती है:
fallocate -l 4G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstabBuild होने में लगभग दस मिनट लगते हैं। Pull करने में कुछ मिनट लगते हैं, इसीलिए release images का उपयोग किया जाता है।
पहला अकाउंट तुरंत क्लेम करें
https://app.example.com खोलें। जिस deployment में अभी तक किसी ने sign-in नहीं किया है, वह sign-in फॉर्म नहीं दिखाता है: यह पहला अकाउंट बनाने का विकल्प देता है। वह अकाउंट स्थायी रूप से privileged अकाउंट होता है, और केवल वही अकाउंट deployment settings स्क्रीन देख सकता है। एक बार इसके बन जाने के बाद, यह route 409 का उत्तर देता है, ताकि कोई भी आपके बाद इसमें प्रवेश न कर सके। stack के healthy होते ही यह काम करें, न कि अगले सप्ताह।
Tracker इंस्टॉल करें
Dashboard में एक साइट जोड़ें और यह आपको tag प्रदान करेगा। इसका प्रारूप निश्चित है:
<script
async
src="https://c.example.com/oa.js"
data-key="YOUR_TRACKING_KEY"
data-collector="https://c.example.com"
></script>इसे page के head में रखें। Tracking key को public रहने के लिए ही बनाया गया है, इसलिए इसे अपने HTML में रखें जहाँ कोई भी इसे पढ़ सके। Script window.oa को इंस्टॉल करती है, और oa("track", ...) जैसे calls को एक stub द्वारा queue में रखा जाता है और file load होते ही उन्हें flush कर दिया जाता है, इसलिए जल्दी fire होने वाला कोई custom event drop नहीं होता है। यदि page पर मौजूद कोई अन्य चीज़ पहले से ही window.oa का उपयोग कर रही है, तो tracker इसके बजाय window.openanalytics के रूप में इंस्टॉल हो जाता है।
इसके बाद पूरे path की end-to-end जाँच करें:
curl -s https://c.example.com/oa.js -o /dev/null -w '%{http_code} %{size_download}\n'
curl -s https://api.example.com/health | head -c 200
docker compose logs --tail=50 worker | grep -i batchपहला command 200 और कुछ kilobytes print करना चाहिए। अपनी साइट पर एक page load करें, फिर कुछ ही seconds में worker log में batch line देखें। Collector event स्वीकार करते ही 202 का उत्तर देता है, और 202 का अर्थ है कि event queue में है, store नहीं हुआ है। Worker ही events को ClickHouse में ले जाता है। यदि events स्वीकार कर लिए गए हैं लेकिन dashboard में कुछ भी दिखाई नहीं दे रहा है, तो इसका मतलब है कि worker blocked है, और Valkey queue की बढ़ती हुई depth इसकी पुष्टि करती है। इसके सामान्य कारण worker.env में गलत ClickHouse credentials होना, या migration द्वारा हाल ही में जोड़ी गई table पर grant का न होना है।
Collector को public रखें और dashboard को auth के पीछे रखें
Caddy compose file के भीतर ही आता है और सभी चार names के लिए अपने आप certificates प्राप्त कर लेता है, इसलिए default path के लिए आपको किसी proxy कार्य की आवश्यकता नहीं है। यदि server पर पहले से ही an nginx reverse proxy चल रहा है, तो stack के सामने दिए गए infra/selfhost/nginx.conf.example का उपयोग करें और इसके header handling को वैसा ही रहने दें:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header CF-Connecting-IP "";
proxy_set_header True-Client-IP "";
proxy_set_header Fly-Client-IP "";Collector client IP से दैनिक visitor hash प्राप्त करता है, इसलिए इसे connection से ही वह address लेना चाहिए, न कि किसी header से। किसी untrusted hop से CF-Connecting-IP को pass करने से कोई भी caller किसी भी address का दावा कर सकता है, जिससे geolocation खराब हो जाती है और visitor counts भी गलत तरीके से बढ़ जाते हैं।
Access hostname के आधार पर स्पष्ट रूप से विभाजित होता है। c. और rt. को आपके द्वारा मापे जाने वाले प्रत्येक site के हर visitor द्वारा पहुँचा जा सकने योग्य होना चाहिए, इसलिए उन दोनों के सामने कभी भी basic auth या IP allowlist न लगाएँ। app. और api. तक केवल उन लोगों को पहुँचने की आवश्यकता है जो sign in करते हैं। Application का अपना auth ही dashboard की सुरक्षा करता है: password sign-in env/api.env में AUTH_PASSWORD_SIGNIN=enabled के माध्यम से default रूप से चालू रहता है, और Google या GitHub buttons केवल तभी दिखाई देते हैं जब उस provider के लिए client ID और client secret दोनों मौजूद हों। Magic links के लिए mail transport की आवश्यकता होती है, और इसके बिना API केवल send को outbox में लिखता है, इसलिए कुछ भी deliver नहीं होता और कोई error भी नहीं आता।
एक setting यह तय करती है कि dashboard काम करेगा या नहीं। env/api.env में AUTH_TRUSTED_ORIGINS का dashboard origin से बिल्कुल मेल खाना आवश्यक है। गलत या अनुपस्थित होने पर, API कोई CORS (cross-origin resource sharing) headers नहीं भेजता, browser हर call को अस्वीकार कर देता है, और आपको एक ऐसा dashboard मिलता है जो layout तो दिखाता है लेकिन कोई data नहीं, जबकि docker compose ps सब कुछ healthy बताता है।
जब आप proxy config में हों, तो automated traffic को संभालें। Crawlers भी बाकी सब की तरह collector को hit करते हैं, और उनके page views ClickHouse में और आपके numbers में दर्ज हो जाते हैं। Blocking AI crawlers at the server ऐसा करने से उस traffic का एक हिस्सा database में जाने से रुक जाता है, जिससे आपकी accuracy बनी रहती है और disk space की बचत होती है।
यहाँ cookieless का क्या अर्थ है और इसकी क्या कीमत चुकानी पड़ती है
यहाँ कोई cookie नहीं होती। विज़िटर की पहचान एक salted hash होती है, salt हर दिन बदलता है, और raw IP addresses को कभी स्टोर नहीं किया जाता है। Geolocation को आपके अपने disk पर मौजूद DB-IP file के माध्यम से स्थानीय रूप से resolve किया जाता है, इसलिए विज़िटर के बारे में कोई भी जानकारी कभी भी host से बाहर नहीं जाती है।
इसका लाभ यह है कि विज़िटर के device पर कोई भी पहचानकर्ता (identifier) स्थायी रूप से नहीं रहता है, जो कि मुख्य रूप से किसी tracker को EU ePrivacy consent नियमों के दायरे में लाता है। इसी कारण से, इस तरह के केवल aggregate डेटा वाले सेटअप अक्सर बिना किसी consent banner के चलाए जाते हैं। आप जो भी डेटा स्टोर करते हैं और उसे कितने समय तक रखते हैं, उस पर GDPR अभी भी लागू होता है, और आपके मामले का निर्णय आपके अपने कानूनी सलाहकार करेंगे, न कि कोई README।
इसकी कीमत आपको cross-day identity के रूप में चुकानी पड़ती है। salt के बदलने का मतलब है कि जो व्यक्ति सोमवार को आता है और फिर बुधवार को आता है, उसे दो अलग-अलग विज़िटर के रूप में गिना जाता है; यह डिज़ाइन का हिस्सा है और इसका कोई समाधान नहीं है। दैनिक unique counts सटीक होते हैं। साप्ताहिक और मासिक unique counts दैनिक आंकड़ों से बनाए जाते हैं और ये reach को बढ़ा-चढ़ाकर दिखा सकते हैं, इसलिए कोई भी लंबी अवधि का "returning visitor" आंकड़ा वह नहीं मापता जो उसके नाम से प्रतीत होता है। एक ही दिन के भीतर sessions और journeys विश्वसनीय होते हैं। ANONYMOUS_IDENTITY_SECRET को rotate करने का प्रभाव दिन बदलने जैसा ही होता है, इसलिए उस rotation को routine hygiene के बजाय डेटा में बदलाव के रूप में देखें।
collector Do Not Track और Global Privacy Control का सम्मान करता है, जो कि browser का वह signal है जो किसी साइट को व्यक्तिगत डेटा बेचने या साझा न करने के लिए कहता है। script tag में इसी उद्देश्य के लिए अपने स्वयं के switches होते हैं: data-respect-gpc, data-respect-dnt, और data-require-consent, जो consent मिलने तक सारा collection रोक कर रखते हैं और उत्तर को localStorage में oa.consent key के तहत याद रखते हैं। data-storage="none" को set करने से browser storage पूरी तरह से बंद हो जाता है।
छह महीने बाद डिस्क भर जाने का कारण
यह वह समस्या है जो self-hosted analytics बॉक्स को पूरी तरह बंद कर देती है, और आमतौर पर इसका कारण events नहीं होते हैं।
शुरुआत images से करें। एक release में दस images होती हैं, और डिस्क पर वे लगभग 13 GB जगह लेती हैं। एक upgrade पुरानी generation को हटाने से पहले नई generation को pull करता है, इसलिए कुछ समय के लिए आपके पास दो generations मौजूद रहती हैं। एक भी page view आने से पहले ही यह 25 GB की आवश्यकता का मुख्य कारण बन जाता है।
फिर snapshots की बात आती है। snapshot.sh stack को रोकता है, सभी secrets के साथ दोनों data volumes को archive करता है, और फिर restart करता है। यहाँ केवल cold copies ही सुरक्षित होती हैं, क्योंकि ClickHouse बैकग्राउंड में parts को merge करता है और merge के दौरान ली गई copy consistent नहीं होती है। upgrade.sh हर upgrade से पहले स्वचालित रूप से एक copy ले लेता है, इसलिए जब तक आप उन्हें सीमित नहीं करते, archives उसी डिस्क पर जमा होते रहते हैं।
./snapshot.sh create --label before-something-risky
./snapshot.sh list
./snapshot.sh --keep 3सीमा के करीब पहुँच चुके host पर, upgrade करने से पहले पिछली generation को हटा दें। stack के चलते समय ऐसा करना सुरक्षित है, क्योंकि चल रहे containers के पीछे की images अभी भी referenced होती हैं:
docker image prune -a -fअब बात करते हैं स्वयं events की। ClickHouse columnar data को बहुत अधिक compress करता है, इसलिए raw event volume लोगों की उम्मीद से कहीं धीमी गति से बढ़ता है, और dashboard जिन rollup tables को पढ़ता है, वे raw table की तुलना में बहुत छोटी होती हैं। अनुमान लगाने के बजाय मापें:
docker system df -v
docker compose exec clickhouse df -h /var/lib/clickhouseप्रति-table आंकड़े के लिए, इसे उन ClickHouse credentials के साथ चलाएं जिन्हें generator ने infra/selfhost/env/ के तहत लिखा था:
SELECT table, formatReadableSize(sum(bytes_on_disk)) AS size, sum(rows) AS row_count
FROM system.parts
WHERE active
GROUP BY table
ORDER BY sum(bytes_on_disk) DESC;यह रीडिंग पहले सप्ताह में लें और फिर चौथे सप्ताह में दोबारा लें। दो बिंदु आपको growth rate प्रदान करेंगे, और growth rate से पता चलेगा कि volume को कब resize करने की आवश्यकता है। अगस्त 2026 तक, self-hosting guide में raw events के लिए कोई retention या time-to-live विकल्प नहीं दिया गया है, इसलिए यह मान लेने के बजाय कि पुरानी rows अपने आप expire हो जाएंगी, अपनी मापी गई दर के आधार पर डिस्क का आकार निर्धारित करें।
हटाने (deletion) से जुड़ी एक ऐसी समस्या है जिसके बारे में पता होना जरूरी है, इससे पहले कि वह आपको प्रभावित करे। किसी site या account को delete करने पर worker के लिए काम queue हो जाता है, और उस worker को CLICKHOUSE_MAINTENANCE_USER और CLICKHOUSE_MAINTENANCE_PASSWORD सेट होने की आवश्यकता होती है, साथ ही ClickHouse में एक मेल खाता oa_maintenance user भी मौजूद होना चाहिए। इनके बिना, deletion हमेशा के लिए queue में पड़ा रहता है। site dashboard से गायब हो जाती है लेकिन हर row डिस्क पर बनी रहती है, जिससे आपको cleanup होने का आभास तो होता है, लेकिन जगह वापस नहीं मिलती।
अपग्रेड और तीन प्रकार की लागतें
git fetch --tags
git checkout "$(git tag -l 'v*' --sort=-v:refname | sed '/-/d' | head -1)"
cd infra/selfhost
./upgrade.shupgrade.sh कोई भी कार्रवाई करने से पहले तीन प्रकार की लागतें प्रदर्शित करता है। डाउनटाइम वास्तविक है: जब कलेक्टर डाउन होता है, तो उस दौरान किए गए इवेंट्स खो जाते हैं, क्योंकि ट्रैकर उन्हें पुनः प्रयास (retry) नहीं करता है। रोलबैक करने पर डेटा का नुकसान होता है, क्योंकि rollback.sh --to backups/<snapshot> दोनों स्टोर्स को पूरी तरह से बदल देता है और उस स्नैपशॉट के बाद लिखी गई प्रत्येक पंक्ति को हटा देता है। डिस्क तीसरी लागत है, जो ऊपर वर्णित स्नैपशॉट पाइल (snapshot pile) है।
रीस्टार्ट के दो नियमों को गलत समझना आसान है। API से पहले क्वेरी गेटवे को चालू करें, क्योंकि एक नया API ऐसे क्वेरी फील्ड्स भेजता है जिन्हें पुराना गेटवे अस्वीकार कर देता है। और ClickHouse को रीस्टार्ट के बजाय रीक्रिएट (recreate) करने की आवश्यकता होती है, क्योंकि docker compose restart कंटेनर के मूल वातावरण का पुन: उपयोग करता है और आपके द्वारा किए गए बदलावों को चुपचाप अनदेखा कर देता है:
docker compose up -d --force-recreate clickhouseडैशबोर्ड में भी इसी तरह की समस्या होती है। env/web.env में मौजूद तीन NEXT_PUBLIC_* ऑरिजिन्स को ब्राउज़र बंडल में कंपाइल किया जाता है और कंटेनर शुरू होने पर प्रतिस्थापित किया जाता है। इसलिए, गलत होस्टनेम को कॉल करने वाले डैशबोर्ड को docker compose up -d --force-recreate web से ठीक किया जाता है, न कि restart से। वेब कंटेनर का लॉग उन ऑरिजिन्स को प्रिंट करता है जिनके साथ वह शुरू हुआ था, जो यह पुष्टि करने का सबसे तेज़ तरीका है कि फिक्स लागू हो गया है।
यदि कॉन्फ़िगरेशन में बदलाव के बाद ClickHouse शुरू होने से मना कर दे, तो उसके लॉग की पहली पंक्ति पढ़ें। oa-entrypoint: से शुरू होने वाली पंक्ति का अर्थ है कि एंट्रीपॉइंट आपके द्वारा सेट किए गए मान को अस्वीकार कर रहा है। इसके अलावा कुछ भी होने का सामान्य अर्थ है कि कॉन्फ़िगरेशन फ़ाइल अमान्य XML है, और इसका सबसे सामान्य कारण XML कमेंट के अंदर डबल हाइफ़न का होना है, जो वहां अवैध है।
AGPL-3.0 और नाम
यह कोड AGPL-3.0 लाइसेंस के अंतर्गत है। अपनी साइटों के लिए इसे बिना किसी बदलाव के चलाने पर कोई भी प्रकाशन दायित्व (publishing obligation) उत्पन्न नहीं होता है। यह दायित्व तब शुरू होता है जब आप कोड में बदलाव करते हैं और उस संशोधित संस्करण को नेटवर्क सर्विस के रूप में चलाते हैं: ऐसी स्थिति में लाइसेंस यह अनिवार्य बनाता है कि आप अपने संशोधित सोर्स कोड को उस सर्विस के उपयोगकर्ताओं को उपलब्ध कराएं। इसमें आपके इंस्टेंस पर क्लाइंट्स को डैशबोर्ड देना और इसे किसी ऐसी चीज़ में बंडल करना शामिल है जिसे आप बेचते हैं। अपने बदलावों को एक पब्लिक फोर्क (public fork) में रखने से यह शर्त बिना किसी अतिरिक्त प्रक्रिया के पूरी हो जाती है।
ब्रांड कोड से अलग है। "OpenAnalytics" नाम और प्रोजेक्ट का होस्टेड डोमेन उस इंस्टेंस की पहचान करते हैं जिसे इसके लेखक संचालित करते हैं, और वे लाइसेंस अनुदान का हिस्सा नहीं हैं। आपका डिप्लॉयमेंट बिना ब्रांड के सॉफ्टवेयर चलाता है, इसलिए भुगतान करने वाले ग्राहकों के सामने इसे लाने से पहले सर्विस को अपना एक अलग नाम दें।
FAQ
क्या मैं 1 GB VPS पर OpenAnalytics चला सकता हूँ?
नहीं। इस प्रोजेक्ट को लगभग 4 GB RAM और 25 GB खाली डिस्क की आवश्यकता होती है, क्योंकि एक डिप्लॉयमेंट में Postgres, ClickHouse और दो Valkey इंस्टेंस के साथ छह एप्लिकेशन सर्विसेज चलती हैं। ClickHouse अपने आप में एक छोटा प्रोसेस नहीं है। 1 GB वाले बॉक्स पर कंटेनर शुरू तो हो जाते हैं, लेकिन कर्नल का out-of-memory killer उनमें से किसी एक को, आमतौर पर ClickHouse को, बंद कर देता है। यदि 1 GB का प्लान आपकी मजबूरी है, तो GoatCounter जैसे सिंगल-बाइनरी टूल का उपयोग करें, जो बिना किसी बाहरी डेटाबेस के SQLite पर चलता है।
क्या मुझे OpenAnalytics के साथ कुकी बैनर की आवश्यकता है?
यह आपके वकील के लिए एक प्रश्न है, और तकनीकी तथ्य आपके पक्ष में हैं। इसमें कोई कुकी नहीं होती, विज़िटर की पहचान एक साल्टेड हैश (salted hash) है जो प्रतिदिन बदलती है, और रॉ IP एड्रेस कभी स्टोर नहीं किए जाते, इसलिए विज़िटर की पहचान करने के लिए कुछ भी स्थायी रूप से नहीं लिखा जाता है। GDPR अभी भी यह नियंत्रित करता है कि आप क्या स्टोर करते हैं और उसे कितने समय तक रखते हैं। यदि आप चाहते हैं कि डेटा संग्रह स्पष्ट सहमति पर आधारित हो, तो स्क्रिप्ट टैग पर data-require-consent सेट करें: ट्रैकर तब तक कुछ भी कलेक्ट नहीं करेगा जब तक सहमति नहीं दी जाती और वह उत्तर को oa.consent के अंतर्गत localStorage में सुरक्षित रखता है।
इवेंट्स 202 क्यों रिटर्न करते हैं लेकिन डैशबोर्ड पर कभी दिखाई नहीं देते?
202 का अर्थ है कि कलेक्टर ने इवेंट को स्वीकार कर लिया है और कतार (queue) में लगा दिया है, न कि यह कि उसने इसे स्टोर कर लिया है। वर्कर उस कतार से डेटा निकालकर ClickHouse में डालता है, इसलिए सफल अनुरोधों के बावजूद खाली डैशबोर्ड का मतलब है कि वर्कर में समस्या है। docker compose logs --tail=50 worker पढ़ें और Valkey कतार की गहराई (queue depth) पर नज़र रखें। यदि कतार लगातार बढ़ रही है, तो इसका मतलब है कि वर्कर ब्लॉक है, और इसके सामान्य कारण worker.env में गलत ClickHouse क्रेडेंशियल्स या किसी हालिया माइग्रेशन द्वारा बनाई गई टेबल पर अनुमतियों (grant) की कमी हैं।
जब सभी कंटेनर स्वस्थ (healthy) हैं, तो डैशबोर्ड खाली क्यों है?
सबसे पहले env/api.env में AUTH_TRUSTED_ORIGINS की जाँच करें। इसे डैशबोर्ड ओरिजिन से बिल्कुल मेल खाना चाहिए, और जब ऐसा नहीं होता है तो API कोई CORS हेडर नहीं भेजता है, इसलिए ब्राउज़र हर कॉल को अस्वीकार कर देता है और आपको बिना डेटा के केवल वर्किंग लेआउट दिखाई देता है। दूसरी चीज़ जो जाँचनी है, वह env/web.env में तीन NEXT_PUBLIC_* मान हैं, जिन्हें वेब कंटेनर शुरू होने पर प्रतिस्थापित (substitute) किया जाता है। उन्हें सही करने के लिए docker compose up -d --force-recreate web की आवश्यकता होती है, क्योंकि केवल रीस्टार्ट करने से पुराने मान ही बने रहते हैं।
क्या AGPL-3.0 मुझे इसे ग्राहकों को देने से रोकता है?
नहीं, यह केवल एक शर्त जोड़ता है। कोड को बिना किसी बदलाव के चलाएं और आपको किसी का कुछ नहीं देना है। यदि आप इसे संशोधित करते हैं और उस संशोधित संस्करण को ऐसी सर्विस के रूप में चलाते हैं जिसका उपयोग अन्य लोग करते हैं, तो आपको उन उपयोगकर्ताओं को अपना संशोधित सोर्स कोड उपलब्ध कराना होगा, जिसे एक पब्लिक फोर्क (public fork) के माध्यम से पूरा किया जा सकता है। इसके अलावा, "OpenAnalytics" नाम कोड के साथ लाइसेंस प्राप्त नहीं है, इसलिए आप जो कुछ भी बेचते हैं उसे अपना नाम देना होगा।