<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hakan İSMAİL</title>
    <description>The latest articles on DEV Community by Hakan İSMAİL (@hakanbaban53).</description>
    <link>https://dev.to/hakanbaban53</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3593379%2F63770104-9eda-408d-bbe7-f9d3072ffe6e.jpeg</url>
      <title>DEV Community: Hakan İSMAİL</title>
      <link>https://dev.to/hakanbaban53</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hakanbaban53"/>
    <language>en</language>
    <item>
      <title>Local LLM Ops: Building an Observable, GPU-Accelerated AI Cloud at Home with Docker &amp; Grafana</title>
      <dc:creator>Hakan İSMAİL</dc:creator>
      <pubDate>Fri, 13 Feb 2026 19:50:35 +0000</pubDate>
      <link>https://dev.to/hakanbaban53/local-llm-ops-building-an-observable-gpu-accelerated-ai-cloud-at-home-with-docker-grafana-4hbi</link>
      <guid>https://dev.to/hakanbaban53/local-llm-ops-building-an-observable-gpu-accelerated-ai-cloud-at-home-with-docker-grafana-4hbi</guid>
      <description>&lt;h3&gt;
  
  
  Why I Built My Own Local AI Stack: Prioritizing Privacy &amp;amp; ROI
&lt;/h3&gt;

&lt;p&gt;Integrating AI into a development workflow usually starts with a compromise: you either send your proprietary code to a third-party API (risking &lt;strong&gt;Data Privacy&lt;/strong&gt; and &lt;strong&gt;Compliance&lt;/strong&gt;) or you watch your "pay-per-token" bill spiral out of control (&lt;strong&gt;Operational Overhead&lt;/strong&gt;).&lt;/p&gt;

&lt;p&gt;As a &lt;strong&gt;Systems Administrator&lt;/strong&gt;, I prefer a third option: &lt;strong&gt;Data Sovereignty.&lt;/strong&gt; I wanted a private, secure, and fully observable AI environment, eliminating data leak risks (&lt;strong&gt;GDPR/KVKK compliance&lt;/strong&gt;) while achieving significant &lt;strong&gt;Long-term ROI&lt;/strong&gt; by running on my own hardware (Arch Linux + NVIDIA RTX 3050 Ti).&lt;/p&gt;

&lt;p&gt;The real challenge wasn't just downloading an LLM; it was engineering a &lt;strong&gt;Scalable AI Infrastructure&lt;/strong&gt; that runs efficiently on consumer hardware. I'm documenting how I orchestrated this &lt;strong&gt;microservices-based stack&lt;/strong&gt; with &lt;strong&gt;Docker Compose&lt;/strong&gt;, optimized &lt;strong&gt;Resource Management&lt;/strong&gt; for limited VRAM, and established &lt;strong&gt;Full-Stack Observability&lt;/strong&gt; with &lt;strong&gt;Grafana and Prometheus&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  Scalable Microservices Architecture
&lt;/h3&gt;

&lt;p&gt;I went with a modular, containerized approach to ensure internal &lt;strong&gt;Scalability&lt;/strong&gt; and keep the host system clean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inference Management:&lt;/strong&gt; &lt;code&gt;Ollama&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secure Hardware Integration:&lt;/strong&gt; &lt;code&gt;NVIDIA Container Toolkit&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Experience (UX):&lt;/strong&gt; &lt;code&gt;OpenWebUI&lt;/code&gt; (for a polished RAG-capable interface).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Observability Layer:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;NVIDIA DCGM Exporter&lt;/code&gt; for real-time hardware telemetry.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Prometheus&lt;/code&gt; &amp;amp; &lt;code&gt;Grafana&lt;/code&gt; for &lt;strong&gt;SLA monitoring&lt;/strong&gt; and data retention.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Infrastructure &amp;amp; GPU Passthrough
&lt;/h3&gt;

&lt;p&gt;Before deploying the containers, we must ensure the host operating system (Arch Linux in my case) allows Docker to access the GPU hardware. This is not enabled by default.&lt;/p&gt;

&lt;h4&gt;
  
  
  1.1 The Prerequisites: NVIDIA Container Toolkit
&lt;/h4&gt;

&lt;p&gt;The bridge between Docker containers and the physical GPU is the &lt;strong&gt;NVIDIA Container Toolkit&lt;/strong&gt;. Without this, the containers would only see the CPU, resulting in painfully slow inference speeds (0.5 tokens/sec).&lt;/p&gt;

&lt;p&gt;Since I am running Arch Linux, the setup was straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install the toolkit&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; nvidia-container-toolkit

&lt;span class="c"&gt;# Configure the Docker daemon to use the NVIDIA runtime&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;nvidia-ctk runtime configure &lt;span class="nt"&gt;--runtime&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;docker

&lt;span class="c"&gt;# Restart Docker to apply changes&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To verify the passthrough is working, I ran a quick ephemeral container. If &lt;code&gt;nvidia-smi&lt;/code&gt; prints the GPU stats inside Docker, we are green.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--gpus&lt;/span&gt; all nvidia/cuda:12.4.1-runtime-ubuntu22.04 nvidia-smi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsrrkjcd161yeworup8ri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsrrkjcd161yeworup8ri.png" alt="GPU Passthrough Verification (NVIDIA 590.48.01 / CUDA 13.1 on Arch Linux)" width="800" height="639"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Container Orchestration
&lt;/h3&gt;

&lt;p&gt;I believe in "defining once, running everywhere." Instead of running disparate &lt;code&gt;docker run&lt;/code&gt; commands, I defined the entire stack in a single &lt;code&gt;docker-compose.yml&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;This file handles network isolation (creating a private ai-net), volume persistence (so our chat history isn't lost on reboot), and most importantly, &lt;strong&gt;GPU resource reservation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here is the complete configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# 🧠 1. AI ENGINE: Ollama&lt;/span&gt;
  &lt;span class="c1"&gt;# This is the backend that runs the LLM inference.&lt;/span&gt;
  &lt;span class="na"&gt;ollama&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ollama/ollama:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ollama&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;11434:11434"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ollama_storage:/root/.ollama&lt;/span&gt;
    &lt;span class="c1"&gt;# Critical: This section reserves the NVIDIA GPU for this container&lt;/span&gt;
    &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;reservations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;devices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nvidia&lt;/span&gt;
              &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
              &lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;gpu&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ai-net&lt;/span&gt;

  &lt;span class="c1"&gt;# 💻 2. INTERFACE: OpenWebUI&lt;/span&gt;
  &lt;span class="c1"&gt;# A user-friendly frontend that connects to Ollama.&lt;/span&gt;
  &lt;span class="na"&gt;open-webui&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/open-webui/open-webui:main&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;open-webui&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3000:8080"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;OLLAMA_BASE_URL=http://ollama:11434&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;openwebui_storage:/app/backend/data&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ollama&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ai-net&lt;/span&gt;

  &lt;span class="c1"&gt;# 🕵️ 3. METRICS EXPORTER: NVIDIA DCGM&lt;/span&gt;
  &lt;span class="c1"&gt;# This container scrapes GPU metrics (Temp, Power, Utilization).&lt;/span&gt;
  &lt;span class="na"&gt;dcgm-exporter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nvidia/dcgm-exporter:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dcgm-exporter&lt;/span&gt;
    &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;reservations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;devices&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nvidia&lt;/span&gt;
              &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
              &lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;gpu&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DCGM_EXPORTER_NO_HOSTNAME=1&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9400:9400"&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ai-net&lt;/span&gt;

  &lt;span class="c1"&gt;# 🗄️ 4. TIME-SERIES DB: Prometheus&lt;/span&gt;
  &lt;span class="c1"&gt;# Collects the metrics exposed by dcgm-exporter.&lt;/span&gt;
  &lt;span class="na"&gt;prometheus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prom/prometheus:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prometheus&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9090:9090"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./prometheus.yml:/etc/prometheus/prometheus.yml&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;prometheus_data:/prometheus&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;--config.file=/etc/prometheus/prometheus.yml"&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ai-net&lt;/span&gt;

  &lt;span class="c1"&gt;# 📊 5. VISUALIZATION: Grafana&lt;/span&gt;
  &lt;span class="c1"&gt;# Displays the metrics in a dashboard.&lt;/span&gt;
  &lt;span class="na"&gt;grafana&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;grafana/grafana:latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;grafana&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3001:3000"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;grafana_storage:/var/lib/grafana&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ai-net&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ollama_storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;openwebui_storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;prometheus_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;grafana_storage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;ai-net&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Prometheus Scraper Configuration
&lt;/h4&gt;

&lt;p&gt;Prometheus needs to know exactly where to pull metrics from. I configured a 5-second &lt;code&gt;scrape_interval&lt;/code&gt;. While 15s-30s is more common for production, a 5s interval is better for a local lab where we want to track immediate power spikes during token generation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;scrape_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5s&lt;/span&gt; &lt;span class="c1"&gt;# Scrape often for real-time visibility&lt;/span&gt;

&lt;span class="na"&gt;scrape_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpu-metrics"&lt;/span&gt;
    &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dcgm-exporter:9400"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the configuration files in place, a single command boots the entire cloud infrastructure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyux3ha2qpeek4tncp2k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdyux3ha2qpeek4tncp2k.png" alt="Stack Deployment (Ollama, DCGM Exporter, Prometheus, Grafana, OpenWebUI)" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resource Management: Optimizing for 4GB VRAM
&lt;/h3&gt;

&lt;p&gt;The infrastructure setup is the foundation, but &lt;strong&gt;Cost-Sensitive Resource Allocation&lt;/strong&gt;, selecting a model that runs effectively on limited hardware, is where the real value lies. I optimized this build for an &lt;strong&gt;NVIDIA RTX 3050 Ti with 4GB of VRAM&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  The VRAM Constraint
&lt;/h4&gt;

&lt;p&gt;Popular models like DeepSeek R1 or Llama 3 (8B) usually require 5GB to 6GB of VRAM just to load. Offloading these models to system RAM via PCIe on a 4GB card results in unusable generation speeds, often dropping to 1-2 tokens per second.&lt;/p&gt;

&lt;p&gt;I needed a model that fits entirely within the 4GB ceiling while remaining capable for coding tasks.&lt;/p&gt;

&lt;h4&gt;
  
  
  Choosing the right model: Qwen 2.5 Coder (3B)
&lt;/h4&gt;

&lt;p&gt;I used &lt;strong&gt;Hugging Face&lt;/strong&gt; to cross-reference benchmarks and VRAM requirements for various 1B, 3B, and 7B models. After evaluating the trade-offs between parameter count and inference speed, I settled on &lt;strong&gt;Qwen 2.5 Coder (3B Instruct)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Since it only occupies roughly &lt;strong&gt;2.2 GB of VRAM&lt;/strong&gt;, it leaves enough headroom for the context window without triggering a bottleneck. It's significantly faster than larger models that would force the system to swap to system RAM.&lt;/p&gt;

&lt;p&gt;I specifically used the &lt;strong&gt;Instruct&lt;/strong&gt; version; it's much better at actual code logic than the base model.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frj6xcwm5mwioykt0kdej.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frj6xcwm5mwioykt0kdej.png" alt="Qwen Model Card" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can pull it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; ollama ollama run qwen2.5-coder:3b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verifying Telemetry
&lt;/h3&gt;

&lt;p&gt;Once the containers are up, query the DCGM exporter directly to ensure the GPU is communicating correctly with Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:9400/metrics
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6xwjnxnxa31wbqeo05f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6xwjnxnxa31wbqeo05f.png" alt="Raw DCGM Metrics Exposer (Port 9400)" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll see keys like &lt;code&gt;DCGM_FI_DEV_GPU_TEMP&lt;/code&gt; and &lt;code&gt;DCGM_FI_DEV_POWER_USAGE&lt;/code&gt;. Now we need to visualize these in Grafana.&lt;/p&gt;




&lt;h3&gt;
  
  
  Dashboard Configuration
&lt;/h3&gt;

&lt;p&gt;Since Grafana and Prometheus are on the same Docker network (&lt;code&gt;ai-net&lt;/code&gt;), they communicate via container names.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Log in to Grafana (&lt;code&gt;http://localhost:3001&lt;/code&gt;, default &lt;code&gt;admin&lt;/code&gt;/&lt;code&gt;admin&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt; Add &lt;strong&gt;Prometheus&lt;/strong&gt; as a data source and use the URL: &lt;code&gt;http://prometheus:9090&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbcoequasudm252ymofzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbcoequasudm252ymofzv.png" alt="Grafana Data Source Connection" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Import Dashboard ID &lt;strong&gt;12239&lt;/strong&gt; (NVIDIA DCGM Exporter).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffowxbzl9bcmxfys8dvi1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffowxbzl9bcmxfys8dvi1.png" alt="NVIDIA Dashboard Import" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The result is a comprehensive command center for your local AI hardware.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkc4hncwchp5xt8ljxdw7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkc4hncwchp5xt8ljxdw7.png" alt="Active GPU Dashboard (Idle State: ~54.1°C / 10.8 W)" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Real-World Business Value &amp;amp; Metrics
&lt;/h3&gt;

&lt;p&gt;I tested the stack with a typical DevOps automation request:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Write a bash script that detects zombie processes and logs the action."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Full-Stack Observability Analysis
&lt;/h4&gt;

&lt;p&gt;Checking the Grafana dashboard during inference gives the ultimate validation of the setup, proving &lt;strong&gt;System Reliability&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsf45d3zh91rqg6ikx1dj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsf45d3zh91rqg6ikx1dj.png" alt="Final Hardware Analysis (Peak Inference: 64°C / 20.0 W / 2.8 GB VRAM)" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;VRAM Efficiency&lt;/strong&gt;: Usage peaked at &lt;strong&gt;2.8 GB&lt;/strong&gt;. This confirms that the 3B model is the sweet spot: fluent generation with &lt;strong&gt;Zero Licensing Overhead&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Scalability Benchmarks&lt;/strong&gt;: &lt;strong&gt;~438 prompt tokens/s&lt;/strong&gt; and &lt;strong&gt;~10 generation tokens/s&lt;/strong&gt;. Proving that high-performance AI is possible without cloud dependency.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuwvbt0z0er6uupjrv7ue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuwvbt0z0er6uupjrv7ue.png" alt="Scalability Benchmarks" width="218" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Operational Sustainability&lt;/strong&gt;: The GPU pulled a steady &lt;strong&gt;20W&lt;/strong&gt; and stayed at &lt;strong&gt;64°C&lt;/strong&gt;. This is a &lt;strong&gt;Low-Cost/High-Performance&lt;/strong&gt; local solution.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Summary: Driving Innovation Internally
&lt;/h3&gt;

&lt;p&gt;Building a local AI stack isn't just a technical exercise; it's a strategic move for &lt;strong&gt;Business Continuity&lt;/strong&gt; and &lt;strong&gt;Data Security&lt;/strong&gt;. By combining Docker, NVIDIA's toolkit, and a comprehensive observability layer, I've created a dev environment that's both secure and cost-efficient, proving that significant &lt;strong&gt;AI ROI&lt;/strong&gt; can be achieved on existing on-premise hardware.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
    <item>
      <title>Dijital Mahremiyeti Geri Kazanmak: Pi-hole, Unbound ve Tailscale ile Gözetimsiz İnternet</title>
      <dc:creator>Hakan İSMAİL</dc:creator>
      <pubDate>Wed, 28 Jan 2026 15:44:13 +0000</pubDate>
      <link>https://dev.to/hakanbaban53/dijital-mahremiyeti-geri-kazanmak-pi-hole-unbound-ve-tailscale-ile-gozetimsiz-internet-53b2</link>
      <guid>https://dev.to/hakanbaban53/dijital-mahremiyeti-geri-kazanmak-pi-hole-unbound-ve-tailscale-ile-gozetimsiz-internet-53b2</guid>
      <description>&lt;h3&gt;
  
  
  Giriş
&lt;/h3&gt;

&lt;p&gt;Bir Sistem Mühendisi için en büyük israf, atıl duran işlem gücüdür. Çekmecemde uzun süredir "kış uykusunda" olan Raspberry Pi 3'e baktığımda, sadece eski bir devre kartı değil, potansiyel bir ağ savunma hattı görüyordum.&lt;/p&gt;

&lt;p&gt;İnternet Servis Sağlayıcımın (ISS) şeffaf olmayan DNS yönlendirmeleri ve evdeki Akıllı TV’min, ben kullanmasam bile arka planda &lt;strong&gt;Google sunucularına telemetri verisi gönderme çabası&lt;/strong&gt; artık bardağı taşırmıştı.&lt;/p&gt;

&lt;p&gt;Ev ağım, benim kontrolümde olması gereken özel bir alanken, adeta büyük şirketlerin veri madenciliği sahasına dönüşmüştü. Çözüm, o çekmecedeki atıl donanımı &lt;strong&gt;aktif ve tavizsiz bir ağ geçidine&lt;/strong&gt; dönüştürmekte yatıyordu.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amacım netti:&lt;/strong&gt; Kurumsal ağlarda uyguladığımız "Zero Trust" prensibini ev ölçeğine taşımak. Hiçbir cihazın, benim iznim olmadan "Big Tech" sunucularına veri göndermediğinden emin olmak ve bunu yaparken internet performansından ödün vermemek.&lt;/p&gt;

&lt;p&gt;Bu yazıda, basit bir "reklam engelleyici kur geç" rehberinin ötesine geçeceğiz. Terminali açıp, sistemin derinliklerine inerek şunları nasıl yaptığımı anlatacağım:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Google veya Cloudflare'a güvenmek yerine, kendi &lt;strong&gt;Recursive DNS (Unbound)&lt;/strong&gt; sunucumu yapılandırarak aracıları nasıl ortadan kaldırdım?&lt;/li&gt;
&lt;li&gt;İnatçı ISS modeminin elinden &lt;strong&gt;DHCP yetkisini&lt;/strong&gt; alarak ağ yönetimini nasıl tamamen kendi kontrolüme geçirdim?&lt;/li&gt;
&lt;li&gt;Ve en önemlisi: &lt;strong&gt;CGNAT&lt;/strong&gt; arkasında olmama rağmen, bu güvenli kaleye &lt;strong&gt;Tailscale&lt;/strong&gt; ile dünyanın her yerinden nasıl şifreli bir tünel açtım?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eski bir donanımı, modern bir güvenlik cihazına (Network Appliance) dönüştürme hikayesi başlıyor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Araç Çantası (The Stack)
&lt;/h2&gt;

&lt;p&gt;Bu projeyi hayata geçirmek için bir süper bilgisayara veya pahalı firewall cihazlarına ihtiyacınız yok. DNS sorguları ve VPN tünelleme işlemleri şaşırtıcı derecede hafiftir; bu yüzden "atıl donanım" felsefesi burada mükemmel işler.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Donanım (Elimdeki Envanter)
&lt;/h3&gt;

&lt;p&gt;Bu proje için özel bir alışveriş yapmadım. Tamamen "çekmeceden ne çıkarsa" prensibiyle ilerledim.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kart:&lt;/strong&gt; &lt;strong&gt;Raspberry Pi 3 Model B&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Neden Bu?&lt;/em&gt; Çünkü elimde boşta duran kart buydu. Ancak şansıma, &lt;strong&gt;dahili Ethernet portuna&lt;/strong&gt; sahip olması DNS sunucusu için büyük avantaj. Wi-Fi gecikmesini (latency) veya sinyal kopmalarını bir DNS sunucusunda asla istemezsiniz. Kablo kararlılıktır.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Depolama:&lt;/strong&gt; &lt;strong&gt;MicroSD Kart (Class 10)&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Alternatifler
&lt;/h4&gt;

&lt;p&gt;Elinizde illaki Raspberry Pi 3 gibi bit kart olmak zorunda değil. İşte diğer güzel alternatifler:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Raspberry Pi Zero W / 2W:&lt;/strong&gt; Çok daha ucuz ve az güç tüketir. (Ancak Micro-USB Ethernet adaptörü kullanmanızı şiddetle öneririm).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eski Bir Laptop:&lt;/strong&gt; Ekranı kırık, bataryası bitik eski dizüstü bilgisayarınız harika bir sunucu olur. Üstelik dahili bataryası "UPS" (Kesintisiz Güç Kaynağı) görevi görür.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Orange Pi / Banana Pi:&lt;/strong&gt; Piyasadaki Raspberry Pi klonlarının çoğu bu proje için fazlasıyla yeterlidir.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Always-Free Cloud VPS:&lt;/strong&gt; Oracle Cloud veya Google Cloud'un ücretsiz katmanlarında (Free Tier) bir Ubuntu sunucu açıp, ev ağınıza Tailscale "Subnet Router" olarak bağlayabilirsiniz. (Donanım maliyeti: 0₺).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Yazılım (Software)
&lt;/h3&gt;

&lt;p&gt;Burada "bloat"tan (gereksiz şişkinlikten) kaçınan, Unix felsefesine uygun (bir şeyi yap ve iyi yap) araçları seçtim:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;İşletim Sistemi:&lt;/strong&gt; &lt;strong&gt;Raspberry Pi OS Lite (64-bit)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Masaüstü ortamı (GUI) yok, sadece terminal. Bir sunucunun monitöre ihtiyacı yoktur. Headless kurulum yapacağız.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Pi-hole:&lt;/strong&gt; Ağ seviyesinde reklam ve takipçi engelleyici (DNS Sinkhole).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Unbound:&lt;/strong&gt; Recursive DNS çözümleyici. Google'a veya diğer DNS sağlayıcılarına güvenmek yerine kendi doğrulamamızı yapacağız.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tailscale:&lt;/strong&gt; WireGuard tabanlı Mesh VPN. CGNAT duvarlarını delmek ve dışarıdan eve güvenli tünel açmak için.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🏗️ Bölüm 1: Temeli Atmak (İşletim Sistemi Kurulumu)
&lt;/h2&gt;

&lt;p&gt;Bir sunucu kuruyorsak, ilk kural şudur: &lt;strong&gt;GUI (Grafik Arayüz) gereksiz yük ve güvenlik açığıdır.&lt;/strong&gt; Sunucunun monitörü olmaz, terminali olur. Bu yüzden "Raspberry Pi OS Lite (64-bit)" sürümünü tercih ettim.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adım 1: İmajı Yazdırmak
&lt;/h3&gt;

&lt;p&gt;Raspberry Pi kullandığım için işim nispeten kolaydı. Resmi &lt;strong&gt;Raspberry Pi Imager&lt;/strong&gt; yazılımı, sadece imajı karta yazmakla kalmıyor, "OS Customization" özelliğiyle SSH ayarlarını daha kartı cihaza takmadan yapmamızı sağlıyor.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Cihaz Seçimi:&lt;/strong&gt; Raspberry Pi 3.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;İşletim Sistemi:&lt;/strong&gt; Raspberry Pi OS (Other) -&amp;gt; &lt;strong&gt;Raspberry Pi OS Lite (64-bit)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Neden 64-bit?&lt;/em&gt; Pi 3, 64-bit mimariyi destekler. MongoDB gibi bazı modern veritabanı ve servisler artık 32-bit desteğini kesiyor. Geleceğe yatırım yapmak iyidir.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  3. Kritik Adım: "Headless" Hazırlık (OS Customization)
&lt;/h3&gt;

&lt;p&gt;Bir sunucu kurarken monitör, klavye ve fare aramakla vakit kaybetmek istemeyiz. Amacımız &lt;strong&gt;"Tak ve Çalıştır" (Plug and Play)&lt;/strong&gt; değil, &lt;strong&gt;"Tak ve Yönet"&lt;/strong&gt; olmalı.&lt;/p&gt;

&lt;p&gt;Raspberry Pi Imager'ın yeni sürümleri, &lt;strong&gt;"OS Customization"&lt;/strong&gt; özelliği sayesinde işletim sistemini daha karta yazmadan konfigüre etmemize olanak tanıyor. Bu sayede Pi ilk açıldığı anda ağa bağlanıyor, SSH kapısını açıyor ve bizim bağlanmamızı bekliyor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;İmajı yazdır ("Write") demeden önce, o sihirli ayar menüsünü açarak şu konfigürasyonları yaptım:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hostname (Cihaz Adı):&lt;/strong&gt; Cihaza ağda tanınacağı kimliği verdim: &lt;code&gt;pi-hole&lt;/code&gt;. (Siz &lt;code&gt;dns-server&lt;/code&gt; veya yaratıcı başka bir isim seçebilirsiniz).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enable SSH (SSH'ı Aç):&lt;/strong&gt; Bu adım hayati önem taşıyor. Cihaza monitör bağlamayacağımız için tek iletişim yolumuz bu olacak. "Use password authentication" seçeneğini aktif ettim.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Username &amp;amp; Password:&lt;/strong&gt; Buraya kendime özel, kullanıcı adı ve güçlü bir şifre tanımladım.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wireless LAN (Wi-Fi):&lt;/strong&gt; Burayı bilinçli olarak &lt;strong&gt;boş bıraktım&lt;/strong&gt;. Bir DNS sunucusu kablosuz ağın kararsızlığına emanet edilemez. Ethernet kablosu takılı olacağı için Wi-Fi konfigürasyonuna ihtiyacımız yok.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bu ayarları kaydedip &lt;strong&gt;"WRITE"&lt;/strong&gt; butonuna bastığımda, elimde sadece bir işletim sistemi değil, tamamen benim kurallarımla yapılandırılmış, göreve hazır bir sunucu kartı vardı.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstol7m2tcntxn81m4khh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstol7m2tcntxn81m4khh.png" alt="Raspberry Pi Imager" width="730" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Laptop veya Mini PC Kullananlar İçin Not
&lt;/h3&gt;

&lt;p&gt;Eğer bu projeyi eski bir laptop veya Intel NUC gibi bir x86 cihazda yapacaksanız süreç biraz daha geleneksel:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hafif bir dağıtımın ISO dosyasını indirin (Örn: &lt;strong&gt;Debian Server&lt;/strong&gt; veya &lt;strong&gt;Ubuntu Server&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rufus&lt;/strong&gt; veya &lt;strong&gt;BalenaEtcher&lt;/strong&gt; kullanarak USB belleğe yazdırın.&lt;/li&gt;
&lt;li&gt;Cihazı USB'den başlatıp kurulumu tamamlayın.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Adım 2: İlk Önyükleme (First Boot) ve Ağ Taraması
&lt;/h3&gt;

&lt;p&gt;SD kartı Pi'ye taktım, Ethernet kablosunu modeme bağladım ve gücü verdim. Işıklar yanıp sönmeye başladı ama kritik bir eksiğimiz var: &lt;strong&gt;Monitörsüz bir cihazın IP adresini nasıl bulacağız?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bunun için iki yolumuz var.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yöntem 1: Klasik Yol (Modem Arayüzü)&lt;/strong&gt;&lt;br&gt;
En garantili yöntem, ağın patronuna yani modeme sormaktır. &lt;code&gt;192.168.1.1&lt;/code&gt; (veya modeminizin IP'si neyse) adresinden arayüze giriş yapıp &lt;strong&gt;"Bağlı Cihazlar" (Connected Devices)&lt;/strong&gt; listesine baktığınızda, Raspberry Pi'nin sessizce bir IP aldığını göreceksiniz.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hhwif2w18tqics5rrup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4hhwif2w18tqics5rrup.png" alt="Modem Web Arayüzü" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Yöntem 2: Terminal Yolu (Nmap Taraması)&lt;/strong&gt;&lt;br&gt;
Eğer modem şifresini hatırlamıyorsanız veya tarayıcıyla uğraşmak istemiyorsanız, terminalden ağı taramak çok daha hızlı bir yöntemdir.&lt;/p&gt;

&lt;p&gt;Ağdaki cihazları ve üreticilerini listelemek için şu komutu kullandım:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# -sn: Port taraması yapma, sadece ping at (Ping Scan)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;nmap &lt;span class="nt"&gt;-sn&lt;/span&gt; 192.168.1.0/24
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ve işte aradığım cevap karşımda:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Nmap scan report for PC192.168.1.4.station (192.168.1.4)
Host is up (0.0040s latency).
MAC Address: B8:27:EB:4B:79:A8 (Raspberry Pi Foundation)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftf33oxb0j56og77ofkkm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftf33oxb0j56og77ofkkm.png" alt="Nmap Tarama Sonucu" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Terminal, üreticisi "Raspberry Pi Foundation" olan cihazın &lt;strong&gt;192.168.1.4&lt;/strong&gt; adresinde olduğunu raporladı.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bağlantı Anı
&lt;/h3&gt;

&lt;p&gt;Hedef belli olduğuna göre, o büyülü an geldi. SSH ile sisteme giriş yapıyoruz:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh hakan@192.168.1.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuswnm03rlfsui7kr5fwk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuswnm03rlfsui7kr5fwk.png" alt="ssh Bağlantısı Başarılı" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;İçerideyim. 🎉&lt;/p&gt;

&lt;p&gt;Ancak titiz bir &lt;strong&gt;Linux&lt;/strong&gt; kullanıcısı olarak, ilk iş &lt;code&gt;htop&lt;/code&gt; ve &lt;code&gt;systemd-analyze&lt;/code&gt; komutlarını çalıştırdığımda gördüğüm manzara beni tatmin etmedi. Kullanmadığım donanımlar için çalışan servisler ve arka plandaki gereksiz yükler (bloatware), açılış süresini uzatıyordu.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hakan@pi-hole:~ &lt;span class="nv"&gt;$ &lt;/span&gt;systemd-analyze
Startup finished &lt;span class="k"&gt;in &lt;/span&gt;5.988s &lt;span class="o"&gt;(&lt;/span&gt;kernel&lt;span class="o"&gt;)&lt;/span&gt; + 52.832s &lt;span class="o"&gt;(&lt;/span&gt;userspace&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 58.821s 
multi-user.target reached after 22.577s &lt;span class="k"&gt;in &lt;/span&gt;userspace.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sıradaki adımda, elime dijital süpürgeyi alıp bu sistemi temizlemem ve sunucu kondisyonuna getirmem gerekiyordu.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧹 Bölüm 2: "Lite" Yeterince Hafif Değildir (System Hardening)
&lt;/h2&gt;

&lt;p&gt;Sisteme ilk bağlandığımda &lt;code&gt;htop&lt;/code&gt; ve &lt;code&gt;systemd-analyze blame&lt;/code&gt; komutlarını çalıştırdım. Gördüğüm manzara, bir sistem mühendisi için kabul edilemezdi. Boot süresi 1 dakikaya yakındı ve kullanmadığım donanımlar için servisler çalışıyordu.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fba88yh1d5ur7oy9vbhm5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fba88yh1d5ur7oy9vbhm5.png" alt="systemd-analyze blame" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Raspberry Pi OS Lite, genel uyumluluk için "herkese her şey" mantığıyla gelir. Ancak bizim senaryomuzda &lt;strong&gt;Headless (Monitörsüz)&lt;/strong&gt; ve &lt;strong&gt;Kablolu (Ethernet)&lt;/strong&gt; bir DNS sunucusu kuruyoruz. Fazlalıklara yer yok.&lt;/p&gt;

&lt;p&gt;İşte uyguladığım "diyet" programı:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Baş Şüpheli: Cloud-Init
&lt;/h3&gt;

&lt;p&gt;En büyük gecikmeyi (yaklaşık 50 saniye) &lt;code&gt;cloud-init&lt;/code&gt; servisi yaratıyordu. Bu servis, cihaz bir bulut ortamında (AWS, Azure vb.) çalışıyorsa metadata çekmeye yarar. Benim Pi'm masamın üstündeydi, bulutta değil.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Servisleri durdur&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl disable &lt;span class="nt"&gt;--now&lt;/span&gt; cloud-init-local.service cloud-config.service cloud-final.service

&lt;span class="c"&gt;# Paketi ve kalıntılarını sistemden kazı&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt purge &lt;span class="nt"&gt;-y&lt;/span&gt; cloud-init
&lt;span class="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /etc/cloud /var/lib/cloud
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Gereksiz Donanım Servisleri
&lt;/h3&gt;

&lt;p&gt;Sunucumda hoparlör, bluetooth kulaklık veya Wi-Fi kullanmayacağım. Bunları kapatmak hem RAM kazandırır hem de saldırı yüzeyini (attack surface) daraltır.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Bluetooth ve Ses (ALSA) servislerini kaldır&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt purge &lt;span class="nt"&gt;-y&lt;/span&gt; bluez bluez-firmware alsa-utils

&lt;span class="c"&gt;# ModemManager (3G/4G dongle kullanmayacaksanız gereksiz)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt purge &lt;span class="nt"&gt;-y&lt;/span&gt; modemmanager

&lt;span class="c"&gt;# Wi-Fi Servisi (Ethernet kullandığım için)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl disable &lt;span class="nt"&gt;--now&lt;/span&gt; wpa_supplicant
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl mask wpa_supplicant
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Avahi (mDNS)
&lt;/h3&gt;

&lt;p&gt;Sabit IP kullanacağım ve DNS yönetimini kendim yapacağım için &lt;code&gt;raspberrypi.local&lt;/code&gt; gibi mDNS yayınlarına (Bonjour) ihtiyacım yoktu.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl disable &lt;span class="nt"&gt;--now&lt;/span&gt; avahi-daemon
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt purge &lt;span class="nt"&gt;-y&lt;/span&gt; avahi-daemon
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Son Temizlik, Güncellemeler ve Yeniden Başlatma
&lt;/h3&gt;

&lt;p&gt;Sistemi gereksiz servislerden arındırdık. Sistemde yaptığım &lt;code&gt;cloud-init&lt;/code&gt; ve diğer temizliklerden sonra geriye, artık hiçbir işe yaramayan "yetim" paketler (orphan packages) kalmıştı. Terminal bana bunları temizlememi öneriyordu, ben de öneriye uydum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt autoremove &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Artık elimizde, üzerine bina inşa edebileceğimiz tertemiz bir temel var. Bu temeli en son güncellemeler ile güçlendirelim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sistemi yeniden başlatıp sonuca bakalım:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;reboot now
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yeni sonuçlar ise daha tatmin edici:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hakan@pi-hole:~ &lt;span class="nv"&gt;$ &lt;/span&gt;systemd-analyze
Startup finished &lt;span class="k"&gt;in &lt;/span&gt;9.046s &lt;span class="o"&gt;(&lt;/span&gt;kernel&lt;span class="o"&gt;)&lt;/span&gt; + 21.894s &lt;span class="o"&gt;(&lt;/span&gt;userspace&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 30.941s 
multi-user.target reached after 20.891s &lt;span class="k"&gt;in &lt;/span&gt;userspace.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ⚓ Sabit IP (Static IP) Ayarı
&lt;/h3&gt;

&lt;p&gt;Temizlik bitince, ağdaki yerimizi sağlamlaştırmamız gerekiyordu. DNS sunucusunun IP adresi değişirse tüm evin interneti kesilir.&lt;/p&gt;

&lt;p&gt;Modern Raspberry Pi OS sürümleri &lt;strong&gt;NetworkManager&lt;/strong&gt; kullanır. IP sabitlemek için en temiz yol &lt;code&gt;nmtui&lt;/code&gt; aracıdır.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Terminale &lt;code&gt;sudo nmtui&lt;/code&gt; yazdım.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edit a connection&lt;/strong&gt; -&amp;gt; &lt;strong&gt;netplan-eth0&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IPv4 CONFIGURATION&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Manual&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Addresses:&lt;/strong&gt; &lt;code&gt;192.168.1.4/24&lt;/code&gt; (Siz kendi ağınıza göre belirleyin).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gateway:&lt;/strong&gt; &lt;code&gt;192.168.1.1&lt;/code&gt; (Modem IP'si).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DNS Servers:&lt;/strong&gt; Şimdilik &lt;code&gt;1.1.1.1&lt;/code&gt; (Kurulum bitince &lt;code&gt;127.0.0.1&lt;/code&gt; yapacağız).&lt;/li&gt;
&lt;li&gt;(Opsiyonel) &lt;strong&gt;IPv6 CONFIGURATION&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Disabled&lt;/strong&gt; (Eğer IPv6 kullanmıyorsanız yapabilirsiniz).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4es3zllr10f2ea74rrf2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4es3zllr10f2ea74rrf2.png" alt="nmtui ile konfigürasyon" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sistemi yeniden başlatabiliriz:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;reboot now
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🛡️ Bölüm 3: Savunma Hattı (Pi-hole &amp;amp; Unbound)
&lt;/h2&gt;

&lt;p&gt;Temiz bir işletim sistemimiz var. Şimdi onu bir ağ cihazına (Network Appliance) dönüştüreceğiz. Buradaki stratejimiz iki katmanlı:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pi-hole:&lt;/strong&gt; Reklamları ve izleyicileri çöpe atan bekçi.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unbound:&lt;/strong&gt; Sorguları Google'a sormak yerine, doğrudan internetin kök sunucularından (Root Servers) öğrenen çözümleyici.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Adım 1: Pi-hole Kurulumu (Bekçi)
&lt;/h3&gt;

&lt;p&gt;Pi-hole kurulumu, Linux dünyasının en pratik scriptlerinden birine sahip. Terminale şu komutu yapıştırarak kurulum sihirbazı başlattım:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;curl &lt;span class="nt"&gt;-sSL&lt;/span&gt; https://install.pi-hole.net | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sihirbaz sırasında dikkat ettiğim kritik noktalar:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static IP:&lt;/strong&gt; Burada size basit bir uyarı veriyor. Cihazın IP'sinin statik olması gerektiğini özellikle belirtiyor. Biz bunu önceki adımda tamamladık.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Upstream DNS:&lt;/strong&gt; Kurulum sırasında herhangi birini (örn: Google) seçebilirsiniz, birazdan bunu değiştireceğiz.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bloclist:&lt;/strong&gt; Burada pihole un kullandığı 3. pari filtreler için bildirge var. Ben kullanmak istediğim için 'yes'i seçtim.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query Logging:&lt;/strong&gt; Eğer aşırı gizlilik isterneniz 'no' yu seçebilirsiniz. Ben 'yes' ile devam ettim.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy mode for FTL:&lt;/strong&gt; Kullanıcıların hangi siteye sorgu gönderdiğini web arayüzünde  göstermek için &lt;code&gt;Show Everything&lt;/code&gt; ile devam ettim.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Adım 2: Erişim ve Yetkilendirme (Post-Install)
&lt;/h3&gt;

&lt;p&gt;Kurulum sihirbazı bitti ama terminalden henüz çıkmıyoruz. Özellikle &lt;strong&gt;Pi-hole v6&lt;/strong&gt; mimarisiyle gelen önemli bir değişikliği yapılandırmamız gerekiyor.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CLI için API Yetkilendirmesi&lt;/strong&gt;&lt;br&gt;
Pi-hole v6, CLI (Komut Satırı) komutları için artık doğrudan veritabanı manipülasyonu yerine yeni API'sini kullanıyor. Bu güvenlik açısından harika olsa da, her komut girdiğimizde bizden parola istemesi (API authentication) can sıkıcı olabilir.&lt;/p&gt;

&lt;p&gt;Bir sistemci "sudo" yazmaya alışkındır ama gereksiz parola girmekten nefret eder. Kendi kullanıcımızı &lt;code&gt;pihole&lt;/code&gt; grubuna ekleyerek, terminalden parola girmeden yönetim komutlarını çalıştırabilme yetkisi verelim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Mevcut kullanıcımızı ($USER), pihole grubuna ekle&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; pihole &lt;span class="nv"&gt;$USER&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Not: Bu değişikliğin aktif olması için SSH oturumunu kapatıp (&lt;code&gt;exit&lt;/code&gt;) tekrar bağlanmanız gerekebilir.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web Arayüzü Şifresi&lt;/strong&gt;&lt;br&gt;
Pi-hole kurulum sırasında rastgele bir şifre atar. Web arayüzüne (&lt;code&gt;http://192.168.1.4/admin&lt;/code&gt;) her girişte loglara bakmak için o karmaşık şifreyi aramak istemeyiz.&lt;/p&gt;

&lt;p&gt;Aklımızda kalacak güçlü bir şifre belirleyelim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pihole setpassword
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Komutu girdikten sonra yeni şifrenizi yazın (ekranda görünmeyecektir) ve onaylayın.&lt;/p&gt;

&lt;p&gt;Artık hem terminalde hem de web arayüzünde tam yetkiliyiz. Sıra geldi DNS sorgularını özgürleştirmeye: &lt;strong&gt;Unbound Kurulumu.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adım 3: Unbound Kurulumu (Özgürlük)
&lt;/h3&gt;

&lt;p&gt;İşte işin mühendislik kısmı burada başlıyor. Çoğu kullanıcı Pi-hole'u kurar ve DNS olarak Google (8.8.8.8) kullanmaya devam eder. Bu, reklamları engeller ama gizliliğinizi korumaz. Verileriniz hala Google'a akar.&lt;/p&gt;

&lt;p&gt;Biz &lt;strong&gt;Recursive DNS&lt;/strong&gt; kuracağız. Yani aracıları aradan çıkaracağız.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;unbound &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adım 3: Konfigürasyon ve Hız Optimizasyonu 🚀
&lt;/h3&gt;

&lt;p&gt;Unbound'un varsayılan ayarları güvenlik odaklıdır ancak biraz hantaldır. Benim buradaki amacım ise &lt;strong&gt;gecikme hissini&lt;/strong&gt; biraz da olsa azaltmak.&lt;/p&gt;

&lt;p&gt;Bunun için Unbound konfigürasyon dosyasını oluşturdum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/unbound/unbound.conf.d/pi-hole.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ve içine şu optimize edilmiş ayarları girdim. (Buradaki &lt;code&gt;serve-expired&lt;/code&gt; parametresi sihirli dokunuştur):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Log seviyesi (Hata ayıklama gerekmedikçe 0)&lt;/span&gt;
    &lt;span class="na"&gt;verbosity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="na"&gt;interface&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;127.0.0.1&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5335&lt;/span&gt;
    &lt;span class="na"&gt;do-ip4&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
    &lt;span class="na"&gt;do-udp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
    &lt;span class="na"&gt;do-tcp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;

    &lt;span class="c1"&gt;# IPv6'yı kapat (Ev ağında gecikme yaratabilir)&lt;/span&gt;
    &lt;span class="na"&gt;do-ip6&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;no&lt;/span&gt;

    &lt;span class="c1"&gt;# Root Hints dosyası&lt;/span&gt;
    &lt;span class="na"&gt;root-hints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/var/lib/unbound/root.hints"&lt;/span&gt;

    &lt;span class="c1"&gt;# Gizlilik Ayarları&lt;/span&gt;
    &lt;span class="na"&gt;hide-identity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
    &lt;span class="na"&gt;hide-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
    &lt;span class="na"&gt;harden-glue&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
    &lt;span class="na"&gt;harden-dnssec-stripped&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;

    &lt;span class="c1"&gt;# --- PERFORMANS OPTİMİZASYONLARI ---&lt;/span&gt;

    &lt;span class="c1"&gt;# Süresi bitmiş kayıtları (expired) anında sun, arkada güncelle&lt;/span&gt;
    &lt;span class="na"&gt;serve-expired&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;yes&lt;/span&gt;
    &lt;span class="na"&gt;serve-expired-ttl&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;86400&lt;/span&gt;  &lt;span class="c1"&gt;# 1 gün&lt;/span&gt;

    &lt;span class="c1"&gt;# Cache boyutlarını Pi 3'ün RAM'ine göre ayarla&lt;/span&gt;
    &lt;span class="na"&gt;msg-cache-size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;50m&lt;/span&gt;
    &lt;span class="na"&gt;rrset-cache-size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100m&lt;/span&gt;

    &lt;span class="c1"&gt;# İşlemci çekirdeklerini kullan&lt;/span&gt;
    &lt;span class="na"&gt;num-threads&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dosyayı kaydettikten sonra kök sunucuları resmi kaynaktan (InterNIC) en güncel &lt;code&gt;Root Hints&lt;/code&gt; listesini çekip Unbound'un beklediği klasöre koyalım ve izinlerini sağlama alalım:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Dosyayı indir&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;wget &lt;span class="nt"&gt;-O&lt;/span&gt; /var/lib/unbound/root.hints https://www.internic.net/domain/named.root

&lt;span class="c"&gt;# İzinleri ayarla (Unbound kullanıcısının okuyabildiğinden emin olalım)&lt;/span&gt;
&lt;span class="nb"&gt;sudo chown &lt;/span&gt;unbound:unbound /var/lib/unbound/root.hints
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dosyayı kaydedip (CTRL+X, Y, Enter) Servisi yeniden başlatalım:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart unbound
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ayrıca unbound servisi her açılışta otomatik açılacak şekilde ayarlayalım:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;unbound
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adım 4: Büyük Buluşma (Entegrasyon)
&lt;/h3&gt;

&lt;p&gt;Artık Pi-hole'a "Google ile konuşma, yan odadaki Unbound ile konuş" dememiz lazım.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sabit IP (Static IP) Ayarı Yaptığımızda DNS Servers kısmına &lt;code&gt;1.1.1.1&lt;/code&gt; vererek DNS sunucusunu cloudflare olarak ayarlamıştık. Şimdi o ayarı değiştirerek &lt;code&gt;127.0.0.1&lt;/code&gt; yapıp dns sunucusunu yerel cihaz olarak değiştirdim.&lt;/li&gt;
&lt;li&gt;Web tarayıcısından &lt;code&gt;http://192.168.1.4/admin&lt;/code&gt; adresine girdim.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Settings &amp;gt; DNS&lt;/strong&gt; sekmesine geldim.&lt;/li&gt;
&lt;li&gt;Sağdaki hazır listelerin (Google, OpenDNS vb.) hepsinin tikini &lt;strong&gt;kaldırdım&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom 1 (IPv4)&lt;/strong&gt; kutusuna şunu yazdım: &lt;code&gt;127.0.0.1#5335&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsjxyywc1c63bbwh8m4l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsjxyywc1c63bbwh8m4l.png" alt="DNS Ayarı" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sonuç:&lt;/strong&gt;&lt;br&gt;
Şu anda ağımda bir reklam engelleme servisi çalışıyor ve DNS sorgularım şifreli, doğrulanmış ve aracı olmadan çözülüyor. Ancak bir sorun var: Cihazlarım (Telefon, TV) hala modemi dinliyor.&lt;/p&gt;

&lt;p&gt;Sıradaki adımda "Ağ Yönetimini Ele Geçirme" (DHCP Handover) operasyonunu yapacağız.&lt;/p&gt;
&lt;h2&gt;
  
  
  ⚔️ Bölüm 4: Modemi "Aptallaştırmak" (DHCP Operasyonu)
&lt;/h2&gt;

&lt;p&gt;Pi-hole ve Unbound hazırdı. Normal şartlarda, modem arayüzüne girip DNS adresini &lt;code&gt;192.168.1.4&lt;/code&gt; olarak değiştirmek yeterli olmalıydı.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0gnrekv56iv8m1b82i5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0gnrekv56iv8m1b82i5.png" alt="Modem DNS Ayarı" width="758" height="684"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ancak teori ve pratik, ISS modemlerinde asla uyuşmaz.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Kullandığım modem (Vodafone H300s), çoğu ISS cihazı gibi "kilitli" bir kutuydu. DNS ayarlarını değiştirmeme izin verse bile, arka planda ikincil DNS olarak kendi sunucularını zorluyor veya bazı cihazlar (özellikle Android TV ve Chromecast) inatla modemin önerdiği DNS'e gidiyordu. Sonuç? Reklamlar sızmaya devam ediyordu.&lt;/p&gt;

&lt;p&gt;"Kibarca" rica ettim olmadı. Ben de yönetimi zorla almaya karar verdim.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Çözüm:&lt;/strong&gt; Modemin &lt;strong&gt;DHCP sunucusunu&lt;/strong&gt; kapatmak ve IP dağıtma yetkisini &lt;strong&gt;Pi-hole'a&lt;/strong&gt; vermek.&lt;/p&gt;

&lt;p&gt;Bu yöntem iki devasa avantaj sağlar:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Garanti Yönlendirme:&lt;/strong&gt; Pi-hole, IP dağıtırken cihazlara "Tek DNS benim, başka yere bakma" der. Kaçış yoktur.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detaylı Analiz:&lt;/strong&gt; Modem DHCP iken Pi-hole loglarında tüm trafiği tek bir cihazdan (Modem) geliyormuş gibi görürsünüz. Pi-hole DHCP olduğunda, hangi cihazın (iPad, TV, Laptop) hangi siteye girdiğini tek tek görebilirsiniz.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Operasyon Sırası (Dikkat!)
&lt;/h3&gt;

&lt;p&gt;Ağdan kopmamak için sıralama hayati önem taşır. Önce yeni patronu (Pi-hole) devreye almalı, sonra eskisini (Modem) emekli etmelisiniz.&lt;/p&gt;
&lt;h4&gt;
  
  
  Adım 1: Yeni Patronu Hazırla (Pi-hole)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Pi-hole panelinde &lt;strong&gt;Settings &amp;gt; DHCP&lt;/strong&gt; sekmesine gittim.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DHCP server enabled&lt;/strong&gt; kutusunu işaretledim.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Range:&lt;/strong&gt; Modeminkiyle çakışmayacak bir aralık verdim (Örn: &lt;code&gt;192.168.1.5&lt;/code&gt; - &lt;code&gt;192.168.1.254&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Router (Gateway):&lt;/strong&gt; Modemin IP adresini (&lt;code&gt;192.168.1.1&lt;/code&gt;) girdim. &lt;em&gt;Burası çok kritik, yanlış girerseniz internete çıkamazsınız.&lt;/em&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxomqrrr5st017knf57m0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxomqrrr5st017knf57m0.png" alt="DHCP Ayarı" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Adım 2: Eskisini Sustur (Modem)
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Modem arayüzüne girdim.&lt;/li&gt;
&lt;li&gt;LAN / Yerel Ağ ayarlarından &lt;strong&gt;DHCP Sunucusu&lt;/strong&gt; seçeneğini &lt;strong&gt;KAPALI (Disable)&lt;/strong&gt; konuma getirdim.&lt;/li&gt;
&lt;li&gt;Kaydettim.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshx3kyj11wfkftuio7o5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshx3kyj11wfkftuio7o5.png" alt="Son Modem Ayarı" width="758" height="662"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Adım 3: Sözleşme Yenileme (Renew Leases)
&lt;/h4&gt;

&lt;p&gt;Şu an ağda bir kaos yok ama cihazların hala eski "kira sözleşmeleri" (IP Lease) var. Onları yenilemek için:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Telefonun Wi-Fi özelliğini kapatıp açtım.&lt;/li&gt;
&lt;li&gt;Bilgisayarın Ethernet kablosunu çıkarıp taktım.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sonuç:&lt;/strong&gt; Pi-hole panelindeki "DHCP Leases" kısmında cihazlarımın tek tek belirdiğini gördüm. Artık ağın mutlak hakimi Raspberry Pi idi. Modem ise sadece internet sinyalini içeri taşıyan "aptal" bir kutuya (Dumb Pipe) dönüşmüştü. Tam istediğim gibi.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8lel6oams3sj65dfykao.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8lel6oams3sj65dfykao.png" alt="Pi-Hole Üzerinden IP Leases" width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🌍 Bölüm 5: Duvarların İçinden Tünel Açmak (CGNAT ve Tailscale)
&lt;/h2&gt;

&lt;p&gt;Ev ağım artık bir kaleydi: Reklamlar giremiyor, DNS sorguları dışarı sızmıyordu. Ancak büyük bir sorunum vardı: &lt;strong&gt;Ben de eve giremiyordum.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Evden çıktığım anda (mobil veri veya kafe Wi-Fi'ı), ISS'mın güvenli olmayan ağına veya halka açık güvensiz ağlara mahkum kalıyordum. Eve bağlanmak için geleneksel yöntem, modemden port açmaktır. Ancak Türkiye'deki çoğu ev kullanıcısı gibi ben de &lt;strong&gt;CGNAT&lt;/strong&gt; (Carrier Grade NAT) havuzundayım. Yani gerçek bir genel (public) IP adresim yok, bir apartman bloğu gibi binlerce kişiyle aynı IP'yi paylaşıyorum. Dolayısıyla dışarıdan içeriye kapı (port) açmam teknik olarak imkansız.&lt;/p&gt;

&lt;p&gt;Çözüm? &lt;strong&gt;NAT Traversal (NAT Aşımı) ve Overlay Network.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Burada &lt;strong&gt;Tailscale&lt;/strong&gt; devreye giriyor. Tailscale, ISS'nın karmaşık NAT duvarlarını yıkmaz (bunu yapamayız), ancak &lt;strong&gt;"NAT Traversal"&lt;/strong&gt; tekniklerini kullanarak bu duvarların içinden şifreli bir tünel (WireGuard) açar.&lt;/p&gt;

&lt;p&gt;Bu sayede ISS altyapısını kullanmaya devam ederiz ancak ISS, paketlerimizin içeriğini veya nereye gittiğini (DNS) göremez. Sadece şifreli bir veri akışı görür. Kısacası ISS'yı, veriyi sadece A noktasından B noktasına taşıyan "kör" bir taşıyıcıya (Dumb Pipe) dönüştürürüz.&lt;/p&gt;
&lt;h3&gt;
  
  
  Adım 1: Kurulum ve IP Yönlendirme
&lt;/h3&gt;

&lt;p&gt;Headless sunucuma tek satırla Tailscale'i kurdum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://tailscale.com/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tailscale bir "Overlay Network" (Katman Ağı) oluşturur. Ancak Linux çekirdeği varsayılan olarak üzerinden geçen trafiği (packet forwarding) engeller. Pi'nin gelen trafiği internete taşıması için çekirdek ayarlarını değiştirdim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# IPv4 Forwarding'i aç&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'net.ipv4.ip_forward = 1'&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/sysctl.d/99-tailscale.conf
&lt;span class="c"&gt;# Eğer IPv6 Kullanacaksanız:&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'net.ipv6.conf.all.forwarding = 1'&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; /etc/sysctl.d/99-tailscale.conf
&lt;span class="nb"&gt;sudo &lt;/span&gt;sysctl &lt;span class="nt"&gt;-p&lt;/span&gt; /etc/sysctl.d/99-tailscale.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adım 2: Sihirli Komut (Exit Node)
&lt;/h3&gt;

&lt;p&gt;Servisi başlatırken Pi'ye "Sen artık bu sanal ağın internete çıkış kapısısın" dedim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;tailscale up &lt;span class="nt"&gt;--advertise-exit-node&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bana verdiği linke tıklayıp cihazı hesabımla eşleştirdim.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adım 3: Admin Onayı (Güvenlik)
&lt;/h3&gt;

&lt;p&gt;Bu adım genellikle unutulur. Terminalden "ben çıkış kapısıyım" demek yetmez, Tailscale yönetim panelinden (Web) buna izin vermeniz gerekir.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Admin Paneli &amp;gt; Machines &amp;gt; &lt;code&gt;pi-hole&lt;/code&gt; &amp;gt; &lt;strong&gt;Edit Route Settings&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use as exit node&lt;/strong&gt; seçeneğini aktif ettim.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Adım 4 (Opsiyonel ama Önemli): Anahtar Süresini Uzatmak (Disable Key Expiry)
&lt;/h3&gt;

&lt;p&gt;Tailscale, güvenlik tedbiri olarak cihazların oturum anahtarlarını belirli aralıklarla (varsayılan 180 gün) geçersiz kılar. 7/24 çalışan bir sunucu için bu risklidir; tam ihtiyacınız olduğu anda erişiminiz kesilebilir.&lt;/p&gt;

&lt;p&gt;Bu "baş ağrısını" yaşamamak için Pi-hole sunucumuzun oturum süresini kalıcı hale getiriyoruz:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Admin Paneli &amp;gt; Machines&lt;/strong&gt; listesinden &lt;code&gt;pi-hole&lt;/code&gt; cihazını bulun.&lt;/li&gt;
&lt;li&gt;Sağdaki üç noktaya tıklayıp &lt;strong&gt;Disable Key Expiry&lt;/strong&gt; seçeneğini işaretledik. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftg6x91nj5wawkmibbyh1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftg6x91nj5wawkmibbyh1.png" alt="Son Durum" width="363" height="215"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🎉 Sonuç: Dijital Özgürlük
&lt;/h2&gt;

&lt;p&gt;Telefonumun Wi-Fi'ını kapattım, mobil veriye geçtim. Tailscale uygulamasından "Exit Node" olarak evdeki Pi'mi seçtim ve testi başlattım:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fce95wg8qtix2dud4llkk.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fce95wg8qtix2dud4llkk.jpeg" alt="Çıkış Node Seçme" width="800" height="1733"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tünel Testi (Exit Node):&lt;/strong&gt; &lt;code&gt;whatismyip.com&lt;/code&gt;'a girdiğimde, mobil operatörümün IP'sini değil, evimdeki fiber hattın IP'sini gördüm. Trafiğim şifreli bir tünelden eve gidiyor, oradan internete çıkıyordu.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sanal Yerel Ağ:&lt;/strong&gt; Tarayıcıya Pi-hole'un &lt;strong&gt;Tailscale IP adresini&lt;/strong&gt; (100.x.x.x) yazdığımda, sanki evde masamda oturuyormuşum gibi yönetim paneli karşımdaydı. CGNAT engelini, sanal bir ağ katmanıyla aşmıştım.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Termux ile Tam Kontrol:&lt;/strong&gt; Mobil telefonumdan Termux'u açıp, yine aynı Tailscale IP'sine SSH bağlantısı kurdum.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffa1bd6124v1rewjqp0sr.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffa1bd6124v1rewjqp0sr.jpeg" alt="Mobil Durumu" width="800" height="1733"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Özetle:&lt;/strong&gt;&lt;br&gt;
ISS'yi veya CGNAT'ı yok etmedik; bu fiziksel olarak imkansızdı. Ancak kurduğumuz bu yapı ile onları sadece &lt;strong&gt;şifreli paket taşıyan bir altyapıya&lt;/strong&gt; indirgedik.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DNS sorgularımızı göremiyorlar (Unbound + Şifreleme).&lt;/li&gt;
&lt;li&gt;Hangi sitelere girdiğimizi analiz edemiyorlar (VPN Tüneli).&lt;/li&gt;
&lt;li&gt;Bize "public IP vermiyoruz, eve bağlanamazsın" diyemiyorlar (Tailscale/NAT Traversal).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eski bir Raspberry Pi ve doğru mühendislik yaklaşımıyla; binlerce liralık kurumsal cihazların sunduğu "Zero Trust" konforunu evimize getirdik.&lt;/p&gt;

&lt;p&gt;Çekmecenizdeki o kartı çıkarın. İnternetiniz size ait olsun.&lt;/p&gt;

</description>
      <category>raspberrypi</category>
      <category>pihole</category>
      <category>tailscale</category>
      <category>unbound</category>
    </item>
  </channel>
</rss>
