Un 3060 și zero buget de cloud. Modele AI în spatele unui singur endpoint: cinci provideri de cloud cu nivel gratuit, cinci motoare locale care rulează pe hardware-ul tău, restul pe abonamente sau plată la token, ca ultimă soluție.
Nu teoretic. Chiar acum. aigate e un stack de Docker în spatele unui singur port de nginx. Generare de text, generare de imagini, sinteză vocală, transcriere, căutare web, automatizare de browser, object storage, execuție agentică de cod, execuție de cod izolată în sandbox pe mai multe limbaje, un gateway de email, contul tău de Telegram ca tool MCP, forecasting pe serii de timp, producție audio, o trusă video cu lipsync, o coadă de job-uri asincrone și o interfață web. Pe hardware care costă mai puțin decât o singură lună de factură la API-ul OpenAI.
Tot ce e aici e compatibil OpenAI. Îndreaptă orice client spre http://localhost:4000 și merge. Cod existent, SDK-uri existente, unelte existente: toate vorbesc cu el ca și cum ar fi OpenAI. Nu e. E al tău.
Modele, Majoritatea Gratis
Cinci provideri, Groq, OpenRouter, HuggingFace, Mistral, Cohere, au nivel gratuit. Fără card la înscriere. Dar hai să fim cinstiți cu ce înseamnă “gratis”, pentru că paginile de marketing n-au de gând: gratis înseamnă limitat ca rată și plafonat, nu nelimitat. Groq îți dă 30 RPM și undeva între 1K și 14,4K cereri pe zi, în funcție de model. OpenRouter e 50 de cereri pe zi la 0 dolari, 1K pe zi dacă ai băgat vreodată 10 dolari. HuggingFace îți întinde credite de 0,10 dolari pe lună, adică un buget de evaluare, nu un nivel gratuit. Trialul de la Cohere e 1K de apeluri pe lună și se termină repede. Nivelul “Experiment” de la Mistral nu publică deloc limite exacte. Cerebras era pe lista asta. Nu mai e: la ultimul audit fiecare model de acolo răspundea “payment required”, așa că stă în stack ca provider plătit cu trei modele, nu ca nivel gratuit. Asta e cealaltă chestie cu nivelurile gratuite, se retrag, iar un stack construit pe exact unul dintre ele e un stack care se rupe în ziua în care dispare.
Deci nu, nu îți ții firma pe tokeni gratuiți. Dar îți rulezi propriile treburi pe ei, iar când unul seacă îl preia următorul. Ăsta e tot rostul.
Încă trei, claudebox, pibox-zai și pibox, sunt containere de agent. Primele două merg pe abonamente, ceea ce nu e același lucru cu gratis: alocarea tot e contorizată, doar că plătești lunar în loc de per token. Anthropic și OpenAI sunt în stack, dar sunt ultima soluție. Cinci motoare locale rulează pe hardware-ul tău: fără rețea, fără limite de rată, fără niciun cost.
Filosofia de rutare e simplă: nu plăti niciodată un token pe care îl puteai lua gratis.
LiteLLM se ocupă. Ceri groq-llama-3.3-70b. Groq te limitează. LiteLLM cade în tăcere pe cerebras-gpt-oss-120b. Cerebras e picat. Cade pe mistral-small. Mistral răspunde. Primești răspunsul. Clientul n-a aflat niciodată că s-a întâmplat ceva. Fiecare model are un lanț de fallback: întâi cloud gratuit, apoi abonament, apoi plată la token, apoi local. Lanțul se reconstruiește de fiecare dată când pornești stack-ul, filtrat doar pe providerii pe care i-ai activat efectiv.
groq-llama-3.3-70b → 429 rate limited
↓ fallback
cerebras-gpt-oss-120b → 503 unavailable
↓ fallback
mistral-small → 200 ✓N-ai scris logică de retry. N-ai scris logică de fallback. Ai trimis o cerere și ai primit un răspuns.
Arhitectura
nginx :4000 ┌──────────── always on ────────────┐
├─► /claudebox/ → claudebox │ nginx, LiteLLM, PostgreSQL, Redis │
├─► /pibox-zai/ → pibox-zai │ proxq — everything else is opt-in │
├─► /pibox/ → pibox └───────────────────────────────────┘
├─► /stealthy-auto-browse/ → HAProxy → [×5]
├─► /storage/ → hybrids3
├─► /q/ → proxq → LiteLLM (async, returns job ID)
├─► /librechat/ → LibreChat (web UI, LIBRECHAT=1)
├─► /searxng/ → SearXNG (meta-search, SEARXNG=1)
├─► /telethon/ → Telethon (Telegram client, TELETHON=1)
├─► /mailbox/ → mailbox (IMAP+SMTP gateway, MAILBOX=1)
├─► /piston/ → piston (sandboxed code execution, PISTON=1)
├─► /predictalot/ → predictalot (forecasting + tabular ML, PREDICTALOT=1)
├─► /audiolla/ → audiolla (audio production, AUDIOLLA=1)
├─► /flickies/ → flickies (video toolkit, FLICKIES=1)
└─► / → LiteLLM (sync)
├─ Groq (free: 30 RPM, 1K-14.4K RPD per model, GROQ=1)
├─ Cerebras (paid plan, 3 models, CEREBRAS=1)
├─ OpenRouter (free: 50 RPD $0 / 1K RPD with $10+, OPENROUTER=1)
├─ HuggingFace (free: $0.10/mo credits — eval only, HUGGINGFACE=1)
├─ Mistral (free "Experiment" tier, MISTRAL=1)
├─ Cohere (trial: 1K calls/MONTH, COHERE=1)
├─ Ollama (local CPU + CUDA, OLLAMA=1 / OLLAMA_CUDA=1)
├─ Talkies (local ASR + TTS, TALKIES=1 / TALKIES_CUDA=1)
├─ sd.cpp (local image gen, SDCPP=1 / SDCPP_CUDA=1)
├─ vLLM (local text LLM + embeddings, VLLM=1 / VLLM_CUDA=1)
├─ llama.cpp (local GGUF + vision-VLM, LLAMACPP=1 / LLAMACPP_CUDA=1)
├─ claudebox (subscription, CLAUDEBOX=1)
├─ pibox-zai (subscription, PIBOX_ZAI=1)
├─ pibox (points back at this stack's LiteLLM, PIBOX=1)
├─ Anthropic (pay-per-token, ANTHROPIC=1)
└─ OpenAI (pay-per-token, OPENAI=1)
MCP servers (all optional):
├─ stealthy_auto_browse — run_script: multi-step browser automation (BROWSER=1)
├─ hybrids3 — upload, download, list, delete, presign (HYBRIDS3=1)
├─ claudebox — agentic Claude Code via OAuth or API key (CLAUDEBOX=1)
├─ pibox_zai — agentic pi-coding-agent via z.ai/GLM (PIBOX_ZAI=1)
├─ pibox — agentic pi-coding-agent on your own models (PIBOX=1)
├─ telethon — your Telegram account as a tool (TELETHON=1)
├─ mailbox — IMAP+SMTP across N accounts (MAILBOX=1)
├─ predictalot — time-series forecasting (PREDICTALOT=1)
├─ audiolla — audio production, MIR, mastering, MIDI (AUDIOLLA=1)
├─ flickies — lipsync, face restore, ffmpeg ops (FLICKIES=1)
└─ mcp_tools — generate_image + generate_tts + search_web
+ execute_code (auto-enabled)Totul e opt-in. Comuți flag-uri în .env. N-ai cheie de Anthropic? N-o seta. Ai doar CPU? Sari peste flag-urile de CUDA. Stack-ul se adaptează la ce ai și își reconstruiește configul în consecință. Nucleul mereu pornit e format din cinci lucruri: nginx, LiteLLM, PostgreSQL, Redis, proxq. Restul e flag.
Unelte Pe Care Le Poate Chema Orice Model
Asta e ce face din aigate mai mult decât un proxy cu lanț de fallback. Un morman întreg de servere MCP, zeci de unelte. Orice model cu function calling poate să le cheme singur pe oricare. Tu dai promptul. Modelul decide de ce unelte are nevoie. Tu primești rezultate.
Fluxul concret: trimiți un prompt la Groq, gratis, rapid. Modelul decide că trebuie să documenteze ceva. Cheamă search_web, SearXNG interoghează Google, Bing și DuckDuckGo simultan și întoarce rezultate. Modelul are nevoie de mai multe detalii pe un rezultat. Cheamă tool-ul de browser. O instanță de Camoufox deschide un Firefox adevărat, mișcă un cursor de mouse adevărat, încarcă pagina, extrage conținutul. Modelul citește, decide să salveze rezultatul. Cheamă tool-ul de storage. hybrids3 scrie fișierul și întoarce un URL public. Modelul decide că îi trebuie o imagine pentru raport. Cheamă generate_image. stable-diffusion.cpp o randează local, o urcă în storage, întoarce un URL. Modelul îți dă un răspuns structurat cu linkuri către tot ce a produs. Un singur apel de API. Zero tokeni plătiți. Clientul a văzut o cerere și un răspuns.
stealthy_auto_browse
Cinci replici de Camoufox în spatele unui HAProxy. Camoufox e un Firefox întărit: input real de mouse și tastatură la nivel de sistem prin PyAutoGUI, zero expunere CDP, amprente persistente per sesiune. Trece de Cloudflare. Trece de CreepJS. Trece de BrowserScan. Trece de Pixelscan. Nu “trece în mare parte”, chiar trece, pentru că nu e detectabil ca automatizare în felurile în care verifică sistemele alea.
O singură unealtă: run_script. Scripturi în mai mulți pași: navighează, dă click, tastează, extrage, face screenshot, derulează, așteaptă elemente, execută JavaScript. Modelul scrie scriptul, browserul îl execută, tu primești înapoi date structurate din pagina vie.
hybrids3
Object storage compatibil S3 care rulează local. Bucket-ul uploads e public-read: fișierele sunt accesibile direct prin URL, fără semnătură. URL-uri PUT presemnate pentru upload direct. Expirare automată. Unelte pentru put, get, list, delete, info, presign și listare de bucket-uri.
Asta rezolvă o problemă anume din fluxurile agentice. Când un model produce ceva mare, un set de date scrapuit, o imagine generată, un raport randat, nu îl îndeși în fereastra de context. Îl pui în storage, iei un URL, pasezi URL-ul. Pasul următor îl poate lua de acolo. Tu îl poți lua de acolo. Contextul rămâne curat.
Trei Agenți de Cod: claudebox, pibox-zai și pibox
Trei agenți de cod agentici diferiți, nu trei copii ale aceluiași. claudebox rulează Claude Code pe abonamentul sau cheia ta de API. pibox-zai rulează pi-coding-agent îndreptat spre z.ai pentru modelele GLM (glm-5.3 și glm-5.3-flash). pibox e același agent îndreptat înapoi spre LiteLLM-ul stack-ului ăstuia, deci scrie cod pe orice ai activat deja: numești modelele cu PIBOX_MODELS, alegi unul implicit cu PIBOX_DEFAULT_MODEL. Două avertismente acolo, și mușcă amândouă: un model pe care îl treci în listă chiar trebuie să suporte tool calling, altfel agentul n-are ce să conducă, și nu îi da unui agent propriul model înapoi în listă decât dacă îți place recursivitatea. Toți trei primesc acces complet la shell, workspace-uri persistente, I/O pe fișiere, tool use, și toți trei expun un API REST, un endpoint compatibil OpenAI și un server MCP.
Folosești Groq pentru viteză. Groq dă peste ceva care cere muncă serioasă de cod. Groq cheamă tool-ul claudebox. Claude Code preia, primește un shell, scrie cod, rulează teste, întoarce rezultate structurate. Înapoi în contextul lui Groq. Orchestrarea se întâmplă în bucla de function calling a modelului, iar tu n-ai scris nimic din logica aia.
piston: Execuție de Cod în Sandbox
LLM-urile sunt catastrofal de proaste la aritmetică, la hashuri și la parsat. Deci nu le pune să ghicească. execute_code rulează cod adevărat într-un sandbox nsjail, cu propriul user namespace, chroot, filtru seccomp, limite de cgroup și fără rețea, și îi întinde modelului un rezultat determinist.
Instalarea implicită e Python plus Node. Adaugi Bash, Deno, Go, Rust, TypeScript sau alte vreo 40 de limbaje prin PISTON_LANGUAGES și reconstruiești. Modelului îi trebuie un SHA-256, o diferență de date, un regex aplicat pe 10K de rânduri? Scrie cod, piston îl rulează în carceră, iar cifra vine înapoi corectă în loc de halucinată.
mcp_tools
generate_image, generate_tts, search_web și execute_code. Se activează automat când backendul potrivit e pornit. Toate întorc JSON structurat, iar fișierele generate se urcă automat în hybrids3 cu URL-uri persistente. Fără bucăți de base64 în fereastra de context.
Generarea de imagini se duce pe FLUX, DALL-E sau stable-diffusion.cpp, în funcție de ce e activat. TTS-ul se duce pe Kokoro (CPU plus CUDA), Qwen3-TTS cu clonare de voce, design de voce și control al emoției (CUDA), sau OpenAI TTS. Căutarea web interoghează SearXNG. Execuția de cod se duce la piston. Uneltele descoperă dinamic din LiteLLM ce modele sunt disponibile, deci reflectă mereu ce rulează de fapt.
telethon
Contul tău real de Telegram, ca unealtă. Nu Bot API, ci MTProto complet, exact accesul pe care îl ai de pe telefon. Citește mesaje, trimite mesaje, listează conversații, administrează grupuri, redirecționează conținut, editează, șterge, marchează ca citit, trimite fișiere. Modelul decide când. Agentul se poartă ca tine.
Un model Groq de nivel gratuit care caută pe web, scrapuiește o pagină, generează o imagine și trimite rezultatul în Mesajele tale salvate: zero tokeni plătiți, o conversație, mai multe apeluri de unelte. Sau un cron care îți rezumă ultimele 24 de ore din grupul de muncă și ți-l dă pe privat în fiecare dimineață. Contul tău, programabil.
Pus la treabă de telethon-plus. Comuți TELETHON=1, setezi TELETHON_API_ID / TELETHON_API_HASH / TELETHON_SESSION în .env. Stringul de sesiune înseamnă acces complet la cont, deci tratează-l ca parola care de fapt și este.
mailbox: Emailul Ca Unealtă
IMAP plus SMTP fără stare, pe N conturi, dintr-un singur config YAML. Inbox unificat, listare/căutare/CRUD per cont, trimitere pe SMTP. API REST plus un set plat de unelte MCP unde un parametru mailbox alege contul.
Ceea ce înseamnă că un model îți poate citi inboxul, poate găsi factura, îi poate extrage totalul și poate răspunde, fără să scrii tu o linie de manevrat IMAP. MAILBOX=1, îndrepți MAILBOX_CONFIG spre YAML-ul tău, gata.
predictalot: Forecasting și ML Tabular
Cinci modele fundaționale zero-shot pentru serii de timp, chronos-2, timesfm-2.5, moirai-2, toto-1, sundial-base-128m, pe șase tipuri de forecast (univariat, multivariat, covariate din trecut, covariate din viitor, sample-uri și ansambluri ponderate per tip) la /v1/timeseries/<type>/….
Apoi o familie soră întreagă la /v1/tabular/*: nouă backenduri supervizate (lightgbm, xgboost, hist-gbt, random-forest, logistic, mlp, svm-rbf, knn, naive-bayes) și trei meta-learneri (calibrated, stacking, diversified). 26 de unelte MCP acoperă modelele fundaționale; partea tabulară e doar pe REST. CPU sau CUDA.
Zero-shot înseamnă fără rulare de antrenare. Îi întinzi o serie, îți dă forecastul. Atât.
audiolla: Producție Audio
Ăsta e absurd ca întindere. Separare de stem-uri (Demucs / UVR). Restaurare: de-reverb, de-echo, de-noise. Masterizare prin matchering și lanțuri pedalboard, cu presetări făcute de mână ca master-for-spotify, podcast-cleanup, vocal-cleanup. Analiză MIR: BPM, tonalitate, LUFS, bătăi, onset-uri, melodie, acorduri, segmente. Transformări DSP prin sox și ffmpeg. Normalizare de loudness. Îmbunătățire de voce (DeepFilterNet). VAD (silero). Diarizare (pyannote). Embeddinguri CLAP și clasificare audio zero-shot. Etichetare AudioSet. Audio→MIDI prin basic-pitch, plus compunere / inspectare / transformare / randare de MIDI prin fluidsynth.
Plus generare text-to-audio, stable-audio-open, musicgen, riffusion, audioldm2, doar pe CUDA.
Job-uri asincrone și webhook-uri peste tot. Contractul de la v1.0 încolo e strict: body JSON pe fiecare endpoint audio, octeți bruți doar la PUT /v1/files/{path}, și output_path xor output_url obligatoriu pe orice produce audio.
flickies: Video și Lipsync
Lipsync prin LatentSync 1.5 (ByteDance, Apache-2.0, ~8 GB VRAM, implicit pe CUDA) și Wav2Lip / Wav2Lip-GAN (LRS2, necomercial, cu acces restricționat). Restaurare de fețe prin GFPGAN v1.4. Operații ffmpeg: trim, concat, transcodare inclusiv schimbări de gif/fps/codec, scalare, mux de audio, extragere de audio, grilă de thumbnail-uri. Info ffprobe. Job-uri asincrone și webhook-uri. 11 unelte MCP, același contract cu body JSON și output_path xor output_url ca la audiolla.
GFPGAN și LatentSync 1.5 merg doar pe CUDA. Imaginea de CPU tot face operații ffmpeg și un Wav2Lip foarte lent.
Inferență Locală: Mai Lentă, Dar A Ta
Cinci motoare locale. Fiecare dintre ele are mod de CPU.
Asta e partea de “calculatorul săracului”. Laptopul tău vechi cu 16GB de RAM poate să facă generare de text, generare de imagini, transcriere și sinteză vocală. Fără cheie de API. Fără rețea. Fără limită de rată. Fără factură. E mai lent decât cloudul. Uneori mult mai lent. Dar e al tău, e privat și merge offline.
Ollama: llama3.2:3b, qwen3:4b, smollm2:1.7b, qwen2.5-coder:1.5b, qwen2.5-coder:3b, phi4-mini (raționament, context de 128K), gemma4:e2b (vedere), gemma3:4b (vedere), nuextract-v1.5 (extragere de text structurat în JSON), dolphin-phi, plus două modele de embedding pentru RAG. Celui mai mic îi trebuie 1GB de RAM. OLLAMA_CUDA=1 adaugă setul greu: qwen3:8b, gemma4:e4b (vedere), deepseek-coder-v2:16b (MoE, context de 160K), deepseek-r1:8b (raționament), qwen3-abliterated:16b (necenzurat), gemma4-abliterated:e4b (vedere necenzurată), qwen2.5-coder:7b, llama3.1:8b. Flash attention, cache KV cuantizat, storage de modele partajat cu serviciul de CPU, deci fără descărcări duble.
talkies: serviciul unificat de ASR plus TTS și înlocuitorul a ceea ce era Speaches în stack-ul ăsta. Pe CPU vine acum cu 13 modele: whisper-large-v3 și -turbo, canary-180m-flash, nemotron-3.5-asr-0.6b, patru variante Sherpa-ONNX Zipformer, Vosk small English și două recunoscătoare de foneme care îți dau un flux brut de foneme IPA cu timestamp per fonem în loc de cuvinte; Kokoro pentru TTS. Pe CUDA se ajunge la 22, adăugând parakeet-tdt-0.6b-v3, canary-1b-flash, canary-qwen-2.5b, Chatterbox Turbo și familia Qwen3-TTS, 0.6B și 1.7B, cu clonare de voce, design de voce și control al emoției prin câmpul instructions. Chatterbox e singurul dintre ele care își marchează ieșirea: watermarkul neural PerTh de la ResembleAI, pornit implicit, iar TALKIES_CHATTERBOX_WATERMARK=false îl oprește pentru audio curat, în timp ce Kokoro și Qwen3-TTS nu încorporează niciodată nimic. Endpointuri compatibile OpenAI, deci apelurile existente de Whisper merg nemodificate. TALKIES=1 / TALKIES_CUDA=1.
Adăugările Sherpa și Vosk aterizează ca zece aliasuri noi de transcriere: cele cinci modele sub local-talkies-, apoi aceleași cinci din nou sub local-talkies-cuda-. Build-urile int8 sunt cuantizate (mai mici și mai rapide, cu acuratețe puțin mai mică); left-64 față de left-128 setează fereastra de context stâng a atenției. Toate cinci fac ASR live nativ peste WebSocket-ul de streaming, pe lângă obișnuitul POST /v1/audio/transcriptions, iar imaginea de CUDA instalează un wheel Sherpa CUDA din upstream verificat prin hash, ca să folosească efectiv execution providerul lui de CUDA în loc să cadă în tăcere pe CPU într-un container cu GPU.
O subtilitate de fallback care merită furată: șase lanțuri din fallbacks.json listau înainte un model talkies frate pe prima poziție, whisper-large-v3 → whisper-large-v3-turbo, plus echivalentele pentru varianta de CUDA și pentru ambele intrări de TTS. Așa ceva nu poate funcționa niciodată. Fiecare container talkies servește un singur model odată și îl evacuează pe cel anterior la admitere, așa că un salt către un frate nu găsește capacitate liberă, ci forțează o schimbare de model, iar sub retry-uri asta e doar evacuare în buclă. Lanțurile se duc acum întâi spre celălalt container talkies, apoi afară spre providerii din cloud. Salturile CPU↔CUDA rămân, pentru că alea chiar sunt procese independente.
stable-diffusion.cpp: generare locală de imagini. Pe CPU merge sd-turbo și sdxl-turbo din start. SDCPP_CUDA=1 pentru accelerare hardware și setul complet de modele: sd-turbo, sdxl-turbo, sdxl-lightning, flux-schnell, juggernaut-xi. Modelele se descarcă la prima folosire și se cachează local. Endpointul compatibil OpenAI /images/generations înseamnă că din codul existent merge ca atare.
vLLM: LLM-uri locale de text plus embeddinguri. qwen3-0.6b pentru generare, nomic-embed-v2 pentru embeddinguri. VLLM=1 / VLLM_CUDA=1.
llama.cpp: modele GGUF și VLM-uri de vedere, inclusiv Surya OCR 2 pentru înțelegerea documentelor. LLAMACPP=1 / LLAMACPP_CUDA=1.
Modelele locale stau implicit la coada lanțului de fallback. Cade cloudul? Preia localul. Sau le țintești direct: "model": "local-ollama-cpu-llama3.2-3b". Zero rețea. Zero cost. Mai lent, dar răspunde.
Un Singur GPU, Tot
Uite problema de inginerie: ai un singur GPU. Ollama vrea VRAM pentru LLM. sd.cpp vrea VRAM pentru generare de imagini. talkies vrea VRAM pentru transcriere și voce. audiolla îl vrea pentru separare de stem-uri. flickies vrea vreo 8GB din el pentru LatentSync. Le încarci pe toate și dai în OOM.
Managerul de resurse rezolvă asta automat. Un callback de LiteLLM impune excludere mutuală per hardware: un singur job CUDA odată. Când vine o cerere de generare de imagini în timp ce e încărcat un LLM, managerul de resurse ia semaforul, descarcă LLM-ul, apoi lasă generarea de imagini să meargă mai departe. Când vine după aia o cerere de TTS, descarcă întâi generatorul de imagini. Aceeași logică și pe CPU.
Fiecare serviciu are propriul API de descărcare, iar managerul de resurse le știe pe toate: Ollama ia keep_alive: 0, sd.cpp are POST /sdcpp/v1/unload, talkies / vllm-cuda / llamacpp-cuda iau DELETE /api/ps/{model_id} per model sau POST /unload ca să omoare orice e încărcat, iar audiolla are POST /v1/unload ca să evacueze în bloc orice motor încărcat.
Există și endpointuri pentru operator, când vrei să faci curat manual: POST /v1/unload/cuda se împrăștie concurent spre ollama-cuda, sdcpp-cuda, talkies-cuda, vllm-cuda, llamacpp-cuda, audiolla-cuda și flickies-cuda. POST /v1/unload/cpu face același lucru pentru aceleași șapte pe partea de CPU. POST /v1/unload le rulează pe amândouă în ordine și îți dă înapoi un raport pe servicii cu ce a fost evacuat efectiv.
Tu nu administrezi nimic din asta. Trimiți cereri. Platforma jonglează cu VRAM-ul automat. Singurul cost e latența: prima cerere de după o schimbare include timpul de încărcare a modelului. După aia e rapid, până când timeoutul de inactivitate descarcă modelul ca să elibereze memorie pentru următorul lucru.
Căutare Web
SearXNG la /searxng/. Meta-căutare self-hosted: interoghează Google, Bing, DuckDuckGo și Wikipedia simultan. Fără cheie de API. Rulează complet local.
Repară-ți secret_key dacă ai pus asta în funcțiune devreme. Cea de la SearXNG era hardcodată în searxng/settings.yml, care era în repo. Acum se generează per instalare și se citește din SEARXNG_SECRET_KEY în .env: setează-o cu openssl rand -hex 32 când comuți SEARXNG=1, altfel SearXNG pornește pe placeholderul din upstream. Fișierul settings.yml din repo a dispărut de tot; setările se randează dintr-o intrare searxng_config din blocul configs:, la fel cum proxq_config lua deja ${REDIS_PASSWORD}. Expunerea era limitată, /searxng/ stă în spatele autentificării de admin din nginx, containerul nu publică porturi pe host, iar limiter: false însemna că cheia nu păzea limitele de rată, dar valoarea veche tot stă în istoricul de git, și partea aia nu se mai des-întâmplă.
Unealta MCP search_web înseamnă că orice model cu function calling poate căuta singur pe web. Modelul decide că trebuie să verifice ceva, cheamă unealta, primește rezultate, merge mai departe cu raționamentul. N-ai construit o integrare de căutare. Ai comutat SEARXNG=1.
LibreChat: Ăla de Zi cu Zi
Tot ce e mai sus merge din API. Dar pentru uz zilnic ai LibreChat la /librechat/.
Toate modelele în dropdown. Toate uneltele MCP legate. Alegi un model, începi să vorbești. Modelul tot poate să cheme singur browserul, storage-ul, agenții de cod, generarea de imagini, TTS-ul și căutarea web: tot ce e disponibil din API e disponibil și în interfață. Istoricul conversațiilor stă pe MongoDB. Upload de fișiere. Streaming pe WebSocket.
Primul utilizator înregistrat devine admin. Setezi LIBRECHAT_ALLOW_REGISTRATION=false după aia și rămâi singurul dinăuntru.
Îl activezi: LIBRECHAT=1 în .env.
Coadă Asincronă
Cererile lungi de inferență dau timeout. Lovești /q/ în loc de / și cererea intră într-o coadă pe Redis. Primești instant un ID de job. Inferența propriu-zisă rulează în fundal. Interoghezi statusul, iei rezultatul când e gata.
# submit — returns 202 immediately
curl http://localhost:4000/q/v1/chat/completions
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "cerebras-gpt-oss-120b", "messages": [{"role":"user","content":"write a novel"}]}'
# → {"jobId": "550e8400-e29b-41d4-a716-446655440000"}
# check status
curl http://localhost:4000/q/__jobs/550e8400-e29b-41d4-a716-446655440000
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
# get the result
curl http://localhost:4000/q/__jobs/550e8400-e29b-41d4-a716-446655440000/content
-H "Authorization: Bearer $LITELLM_MASTER_KEY"Concurență, retenție, timeouturi, retry-uri și cache de răspunsuri, toate configurabile. Doar căile de API OpenAI intră în coadă; verificările de sănătate și cererile de admin trec direct.
Vine cu Propriul Lui Agent Skill
Repo-ul cară .agents/skills/aigate/, un agent skill publicat pe ClawHub care învață un agent de cod cum să conducă stack-ul. Deci în loc să îi explici propria ta infrastructură unui asistent în fiecare sesiune, instalezi skill-ul și el știe deja endpointurile, flag-urile și contractele uneltelor.
Securitate
Serviciile interne, PostgreSQL, MongoDB, Redis, clusterul de browsere, backendul de storage, n-au porturi pe host. Stau pe rețele Docker izolate. Nimic nu ajunge la ele din afara stack-ului. Singura suprafață expusă e nginx pe portul 4000, iar aia cere autentificare cu bearer token.
Containerele de aplicație rulează cu no-new-privileges:true. Două excepții, ambele intenționate și ambele documentate în fișierul de compose: piston are nevoie de privileged: true pentru că nsjail trebuie să construiască user namespace-uri și chroot-uri la fiecare execuție, izolarea propriu-zisă stă înăuntrul subprocesului nsjail, iar containerul privilegiat e exact ce îi trebuie lui nsjail ca să ridice carcera aia. tailscale are nevoie de NET_ADMIN pentru dispozitivul lui tun din userspace. Tot restul renunță la privilegii. make run validează că orice cale de fișier din .env chiar există înainte să pornească, deci fără volume mount-uri rupte în tăcere.
Îl vrei accesibil public fără să deschizi un port în firewall? CLOUDFLARED=1, adică Cloudflare Tunnel. Protecție DDoS, terminare TLS, fără porturi deschise, fără IP de scanat. Tunel rapid pentru un URL aleatoriu *.trycloudflare.com, sau tunel cu nume pentru un domeniu fix.
Nu îl vrei public deloc, dar tot vrei să ajungi la el de pe laptop, de pe telefon sau de pe altă mașină? TAILSCALE=1 cu TS_AUTHKEY=tskey-auth-... și un TS_HOSTNAME. Un sidecar de Tailscale intră în tailnetul tău și rulează tailscale serve în mod de forwarding TCP L4 direct spre nginx:4000: fără potrivire pe Host header, fără configurare de FQDN pe partea de tailscale, fără auto-certificat HTTPS (terminarea TLS, dacă o vrei, stă în nginx). nginx primește octeții cererii originale ca atare și îi rutează prin logica lui existentă de vhost și cale. Acces prin http://<TS_HOSTNAME>.<tailnet>.ts.net, iar HTTP simplu e în regulă aici, pentru că WireGuard deja criptează fiecare octet din tailnet. Merge cu Tailscale găzduit sau cu Headscale self-hosted (folosești TS_EXTRA_ARGS=--login-server=...). Starea persistă în .data/tailscale/, deci repornirile refolosesc loginul existent. Combină-l cu autentificarea pe bearer token și ai două straturi complet independente de control al accesului.
Ăsta e traficul care intră. Traficul care iese e altă treabă, pe care acum o poți porni: egress prin tailnet pentru agenții de cod, ca să poată claudebox, pibox-zai și pibox să ajungă la mașini din tailnetul tău, nu doar la internetul public. Vine ca un overlay de compose (docker-compose.tailscale.yml) și mai cere două valori, TS_MAGICDNS_SUFFIX (sufixul MagicDNS al tailnetului tău, direct din tailscale status) și TS_FALLBACK_DNS (implicit 1.1.1.1). A doua există pentru că DNS-ul ajunge împărțit: MagicDNS răspunde pentru numele din tailnet și dă SERVFAIL pentru tot restul, deci numelor publice le trebuie un resolver pe care să cadă mai departe.
Sute de teste. Verificări de sănătate, rutare, autentificare, validare de unelte MCP, CRUD pe storage, automatizare de browser, rulări agentice de cod, ciclul de viață al job-urilor asincrone, dus-întors de TTS/STT local, verificarea managerului de resurse CUDA, generare locală de imagini, tool calling cap-coadă de la LLM la MCP, căutare pe SearXNG, dus-întors MTProto pe Telethon cu un cont real. Plus securitate: izolare între tokenuri, încercări de deturnare de sesiune, HTTP request smuggling (CL.TE/TE.CL), h2c smuggling, SSRF prin browser și prin MCP spre servicii interne, extragere de chei prin prompt injection, path traversal, abuz de presign pe S3, XSS stocat, injecție de nume de model, injecție de headere, izolarea socketului de Docker. Asta nu e suita de teste a unui proiect de hobby. Asta e paranoia ca funcționalitate.
Instalare
git clone https://github.com/psyb0t/aigate && cd aigate
make bootstrap # seeds .env; then edit it: add keys, flip flags
make run-bgFiecare variabilă e documentată în .env.example. Activează ce ai, ignoră ce n-ai. Nici nu mai trebuie să copiezi fișierul ăla de mână: make bootstrap îți seamănă .env, iar orice alt target îl seamănă întâi, deci make run pe un checkout proaspăt pur și simplu merge.
Când vrei să schimbi ceva la stack-ul în sine, nu doar un flag, pui în docker-compose.override.yml. Asta e cusătura suportată acum: Makefile-ul asamblează COMPOSE_FILE din fișierul de bază, overlay-ul de tailscale când l-ai activat, și overrideul tău la final. Editezi direct fișierul de compose de bază și următorul update îți mănâncă modificările; overrideul supraviețuiește.
Dacă resursele contează, și pe un calculator normal chiar contează, make limits îți citește RAM-ul și CPU-ul disponibil și scrie limite recomandate pentru fiecare serviciu. MAXUSE=80 make limits plafonează tot stack-ul la 80% din resursele sistemului dacă împarți mașina cu alte treburi. Serviciile CUDA știu de managerul de resurse, deci bugetul socotește cel mai mare dintre ele, nu fiecare serviciu de GPU la alocare maximă simultan.
# free tier, auto-fallback
curl http://localhost:4000/chat/completions
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "cerebras-gpt-oss-120b", "messages": [{"role":"user","content":"hello"}]}'
# local, no network, no limits
curl http://localhost:4000/chat/completions
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "local-ollama-cpu-llama3.2-3b", "messages": [{"role":"user","content":"hello"}]}'
# image generation
curl http://localhost:4000/images/generations
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "hf-flux-schnell", "prompt": "a cat riding a skateboard"}'
# local image generation (no network, no cost)
curl http://localhost:4000/images/generations
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "local-sdcpp-cpu-sd-turbo", "prompt": "a red panda in a forest", "size": "512x512"}'
# transcription (local, CPU)
curl http://localhost:4000/audio/transcriptions
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-F "model=local-talkies-whisper-large-v3-turbo" -F "[email protected]"
# text-to-speech (local, multiple voices)
curl http://localhost:4000/audio/speech
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "local-talkies-kokoro-tts", "input": "Hello world", "voice": "af_heart"}'
-o speech.mp3
# web search (no API key, self-hosted)
curl http://localhost:4000/chat/completions
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "groq-qwen3-32b", "messages": [{"role":"user","content":"search the web for latest rust release notes"}]}'
# async — submit and poll
curl http://localhost:4000/q/v1/chat/completions
-H "Authorization: Bearer $LITELLM_MASTER_KEY"
-d '{"model": "cerebras-gpt-oss-120b", "messages": [{"role":"user","content":"write a novel"}]}'Cinci provideri cu nivel gratuit, cinci motoare locale, restul ca fallback. Mai lent pe un calculator normal, dar merge, e privat și nu te poate da nimeni afară din propria ta infrastructură cu o limită de rată.
github.com/psyb0t/aigate
Cum Îl Instalezi în Agentul Tău
Skill-ul ăla nu mai e doar pentru OpenClaw. Tot ce e sub .agents/ e catalogat într-un singur marketplace, deci sunt două comenzi:
claude plugin marketplace add psyb0t/agents
claude plugin install aigate@psyb0tCodex folosește același marketplace cu alt verb, codex plugin add aigate@psyb0t, pentru că nu există codex plugin install. Îl mai și găsește singur într-un checkout al repo-ului, pentru că scanează nativ .agents/skills/ fără să fie instalat absolut nimic.