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— CAserver-cert.pem/server-key.pem— serveradmin-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):
./config.toml./charybdis.toml/etc/charybdis/config.toml- 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
- Core Concepts — entity model, events, annotations
- Architecture — protobuf schema, storage, event bus
- Plugins — DefectDojo, Keycloak, writing your own
- Vision & Roadmap — where Charybdis is going