Wakapi · PostgreSQL · custom Flask admin paneli · Prometheus · Grafana — tek docker compose up ile
⭐ Ekibinde kullanıyorsan yıldız bırak — geliştirme hızlanıyor.
Kendi sunucunda çalışan Wakapi instance'ı + üzerine geliştirilmiş özel admin paneli: Realtime active users · domain tag system · AI editor detection (Cursor / Copilot / Claude Code / Codeium...) · izin/düzeltme yönetimi · PDF rapor · leaderboard auto-refresh.
- Genel Bakış
- Mimari
- Servisler
- Admin Panel Özellikleri
- Hızlı Başlangıç
- Konfigürasyon
- Operasyonel Scriptler
- Monitoring (Prometheus + Grafana)
- Backup & Restore
- Reverse Proxy Önerisi
- Güvenlik Notları
- Sorun Giderme
- Lisans
Bu repo, Wakapi'yi kişisel kullanım sınırının dışına taşıyıp küçük/orta ölçek ekipler için kurumsal seviyede çalışır hale getirmek için gerekli her şeyi tek bir yerde toplar:
| Sorun (vanilla Wakapi) | Bu repo'nun çözümü |
|---|---|
| Yöneticinin görebileceği "kim, ne, ne kadar?" raporu yok | wakapi-admin Flask paneli — dashboard, kullanıcı detay modal'ı, raporlar |
| AI editör/aracı kullanımını ayırt etme yok | editor, user_agent ve category üzerinden AI tespiti (Cursor, Windsurf, Copilot, Claude Code, Codeium...) |
| Domain bazlı kategorilendirme yok | Domain Tag Sistemi — pattern bazlı tag'leme (İş / Eğlence / Sosyal Medya / AI Araçları / Eğitim) |
| "Şu an aktif" görünürlüğü zayıf | Realtime Active Users paneli — 15 sn'de bir refresh, durum rengi, mevcut proje/dosya |
| İzin / mola düzeltmeleri için altyapı yok | adjustments ve leaves tabloları + UI |
| PDF rapor yok | fpdf2 ile günlük/haftalık PDF raporu |
| Backup, leaderboard refresh, public ayarı manuel | backup.sh, refresh-leaderboard.sh, force-public.sh, daily-report.sh |
| Operasyonel görünürlük yok | Prometheus scrape + hazır Grafana dashboard'ı |
┌────────────────────────────────────────────┐
│ Reverse Proxy (Caddy/Nginx) │
│ wakapi.example.com admin.example.com │
│ grafana-wakapi.example.com │
└───────────────┬────────────────────────────┘
│
┌───────────────────────────────────┼────────────────────────────────────┐
│ docker network: wakapi-net │ │
│ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌──────────┐ ┌─────────┐ ┌────┐ │
│ │ wakapi │───▶│ admin │───▶│ Postgres │◀───│ pgAdmin │ │... │ │
│ │ :3000 │ │ Flask │ │ :5432 │ │ :5050 │ │ │ │
│ └────┬────┘ │ :8080 │ └──────────┘ └─────────┘ └────┘ │
│ │ └─────────┘ │
│ │ /api/metrics (bearer) │
│ ▼ │
│ ┌──────────────┐ ┌──────────┐ │
│ │ Prometheus │───▶│ Grafana │ │
│ │ :9090 │ │ :3001 │ │
│ └──────────────┘ └──────────┘ │
└────────────────────────────────────────────────────────────────────────┘
| Servis | Image | Port (host) | Açıklama |
|---|---|---|---|
| wakapi | ghcr.io/muety/wakapi:latest |
3000 |
Wakapi çekirdek API + UI. WakaTime API uyumlu. |
| postgres | postgres:16-alpine |
5432 |
Heartbeat'lerin tutulduğu birincil veri deposu. Tuned parametreler (shared_buffers=512MB, effective_cache_size=1536MB). |
| pgadmin | dpage/pgadmin4:latest |
5050 |
DB'ye web üzerinden erişim. |
| admin | wakapi-admin:latest (yerel build) |
8080 |
Flask + psycopg2 + Gunicorn + fpdf2. Bu repo'nun admin/ klasöründen build edilir. |
| prometheus | prom/prometheus:latest |
9090 |
Wakapi /api/metrics endpoint'ini scrape eder. |
| grafana | grafana/grafana:latest |
3001 |
wakapi.json dashboard'ı otomatik provision edilir. |
admin/app.py 2.000+ satırlık Flask uygulaması. Önemli özellikler:
- Stats grid: toplam kullanıcı, bugünkü aktif kullanıcı, bu hafta toplam kodlama, AI kullanım oranı.
- Realtime Active Users panel: Son 10 dk içinde heartbeat atan kullanıcıların kart grid'i.
- Sol border rengi: 🟢 < 2 dk · 🟡 2–5 dk · 🟠 5–10 dk
- Şu anki proje / dosya / dil / editör
- 🤖 AI badge (editor adı veya user_agent eşleşmesinden)
- Bugünkü toplam süre + 8 saatlik mini progress bar
- 15 saniyede bir oto-refresh.
- Genel — günlük/haftalık özet, dil dağılımı, editör dağılımı.
- Projeler — proje bazlı süre, son aktivite.
- Diller — dil bazlı dağılım, trend.
- Siteler —
type='domain'heartbeat'lerinden domain bazlı süre + Tag sistemi:- Zaman filtresi: 24 saat / 7 / 14 / 30 gün
- Tag özet kartları (İş/Eğlence/AI/Sosyal Medya/Eğitim)
- Yatay stacked bar — kategori dağılımı
- Tag chip filtreleri — tıklayınca sadece o tag.
- Düzeltmeler — manuel saat ekleme/çıkarma (
adjustmentstablosu). - İzinler — gün bazlı izin tanımlama (
leavestablosu).
- Pattern bazlı domain matching:
aysbulut.compattern'ihttps://crm.aysbulut.com'u da yakalar. - Renk + emoji ikon ile özelleştirme.
- "Etiketlenmemiş Domain'ler" bölümü — son 30 günde görülüp hiçbir tag'e uymayanlar.
- Default tag'ler init'te seed edilir; istediğinizi silip ekleyebilirsiniz.
AI_EDITORS = ['cursor', 'windsurf', 'trae']
AI_USERAGENT_KEYWORDS = ['claudecode', 'copilot', 'codeium',
'tabnine', 'supermaven', 'cody']
# + LOWER(category) = 'ai coding'cached_swr (Stale-While-Revalidate) — pahalı SQL'leri TTL ile cache'ler,
TTL bitince eski değeri döndürüp arka planda yeniler. Kullanıcıya hep "anında"
yanıt; DB'ye düşük yük.
GET / Dashboard
GET /projects /languages Listeleme sayfaları
GET /users /tags /reports
GET /api/realtime Aktif kullanıcılar (10 dk window)
GET /api/summary Stats grid verisi
GET /api/projects Proje breakdown
GET /api/languages Dil breakdown
GET /api/users Kullanıcı listesi
GET /api/user/<id> Kullanıcı detay (modal)
GET /api/user/<id>/sites Domain breakdown + tag matching
GET /api/tags Tag listesi
POST /api/tags Tag ekle
PUT /api/tags/<id> Tag güncelle
DELETE /api/tags/<id> Tag sil
GET /api/untagged-domains Etiketlenmemiş domain'ler
GET /api/user/<id>/adjustments İzin/düzeltme listesi
POST /api/user/<id>/adjustments Yeni düzeltme
GET /api/user/<id>/leaves İzin günleri
POST /api/user/<id>/leaves Yeni izin
GET /api/reports/daily PDF raporu
- Docker 24+ ve Docker Compose v2
- 2 vCPU / 2 GB RAM minimum (önerilen 4 GB)
- Linux/macOS host (Windows için WSL2)
git clone https://github.com/halilibrahimd27/wakapi-admin.git
cd wakapi-admincp .env.example .env
# .env dosyasını editör ile aç ve şifreleri/secret'ları doldur:
# WAKAPI_PASSWORD_SALT → openssl rand -base64 48
# WAKAPI_DB_PASSWORD → güçlü bir parola
# PGADMIN_DEFAULT_PASSWORD
# GF_ADMIN_PASSWORDdocker build -t wakapi-admin:latest ./admindocker compose up -d
docker compose pshttp://localhost:3000→ Sign up- Settings → Integrations → Wakapi API key'i (kullanıcı API key) ve ayrı olarak Metrics token'ı kopyala.
echo "<wakapi-metrics-token>" > prometheus/wakapi.token
docker compose restart prometheuscurl http://localhost:3000/api/health # wakapi
curl http://localhost:8080/api/realtime # admin
curl http://localhost:9090/-/ready # prometheus
curl http://localhost:3001/api/health # grafanaErişim:
- Wakapi UI: http://localhost:3000
- Admin Panel: http://localhost:8080
- pgAdmin: http://localhost:5050
- Grafana: http://localhost:3001 (dashboard: Wakapi → wakapi)
- Prometheus: http://localhost:9090
~/.wakatime.cfg:
[settings]
api_url = http://localhost:3000/api/heartbeat
api_key = <wakapi-api-key>VS Code'un WakaTime eklentisi/Cursor/Windsurf bu konfigürasyonu okur ve heartbeat'leri Wakapi'ye gönderir.
Tüm secret değerler .env üzerinden geçer. compose.yml içinde hiçbir
hardcoded credential yoktur — ${VAR} interpolasyonu kullanılır. Her değer
için .env.example referans alınmalıdır.
compose.yml içinde sabit/varsayılan olarak ayarlanan dikkate değer
parametreler:
| Parametre | Değer | Notu |
|---|---|---|
WAKAPI_ALLOW_SIGNUP |
true |
Public signup açık. Kapalı ekip için false yapın. |
WAKAPI_INVITE_CODES |
true |
Sadece davet kodu ile kayıt. |
WAKAPI_SIGNUP_CAPTCHA |
true |
Bot kayıt engeli. |
WAKAPI_LEADERBOARD_ENABLED |
true |
7 gün scope, 15 dk'da bir refresh. |
WAKAPI_LEADERBOARD_REQUIRE_AUTH |
true |
Sadece login'liler görür. |
WAKAPI_DATA_RETENTION_MONTHS |
12 |
12 aydan eski heartbeat purge. |
WAKAPI_MAX_INACTIVE_MONTHS |
6 |
6 aydır aktif değilse hesap pasifleştirilir. |
WAKAPI_TRUSTED_HEADER_AUTH |
true |
Reverse proxy'den X-Remote-User ile SSO destekli. |
WAKAPI_TRUST_REVERSE_PROXY_IPS |
172.0.0.0/8,127.0.0.1,10.0.0.0/8 |
RP IP'leri. Production'da daraltın. |
Tüm Wakapi env'leri için: muety/wakapi config docs
backup.sh, daily-report.sh, force-public.sh, refresh-leaderboard.sh
script'leri host üzerinde cron ile zamanlanmaya yöneliktir.
chmod +x backup.sh
./backup.sh
# /opt/wakapi/backups/wakapi_<TIMESTAMP>.sql.gz oluşturur
# 7 günden eski yedekleri otomatik siler.crontab -e:
0 3 * * * /opt/wakapi/backup.sh >> /var/log/wakapi-backup.log 2>&1Wakapi'nin kendi leaderboard hesabı zaman zaman drift edebilir; bu script son 7 günün heartbeat'lerinden (10 dk gap kuralı ile) leaderboard'u temizden hesaplar ve container'ı restart eder.
*/15 * * * * /opt/wakapi/refresh-leaderboard.shEkipte herkesin leaderboard ve breakdown'ları görünmesi gereken senaryo için. Kullanıcı tercihlerini override eder, dikkatli kullanın.
Gün içinde her kullanıcının kaç heartbeat attığını, hangi proje/dil'lerde çalıştığını, ilk/son aktivite saatini terminale basar. Slack webhook'a pipe edebilirsiniz:
./daily-report.sh | curl -X POST -H 'Content-Type: text/plain' \
--data-binary @- $SLACK_WEBHOOK_URL/api/metrics endpoint'i Wakapi'nin bütün metriklerini Prometheus formatında
expose eder. Bearer token ile korunur — token prometheus/wakapi.token
dosyasından okunur (commit edilmez).
Token'ı almak için Wakapi UI:
Settings → Integrations → Metrics URL içindeki
?token=parametresi sizin metrics token'ınızdır.
Provisioning otomatiktir:
- Datasource: Prometheus (
http://prometheus:9090) - Dashboard: Wakapi (
grafana/dashboards/wakapi.json)
İlk girişte GF_ADMIN_USER / GF_ADMIN_PASSWORD ile login olun.
docker exec wakapi-db pg_dump -U wakapi wakapi | gzip > wakapi_$(date +%F).sql.gzgunzip -c wakapi_2025-04-30.sql.gz | docker exec -i wakapi-db psql -U wakapi -d wakapidocker compose downdocker volume rm wakapi_pgdatadocker compose up -d postgres— boş DB ile ayağa kalksın- Restore komutunu çalıştır
docker compose up -d
wakapi.example.com {
reverse_proxy localhost:3000
}
admin.example.com {
basicauth {
yonetici JDJhJDEw... # caddy hash-password
}
reverse_proxy localhost:8080
}
grafana-wakapi.example.com {
reverse_proxy localhost:3001
}
Reverse proxy IP'lerini WAKAPI_TRUST_REVERSE_PROXY_IPS env'ine eklemeyi
unutmayın; aksi halde Wakapi gerçek client IP'sini göremez.
Admin paneli (8080) built-in auth içermez. Mutlaka reverse proxy seviyesinde Basic Auth, OAuth Proxy veya benzeri ile koruyun ya da private network'te bırakın.
- ✅
compose.ymltüm secret'lar için${VAR}interpolasyonu kullanır. - ✅
.env,prometheus/wakapi.token,backups/.gitignoreile hariç. ⚠️ Admin paneli (8080) auth'suzdur. Public erişime kapatın.⚠️ pgAdmin (5050) ve Prometheus (9090) public açmayın.⚠️ Production'daWAKAPI_INSECURE_COOKIES=falseve HTTPS reverse proxy zorunlu.⚠️ Postgres port 5432'yi host'a expose etmek DEV içindir — production'daportssatırını silin, sadece compose network üzerinden erişin.
postgres:
ports: [] # 5432'yi dışarı açma
pgadmin:
ports: [] # sadece compose network içinden
prometheus:
ports: [] # sadece grafana scrape eder.env içinde tanımlı değil. Doldurun:
echo "WAKAPI_PASSWORD_SALT=$(openssl rand -base64 48)" >> .envdocker compose logs admin --tail=50
docker exec wakapi-admin printenv | grep DB_DB_PASSWORD'un Wakapi DB parolası ile aynı olduğundan emin olun.
prometheus/wakapi.token dosyası yok veya yanlış. Wakapi UI → Integrations →
Metrics token'ı kopyala → dosyaya yaz → docker compose restart prometheus.
Wakapi background job'ı her saatte özetleri hesaplar. Test için
/api/summary?recompute=true veya container restart.
Editor adınız AI_EDITORS listesinde değil olabilir. admin/app.py'da
AI_EDITORS ve AI_USERAGENT_KEYWORDS listelerini düzenleyin, image'ı tekrar
build edin.
docker build -t wakapi-admin:latest ./admin --no-cache
docker compose up -d adminMIT — Wakapi'nin kendisi de MIT lisanslıdır (muety/wakapi/LICENSE). Bu repo'da Wakapi'yi paketleyip ek admin paneli ile sunuyoruz; çekirdek koda ait tüm haklar Ferdinand Mütsch (@muety) ve katkıcılarına aittir.
Issue'lar ve PR'lar için: https://github.com/halilibrahimd27/wakapi-admin/issues
SECURITY.md ve CODE_OF_CONDUCT.md okunmalı.
Bir özellik eklerken
admin/app.py'da yorumların Türkçe, kullanıcıya görünen UI metinlerinin de Türkçe olduğuna dikkat edin (proje konvansiyonu).
| Süre | Yardım |
|---|---|
| 5 sn | ⭐ Star |
| 30 sn | Twitter/LinkedIn'de paylaş ("WakaTime self-hosted, ekip analytics'i hazır") |
| 5 dk | Issue aç (eksik bulduğun feature) |
| 30 dk | Yeni AI editor detection ekle (Cursor, Continue, vb.) |
| 2 saat | Yeni dashboard widget'ı yaz (rapor, leaderboard, stats) |