Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4328e15
chore: move apps to svc
chronark Jan 5, 2026
39c519b
Merge branch 'main' of github.com:unkeyed/unkey into proto
chronark Jan 5, 2026
0eaee6e
chore: move protos to reflect ownership
chronark Jan 5, 2026
9dca886
feat: vault is its own service
chronark Jan 7, 2026
fe8d1eb
test: add vault tests
chronark Jan 7, 2026
56c7811
Merge branch 'main' of github.com:unkeyed/unkey into vault
chronark Jan 7, 2026
5be8ab1
Merge branch 'main' of github.com:unkeyed/unkey into vault
chronark Jan 8, 2026
8ed95b0
Update cmd/vault/main.go
chronark Jan 8, 2026
6d1fd9b
Merge branch 'main' of github.com:unkeyed/unkey into vault
chronark Jan 12, 2026
c32b23d
test: fuzz tests for vault
chronark Jan 12, 2026
5cbc187
fix: env prefix
chronark Jan 12, 2026
e4551be
fix: liveness endpoints
chronark Jan 12, 2026
9835182
fix: link cmd
chronark Jan 12, 2026
a84479e
fix: port
chronark Jan 12, 2026
8ae8692
refactor: clean up decrypt validation
chronark Jan 12, 2026
4b19b60
Merge branch 'main' into vault
chronark Jan 12, 2026
c375d14
fix: liveness
chronark Jan 12, 2026
d092a2d
Merge branch 'vault' of github.com:unkeyed/unkey into vault
chronark Jan 12, 2026
6a1d745
Merge branch 'main' into vault
chronark Jan 12, 2026
9434fb1
fmt: vet
chronark Jan 12, 2026
cd4eed3
revert: remote cache
chronark Jan 12, 2026
61b251b
Update svc/vault/internal/storage/memory_test.go
chronark Jan 13, 2026
c79f8f5
Update web/apps/agent/services/vault/keyring/decode_and_decrypt_key.go
chronark Jan 13, 2026
5a0cc20
Update svc/vault/internal/storage/memory_test.go
chronark Jan 13, 2026
8ca0781
Merge branch 'main' of github.com:unkeyed/unkey into vault
chronark Jan 13, 2026
3d806b6
fix: BUILD dep
chronark Jan 13, 2026
a688be2
fix: import correct package
chronark Jan 13, 2026
f20dd8f
Merge branch 'main' into vault
chronark Jan 13, 2026
dcdd1c6
chore: clean up
chronark Jan 14, 2026
05cad93
Merge branch 'main' into vault
chronark Jan 14, 2026
41fe545
Merge branch 'main' into vault
chronark Jan 14, 2026
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
1 change: 1 addition & 0 deletions .bazelignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ web
proto
svc/ctrl/proto
svc/krane/proto
svc/vault/proto
15 changes: 8 additions & 7 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
FROM golang:1.25 AS builder

WORKDIR /go/src/github.com/unkeyed/unkey
# Install Bazelisk (which will download the correct Bazel version)
RUN go install github.com/bazelbuild/bazelisk@latest

WORKDIR /src

COPY go.mod go.sum ./
RUN go mod download
COPY . .

RUN bazelisk build //:unkey

ARG VERSION
ENV CGO_ENABLED=0
RUN go build -o bin/unkey -ldflags="-X 'github.com/unkeyed/unkey/pkg/version.Version=${VERSION}'" ./main.go
# Extract the binary path and copy it to a known location
RUN cp $(bazelisk cquery //:unkey --output=files 2>/dev/null) /unkey

FROM gcr.io/distroless/static-debian12
COPY --from=builder /go/src/github.com/unkeyed/unkey/bin/unkey /
COPY --from=builder /unkey /unkey

LABEL org.opencontainers.image.source=https://github.com/unkeyed/unkey
LABEL org.opencontainers.image.description="Unkey API"
Expand Down
11 changes: 11 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,17 @@ down: ## Stop dev environment
local-dashboard: install build ## Run local development setup for dashboard
pnpm --dir=web/apps/dashboard local

.PHONY: fuzz
fuzz: ## Run fuzz tests
@files=$$(grep -r --include='*_test.go' -l 'func Fuzz' .); \
for file in $$files; do \
funcs=$$(grep -oE 'func (Fuzz[a-zA-Z0-9_]*)' $$file | sed 's/func //'); \
for func in $$funcs; do \
echo "Fuzzing $$func in $$file"; \
parentDir=$$(dirname $$file); \
go test $$parentDir -run=$$func -fuzz=$$func -fuzztime=60s; \
done; \
done
.PHONY: unkey
unkey: ## Run unkey CLI (usage: make unkey dev seed local, make unkey run api ARGS="--http-port=7070")
@set -a; [ -f .env ] && . ./.env; set +a; bazel run //:unkey -- $(filter-out unkey,$(MAKECMDGOALS)) $(ARGS)
Expand Down
3 changes: 3 additions & 0 deletions buf.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Generated by buf. DO NOT EDIT.
version: v2
deps:
- name: buf.build/bufbuild/protovalidate
commit: 2a1774d888024a9b93ce7eb4b59f6a83
digest: b5:6b7f9bc919b65e5b79d7b726ffc03d6f815a412d6b792970fa6f065cae162107bd0a9d47272c8ab1a2c9514e87b13d3fbf71df614374d62d2183afb64be2d30a
- name: buf.build/restatedev/sdk-go
commit: 9ea0b54286dd4f35b0cb96ecdf09b402
digest: b5:822b9362e943c827c36e44b0db519542259439382f94817989349d0ee590617ba70e35975840c5d96ceff278254806435e7d570db81548f9703c00b01eec398e
4 changes: 2 additions & 2 deletions buf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ version: v2
modules:
- path: svc/ctrl/proto
- path: svc/krane/proto
- path: svc/vault/proto
- path: proto

deps:
- buf.build/googleapis/googleapis
- buf.build/restatedev/sdk-go
- buf.build/bufbuild/protovalidate
lint:
use:
- STANDARD
Expand Down
1 change: 1 addition & 0 deletions cmd/run/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ go_library(
"//cmd/krane",
"//cmd/preflight",
"//cmd/sentinel",
"//cmd/vault",
"//pkg/cli",
],
)
4 changes: 4 additions & 0 deletions cmd/run/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/unkeyed/unkey/cmd/krane"
"github.com/unkeyed/unkey/cmd/preflight"
"github.com/unkeyed/unkey/cmd/sentinel"
"github.com/unkeyed/unkey/cmd/vault"
"github.com/unkeyed/unkey/pkg/cli"
)

Expand All @@ -29,6 +30,7 @@ AVAILABLE SERVICES:
- krane: The VM management service for infrastructure
- frontline: Multi-tenant frontline service for TLS termination and routing
- sentinel: Environment tenant sentinel service for routing requests to the actual instances
- vault: Secret management service for encryption

EXAMPLES:
unkey run api # Run the API server
Expand All @@ -44,6 +46,7 @@ unkey run api --port 8080 --env production # Run API server with custom con
frontline.Cmd,
sentinel.Cmd,
preflight.Cmd,
vault.Cmd,
},
Action: runAction,
}
Expand All @@ -56,6 +59,7 @@ func runAction(ctx context.Context, cmd *cli.Command) error {
fmt.Println(" frontline - Multi-tenant ingress service for TLS termination and routing")
fmt.Println(" sentinel - Environment tenant gateway service for routing requests to the actual instances")
fmt.Println(" preflight - Kubernetes mutating webhook for secrets and credentials injection")
fmt.Println(" vault - Encryption service for sensitive data")
fmt.Println()
fmt.Println("Use 'unkey run <service>' to start a specific service")
fmt.Println("Use 'unkey run <service> --help' for service-specific options")
Expand Down
13 changes: 13 additions & 0 deletions cmd/vault/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
load("@rules_go//go:def.bzl", "go_library")

go_library(
name = "vault",
srcs = ["main.go"],
importpath = "github.com/unkeyed/unkey/cmd/vault",
visibility = ["//visibility:public"],
deps = [
"//pkg/cli",
"//pkg/uid",
"//svc/vault",
],
)
70 changes: 70 additions & 0 deletions cmd/vault/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package vault

import (
"context"

"github.com/unkeyed/unkey/pkg/cli"
"github.com/unkeyed/unkey/pkg/uid"
"github.com/unkeyed/unkey/svc/vault"
)

var Cmd = &cli.Command{
Version: "",
Commands: []*cli.Command{},
Aliases: []string{},
Description: "",
Name: "vault",
Usage: "Run unkey's encryption service",
Flags: []cli.Flag{
// Server Configuration
cli.Int("http-port", "HTTP port for the control plane server to listen on. Default: 8080",
cli.Default(8060), cli.EnvVar("UNKEY_HTTP_PORT")),

// Instance Identification
cli.String("instance-id", "Unique identifier for this instance. Auto-generated if not provided.",
cli.Default(uid.New(uid.InstancePrefix, 4)), cli.EnvVar("UNKEY_INSTANCE_ID")),

cli.String("bearer-token", "Authentication token for API access.",
cli.Required(),
cli.EnvVar("UNKEY_BEARER_TOKEN")),

// Vault Configuration - General secrets (env vars, API keys)
cli.StringSlice("master-keys", "Vault master keys for encryption (general vault)",
cli.Required(), cli.EnvVar("UNKEY_MASTER_KEYS")),
cli.String("s3-url", "S3 endpoint URL for general vault",
cli.Required(),
cli.EnvVar("UNKEY_S3_URL")),
cli.String("s3-bucket", "S3 bucket for general vault (env vars, API keys)",
cli.Required(),
cli.EnvVar("UNKEY_S3_BUCKET")),
cli.String("s3-access-key-id", "S3 access key ID for general vault",
cli.Required(),
cli.EnvVar("UNKEY_S3_ACCESS_KEY_ID")),
cli.String("s3-access-key-secret", "S3 secret access key for general vault",
cli.Required(),
cli.EnvVar("UNKEY_S3_ACCESS_KEY_SECRET")),
},
Action: action,
}

func action(ctx context.Context, cmd *cli.Command) error {

config := vault.Config{
// Basic configuration
HttpPort: cmd.RequireInt("http-port"),
InstanceID: cmd.RequireString("instance-id"),
S3Url: cmd.RequireString("s3-url"),
S3Bucket: cmd.RequireString("s3-bucket"),
S3AccessKeyID: cmd.RequireString("s3-access-key-id"),
S3AccessKeySecret: cmd.RequireString("s3-access-key-secret"),
MasterKeys: cmd.RequireStringSlice("master-keys"),
BearerToken: cmd.RequireString("bearer-token"),
}

err := config.Validate()
if err != nil {
return err
}

return vault.Run(ctx, config)
}
30 changes: 26 additions & 4 deletions dev/Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ local_resource('build-unkey','cd .. && CGO_ENABLED=0 GOOS=linux ARCH=amd64 go bu



# Agent service (1 replica)
# Agent service
docker_build(
'unkey/agent:latest',
'../web/apps/agent',
Expand All @@ -80,7 +80,29 @@ k8s_resource(
trigger_mode=TRIGGER_MODE_AUTO
)

# API service (3 replicas)

# Vault service
docker_build_with_restart(
'unkey/vault:latest',
'..',
dockerfile='./Dockerfile.tilt',
entrypoint=['/unkey', 'run', 'vault'],
only=['./bin'],
live_update=[
sync('./bin/unkey', '/unkey'),
]
)
k8s_yaml('k8s/manifests/vault.yaml')
k8s_resource(
'vault',
port_forwards='8060:8060',
resource_deps=['s3', 'build-unkey'],
labels=['unkey'],
auto_init=True,
trigger_mode=TRIGGER_MODE_AUTO
)

# API service
docker_build_with_restart(
'unkey/api:latest',
'..',
Expand All @@ -101,7 +123,7 @@ k8s_resource(
trigger_mode=TRIGGER_MODE_AUTO
)

# Ctrl service (1 replica)
# Ctrl service
docker_build_with_restart(
'unkey/ctrl:latest',
'..',
Expand All @@ -122,7 +144,7 @@ k8s_resource(
trigger_mode=TRIGGER_MODE_AUTO
)

# Krane service (1 replica)
# Krane service
docker_build_with_restart(
'unkey/krane:latest',
'..',
Expand Down
32 changes: 30 additions & 2 deletions dev/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ services:
volumes:
- mysql:/var/lib/mysql
healthcheck:
test:
["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-proot"]
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-proot"]
timeout: 20s
retries: 10
start_period: 40s
Expand Down Expand Up @@ -122,6 +121,35 @@ services:
network_mode: host
command: ["serve", "--inmemory"]

# Vault service for encryption and key management
vault:
networks:
- default
container_name: vault
build:
context: ../
dockerfile: Dockerfile
command: ["run", "vault"]
ports:
- "8060:8060"
depends_on:
s3:
condition: service_healthy
environment:
UNKEY_HTTP_PORT: "8060"
UNKEY_S3_URL: "http://s3:3902"
UNKEY_S3_BUCKET: "vault"
UNKEY_S3_ACCESS_KEY_ID: "minio_root_user"
UNKEY_S3_ACCESS_KEY_SECRET: "minio_root_password"
UNKEY_MASTER_KEYS: "Ch9rZWtfMmdqMFBJdVhac1NSa0ZhNE5mOWlLSnBHenFPENTt7an5MRogENt9Si6wms4pQ2XIvqNSIgNpaBenJmXgcInhu6Nfv2U="
UNKEY_BEARER_TOKEN: "vault-test-token-123"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8060/v1.vault.VaultService/Liveness"]
timeout: 10s
retries: 5
start_period: 30s
interval: 10s

agent:
networks:
- default
Expand Down
83 changes: 83 additions & 0 deletions dev/k8s/manifests/vault.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: vault
namespace: unkey
labels:
app: vault
component: unkey
spec:
replicas: 1
selector:
matchLabels:
app: vault
template:
metadata:
labels:
app: vault
component: unkey
spec:
containers:
- name: vault
image: unkey/vault:latest
command: ["run", "vault"]
ports:
- name: http
containerPort: 8060
protocol: TCP
env:
- name: UNKEY_HTTP_PORT
value: "8060"
- name: UNKEY_S3_URL
value: "http://s3:3902"
- name: UNKEY_S3_BUCKET
value: "vault"
- name: UNKEY_S3_ACCESS_KEY_ID
value: "minio_root_user"
- name: UNKEY_S3_ACCESS_KEY_SECRET
value: "minio_root_password"
- name: UNKEY_MASTER_KEYS
value: "Ch9rZWtfMmdqMFBJdVhac1NSa0ZhNE5mOWlLSnBHenFPENTt7an5MRogENt9Si6wms4pQ2XIvqNSIgNpaBenJmXgcInhu6Nfv2U="
- name: UNKEY_BEARER_TOKEN
value: "vault-test-token-123"
livenessProbe:
httpGet:
path: /vault.v1.VaultService/Liveness
port: 8060
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /vault.v1.VaultService/Liveness
port: 8060
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "256Mi"
cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
name: vault
namespace: unkey
labels:
app: vault
component: unkey
spec:
type: ClusterIP
ports:
- name: http
port: 8060
targetPort: 8060
protocol: TCP
selector:
app: vault
Loading
Loading