SSD Nodes Learn 🎉 VPS เริ่ม $5.50/เดือน
คู่มือ Matt Connorโดย Matt Connor · อัปเดตเมื่อ 2026-08-16

เปรียบเทียบเครื่องมือวิเคราะห์เว็บ Self-hosted บน VPS

แนะนำการเลือกใช้ Plausible, Umami, Matomo และ GoAccess บน VPS ขนาดเล็ก พร้อมข้อมูลการใช้ RAM การจัดการฐานข้อมูล การตั้งค่า Reverse Proxy และปัญหาเรื่อง Ad blocker

เครื่องมือวิเคราะห์เว็บแบบ self-hosted ตัวใดที่ควรใช้งานบน VPS?

เครื่องมือวิเคราะห์เว็บแบบ self-hosted แบ่งออกเป็น 2 ประเภทหลัก การเลือกประเภทผิดจะทำให้คุณมีภาระมากกว่าการเลือกใช้ผลิตภัณฑ์ผิด ประเภทแรกจะรันสคริปต์ขนาดเล็กในเบราว์เซอร์ของผู้เข้าชมและจัดเก็บข้อมูลที่สคริปต์นั้นรายงานกลับมา ส่วนประเภทที่สองจะอ่านจาก access log ที่เว็บเซิร์ฟเวอร์ของคุณเขียนบันทึกไว้อยู่แล้ว ทุกอย่างหลังจากนั้น รวมถึงฐานข้อมูลและหน่วยความจำที่จำเป็น จะขึ้นอยู่กับการตัดสินใจเลือกในขั้นตอนนี้

คำตอบสั้นๆ สำหรับเซิร์ฟเวอร์ขนาดเล็ก: GoatCounter และ Medama สามารถรันบน RAM 1 GB ได้ เนื่องจากแต่ละตัวเป็นเพียงกระบวนการเดียวที่ทำงานบนไฟล์เดียว ส่วน Umami จะเพิ่มคอนเทนเนอร์ Postgres เข้ามาและให้แดชบอร์ดที่ผู้ใช้งานทั่วไปสามารถอ่านเข้าใจได้ง่าย สำหรับ Plausible Community Edition และ Rybbit ทั้งคู่ต้องใช้ ClickHouse ดังนั้นควรเตรียม RAM ไว้ 2 GB ขึ้นไป Matomo เป็นผลิตภัณฑ์เต็มรูปแบบซึ่งต้องการเซิร์ฟเวอร์ที่มีขนาดเหมาะสมกับปริมาณ traffic ของคุณ ในขณะที่ GoAccess ไม่เพิ่มภาระใดๆ ให้กับหน้าเว็บเลย เพราะมันทำหน้าที่เพียงแค่อ่าน log ที่มีอยู่แล้วเท่านั้น

Script tag หรือ server log: สิ่งที่แต่ละวิธีมองเห็น

Script tag ทำหน้าที่วัดผลจากเบราว์เซอร์ เมื่อหน้าเว็บโหลด สคริปต์จะทำงานและส่งคำขอหนึ่งรายการไปยังตัวเก็บข้อมูล (collector) ของคุณ สิ่งใดก็ตามที่ทำให้ห่วงโซ่นี้ขาดตอนจะทำให้คุณมองไม่เห็นข้อมูลนั้น เช่น การปิดใช้งาน JavaScript, รายการตัวกรองที่บล็อกคำขอ, คำขอไปยัง collector ล้มเหลว หรือ crawler ที่ไม่ประมวลผลสคริปต์

Log parser ทำหน้าที่วัดผลจากคำขอ เว็บเซิร์ฟเวอร์ของคุณจะเขียนบันทึกหนึ่งบรรทัดต่อหนึ่งคำขอไม่ว่าคุณจะติดตั้งอะไรไว้หรือไม่ก็ตาม ดังนั้นข้อมูลจึงถูกจัดเก็บอยู่ในดิสก์อยู่แล้ว วิธีนี้มองเห็น crawler ทุกตัวและทุกการเข้าถึงไฟล์ที่ไม่มี script tag ติดตั้งอยู่ แต่ไม่สามารถมองเห็นสิ่งที่เกิดขึ้นภายในเบราว์เซอร์ และไม่สามารถมองเห็นหน้าเว็บที่ถูกเรียกจากแคชของเบราว์เซอร์หรือจาก CDN (content delivery network) ที่อยู่หน้าเซิร์ฟเวอร์ของคุณได้ เนื่องจากคำขอดังกล่าวไม่เคยมาถึงเซิร์ฟเวอร์ของคุณ

ตัวเลขจากทั้งสองวิธีจะไม่ตรงกัน และไม่มีวิธีใดที่ผิด Matomo สามารถทำได้ทั้งสองอย่าง และได้ระบุสิ่งที่การนำเข้า log (log import) จะสูญเสียไปเมื่อเทียบกับ JavaScript tracker ไว้ดังนี้: ความละเอียดหน้าจอ, ชื่อหน้าเว็บ, เหตุการณ์ (events), การติดตามเนื้อหา (content tracking), heatmap, การบันทึกเซสชัน (session recordings) และการวิเคราะห์ฟอร์ม (form analytics) รายการเหล่านี้คือสิ่งที่ต้องแลกมาจากการนับจำนวนคำขอแทนการนับจำนวนเบราว์เซอร์

Traffic จากบอทเป็นอีกครึ่งหนึ่งของช่องว่างนี้ การนับจาก log จะรวม crawler เข้าไปด้วยเว้นแต่คุณจะกรองออก ซึ่งในเว็บไซต์ทั่วไปสัดส่วนของ crawler นั้นมีมากพอที่จะทำให้ข้อสรุปของคุณคลาดเคลื่อนได้ ทั้ง GoAccess และการนำเข้า log ของ Matomo ต่างก็มีตัวกรองบอทที่รู้จัก แต่ไม่มีวิธีใดที่สามารถกรอง crawler ที่ปลอมแปลง user agent ได้ ซึ่งเป็นเหตุผลที่ดีในการจับคู่การนับจาก log เข้ากับการ บล็อก AI crawler ที่ระดับเซิร์ฟเวอร์ และควรอ่าน log หลังจากทำการบล็อกแล้วแทนที่จะอ่านก่อนบล็อก

GoAccess: การวิเคราะห์จาก log ที่คุณมีอยู่แล้ว

ติดตั้งโปรแกรมจาก repository ของ Debian และ Ubuntu โดยตรง เนื่องจากแพ็กเกจใน distribution มักจะล้าหลังกว่าเวอร์ชันที่ปล่อยออกมาจริง

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

จากนั้นระบุไฟล์ log และเขียนรายงานแบบ static

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

คำสั่งดังกล่าวจะล้มเหลวด้วยข้อผิดพลาด Permission denied สำหรับผู้ใช้ทั่วไป เนื่องจากบน Ubuntu ไฟล์ log ของ nginx จะถูกครอบครองโดย root และมีกลุ่มเป็น adm ให้เพิ่มชื่อผู้ใช้ของคุณเข้าในกลุ่มดังกล่าวด้วยคำสั่ง sudo usermod -aG adm $USER จากนั้นให้ log out และ log in ใหม่ เนื่องจากระบบจะอ่านการเป็นสมาชิกกลุ่มเฉพาะตอน login เท่านั้น ให้รันคำสั่ง id และตรวจสอบว่า adm ปรากฏอยู่ในรายการก่อนที่จะลองใหม่อีกครั้ง

รายงานจาก log แบบสดจะครอบคลุมเฉพาะข้อมูลที่ logrotate ยังไม่ได้ย้ายไปเท่านั้น คำขอของเมื่อวานจะอยู่ใน access.log.1 และไฟล์ที่เก่ากว่านั้นจะถูกบีบอัดไว้ ดังนั้นการดูรายงานรายสัปดาห์จึงจำเป็นต้องอ่านไฟล์ที่ถูก rotate ไปแล้วด้วยเช่นกัน

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

นอกจากนี้ยังมีโหมดแสดงผลสดคือ --real-time-html ซึ่งจะอัปเดตหน้าเว็บผ่าน WebSocket วิธีนี้จำเป็นต้องใช้พอร์ตที่สองและกฎของ proxy แยกต่างหาก สำหรับเว็บไซต์ส่วนใหญ่ การสร้างรายงานรายชั่วโมงด้วย cron นั้นเพียงพอแล้วและมีความเสี่ยงด้านความปลอดภัยน้อยกว่า

GoatCounter: หนึ่ง Go binary และหนึ่งไฟล์ SQLite

GoatCounter ถูกจัดส่งในรูปแบบ binary ที่คอมไพล์แบบ static จึงไม่มี runtime ที่ต้องติดตั้ง ให้ดาวน์โหลด build จากหน้า release แล้วเรียกใช้งาน หรือใช้ image ก็ได้

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

เมื่อรันเป็น binary ตัว goatcounter serve จะฟังที่พอร์ต 8080 และสร้างไฟล์ SQLite ไว้ที่ ./goatcounter-data/db.sqlite3 ให้สร้างไซต์แรกผ่าน command line แทนการใช้ web wizard ในกรณีที่ instance อยู่หลัง proxy แล้ว

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

ตัวโปรแกรมสามารถจัดการ certificate ของตนเองได้ด้วย goatcounter serve -listen=:443 -tls=tls,rdr,acme โดยใช้ ACME (automatic certificate management environment) ซึ่งมีประโยชน์สำหรับเครื่องที่ไม่ได้รันบริการอื่น ในกรณีที่ nginx หรือ Caddy ใช้งานพอร์ต 443 อยู่แล้ว ให้ปล่อย GoatCounter ไว้ที่พอร์ต 8080 และทำ proxy ไปยังพอร์ตดังกล่าวแทน สคริปต์ติดตามมีขนาดประมาณ 3.5K ตามข้อมูลของโครงการ และยังมี tracking pixel สำหรับหน้าเว็บที่ไม่มี JavaScript หาก SQLite กลายเป็นข้อจำกัดสำหรับไซต์ที่มีการใช้งานสูง binary ตัวเดียวกันนี้สามารถรองรับ Postgres ได้ด้วย goatcounter serve -db 'postgresql+dbname=goatcounter' การสำรองข้อมูลทำได้โดยการคัดลอกไฟล์ ซึ่งเป็นข้อดีหลักของเครื่องมือในรูปแบบนี้

Medama: คอนเทนเนอร์เดี่ยวที่ใช้หน่วยความจำ 256 MB

Medama เป็นตัวเลือกแบบ single binary ล่าสุดในกลุ่มนี้ โดยถูกออกแบบมาให้ไม่มีการใช้คุกกี้ และทางโครงการระบุว่าตัวติดตามมีขนาดเล็กกว่า 1 KB อีกทั้งยังรองรับเว็บไซต์ขนาดเล็กที่รันบนเครื่องเสมือน (virtual machine) ที่มีหน่วยความจำ 256 MB นี่คือข้อมูลที่ทางโครงการเผยแพร่ ไม่ใช่ตัวเลขที่วัดผลสำหรับการจัดทำคู่มือนี้

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 การใส่ prefix สำหรับ loopback ไว้ข้างต้นนั้นเป็นความตั้งใจ และส่วนของ reverse proxy จะอธิบายเหตุผลไว้ การเข้าสู่ระบบครั้งแรกใช้ admin ด้วยรหัสผ่าน CHANGE_ME_ON_FIRST_LOGIN ซึ่งชื่อของรหัสผ่านนั้นก็คือคำสั่งที่ต้องปฏิบัติตาม

รูปแบบความล้มเหลวที่ระบุไว้ในเอกสารอย่างหนึ่งอาจทำให้คุณติดขัดได้ การเข้าสู่ระบบจะทำงานผ่าน HTTPS หรือบน localhost เท่านั้น ดังนั้นหากคุณตั้งค่า proxy ก่อนที่จะมีใบรับรอง (certificate) ฟอร์มจะปฏิเสธรหัสผ่านที่ถูกต้องโดยไม่แสดงเหตุผลให้ทราบ ให้ดำเนินการตั้งค่า TLS (transport layer security) ให้เสร็จสิ้นก่อน แล้วจึงค่อยเข้าสู่ระบบ

Umami: Postgres และแดชบอร์ดที่คุ้นเคย

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

คำสั่งดังกล่าวจะเริ่มการทำงานของแอปพลิเคชันบนพอร์ต 3000 โดยมีคอนเทนเนอร์ PostgreSQL ทำงานควบคู่กัน เอกสารระบุว่า PostgreSQL v12.14 เป็นเวอร์ชันขั้นต่ำที่รองรับ และหากคุณ build จาก source จะต้องใช้ Node.js 18.18 หรือใหม่กว่า ทั้งนี้มี image ที่ build ไว้ล่วงหน้าคือ docker.umami.is/umami-software/umami:postgresql-latest ซึ่งจำเป็นต้องตั้งค่า DATABASE_URL ให้ชี้ไปยังฐานข้อมูลที่คุณใช้งานอยู่แล้ว

การเข้าสู่ระบบครั้งแรกให้ใช้ admin พร้อมรหัสผ่าน umami คุณควรเปลี่ยนรหัสผ่านก่อนที่จะชี้ DNS มายังเซิร์ฟเวอร์ เนื่องจาก instance จะสามารถเข้าถึงได้จากอินเทอร์เน็ตทันทีที่ record มีผลและ proxy ตอบรับคำขอ สำหรับรายละเอียดเกี่ยวกับ Compose, ไฟล์ environment และนโยบายการ restart โปรดดูที่ Docker Compose stack บน VPS แทนการคัดลอก stack ที่คุณยังไม่ได้อ่านทำความเข้าใจ

ทรัพยากรที่ใช้ประกอบด้วยกระบวนการ Node และ Postgres ซึ่งถือว่าใช้ทรัพยากรมากกว่าการรัน binary ไฟล์เดียว แต่เบากว่าการรันระบบใดๆ ที่ใช้ 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

เวอร์ชัน v3.2.1 เป็นเวอร์ชันปัจจุบัน ณ เดือนสิงหาคม 2026 และคำสั่ง clone ได้ระบุเวอร์ชันนี้ไว้โดยเฉพาะ สแต็กของระบบประกอบด้วย 3 ส่วน ได้แก่ ตัวแอปพลิเคชัน, Postgres สำหรับบัญชีและการตั้งค่า และ ClickHouse สำหรับข้อมูลเหตุการณ์ SECRET_KEY_BASE จะต้องมีความยาวอย่างน้อย 64 ไบต์ ซึ่งเป็นสิ่งที่ได้จากคำสั่ง openssl

ข้อกำหนดของ Plausible ระบุว่าต้องใช้ RAM อย่างน้อย 2 GB เพื่อป้องกันไม่ให้ ClickHouse และตัวแอปพลิเคชันถูกระบบสั่งยุติการทำงานด้วย out of memory killer รวมถึงต้องใช้ CPU ที่รองรับชุดคำสั่ง SSE 4.2 หรือ NEON ซึ่ง ClickHouse จำเป็นต้องใช้ ข้อกำหนดประการที่สองนี้ควรตรวจสอบก่อนตัดสินใจซื้อ และเป็นหนึ่งในความแตกต่างเชิงปฏิบัติใน การเลือกระหว่าง ARM และ x86 VPS นอกจากนี้ ClickHouse จะพยายามใช้หน่วยความจำเท่าที่มีอยู่ ดังนั้นหากใช้งานบนเซิร์ฟเวอร์ร่วมกับบริการอื่น ควรตั้งค่าเพดานหน่วยความจำตามที่อธิบายไว้ใน การจำกัดหน่วยความจำคอนเทนเนอร์ใน Compose

BASE_URL จะต้องตรงกับ URL สาธารณะอย่างแม่นยำ หากไม่ตรงกัน เมื่อคุณล็อกอิน แอปพลิเคชันจะเปลี่ยนเส้นทางไปยังโฮสต์ที่ผิด และ session cookie จะถูกเขียนลงในโดเมนที่เบราว์เซอร์ของคุณไม่ได้ใช้งานอยู่ ส่งผลให้คุณถูกส่งกลับมาที่หน้าล็อกอินโดยไม่มีข้อความแจ้งเตือนใดๆ

ไฟล์ compose ที่ให้มาไม่ได้เปิดพอร์ตไว้ เนื่องจากคาดการณ์ว่าจะมีการใช้งานพร็อกซีอยู่ด้านหน้า ให้เพิ่มไฟล์ override เพื่อเปิดพอร์ตแอปพลิเคชันเริ่มต้นบน loopback เท่านั้น

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

Matomo: ตัวผลิตภัณฑ์เต็มรูปแบบและเซิร์ฟเวอร์ที่ต้องการ

Matomo ทำงานบน PHP ร่วมกับ MySQL หรือ MariaDB ซึ่งหมายความว่ามันเหมาะกับ stack เว็บแบบดั้งเดิมมากกว่า container stack นอกจากนี้ยังเป็นเครื่องมือเดียวในที่นี้ที่มีการเผยแพร่คำแนะนำด้านฮาร์ดแวร์ตามปริมาณ traffic

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
  }
]

ตัวเลขเหล่านั้นคือค่าขั้นต่ำที่ Matomo เผยแพร่ ณ เดือนสิงหาคม 2026 ไม่ใช่การวัดผลที่ทำขึ้นสำหรับคู่มือนี้ สำหรับยอดการเข้าชมสูงสุด 100,000 หน้าต่อเดือน Matomo ต้องการ CPU จำนวน 2 คอร์, RAM 2 GB และ SSD 50 GB โดยใช้เซิร์ฟเวอร์หนึ่งเครื่องสำหรับทั้งแอปพลิเคชันและฐานข้อมูล ที่ระดับ 1M/month ความต้องการจะเพิ่มเป็น RAM 8 GB และพื้นที่ดิสก์ 250 GB ที่ระดับ 10M/month Matomo แนะนำให้ใช้เซิร์ฟเวอร์สองเครื่อง โดยแถวสุดท้ายแสดงสเปกของเซิร์ฟเวอร์ฐานข้อมูลคือ RAM 16 GB และพื้นที่ดิสก์ 400 GB โปรดอ่านตัวเลขพื้นที่ดิสก์เหล่านั้นเทียบกับตัวเลือกแบบ binary ไฟล์เดียว ซึ่งชุดข้อมูลทั้งหมดจะถูกเก็บเป็นไฟล์ SQLite ไฟล์เดียว

กระบวนการ Archiving เป็นสิ่งที่ทำให้ผู้ใช้ประหลาดใจ โดยปกติ Matomo จะสร้างรายงานเมื่อมีคนเปิดหน้า dashboard ดังนั้นเมื่อข้อมูลมีขนาดใหญ่ขึ้น dashboard จะทำงานช้าลงและหมดเวลา (timeout) ในที่สุด วิธีแก้ไขที่ระบุไว้ในเอกสารคือการปิดการทำงานของ browser triggered archiving ในการตั้งค่าทั่วไป แล้วเปลี่ยนไปรัน archiver ผ่าน cron แทน โดยรันในฐานะผู้ใช้ที่เป็นเจ้าของไฟล์ Matomo จากภายในไดเรกทอรีของ Matomo

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

Matomo ยังคงเก็บตาราง log ดิบไว้ควบคู่กับตารางรายงานที่ประมวลผลแล้ว และสามารถตั้งเวลาลบข้อมูลดิบเก่าและรายงานเก่าได้ ให้เปิดใช้งานฟังก์ชันนี้ตั้งแต่ตอนติดตั้ง ไม่ใช่รอจนกว่าดิสก์จะเต็ม นอกจากนี้ Matomo ยังสามารถนำเข้า server access logs ได้ ซึ่งทำให้มันเป็นผลิตภัณฑ์เดียวในที่นี้ที่ครอบคลุมทั้งสองรูปแบบพร้อมกัน

Rybbit และ stack รุ่นใหม่

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

Rybbit เป็นซอฟต์แวร์ที่เพิ่งเปิดตัวพร้อมแดชบอร์ดที่ทันสมัย สคริปต์การติดตั้งจะเขียนไฟล์ environment และเริ่มการทำงานของ stack ด้วย Docker Compose โดยมีการรัน ClickHouse และมาพร้อมกับ Caddy ในฐานะเว็บเซิร์ฟเวอร์ของตัวเอง ซึ่งจะเข้าใช้งานพอร์ต 443 และร้องขอใบรับรองสำหรับโดเมนที่คุณระบุ หากบนเซิร์ฟเวอร์มี nginx ใช้งานพอร์ต 443 อยู่แล้ว สคริปต์จะไม่สามารถ bind พอร์ตได้ ดังนั้นให้ใช้วิธีการตั้งค่า Compose ด้วยตนเองของโปรเจกต์และนำไปวางไว้หลัง proxy ที่คุณใช้งานอยู่ เอกสารระบุว่าต้องการ RAM อย่างน้อย 2 GB โดยผ่านการทดสอบบน Ubuntu 24 LTS และต้องใช้สถาปัตยกรรม ARMv8.2-A หรือใหม่กว่าในกรณีของ ARM เนื่องจากข้อกำหนดของ ClickHouse

ข้อควรระวังตามความเป็นจริงสำหรับโปรเจกต์ใหม่คือ ฟีเจอร์ต่างๆ ถูกเพิ่มเข้ามาอย่างรวดเร็วและอาจมีการเปลี่ยนแปลงที่ส่งผลกระทบต่อระบบ (breaking changes) ควรระบุเวอร์ชัน (pin a tag) อ่านบันทึกการปรับปรุง (release notes) ก่อนทำการ pull และสำรองข้อมูลฐานข้อมูลไว้ก่อนเสมอ

การเก็บรักษาข้อมูลและการเพิ่มขึ้นของขนาดดิสก์: วัดผลด้วยตนเองบนเซิร์ฟเวอร์ของคุณ

การเพิ่มขึ้นของขนาดดิสก์ขึ้นอยู่กับสิ่งที่เครื่องมือจัดเก็บต่อเหตุการณ์ GoatCounter จะรวมยอดการเข้าชมเข้าเป็นตัวนับ ดังนั้นไฟล์จะขยายตัวตามจำนวนหน้าและวันที่ที่ไม่ซ้ำกันมากกว่าปริมาณข้อมูลดิบ ส่วน Umami และ Matomo จะจัดเก็บข้อมูลเป็นแถวต่อเหตุการณ์ และ Matomo จะจัดเก็บตารางรายงานที่ประมวลผลแล้วเพิ่มเติมจากข้อมูลดิบ ในขณะที่ ClickHouse จะจัดเก็บเหตุการณ์ในรูปแบบคอลัมน์และบีบอัดข้อมูลอย่างแน่นหนา ซึ่งเป็นเหตุผลว่าทำไม Plausible จึงรับมือกับปริมาณข้อมูลที่อาจทำให้ฐานข้อมูลแบบแถวทั่วไปทำงานหนักเกินไปได้

คู่มือนี้ไม่ได้ระบุตัวเลขจำนวนเมกะไบต์ต่อการเข้าชมหนึ่งล้านครั้ง เนื่องจากไม่ได้วัดผลจากปริมาณการใช้งานจริงของคุณ ให้คุณทำการวัดผลด้วยตนเอง โดยปรับชื่อบริการและชื่อผู้ใช้ให้ตรงกับไฟล์ 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 หยุดทำงาน ไม่ใช่แค่ระบบวิเคราะห์ข้อมูลเท่านั้น ซึ่งเป็นเหตุผลสำคัญที่สุดในการจัดเก็บ volume ของฐานข้อมูลไว้ในตำแหน่งที่ df -h สามารถแจ้งเตือนคุณได้ ความเสี่ยงนี้ควรได้รับความสนใจมากขึ้นบนเซิร์ฟเวอร์ที่มีข้อมูลขนาดใหญ่อยู่แล้ว เพราะ เซิร์ฟเวอร์รูปภาพแบบ self-hosted จะทำให้พื้นที่ดิสก์เต็มเร็วกว่าฐานข้อมูลวิเคราะห์ข้อมูลใดๆ มาก

พฤติกรรมเมื่อทำงานอยู่หลัง reverse proxy บน subdomain

ให้วาง collector ไว้บน subdomain ของเว็บไซต์ที่ต้องการวัดผล เช่น stats.example.com วิธีนี้จะทำให้คำขอของ collector กลายเป็น first party ซึ่งจะไม่ถูกบล็อกโดยกฎของเบราว์เซอร์ที่จัดการกับคำขอ third party

ให้ bind แอปพลิเคชันเข้ากับ loopback เมื่อคุณ publish พอร์ตของ container เนื่องจาก Docker จะเขียนกฎ firewall ของตัวเองนำหน้า ufw ดังนั้น container ที่ถูก publish ด้วย -p 3000:3000 จึงสามารถเข้าถึงได้จากอินเทอร์เน็ตแม้ว่า ufw status จะระบุว่าพอร์ตถูกปฏิเสธก็ตาม ให้ทดสอบจากเครื่องอื่นด้วย curl http://SERVER_IP:3000 แล้วคุณจะพบหน้า dashboard หาก publish ด้วย -p 127.0.0.1:3000:3000 การทดสอบแบบเดียวกันจะให้ผลลัพธ์เป็น Connection refused และมีเพียง proxy เท่านั้นที่สามารถเข้าถึงได้

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;
    }
}

การส่งต่อ header (forwarding headers) เป็นสิ่งที่จำเป็นในกรณีนี้ หากไม่มี X-Forwarded-For การเข้าชมทุกครั้งจะปรากฏว่ามาจาก 127.0.0.1 ส่งผลให้รายงานข้อมูลรายประเทศว่างเปล่าและจำนวนผู้เข้าชมที่ไม่ซ้ำกัน (unique visitors) จะถูกนับรวมเหลือเพียงหนึ่งเดียว แต่ละโปรเจกต์จะมีนโยบายการเชื่อถือ header ที่แตกต่างกันไปตามการตั้งค่า ดังนั้นควรตรวจสอบเอกสารประกอบของ proxy สำหรับโปรเจกต์นั้นๆ แทนการคาดเดา ทั้งนี้ Caddy จะตั้งค่า header เหล่านี้ให้โดยอัตโนมัติ และ Caddyfile สำหรับงานเดียวกันนี้ใช้เพียงสองบรรทัดเท่านั้น

stats.example.com {
    reverse_proxy 127.0.0.1:3000
}

หากคุณยังไม่ได้เลือก proxy การเปรียบเทียบระหว่าง nginx, Caddy และ Traefik จะช่วยให้คุณทราบว่าตัวเลือกใดเหมาะสมที่สุดสำหรับเซิร์ฟเวอร์เครื่องเดียวที่มี subdomain จำนวนไม่มาก

คุณยังจำเป็นต้องมีแบนเนอร์คุกกี้หากคุณโฮสต์บริการด้วยตนเองหรือไม่

การโฮสต์บริการด้วยตนเอง (self-hosting) เปลี่ยนผู้ถือครองข้อมูล แต่ไม่ได้เปลี่ยนข้อกำหนดทางกฎหมายเกี่ยวกับข้อมูลนั้น โปรดแยกกฎสองข้อนี้ออกจากกัน กฎการให้ความยินยอมตาม ePrivacy เกี่ยวข้องกับการจัดเก็บหรือการอ่านข้อมูลใดๆ บนอุปกรณ์ของผู้เข้าชม ดังนั้นเครื่องมือที่ไม่ตั้งค่าคุกกี้และไม่เขียนข้อมูลใดๆ ลงใน local storage จึงอยู่นอกเหนือข้อกำหนดเฉพาะส่วนนี้ ส่วน GDPR เกี่ยวข้องกับการประมวลผลข้อมูลส่วนบุคคล และที่อยู่ IP ถือเป็นข้อมูลส่วนบุคคล ดังนั้นคุณยังคงต้องมีฐานทางกฎหมายในการประมวลผล มีการจำกัดระยะเวลาการเก็บรักษา และมีคำตอบเมื่อมีผู้สอบถามว่าคุณเก็บข้อมูลอะไรเกี่ยวกับพวกเขาไว้บ้าง

Plausible, Umami, GoatCounter และ Medama ไม่ตั้งค่าคุกกี้โดยค่าเริ่มต้น สิ่งที่แต่ละเครื่องมือใช้ประมวลผลแทนนั้นแตกต่างกันไปตามแต่ละโปรเจกต์และอาจเปลี่ยนแปลงระหว่างเวอร์ชัน ดังนั้นโปรดอ่านเอกสารเกี่ยวกับความเป็นส่วนตัวของโปรเจกต์นั้นๆ โดยตรงแทนการอ่านบทสรุป Matomo มีฟีเจอร์การทำ IP anonymisation และ endpoint สำหรับการ opt-out ซึ่งคุณสามารถเปิดใช้งานได้ในหน้าอินเทอร์เฟซผู้ดูแลระบบ

หน่วยงานกำกับดูแลในแต่ละประเทศมีข้อสรุปที่แตกต่างกัน ตัวอย่างเช่น CNIL ของประเทศฝรั่งเศสได้เผยแพร่เงื่อนไขที่การวัดผลผู้ชมอาจได้รับการยกเว้นจากการขอความยินยอม ส่วนนี้เป็นเพียงบทสรุปข้อเท็จจริงไม่ใช่คำแนะนำทางกฎหมาย สำหรับเว็บไซต์จริงที่มีผู้ใช้งานจริง โปรดปรึกษาทนายความในเขตอำนาจศาลของคุณ

ประเด็นหนึ่งที่ผู้คนมักมองข้ามคือ access log ก็ถือเป็นข้อมูลส่วนบุคคลเช่นกัน GoAccess ไม่ได้เพิ่มสคริปต์ใดๆ ลงในหน้าเว็บ แต่ยังคงประมวลผลที่อยู่ IP ดังนั้นการวิเคราะห์ข้อมูลจาก log จึงไม่ได้อยู่นอกเหนือกฎระเบียบโดยอัตโนมัติ

ตัวบล็อกโฆษณาและสาเหตุที่ตัวเลขของคุณจะลดลง

รายการตัวกรอง (filter lists) จะจับคู่จากชื่อโฮสต์และรูปแบบของ URL ผลิตภัณฑ์วิเคราะห์ข้อมูลแบบโฮสต์ (hosted analytics) นั้นตรวจจับได้ง่าย เพราะทุกคนโหลดข้อมูลจากชื่อโฮสต์ที่เป็นที่รู้จักเหมือนกันหมด การย้ายตัวเก็บข้อมูล (collector) ไปยังโดเมนย่อยของคุณเองจะช่วยลบชื่อโฮสต์นั้นออกจากการร้องขอ และการให้บริการสคริปต์จาก path ที่คุณเลือกเองจะช่วยลบชื่อไฟล์ที่เป็นที่รู้จักออกไป ทั้งสองวิธีนี้เปลี่ยนสิ่งที่รายการตัวกรองต้องใช้ในการจับคู่

โพสต์นี้ไม่ได้ยืนยันอัตราการตรวจจับ (hit rate) เนื่องจากไม่ได้ทำการวัดผล สัดส่วนของผู้เข้าชมที่บล็อกการตั้งค่าใดการตั้งค่าหนึ่งนั้นขึ้นอยู่กับกลุ่มเป้าหมายของคุณ โดยกลุ่มนักพัฒนาจะมีการบล็อกมากกว่ากลุ่มผู้ใช้งานทั่วไปอย่างมาก ให้คุณวัดช่องว่างของข้อมูลด้วยตนเอง ในช่วงสัปดาห์เดียวกัน ให้คุณนับจำนวนการร้องขอหน้า HTML ใน access log ด้วย GoAccess แล้วนำไปเปรียบเทียบกับจำนวนการดูหน้าเว็บ (pageviews) ที่เครื่องมือแบบใช้สคริปต์ของคุณรายงาน ผลต่างที่ได้คือจำนวนการเข้าชมที่ถูกบล็อกรวมกับหน้าที่ถูกเรียกจากแคชบนเว็บไซต์ของคุณ

คาดการณ์ได้ว่าตัวเลขรวมจะเปลี่ยนแปลงในวันที่คุณเปลี่ยนจากผลิตภัณฑ์แบบโฮสต์ และคาดการณ์ได้ว่าส่วนหนึ่งของการเปลี่ยนแปลงนั้นอาจไม่เกี่ยวข้องกับการบล็อกเลย ผลิตภัณฑ์แต่ละตัวมีนิยามของ "การดูหน้าเว็บ" ที่แตกต่างกัน รวมถึงการนับการเปลี่ยนเส้นทาง (route change) ภายในแอปพลิเคชันหน้าเดียว (single page application) และช่วงเวลาที่เซสชันสิ้นสุดลง ให้เปรียบเทียบแนวโน้มในแต่ละสัปดาห์ก่อนที่จะสรุปว่าปริมาณการเข้าชมลดลงจริง

เลือกเครื่องมือให้เหมาะกับเว็บไซต์

  • เว็บไซต์ส่วนตัวหรือบล็อกที่มีผู้เข้าชมประมาณ 50,000 ครั้งต่อเดือน: ใช้ GoatCounter หรือ Medama บน VPS ขนาด 1 GB โดยสำรองข้อมูลด้วยการคัดลอกไฟล์
  • เว็บไซต์ที่ไม่สามารถเพิ่มสคริปต์ได้ หรือกลุ่มผู้ใช้งานมีการบล็อกสคริปต์อย่างหนัก: ใช้ GoAccess วิเคราะห์จาก log ที่มีอยู่ตามกำหนดเวลา
  • เว็บไซต์ธุรกิจขนาดเล็กที่มีผู้อื่นคอยอ่านแดชบอร์ด: ใช้ Umami ร่วมกับคอนเทนเนอร์ Postgres
  • เว็บไซต์ที่ต้องการติดตามเป้าหมาย (goals) และเส้นทางของผู้ใช้ (funnels) บนเซิร์ฟเวอร์ที่มี RAM 2 GB ขึ้นไป: ใช้ Plausible Community Edition หรือ Rybbit หากต้องการแดชบอร์ดที่ทันสมัยกว่าและยอมรับโครงการที่ใหม่กว่าได้
  • เว็บไซต์จำนวนมาก, บัญชีผู้ใช้หลายระดับ หรือมีความจำเป็นต้องเก็บข้อมูลดิบภายใต้นโยบายการเก็บรักษาข้อมูลของคุณเอง: ใช้ Matomo โดยปรับขนาดตามคำแนะนำที่ระบุไว้ข้างต้น

ให้เริ่มต้นด้วยเครื่องมือที่เล็กที่สุดที่ตอบโจทย์ความต้องการของคุณ การย้ายจาก GoatCounter ไปยัง Plausible ในภายหลังจะมีค่าใช้จ่ายเป็นเพียงการเปลี่ยน subdomain และประวัติข้อมูลบางส่วน แต่การย้ายจาก Matomo ไปยังเครื่องมืออื่นนั้นต้องผ่านกระบวนการย้ายข้อมูลที่คุณจะไม่สนุกกับมันแน่นอน หากคุณยังตัดสินใจไม่ได้ว่าควรติดตั้งอะไรเพิ่มเติมบนเซิร์ฟเวอร์เดียวกัน บทสรุปการทำ self-hosting ในภาพรวม จะครอบคลุมสิ่งที่สามารถติดตั้งควบคู่กันได้ และหากสิ่งที่คุณต้องการจริงๆ คือการติดตามคำขอในระดับแอปพลิเคชันแทนที่จะเป็นเพียงจำนวนผู้เข้าชม บริการ observability แบบ self-hosted คือเครื่องมือที่เหมาะสมสำหรับงานนั้นมากกว่า

FAQ

การทำ self-hosting ระบบวิเคราะห์ข้อมูลช่วยให้ไม่ต้องติดป้ายแจ้งเตือนคุกกี้หรือไม่?

ไม่เกี่ยวกัน และทั้งสองประเด็นเป็นเรื่องแยกจากกัน กฎเรื่องความยินยอมภายใต้ ePrivacy ครอบคลุมถึงการจัดเก็บหรืออ่านข้อมูลบนอุปกรณ์ของผู้เข้าชม ดังนั้นเครื่องมือที่ไม่สร้างคุกกี้และไม่เขียนข้อมูลลงใน local storage จึงไม่อยู่ในข้อกำหนดส่วนนี้ ส่วน GDPR เป็นกฎอีกฉบับที่ครอบคลุมการประมวลผลข้อมูลส่วนบุคคล และ IP address ถือเป็นข้อมูลส่วนบุคคล ดังนั้นคุณยังคงต้องมีฐานทางกฎหมายและกำหนดระยะเวลาการเก็บรักษาข้อมูลแม้ว่าจะไม่มีคุกกี้ก็ตาม การทำ self-hosting เป็นการย้ายข้อมูลมาไว้บนเซิร์ฟเวอร์ของคุณและทำให้คุณกลายเป็นผู้รับผิดชอบข้อมูลนั้นโดยตรง โปรดตรวจสอบคำแนะนำจากหน่วยงานกำกับดูแลในพื้นที่ของคุณและปรึกษาทนายความสำหรับกรณีเฉพาะของคุณ

ระบบวิเคราะห์ข้อมูลแบบ self-hosted ต้องการ RAM เท่าใดบน VPS?

ตัวจัดเก็บข้อมูล (datastore) เป็นตัวกำหนด ไม่ใช่ตัว dashboard ตัวอย่างเช่น GoatCounter และ Medama ทำงานเป็น process เดียวบนไฟล์เดียว ซึ่งเอกสารของ Medama ระบุว่าเว็บไซต์ขนาดเล็กสามารถรันบนเครื่องที่มี RAM 256 MB ได้ ส่วน Umami จะเพิ่ม container ของ Postgres ควบคู่ไปกับแอปพลิเคชัน Node สำหรับ Plausible Community Edition และ Rybbit ทั้งคู่ใช้ ClickHouse ซึ่งทั้งสองโครงการระบุว่าต้องการ RAM อย่างน้อย 2 GB สำหรับ Matomo คำแนะนำระบุว่าต้องใช้ CPU 2 คอร์ และ RAM 2 GB สำหรับยอดเข้าชมสูงสุด 100,000 ครั้งต่อเดือน

ทำไมตัวเลขจากระบบ self-hosted ถึงต่ำกว่าระบบวิเคราะห์ข้อมูลเดิมที่เคยใช้?

มีสองสาเหตุที่เป็นไปได้จริง ประการแรก รายการกรอง (filter lists) จะบล็อกคำขอไปยังตัวเก็บข้อมูล (collector) ทำให้เครื่องมือที่ใช้สคริปต์ทุกตัวพลาดการนับผู้เข้าชมกลุ่มนี้ ประการที่สอง ผลิตภัณฑ์แต่ละตัวมีวิธีการนับที่ต่างกัน เนื่องจากนิยามของ pageview และจุดสิ้นสุดของ session ในแต่ละตัวไม่เหมือนกัน ให้ลองเปรียบเทียบจำนวนคำขอหน้าเว็บ HTML จาก access log ของคุณในหนึ่งสัปดาห์ กับจำนวน pageview จากสคริปต์ในสัปดาห์เดียวกัน ช่องว่างที่เกิดขึ้นคือจำนวนการเข้าชมที่ถูกบล็อกรวมกับหน้าที่ถูกเรียกจากแคช โดยเป็นการวัดผลจากเว็บไซต์ของคุณเองแทนที่จะอ้างอิงจากอัตราเฉลี่ยของผู้อื่น

ฉันสามารถรัน Plausible หรือ Rybbit บน ARM VPS ได้หรือไม่?

ทั้งสองตัวใช้ ClickHouse ซึ่ง ClickHouse ต้องการชุดคำสั่ง SSE 4.2 บน x86 หรือ NEON บน ARM ข้อกำหนดของ Plausible ระบุไว้ชัดเจน และเอกสารของ Rybbit ระบุว่าระบบ ARM ต้องเป็น ARMv8.2-A หรือใหม่กว่า เซิร์ฟเวอร์ ARM รุ่นปัจจุบันรองรับมาตรฐานนี้ แต่รุ่นเก่าจะไม่รองรับ โดยความล้มเหลวจะแสดงในลักษณะที่ ClickHouse ปฏิเสธที่จะเริ่มทำงานพร้อมข้อผิดพลาดเกี่ยวกับชุดคำสั่ง (instruction set error) แทนที่จะเป็นข้อผิดพลาดใน log ของแอปพลิเคชัน สำหรับเครื่อง ARM ขนาดเล็ก เครื่องมือที่ทำงานด้วยไฟล์เดียวจะไม่มีปัญหานี้เนื่องจากไม่ได้ใช้ ClickHouse

ฉันควรวิเคราะห์จาก server log แทนการใช้สคริปต์ติดตามหรือไม่?

ควรใช้การวิเคราะห์ log เมื่อคุณไม่สามารถเพิ่มสคริปต์ได้ เมื่อกลุ่มเป้าหมายของคุณมีการบล็อกสคริปต์อย่างหนัก หรือเมื่อคุณต้องการนับจำนวนรวมถึง crawler ด้วย GoAccess สามารถอ่าน log ที่เซิร์ฟเวอร์ของคุณเขียนอยู่แล้วได้ จึงไม่เพิ่มภาระให้กับหน้าเว็บและไม่ต้องใช้ฐานข้อมูล แต่คุณจะสูญเสียข้อมูลทุกอย่างที่เกิดขึ้นภายในเบราว์เซอร์ และจะพลาดการนับหน้าเว็บที่ถูกเรียกผ่าน CDN หรือจากแคชของเบราว์เซอร์ เนื่องจากคำขอเหล่านั้นไม่เคยมาถึงเซิร์ฟเวอร์ของคุณ เว็บไซต์จำนวนมากเลือกใช้ทั้งสองวิธีและถือว่าเป็นตัวชี้วัดที่แยกจากกัน