chore: initialize
This commit is contained in:
commit
f202a39e52
6 changed files with 301 additions and 0 deletions
27
.env.example
Normal file
27
.env.example
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
# ============================================
|
||||||
|
# Hetzner Self-Hosted Stack — Environment Variables
|
||||||
|
# Copy to .env and fill in your values:
|
||||||
|
# cp .env.example .env
|
||||||
|
# ============================================
|
||||||
|
|
||||||
|
# --- LiteLLM ---
|
||||||
|
LITELLM_MASTER_KEY=sk-change-me-to-a-random-string
|
||||||
|
OPENROUTER_API_KEY=sk-or-...
|
||||||
|
SILICONFLOW_API_KEY=sk-...
|
||||||
|
DEEPINFRA_API_KEY=...
|
||||||
|
GROQ_API_KEY=gsk_...
|
||||||
|
CEREBRAS_API_KEY=...
|
||||||
|
|
||||||
|
# --- Cloudflare Tunnel ---
|
||||||
|
# Create a tunnel in Cloudflare Zero Trust dashboard → Networks → Tunnels
|
||||||
|
# Copy the token from the tunnel install command
|
||||||
|
CLOUDFLARE_TUNNEL_TOKEN=eyJ...
|
||||||
|
|
||||||
|
# --- Tailscale ---
|
||||||
|
# Generate at https://login.tailscale.com/admin/settings/keys
|
||||||
|
# Use a reusable + ephemeral key for unattended servers
|
||||||
|
TS_AUTHKEY=tskey-auth-...
|
||||||
|
|
||||||
|
# --- SearXNG ---
|
||||||
|
# Random secret key for SearXNG (generate with: openssl rand -hex 32)
|
||||||
|
SEARXNG_SECRET_KEY=change-me-to-a-random-hex-string
|
||||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Environment secrets
|
||||||
|
.env
|
||||||
|
|
||||||
|
# SearXNG runtime state
|
||||||
|
searxng/uwsgi.ini
|
||||||
31
cloud-init.yml
Normal file
31
cloud-init.yml
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
#cloud-config
|
||||||
|
|
||||||
|
users:
|
||||||
|
- name: rayandrew
|
||||||
|
groups: [sudo, docker]
|
||||||
|
shell: /bin/bash
|
||||||
|
sudo: ALL=(ALL) NOPASSWD:ALL
|
||||||
|
ssh_authorized_keys:
|
||||||
|
- ssh-import-id gh:rayandrew
|
||||||
|
|
||||||
|
package_update: true
|
||||||
|
package_upgrade: true
|
||||||
|
|
||||||
|
packages:
|
||||||
|
- curl
|
||||||
|
- git
|
||||||
|
- unattended-upgrades
|
||||||
|
|
||||||
|
runcmd:
|
||||||
|
# Install Docker via official convenience script
|
||||||
|
- curl -fsSL https://get.docker.com | sh
|
||||||
|
- systemctl enable docker
|
||||||
|
- systemctl start docker
|
||||||
|
|
||||||
|
# Clone repo and set ownership
|
||||||
|
- git clone https://git.rs.ht/rayandrew/ai-servers.git /home/rayandrew/ai-servers
|
||||||
|
- chown -R rayandrew:rayandrew /home/rayandrew/ai-servers
|
||||||
|
|
||||||
|
# Enable automatic security updates
|
||||||
|
- systemctl enable unattended-upgrades
|
||||||
|
- systemctl start unattended-upgrades
|
||||||
122
docker-compose.yml
Normal file
122
docker-compose.yml
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
services:
|
||||||
|
# ── Cache for SearXNG ──
|
||||||
|
valkey:
|
||||||
|
image: valkey/valkey:8-alpine
|
||||||
|
command: valkey-server --save 30 1 --loglevel warning
|
||||||
|
volumes:
|
||||||
|
- valkey-data:/data
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "valkey-cli", "ping"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
|
# ── Private search engine ──
|
||||||
|
searxng:
|
||||||
|
image: searxng/searxng:latest
|
||||||
|
volumes:
|
||||||
|
- ./searxng:/etc/searxng:rw
|
||||||
|
environment:
|
||||||
|
- SEARXNG_SECRET_KEY=${SEARXNG_SECRET_KEY}
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8080:8080"
|
||||||
|
depends_on:
|
||||||
|
valkey:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# ── Vector database ──
|
||||||
|
chromadb:
|
||||||
|
image: chromadb/chroma:latest
|
||||||
|
volumes:
|
||||||
|
- chromadb-data:/chroma/chroma
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:8000:8000"
|
||||||
|
environment:
|
||||||
|
- IS_PERSISTENT=TRUE
|
||||||
|
- ANONYMIZED_TELEMETRY=FALSE
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8000/api/v1/heartbeat"]
|
||||||
|
interval: 15s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
|
# ── LLM API proxy ──
|
||||||
|
litellm:
|
||||||
|
image: ghcr.io/berriai/litellm:main-latest
|
||||||
|
command: ["--config", "/app/config.yaml", "--port", "4000"]
|
||||||
|
volumes:
|
||||||
|
- ./litellm/config.yaml:/app/config.yaml:ro
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:4000:4000"
|
||||||
|
environment:
|
||||||
|
- LITELLM_MASTER_KEY=${LITELLM_MASTER_KEY}
|
||||||
|
- OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
|
||||||
|
- SILICONFLOW_API_KEY=${SILICONFLOW_API_KEY}
|
||||||
|
- DEEPINFRA_API_KEY=${DEEPINFRA_API_KEY}
|
||||||
|
- GROQ_API_KEY=${GROQ_API_KEY}
|
||||||
|
- CEREBRAS_API_KEY=${CEREBRAS_API_KEY}
|
||||||
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:4000/health/liveliness"]
|
||||||
|
interval: 15s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
start_period: 30s
|
||||||
|
|
||||||
|
# ── Chat UI ──
|
||||||
|
open-webui:
|
||||||
|
image: ghcr.io/open-webui/open-webui:main
|
||||||
|
volumes:
|
||||||
|
- open-webui-data:/app/backend/data
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:3000:8080"
|
||||||
|
environment:
|
||||||
|
- OLLAMA_BASE_URL=
|
||||||
|
- OPENAI_API_BASE_URL=http://litellm:4000/v1
|
||||||
|
- OPENAI_API_KEY=${LITELLM_MASTER_KEY}
|
||||||
|
- ENABLE_RAG_WEB_SEARCH=true
|
||||||
|
- RAG_WEB_SEARCH_ENGINE=searxng
|
||||||
|
- SEARXNG_QUERY_URL=http://searxng:8080/search?q=<query>&format=json
|
||||||
|
- CHROMA_HTTP_HOST=chromadb
|
||||||
|
- CHROMA_HTTP_PORT=8000
|
||||||
|
- WEBUI_AUTH=true
|
||||||
|
depends_on:
|
||||||
|
litellm:
|
||||||
|
condition: service_healthy
|
||||||
|
chromadb:
|
||||||
|
condition: service_healthy
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# ── Cloudflare Tunnel (public HTTPS) ──
|
||||||
|
cloudflared:
|
||||||
|
image: cloudflare/cloudflared:latest
|
||||||
|
command: tunnel run
|
||||||
|
environment:
|
||||||
|
- TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# ── Tailscale (private VPN access) ──
|
||||||
|
tailscale:
|
||||||
|
image: tailscale/tailscale:latest
|
||||||
|
hostname: hetzner-stack
|
||||||
|
volumes:
|
||||||
|
- tailscale-state:/var/lib/tailscale
|
||||||
|
- /dev/net/tun:/dev/net/tun
|
||||||
|
cap_add:
|
||||||
|
- NET_ADMIN
|
||||||
|
- SYS_MODULE
|
||||||
|
environment:
|
||||||
|
- TS_AUTHKEY=${TS_AUTHKEY}
|
||||||
|
- TS_STATE_DIR=/var/lib/tailscale
|
||||||
|
- TS_USERSPACE=false
|
||||||
|
restart: unless-stopped
|
||||||
|
network_mode: host
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
valkey-data:
|
||||||
|
chromadb-data:
|
||||||
|
open-webui-data:
|
||||||
|
tailscale-state:
|
||||||
64
litellm/config.yaml
Normal file
64
litellm/config.yaml
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
model_list:
|
||||||
|
# --- OpenRouter models ---
|
||||||
|
- model_name: kimi-k2.5
|
||||||
|
litellm_params:
|
||||||
|
model: openrouter/moonshotai/kimi-k2.5
|
||||||
|
api_key: os.environ/OPENROUTER_API_KEY
|
||||||
|
|
||||||
|
- model_name: devstral
|
||||||
|
litellm_params:
|
||||||
|
model: openrouter/mistralai/devstral-small
|
||||||
|
api_key: os.environ/OPENROUTER_API_KEY
|
||||||
|
|
||||||
|
- model_name: minimax-m2
|
||||||
|
litellm_params:
|
||||||
|
model: openrouter/minimax/minimax-m1
|
||||||
|
api_key: os.environ/OPENROUTER_API_KEY
|
||||||
|
|
||||||
|
- model_name: gpt-oss
|
||||||
|
litellm_params:
|
||||||
|
model: openrouter/openai/gpt-4.1-mini
|
||||||
|
api_key: os.environ/OPENROUTER_API_KEY
|
||||||
|
|
||||||
|
# --- SiliconFlow models ---
|
||||||
|
- model_name: glm-4.7
|
||||||
|
litellm_params:
|
||||||
|
model: openai/THUDM/GLM-4-32B-0414
|
||||||
|
api_base: https://api.siliconflow.cn/v1
|
||||||
|
api_key: os.environ/SILICONFLOW_API_KEY
|
||||||
|
|
||||||
|
- model_name: qwen3-coder
|
||||||
|
litellm_params:
|
||||||
|
model: openai/Qwen/Qwen3-Coder
|
||||||
|
api_base: https://api.siliconflow.cn/v1
|
||||||
|
api_key: os.environ/SILICONFLOW_API_KEY
|
||||||
|
|
||||||
|
# --- DeepInfra models ---
|
||||||
|
- model_name: deepseek-v3.2
|
||||||
|
litellm_params:
|
||||||
|
model: deepinfra/deepseek-ai/DeepSeek-V3-0324
|
||||||
|
api_key: os.environ/DEEPINFRA_API_KEY
|
||||||
|
|
||||||
|
- model_name: devstral-deepinfra
|
||||||
|
litellm_params:
|
||||||
|
model: deepinfra/mistralai/Devstral-Small-2505
|
||||||
|
api_key: os.environ/DEEPINFRA_API_KEY
|
||||||
|
|
||||||
|
# --- Groq (free/fast) ---
|
||||||
|
- model_name: llama-3.3-70b
|
||||||
|
litellm_params:
|
||||||
|
model: groq/llama-3.3-70b-versatile
|
||||||
|
api_key: os.environ/GROQ_API_KEY
|
||||||
|
|
||||||
|
# --- Cerebras (free/fast) ---
|
||||||
|
- model_name: llama-3.3-70b-cerebras
|
||||||
|
litellm_params:
|
||||||
|
model: cerebras/llama-3.3-70b
|
||||||
|
api_key: os.environ/CEREBRAS_API_KEY
|
||||||
|
|
||||||
|
general_settings:
|
||||||
|
master_key: os.environ/LITELLM_MASTER_KEY
|
||||||
|
|
||||||
|
litellm_settings:
|
||||||
|
drop_params: true
|
||||||
|
set_verbose: false
|
||||||
52
searxng/settings.yml
Normal file
52
searxng/settings.yml
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
use_default_settings: true
|
||||||
|
|
||||||
|
general:
|
||||||
|
instance_name: "SearXNG"
|
||||||
|
privacypolicy_url: false
|
||||||
|
donation_url: false
|
||||||
|
enable_metrics: false
|
||||||
|
|
||||||
|
search:
|
||||||
|
safe_search: 0
|
||||||
|
autocomplete: "google"
|
||||||
|
formats:
|
||||||
|
- html
|
||||||
|
- json
|
||||||
|
|
||||||
|
server:
|
||||||
|
secret_key: "${SEARXNG_SECRET_KEY}"
|
||||||
|
limiter: false
|
||||||
|
image_proxy: true
|
||||||
|
public_instance: false
|
||||||
|
|
||||||
|
ui:
|
||||||
|
static_use_hash: true
|
||||||
|
|
||||||
|
engines:
|
||||||
|
- name: google
|
||||||
|
engine: google
|
||||||
|
shortcut: g
|
||||||
|
|
||||||
|
- name: duckduckgo
|
||||||
|
engine: duckduckgo
|
||||||
|
shortcut: ddg
|
||||||
|
|
||||||
|
- name: brave
|
||||||
|
engine: brave
|
||||||
|
shortcut: br
|
||||||
|
|
||||||
|
- name: wikipedia
|
||||||
|
engine: wikipedia
|
||||||
|
shortcut: wp
|
||||||
|
|
||||||
|
- name: github
|
||||||
|
engine: github
|
||||||
|
shortcut: gh
|
||||||
|
|
||||||
|
- name: stackoverflow
|
||||||
|
engine: stackoverflow
|
||||||
|
shortcut: so
|
||||||
|
|
||||||
|
- name: arxiv
|
||||||
|
engine: arxiv
|
||||||
|
shortcut: arx
|
||||||
Loading…
Reference in a new issue