Files
charybdis/docs/getting-started.md
T
Guillaume GRABÉ f1b1543f29
CI / Check (push) Successful in 13m13s
CI / Format (push) Successful in 48s
CI / Clippy (push) Successful in 12m13s
CI / Test (push) Successful in 12m45s
doc: update and cleanup
2026-06-09 11:26:47 +02:00

8.4 KiB

Getting Started with Charybdis

This guide gets you from zero to a running Charybdis instance: a software catalog with a gRPC API, optional Backstage YAML adapter, and plugin integrations on entity events.

Prerequisites

  • Rust 1.70+ (install)
  • PostgreSQL 14+
  • protoc + libprotobuf-dev (for the build script)
  • grpcurl for testing (optional, install)

Install

git clone <your-charybdis-repo-url>
cd charybdis
cargo build --release
# Binary at target/release/charybdis-server

Quick Start

1. Start PostgreSQL

docker run -d \
  --name charybdis-postgres \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 5432:5432 \
  postgres:15

2. Configure

cp config.toml.example config.toml
export DATABASE_URL="postgresql://postgres:mysecretpassword@localhost:5432/postgres"

config.toml reads ${DATABASE_URL} from the environment. See Configuration below for all options.

3. Run

cargo run

Expected startup logs:

INFO  charybdis: Database ready
INFO  charybdis: Event bus started successfully
INFO  charybdis: EntityService server listening on [::1]:50051

4. Verify

grpcurl -plaintext localhost:50051 list
# charybdis.entities.EntityService
# charybdis.ingestion.IngestionService
# grpc.reflection.v1.ServerReflection

Create Your First Entity

grpcurl -plaintext -d '{
  "entity": {
    "kind": "Component",
    "component_metadata": {
      "name": "payment-api",
      "namespace": "production",
      "description": "Payment processing service",
      "tags": ["api", "critical"]
    },
    "component_spec": {
      "type": "service",
      "lifecycle": "production",
      "owner": "team-payments"
    }
  }
}' localhost:50051 charybdis.entities.EntityService/CreateEntity

Response:

{
  "entity": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "kind": "Component",
    "componentMetadata": { "...": "..." },
    "createdAt": "2026-06-01T10:00:00Z",
    "updatedAt": "2026-06-01T10:00:00Z"
  }
}

Retrieve and list

# Get by ID
grpcurl -plaintext \
  -d '{"id": "550e8400-e29b-41d4-a716-446655440000"}' \
  localhost:50051 charybdis.entities.EntityService/GetEntity

# List all
grpcurl -plaintext -d '{}' \
  localhost:50051 charybdis.entities.EntityService/ListEntities

# Filter by kind and name
grpcurl -plaintext \
  -d '{"kind": "Component", "name": "payment-api"}' \
  localhost:50051 charybdis.entities.EntityService/ListEntities

Entity Kinds

The valid kind values are: Component, System, API, User, Group, Domain, Resource, Finding. Each kind uses a matching <kind>_metadata + <kind>_spec payload.

Conceptual reference: core-concepts.md. Per-kind protobuf definitions: proto/core/*.proto.

Component example with metadata and annotations

grpcurl -plaintext -d '{
  "entity": {
    "kind": "Component",
    "component_metadata": {
      "name": "payment-service",
      "namespace": "production",
      "description": "Payment processing",
      "labels": { "team": "payments", "tier": "critical" },
      "links": [{
        "url": "https://dashboard.company.com/payments",
        "title": "Dashboard",
        "icon": "dashboard"
      }],
      "tags": ["payments", "pci-compliant"]
    },
    "component_spec": {
      "type": "service",
      "lifecycle": "production",
      "owner": "team-payments"
    },
    "annotations": {
      "github.com/repo-slug": "myorg/payment-service",
      "pagerduty.com/service-id": "PXYZ123"
    }
  }
}' localhost:50051 charybdis.entities.EntityService/CreateEntity

Registering Entities from CI

Charybdis is designed to be called from pipelines. With grpcurl available in your runner:

# Example pipeline step (Gitea Actions / GitHub Actions syntax)
- name: Register service in Charybdis
  run: |
    grpcurl -plaintext \
      -d "{
        \"entity\": {
          \"kind\": \"Component\",
          \"component_metadata\": {
            \"name\": \"$CI_PROJECT_NAME\",
            \"namespace\": \"production\"
          },
          \"component_spec\": {
            \"type\": \"service\",
            \"lifecycle\": \"production\",
            \"owner\": \"$CI_PROJECT_NAMESPACE\"
          },
          \"annotations\": {
            \"repo-slug\": \"$CI_PROJECT_PATH\"
          }
        }
      }" \
      charybdis.internal:50051 \
      charybdis.entities.EntityService/CreateEntity

In production, secure the endpoint with mTLS (see Enabling Security).

Enabling Security

Charybdis ships with mTLS + RBAC disabled for local exploration. For shared or production environments, enable both.

1. Generate dev certificates

./deploy/scripts/generate-dev-certs.sh

This writes deploy/certs/ with:

  • ca.pem — CA
  • server-cert.pem / server-key.pem — server
  • admin-cert.pem / admin-key.pem — admin client
  • (and per-role client certs)

2. Enable in config.toml

[security.mtls]
enabled = true
server_cert = "./deploy/certs/server-cert.pem"
server_key  = "./deploy/certs/server-key.pem"
client_ca_cert = "./deploy/certs/ca.pem"

[security.rbac]
enabled = true

Restart Charybdis. RBAC defaults map cert OUs to roles (platform-team → full access, automation → CRUD without delete, plugins → read-only).

3. Call with mTLS

grpcurl \
  -cacert deploy/certs/ca.pem \
  -cert deploy/certs/admin-cert.pem \
  -key deploy/certs/admin-key.pem \
  -d '{}' \
  localhost:50051 charybdis.entities.EntityService/ListEntities

Full reference (custom role mappings, audit logging, reverse-proxy mode): security.md.

Backstage Migration (Optional)

If you currently run Backstage, Charybdis serves entities in Backstage's Location YAML format:

# backstage app-config.yaml
catalog:
  locations:
    - type: url
      target: http://your-charybdis-host:8080/yaml/locations
      rules:
        - allow: [Component, System, API, User, Group]

Backstage discovers entities by polling the endpoint. Entities created via gRPC are visible on the next poll. The YAML adapter is served by an HTTP listener separate from the gRPC port (default :8080).

Configuration

Charybdis loads its config from (in order):

  1. ./config.toml
  2. ./charybdis.toml
  3. /etc/charybdis/config.toml
  4. Environment variables (fallback)

config.toml skeleton

[server]
grpc_host = "[::1]"
grpc_port = 50051

[server.yaml_adapter]
enabled = true
host = "0.0.0.0"
port = 8080

[database]
url = "${DATABASE_URL}"
max_connections = 10
connection_timeout_secs = 30

[security.mtls]
enabled = false

[security.rbac]
enabled = false

[telemetry]
service_name = "charybdis"
environment = "development"
enable_console = true

[plugins.defectdojo]
enabled = false
# see plugins/README.md for the full plugin reference

${VAR} and ${VAR:-default} substitution works in any string value — keep secrets in the environment, not in the file.

Environment-variable fallback

If no config file is found, these env vars are read:

Variable Default Description
DATABASE_URL (required) PostgreSQL connection string
GRPC_HOST [::1] gRPC bind address
GRPC_PORT 50051 gRPC port
RUST_LOG info Logging level filter
SECURITY_MTLS_ENABLED false Enable mTLS
SECURITY_RBAC_ENABLED false Enable RBAC
OTEL_ENABLE_CONSOLE true Console exporter
OTEL_SERVICE_NAME charybdis Service name for telemetry

See config.toml.example for the complete template.

Troubleshooting

Port already in use

Error: transport error

Find and free port 50051: lsof -ti:50051 | xargs kill, or set GRPC_PORT=50052.

Database connection failed

Verify the URL: psql "$DATABASE_URL" -c "SELECT 1;".

Permission denied with security enabled

Code: PermissionDenied
Message: Role 'X' does not have permission 'Y'

Inspect your cert subject (OU determines the role) and the [security.rbac.permissions] table in config.toml. Reference: security.md.

Next Steps