Analytics · Privacy · Docker

ติดตั้ง Umami Analytics บน VPS — วิเคราะห์เว็บ Privacy-First

Umami Analytics dashboard บน VPS

Umami เป็น web analytics แบบ open-source ที่เน้น privacy-first — ไม่ใช้ cookies ไม่เก็บ personal data ของผู้เข้าชม และ GDPR compliant ตามค่าเริ่มต้น เหมาะมากสำหรับเจ้าของเว็บที่ต้องการ analytics ที่เชื่อถือได้โดยไม่ต้องพึ่ง Google Analytics

บทความนี้จะสอนติดตั้ง Umami บน VPS Ubuntu 22.04 ด้วย Docker Compose, Nginx reverse proxy และ SSL certificate จาก Let's Encrypt แบบ production-ready

ทำไมต้องใช้ Umami แทน Google Analytics?

ฟีเจอร์Umami (self-hosted)Google Analytics 4
Privacy / GDPR✅ ไม่เก็บ personal data⚠️ ต้องการ consent banner
Cookies✅ ไม่ใช้ cookies❌ ใช้ cookies
ข้อมูลเป็นของคุณ✅ 100%❌ Google เก็บข้อมูล
ค่าใช้จ่าย✅ ฟรี (เสียแค่ VPS)✅ ฟรี (แต่แลกด้วยข้อมูล)
ความเร็ว script✅ <2KB❌ ~45KB+
Ad blocker ผ่าน✅ host เองใน domain ตัวเอง❌ ถูก block บ่อย

ความต้องการระบบ

ขั้นที่ 1 — ติดตั้ง Docker (ถ้ายังไม่มี)

sudo apt update && sudo apt install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list
sudo apt update && sudo apt install -y docker-ce docker-compose-plugin
sudo usermod -aG docker $USER
Tip: หลัง usermod ให้ logout แล้ว login ใหม่เพื่อให้สิทธิ์ group มีผล

ขั้นที่ 2 — สร้าง Docker Compose สำหรับ Umami

mkdir -p /opt/umami && cd /opt/umami

สร้าง docker-compose.yml:

cat > docker-compose.yml <<'EOF'
version: '3'
services:
  umami:
    image: ghcr.io/umami-software/umami:postgresql-latest
    restart: unless-stopped
    environment:
      DATABASE_URL: postgresql://umami:umami_secure_pass@db:5432/umami
      DATABASE_TYPE: postgresql
      APP_SECRET: your_random_secret_here_32chars
    depends_on:
      - db
    ports:
      - "3000:3000"

  db:
    image: postgres:15-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: umami
      POSTGRES_USER: umami
      POSTGRES_PASSWORD: umami_secure_pass
    volumes:
      - umami_db:/var/lib/postgresql/data

volumes:
  umami_db:
EOF
Tip: เปลี่ยน umami_secure_pass และ APP_SECRET เป็นค่าสุ่มจริง ใช้ openssl rand -base64 32 สร้างรหัสผ่าน

ขั้นที่ 3 — สร้าง APP_SECRET และ DB password ที่ปลอดภัย

# สร้าง secret สุ่ม
DB_PASS=$(openssl rand -base64 24)
APP_SECRET=$(openssl rand -hex 32)
echo "DB_PASS: $DB_PASS"
echo "APP_SECRET: $APP_SECRET"

# แก้ค่าใน docker-compose.yml
sed -i "s/umami_secure_pass/$DB_PASS/g" docker-compose.yml
sed -i "s/your_random_secret_here_32chars/$APP_SECRET/" docker-compose.yml

ขั้นที่ 4 — รัน Umami

cd /opt/umami
docker compose up -d

# ดู logs
docker compose logs -f umami

รอสัก 30 วินาที Umami จะ initialize database แล้วฟัง port 3000

ขั้นที่ 5 — ตั้งค่า Nginx Reverse Proxy + SSL

sudo apt install -y nginx certbot python3-certbot-nginx

# สร้าง config
sudo tee /etc/nginx/sites-available/umami <<'EOF'
server {
    listen 80;
    server_name analytics.yourdomain.com;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        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;
        proxy_cache_bypass $http_upgrade;
    }
}
EOF

sudo ln -s /etc/nginx/sites-available/umami /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

# ขอ SSL
sudo certbot --nginx -d analytics.yourdomain.com

ขั้นที่ 6 — Login และตั้งค่าแรก

เปิดเบราว์เซอร์ไปที่ https://analytics.yourdomain.com

ขั้นที่ 7 — เพิ่มเว็บไซต์และฝัง Tracking Script

ใน Umami dashboard ไปที่ Settings → Websites → Add website แล้วก็อป tracking script ที่ได้ไปวางใน <head> ของเว็บ:

<script defer src="https://analytics.yourdomain.com/script.js"
        data-website-id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"></script>
Tip: script ของ Umami ขนาดเล็กมาก (~2KB) และ load แบบ defer จึงไม่กระทบ Core Web Vitals ของเว็บ

ขั้นที่ 8 — ตั้งค่า Auto-backup Database

# สร้าง backup script
cat > /opt/umami/backup.sh <<'EOF'
#!/bin/bash
BACKUP_DIR="/opt/umami/backups"
DATE=$(date +%Y%m%d_%H%M)
mkdir -p "$BACKUP_DIR"
docker exec umami-db-1 pg_dump -U umami umami | gzip > "$BACKUP_DIR/umami_$DATE.sql.gz"
# เก็บแค่ 14 วัน
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +14 -delete
EOF

chmod +x /opt/umami/backup.sh

# ตั้ง cron backup ทุกคืน 2:00
(crontab -l 2>/dev/null; echo "0 2 * * * /opt/umami/backup.sh") | crontab -

ตรวจสอบว่า Umami ทำงานถูกต้อง

# ดูสถานะ containers
docker compose -f /opt/umami/docker-compose.yml ps

# ตรวจสอบ Umami API
curl -s http://localhost:3000/api/heartbeat
# ควรได้: {"ok":true}

# ตรวจสอบ database connection
docker compose -f /opt/umami/docker-compose.yml exec db \
  psql -U umami -c '\l'

# ดู logs errors
docker compose -f /opt/umami/docker-compose.yml logs --tail=50 umami

# ตรวจสอบ Nginx
sudo nginx -t && sudo systemctl status nginx
Tip: ถ้า /api/heartbeat ตอบ {"ok":true} แสดงว่า Umami พร้อมรับ requests แล้ว ถ้า tracking script ยังไม่ส่ง event ลองเปิด browser DevTools ดู Network tab ว่า request ถึง Umami หรือเปล่า

แก้ปัญหาที่พบบ่อย

Error: "Error: connect ECONNREFUSED 127.0.0.1:5432"

Umami หา database ไม่เจอ เกิดจาก container db ยังไม่พร้อม หรือชื่อ service ไม่ตรงกับใน DATABASE_URL

docker compose ps  # ดูว่า db running
docker compose logs db  # ดู postgres error
# แก้: รอสัก 30 วินาทีแล้ว restart
docker compose restart umami

Error: "invalid input syntax for type uuid"

APP_SECRET ไม่ตรงกับที่ใช้สร้าง session — เกิดเมื่อเปลี่ยน secret โดยไม่ clear session เก่า

# หน้า login → กด Ctrl+Shift+Delete ล้าง cookies แล้ว login ใหม่
# หรือ restart umami container
docker compose restart umami

Error: "502 Bad Gateway" จาก Nginx

Nginx ส่ง request ไปหา Umami ไม่ถึง อาจเพราะ container ยังไม่ขึ้น หรือ port ผิด

docker compose ps  # ดู port mapping
curl -s http://localhost:3000  # ทดสอบ direct
sudo tail -f /var/log/nginx/error.log  # ดู nginx error

Error: "ERR_TOO_MANY_REDIRECTS" บน HTTPS

Nginx ส่ง X-Forwarded-Proto ซ้ำกับ Umami config ทำให้ redirect loop

# ตรวจสอบ Nginx config
grep -n "X-Forwarded-Proto" /etc/nginx/sites-available/umami
# ต้องมีแค่บรรทัดเดียว: proxy_set_header X-Forwarded-Proto $scheme;

Script ถูก Ad Blocker บล็อก

ถ้า tracking script ชี้ที่ analytics.yourdomain.com มักไม่โดน block ต่างจาก Google Analytics แต่ถ้ายังโดนให้ลอง custom script path

# แก้ใน docker-compose.yml เพิ่ม environment
TRACKER_SCRIPT_NAME: track

คำถามที่พบบ่อย

Umami เก็บข้อมูลอะไรบ้าง?

Umami เก็บ URL ที่เยี่ยมชม, referrer, browser, OS, device type, country (จาก IP แต่ไม่เก็บ IP จริง) และ timestamp ไม่มีการเก็บ IP address จริง, cookies หรือ personal identifier ใดๆ ทำให้ compliant กับ GDPR, CCPA โดยอัตโนมัติ

รองรับ multiple websites ในบัญชีเดียวได้ไหม?

ได้เลย Umami รองรับการเพิ่มเว็บหลายแห่งในบัญชีเดียว โดยแต่ละเว็บจะได้ website-id ของตัวเอง สามารถ share dashboard ให้คนอื่น view-only ได้ด้วย

Umami กินทรัพยากรเท่าไหร่?

บน VPS RAM 1GB Umami + PostgreSQL ใช้ RAM ประมาณ 200-300MB รองรับเว็บที่มี pageviews หลักหมื่นต่อวันได้สบาย ถ้าต้องการรองรับ traffic สูงขึ้นให้เพิ่ม RAM หรือ upgrade PostgreSQL index