<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Adem Hatay</title>
  <subtitle>Software Developer from Türkiye.</subtitle>
  <link href="https://ademhatay.com/feed.xml" rel="self" type="application/atom+xml"/>
  <link href="https://ademhatay.com/" rel="alternate" type="text/html"/>
  <id>https://ademhatay.com/</id>
  <updated>2026-02-08T01:53:04Z</updated>
  <author>
    <name>Adem Hatay</name>
  </author>

  <entry>
    <title>VSCodium Nedir? Telemetrisiz, Özgür ve Güçlü Bir Kod Editörü</title>
    
    <link href="https://ademhatay.com/yazilar/vscodium-nedir-telemetrisiz-ozgur-kod-editoru/" rel="alternate" type="text/html"/>
    <id>https://ademhatay.com/yazilar/vscodium-nedir-telemetrisiz-ozgur-kod-editoru/</id>
    
    <published>2026-02-08T01:53:04Z</published>
    <updated>2026-02-08T01:53:04Z</updated>
    
    
    <summary>VSCodium&apos;un telemetri içermeyen yapısını, kullanım senaryolarını ve kurulum adımlarını adım adım inceleyen yazı.</summary>
    
    
    <content type="html"><![CDATA[<h1>VSCodium Nedir? Telemetrisiz, Özgür ve Güçlü Bir Kod Editörü</h1>
<blockquote>
<p>Bu blog yazısı, özgür yazılım felsefesini benimseyen geliştiriciler için hazırlanmıştır.</p>
</blockquote>
<p><img src="https://vscodium.com/img/codium_cnl.svg" alt="VSCodium Logo"></p>
<p>Günümüzde yazılım geliştirme dünyası hızla <strong>AI destekli “vibe coding”</strong> anlayışına kayıyor. Ancak herkes kod yazarken arka planda çalışan modelleri, telemetriyi ve kapalı lisansları kabullenmek zorunda değil. Eğer <strong>“ben kodumun kontrolünü elinde tutmak istiyorum”</strong> diyorsan, <strong>VSCodium</strong> tam sana göre.</p>
<h2>VSCodium Nedir?</h2>
<p><strong>VSCodium</strong>, Microsoft’un Visual Studio Code editörünün <strong>topluluk tarafından derlenen</strong>, <strong>telemetri içermeyen</strong> ve <strong>MIT lisanslı</strong> binary dağıtımıdır.</p>
<p>Kısa tanım:</p>
<ul>
<li>Visual Studio Code deneyimi ✅</li>
<li>Microsoft’a ait telemetri ❌</li>
<li>Tamamen özgür ve açık kaynak ✅</li>
</ul>
<h2>Neden Böyle Bir Proje Var?</h2>
<p>VS Code’un kaynak kodu MIT lisansı ile açık olsa da, Microsoft’un sunduğu hazır binary:</p>
<ul>
<li>Telemetri içerir</li>
<li>Microsoft servislerine varsayılan olarak bağlıdır</li>
<li>FLOSS uyumlu değildir</li>
</ul>
<p>Microsoft’un bir geliştirici yorumu durumu net özetliyor:</p>
<blockquote>
<p>Microsoft olarak VS Code’u derlerken product.json dosyasını özelleştiriyor,</p>
</blockquote>
<blockquote>
<p>telemetri ve Microsoft’a özel servisleri ekleyerek kendi lisansımızla yayımlıyoruz.</p>
</blockquote>
<p>İşte <strong>VSCodium</strong>, tam bu noktada devreye giriyor.</p>
<ul>
<li>Aynı kaynak kod</li>
<li>Aynı özellikler</li>
<li>Ama <strong>temiz</strong>, <strong>takipsiz</strong> ve <strong>özgür</strong></li>
</ul>
<h2>Kimler İçin İdeal?</h2>
<ul>
<li>🔐 Gizliliğe önem veren geliştiriciler</li>
<li>🐧 Linux kullanıcıları</li>
<li>🧠 AI bağımlılığı olmadan üretmek isteyenler</li>
<li>📜 Lisans ve etik konularına hassas olanlar</li>
</ul>
<h2>Ekran Görüntüsü</h2>
<p><img src="https://vscodium.com/img/vscodium.png" alt="VSCodium Screenshot"></p>
<h2>Nasıl İndirilir?</h2>
<p>VSCodium; Windows, macOS ve Linux için hazır binary olarak sunulur.</p>
<h3>macOS (Homebrew)</h3>
<pre><code>brew install --cask vscodium
</code></pre>
<h3>Windows</h3>
<pre><code>winget install vscodium
</code></pre>
<pre><code>choco install vscodium
</code></pre>
<pre><code>scoop bucket add extras
scoop install vscodium
</code></pre>
<h3>Linux</h3>
<pre><code>snap install codium --classic
</code></pre>
<pre><code>sudo apt update &amp;&amp; sudo apt install codium
</code></pre>
<pre><code>yay -S vscodium-bin
</code></pre>
<pre><code>sudo dnf install codium
</code></pre>
<pre><code>flatpak install flathub com.vscodium.codium
</code></pre>
<h2>Lisans ve Topluluk</h2>
<ul>
<li>📄 Lisans: <strong>MIT</strong></li>
<li>🤝 Topluluk odaklı</li>
<li>💬 Gitter üzerinden aktif destek</li>
<li>🚫 Telemetri yok</li>
</ul>
<h2>Sonuç</h2>
<p>Eğer:</p>
<ul>
<li>Kod editörünün sana hizmet etmesini,</li>
<li>Seni izlemesini değil,</li>
<li>AI olmadan da güçlü bir geliştirme deneyimi sunmasını</li>
</ul>
<p>istiyorsan, <strong>VSCodium</strong> net bir şekilde doğru tercih.</p>
<p>Özgür yazılım ruhu burada yaşıyor. 🐧✨</p>
]]></content>
    
  </entry>

  <entry>
    <title>Expo + React Native: Google ile Giriş Rehberi (Android + iOS)</title>
    
    <link href="https://ademhatay.com/yazilar/google-auth-expo-cross-platform/" rel="alternate" type="text/html"/>
    <id>https://ademhatay.com/yazilar/google-auth-expo-cross-platform/</id>
    
    <published>2026-02-07T03:00:00Z</published>
    <updated>2026-02-07T03:00:00Z</updated>
    
    
    <summary>Expo projesinde Google login akışını Android ve iOS için kısa, net ve üretime uygun şekilde kurma rehberi.</summary>
    
    
    <content type="html"><![CDATA[<h1>Expo + React Native: Google ile Giriş Rehberi (Android + iOS)</h1>
<p>Bu rehber, <code>@ademhatay/expo-google-signin</code> ile Google girişini hızlıca kurmak içindir.</p>
<p>Hedef:</p>
<ul>
<li>Android ve iOS'ta tek API ile giriş</li>
<li>Kullanıcıyı local'de saklama</li>
<li>Backend'de <code>idToken</code> doğrulama</li>
</ul>
<h2>1) Paket Kurulumu</h2>
<blockquote>
<p>Bu paket Expo Go'da çalışmaz. Development build gerekir.</p>
</blockquote>
<pre><code class="language-bash">npm install @ademhatay/expo-google-signin
# veya
bun add @ademhatay/expo-google-signin
</code></pre>
<pre><code class="language-bash">npx expo run:android
npx expo run:ios
</code></pre>
<h2>2) Google Cloud Console Ayarları</h2>
<p>Gerekli sayfalar:</p>
<ul>
<li>https://console.cloud.google.com/</li>
<li>https://console.cloud.google.com/apis/credentials</li>
<li>https://console.cloud.google.com/apis/credentials/consent</li>
</ul>
<h3>2.1 Web OAuth Client (zorunlu)</h3>
<ul>
<li>Tür: <code>Web application</code></li>
<li>Bu ID, uygulamada <code>serverClientId</code> olarak kullanılacak.</li>
</ul>
<p>Kural:</p>
<ul>
<li><code>serverClientId</code> her zaman <strong>Web Client ID</strong> olmalı.</li>
</ul>
<h3>2.2 Android OAuth Client</h3>
<ul>
<li>Tür: <code>Android</code></li>
<li>Package name ve SHA-1 doğru olmalı.</li>
</ul>
<p>SHA-1 alma:</p>
<pre><code class="language-bash">cd android
./gradlew signingReport
</code></pre>
<p>Release sürecinde birden fazla SHA-1 olabilir (upload key, Play signing key). Gerekli olanları Console'a ekleyin.</p>
<h3>2.3 iOS OAuth Client</h3>
<ul>
<li>Tür: <code>iOS</code></li>
<li>Bundle Identifier, uygulamadaki bundle ID ile aynı olmalı.</li>
</ul>
<h3>2.4 OAuth Consent Screen</h3>
<ul>
<li>Uygulama <code>Testing</code> modundaysa test kullanıcılarını ekleyin.</li>
</ul>
<h2>3) Expo Plugin Ayarı (iOS)</h2>
<p><code>app.json</code> veya <code>app.config.ts</code>:</p>
<pre><code class="language-json">{
  &quot;expo&quot;: {
    &quot;plugins&quot;: [
      [
        &quot;@ademhatay/expo-google-signin&quot;,
        {
          &quot;iosClientId&quot;: &quot;YOUR_IOS_CLIENT_ID.apps.googleusercontent.com&quot;
        }
      ]
    ]
  }
}
</code></pre>
<h2>4) Ortam Değişkenleri</h2>
<pre><code class="language-env">EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID=YOUR_WEB_CLIENT_ID.apps.googleusercontent.com
EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID=YOUR_IOS_CLIENT_ID.apps.googleusercontent.com
</code></pre>
<h2>5) Servis Katmanı</h2>
<h3>5.1 <code>auth-storage.ts</code></h3>
<pre><code class="language-ts">import AsyncStorage from '@react-native-async-storage/async-storage';

export type PersistedGoogleUser = {
  id: string;
  idToken: string;
  displayName?: string;
  givenName?: string;
  familyName?: string;
  profilePictureUrl?: string;
  phoneNumber?: string;
};

const KEY = 'auth:google-user:v1';

export async function saveUser(user: PersistedGoogleUser | null) {
  if (!user) {
    await AsyncStorage.removeItem(KEY);
    return;
  }
  await AsyncStorage.setItem(KEY, JSON.stringify(user));
}

export async function loadUser(): Promise&lt;PersistedGoogleUser | null&gt; {
  const raw = await AsyncStorage.getItem(KEY);
  if (!raw) return null;
  try {
    return JSON.parse(raw) as PersistedGoogleUser;
  } catch {
    return null;
  }
}
</code></pre>
<h3>5.2 <code>auth-service.ts</code></h3>
<pre><code class="language-ts">import { Platform } from 'react-native';
import { signIn, signOut, GoogleUser } from '@ademhatay/expo-google-signin';
import { saveUser, loadUser } from './auth-storage';

const WEB_CLIENT_ID = process.env.EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID!;
const IOS_CLIENT_ID = process.env.EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID;

if (!WEB_CLIENT_ID) {
  throw new Error('Missing EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID');
}

function getIosClientId() {
  if (Platform.OS !== 'ios') return undefined;
  return IOS_CLIENT_ID;
}

export async function loginWithGoogle(options?: { androidButtonFlow?: boolean }) {
  const user = await signIn({
    serverClientId: WEB_CLIENT_ID,
    iosClientId: getIosClientId(),
    filterByAuthorizedAccounts: false,
    signInButtonFlow: options?.androidButtonFlow ?? false
  });

  await saveUser(user);
  return user;
}

export async function logoutGoogle() {
  await signOut();
  await saveUser(null);
}

export async function restorePersistedUser(): Promise&lt;GoogleUser | null&gt; {
  return loadUser();
}
</code></pre>
<h3>5.3 <code>AuthProvider.tsx</code></h3>
<pre><code class="language-tsx">import React, { createContext, useContext, useEffect, useState } from 'react';
import type { GoogleUser } from '@ademhatay/expo-google-signin';
import { loginWithGoogle, logoutGoogle, restorePersistedUser } from './auth-service';

type AuthContextValue = {
  user: GoogleUser | null;
  loading: boolean;
  signInGoogle: (opts?: { androidButtonFlow?: boolean }) =&gt; Promise&lt;void&gt;;
  signOutGoogle: () =&gt; Promise&lt;void&gt;;
};

const AuthContext = createContext&lt;AuthContextValue | null&gt;(null);

export function AuthProvider({ children }: { children: React.ReactNode }) {
  const [user, setUser] = useState&lt;GoogleUser | null&gt;(null);
  const [loading, setLoading] = useState(true);

  useEffect(() =&gt; {
    (async () =&gt; {
      const restored = await restorePersistedUser();
      setUser(restored);
      setLoading(false);
    })();
  }, []);

  async function signInGoogle(opts?: { androidButtonFlow?: boolean }) {
    const next = await loginWithGoogle(opts);
    setUser(next);
  }

  async function signOutGoogle() {
    await logoutGoogle();
    setUser(null);
  }

  return (
    &lt;AuthContext.Provider value={{ user, loading, signInGoogle, signOutGoogle }}&gt;
      {children}
    &lt;/AuthContext.Provider&gt;
  );
}

export function useAuth() {
  const ctx = useContext(AuthContext);
  if (!ctx) throw new Error('useAuth must be used inside AuthProvider');
  return ctx;
}
</code></pre>
<h3>5.4 Ekran Kullanımı</h3>
<pre><code class="language-tsx">import React from 'react';
import { View, Text, Pressable, Platform } from 'react-native';
import { useAuth } from './AuthProvider';

export default function LoginScreen() {
  const { user, signInGoogle, signOutGoogle } = useAuth();

  if (user) {
    return (
      &lt;View style={{ padding: 24 }}&gt;
        &lt;Text style={{ fontSize: 18, fontWeight: '700' }}&gt;
          Welcome {user.displayName || user.id}
        &lt;/Text&gt;
        &lt;Pressable onPress={signOutGoogle} style={{ marginTop: 16 }}&gt;
          &lt;Text&gt;Sign out&lt;/Text&gt;
        &lt;/Pressable&gt;
      &lt;/View&gt;
    );
  }

  return (
    &lt;View style={{ padding: 24, gap: 12 }}&gt;
      {Platform.OS === 'ios' ? (
        &lt;Pressable onPress={() =&gt; signInGoogle({ androidButtonFlow: false })}&gt;
          &lt;Text&gt;Sign In with Google&lt;/Text&gt;
        &lt;/Pressable&gt;
      ) : (
        &lt;&gt;
          &lt;Pressable onPress={() =&gt; signInGoogle({ androidButtonFlow: true })}&gt;
            &lt;Text&gt;Sign In with Google (Button Flow)&lt;/Text&gt;
          &lt;/Pressable&gt;
          &lt;Pressable onPress={() =&gt; signInGoogle({ androidButtonFlow: false })}&gt;
            &lt;Text&gt;Sign In with One-Tap&lt;/Text&gt;
          &lt;/Pressable&gt;
        &lt;/&gt;
      )}
    &lt;/View&gt;
  );
}
</code></pre>
<h2>6) Backend'de Token Doğrulama</h2>
<p><code>idToken</code>'ı doğrudan güvenip session açmayın. Backend'de doğrulayın.</p>
<pre><code class="language-ts">import { OAuth2Client } from 'google-auth-library';

const client = new OAuth2Client();

export async function verifyGoogleIdToken(idToken: string, webClientId: string) {
  const ticket = await client.verifyIdToken({
    idToken,
    audience: webClientId
  });

  const payload = ticket.getPayload();
  if (!payload) throw new Error('Invalid token payload');

  return {
    googleSub: payload.sub,
    email: payload.email,
    emailVerified: payload.email_verified,
    name: payload.name,
    picture: payload.picture
  };
}
</code></pre>
<h2>7) Sık Hatalar</h2>
<h3><code>serverClientId is required</code></h3>
<ul>
<li><code>EXPO_PUBLIC_GOOGLE_WEB_CLIENT_ID</code> eksik.</li>
<li><code>.env</code> uygulamaya yüklenmiyor.</li>
</ul>
<h3><code>Developer console is not set up correctly</code></h3>
<ul>
<li>SHA-1 yanlış.</li>
<li>Package name yanlış.</li>
<li><code>serverClientId</code> olarak Web ID yerine Android/iOS ID verilmiş.</li>
</ul>
<h3><code>iosClientId is required for iOS</code></h3>
<ul>
<li><code>iosClientId</code> yok.</li>
<li>Plugin ayarı yok.</li>
<li>Native rebuild yapılmadı.</li>
</ul>
<h2>Sonuç</h2>
<p>Bu kurulumla:</p>
<ul>
<li>Android ve iOS için tek auth akışı kurarsın.</li>
<li>Kullanıcıyı local'de saklarsın.</li>
<li>Güvenliği backend doğrulamasıyla tamamlarsın.</li>
</ul>
<p>Üretime çıkmadan önce SHA-1, bundle ID ve consent screen ayarlarını tekrar kontrol et.</p>
]]></content>
    
  </entry>

  <entry>
    <title>Self-Host Rehberi: VPS/VDS Üzerinde Docker, Nginx ve Open Source Projelerle Kendi Sunucunu Kur</title>
    
    <link href="https://ademhatay.com/yazilar/self-host-rehberi/" rel="alternate" type="text/html"/>
    <id>https://ademhatay.com/yazilar/self-host-rehberi/</id>
    
    <published>2026-02-05T13:00:00Z</published>
    <updated>2026-02-05T13:00:00Z</updated>
    
    
    <summary>Kendi sunucunu kirala, kontrolü eline al ve servislerini self-host et. Docker, Nginx, domain yönetimi ve güvenlik ipuçlarıyla dolu güncel bir rehber.</summary>
    
    
    <content type="html"><![CDATA[<h1>Self-Host Rehberi: VPS/VDS Üzerinde Docker, Nginx ve Open Source Projelerle Kendi Sunucunu Kur</h1>
<p><img src="https://img.shields.io/badge/self--hosted-%E2%9C%94-brightgreen" alt=""></p>
<p><img src="https://img.shields.io/badge/docker-ready-blue" alt=""></p>
<blockquote>
<p>Bu yazı, bulut bağımlılığından kurtulmak ve dijital egemenliğini eline almak isteyenler için hazırlandı.</p>
</blockquote>
<p><img src="https://www.docker.com/wp-content/uploads/2022/03/Moby-logo.png" alt=""></p>
<h2>Self-Host Nedir ve Neden 2025’te Hâlâ Çok Güçlü?</h2>
<p><strong>Self-host</strong>, kullandığın servisleri (blog, git, cloud, mail, analytics, monitoring vb.) başkalarının SaaS platformlarında değil, <strong>kendi kontrolündeki bir sunucuda</strong> çalıştırmak demektir.</p>
<p>2025 itibarıyla self-host hâlâ çok güçlü çünkü:</p>
<ul>
<li>🔐 Veri senin, kontrol senin</li>
<li>💸 SaaS aboneliklerinden kurtulursun</li>
<li>⚙️ İstediğin gibi özelleştirirsin</li>
<li>🌍 Vendor lock‑in yok</li>
<li>🧠 Gerçek sistem bilgisi kazanırsın</li>
</ul>
<h2>VPS mi, VDS mi? Ne Kiralamalıyım?</h2>
<p>Kısaca:</p>
<table>
<thead>
<tr>
<th>Tür</th>
<th>Açıklama</th>
<th>Kime Uygun</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>VPS</strong></td>
<td>Paylaşımlı fiziksel sunucu</td>
<td>Blog, küçük projeler</td>
</tr>
<tr>
<td><strong>VDS</strong></td>
<td>Dedicated kaynaklar</td>
<td>Yoğun trafik, production</td>
</tr>
</tbody>
</table>
<p>Başlangıç için öneri:</p>
<ul>
<li>2 vCPU</li>
<li>4 GB RAM</li>
<li>40–80 GB SSD</li>
<li>Ubuntu 22.04 / 24.04 LTS</li>
</ul>
<h2>Sunucu İlk Kurulum (Hardening)</h2>
<pre><code>ssh root@SUNUCU_IP
</code></pre>
<pre><code>adduser deploy
usermod -aG sudo deploy
</code></pre>
<pre><code>nano /etc/ssh/sshd_config
PermitRootLogin no
PasswordAuthentication no
</code></pre>
<pre><code>ufw allow OpenSSH
ufw allow 80
ufw allow 443
ufw enable
</code></pre>
<h2>Docker Kurulumu</h2>
<pre><code>curl -fsSL https://get.docker.com | sh
usermod -aG docker deploy
</code></pre>
<pre><code>sudo apt install docker-compose-plugin
</code></pre>
<pre><code>docker compose version
</code></pre>
<h2>Open Source Projeleri Docker ile Deploy Etmek</h2>
<p>Örnek: <strong>Gitea</strong></p>
<pre><code>version: &quot;3&quot;

services:
  gitea:
    image: gitea/gitea:latest
    container_name: gitea
    ports:
      - &quot;3000:3000&quot;
      - &quot;222:22&quot;
    volumes:
      - ./data:/data
    restart: unless-stopped
</code></pre>
<pre><code>docker compose up -d
</code></pre>
<p>Artık servis ayağa kalktı.</p>
<h2>Domain Bağlamak</h2>
<ol>
<li>Domain aldığın yerden <strong>A Record</strong> ekle</li>
<li>IP → sunucu IP’si</li>
<li>TTL: Auto</li>
</ol>
<pre><code>gitea.example.com → 123.123.123.123
</code></pre>
<h2>Nginx ile Reverse Proxy</h2>
<pre><code>apt install nginx
</code></pre>
<pre><code>server {
    server_name gitea.example.com;

    location / {
        proxy_pass http://localhost:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
</code></pre>
<pre><code>ln -s /etc/nginx/sites-available/gitea /etc/nginx/sites-enabled/
nginx -t &amp;&amp; systemctl reload nginx
</code></pre>
<h2>HTTPS (Let’s Encrypt)</h2>
<pre><code>apt install certbot python3-certbot-nginx
certbot --nginx
</code></pre>
<p>🎉 Artık HTTPS aktif.</p>
<h2>En Çok Self-Host Edilen Servisler</h2>
<ul>
<li>📝 Ghost / WordPress</li>
<li>☁️ Nextcloud</li>
<li>🧠 Gitea / Forgejo</li>
<li>📊 Umami Analytics</li>
<li>🗂️ Vaultwarden</li>
<li>📡 Uptime Kuma</li>
</ul>
<h2>Faydalı İpuçları</h2>
<ul>
<li>📦 Her servis için ayrı docker‑compose</li>
<li>🔁 Otomatik yedekleme (restic + cron)</li>
<li>📈 Monitoring (Netdata, Prometheus)</li>
<li>🔒 Fail2ban mutlaka kur</li>
<li>🧹 Log rotation yap</li>
</ul>
<h2>Gerçek Hayat Kullanım Senaryosu</h2>
<blockquote>
<p>Tek bir VDS üzerinde:</p>
</blockquote>
<ul>
<li>5 site</li>
<li>1 Git servisi</li>
<li>Analytics</li>
<li>Status page</li>
</ul>
<p>Hepsi:</p>
<ul>
<li>Docker ile</li>
<li>Nginx arkasında</li>
<li>HTTPS aktif</li>
<li>Aylık maliyet: <strong>tek bir VPS ücreti</strong></li>
</ul>
<h2>Sonuç</h2>
<p>Self-host:</p>
<ul>
<li>Öğreticidir</li>
<li>Özgürleştiricidir</li>
<li>Uzun vadede ekonomiktir</li>
</ul>
<p>Kendi altyapını kurmak zor değil. Zor olan <strong>ilk adımı atmamak</strong>.</p>
<p>Kontrolü geri al. 🚀</p>
]]></content>
    
  </entry>

  <entry>
    <title>Godot Rehberi: Geliştiriciler Neden Bu Motora Akın Ediyor?</title>
    
    <link href="https://ademhatay.com/" rel="alternate" type="text/html"/>
    <id>https://ademhatay.com/#note-202511271200</id>
    
    <published>2025-11-27T12:00:00Z</published>
    <updated>2025-11-27T12:00:00Z</updated>
    
    
    <summary>note posted on 2025-11-27T09:00:00</summary>
    
    
    <content type="html"><![CDATA[<p><a href="https://www.youtube.com/watch?v=FsMIEZ85kbI">Godot Rehberi: Geliştiriciler Neden Bu Motora Akın Ediyor?</a></p>]]></content>
    
  </entry>

  <entry>
    <title>React Native App Performance</title>
    
    <link href="https://ademhatay.com/" rel="alternate" type="text/html"/>
    <id>https://ademhatay.com/#note-202511121200</id>
    
    <published>2025-11-12T12:00:00Z</published>
    <updated>2025-11-12T12:00:00Z</updated>
    
    
    <summary>note posted on 2025-11-12T09:00:00</summary>
    
    
    <content type="html"><![CDATA[<p><a href="https://www.youtube.com/watch?v=lq2H35D9gb0">React Native App Performance</a></p>]]></content>
    
  </entry>

  <entry>
    <title>Gemini CLI Nedir? Nasıl Kullanılır?</title>
    
    <link href="https://ademhatay.com/yazilar/gemini-cli-nedir/" rel="alternate" type="text/html"/>
    <id>https://ademhatay.com/yazilar/gemini-cli-nedir/</id>
    
    <published>2025-07-03T13:00:00Z</published>
    <updated>2025-07-03T13:00:00Z</updated>
    
    
    <summary>Gemini CLI, Google&apos;ın güçlü yapay zeka modeli Gemini&apos;yi doğrudan terminalinize getiren açık kaynaklı bir araçtır. Bu yazıda, Gemini CLI&apos;nin ne olduğunu, nasıl kurulacağını ve nasıl kullanılacağını inceleyeceğiz.</summary>
    
    
    <content type="html"><![CDATA[<img src="https://img.shields.io/badge/AI%20ile-%C3%9Cretilmi%C5%9Ftir-blue" alt="AI ile Üretilmiştir" width="120" />
<blockquote>
<p>Bu blog yazısı Gemini CLI kullanılarak üretilmiştir.</p>
</blockquote>
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Google_Gemini_logo.svg/688px-Google_Gemini_logo.svg.png" width="150" />
<p>Geliştiriciler için komut satırı (CLI), sadece bir araç değil, aynı zamanda bir evdir. Terminalin verimliliği, her yerde bulunabilirliği ve taşınabilirliği, onu işleri halletmek için başvurulan bir yardımcı program haline getirir. Geliştiricilerin terminale olan bağımlılığı devam ettikçe, entegre yapay zeka yardımına olan talep de artmaktadır.</p>
<p>İşte bu yüzden Google, Gemini'nin gücünü doğrudan terminalinize getiren açık kaynaklı bir yapay zeka ajanı olan <strong>Gemini CLI</strong>'yi tanıttı. Gemini'ye hafif erişim sağlayarak, isteminizden modele en doğrudan yolu sunar. Kodlama konusunda üstün olsa da, Google Gemini CLI'yi çok daha fazlasını yapacak şekilde geliştirdi. İçerik oluşturma ve problem çözmeden derin araştırmalara ve görev yönetimine kadar çok çeşitli görevler için kullanabileceğiniz çok yönlü, yerel bir yardımcı programdır.</p>
<h2>Bireysel Geliştiriciler için Eşsiz Kullanım Limitleri</h2>
<p>Gemini CLI'yi ücretsiz kullanmak için kişisel bir Google hesabıyla giriş yapmanız yeterlidir. Bu ücretsiz lisans, size Gemini 2.5 Pro'ya ve devasa 1 milyon jetonluk bağlam penceresine erişim sağlar. Bu önizleme sırasında nadiren bir sınıra takılmanızı sağlamak için sektördeki en büyük kullanım hakkını sunuyor: dakikada 60 model isteği ve günde 1.000 istek ücretsiz.</p>
<h2>Komut Satırınızdaki Güçlü Modeller</h2>
<p>Şu anda önizlemede olan Gemini CLI, kod anlama ve dosya manipülasyonundan komut yürütme ve dinamik sorun gidermeye kadar güçlü yapay zeka yetenekleri sunar. Komut satırı deneyiminize temel bir yükseltme sunarak, doğal dil ile kod yazmanıza, sorunları ayıklamanıza ve iş akışınızı kolaylaştırmanıza olanak tanır.</p>
<h2>Açık ve Genişletilebilir</h2>
<p>Gemini CLI tamamen açık kaynaklı (Apache 2.0) olduğundan, geliştiriciler kodu inceleyerek nasıl çalıştığını anlayabilir ve güvenlik etkilerini doğrulayabilirler. Google, küresel bir geliştirici topluluğunun hataları bildirerek, özellikler önererek, güvenlik uygulamalarını sürekli iyileştirerek ve kod iyileştirmeleri göndererek bu projeye katkıda bulunmasını bekliyor.</p>
<h2>Nasıl Başlanır?</h2>
<p>Gemini CLI ile terminal deneyiminizi bugün yükseltin. Başlamak için Gemini CLI'yi yüklemeniz yeterlidir. Terminalinizde Gemini'yi neredeyse sınırsız kullanmak için tek ihtiyacınız olan bir e-posta adresi.</p>
<h2>Bu Blog Yazısı Gemini CLI ile Nasıl Yazıldı?</h2>
<p>Bu okuduğunuz blog yazısı da aslında Gemini CLI kullanılarak oluşturuldu. Süreç oldukça basitti:</p>
<ol>
<li>
<p><strong>Projenin Klonlanması:</strong> İlk olarak, blog projesinin bulunduğu GitHub deposunu klonladım:</p>
<pre><code class="language-bash">git clone https://github.com/ademhatay/ademhatay.git
</code></pre>
</li>
<li>
<p><strong>Geliştirme Sunucusunun Başlatılması:</strong> Proje dizinine girdikten sonra, gerekli bağımlılıkları kurdum ve geliştirme sunucusunu başlattım:</p>
<pre><code class="language-bash">cd ademhatay
npm install
npm run dev
</code></pre>
</li>
<li>
<p><strong>Blog Yazısının Oluşturulması:</strong> Son olarak, Gemini CLI'ye bu blog yazısını oluşturması için gerekli talimatları verdim. Gemini, verdiğim İngilizce metni referans alarak, Türkçe'ye çevirdi, imla ve dilbilgisi kurallarına uygun hale getirdi ve markdown formatında yeni bir blog yazısı dosyası oluşturdu.</p>
</li>
</ol>
<p>İşte bu kadar! Gemini CLI, geliştiricilerin iş akışlarını hızlandırmak ve daha verimli çalışmalarını sağlamak için tasarlanmış güçlü bir araç.</p>
<p><strong>Kaynak:</strong> <a href="https://blog.google/technology/developers/introducing-gemini-cli-open-source-ai-agent/">https://blog.google/technology/developers/introducing-gemini-cli-open-source-ai-agent/</a></p>
]]></content>
    
  </entry>

  <entry>
    <title>YouTube Playlist&apos;lerini Toplu Halde MP3 Olarak İndirme: Kolay Bir Rehber</title>
    
    <link href="https://ademhatay.com/yazilar/youtube-playlist-mp3-indir/" rel="alternate" type="text/html"/>
    <id>https://ademhatay.com/yazilar/youtube-playlist-mp3-indir/</id>
    
    <published>2024-08-26T07:00:00Z</published>
    <updated>2024-08-26T07:00:00Z</updated>
    
    
    <summary>YouTube playlist&apos;lerini toplu halde MP3 formatında bilgisayarınıza indirmek için kullanabileceğiniz açık kaynak araçlar ve adım adım rehber.</summary>
    
    
    <content type="html"><![CDATA[<h1>YouTube Playlist'lerini Toplu Halde MP3 Olarak İndirme: Kolay Bir Rehber</h1>
<p>Merhaba değerli müzikseverler! Bugün, YouTube'daki en sevdiğiniz çalma listelerini MP3 formatında nasıl indirebileceğinizi anlatacağım. Bazen internete bağlı olmadığınızda da müziğin tadını çıkarmak isteyebilirsiniz ya da en sevdiğiniz şarkıları her an elinizin altında bulundurmak isteyebilirsiniz. Bu rehberde, açık kaynaklı araçlar kullanarak bu işlemi nasıl gerçekleştirebileceğinizi öğreneceksiniz. Endişelenmeyin, adımları takip ederek kolayca bu işlemi gerçekleştirebilirsiniz!</p>
<h2>Neden Açık Kaynak Araçlar Kullanmalıyız?</h2>
<p>Açık kaynak yazılımlar, dünyanın dört bir yanındaki geliştiriciler tarafından geliştirilen ve herkesin kullanımına sunulan harika araçlardır. Bu yazılımları istediğiniz gibi kullanabilir, hatta ihtiyacınıza göre özelleştirebilirsiniz. Üstelik, bu yazılımlar tamamen ücretsizdir! İşte bu yüzden açık kaynak araçlar, YouTube playlist'lerini MP3 olarak indirmek için mükemmel bir tercihtir.</p>
<h2>Adım Adım Rehber</h2>
<p>Şimdi, YouTube playlist'lerinizi nasıl MP3 olarak indirebileceğinizi adım adım inceleyelim. Her bir adımı dikkatlice takip ederek işlemi başarıyla tamamlayabilirsiniz.</p>
<h4>1. Gerekli Araçları Hazırlayın</h4>
<p>İlk olarak, ihtiyacımız olan birkaç yazılım var:</p>
<ul>
<li><strong>Python</strong>: Eğer bilgisayarınızda Python yüklü değilse, <a href="https://www.python.org/downloads/">Python'un resmi web sitesinden</a> indirebilirsiniz.</li>
<li><strong>yt-dlp</strong>: YouTube videolarını indirmek için kullanacağımız güçlü bir araçtır.</li>
<li><strong>ffmpeg</strong>: Ses dosyalarıyla çalışmak için gerekli olan bir programdır.</li>
</ul>
<h4>2. Araçları Kurun</h4>
<p>Şimdi bu araçları bilgisayarımıza kurmamız gerekiyor:</p>
<ol>
<li>
<p>Python'u bilgisayarınıza indirin ve kurulum adımlarını takip edin.</p>
</li>
<li>
<p>Kurulum tamamlandıktan sonra, komut satırını (CMD veya Terminal) açın ve şu komutu yazarak yt-dlp'yi yükleyin:</p>
<pre><code class="language-bash">pip install yt-dlp
</code></pre>
</li>
<li>
<p>ffmpeg'i kurmak ise işletim sisteminize göre farklılık gösterir:</p>
<ul>
<li><strong>Mac kullanıcıları</strong> için: <code>brew install ffmpeg</code> komutunu kullanabilirsiniz.</li>
<li><strong>Linux kullanıcıları</strong> için: <code>sudo apt-get install ffmpeg</code> komutunu kullanın.</li>
<li><strong>Windows kullanıcıları</strong>: <a href="https://ffmpeg.org/download.html">ffmpeg'in web sitesinden</a> indirip, talimatlara göre sisteminize eklemeniz gerekiyor.</li>
</ul>
</li>
</ol>
<h4>3. İndirme Kodunu Hazırlayın</h4>
<p>Şimdi işin en eğlenceli kısmına geldik! Bir metin düzenleyici (Notepad, VS Code vb.) açın ve aşağıdaki Python kodunu yapıştırın:</p>
<pre><code class="language-python">import yt_dlp

ydl_opts = {
    'format': 'bestaudio/best',
    'postprocessors': [{
        'key': 'FFmpegExtractAudio',
        'preferredcodec': 'mp3',
        'preferredquality': '192',
    }],
    'ffmpeg_location': 'C:/path/to/ffmpeg/bin'  # Windows için, diğerleri için gerekli değil
}

playlist_url = 'https://www.youtube.com/playlist?list=PLAYLIST_ID_BURAYA'

with yt_dlp.YoutubeDL(ydl_opts) as ydl:
    ydl.download([playlist_url])
</code></pre>
<p>Bu kodu <code>youtube_indirici.py</code> adıyla kaydedin. Bu kod, playlist'inizdeki videoları en iyi ses kalitesinde indirip MP3 formatına dönüştürecektir.</p>
<h5>4. Playlist'i İndirme Zamanı</h5>
<p>Artık her şey hazır! Şimdi playlist'inizi MP3 formatında indirmek için yapmanız gerekenler:</p>
<ol>
<li>Komut satırını açın.</li>
<li>Kod dosyanızı kaydettiğiniz klasöre gidin.</li>
<li>Aşağıdaki komutu yazın:
<code>python youtube_indirici.py</code></li>
</ol>
<p>Ve işlem bu kadar! Kod çalışmaya başlayacak ve playlist'inizdeki tüm şarkıları MP3 olarak bilgisayarınıza indirecek.</p>
<h2>Son Notlar</h2>
<ul>
<li>İndirme işlemi, playlist'in uzunluğuna ve internet hızınıza bağlı olarak biraz zaman alabilir. Sabırlı olun!</li>
<li>Lütfen telif haklarına saygı gösterin. Bu aracı sadece kişisel kullanım için veya yasal olarak izin verilen içerikler için kullanın.</li>
<li>Eğer bir sorunla karşılaşırsanız, açık kaynak topluluğu her zaman yardıma hazırdır. Çekinmeden sorularınızı sorabilirsiniz!</li>
</ul>
<p>Artık favori YouTube playlist'lerinizi MP3 olarak indirebilir ve dilediğiniz zaman, dilediğiniz yerde müziğin tadını çıkarabilirsiniz. Müzikle kalın ve keyfini çıkarın!</p>
]]></content>
    
  </entry>

  <entry>
    <title>React&apos;te Anlık Saat</title>
    
    <link href="https://ademhatay.com/yazilar/react-anlik-saat/" rel="alternate" type="text/html"/>
    <id>https://ademhatay.com/yazilar/react-anlik-saat/</id>
    
    <published>2024-08-17T03:00:00Z</published>
    <updated>2024-08-17T03:00:00Z</updated>
    
    
    <summary>React uygulamalarında anlık saati göstermek için `requestAnimationFrame` kullanarak nasıl daha iyi bir yaklaşım benimseyebiliriz?</summary>
    
    
    <content type="html"><![CDATA[<h1>Tik Tak: Anlık Saati React'te En İyi Nasıl Gösteririz?</h1>
<p>Bir web uygulamasında anlık saati göstermek, kullanıcı deneyimi açısından önemli bir detaydır. React gibi modern bir kütüphane kullanırken, bunu en verimli ve pürüzsüz şekilde nasıl yapabiliriz? Bu yazıda, <code>requestAnimationFrame</code> kullanarak React'te gerçek zamanlı bir saat nasıl oluşturacağımızı adım adım inceleyeceğiz.</p>
<h2>Neden <code>setInterval</code> veya <code>setTimeout</code> Kullanmamalıyız?</h2>
<p>Genellikle, belirli aralıklarla bir işlevi çağırmak için <code>setInterval</code> veya <code>setTimeout</code> kullanırız. Ancak, bu yöntemler, özellikle hızlı tempolu güncellemeler söz konusu olduğunda, bazı sınırlamalara sahiptir:</p>
<ol>
<li>Zamanı %100 doğru gösteremeyebilir</li>
<li>Gereksiz yere kaynak tüketebilir.</li>
<li>Pürüzsüz ve akıcı bir deneyim sunmayabilir.</li>
</ol>
<h2><code>requestAnimationFrame</code> ile Daha İyi Bir Yaklaşım</h2>
<p><code>requestAnimationFrame</code>, tarayıcıya bir animasyon çerçevesi oluşturmadan önce belirtilen işlevi çağırmasını söyler. Bu, tarayıcının yenileme hızıyla senkronize olarak çalışır ve daha pürüzsüz, verimli güncellemeler sağlar.</p>
<p>İşte React bileşenimizde <code>requestAnimationFrame</code> kullanarak gerçek zamanlı bir saat oluşturmanın adımları:</p>
<ol>
<li>Bileşenin state'inde <code>dateTime</code> adında bir değişken oluşturun ve başlangıç değerini <code>new Date()</code> olarak ayarlayın.</li>
</ol>
<pre><code class="language-jsx">const [dateTime, setDateTime] = useState(new Date());
</code></pre>
<ol start="2">
<li><code>useEffect</code> hook'unu kullanarak, bileşen mount olduğunda <code>updateDateTime</code> fonksiyonunu çağırın. Bu fonksiyon, <code>dateTime</code> state'ini günceller ve <code>requestAnimationFrame</code> kullanarak kendisini yeniden çağırır.</li>
</ol>
<pre><code class="language-jsx">useEffect(() =&gt; {
  let animationFrameId;

  const updateDateTime = () =&gt; {
    setDateTime(new Date());
    animationFrameId = requestAnimationFrame(updateDateTime);
  };

  updateDateTime();

  return () =&gt; {
    if (animationFrameId) {
      cancelAnimationFrame(animationFrameId);
    }
  };
}, []);
</code></pre>
<ol start="3">
<li>JSX'te, <code>dateTime</code> state'ini kullanarak anlık saati render edin.</li>
</ol>
<pre><code class="language-jsx">&lt;div&gt;
  {dateTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' })}
&lt;/div&gt;
</code></pre>
<p>Tüm bunları bir araya getiren kodun tamamı:</p>
<pre><code class="language-jsx">import React, { useState, useEffect } from 'react';

function RealTimeClock() {
  const [dateTime, setDateTime] = useState(new Date());

  useEffect(() =&gt; {
    let animationFrameId;

    const updateDateTime = () =&gt; {
      setDateTime(new Date());
      animationFrameId = requestAnimationFrame(updateDateTime);
    };

    updateDateTime();

    return () =&gt; {
      if (animationFrameId) {
        cancelAnimationFrame(animationFrameId);
      }
    };
  }, []);

  return (
    &lt;div&gt;
      {dateTime.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' })}
    &lt;/div&gt;
  );
}

export default RealTimeClock;
</code></pre>
<p>Bu yaklaşım, saati her saniye güncellerken bile son derece pürüzsüz ve verimli bir şekilde çalışır. Tarayıcının yenileme hızıyla senkronize olduğu için, gereksiz güncellemelerden kaçınır ve kullanıcıya daha iyi bir deneyim sunar.</p>
<h2>Sonuç</h2>
<p>React uygulamalarında anlık saati göstermek uygulamaya ayrı bir hava katar. <code>setInterval</code> veya <code>setTimeout</code> gibi geleneksel yöntemler yerine <code>requestAnimationFrame</code> kullanmak, daha pürüzsüz, verimli ve kullanıcı dostu bir deneyim sağlar. Bu makalede, <code>requestAnimationFrame</code> ile React'te gerçek zamanlı bir saat bileşeni oluşturmanın adımlarını gördük. Umarım bu tekniği kendi projelerinizde kullanabilir ve kullanıcılarınıza daha iyi bir deneyim sunabilirsiniz!</p>
]]></content>
    
  </entry>

  <entry>
    <title>WireGuard Nedir? Nasıl Kurulur?</title>
    
    <link href="https://ademhatay.com/yazilar/wireguard-nedir-nasil-kurulur/" rel="alternate" type="text/html"/>
    <id>https://ademhatay.com/yazilar/wireguard-nedir-nasil-kurulur/</id>
    
    <published>2024-08-09T03:00:00Z</published>
    <updated>2024-08-09T03:00:00Z</updated>
    
    
    <summary>Wireguard hızlı, modern ve güvenli bir VPN protokolüdür. Bu rehberde, WireGuard&apos;ın ne olduğunu, nasıl çalıştığını ve kimlerin işine yarayacağını detaylı bir şekilde ele alacağız.</summary>
    
    
    <content type="html"><![CDATA[<img src="https://fineproxy.org/wp-content/uploads/2023/09/WireGuard-logo.png" width="300" />
<h2>WireGuard Nedir? Ne İşe Yarar? Ne Amaçla Kuruldu?</h2>
<p><strong>WireGuard</strong>, hızlı, modern ve güvenli bir VPN (Virtual Private Network) protokolüdür. Bu protokol, cihazlar arasındaki iletişimi şifreleyerek güvenli bir ağ tüneli oluşturur. WireGuard, basitliği ve performansıyla dikkat çeker. Diğer VPN protokollerine göre daha az kod içermesi, onu daha güvenli ve verimli kılar. WireGuard, başlangıçta Linux çekirdeği için geliştirilmiştir, ancak günümüzde neredeyse tüm büyük işletim sistemleri için destek sunmaktadır.</p>
<p>WireGuard'ın temel amacı, geleneksel VPN protokollerine (OpenVPN, IPSec vb.) kıyasla daha yüksek güvenlik, daha az gecikme ve daha iyi performans sunmaktır. Ayrıca, karmaşık yapılandırmalara gerek kalmadan kolayca kullanılabilen bir çözüm sunmayı hedefler.</p>
<h2>WireGuard Nasıl Çalışır?</h2>
<p>WireGuard, VPN tünelleri oluşturmak için &quot;kapsamlı ağ kodu&quot; yerine modern kriptografik protokolleri kullanır. Bu, protokolün daha hızlı, daha güvenli ve daha esnek olmasını sağlar. Her bir WireGuard bağlantısı, &quot;public key&quot; (genel anahtar) ve &quot;private key&quot; (özel anahtar) çifti kullanılarak kimlik doğrulama ve şifreleme gerçekleştirir. Ayrıca, WireGuard bağlantıları, UDP protokolü üzerinden yapılır, bu da onu hızlı ve verimli kılar.</p>
<h2>Kimlerin İşine Yarar?</h2>
<p>WireGuard, aşağıdaki amaçlar için idealdir:</p>
<ul>
<li>
<p><strong>Bireyler ve küçük işletmeler:</strong> Evde veya küçük ofis ortamlarında güvenli bir şekilde internete bağlanmak isteyen kullanıcılar için uygundur.</p>
</li>
<li>
<p><strong>Büyük ölçekli şirketler:</strong> Şirket içi ağlar arasında güvenli bağlantılar oluşturmak için kullanılabilir.</p>
</li>
<li>
<p><strong>Geliştiriciler ve ağ yöneticileri:</strong> Kolay kurulumu ve yapılandırması nedeniyle, test ve geliştirme ortamları için mükemmeldir.</p>
</li>
</ul>
<h2>WireGuard Nasıl Kurulur?</h2>
<p>WireGuard'ı iki farklı yöntemle kurabilirsiniz: self-hosted (kendi sunucunuzda) veya Docker kullanarak. İki yöntem de oldukça basit ve etkili.</p>
<h4>Self-Hosted Kurulum</h4>
<ol>
<li>
<p><strong>Sunucuyu Hazırlayın:</strong></p>
<ul>
<li>
<p>Sunucunuzun işletim sistemini güncelleyin:</p>
<pre><code class="language-bash">sudo apt update &amp;&amp; sudo apt upgrade -y
</code></pre>
</li>
<li>
<p>WireGuard'ı kurmak için gerekli olan paketleri yükleyin:</p>
<pre><code class="language-bash">sudo apt install wireguard -y
</code></pre>
</li>
</ul>
</li>
<li>
<p><strong>Anahtar Çifti Oluşturun:</strong></p>
<ul>
<li>
<p>Private ve public key çiftini oluşturun:</p>
<pre><code class="language-bash">wg genkey | tee privatekey | wg pubkey &gt; publickey
</code></pre>
</li>
</ul>
</li>
<li>
<p><strong>Konfigürasyon Dosyasını Ayarlayın:</strong></p>
<ul>
<li>
<p><code>/etc/wireguard/wg0.conf</code> dosyasını oluşturun ve aşağıdaki gibi yapılandırın:</p>
<pre><code class="language-bash">[Interface]
PrivateKey = &lt;Sunucunun Private Key i&gt;
Address = 10.0.0.1/24
ListenPort = 51820
SaveConfig = true
</code></pre>
</li>
</ul>
</li>
<li>
<p><strong>WireGuard'ı Başlatın:</strong></p>
<pre><code class="language-bash">sudo systemctl start wg-quick@wg0
sudo systemctl enable wg-quick@wg0
</code></pre>
</li>
</ol>
<h4>Docker ile WireGuard Kurulumu (wg-easy)</h4>
<p><strong>wg-easy</strong>, WireGuard'ı Docker ile kurmayı ve yönetmeyi oldukça kolaylaştıran bir çözüm sunar. Bu yazılım, web tabanlı bir arayüz üzerinden VPN'inizi yönetmenizi sağlar.</p>
<h5>Adım 1: Docker'ı Kurun</h5>
<p>Docker'ın yüklü olup olmadığını kontrol edin ve gerekirse yükleyin:</p>
<pre><code class="language-bash">curl -sSL https://get.docker.com | sh
sudo usermod -aG docker $(whoami)
exit
</code></pre>
<p>Komutlardan sonra tekrar oturum açarak Docker'ın düzgün çalıştığını doğrulayın.</p>
<h5>Adım 2: WireGuard Easy'i Çalıştırın</h5>
<p>WireGuard Easy'i Docker üzerinde çalıştırmak için aşağıdaki komutu kullanın:</p>
<pre><code class="language-bash">docker run -d \
  --name=wg-easy \
  -e LANG=tr \
  -e WG_HOST=&lt;Sunucunuzun_IP_Adresi&gt; \
  -e PASSWORD_HASH=&lt;Şifrenizin_Bcrypt_Hash'i&gt; \
  -e PORT=51821 \
  -e WG_PORT=51820 \
  -v ~/.wg-easy:/etc/wireguard \
  -p 51820:51820/udp \
  -p 51821:51821/tcp \
  --cap-add=NET_ADMIN \
  --cap-add=SYS_MODULE \
  --sysctl=&quot;net.ipv4.conf.all.src_valid_mark=1&quot; \
  --sysctl=&quot;net.ipv4.ip_forward=1&quot; \
  --restart unless-stopped \
  ghcr.io/wg-easy/wg-easy
</code></pre>
<p>Bu komut, WireGuard'ı Docker üzerinde çalıştırır ve web arayüzü üzerinden yönetim sağlar. Web arayüzü, sunucunuzun IP adresi veya alan adı üzerinden erişilebilir olacaktır (örneğin: <code>http://0.0.0.0:51821</code>).</p>
<h5>Adım 3: wg-easy Kullanarak İstemciyi Kurun</h5>
<p>Web arayüzünden yeni bir istemci oluşturun. Oluşturulan istemci için QR kodunu kullanarak mobil cihazdan bağlanabilirsiniz. Mobil cihazınızda WireGuard uygulamasını açın, &quot;Add Tunnel&quot; seçeneği ile QR kodunu taratın.</p>
<h5>Adım 4: Docker'ı Nginx ile Custom Domain'e Bağlamak</h5>
<p>WireGuard arayüzünü bir custom domain altında çalıştırmak için Nginx'i proxy olarak kullanabilirsiniz.</p>
<ol>
<li>
<p><strong>Nginx'i Kurun:</strong></p>
<pre><code class="language-bash">sudo apt install nginx -y
</code></pre>
</li>
<li>
<p><strong>Nginx Konfigürasyon Dosyasını Ayarlayın:</strong></p>
<ul>
<li>
<p><code>/etc/nginx/sites-available/wireguard</code> dosyasını oluşturun ve aşağıdaki gibi yapılandırın:</p>
<pre><code class="language-bash">server {
    listen 80;
    server_name vpn.example.com;

    location / {
        proxy_pass http://localhost:51821;
        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;
    }
}
</code></pre>
</li>
</ul>
</li>
<li>
<p><strong>Domain Adınızı Etkinleştirin:</strong></p>
<pre><code class="language-bash">sudo ln -s /etc/nginx/sites-available/wireguard /etc/nginx/sites-enabled/
sudo systemctl restart nginx
</code></pre>
</li>
<li>
<p><strong>DNS Ayarlarınızı Yapın:</strong></p>
<ul>
<li>Domain adınızın DNS ayarlarında, A kaydı ekleyerek sunucunuzun IP adresini ekleyin.</li>
</ul>
</li>
</ol>
<p>Artık VPN sunucunuza <code>vpn.sizin-domaininiz.com</code> üzerinden erişebilirsiniz.</p>
<h2>Sonuç</h2>
<p>Bu rehberde, WireGuard'ın ne olduğunu, nasıl çalıştığını ve kimlerin işine yarayacağını detaylı bir şekilde ele aldık. Ayrıca, hem self-hosted hem de Docker ile nasıl kurulacağını gösterdik. Özellikle Docker tabanlı <strong>wg-easy</strong> aracı sayesinde, WireGuard VPN sunucusunu kurmak ve yönetmek oldukça basit hale gelmektedir. Nginx ile custom domain üzerinden erişim sağlayarak, daha profesyonel bir yapı kurabilirsiniz. Bu adımları izleyerek kendi güvenli VPN altyapınızı kurabilir ve yönetebilirsiniz.</p>
]]></content>
    
  </entry>

  <entry>
    <title>Next.js &amp; Docker</title>
    
    <link href="https://ademhatay.com/yazilar/nextjs-docker-export/" rel="alternate" type="text/html"/>
    <id>https://ademhatay.com/yazilar/nextjs-docker-export/</id>
    
    <published>2024-07-27T07:00:00Z</published>
    <updated>2024-07-27T07:00:00Z</updated>
    
    
    <summary>Next.js uygulamasının Docker ile standalone export edilmesi ve containerize edilmesi</summary>
    
    
    <content type="html"><![CDATA[<img src="https://i.hizliresim.com/qu90umb.png" width="350" />
<h1>Next.js Uygulamasının Docker ile Standalone Export Edilmesi</h1>
<p>Next.js, React tabanlı web uygulamaları geliştirmek için popüler bir framework'tür. Next.js uygulamalarını Docker ile containerize etmek, daha iyi güvenlik, taşınabilirlik ve ölçeklenebilirlik sağlar.</p>
<p>Bu yazıda, Next.js uygulamasının Docker ile standalone export edilmesi ve containerize edilmesi adım adım anlatılacaktır.</p>
<h2>1. Next.js Uygulaması Oluşturma</h2>
<p>İlk adım olarak, yeni bir Next.js uygulaması oluşturalım:</p>
<pre><code class="language-bash">npx create-next-app nextjs-docker-export
cd nextjs-docker-export
</code></pre>
<h2>2. Gerekli Dosyaların Eklenmesi</h2>
<p>Uygulamaya birkaç örnek CSS, JavaScript dosyası ve resim ekleyelim:</p>
<ul>
<li><code>styles/global.css</code> dosyasını oluşturun ve genel stilleri ekleyin.</li>
<li><code>public</code> klasörüne birkaç örnek resim ekleyin.</li>
<li><code>pages/index.js</code> dosyasını düzenleyerek örnek içerik ve resimler ekleyin.</li>
</ul>
<p><code>next.config.mjs</code> dosyasında aşağıdaki içeriği ekleyin:</p>
<pre><code class="language-javascript">const nextConfig = {
    output: &quot;standalone&quot;
};
</code></pre>
<h2>3. Dockerfile Oluşturma</h2>
<p>Projenin kök dizininde <code>Dockerfile</code> adında bir dosya oluşturun ve aşağıdaki içeriği ekleyin:</p>
<pre><code class="language-dockerfile">FROM node:18-alpine

WORKDIR /app

COPY package.json yarn.lock ./

RUN yarn install

COPY . .

RUN yarn build

RUN mkdir -p .next/standalone/.next &amp;&amp; \
    mv .next/static .next/standalone/.next/static &amp;&amp; \
    mv public .next/standalone/public &amp;&amp; \
    mv .env.development .next/standalone/

WORKDIR /app/.next/standalone

EXPOSE 3000

CMD [&quot;node&quot;, &quot;server.js&quot;]
</code></pre>
<p>Bu Dockerfile, Next.js uygulamasını Docker imajına derleyecek ve çalıştıracaktır.</p>
<h2>4. .dockerignore Dosyası Oluşturma</h2>
<p>Projenin kök dizininde <code>.dockerignore</code> adında bir dosya oluşturun ve aşağıdaki içeriği ekleyin:</p>
<pre><code>node_modules
.next
</code></pre>
<p>Bu dosya, gereksiz dosyaların Docker imajına kopyalanmasını önleyecektir.</p>
<h2>5. Docker Compose Dosyası Oluşturma</h2>
<p>Projenin kök dizininde <code>docker-compose.yml</code> adında bir dosya oluşturun ve aşağıdaki içeriği ekleyin:</p>
<pre><code class="language-yaml">version: '3'
services:
  frontend:
    build: .
    ports:
      - &quot;3000:3000&quot;
    volumes:
      - .:/app
      - /app/node_modules
      - /app/.next
    environment:
      - NODE_ENV=development # or production
</code></pre>
<p>Bu Docker Compose dosyası, uygulamayı Docker containerında çalıştıracaktır.</p>
<h2>6. Uygulamayı Çalıştırma</h2>
<p>Aşağıdaki komutu kullanarak uygulamayı Docker containerında çalıştırın:</p>
<p><code>docker-compose up --build</code></p>
<p>Uygulama, <code>http://localhost:3000</code> adresinde çalışacaktır.</p>
<h2>Sonuç</h2>
<p>Bu yazıda, Next.js uygulamasının Docker ile standalone export edilmesi ve containerize edilmesi adım adım anlatıldı. Docker, Next.js uygulamalarının daha güvenli, taşınabilir ve ölçeklenebilir bir şekilde dağıtılmasını sağlar. Umarım bu yazı, Next.js uygulamalarınızı Docker ile dağıtmanıza yardımcı olmuştur.</p>
<p>Faydalı olması dileğiyle!</p>
]]></content>
    
  </entry>

  <entry>
    <title>Perast, Karadağ</title>
    
    <link href="https://ademhatay.com/" rel="alternate" type="text/html"/>
    <id>https://ademhatay.com/#note-202304051300</id>
    
    <published>2023-04-05T13:00:00Z</published>
    <updated>2023-04-05T13:00:00Z</updated>
    
    
    <summary>note posted on 2023-04-05T10:00:00</summary>
    
    
    <content type="html"><![CDATA[<img src="https://ademhatay.com/assets/images/perast.jpg" alt="Perast, Karadağ">]]></content>
    
  </entry>

  <entry>
    <title>Kotor, Karadağ</title>
    
    <link href="https://ademhatay.com/" rel="alternate" type="text/html"/>
    <id>https://ademhatay.com/#note-202304051200</id>
    
    <published>2023-04-05T12:00:00Z</published>
    <updated>2023-04-05T12:00:00Z</updated>
    
    
    <summary>note posted on 2023-04-05T09:00:00</summary>
    
    
    <content type="html"><![CDATA[<img src="https://ademhatay.com/assets/images/kotor.jpg" alt="Kotor, Karadağ">]]></content>
    
  </entry>

</feed>
