Add LICENSE, update docs with Anthropic endpoint and free-claude-code attribution

This commit is contained in:
Oliver Hofmann 2026-05-10 09:53:12 +02:00
parent cc3ee5a03c
commit 9872175fb0
4 changed files with 105 additions and 17 deletions

View File

@ -1,10 +1,11 @@
# mediaeng/llmproxy
A lightweight reverse proxy for [Ollama](https://ollama.com) that manages API keys with configurable token and request quotas. Incoming requests in OpenAI-compatible format are authenticated, checked against the quota, and forwarded to the configured Ollama server.
A lightweight reverse proxy for [Ollama](https://ollama.com) that manages API keys with configurable token and request quotas. Incoming requests in OpenAI-compatible or Anthropic-compatible format are authenticated, checked against the quota, and forwarded to the configured Ollama server.
## Features
- OpenAI-compatible endpoint (`/v1/chat/completions`, `/v1/models`)
- **Anthropic Messages API** (`/v1/messages`) — compatible with Claude Code CLI and Anthropic SDK clients
- API key management with daily and monthly token/request limits
- Web-based admin interface (port 8001)
- Model lock: enforces a specific model for all requests (useful for courses and lab sessions)
@ -17,7 +18,7 @@ A lightweight reverse proxy for [Ollama](https://ollama.com) that manages API ke
| Port | Service |
|------|---------|
| `8000` | Proxy endpoint (OpenAI API) |
| `8000` | Proxy endpoint (OpenAI and Anthropic API) |
| `8001` | Admin API + web interface |
All API endpoints require the `ADMIN_PASSWORD` — without a valid token, only the public frontend files (HTML/JS/CSS of the login page) are accessible. The password is therefore the primary protection.
@ -35,6 +36,8 @@ All API endpoints require the `ADMIN_PASSWORD` — without a valid token, only t
| `ADMIN_PORT` | `8001` | Admin API port |
| `APP_TZ` | `Europe/Berlin` | Timezone for daily/monthly quota resets |
| `LOG_FILE` | `logs/usage.log` | Path of the rotating usage log file |
| `ANTHROPIC_DEFAULT_MODEL` | | Default model for `/v1/messages` (Ollama model name, e.g. `llama3`) |
| `BACKEND_API_KEY` | | API key for an upstream proxy (forwarded to the backend) |
## Docker Compose Ollama on the Host (Linux, recommended)
@ -60,6 +63,7 @@ volumes:
ADMIN_PASSWORD=changeme
OLLAMA_URL=http://localhost:11434
APP_TZ=Europe/Berlin
ANTHROPIC_DEFAULT_MODEL=llama3
```
## Docker Compose Ollama as Container, SQLite
@ -77,8 +81,8 @@ services:
environment:
ADMIN_PASSWORD: changeme
OLLAMA_URL: http://ollama:11434
APP_TZ: Europe/Berlin
ANTHROPIC_DEFAULT_MODEL: llama3
volumes:
- llmproxy-data:/app/backend
depends_on:
@ -110,9 +114,9 @@ services:
environment:
ADMIN_PASSWORD: changeme
OLLAMA_URL: http://ollama:11434
APP_TZ: Europe/Berlin
DATABASE_URL: postgresql://llmproxy:secret@db:5432/llmproxy
ANTHROPIC_DEFAULT_MODEL: llama3
depends_on:
db:
condition: service_healthy
@ -147,9 +151,19 @@ volumes:
## Client Configuration
Configure the proxy as an OpenAI-compatible endpoint:
**OpenAI-compatible client:**
```
Base URL: http://<host>:8000/v1
API Key: <API key created in the admin interface>
```
**Claude Code CLI:**
```bash
ANTHROPIC_BASE_URL=http://<host>:8000 \
ANTHROPIC_AUTH_TOKEN=<API key> \
claude
```
## Acknowledgements
The Anthropic Messages API endpoint (`/v1/messages`) was inspired by [free-claude-code](https://github.com/Alishahryar1/free-claude-code) by Ali Khokhar, which pursues a similar approach for routing Claude Code requests to alternative LLM backends.

View File

@ -1,10 +1,11 @@
# mediaeng/llmproxy
Ein schlanker Reverse-Proxy für [Ollama](https://ollama.com), der API-Keys mit konfigurierbaren Token- und Request-Quoten verwaltet. Eingehende Anfragen im OpenAI-kompatiblen Format werden authentifiziert, auf Quota geprüft und an den konfigurierten Ollama-Server weitergeleitet.
Ein schlanker Reverse-Proxy für [Ollama](https://ollama.com), der API-Keys mit konfigurierbaren Token- und Request-Quoten verwaltet. Eingehende Anfragen im OpenAI-kompatiblen oder Anthropic-kompatiblen Format werden authentifiziert, auf Quota geprüft und an den konfigurierten Ollama-Server weitergeleitet.
## Funktionen
- OpenAI-kompatibler Endpunkt (`/v1/chat/completions`, `/v1/models`)
- **Anthropic Messages API** (`/v1/messages`) — kompatibel mit Claude Code CLI und Anthropic-SDK-Clients
- API-Key-Verwaltung mit tages- und monatlichen Token-/Request-Limits
- Web-basierte Admin-Oberfläche (Port 8001)
- Modell-Lock: erzwingt ein bestimmtes Modell für alle Requests (nützlich für Praktika/Kurse)
@ -17,7 +18,7 @@ Ein schlanker Reverse-Proxy für [Ollama](https://ollama.com), der API-Keys mit
| Port | Dienst |
|------|--------|
| `8000` | Proxy-Endpunkt (OpenAI-API) |
| `8000` | Proxy-Endpunkt (OpenAI- und Anthropic-API) |
| `8001` | Admin-API + Web-Oberfläche |
Alle API-Endpunkte erfordern das `ADMIN_PASSWORD` — ein Zugriff ohne gültiges Token liefert nur die öffentlichen Frontend-Dateien (HTML/JS/CSS der Login-Seite). Das Passwort ist damit die primäre Schutzmaßnahme.
@ -35,6 +36,8 @@ Alle API-Endpunkte erfordern das `ADMIN_PASSWORD` — ein Zugriff ohne gültiges
| `ADMIN_PORT` | `8001` | Port der Admin-API |
| `APP_TZ` | `Europe/Berlin` | Zeitzone für Tages-/Monats-Reset der Quoten |
| `LOG_FILE` | `logs/usage.log` | Pfad der rotierenden Nutzungs-Logdatei |
| `ANTHROPIC_DEFAULT_MODEL` | | Standard-Modell für `/v1/messages` (Ollama-Modellname, z. B. `llama3`) |
| `BACKEND_API_KEY` | | API-Key für einen vorgelagerten Proxy (wird an das Backend weitergereicht) |
## Docker Compose Ollama auf dem Host (Linux, empfohlen)
@ -60,6 +63,7 @@ volumes:
ADMIN_PASSWORD=changeme
OLLAMA_URL=http://localhost:11434
APP_TZ=Europe/Berlin
ANTHROPIC_DEFAULT_MODEL=llama3
```
## Docker Compose Ollama als Container, SQLite
@ -77,8 +81,8 @@ services:
environment:
ADMIN_PASSWORD: changeme
OLLAMA_URL: http://ollama:11434
APP_TZ: Europe/Berlin
ANTHROPIC_DEFAULT_MODEL: llama3
volumes:
- llmproxy-data:/app/backend
depends_on:
@ -110,9 +114,9 @@ services:
environment:
ADMIN_PASSWORD: changeme
OLLAMA_URL: http://ollama:11434
APP_TZ: Europe/Berlin
DATABASE_URL: postgresql://llmproxy:secret@db:5432/llmproxy
ANTHROPIC_DEFAULT_MODEL: llama3
depends_on:
db:
condition: service_healthy
@ -147,9 +151,15 @@ volumes:
## Client-Konfiguration
Den Proxy als OpenAI-kompatibler Endpunkt konfigurieren:
**OpenAI-kompatibler Client:**
```
Base URL: http://<host>:8000/v1
API Key: <angelegter API-Key aus der Admin-Oberfläche>
```
**Claude Code CLI:**
```bash
ANTHROPIC_BASE_URL=http://<host>:8000 \
ANTHROPIC_AUTH_TOKEN=<API-Key> \
claude
```

27
LICENSE Normal file
View File

@ -0,0 +1,27 @@
MIT License
Copyright (c) 2026 Oliver Hofmann
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---
Portions of this software were inspired by free-claude-code
(https://github.com/Alishahryar1/free-claude-code),
copyright (c) 2026 Ali Khokhar, MIT License.

View File

@ -4,12 +4,13 @@ Ollama bietet von sich aus keine Authentifizierung — wer die API erreicht, kan
## Features
- API-Key-Authentifizierung (Bearer Token oder `sk-`-Prefix)
- API-Key-Authentifizierung (Bearer Token, `sk-`-Prefix, `x-api-key`- und `anthropic-auth-token`-Header)
- Optionales Ablaufdatum pro API-Key
- Quota-Management mit getrennten Tages- und Monatslimits (Tokens & Requests)
- Token-Zählung via tiktoken, Reset-Grenzen in der Zeitzone Europe/Berlin
- Token-Zählung via tiktoken, Reset-Grenzen in der konfigurierten Zeitzone
- Web-Admin-Oberfläche (API-Keys verwalten, Ollama-Einstellungen, Verbrauchsanzeige)
- OpenAI-kompatibler `/v1/chat/completions`-Endpunkt mit Streaming und Tool-Use
- **Anthropic Messages API** `/v1/messages` — kompatibel mit Claude Code CLI und Anthropic-SDK-Clients
- Rotierende Nutzungs-Logs
- SQLite (Standard) oder PostgreSQL
- Docker-Image auf DockerHub: `mediaeng/llmproxy`
@ -35,6 +36,7 @@ DATABASE_URL=sqlite:///./test.db
OLLAMA_URL=http://localhost:11434
APP_TZ=Europe/Berlin
LOG_FILE=logs/usage.log
ANTHROPIC_DEFAULT_MODEL=llama3
```
| Variable | Standard | Beschreibung |
@ -49,6 +51,8 @@ LOG_FILE=logs/usage.log
| `APP_TZ` | `Europe/Berlin` | Zeitzone für tägliche/monatliche Quota-Resets |
| `LOG_FILE` | `logs/usage.log` | Pfad der rotierenden Nutzungs-Logdatei |
| `ALLOWED_ORIGINS` | `http://localhost:5173` | CORS-Origins (nur für Entwicklung relevant) |
| `ANTHROPIC_DEFAULT_MODEL` | — | Standard-Modell für `/v1/messages` (Ollama-Modellname) |
| `BACKEND_API_KEY` | — | API-Key für einen vorgelagerten Proxy (wird an das Backend weitergereicht) |
## Entwicklung (lokal)
@ -78,6 +82,23 @@ Das Script prüft alle Ports auf Belegung, initialisiert die Datenbank und start
Admin-Oberfläche: `http://localhost:5173`
## Claude Code CLI
Der Proxy stellt einen Anthropic-kompatiblen Endpunkt bereit, über den Claude Code CLI mit lokalen Ollama-Modellen genutzt werden kann.
```bash
# ANTHROPIC_DEFAULT_MODEL in .env setzen, dann:
./start_claude.sh
# Oder mit Key als Argument:
./start_claude.sh sk-dein-api-key
# Oder als Umgebungsvariable:
PROXY_API_KEY=sk-dein-api-key ./start_claude.sh
```
Das Script setzt `ANTHROPIC_BASE_URL` und `ANTHROPIC_AUTH_TOKEN` automatisch aus der `.env` und startet `claude`.
## Produktion (Docker)
### Docker Compose (empfohlen)
@ -168,17 +189,26 @@ Clients konfigurieren dann `https://llm.example.com/v1` als Base URL.
## Proxy-Endpunkte (Port 8000)
Alle Endpunkte erfordern einen gültigen API-Key im `Authorization`-Header.
Alle Endpunkte erfordern einen gültigen API-Key im `Authorization`-Header (`Bearer sk-...`), im `x-api-key`-Header oder im `anthropic-auth-token`-Header.
```bash
# OpenAI-kompatibler Endpunkt
curl -X POST http://localhost:8000/v1/chat/completions \
-H "Authorization: Bearer sk-xxxxxx" \
-H "Content-Type: application/json" \
-d '{"model":"llama3","messages":[{"role":"user","content":"Hallo"}]}'
# Anthropic-kompatibler Endpunkt (z. B. für Claude Code)
curl -X POST http://localhost:8000/v1/messages \
-H "x-api-key: sk-xxxxxx" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{"model":"llama3","messages":[{"role":"user","content":"Hallo"}],"max_tokens":1024}'
```
| Endpunkt | Methode | Beschreibung |
|----------|---------|--------------|
| `/v1/messages` | POST | Chat (Anthropic-Format, Streaming + Tool-Use) |
| `/v1/chat/completions` | POST | Chat (OpenAI-Format, Streaming + Tool-Use) |
| `/v1/models` | GET | Modelle (OpenAI-Format) |
| `/api/generate` | POST | Ollama generate (nativ) |
@ -226,7 +256,8 @@ llm_quota/
│ └── tests/
│ ├── conftest.py
│ ├── test_auth.py
│ └── test_quota.py
│ ├── test_quota.py
│ └── test_anthropic_messages.py
├── frontend/
│ └── src/
│ ├── main.jsx # React-Admin-UI
@ -238,13 +269,19 @@ llm_quota/
├── docker-entrypoint.sh
├── .dockerignore
├── start.sh # Entwicklungs-Startscript
├── start_claude.sh # Claude Code CLI mit Proxy starten
├── run_dev.py # Entwicklungs-Runner für PyCharm
├── build_push.sh # Docker-Build & Push zu DockerHub
├── LICENSE
├── DOCKERHUB.md # DockerHub-Beschreibung (deutsch)
├── DOCKERHUB.en.md # DockerHub-Beschreibung (englisch)
└── .gitignore
```
## Danksagung
Der Anthropic-kompatible Endpunkt (`/v1/messages`) wurde durch das Projekt [free-claude-code](https://github.com/Alishahryar1/free-claude-code) von Ali Khokhar inspiriert, das einen ähnlichen Ansatz für das Weiterleiten von Claude-Code-Anfragen an alternative LLM-Backends verfolgt.
## Lizenz
MIT
MIT — siehe [LICENSE](LICENSE)