LocalAI API Güvenliği ve Reverse Proxy Yapılandırması
Sunucunuzda LocalAI kurulumunu tamamladınız, modeller çalışıyor, istekler yanıt veriyor. Peki ya güvenlik? Varsayılan kurulumda LocalAI, kimlik doğrulama olmadan 8080 portunda dinliyor. Bu, iç ağda bile ciddi bir risk. Dış dünyaya açık bir sunucuda ise tam anlamıyla felaket reçetesi. Bu yazıda LocalAI’ı production ortamına hazır hale getirmek için API güvenliği, reverse proxy yapılandırması ve pratik güvenlik katmanlarını ele alacağız.
Neden Güvenlik Gerekli?
LocalAI’ı sadece localhost’ta kullanıyorsanız bile birkaç senaryo var ki görmezden gelemezsiniz. Sunucunuzda başka servisler çalışıyor olabilir, bu servislerden birinin XSS veya SSRF açığı varsa LocalAI’a ulaşabilir. Geliştirme ortamınızda çalışan bir uygulama yanlışlıkla dışarı açılabilir. Ya da ekibinizdeki herkes API’ye sınırsız erişim istiyor ama bant genişliği ve GPU kaynakları sınırlı.
Temel tehdit modeli şu şekilde:
- Kimliği doğrulanmamış erişim
- Rate limiting eksikliği (kaynak tüketimi)
- Düz HTTP üzerinden veri iletimi
- API key yönetiminin olmaması
- Log kaydının yetersizliği
LocalAI’ın Yerleşik Güvenlik Ayarları
LocalAI bazı temel güvenlik özelliklerini built-in olarak sunuyor. İlk adım bunları aktif etmek.
API Key Yapılandırması
LocalAI, LOCALAI_API_KEY ortam değişkeniyle basit bir API key koruması sunuyor:
# Docker ile çalıştırıyorsanız
docker run -d
--name localai
-p 127.0.0.1:8080:8080
-e LOCALAI_API_KEY="gizli-api-anahtariniz-buraya"
-v /opt/localai/models:/models
--gpus all
localai/localai:latest
# Systemd service ile çalıştırıyorsanız /etc/localai/env dosyasına ekleyin
echo 'LOCALAI_API_KEY=gizli-api-anahtariniz-buraya' >> /etc/localai/env
Dikkat edin, portu 127.0.0.1:8080 olarak bağladık. Bu, LocalAI’ın sadece localhost’tan erişilebilir olmasını sağlıyor. 0.0.0.0:8080 yazmayın, bu tüm arayüzlere açar.
API key doğrulamak için:
# Doğru key ile istek
curl -H "Authorization: Bearer gizli-api-anahtariniz-buraya"
http://localhost:8080/v1/models
# Key olmadan istek (401 dönmeli)
curl http://localhost:8080/v1/models
Güçlü API Key Oluşturma
Basit bir string yazmayın. OpenSSL ile güçlü bir key üretin:
# 32 byte random key üretimi
openssl rand -base64 32
# Çıktı örneği: K8mP2xQrT5vN9wL1jH4cA7sE6fY0bI3dU+oZ==
# Bu çıktıyı API key olarak kullanın
Nginx ile Reverse Proxy Kurulumu
Nginx, LocalAI önüne koyabileceğiniz en iyi reverse proxy seçeneklerinden biri. TLS sonlandırma, rate limiting, IP kısıtlaması ve header manipülasyonu için mükemmel.
Nginx Kurulumu
# Ubuntu/Debian
apt update && apt install -y nginx
# RHEL/CentOS/Rocky Linux
dnf install -y nginx
# Nginx'i başlatın
systemctl enable --now nginx
Temel Reverse Proxy Yapılandırması
/etc/nginx/sites-available/localai dosyasını oluşturun:
cat > /etc/nginx/sites-available/localai << 'EOF'
# Rate limiting zone tanımları
limit_req_zone $binary_remote_addr zone=localai_general:10m rate=10r/m;
limit_req_zone $binary_remote_addr zone=localai_completion:10m rate=5r/m;
limit_conn_zone $binary_remote_addr zone=localai_conn:10m;
upstream localai_backend {
server 127.0.0.1:8080;
keepalive 32;
}
server {
listen 80;
server_name ai.sirketiniz.com;
# HTTP'yi HTTPS'e yönlendir
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name ai.sirketiniz.com;
# SSL sertifika ayarları
ssl_certificate /etc/letsencrypt/live/ai.sirketiniz.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/ai.sirketiniz.com/privkey.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;
# Güvenlik headerlari
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "strict-origin-when-cross-origin";
# Bağlantı limiti - IP başına max 10 eş zamanlı bağlantı
limit_conn localai_conn 10;
# Genel istek boyutu limiti (büyük prompt'lar için artırabilirsiniz)
client_max_body_size 10m;
client_body_timeout 300s;
# Completion endpoint - daha sıkı rate limit
location /v1/completions {
limit_req zone=localai_completion burst=3 nodelay;
limit_req_status 429;
proxy_pass http://localai_backend;
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;
# Streaming için timeout değerleri
proxy_read_timeout 600s;
proxy_send_timeout 600s;
proxy_connect_timeout 10s;
# Streaming desteği
proxy_buffering off;
proxy_cache off;
}
# Chat completion endpoint
location /v1/chat/completions {
limit_req zone=localai_completion burst=3 nodelay;
limit_req_status 429;
proxy_pass http://localai_backend;
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;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
proxy_buffering off;
proxy_cache off;
}
# Genel API endpoint'leri
location /v1/ {
limit_req zone=localai_general burst=20 nodelay;
limit_req_status 429;
proxy_pass http://localai_backend;
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;
proxy_read_timeout 120s;
proxy_connect_timeout 10s;
}
# Diğer tüm istekleri reddet
location / {
return 404;
}
# Log yapılandırması
access_log /var/log/nginx/localai_access.log combined;
error_log /var/log/nginx/localai_error.log warn;
}
EOF
# Symlink oluştur
ln -s /etc/nginx/sites-available/localai /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
Let’s Encrypt ile TLS Sertifikası
# Certbot kurulumu
apt install -y certbot python3-certbot-nginx
# Sertifika al
certbot --nginx -d ai.sirketiniz.com
--non-interactive
--agree-tos
-m [email protected]
# Otomatik yenileme kontrolü
systemctl status certbot.timer
certbot renew --dry-run
IP Bazlı Erişim Kısıtlaması
Eğer LocalAI’ı sadece belirli IP adreslerinden erişilebilir yapmak istiyorsanız, Nginx’te bunu kolayca yapabilirsiniz. Örneğin sadece ofis IP’si ve VPN subnet’inden erişim:
# /etc/nginx/conf.d/localai_whitelist.conf
cat > /etc/nginx/conf.d/localai_whitelist.conf << 'EOF'
geo $localai_allowed {
default 0;
# Ofis IP adresi
203.0.113.50/32 1;
# VPN subnet
10.8.0.0/24 1;
# Dahili ağ
192.168.1.0/24 1;
# Localhost
127.0.0.1/32 1;
}
EOF
Sonra Nginx server bloğunuzun başına ekleyin:
# server bloğu içine, diğer location direktiflerinden önce
if ($localai_allowed = 0) {
return 403 "Bu kaynaga erisim yetkiniz yok.";
}
Caddy ile Alternatif Reverse Proxy
Caddy, otomatik TLS yönetimi ile daha basit bir kurulum sunuyor. Özellikle hızlı kurulum gerekiyorsa tercih edilebilir:
# Caddy kurulumu
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' |
gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' |
tee /etc/apt/sources.list.d/caddy-stable.list
apt update && apt install -y caddy
Caddyfile yapılandırması:
cat > /etc/caddy/Caddyfile << 'EOF'
ai.sirketiniz.com {
# Otomatik TLS - Let's Encrypt
tls [email protected]
# Rate limiting
rate_limit {
zone dynamic_zone {
key {remote_host}
events 10
window 1m
}
}
# Güvenlik headerlari
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains"
X-Content-Type-Options nosniff
X-Frame-Options DENY
-Server
}
# Sadece /v1/ path'ini proxy'le
handle /v1/* {
reverse_proxy localhost:8080 {
transport http {
read_timeout 10m
write_timeout 10m
}
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
}
}
# Diğer istekleri reddet
handle {
respond "Not Found" 404
}
log {
output file /var/log/caddy/localai_access.log
format json
}
}
EOF
systemctl enable --now caddy
Fail2ban ile Brute Force Koruması
Rate limiting tek başına yeterli değil. Fail2ban ile kötü niyetli IP’leri kalıcı olarak engelleyebilirsiniz:
apt install -y fail2ban
# LocalAI için özel jail tanımı
cat > /etc/fail2ban/jail.d/localai.conf << 'EOF'
[localai-auth]
enabled = true
port = http,https
filter = localai-auth
logpath = /var/log/nginx/localai_access.log
maxretry = 5
findtime = 300
bantime = 3600
action = iptables-multiport[name=localai, port="http,https", protocol=tcp]
[localai-ratelimit]
enabled = true
port = http,https
filter = localai-ratelimit
logpath = /var/log/nginx/localai_access.log
maxretry = 10
findtime = 60
bantime = 600
EOF
# Filter tanımlamaları
cat > /etc/fail2ban/filter.d/localai-auth.conf << 'EOF'
[Definition]
failregex = ^<HOST> .* "(GET|POST) /v1/.* HTTP/.*" 401
ignoreregex =
EOF
cat > /etc/fail2ban/filter.d/localai-ratelimit.conf << 'EOF'
[Definition]
failregex = ^<HOST> .* "(GET|POST) /v1/.* HTTP/.*" 429
ignoreregex =
EOF
systemctl enable --now fail2ban
fail2ban-client status localai-auth
API Key Rotasyonu ve Yönetimi
Production ortamında tek bir API key kullanmak riskli. Birden fazla client için farklı keyler oluşturun ve bunları bir script ile yönetin:
#!/bin/bash
# /usr/local/bin/localai-key-manager.sh
KEYS_FILE="/etc/localai/api_keys"
LOG_FILE="/var/log/localai/key_rotations.log"
generate_key() {
local client_name=$1
local new_key=$(openssl rand -base64 32 | tr -d '/+=' | head -c 40)
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
echo "${client_name}:${new_key}" >> "$KEYS_FILE"
echo "[$timestamp] Yeni key olusturuldu: $client_name" >> "$LOG_FILE"
echo "Client: $client_name"
echo "Key: $new_key"
echo "Bu key'i guvenli bir yerde saklayin!"
}
revoke_key() {
local client_name=$1
local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
sed -i "/^${client_name}:/d" "$KEYS_FILE"
echo "[$timestamp] Key iptal edildi: $client_name" >> "$LOG_FILE"
echo "$client_name icin key iptal edildi."
}
list_clients() {
echo "Aktif client'lar:"
cut -d: -f1 "$KEYS_FILE" | sort
}
case "$1" in
generate) generate_key "$2" ;;
revoke) revoke_key "$2" ;;
list) list_clients ;;
*) echo "Kullanim: $0 {generate|revoke|list} [client_name]" ;;
esac
Monitoring ve Alerting
Güvenlik ayarları kadar önemli olan şey, ne olduğunu bilmek. Basit bir monitoring scripti:
#!/bin/bash
# /usr/local/bin/localai-monitor.sh
# Crontab: */5 * * * * /usr/local/bin/localai-monitor.sh
LOCALAI_URL="http://localhost:8080"
API_KEY="gizli-api-anahtariniz"
ALERT_EMAIL="[email protected]"
LOG="/var/log/localai/monitor.log"
THRESHOLD_401=20
THRESHOLD_429=50
# Son 5 dakikadaki 401 sayısını kontrol et
count_401=$(grep "401" /var/log/nginx/localai_access.log |
awk -v d="$(date -d '5 minutes ago' '+%d/%b/%Y:%H:%M')"
'$4 > "["d' | wc -l)
# Son 5 dakikadaki 429 sayısını kontrol et
count_429=$(grep "429" /var/log/nginx/localai_access.log |
awk -v d="$(date -d '5 minutes ago' '+%d/%b/%Y:%H:%M')"
'$4 > "["d' | wc -l)
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
if [ "$count_401" -gt "$THRESHOLD_401" ]; then
echo "[$timestamp] UYARI: Son 5 dakikada $count_401 adet 401 hatasi" >> "$LOG"
echo "LocalAI'da anormal kimlik dogrulama hatasi: $count_401 adet 401" |
mail -s "LocalAI Guvenlik Uyarisi" "$ALERT_EMAIL"
fi
if [ "$count_429" -gt "$THRESHOLD_429" ]; then
echo "[$timestamp] UYARI: Son 5 dakikada $count_429 adet 429 hatasi" >> "$LOG"
echo "LocalAI'da rate limit asimi: $count_429 adet 429" |
mail -s "LocalAI Rate Limit Uyarisi" "$ALERT_EMAIL"
fi
# LocalAI'in ayakta olup olmadığını kontrol et
http_code=$(curl -s -o /dev/null -w "%{http_code}"
-H "Authorization: Bearer $API_KEY"
"$LOCALAI_URL/v1/models")
if [ "$http_code" != "200" ]; then
echo "[$timestamp] KRITIK: LocalAI yanit vermiyor! HTTP: $http_code" >> "$LOG"
echo "LocalAI servisi yanit vermiyor! HTTP kodu: $http_code" |
mail -s "LocalAI Servis Hatasi" "$ALERT_EMAIL"
fi
Firewall Yapılandırması
Tüm bu güvenlik katmanlarını desteklemek için UFW veya nftables kuralları:
# UFW ile temel güvenlik kuralları
ufw default deny incoming
ufw default allow outgoing
# SSH erişimi (sadece güvenilen IP'lerden)
ufw allow from 203.0.113.50 to any port 22 proto tcp
# HTTP ve HTTPS (Nginx için)
ufw allow 80/tcp
ufw allow 443/tcp
# LocalAI portunu dışarıya ASLA açmayın
# ufw allow 8080 --> BU SATIRI EKLEMEYIN
ufw enable
ufw status verbose
Gerçek Dünya Senaryosu: Ekip Ortamı
Diyelim ki 5 kişilik bir geliştirici ekibiniz var ve hepsi LocalAI’ı kullanacak. Her biri farklı projelerde çalışıyor ve kaynak kullanımını takip etmek istiyorsunuz. İşte pratik yaklaşım:
Her geliştirici için ayrı bir API key oluşturun:
for dev in ahmet mehmet ayse fatma ali; do
/usr/local/bin/localai-key-manager.sh generate $dev
done
Nginx’te her key için farklı rate limit uygulayın. Özellikle test ortamında sınırsız istek atan birini hemen fark edersiniz. Log’lardan kim ne kadar istek atıyor görebilir, GPU kullanımını planlayabilirsiniz.
Ayrıca belirli model endpoint’lerini kısıtlayabilirsiniz. Örneğin büyük modeller sadece belirli saatlerde kullanılabilsin:
# Nginx time-based erişim kısıtlaması
map $time_iso8601 $working_hours {
default 0;
"~T(0[89]|1[0-7]):" 1; # 08:00 - 17:59 arası
}
# location bloğu içinde
if ($working_hours = 0) {
return 503 "Bu model mesai saatleri disinda kullanilamaz.";
}
Sonuç
LocalAI’ı production ortamına almak düşündüğünüzden fazla iş gerektiriyor ama bu adımları atlarsanız er ya da geç başınız ağrıyacak. Özetlersek:
- Lokalhosta bağlama: LocalAI her zaman
127.0.0.1:8080dinlemeli, asla0.0.0.0‘a açılmamalı - API key zorunluluğu:
LOCALAI_API_KEYolmadan servisi başlatmayın - Reverse proxy: Nginx veya Caddy arkasına alın, TLS sonlandırmayı burada yapın
- Rate limiting: Hem genel hem de completion endpoint’leri için ayrı limitler koyun
- Fail2ban: Tekrarlı başarısız girişimleri otomatik engelleyin
- Firewall: 8080 portunu asla dışarıya açmayın
- Monitoring: Ne olduğunu bilmezseniz sorun büyüdükten sonra fark edersiniz
Bu yapılandırmalar büyük bir kurumsal güvenlik altyapısı gerektirmiyor. Birkaç saat ayırıp bu adımları uygularsanız, LocalAI kurulumunuz hem güvenli hem de yönetilebilir bir hale gelir. GPU’nuz sizin için çalışsın, başkaları için değil.
