Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3eaeecf
feat: tracing middleware
chronark Feb 12, 2025
a6dbd71
wip
chronark Feb 13, 2025
6fe47ee
[autofix.ci] apply automated fixes
autofix-ci[bot] Feb 13, 2025
89a48d2
Merge branch 'main' of https://github.com/unkeyed/unkey into routes_v…
chronark Feb 13, 2025
8180c8b
wip
chronark Feb 13, 2025
db95a3c
test: simulation test cache
chronark Feb 17, 2025
d6b9dd9
test: simulation test cache
chronark Feb 17, 2025
64204ce
feat: setting overrides works
chronark Feb 17, 2025
1cc2271
Merge branch 'main' into routes_v2_ratelimit
chronark Feb 17, 2025
254ca82
Merge branch 'main' of https://github.com/unkeyed/unkey into routes_v…
chronark Feb 17, 2025
1580c14
Merge branch 'routes_v2_ratelimit' of https://github.com/unkeyed/unke…
chronark Feb 17, 2025
271551e
Update go/pkg/fault/tag.go
chronark Feb 17, 2025
568c10b
Update go/pkg/database/transform/identity.go
chronark Feb 17, 2025
3204f86
Update go/pkg/database/transform/key.go
chronark Feb 17, 2025
36247d2
feat: use clocks in the db to better simulate later
chronark Feb 17, 2025
c79542e
Merge branch 'routes_v2_ratelimit' of https://github.com/unkeyed/unke…
chronark Feb 17, 2025
b67a47d
docs: explain api config
chronark Feb 18, 2025
e14083d
Update go/pkg/discovery/redis.go
chronark Feb 18, 2025
5d16cb7
feat: use redis based discovery
chronark Feb 18, 2025
a8ba276
Merge branch 'routes_v2_ratelimit' of https://github.com/unkeyed/unke…
chronark Feb 18, 2025
f3a1665
fix: small issues
chronark Feb 18, 2025
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
2 changes: 1 addition & 1 deletion .github/workflows/job_test_go_api_local.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ jobs:
working-directory: go

- name: Test
run: go test -cover -json -timeout=60m -failfast ./... | tparse -all -progress
run: task test
working-directory: go
6 changes: 3 additions & 3 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@ jobs:
# AGENT_BASE_URL: "http://localhost:8080"
# working-directory: apps/agent

# test_go_api_local:
# name: Test Go API Local
# uses: ./.github/workflows/job_test_go_api_local.yaml
test_go_api_local:
name: Test Go API Local
uses: ./.github/workflows/job_test_go_api_local.yaml
4 changes: 2 additions & 2 deletions apps/engineering/app/architecture/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ export default async function Page(props: {
>
<DocsTitle>{page.data.title}</DocsTitle>

<DocsDescription className="text-sm">{page.data.description}</DocsDescription>
<DocsDescription>{page.data.description}</DocsDescription>

<DocsBody className="text-sm">
<DocsBody>
<MDX components={{ ...defaultMdxComponents }} />
</DocsBody>
</DocsPage>
Expand Down
8 changes: 3 additions & 5 deletions apps/engineering/app/architecture/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import { baseOptions } from "../layout.config";

export default function Layout({ children }: { children: ReactNode }) {
return (
<div>
<DocsLayout tree={architectureSource.pageTree} {...baseOptions}>
{children}
</DocsLayout>
</div>
<DocsLayout tree={architectureSource.pageTree} {...baseOptions}>
{children}
</DocsLayout>
);
}
2 changes: 1 addition & 1 deletion apps/engineering/app/company/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default async function Page(props: {
>
<DocsTitle>{page.data.title}</DocsTitle>

<DocsDescription className="text-sm">{page.data.description}</DocsDescription>
<DocsDescription>{page.data.description}</DocsDescription>

<DocsBody>
<MDX components={{ ...defaultMdxComponents }} />
Expand Down
4 changes: 2 additions & 2 deletions apps/engineering/app/contributing/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ export default async function Page(props: {
>
<DocsTitle>{page.data.title}</DocsTitle>

<DocsDescription className="text-sm">{page.data.description}</DocsDescription>
<DocsDescription>{page.data.description}</DocsDescription>

<DocsBody className="text-sm">
<DocsBody>
<MDX components={{ ...defaultMdxComponents }} />
</DocsBody>
</DocsPage>
Expand Down
2 changes: 1 addition & 1 deletion apps/engineering/app/rfcs/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { baseOptions } from "../layout.config";

export default function Layout({ children }: { children: ReactNode }) {
return (
<div>
<div className="font-mono text-sm">
<DocsLayout tree={rfcSource.pageTree} {...baseOptions}>
{children}
</DocsLayout>
Expand Down
211 changes: 211 additions & 0 deletions apps/engineering/content/architecture/services/api.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
---
title: API
---
import { Step, Steps } from 'fumadocs-ui/components/steps';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import {Property} from "fumadocs-openapi/ui"


<Callout>
This document only covers v2 of the Unkey API. The v1 API on Cloudflare Workers is deprecated and will be removed in the future. It was too hard to selfhost anyways.
</Callout>

Our API runs on AWS containers, in multiple regions behind a global load balancer to ensure high availability and low latency.


The source code is available on [GitHub](https://github.com/unkeyed/unkey/tree/main/go/cmd/api).

## Quickstart

To get started, you need [go1.24+](https://go.dev/dl/) installed on your machine.

<Steps>

<Step>
### Clone the repository:

```bash
git clone git@github.com:unkeyed/unkey.git
cd unkey/go
```
</Step>

<Step>
### Build the binary:

```bash
go build -o unkey .
```
</Step>

<Step>
### Run the binary:

```bash
unkey api --config ./path/to/config.json
```

You should now be able to access the API at

```bash
$ curl http://localhost:<HTTP_PORT>/v2/liveness
{"message":"we're cooking"}%
```
</Step>



</Steps>

## Configuration

The API server requires a json configuration file to be passed as an argument to the binary.

You can use `${SOME_NAME}` as placeholder in your config file and it will be replaced by the value of the environment variable `SOME_NAME`.


```json title="Example"
{
"httpPort": "${PORT}"
}
```

The most up to date json schema can be found here: [https://raw.githubusercontent.com/unkeyed/unkey/refs/heads/main/go/schema.json](https://raw.githubusercontent.com/unkeyed/unkey/refs/heads/main/go/schema.json)

Most IDEs support JSON schema validation if you put it in your config file.
```json
{
"$schema": "https://raw.githubusercontent.com/unkeyed/unkey/refs/heads/main/go/schema.json",
// ...
}
```

<Callout type="info">
You can check out our own configuration files on [GitHub](https://github.com/unkeyed/unkey/tree/main/go).
</Callout>




### General Configuration

These settings define the fundamental properties of the server.

<Property name="platform" type="string" >
The platform this server is running on ("aws", "gcp", ...).

Most metrics include this information to help with troubleshooting and monitoring.
</Property>

<Property name="image" type="string">
The container image and version identifier for this instance.
</Property>

<Property name="httpPort" type="number">
The HTTP port where the server will listen for incoming connections. Defaults to 7070.
</Property>


<Property name="region" type="string">
Geographic region identifier where this server is deployed (e.g., "us-west-1")
</Property>

### Heartbeat Configuration
The API can send heartbeats to a destination to monitor its health.

<Property name="heartbeat" type="object">
Configuration for server health check reporting. Contains the following properties:

<Property name="url" type="string" required>
Endpoint URL where heartbeat signals will be sent (e.g., "http://monitor.example.com/heartbeat")
</Property>

<Property name="interval" type="number" required>
Time between heartbeat signals in seconds (e.g., 30 for checking every half minute)
</Property>
</Property>

### Cluster Configuration
Settings for cluster operation when running multiple server instances together.

<Property name="cluster" type="object">
Settings for multi-server cluster operations:

<Property name="nodeId" type="string">
Unique identifier for this node in the cluster (e.g., "node-1", "server-east-1")

If omitted, a random id will be generated.
</Property>

<Property name="advertiseAddr" type="string">
Network address other nodes will use to contact this node (e.g., "10.0.0.1", "node1.example.com")
</Property>

<Property name="rpcPort" type="string">
Port used for internal cluster communication via RPC. Defaults to "7071".
</Property>

<Property name="gossipPort" type="string">
Port used for cluster membership and state dissemination. Defaults to "7072".
</Property>

<Property name="discovery" type="object">
Configuration for how cluster nodes discover each other on startup.

Only one discovery method can be configured at a time.

<Property name="static" type="object">
Fixed list of cluster nodes for stable environments:

<Property name="addrs" type="string[]" required>
List of node addresses to connect to (e.g., ["node1:7071", "node2:7071"])
</Property>
</Property>

<Property name="redis" type="object">
Redis-based dynamic discovery for flexible environments.
All nodes will send heartbeats to the Redis server with their address.

<Property name="url" type="string" required>
Redis connection string (e.g., "redis://redis.example.com:6379")
</Property>
</Property>
</Property>
</Property>

### Logging and Monitoring
Configuration for observability and debugging capabilities.

<Property name="logs" type="object">
Logging configuration settings:

<Property name="color" type="boolean">
Enable colored output in log messages for better readability
</Property>
</Property>


### Database Configuration
Database connection settings for the server's data storage.

<Property name="database" type="object" required>
Database connection configuration:

<Property name="primary" type="string" required>
Primary database connection string for read and write operations (e.g., "postgresql://user:pass@localhost:5432/dbname")
</Property>

<Property name="readonlyReplica" type="string">
Optional read-only database replica for scaling read operations
</Property>
</Property>

### ClickHouse Configuration

<Property name="clickhouse" type="object">
ClickHouse integration for metrics and logging:

<Property name="url" type="string" required>
ClickHouse server connection string (e.g., "http://clickhouse:8123")
</Property>
</Property>
9 changes: 8 additions & 1 deletion deployment/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,19 @@ services:
dockerfile: ./Dockerfile
depends_on:
- mysql
- redis
- clickhouse
environment:
GOSSIP_PORT: 9090
RPC_PORT: 9091
DATABASE_PRIMARY_DSN: "mysql://unkey:password@tcp(mysql:3900)/unkey"
DATABASE_PRIMARY_DSN: "mysql://unkey:password@tcp(mysql:3900)/unkey?parseTime=true"
CLICKHOUSE_URL: "clickhouse://default:password@clickhouse:9000"
REDIS_URL: "redis://redis:6379"

redis:
image: redis:latest
ports:
- 6379:6379

agent:
command: ["/usr/local/bin/unkey", "agent", "--config", "config.docker.json"]
Expand Down
13 changes: 5 additions & 8 deletions go/.golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ run:
# Default: 1m
timeout: 3m


# This file contains only configs which differ from defaults.
# All possible options can be found here https://github.com/golangci/golangci-lint/blob/master/.golangci.reference.yml
linters-settings:
Expand Down Expand Up @@ -169,7 +168,7 @@ linters-settings:
nolintlint:
# Exclude following linters from requiring an explanation.
# Default: []
allow-no-explanation: [ funlen, gocognit, lll ]
allow-no-explanation: [funlen, gocognit, lll]
# Enable to require an explanation of nonzero length after each nolint directive.
# Default: false
require-explanation: true
Expand Down Expand Up @@ -217,7 +216,6 @@ linters-settings:
# Default: false
all: true


linters:
disable-all: true
enable:
Expand All @@ -241,14 +239,14 @@ linters:
- errname # checks that sentinel errors are prefixed with the Err and error types are suffixed with the Error
# - errorlint # finds code that will cause problems with the error wrapping scheme introduced in Go 1.13
- exhaustive # checks exhaustiveness of enum switch statements
- fatcontext # detects nested contexts in loops
# - fatcontext # detects nested contexts in loops
# - forbidigo # forbids identifiers
# - funlen # tool for detection of long functions
# - gocheckcompilerdirectives # validates go compiler directive comments (//go:)
# - gochecknoglobals # checks that no global variables exist
# # - gochecknoinits # checks that no init functions are present in Go code
- gochecksumtype # checks exhaustiveness on Go "sum types"
- gocognit # computes and checks the cognitive complexity of functions
# - gocognit # computes and checks the cognitive complexity of functions
- goconst # finds repeated strings that could be replaced by a constant
- gocritic # provides diagnostics that check for bugs, performance and style issues
# - gocyclo # computes and checks the cyclomatic complexity of functions
Expand Down Expand Up @@ -332,7 +330,6 @@ linters:
#- thelper # detects golang test helpers without t.Helper() call and checks the consistency of test helpers
#- wsl # [too strict and mostly code is not more readable] whitespace linter forces you to use empty lines


issues:
# Maximum count of issues with the same text.
# Set to 0 to disable.
Expand All @@ -341,9 +338,9 @@ issues:

exclude-rules:
- source: "(noinspection|TODO)"
linters: [ godot ]
linters: [godot]
- source: "//noinspection"
linters: [ gocritic ]
linters: [gocritic]
- path: "_test\\.go"
linters:
- bodyclose
Expand Down
1 change: 1 addition & 0 deletions go/Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ tasks:
- task: lint
test:
cmds:
- docker pull mysql:latest
- go test -cover -json -failfast ./... | tparse -all -progress

build:
Expand Down
1 change: 0 additions & 1 deletion go/api/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ output: ./gen.go
generate:
models: true


output-options:
nullable-type: true
Loading