Skip to content

pubflow/redge

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Redge

Redge is a Redis/Valkey protocol compatible edge KV server backed by SQL databases.

This first implementation includes:

  • RESP2 TCP listener.
  • Public HTTP status server for platform health checks.
  • Redis client compatibility for common string, TTL, sorted set, scan, pipeline, and simple transaction flows.
  • GUI-friendly inspection commands such as TYPE, DBSIZE, STRLEN, and MEMORY USAGE.
  • Multi-database support through DATABASE_URL: SQLite, libSQL/Turso, PostgreSQL, MySQL, and Cloudflare D1.
  • L1 in-memory cache powered by Ristretto/TinyLFU with TTL, max keys, max bytes, and admin metrics.
  • Admin HTTP server with health, cache metrics, cleanup, paginated key inspection, single-key deletion, and sorted-set inspection.

Run Locally

go mod tidy
go run ./cmd/redge

Then test:

curl.exe http://127.0.0.1:8080/health
curl.exe http://127.0.0.1:8080/ready
redis-cli -p 6379 ping
redis-cli -p 6379 set hello world ex 60
redis-cli -p 6379 get hello

Deploy on Coolify

Redge exposes two different protocols:

  • HTTP status on container port 8080.
  • Redis/Valkey TCP on container port 6379.

Point your Coolify domain, for example https://test1.conn.redgedb.com, to port 8080. That URL is for /health, /ready, and /version; it is not a Redis URL.

Expose Redis by making container port 6379 public as a TCP/public port in Coolify. Clients connect with the domain plus that public port:

redis://:PASSWORD@test1.conn.redgedb.com:PUBLIC_PORT/0

For public encrypted Redis, enable native Redis TLS and use rediss://:

rediss://:PASSWORD@test1.conn.redgedb.com:PUBLIC_PORT/0

If you map host port 6379 directly to container port 6379, clients can use:

redis://:PASSWORD@test1.conn.redgedb.com:6379/0

Prefer object-style client config when your library supports it:

host=test1.conn.redgedb.com
port=6379
password=PASSWORD
db=0

If PASSWORD contains URL-significant characters like @, :, /, #, ?, or %, URL-encode it before putting it in a redis:// URL.

Recommended production variables:

REDGE_ENV=production
REDGE_PROTECTED_MODE=true
REDGE_REQUIRE_AUTH=true
REDGE_PASSWORD=<strong-random-password>
DATABASE_URL=sqlite:///data/redge.db
REDGE_ADMIN_ENABLED=false
REDGE_MAX_CONNECTIONS=1000

Use a persistent volume mounted at /data when using the default SQLite database.

Security presets:

  • Private recommended: route HTTPS to 8080, do not publish 6379, and access Redis through a private network, VPN, tunnel, or internal service discovery. Keep REDGE_REQUIRE_AUTH=true.
  • Public strong: publish TCP 6379, enable REDGE_TLS_ENABLED=true, provide cert/key through base64 env secrets or mounted files, use a long random REDGE_PASSWORD, and set REDGE_ALLOWED_IPS when client IPs are known.

Coolify's HTTPS domain protects only the HTTP status route. It does not automatically encrypt Redis TCP, so public Redis clients should use rediss:// with TLS enabled in Redge.

Deploy (Nixpacks)

This repo includes nixpacks.toml with Go 1.25 build and a startup command that maps platform PORT to the HTTP status server.

Recommended environment variables:

REDGE_ENV=production
DATABASE_URL=sqlite:///data/redge.db
REDGE_ADMIN_ENABLED=false
REDGE_HTTP_ENABLED=true
# Optional:
# REDGE_ADDR=0.0.0.0:6379
# PORT=8080
# ADMIN_PORT=9090

Notes:

  • If your platform sets PORT, Redge will bind HTTP status to 0.0.0.0:${PORT}.
  • Redis TCP remains on REDGE_ADDR, defaulting to 0.0.0.0:6379.
  • If you want admin HTTP on a second port, set REDGE_ADMIN_ENABLED=true and ADMIN_PORT.

Deploy (Docker)

Build and run:

docker build -t redge:latest .
docker run --rm -p 8080:8080 -p 6379:6379 -e REDGE_REQUIRE_AUTH=true -e REDGE_PASSWORD=<strong-random-password> redge:latest

Production-like example with persistent SQLite data:

docker run -d --name redge \
	-p 8080:8080 \
	-p 6379:6379 \
	-v redge_data:/data \
	-v /path/to/certs:/certs:ro \
	-e REDGE_ENV=production \
	-e REDGE_PROTECTED_MODE=true \
	-e REDGE_REQUIRE_AUTH=true \
	-e REDGE_PASSWORD=<strong-random-password> \
	-e REDGE_TLS_ENABLED=true \
	-e REDGE_TLS_CERT_FILE=/certs/fullchain.pem \
	-e REDGE_TLS_KEY_FILE=/certs/privkey.pem \
	-e DATABASE_URL=sqlite:///data/redge.db \
	-e REDGE_ADMIN_ENABLED=false \
	redge:latest

If you do not want to mount certificate files, set base64 env values instead:

REDGE_TLS_ENABLED=true
REDGE_TLS_CERT_B64=<base64-fullchain-pem>
REDGE_TLS_KEY_B64=<base64-private-key-pem>

Generate those values from certificate files:

[Convert]::ToBase64String([IO.File]::ReadAllBytes("fullchain.pem"))
[Convert]::ToBase64String([IO.File]::ReadAllBytes("privkey.pem"))

The Docker image maps platform PORT to the HTTP status server automatically. Redis TCP stays on 6379 unless you set REDGE_ADDR.

Database URLs

DATABASE_URL=sqlite://redge.db
DATABASE_URL=libsql://example.turso.io
TURSO_AUTH_TOKEN=...
DATABASE_URL=postgres://user:pass@localhost:5432/redge?sslmode=disable
DATABASE_URL=mysql://user:pass@tcp(localhost:3306)/redge?parseTime=true
DATABASE_URL=d1://cloudflare_account_id/d1_database_id
D1_API_TOKEN=...
# Quick D1 connection-string form:
DATABASE_URL=d1://cloudflare_account_id/d1_database_id?apiToken=cloudflare_token

D1 uses github.com/pubflow/d1http directly instead of GORM or database/sql, so Redge can preserve D1 metadata and avoid fake SQL transaction semantics on the hot path. For production, prefer keeping D1 tokens in D1_API_TOKEN; when a token is embedded in DATABASE_URL, Redge extracts it and sanitizes the resolved URL before use.

Redis Compatibility

Supported connection and server commands:

  • AUTH, PING, ECHO, QUIT, SELECT, CLIENT SETNAME, CLIENT GETNAME, INFO, COMMAND, DBSIZE.

Supported string and TTL commands:

  • GET, SET, SETEX, DEL, EXISTS, TYPE, STRLEN, MEMORY USAGE, EXPIRE, TTL, PTTL, INCR, DECR, INCRBY, DECRBY.

Supported sorted set commands:

  • ZADD, ZCARD, ZREM, ZREMRANGEBYSCORE, ZRANGE, ZSCORE, ZCOUNT.

Supported iteration and batching behavior:

  • SCAN with MATCH and COUNT.
  • RESP pipelining from clients like ioredis.
  • Simple MULTI, EXEC, and DISCARD queued execution.

Supported admin inspection routes:

  • GET /admin/v1/keys?match=session:*&cursor=0&count=100
  • GET /admin/v1/keys/{key}
  • DELETE /admin/v1/keys/{key}
  • GET /admin/v1/zsets/{key}?start=0&stop=99

Cloudflare D1 notes:

  • D1 schema migrations use d1http.BatchRaw where it is safe.
  • Parameterized hot-path commands use single prepared HTTP calls because the D1 HTTP API rejects multiple statements with params in one /raw request.
  • ioredis pipeline correctness is supported at the Redis protocol layer. True D1 write coalescing for arbitrary client pipelines needs a dedicated server-side coalescer because Redis pipelining has no explicit begin/end marker on the wire.

Not supported yet:

  • Redis Cluster, Lua scripting, Pub/Sub, Streams, hashes, sets, lists, blocking list commands, KEYS, WATCH/UNWATCH, geospatial commands, and probabilistic data structures.

About

Redis-compatible storage for the edge.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors