OpenAnalytics को VPS पर कैसे इंस्टॉल करें
OpenAnalytics self-host करने के लिए 4 GB RAM और 25 GB डिस्क स्पेस की आवश्यकता होती है। इस गाइड में 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 (मॉडल कॉन्टेक्स्ट प्रोटोकॉल) सर्वर की सुविधा देता है। सेल्फ-होस्टेड एनालिटिक्स टूल्स के बीच चयन वह पोस्ट है जो इन विकल्पों के बीच के अंतर को स्पष्ट करती है। यह गाइड मानकर चलती है कि आपने अपना निर्णय ले लिया है।
सबसे पहले DNS records को सर्वर की ओर पॉइंट करें
किसी भी प्रक्रिया को शुरू करने से पहले चार 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 का उपयोग करें जो उसी की ओर पॉइंट करते हों। आगे बढ़ने से पहले 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 वही है जिससे published images मेल खाती हैं। नीचे दी गई 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 में domain names और image references होते हैं। env/*.env में प्रत्येक service के लिए secrets की एक फाइल होती है। docker-compose.override.yml में तीन Ed25519 key pairs YAML block scalars के रूप में होते हैं, क्योंकि एक multi-line PEM फाइल env फाइल में नहीं रह सकती। यह सब git-ignored है, और इनमें से किसी को भी उन्हीं values के साथ दोबारा जनरेट नहीं किया जा सकता।
इन फाइलों को अभी मशीन से बाहर कॉपी कर लें। प्रत्येक के खोने का एक विशिष्ट नुकसान है:
- Store passwords खोने पर आप Postgres और ClickHouse से बाहर हो जाएंगे, जिसे केवल containers के अंदर से ही reset किया जा सकता है।
OA_CREDENTIAL_KEYRINGखोने पर सभी stored third-party credentials रिकवर नहीं किए जा सकते, इसलिए जिस किसी ने भी Stripe account कनेक्ट किया है, उसे दोबारा कनेक्ट करना होगा।ANONYMOUS_IDENTITY_SECRETखोने पर visitor identity फिर से शुरू हो जाती है: कल के सभी visitors नए माने जाएंगे, और यह बदलाव charts में दिखाई देगा।AUTH_SECRETखोने पर हर session अमान्य हो जाता है, इसलिए सभी को दोबारा sign in करना होगा।- Signing private key खोने पर आप pair को rotate कर देते हैं। कुछ भी खोता नहीं है।
दो secrets को दो-दो फाइलों में byte-identical होना चाहिए। ANONYMOUS_IDENTITY_SECRET, collector.env और worker.env में दिखाई देता है, क्योंकि collector visitor hash की गणना करता है और worker उसे लिखता है। OA_CREDENTIAL_KEYRING, api.env और worker.env में दिखाई देता है। बाकी सब कुछ जानबूझकर केवल एक service तक सीमित रखा गया है, और यदि किसी service को ऐसा secret दिया जाता है जिसे उसे नहीं रखना चाहिए, तो वह start होने के बजाय 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 में एक साइट जोड़ें और यह आपको टैग प्रदान करेगा। इसका प्रारूप निश्चित है:
<script
async
src="https://c.example.com/oa.js"
data-key="YOUR_TRACKING_KEY"
data-collector="https://c.example.com"
></script>इसे पेज के head में रखें। ट्रैकिंग की (tracking key) डिज़ाइन के अनुसार सार्वजनिक होती है, इसलिए यह आपके HTML में होनी चाहिए जहाँ कोई भी इसे पढ़ सके। स्क्रिप्ट window.oa को इंस्टॉल करती है, और oa("track", ...) जैसे कॉल्स एक स्टब (stub) द्वारा कतारबद्ध (queued) किए जाते हैं और फ़ाइल लोड होते ही फ्लश कर दिए जाते हैं, इसलिए जल्दी फायर होने वाला कोई कस्टम इवेंट ड्रॉप नहीं होता है। यदि पेज पर किसी अन्य चीज़ के पास पहले से ही window.oa का स्वामित्व है, तो ट्रैकर इसके बजाय window.openanalytics के रूप में इंस्टॉल होता है। यदि वही साइट an onion service के रूप में भी उत्तर देती है, तो उस बिल्ड से टैग को हटा दें, क्योंकि c.example.com से फेच की गई स्क्रिप्ट Tor Browser के विज़िटर को वापस clearnet पर खींच लाती है और एक ही पेज लोड में दोनों पतों को लिंक कर देती है।
फिर पूरे पाथ की एंड-टू-एंड जाँच करें:
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पहले वाले को 200 और कुछ किलोबाइट प्रिंट करना चाहिए। अपनी साइट पर एक पेज लोड करें, फिर कुछ ही सेकंड के भीतर वर्कर लॉग में बैच लाइन देखें। कलेक्टर इवेंट स्वीकार करते ही 202 का उत्तर देता है, और 202 का अर्थ है कतारबद्ध (queued), न कि संग्रहीत (stored)। वर्कर ही इवेंट्स को ClickHouse में ले जाता है। यदि इवेंट स्वीकार कर लिए जाते हैं लेकिन डैशबोर्ड में कुछ भी दिखाई नहीं देता है, तो इसका मतलब है कि वर्कर ब्लॉक है, और Valkey कतार की गहराई (queue depth) का लगातार बढ़ना इसकी पुष्टि करता है। इसके सामान्य कारण worker.env में गलत ClickHouse क्रेडेंशियल्स, या माइग्रेशन द्वारा अभी जोड़ी गई टेबल पर ग्रांट (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. को आपके द्वारा measure की जाने वाली प्रत्येक site के हर visitor के लिए reachable होना चाहिए, इसलिए उन दोनों के आगे कभी भी basic auth या IP allowlist न लगाएँ। app. और api. केवल उन लोगों के लिए reachable होने चाहिए जो 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 भी नहीं आता। यदि आपके अन्य self-hosted apps पहले से ही a single Authentik login के पीछे हैं, तो जल्दी निर्णय लें कि क्या यह dashboard उनके साथ जुड़ेगा या अपने स्वयं के accounts रखेगा, क्योंकि यहाँ आपके द्वारा बनाया गया पहला account स्थायी रूप से privileged account होता है।
एक setting यह तय करती है कि dashboard काम करेगा या नहीं। env/api.env में AUTH_TRUSTED_ORIGINS का dashboard origin से बिल्कुल मेल खाना आवश्यक है। यदि यह गलत है या गायब है, तो API कोई CORS (cross-origin resource sharing) headers emit नहीं करता है, browser हर call को अस्वीकार कर देता है, और आपको एक ऐसा dashboard मिलता है जो अपना layout तो render करता है लेकिन कोई 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 को स्थानीय रूप से आपकी अपनी डिस्क पर मौजूद DB-IP फाइल के माध्यम से हल किया जाता है, इसलिए आगंतुक के बारे में कोई भी जानकारी कभी भी होस्ट से बाहर नहीं जाती है। लुकअप को स्थानीय रखने से वेंडर हट जाता है, डेटा नहीं। यही सीमा तब भी सामने आती है जब आप अपनी खुद की SearXNG instance चलाते हैं और आपके सर्वर का IP ही वह चीज बन जाता है जिसे सर्च इंजन देखते हैं।
इसका लाभ यह है कि आगंतुक के डिवाइस पर कोई भी पहचानकर्ता (identifier) स्थायी रूप से नहीं रहता है, जो कि वह विशिष्ट कारक है जिसके कारण कोई ट्रैकर EU ePrivacy सहमति नियमों के दायरे में आता है। इसी कारण से, इस तरह के केवल aggregate डेटा वाले सेटअप अक्सर बिना किसी सहमति बैनर (consent banner) के चलाए जाते हैं। GDPR अभी भी इस बात को नियंत्रित करता है कि आप क्या स्टोर करते हैं और कितनी देर के लिए, और आपके मामले का निर्णय आपके कानूनी सलाहकार द्वारा किया जाता है, न कि किसी README फाइल द्वारा।
इसकी कीमत आपको cross-day identity के रूप में चुकानी पड़ती है। salt के रोटेशन का मतलब है कि जो व्यक्ति सोमवार को आता है और फिर बुधवार को आता है, उसे दो अलग-अलग आगंतुक गिना जाएगा; यह डिजाइन के अनुसार है और इसका कोई समाधान नहीं है। दैनिक unique counts सटीक होते हैं। साप्ताहिक और मासिक unique counts दैनिक आंकड़ों से बनाए जाते हैं और वे पहुंच (reach) को बढ़ा-चढ़ाकर दिखाएंगे, इसलिए कोई भी लंबी अवधि का "returning visitor" आंकड़ा वह नहीं मापता जो उसका नाम बताता है। Sessions और journeys एक ही दिन के भीतर विश्वसनीय होते हैं। ANONYMOUS_IDENTITY_SECRET को रोटेट करने का प्रभाव दिन बदलने जैसा ही होता है, इसलिए उस रोटेशन को नियमित रखरखाव के बजाय डेटा में बदलाव के रूप में देखें।
यह कलेक्टर Do Not Track और Global Privacy Control का सम्मान करता है, जो ब्राउज़र का वह सिग्नल है जो किसी साइट को व्यक्तिगत डेटा बेचने या साझा न करने के लिए कहता है। स्क्रिप्ट टैग में इसी उद्देश्य के लिए अपने स्वयं के स्विच होते हैं: data-respect-gpc, data-respect-dnt, और data-require-consent, जो सहमति मिलने तक सभी डेटा संग्रह को रोक कर रखते हैं और उत्तर को localStorage में oa.consent कुंजी के तहत याद रखते हैं। data-storage="none" को सेट करने से ब्राउज़र स्टोरेज पूरी तरह से बंद हो जाता है।
छह महीने बाद डिस्क भर जाने का कारण
यह समस्या 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;यह माप पहले सप्ताह में लें और फिर चौथे सप्ताह में दोबारा लें। दो points आपको growth rate बता देंगे, और growth rate से पता चल जाएगा कि volume को कब resize करने की आवश्यकता है। August 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 में एक matching oa_maintenance user का होना भी जरूरी है। इनके बिना, deletion हमेशा के लिए queue में पड़ा रहता है। site dashboard से गायब हो जाती है और हर row डिस्क पर बनी रहती है, जिससे आपको सफाई होने का आभास तो होता है, लेकिन जगह वापस नहीं मिलती।
अपग्रेड और तीन लागतें
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_* ऑरिजिन्स को ब्राउज़र बंडल में कंपाइल किया जाता है और कंटेनर शुरू होने पर प्रतिस्थापित (substitute) किया जाता है, इसलिए गलत होस्टनेम को कॉल करने वाले डैशबोर्ड को docker compose up -d --force-recreate web से ठीक किया जाता है, न कि restart से। वेब कंटेनर का लॉग उन ऑरिजिन्स को प्रिंट करता है जिनके साथ वह शुरू हुआ था, जो यह पुष्टि करने का सबसे तेज़ तरीका है कि सुधार लागू हो गया है।
यदि कॉन्फ़िगरेशन में बदलाव के बाद ClickHouse शुरू होने से मना कर देता है, तो उसके लॉग की पहली पंक्ति पढ़ें। oa-entrypoint: से शुरू होने वाली पंक्ति का अर्थ है कि एंट्रीपॉइंट आपके द्वारा सेट किए गए मान को अस्वीकार कर रहा है। इसके अलावा कुछ भी होने का सामान्य अर्थ यह है कि कॉन्फ़िगरेशन फ़ाइल अमान्य XML है, और इसका सबसे आम कारण XML कमेंट के अंदर डबल हाइफ़न का होना है, जो वहां अवैध है।
AGPL-3.0, और नाम
यह कोड AGPL-3.0 लाइसेंस के अंतर्गत आता है। इसे अपनी साइटों के लिए बिना किसी बदलाव के चलाने पर कोई भी प्रकाशन दायित्व (publishing obligation) उत्पन्न नहीं होता है। दायित्व तब शुरू होता है जब आप कोड में बदलाव करते हैं और उस संशोधित संस्करण को नेटवर्क सेवा के रूप में चलाते हैं: ऐसी स्थिति में लाइसेंस यह अनिवार्य करता है कि आप अपने संशोधित स्रोत कोड को उस सेवा के उपयोगकर्ताओं को उपलब्ध कराएं। इसमें आपके इंस्टेंस पर क्लाइंट्स को डैशबोर्ड देना और इसे किसी ऐसी चीज़ में बंडल करना शामिल है जिसे आप बेचते हैं। अपने परिवर्तनों को एक सार्वजनिक 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) की कमी है जिसे हाल ही के माइग्रेशन ने बनाया है।
जब हर कंटेनर हेल्दी है तो डैशबोर्ड खाली क्यों है?
सबसे पहले env/api.env में AUTH_TRUSTED_ORIGINS की जाँच करें। इसे डैशबोर्ड ओरिजिन से बिल्कुल मेल खाना चाहिए, और यदि ऐसा नहीं होता है तो API कोई CORS हेडर नहीं भेजता है, इसलिए ब्राउज़र हर कॉल को अस्वीकार कर देता है और आपको बिना डेटा वाला वर्किंग लेआउट दिखता है। दूसरी चीज़ जो जाँचनी है, वह env/web.env में तीन NEXT_PUBLIC_* मान हैं, जिन्हें वेब कंटेनर शुरू होने पर सब्स्टिट्यूट किया जाता है। उन्हें ठीक करने के लिए docker compose up -d --force-recreate web की आवश्यकता होती है, क्योंकि केवल रीस्टार्ट करने से पुराने मान ही बने रहते हैं।
क्या AGPL-3.0 मुझे इसे क्लाइंट्स को ऑफर करने से रोकता है?
नहीं, यह केवल एक शर्त जोड़ता है। कोड को बिना किसी बदलाव के चलाएं और आपको किसी को कुछ भी देने की आवश्यकता नहीं है। यदि आप इसमें बदलाव करते हैं और उस संशोधित संस्करण को ऐसी सर्विस के रूप में चलाते हैं जिसका उपयोग अन्य लोग करते हैं, तो आपको उन उपयोगकर्ताओं को अपना संशोधित सोर्स कोड उपलब्ध कराना होगा, जिसे एक पब्लिक फोर्क (public fork) के माध्यम से पूरा किया जा सकता है। इसके अलावा, "OpenAnalytics" नाम कोड के साथ लाइसेंस प्राप्त नहीं है, इसलिए आप जो कुछ भी बेचते हैं उसे अपना नाम देना होगा।