SSD Nodes Learn 8GB RAM — yılda $66
Rehberler Matt ConnorYazan Matt Connor · Güncellendi 2026-08-01

Shlink ile VPS Üzerinde URL Kısaltıcı Kurulumu

Shlink 5.1 ve Docker Compose ile VPS üzerinde kendi URL kısaltıcınızı kurun. Kısa alan adı DNS ayarları, Postgres, API key, web client, QR kodları ve tıklama istatistikleri.

Oluşturulacak sistem

Kendi sunucunuzda barındırılan bir URL kısaltıcı, uzun bir bağlantıyı size ait kısa bir bağlantıya dönüştüren ve bağlantının her tıklanmasını sayan küçük bir sunucudur. Tercih edilmesi gereken ürün Shlink'tir. Shlink açık kaynaklıdır, Docker image olarak sunulur ve tüm işi bir container ile bir veritabanında gerçekleştirir. Bu kılavuzda Shlink, gerçek bir kısa alan adının arkasında, HTTPS, API key, QR kodları ve tıklama istatistikleriyle birlikte bir VPS üzerine kurulmaktadır.

Ticari bir kısaltıcıdaki kullanım deneyimini iki bileşen sağlar. API server yönlendirmelere yanıt verir ve verileri tutar. Web client, tarayıcıdan bu API ile iletişim kuran ayrı bir statik uygulamadır. Her ikisi de çalıştırılabilir veya yalnızca API çalıştırılarak komut satırından kullanılabilir.

Buradaki sürüm numaraları Temmuz 2026 itibarıyla günceldir: Shlink 5.1 ve shlink-web-client 4.8.

Önce kısa alan adını sunucuya yönlendirin

Alan adı ürünün kendisidir. s.example.com/abc123 kullanıcıların gördüğü bağlantıdır; bu nedenle kısa bir ad seçin ve herhangi bir kurulum yapmadan önce bu adı belirleyin. Shlink, alan adını her kısa URL ile birlikte kaydeder. Daha sonra değiştirirseniz daha önce dağıttığınız tüm bağlantılar çalışmaz.

Kısa alan adı için sunucunuzun genel IPv4 adresine işaret eden bir DNS A kaydı oluşturun. Sunucuda IPv6 varsa bir AAAA kaydı da ekleyin. Ardından devam etmeden önce alan adının çözümlendiğini doğrulayın.

dig +short s.example.com A

Çıktı sunucunuzun adresi olmalıdır. Çıktı boşsa kayıt henüz yayılmamıştır. Bu durumda sonraki tüm adımlar anlaşılması zor şekilde başarısız olur; çünkü çözümlenmeyen bir ad için TLS (transport layer security) sertifikası verilemez.

Compose dosyası

Shlink için bir veritabanı gerekir. SQLite test için kullanılabilir, ancak kalıcı olarak kullanılması planlanan kurulumlarda Postgres doğru tercihtir. Bunun nedeni, ziyaret kayıtlarının birikmesi ve Postgres'in dizinleri ve eşzamanlı yazma işlemlerini daha iyi yönetmesidir. Aşağıdakileri /opt/shlink/compose.yaml içine ekleyin.

services:
  shlink:
    image: shlinkio/shlink:stable
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:8080"
    environment:
      DEFAULT_DOMAIN: s.example.com
      IS_HTTPS_ENABLED: "true"
      DB_DRIVER: postgres
      DB_HOST: database
      DB_NAME: shlink
      DB_USER: shlink
      DB_PASSWORD: ${DB_PASSWORD}
    depends_on:
      - database

  database:
    image: postgres:17-alpine
    restart: unless-stopped
    environment:
      POSTGRES_DB: shlink
      POSTGRES_USER: shlink
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - shlink_db:/var/lib/postgresql/data

  web-client:
    image: shlinkio/shlink-web-client:stable
    restart: unless-stopped
    ports:
      - "127.0.0.1:8081:8080"

volumes:
  shlink_db:

Her iki yayımlanan port da 127.0.0.1 adresine bağlanır. Bu nedenle, sonraki bölümde ters proxy kurulana kadar internetten erişim mümkün değildir. Docker, kendi yönlendirme kurallarını ana makinenin güvenlik duvarından önce uygular. Bu nedenle, yalnızca 8080:8080 kullanılması, güvenlik duvarı kapalı görünse bile uygulamayı dışarıya açar. Döngüsel geri besleme adresine bağlanmak bu sorunu önler. Aynı yöntem bu şekilde çalıştırılan tüm uygulamalar için geçerlidir ve VPS üzerinde Docker Compose kılavuzunda daha ayrıntılı olarak açıklanır.

Veritabanı parolası, compose dosyasının yanındaki bir .env dosyasından alınır. Böylece parola YAML dosyasına yazılmaz.

sudo mkdir -p /opt/shlink
printf 'DB_PASSWORD=%s\n' "$(openssl rand -base64 24)" | sudo tee /opt/shlink/.env
sudo chmod 600 /opt/shlink/.env

Başlatın ve API'nin kullanıma hazır olmasını izleyin.

cd /opt/shlink
sudo docker compose up -d
sudo docker compose logs -f shlink

İlk başlatmada veritabanı geçişleri çalıştırılır. Bu nedenle işlem sonraki başlatmalardan daha uzun sürer. İşlem tamamlandığında hizmetin yerel olarak yanıt verdiğini denetleyin.

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/rest/health

Bir 200, API'nin çalıştığını ve veritabanı bağlantısının başarılı olduğunu gösterir. Buradaki 500 neredeyse her zaman veritabanı kaynaklıdır. Bunun nedeni, .env içindeki DB_PASSWORD değerinin Postgres oluşturulurken kullanılan değerle eşleşmemesidir. Postgres imajı POSTGRES_PASSWORD değerini yalnızca boş bir veri dizinini ilk kez başlatırken okur. Parolayı daha sonra düzenlemek, birimi kaldırıp yeniden başlatana kadar etkili olmaz.

HTTPS'i önünde sonlandırma

Shlink, 8080 bağlantı noktasında düz HTTP sunar. TLS işlemi bir ters proxy'de yapılmalıdır. Önemli olan tek ayar, özgün ana bilgisayar adının iletilmesidir. Shlink, kısa kodun hangi etki alanına ait olduğunu Host üst bilgisini okuyarak belirler. Proxy bu üst bilgiyi yeniden yazarsa mevcut bağlantılar için 404 yanıtları döner ve ziyaret istatistikleri yanlış etki alanına bağlanır.

server {
    server_name s.example.com;
    listen 80;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Ardından sertifikayı oluşturun. Yenileme zamanlayıcısı da dahil olmak üzere tüm adımlar Ubuntu 24.04 üzerinde nginx için Certbot kılavuzunda açıklanmıştır.

sudo certbot --nginx -d s.example.com

Compose dosyasındaki IS_HTTPS_ENABLED: "true", Shlink'in döndürdüğü kısa URL'lerde https:// yazdırmasını sağlar. Tek başına TLS'yi etkinleştirmez. HTTPS proxy'sinin arkasında false olarak bırakılırsa API'nin döndürdüğü her bağlantı, ardından yönlendirilen bir http:// bağlantısı olur. Bu durum ek bir gidiş-dönüşe neden olur ve web istemcisinde hatalı görünür.

API anahtarı oluşturma

Anahtar olmadan hiçbir şey API ile iletişim kuramaz. Container içindeki CLI aracılığıyla bir anahtar oluşturun.

sudo docker compose exec shlink shlink api-key:generate --name "web client"

Komut anahtarı yalnızca bir kez yazdırır. Anahtar hash'lenmiş olarak saklandığından ve tekrar görüntülenemeyeceğinden hemen kopyalayın. shlink api-key:list anahtarların adlarını ve her birinin etkin olup olmadığını gösterir; anahtarın kendisini göstermez. Bir anahtarı shlink api-key:disable ve adını kullanarak iptal edin.

Her REST çağrısında anahtar, X-Api-Key başlığında taşınır.

curl -H "X-Api-Key: YOUR_KEY" https://s.example.com/rest/v3/short-urls

shortUrls anahtarını içeren bir JSON nesnesi, anahtarın çalıştığını gösterir. INVALID_API_KEY içeren bir 401, anahtarın hatalı, devre dışı veya geçerlilik süresinin dolmuş olduğunu gösterir.

Komut satırından kısa bağlantılar oluşturma

CLI, bağlantı oluşturmanın en hızlı yoludur ve betiklerle kullanıma uygundur.

sudo docker compose exec shlink shlink short-url:create https://example.com/a/very/long/path
sudo docker compose exec shlink shlink short-url:create https://example.com/docs --custom-slug docs --tag reference

--custom-slug, oluşturulan bir kod yerine okunabilir bir bağlantı sağlar. Kısa adlar etki alanı başına benzersizdir. Bu nedenle, kullanılan bir kısa adla yapılan ikinci deneme ilk bağlantının üzerine sessizce yazmak yerine başarısız olur. --tag tekrarlanabilir. Etiketler, daha sonra birleşik istatistiklerini almak isteyeceğiniz bağlantıları gruplandırmak için kullanılır.

Mevcut öğeleri listeleyin, ardından bir bağlantının trafiğini inceleyin.

sudo docker compose exec shlink shlink short-url:list
sudo docker compose exec shlink shlink short-url:visits docs

short-url:visits, her tıklama için tarih, yönlendiren ve kullanıcı aracısı bilgilerini içeren bir satır yazdırır. GEOLITE_LICENSE_KEY ortam değişkenini ayarlamadığınız sürece ülke ve şehir sütunları boş kalır. Bu değişken, Shlink'in GeoLite2 veritabanını indirmek için kullandığı ücretsiz bir MaxMind anahtarıdır. Bu anahtar olmadan ziyaretler yine kaydedilir, ancak konumları belirlenmez.

Web istemcisi ve QR kodları

Web istemcisi artık 127.0.0.1:8081 üzerinde çalışır ve kendisi için ayrı bir proxy girdisi gerektirir. İstemciyi yayımlamak istemiyorsanız SSH tüneli de kullanılabilir. İlk yüklemede bir sunucu URL'si ve API anahtarı ister. https://s.example.com değerini ve oluşturulan anahtarı girin. İstemci bu iki bilgiyi tarayıcı depolamasında tutar ve API'nizi doğrudan çağırır. Bu nedenle veriler başka bir sistem üzerinden geçmez.

QR kodları için hiçbir yapılandırma gerekmez. Herhangi bir kısa URL'nin sonuna /qr-code eklenir ve API görüntüyü döndürür.

https://s.example.com/docs/qr-code?size=500&format=svg&margin=20

size piksel cinsinden genişliktir ve 50 ile 1000 arasındaki değerleri kabul eder. Varsayılan değer 300'dür. format, png veya svg değeridir. margin, kodun çevresindeki piksel cinsinden boş alandır. Oluşan görüntünün boyutu, belirtilen boyuta kenar boşluğunun iki katı eklenerek hesaplanır. Küçük basıldığında veya bir bölümü kapatıldığında da taranabilen bir kod için errorCorrection=Q eklenir.

Çalışır durumda tutma

Bir kısaltma hizmeti sessizce arızalanır. Bağlantılar yönlendirme yapmayı durdurur ve kimse size bildirmez, çünkü bağlantıya tıklayan kişi bağlantının artık çalışmadığını varsayar. Çalışma süresi denetimini ana sayfa yerine gerçek bir kısa URL'ye yönlendirin ve yönlendirme olmayan her durumu uyarı olarak bildirin. Kendi sunucunuzda barındırılan Uptime Kuma örneği bunu iyi şekilde yapar ve belirli bir durum kodunu izleyebilir.

Container'ı değil, veritabanını yedekleyin. Tek bir komut veritabanının dökümünü oluşturur.

sudo docker compose exec -T database pg_dump -U shlink shlink | gzip > shlink-$(date +%F).sql.gz

Bu dosya ile compose dosyanız, hizmetin tamamını yeni bir sunucuda yeniden oluşturur. Yükseltmelerde önce sudo docker compose pull, ardından sudo docker compose up -d çalıştırılır ve Shlink başlangıçta yeni migration işlemlerini gerçekleştirir. Dökümü pull işleminden önce alın, çünkü bir migration geri alınamaz.

FAQ

Reverse proxy ekledikten sonra kısa bağlantılarım neden 404 döndürüyor?

Shlink, kısa kodu Host üstbilgisindeki etki alanıyla eşleştirir. Proxy kendi adını veya dahili bir adresi gönderirse Shlink bu kodu bağlantı içermeyen bir etki alanında arar ve 404 yanıtı verir. nginx location bloğunda proxy_set_header Host $host; değerini ayarlayın ve proxy'yi yeniden yükleyin. Bağlantılar, container'ı yeniden başlatmaya gerek kalmadan hemen çalışır.

Postgres gerekli mi, yoksa SQLite yeterli mi?

Shlink'i denemek için SQLite yeterlidir ve ikinci bir container gerektirmez. Önemli bağlantıları yayımlamadan önce Postgres'e geçin; çünkü her tıklamayla ziyaret satırları artar ve SQLite yazma işlemlerini serileştirir. Daha sonra geçiş yapmak, bağlantıları dışa aktarıp yeniden içe aktarmayı gerektirir. Bu nedenle başlangıçta Postgres'i seçmek bu geçişi önler.

Kopyalamayı unuttuğum bir API anahtarını kurtarabilir miyim?

Hayır. Shlink, anahtarın hash değerini saklar. Bu nedenle api-key:list adları ve durumu gösterir, ancak anahtar değerini göstermez. shlink api-key:generate ile yeni bir anahtar oluşturun, bunu web istemcisine yapıştırın, ardından çalışmasını durdurmak için eski anahtarı shlink api-key:disable ile devre dışı bırakın.

Ziyaret istatistiklerimde ülke sütunları neden boş?

Coğrafi konum belirleme için GeoLite2 veritabanı gerekir. Shlink bu veritabanını yalnızca bir GEOLITE_LICENSE_KEY verdiğinizde indirir. Anahtar MaxMind'dan ücretsiz olarak alınabilir. Anahtarı ortam bölümüne ekleyin, container'ı yeniden oluşturun ve yeni ziyaretlerin konumu belirlenir. Bundan önce kaydedilmiş ziyaretler, shlink visit:locate komutu çalıştırılana kadar boş kalır.

Etki alanını koruyun ve verileri taşıyın. Veritabanını pg_dump ile dışa aktarın, dışa aktarılan dosyayı ve compose dosyasını yeni sunucuya kopyalayın, stack'i başlatın, ardından gerçek trafik gelmeden önce dışa aktarılan verileri boş veritabanına geri yükleyin. DNS kaydını son olarak değiştirin. Kısa kodlar ve ziyaret geçmişleri korunur; çünkü tüm veriler veritabanında tutulur.

#shlink#url-shortener#self-hosting#docker#postgres