VeloCMS'i Kendi Sunucunuzda Barındırma

15 min readUpdated 27 Apr 2026

Neden Kendi Sunucunuzda Barındırmalısınız?

Çoğu kişi yönetilen bulut çözümünü tercih ediyor, ki bunda bir sorun yok. Ama verilerinizin nerede duracağı konusunda yasal zorunluluklarınız varsa, GDPR veya HIPAA gibi bir uyumluluk meselesi (ya da şirket içi SOC 2 politikanız) söz konusuysa, büyüdükçe artan maliyetler canınızı sıkıyorsa veya en basitinden 'verim benim sunucumda durmalı' diyorsanız, bu rehberle 30 dakikadan kısa sürede, ayda 6 dolarlık bir VPS üzerinde çalışan bir production ortamı kurabilirsiniz. Kendi sunucunuzda barındırmak demek; şema, depolama, yedekler ve güncelleme döngüsü üzerinde tam kontrol sahibi olmanız demek. Bunun karşılığında operasyonel sorumluluğu üstlenmiş oluyorsunuz. VeloCMS, bu takası gerçekten değerli kılmak için elinden geleni yapıyor.

Sistem Gereksinimleri

VeloCMS göründüğünden çok daha hafif. PocketBase, içine SQLite gömülmüş tek bir Go binary'sinden ibaret ve Next.js container'ı da boşta yaklaşık 150MB RSS kullanıyor. Yani sıradan bir blog kurulumu için öyle ahım şahım bir sunucuya ihtiyacınız yok.

ProfilKiracı SayısıRAMDiskCPUNotlar
Küçük blog11 GB25 GB1 vCPUTekil kurulum modu için ideal.
SaaS hobi projesi50'ye kadar2 GB50 GB1 vCPUÇoklu kiracı modu, R2 kullanımı şiddetle tavsiye edilir.
SaaS production50+4 GB+80 GB+2+ vCPUYük arttıkça ölçeklenir. R2 kullanımı neredeyse zorunludur.

Docker Compose ile Hızlı Başlangıç

VeloCMS, iki adet hazır Docker imajıyla geliyor: `velocms/velocms:latest` (Next.js 16 uygulaması) ve `velocms/pocketbase:latest` (VeloCMS şeması önceden yüklenmiş PocketBase 0.36). Çalıştırmak için kaynak koduna ihtiyacınız yok. `public/install/docker-compose.yml` adresindeki Compose şablonu, bu iki servisi mantıklı varsayılan ayarlarla birbirine bağlıyor: paylaşılan volume, dahili DNS ve PocketBase'in hazır olmasını garantileyen sağlık kontrolü sıralaması sayesinde Next.js süreci şema migrasyonuna kalkıştığında her şey yolunda gidiyor.

terminal
# 1. Create a working directory
    mkdir velocms && cd velocms
    
    # 2. Download the official Compose template + env example
    curl -O https://velocms.org/install/docker-compose.yml
    curl -O https://velocms.org/install/.env.example
    cp .env.example .env
    
    # 3. Edit .env — fill in the required secrets (see Environment Variables table below)
    nano .env   # or: vim .env / code .env
    
    # 4. Pull images and start in the background
    docker compose up -d
    
    # Verify both containers are running and healthy
    docker compose ps
bash

Compose dosyasının tam hali repoda `public/install/docker-compose.yml` altında tutuluyor. 2026'nın 3. çeyrek sürümü itibarıyla standart yapısı şu şekilde:

docker-compose.yml
version: "3.9"
    
    services:
      pocketbase:
        image: velocms/pocketbase:latest
        restart: unless-stopped
        volumes:
          - pb_data:/pb/pb_data
        ports:
          - "8090:8090"          # Expose only internally in prod; reverse-proxy to 3000
        healthcheck:
          test: ["CMD", "wget", "-q", "--spider", "http://localhost:8090/api/health"]
          interval: 10s
          timeout: 5s
          retries: 5
    
      velocms:
        image: velocms/velocms:latest
        restart: unless-stopped
        depends_on:
          pocketbase:
            condition: service_healthy
        ports:
          - "3000:3000"
        env_file: .env
        environment:
          POCKETBASE_URL: http://pocketbase:8090  # Internal Docker DNS — do not change
    
    volumes:
      pb_data:
bash

Ortam Değişkenleri Referansı

Tüm yapılandırma ortam değişkenleri üzerinden yapılıyor; herhangi bir ayar dosyası ya da sunucu davranışları için bir arayüz paneli yok. Kurulum paketindeki `.env.example` dosyası bu tablonun birebir aynısı. Zorunlu değişkenler başlangıçta kontrol ediliyor; eksik olanlar uygulamanın net bir hata mesajı verip istekleri sunmayı reddetmesine neden olacaktır.

DeğişkenZorunlu mu?VarsayılanAmacıGüvenlik Notu
`VELOCMS_MODE`Evet`single``single` veya `multi` modunu ayarlar.Yok
`POCKETBASE_URL`Evet`http://pocketbase:8090`Next.js uygulamasının PocketBase API'sine nasıl ulaşacağını belirler.Production'da `https` kullanın.
`ENCRYPTION_KEY`EvetYokKiracı sırlarını (API anahtarları vb.) şifrelemek için kullanılan 32-byte'lık bir anahtar.Çok hassas. Güvenli bir yerde saklayın, veritabanıyla birlikte yedeklemeyin.
`STRIPE_SECRET_KEY`HayırYokStripe entegrasyonu için platformun ana Stripe anahtarı.Her zaman kısıtlı izinlere sahip bir anahtar kullanın.
`R2_ACCOUNT_ID`HayırYokCloudflare R2 medya depolaması için hesap ID'si.Yok
`R2_ACCESS_KEY_ID`HayırYokCloudflare R2 için erişim anahtarı ID'si.Yok
`R2_SECRET_ACCESS_KEY`HayırYokCloudflare R2 için gizli erişim anahtarı.Hassas. Güvenli bir şekilde yönetin.
`R2_BUCKET_NAME`HayırYokMedya dosyalarının yükleneceği R2 bucket'ının adı.Yok

Tekil Kurulum ve Çoklu Kiracı Modu Karşılaştırması

Bu modlar arasındaki seçim bir özellik seviyesi değil, tamamen bir kurulum topolojisi kararı. Tekil kurulum; kişisel bir blog, bir ajansın müşteri sitesi veya çoklu kiracı karmaşası olmadan temiz bir kurulum isteyen küçük bir işletme için gerçekten biçilmiş kaftan. Çoklu kiracı modu ise VeloCMS üzerine bir SaaS ürünü inşa ettiğiniz durumlar için var. Müşterileriniz kendi izole PocketBase kurulumlarına, kendi subdomain'lerine ve isteğe bağlı olarak BYOK faturalandırmasıyla kendi Stripe hesaplarına sahip olurlar. velocms.org'daki production ortamı çoklu modda çalışıyor.

Özellik`VELOCMS_MODE=single``VELOCMS_MODE=multi`
Veritabanı yapısıTek bir `pb_data` diziniHer kiracı için `pb_data/tenants/{tenantId}`
Alan adı yönlendirmeTek bir alan adı (örn: `blog.sirket.com`)Wildcard subdomain'ler (örn: `*.platformunuz.com`)
Kullanıcı kaydıKapalı (sadece davetle)Açık (herkes yeni bir site oluşturabilir)
FaturalandırmaUygulanamazPlatform düzeyinde Stripe veya kiracı başına BYOK

Emin değilseniz, tekil kurulumla başlayın. Daha sonra çoklu kiracı moduna geçiş yapabilirsiniz. Şema aynı, temel fark PocketBase dosyalarının nerede durduğu ve middleware'in istekleri nasıl yönlendirdiği.

İlk Yönetici Kullanıcısını Oluşturma

PocketBase'in kendi yönetici arayüzü var; burası veritabanı için alt seviye kontrol paneli gibi düşünebilirsiniz. Bu arayüze ilk girdiğinizde, sizden bir süper kullanıcı oluşturmanız istenecek. İşte bu süper kullanıcı, VeloCMS'e `/login` adresinden giriş yapacağınız kimlik bilgileri olacak. Bu 'süper kullanıcı oluştur' ekranı sadece temiz bir veritabanında bir kez karşınıza çıkar, o yüzden başka bir şey yapmadan önce bu adımı halledin.

terminal
# While Docker Compose is running, open the PocketBase admin UI:
    open http://localhost:8090/_/
    
    # Create your superuser email + password when prompted.
    # Then log into VeloCMS:
    open http://localhost:3000/login
bash

Eğer bu ilk kurulumu arayüz olmadan (headless) yapmak isterseniz - ki bu CI veya otomatik provizyon süreçlerinde çok işe yarar - PocketBase ilk başlangıçta kimlik bilgilerini ortam değişkenleri aracılığıyla da kabul ediyor. `.env` dosyanızdaki `POCKETBASE_ADMIN_EMAIL` ve `POCKETBASE_ADMIN_PASSWORD` değişkenleri, şema oluşturulurken PB container'ı tarafından okunur. İlk başlatmadan sonra bu değişkenleri değiştirmenin mevcut bir veritabanı üzerinde hiçbir etkisi olmaz; süper kullanıcı yönetimi artık tamamen PB yönetici arayüzünden yapılır.

`/admin` adresinden VeloCMS yönetici paneline giriş yaptıktan sonra, isterseniz demo içerik yükleyicisini çalıştırarak kurulumunuza örnek yazılar, bir tema ve birkaç medya öğesi ekleyebilirsiniz. Böylece sistemi değerlendirirken arayüz tamamen boş görünmez.

terminal
# Optional: seed demo content (posts + default tenant + media placeholders)
    # Run this from inside the velocms container or from the repo if you have it locally:
    node scripts/seed-multi-tenant.mjs
bash

Özel Alan Adı ve TLS Kurulumu

Tekil bir kurulum için, alan adınızın A kaydını sunucu IP'nize yönlendirin ve 443 portundan gelen trafiği 3000'e yönlendirecek bir reverse proxy (nginx veya Caddy) yapılandırın. Caddy en kolay yoldur, Let's Encrypt işini otomatik olarak halleder.

Caddyfile
# Caddyfile — put in /etc/caddy/Caddyfile or your Caddy config path
    yourdomain.com {
        reverse_proxy localhost:3000
    }
    
    # Caddy auto-provisions TLS via Let's Encrypt. No certbot needed.
    # Reload after editing: systemctl reload caddy
bash

Çoklu kiracı modu için ek olarak bir wildcard DNS kaydına ihtiyacınız var. Bu wildcard kaydı sadece DNS (Cloudflare'de gri bulut) olmalı, proxy'lenmemeli. Cloudflare'in proxy'si ücretsiz planda wildcard sertifika sağlamıyor ve eğer Railway üzerinde kurulum yapıyorsanız, her subdomain için TLS sonlandırmasını Railway kendisi hallediyor.

Cloudflare DNS
# Add these two records in the Cloudflare DNS dashboard:
    #
    # Type   Name                 Content            Proxy status
    # A      yourdomain.com       <server-IP>        Proxied  (orange cloud)
    # A      *.yourdomain.com     <server-IP>        DNS only (grey cloud)
    #
    # The apex domain stays proxied (CDN + DDoS protection).
    # The wildcard MUST be grey cloud — Railway or your Caddy handles TLS.
bash

Yedekleme Stratejisi

PocketBase tüm veriyi disk üzerindeki SQLite dosyalarında saklar. Yedeklemek oldukça basit: PocketBase durdurulmuşken veya PB yedekleme API'si kullanılırken (ki bu bir 'hot checkpoint' tetikler) `pb_data` dizinini kopyalayın. Tavsiye edilen yöntem, her gün `pocketbase backup` komutunu çalıştıran ve sonucu R2'ye aktaran bir cron görevi oluşturmaktır. Bu sayede yedekleriniz ana depolama alanınızdan ayrı yaşar ve bir sunucu çökmesinden etkilenmez.

backup-daily.sh
#!/usr/bin/env bash
    # Daily PocketBase backup -> Cloudflare R2
    # Add to crontab: 0 3 * * * /opt/velocms/backup-daily.sh
    
    set -euo pipefail
    
    DATE=$(date +%Y-%m-%d)
    BACKUP_FILE="velocms-backup-${DATE}.zip"
    PB_URL="${POCKETBASE_URL:-http://localhost:8090}"
    R2_BUCKET="${R2_BUCKET_NAME:-velocms-backups}"
    
    # Trigger PocketBase hot backup via API (requires superuser auth)
    curl -s -X POST       -H "Authorization: ${PB_ADMIN_TOKEN}"       "${PB_URL}/api/backups"       -d "{"name":"${BACKUP_FILE}"}"
    
    # Wait for backup to appear in PB's local backup folder, then stream to R2
    # Assumes rclone is configured with the Cloudflare R2 remote named "r2"
    rclone copy "${PB_DATA_DIR}/backups/${BACKUP_FILE}" "r2:${R2_BUCKET}/daily/"
    
    echo "[backup] ${BACKUP_FILE} uploaded to R2 at $(date)"
    
    # Prune local backups older than 7 days
    find "${PB_DATA_DIR}/backups/" -name "*.zip" -mtime +7 -delete
bash

Geri yükleme ise bu işlemin tersi: zip dosyasını R2'den indirin, `pb_data/backups/` içine koyun ve PB geri yükleme API'sini çağırın. Ayda en az bir kez geri yükleme tatbikatı yapın; hiç test etmediğiniz bir yedek, aslında sahip olmadığınız bir yedektir.

terminal
# Download a backup from R2:
    rclone copy "r2:velocms-backups/daily/velocms-backup-2026-04-26.zip" ./restore/
    
    # Restore via PocketBase API (while PB is running):
    curl -X PUT       -H "Authorization: <admin-token>"       "${PB_URL}/api/backups/velocms-backup-2026-04-26.zip/restore"
    
    # PocketBase will restart automatically after restore.
bash

VeloCMS'i Güncelleme

Güncellemeler iki adımlı bir 'pull' ve yeniden başlatma işlemidir. VeloCMS, PocketBase migrasyonlarını başlangıçta otomatik olarak uygular. Yani, yıkıcı bir şema değişikliği getiren büyük bir sürüme yükseltme yapmadığınız sürece (ki bunlar sürüm notlarında açıkça belirtilen yükseltme öncesi adımlarla belgelenir) migrasyon betiklerini manuel olarak çalıştırmanıza gerek kalmaz.

terminal
# 1. Pull the latest images (do this from your velocms working directory)
    docker compose pull
    
    # 2. Take a backup before upgrading (see backup strategy above)
    ./backup-daily.sh
    
    # 3. Restart with the new images — zero-downtime if using a load balancer
    docker compose up -d --remove-orphans
    
    # 4. Verify the app is healthy
    docker compose ps
    curl -s http://localhost:3000/api/health | jq .
bash

`latest` etiketini takip etmek yerine belirli bir sürüme sabitlenmek için `docker-compose.yml` dosyanızdaki imaj etiketini değiştirin. Örneğin, `velocms/velocms:1.2.0` ve `velocms/pocketbase:1.2.0`. Production ortamları için sabitlenmiş etiketler tavsiye edilir; bu size güncelleme zamanlamasını kontrol etme ve bir şeyler ters giderse sorunun yeni bir imaj çekmekten kaynaklanmadığından emin olma imkanı tanır.

Sorun Giderme

Başlangıçtaki hataların çoğu ya eksik bir ortam değişkeninden ya da Next.js container'ı ile PocketBase arasındaki ağ erişim sorunundan kaynaklanır. Bakılacak ilk yer Docker loglarıdır (`docker compose logs -f velocms`). VeloCMS, yapısal JSON hatalarını stdout'a yazar, bu yüzden `| jq .` komutu bunları ayrıştırmanıza yardımcı olur.

HataOlası NedenÇözüm
`Error: connect ECONNREFUSED`VeloCMS container'ı PocketBase'e ulaşamıyor.`POCKETBASE_URL`'nin doğru olduğundan ve `pocketbase` servisinin çalıştığından emin olun. `docker ps` ile kontrol edin.
`Missing required environment variable: ENCRYPTION_KEY`Zorunlu bir ortam değişkeni eksik.`.env` dosyanızı `.env.example` ile karşılaştırın ve eksik değişkenleri ekleyin.
PocketBase loglarında `database is locked`İki süreç aynı anda SQLite dosyasına yazmaya çalışıyor.PocketBase'in sadece bir kopyasının çalıştığından emin olun. `docker compose down` ve `up` ile yeniden başlatmayı deneyin.
TLS hataları veya `P-014` (Railway)Wildcard DNS kaydı Cloudflare'de proxy'lenmiş (turuncu bulut).Wildcard CNAME kaydını 'Sadece DNS' (gri bulut) olarak değiştirin.

Referans Ekler

Docker İmajları

İmajEtiketİçerik
`velocms/velocms``latest`, `1.2.0`Next.js 16 tabanlı VeloCMS ön uç ve yönetici paneli uygulaması.
`velocms/pocketbase``latest`, `1.2.0`VeloCMS şeması ve ayarlarıyla önceden yapılandırılmış PocketBase 0.36.

Donanım Boyutlandırma Hızlı Referansı

SağlayıcıSunucu TipiRAMAylık Maliyet (yaklaşık)Uygun Olduğu Durumlar
DigitalOceanBasic Droplet1 GB$6Tekil kurulum, küçük bloglar
HetznerCPX112 GB€5Küçük SaaS, 50 kiracıya kadar
VultrHigh Frequency4 GB$24Büyüyen SaaS, 50+ kiracı

Docker Container İçindeki Önemli Dosya Yolları

YolAçıklama
`/pb_data`PocketBase'in tüm veritabanı dosyalarını, migrasyonları ve yedekleri içeren ana veri dizini. Bu dizin bir volume olarak bağlanmalıdır.
`/pb_data/tenants/{tenantId}`Çoklu kiracı modunda, her kiracının izole edilmiş kendi `pb_data` dizini.
`/app/.next`VeloCMS (Next.js) uygulamasının derlenmiş dosyaları.