Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
llm-proxy.db
llm-proxy.db-shm
llm-proxy.db-wal
llm-proxy
/proxy.db
/proxy.db-shm
/proxy.db-wal
/proxy
coverage.out

# Frontend
Expand Down
8 changes: 4 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,19 @@ COPY . .
COPY --from=frontend /src/internal/web/frontend/dist ./internal/web/frontend/dist

# Build the binary.
RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /usr/local/bin/llm-proxy .
RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /usr/local/bin/proxy .

# ── Runtime stage ──────────────────────────────────────────────────────
FROM alpine:3.21

RUN apk add --no-cache ca-certificates tzdata

COPY --from=builder /usr/local/bin/llm-proxy /usr/local/bin/llm-proxy
COPY --from=builder /usr/local/bin/proxy /usr/local/bin/proxy

# Default data directory for the SQLite database.
RUN mkdir -p /data
ENV DSN=/data/llm-proxy.db
ENV DSN=/data/proxy.db

EXPOSE 8080

ENTRYPOINT ["llm-proxy"]
ENTRYPOINT ["proxy"]
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# LLM Proxy
# proxy

An OpenAI-compatible LLM proxy that routes requests to any OpenAI-compatible backend. Written in Go. SQLite for storage.

Expand Down Expand Up @@ -39,10 +39,10 @@ The dashboard is embedded into the binary at compile time, so the frontend must
cd internal/web/frontend && npm ci && npm run build && cd -

# 2. Build the binary
go build -o llm-proxy .
go build -o proxy .

# 3. Run (ADMIN_TOKEN is required)
ADMIN_TOKEN=my-secret-admin-token ./llm-proxy
ADMIN_TOKEN=my-secret-admin-token ./proxy
```

> **Note:** `go build` will fail with `pattern frontend/dist/*: no matching files found` if you skip step 1. The `dist/` directory is git-ignored and generated by the frontend build.
Expand All @@ -58,7 +58,7 @@ All configuration is via environment variables:
| Variable | Default | Description |
|---|---|---|
| `ADDR` | `:8080` | Server listen address |
| `DSN` | `llm-proxy.db` | SQLite database file path |
| `DSN` | `proxy.db` | SQLite database file path |
| `ADMIN_TOKEN` | *(required)* | Bearer token for `/admin/*` endpoints and dashboard login |

## Development
Expand All @@ -83,15 +83,15 @@ ADMIN_TOKEN=my-secret ./development.sh

```bash
cd internal/web/frontend && npm ci && npm run build && cd -
go build -trimpath -ldflags="-s -w" -o llm-proxy .
go build -trimpath -ldflags="-s -w" -o proxy .
```

This produces a single binary with the React dashboard embedded.

## Project structure

```
llm-proxy/
proxy/
├── openapi.yaml # OpenAPI 3.1 spec (embedded at compile time)
├── main.go # Entrypoint
├── development.sh # Start frontend + backend for local dev
Expand Down
908 changes: 466 additions & 442 deletions coverage.out

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
services:
llm-proxy:
image: ghcr.io/lab34/llm-proxy:latest
proxy:
image: ghcr.io/lab34-es/proxy:latest
ports:
- "8080:8080"
environment:
- ADMIN_TOKEN=change-me-to-a-secure-token
- ADDR=:8080
- DSN=/data/llm-proxy.db
- DSN=/data/proxy.db
volumes:
- llm-proxy-data:/data
- proxy-data:/data
restart: unless-stopped

volumes:
llm-proxy-data:
proxy-data:
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module github.com/lab34/llm-proxy
module github.com/lab34-es/proxy

go 1.25.0

Expand Down
2 changes: 1 addition & 1 deletion internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func Load() Config {
adminToken := envOr("ADMIN_TOKEN", "")
return Config{
Addr: envOr("ADDR", ":8080"),
DSN: envOr("DSN", "llm-proxy.db"),
DSN: envOr("DSN", "proxy.db"),
AdminToken: adminToken,
SessionSecret: envOr("SESSION_SECRET", adminToken),
}
Expand Down
2 changes: 1 addition & 1 deletion internal/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestLoad_Defaults(t *testing.T) {
cfg := Load()

assert.Equal(t, ":8080", cfg.Addr)
assert.Equal(t, "llm-proxy.db", cfg.DSN)
assert.Equal(t, "proxy.db", cfg.DSN)
assert.Equal(t, "", cfg.AdminToken)
assert.Equal(t, "", cfg.SessionSecret)
}
Expand Down
2 changes: 1 addition & 1 deletion internal/handler/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"regexp"
"time"

"github.com/lab34/llm-proxy/internal/store"
"github.com/lab34-es/proxy/internal/store"
"github.com/labstack/echo/v4"
)

Expand Down
4 changes: 2 additions & 2 deletions internal/handler/admin_guardrail_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"strings"
"testing"

"github.com/lab34/llm-proxy/internal/db"
"github.com/lab34/llm-proxy/internal/store"
"github.com/lab34-es/proxy/internal/db"
"github.com/lab34-es/proxy/internal/store"
"github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down
4 changes: 2 additions & 2 deletions internal/handler/admin_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"strings"
"testing"

"github.com/lab34/llm-proxy/internal/db"
"github.com/lab34/llm-proxy/internal/store"
"github.com/lab34-es/proxy/internal/db"
"github.com/lab34-es/proxy/internal/store"
"github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down
2 changes: 1 addition & 1 deletion internal/handler/docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (h *DocsHandler) SwaggerUI(c echo.Context) error {
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LLM Proxy — API Docs</title>
<title>lab34/proxy — API Docs</title>
<link rel="stylesheet" href="https://unpkg.com/swagger-ui-dist@5/swagger-ui.css">
<style>
html { box-sizing: border-box; overflow-y: scroll; }
Expand Down
6 changes: 3 additions & 3 deletions internal/handler/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"errors"
"net/http"

"github.com/lab34/llm-proxy/internal/middleware"
"github.com/lab34/llm-proxy/internal/proxy"
"github.com/lab34/llm-proxy/internal/store"
"github.com/lab34-es/proxy/internal/middleware"
"github.com/lab34-es/proxy/internal/proxy"
"github.com/lab34-es/proxy/internal/store"
"github.com/labstack/echo/v4"
)

Expand Down
10 changes: 5 additions & 5 deletions internal/handler/proxy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import (
"net/http/httptest"
"testing"

"github.com/lab34/llm-proxy/internal/db"
"github.com/lab34/llm-proxy/internal/middleware"
"github.com/lab34/llm-proxy/internal/models"
"github.com/lab34/llm-proxy/internal/proxy"
"github.com/lab34/llm-proxy/internal/store"
"github.com/lab34-es/proxy/internal/db"
"github.com/lab34-es/proxy/internal/middleware"
"github.com/lab34-es/proxy/internal/models"
"github.com/lab34-es/proxy/internal/proxy"
"github.com/lab34-es/proxy/internal/store"
"github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down
4 changes: 2 additions & 2 deletions internal/middleware/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import (
"net/http"
"strings"

"github.com/lab34/llm-proxy/internal/models"
"github.com/lab34/llm-proxy/internal/store"
"github.com/lab34-es/proxy/internal/models"
"github.com/lab34-es/proxy/internal/store"
"github.com/labstack/echo/v4"
)

Expand Down
6 changes: 3 additions & 3 deletions internal/middleware/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"net/http/httptest"
"testing"

"github.com/lab34/llm-proxy/internal/db"
"github.com/lab34/llm-proxy/internal/models"
"github.com/lab34/llm-proxy/internal/store"
"github.com/lab34-es/proxy/internal/db"
"github.com/lab34-es/proxy/internal/models"
"github.com/lab34-es/proxy/internal/store"
"github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down
2 changes: 1 addition & 1 deletion internal/middleware/ratelimit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"net/http/httptest"
"testing"

"github.com/lab34/llm-proxy/internal/models"
"github.com/lab34-es/proxy/internal/models"
"github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand Down
6 changes: 3 additions & 3 deletions internal/proxy/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (
"strings"
"testing"

"github.com/lab34/llm-proxy/internal/db"
"github.com/lab34/llm-proxy/internal/models"
"github.com/lab34/llm-proxy/internal/store"
"github.com/lab34-es/proxy/internal/db"
"github.com/lab34-es/proxy/internal/models"
"github.com/lab34-es/proxy/internal/store"
"github.com/labstack/echo/v4"
"github.com/stretchr/testify/require"
)
Expand Down
4 changes: 2 additions & 2 deletions internal/proxy/forwarder.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
"sync"
"time"

"github.com/lab34/llm-proxy/internal/models"
"github.com/lab34/llm-proxy/internal/store"
"github.com/lab34-es/proxy/internal/models"
"github.com/lab34-es/proxy/internal/store"
)

// Forwarder proxies OpenAI-compatible requests to an upstream provider.
Expand Down
6 changes: 3 additions & 3 deletions internal/proxy/forwarder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import (
"strings"
"testing"

"github.com/lab34/llm-proxy/internal/db"
"github.com/lab34/llm-proxy/internal/models"
"github.com/lab34/llm-proxy/internal/store"
"github.com/lab34-es/proxy/internal/db"
"github.com/lab34-es/proxy/internal/models"
"github.com/lab34-es/proxy/internal/store"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down
6 changes: 3 additions & 3 deletions internal/proxy/guardrail_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ import (
"strings"
"testing"

"github.com/lab34/llm-proxy/internal/db"
"github.com/lab34/llm-proxy/internal/models"
"github.com/lab34/llm-proxy/internal/store"
"github.com/lab34-es/proxy/internal/db"
"github.com/lab34-es/proxy/internal/models"
"github.com/lab34-es/proxy/internal/store"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down
2 changes: 1 addition & 1 deletion internal/store/apikey.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"time"

"github.com/google/uuid"
"github.com/lab34/llm-proxy/internal/models"
"github.com/lab34-es/proxy/internal/models"
)

type APIKeyStore struct {
Expand Down
2 changes: 1 addition & 1 deletion internal/store/guardrail.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"time"

"github.com/google/uuid"
"github.com/lab34/llm-proxy/internal/models"
"github.com/lab34-es/proxy/internal/models"
)

type GuardrailStore struct {
Expand Down
2 changes: 1 addition & 1 deletion internal/store/guardrail_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"time"

"github.com/google/uuid"
"github.com/lab34/llm-proxy/internal/models"
"github.com/lab34-es/proxy/internal/models"
)

type GuardrailEventStore struct {
Expand Down
2 changes: 1 addition & 1 deletion internal/store/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"time"

"github.com/google/uuid"
"github.com/lab34/llm-proxy/internal/models"
"github.com/lab34-es/proxy/internal/models"
)

type ProviderStore struct {
Expand Down
2 changes: 1 addition & 1 deletion internal/store/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"database/sql"
"testing"

"github.com/lab34/llm-proxy/internal/db"
"github.com/lab34-es/proxy/internal/db"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down
2 changes: 1 addition & 1 deletion internal/store/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"time"

"github.com/google/uuid"
"github.com/lab34/llm-proxy/internal/models"
"github.com/lab34-es/proxy/internal/models"
)

type UsageStore struct {
Expand Down
4 changes: 2 additions & 2 deletions internal/web/frontend/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# llm-proxy dashboard
# proxy dashboard

The admin console for llm-proxy, following the lab34 brand guidelines: React 19 +
The admin console for proxy, following the lab34 brand guidelines: React 19 +
TypeScript on Vite, styled with Tailwind CSS v4 and [shadcn/ui](https://ui.shadcn.com)
components (Radix primitives + `class-variance-authority`).

Expand Down
2 changes: 1 addition & 1 deletion internal/web/frontend/src/components/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export default function Layout() {

{/* The monogram signs the footer — it certifies; it does not shout. */}
<div className="flex items-center gap-2 border-t px-4 py-3 font-mono text-xs text-muted-foreground">
<span className="flex-1 truncate">lab34 — llm-proxy</span>
<span className="flex-1 truncate">lab34 — proxy</span>
<Monogram size={20} variant="outline" />
</div>
</aside>
Expand Down
16 changes: 8 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import (
"github.com/labstack/echo/v4"
echomw "github.com/labstack/echo/v4/middleware"

"github.com/lab34/llm-proxy/internal/config"
"github.com/lab34/llm-proxy/internal/db"
"github.com/lab34/llm-proxy/internal/handler"
"github.com/lab34/llm-proxy/internal/middleware"
"github.com/lab34/llm-proxy/internal/proxy"
"github.com/lab34/llm-proxy/internal/store"
"github.com/lab34/llm-proxy/internal/web"
"github.com/lab34-es/proxy/internal/config"
"github.com/lab34-es/proxy/internal/db"
"github.com/lab34-es/proxy/internal/handler"
"github.com/lab34-es/proxy/internal/middleware"
"github.com/lab34-es/proxy/internal/proxy"
"github.com/lab34-es/proxy/internal/store"
"github.com/lab34-es/proxy/internal/web"
)

//go:embed openapi.yaml
Expand Down Expand Up @@ -97,7 +97,7 @@ func main() {
v1.GET("/models", proxyH.ListModels)

// Start.
log.Printf("LLM Proxy listening on %s", cfg.Addr)
log.Printf("proxy listening on %s", cfg.Addr)
log.Printf("Swagger UI: http://localhost%s/docs", cfg.Addr)
log.Printf("Dashboard: http://localhost%s/dashboard", cfg.Addr)
if err := e.Start(cfg.Addr); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion openapi.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
openapi: 3.1.0
info:
title: LLM Proxy
title: lab34/proxy
description: |
An OpenAI-compatible LLM proxy that routes requests to any OpenAI-compatible
backend. Manages upstream provider credentials, issues proxy API keys for
Expand Down
Loading