My PaaS for hosting multiple elasticsearch clusters in a Kubernetes environment.
JavaScript 36%
Go 34%
TypeScript 14%
CSS 8%
Just 4%
HCL 2%
Shell 2%
Go Template <1%
Dockerfile <1%
HTML <1%
<1%

README.md

Built A Cloud #

This project was created as part of the "Built a Cloud" track at Level3. It's a facade API for provisioning and managing Elasticsearch deployments on Kubernetes via the ECK operator, plus document indexing and search.

Features #

  • Auth: Argon2id password hashing + PASETO v4 local tokens (24h). Optional invite-only registration via the INVITE_CODE build flag.
  • Elasticsearch lifecycle: create / get / list / delete ES clusters through the ECK Elasticsearch CR. Owner isolation via the paas-instance-owner label.
  • Search: index, search (wildcard), delete documents; list indices. Default index default.
  • Audit log: per-instance operation history (GetInstanceLogs).
  • Observability in-cluster: OTel traces to Tempo, Prometheus metrics at /metrics, structured JSON logs to Loki.

Domains #

Domain Serves
pagedb.stackit.gg Backend API + embedded SPA (TLS terminated at Traefik Gateway)
moni.pagedb.stackit.gg Grafana

SDK (Go) #

Setup your project to pull from the private Git Repo:

  1. Go here to create a new Access Token
  2. Tell Git to use the token to fetch stuff from that URL using that token:
git config url."https://<your_token>@level3.git.onstackit.cloud".insteadOf "https://level3.git.onstackit.cloud"
  1. Install the SDK:
go get level3.git.onstackit.cloud/LEVEL3/gabriel/src/sdk
  1. Create your beautiful client, potentially something like this (pls pls, handle errors 😄):
import "level3.git.onstackit.cloud/LEVEL3/gabriel/src/sdk"
ctx := context.Background()
c, _ := sdk.NewClient("https://pagedb.stackit.gg", "")
reg, _ := c.Register(ctx, "alice", "s3cureP@ssw0rd", "sunset-rocket-42") // invite code only in invite-only mode

authed, _ := sdk.NewClient("https://pagedb.stackit.gg", reg.Token)
inst, _ := authed.CreateInstance(ctx, "my-es")
_,  _ = authed.StoreDocument(ctx, inst.ID, model.IndexDocReq{Text: "hello world"})
docs, _ := authed.SearchDocuments(ctx, inst.ID, model.SearchQuery{Query: "hello"})

Full lifecycle (register → login → provision → index → search → list indices → delete doc → delete instance) in src/sdk/example_test.go.

Documentation #

Doc Covers
docs/infra.md Terraform + Kubernetes manifests, TLS/DNS, deployment template, observability stack — with mermaid resource graphs
docs/backend.md Request path, components, in-memory state, ES instance model, full API table, OTel endpoint + custom metrics
docs/cicd.md justfile recipes by group, image build, typical flows, Forgejo Actions CI

Tech stack #

  • Backend: Go 1.26, ECK v3.4.1, oapi-codegen, Argon2id, PASETO v4, controller-runtime k8s client, go-elasticsearch v8
  • Frontend: SolidJS, Pico CSS, Deno, Vite
  • Infra: STACKIT SKE (Terraform), Kubernetes, Gateway API (Traefik), cert-manager + STACKIT DNS-01 webhook
  • Observability: OpenTelemetry (traces only), Prometheus, Loki, Promtail, Tempo, Grafana