Skip to main content

Terraform Provider

Manage SixDegree resources using infrastructure-as-code with Terraform.

GitHub Repository | Terraform Registry

Overview

The SixDegree Terraform provider allows you to define and manage your SixDegree infrastructure as code. Instead of manually configuring discovery providers, MCP endpoints, model providers, and other resources through the UI or API, you can declare your entire configuration in Terraform and manage it with version control.

Why use Terraform for SixDegree?

  • Declarative Configuration: Define your entire SixDegree setup in code, making it easy to understand and reproduce
  • Version Control: Track changes to your infrastructure configuration over time
  • Reproducibility: Easily spin up identical environments for development, staging, and production
  • Team Collaboration: Share and review infrastructure changes through pull requests
  • Automation: Integrate with CI/CD pipelines to automatically provision and update resources
  • Consistency: Avoid configuration drift and manual errors by managing everything through code

Common use cases include:

  • Setting up discovery providers for GitHub, GitLab, Argo CD, and Docker registries
  • Configuring MCP endpoints with custom authentication and tool permissions
  • Managing model providers (OpenAI, Anthropic, xAI) and their associated models
  • Creating chat suggestions and OAuth service configurations
  • Provisioning complete environments with all necessary integrations

Installation

Add to your Terraform configuration:

terraform {
required_providers {
sixdegree = {
source = "sixdegreeai/sixdegree"
}
}
}

provider "sixdegree" {
host = "https://api.sixdegree.ai"
access_token = var.sixdegree_access_token
}

Authentication

The provider supports three authentication methods:

data "external" "sixdegree_auth" {
program = ["bash", "-c", "echo '{\"token\":\"'$(sixdegree auth token)'\"}'"]
}

provider "sixdegree" {
host = "https://api.sixdegree.ai"
access_token = data.external.sixdegree_auth.result.token
}

Option 2: Environment Variables

export SIXDEGREE_ACCESS_TOKEN=$(sixdegree auth token)
export SIXDEGREE_HOST="https://api.sixdegree.ai"
provider "sixdegree" {
# Automatically uses environment variables
}

Option 3: Direct Configuration

provider "sixdegree" {
host = "https://api.sixdegree.ai"
access_token = var.sixdegree_access_token
}

Resources

Environment

Manages an environment in SixDegree.

resource "sixdegree_environment" "production" {
name = "Production"
instance_url = "https://prod.sixdegree.ai"
stripe_subscription_id = "sub_xxxxx"

invited_users = [
"user1@example.com",
"user2@example.com"
]
}

MCP Endpoint

Manages an MCP (Model Context Protocol) endpoint configuration.

resource "sixdegree_mcp_endpoint" "example" {
name = "PostgreSQL Tools"
url = "https://mcp-postgres.example.com/v1"
description = "PostgreSQL database tools"

headers = {
"X-Custom-Header" = "value"
}

sixdegree_auth = false
supports_resources = true
active = true

allowed_tools = ["query", "execute"]
denied_tools = ["drop_table"]
}

For OAuth authentication:

resource "sixdegree_mcp_endpoint" "github" {
name = "GitHub MCP"
url = "https://mcp-github.example.com"
oauth_service_id = sixdegree_oauth_service.github.id
active = true
}

Model Provider

Manages model provider configurations (OpenAI, Anthropic, xAI).

resource "sixdegree_model_provider" "anthropic" {
type = "anthropic"
name = "Anthropic Claude"
api_key = var.anthropic_api_key
default = true
}

resource "sixdegree_model_provider" "openai" {
type = "openai"
name = "OpenAI"
api_key = var.openai_api_key
default = false
}

resource "sixdegree_model_provider" "xai" {
type = "xai"
name = "xAI Grok"
api_key = var.xai_api_key
default = false
}

Model

Manages model configurations.

resource "sixdegree_model" "claude_opus" {
name = "claude-3-opus-20240229"
description = "Claude 3 Opus model"
provider_id = sixdegree_model_provider.anthropic.id
default = true
}

resource "sixdegree_model" "gpt4" {
name = "gpt-4"
description = "GPT-4 model"
provider_id = sixdegree_model_provider.openai.id
default = false
}

Discovery Provider

Manages discovery providers that continuously discover entities and relations from external systems.

resource "sixdegree_discovery_provider" "github" {
name = "GitHub Production"
provider_type = "github"
enabled = true
interval = 300 # 5 minutes (minimum 60 seconds)

config = jsonencode({
token = var.github_token
selectors = [
{
organization = "myorg"
repo_name = ".*"
}
]
})
}

resource "sixdegree_discovery_provider" "argo" {
name = "Argo CD Staging"
provider_type = "argo"
enabled = true
interval = 300

config = jsonencode({
api_url = "https://argocd.example.com/api/v1/"
token = var.argo_token
})
}

resource "sixdegree_discovery_provider" "docker" {
name = "GHCR Docker Registry"
provider_type = "docker"
enabled = true
interval = 600

config = jsonencode({
registry_type = "ghcr"
api_url = "https://ghcr.io/"
username = "myusername"
token = var.docker_token
selectors = [
{
namespace_pattern = "myorg"
repository_pattern = "^(app1|app2)$"
max_tags = 10
exclude_tags = [".*-dev.*", "latest"]
}
]
})
}

Supported provider types:

  • github - GitHub repositories, issues, pull requests
  • gitlab - GitLab projects and resources
  • argo - Argo CD applications
  • vercel - Vercel deployments
  • docker - Docker registries (Docker Hub, GHCR, ECR)
  • file - File-based discovery
  • fossa - FOSSA license compliance
  • meta - Meta integrations

OAuth Service

Manages OAuth service configurations for authenticating with external services.

resource "sixdegree_oauth_service" "github" {
name = "GitHub OAuth"
provider_type = "github"
client_id = var.github_oauth_client_id
client_secret = var.github_oauth_client_secret
redirect_uri = "https://app.sixdegree.ai/oauth/callback"
}

Chat Suggestion

Manages chat suggestions that appear in the SixDegree chat interface.

resource "sixdegree_chat_suggestion" "onboarding" {
title = "Getting Started"
description = "Learn about your infrastructure"
prompt = "Show me an overview of all my repositories and their recent activity"
icon = "rocket"
category = "onboarding"
order = 1
}

Complete Example

terraform {
required_providers {
sixdegree = {
source = "sixdegreeai/sixdegree"
}
}
}

variable "sixdegree_access_token" {
type = string
sensitive = true
}

variable "github_token" {
type = string
sensitive = true
}

variable "anthropic_api_key" {
type = string
sensitive = true
}

variable "db_mcp_token" {
type = string
sensitive = true
}

# Provider configuration
provider "sixdegree" {
host = "https://api.sixdegree.ai"
access_token = var.sixdegree_access_token
}

# Configure GitHub discovery
resource "sixdegree_discovery_provider" "github" {
name = "GitHub Production"
provider_type = "github"
enabled = true
interval = 300

config = jsonencode({
token = var.github_token
selectors = [
{
organization = "myorg"
repo_name = ".*"
}
]
})
}

# Configure Anthropic model provider
resource "sixdegree_model_provider" "anthropic" {
type = "anthropic"
name = "Anthropic Claude"
api_key = var.anthropic_api_key
default = true
}

# Enable Claude Opus
resource "sixdegree_model" "claude_opus" {
name = "claude-3-opus-20240229"
description = "Claude 3 Opus model"
provider_id = sixdegree_model_provider.anthropic.id
default = true
}

# MCP endpoint
resource "sixdegree_mcp_endpoint" "database_tools" {
name = "Database Tools"
url = "https://mcp-db.example.com"
description = "PostgreSQL tools for querying databases"

headers = {
"Authorization" = "Bearer ${var.db_mcp_token}"
}

sixdegree_auth = false
supports_resources = true
active = true

allowed_tools = ["query", "list_tables", "describe_table"]
}

# Chat suggestion
resource "sixdegree_chat_suggestion" "repos_overview" {
title = "Repository Overview"
description = "Get an overview of all repositories"
prompt = "Show me all repositories and their recent activity"
icon = "git-branch"
category = "repositories"
order = 1
}

output "model_provider_id" {
value = sixdegree_model_provider.anthropic.id
}

output "mcp_endpoint_id" {
value = sixdegree_mcp_endpoint.database_tools.id
}

Best Practices

Use Variables for Sensitive Data

Always store sensitive data in variables marked as sensitive:

variable "sixdegree_access_token" {
type = string
sensitive = true
}

variable "github_token" {
type = string
sensitive = true
}

Use External Data Source for CLI Integration

For the best developer experience, use the external data source to fetch tokens from the SixDegree CLI:

data "external" "sixdegree_auth" {
program = ["bash", "-c", "echo '{\"token\":\"'$(sixdegree auth token)'\"}'"]
}

provider "sixdegree" {
access_token = data.external.sixdegree_auth.result.token
}

Remote State

Use remote state for team collaboration:

terraform {
backend "s3" {
bucket = "terraform-state"
key = "sixdegree/production"
region = "us-east-1"
}
}

Organize with Modules

Create reusable modules for common patterns:

module "sixdegree_monitoring" {
source = "./modules/sixdegree-monitoring"

github_token = var.github_token
anthropic_api_key = var.anthropic_api_key
environment_id = var.environment_id
}

Use jsonencode for Complex Config

When configuring discovery providers, use jsonencode() to ensure proper JSON formatting:

config = jsonencode({
token = var.token
selectors = [
{ organization = "myorg" }
]
})

Data Sources

Data sources allow you to reference existing SixDegree resources.

sixdegree_environment

data "sixdegree_environment" "production" {
name = "Production"
}

output "environment_id" {
value = data.sixdegree_environment.production.id
}

sixdegree_model_provider

data "sixdegree_model_provider" "anthropic" {
type = "anthropic"
}

resource "sixdegree_model" "claude" {
provider_id = data.sixdegree_model_provider.anthropic.id
name = "claude-3-5-sonnet-20241022"
}

Importing Existing Resources

Import existing SixDegree resources into Terraform state.

Import Environment

terraform import sixdegree_environment.production env_abc123

Import Discovery Provider

terraform import sixdegree_discovery_provider.github dp_xyz789

Import MCP Endpoint

terraform import sixdegree_mcp_endpoint.example mcp_abc123

Import Model Provider

terraform import sixdegree_model_provider.anthropic mp_xyz789

Bulk Import

Create a script to import multiple resources:

#!/bin/bash

# Import all environments
terraform import sixdegree_environment.production env_prod123
terraform import sixdegree_environment.staging env_stag456

# Import discovery providers
terraform import sixdegree_discovery_provider.github dp_github001
terraform import sixdegree_discovery_provider.gitlab dp_gitlab002

# Import model providers
terraform import sixdegree_model_provider.anthropic mp_anthropic001
terraform import sixdegree_model_provider.openai mp_openai002

State Management

Remote State Backend

Configure remote state for team collaboration:

terraform {
backend "s3" {
bucket = "my-terraform-state"
key = "sixdegree/production/terraform.tfstate"
region = "us-east-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}

State Locking

Use DynamoDB for state locking with S3 backend:

resource "aws_dynamodb_table" "terraform_locks" {
name = "terraform-locks"
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"

attribute {
name = "LockID"
type = "S"
}
}

State Migration

Migrate existing resources to new modules:

# Move resource to module
terraform state mv sixdegree_discovery_provider.github module.github.sixdegree_discovery_provider.main

# Remove resource from state (without destroying)
terraform state rm sixdegree_chat_suggestion.old

# Import into new location
terraform import module.suggestions.sixdegree_chat_suggestion.main cs_abc123

Testing Terraform Configurations

Validation

# Format check
terraform fmt -check

# Validate configuration
terraform validate

# Plan without applying
terraform plan -out=plan.tfplan

# Review plan
terraform show plan.tfplan

Testing Frameworks

Use Terratest for automated testing:

package test

import (
"testing"

"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
)

func TestSixDegreeInfrastructure(t *testing.T) {
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: "../examples/complete",
Vars: map[string]interface{}{
"sixdegree_access_token": getTestToken(),
},
})

defer terraform.Destroy(t, terraformOptions)

terraform.InitAndApply(t, terraformOptions)

// Verify outputs
environmentID := terraform.Output(t, terraformOptions, "environment_id")
assert.NotEmpty(t, environmentID)
}

Pre-commit Hooks

Add .pre-commit-config.yaml:

repos:
- repo: https://github.com/antonbabenko/pre-commit-terraform
rev: v1.83.5
hooks:
- id: terraform_fmt
- id: terraform_validate
- id: terraform_docs
- id: terraform_tflint

CI/CD Integration

GitHub Actions

name: Terraform

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
terraform:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.6.0

- name: Terraform Format
run: terraform fmt -check

- name: Terraform Init
run: terraform init
env:
TF_VAR_sixdegree_access_token: ${{ secrets.SIXDEGREE_TOKEN }}

- name: Terraform Validate
run: terraform validate

- name: Terraform Plan
run: terraform plan -out=plan.tfplan
env:
TF_VAR_sixdegree_access_token: ${{ secrets.SIXDEGREE_TOKEN }}
TF_VAR_github_token: ${{ secrets.GITHUB_TOKEN }}

- name: Terraform Apply
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
run: terraform apply -auto-approve plan.tfplan
env:
TF_VAR_sixdegree_access_token: ${{ secrets.SIXDEGREE_TOKEN }}

GitLab CI

variables:
TF_ROOT: ${CI_PROJECT_DIR}/terraform
TF_STATE_NAME: ${CI_PROJECT_NAME}

stages:
- validate
- plan
- apply

before_script:
- cd ${TF_ROOT}
- terraform init

validate:
stage: validate
script:
- terraform fmt -check
- terraform validate

plan:
stage: plan
script:
- terraform plan -out=plan.tfplan
artifacts:
paths:
- ${TF_ROOT}/plan.tfplan
expire_in: 1 week
only:
- merge_requests

apply:
stage: apply
script:
- terraform apply -auto-approve plan.tfplan
dependencies:
- plan
only:
- main

Troubleshooting

Common Issues

Authentication Failures:

# Verify token is valid
export SIXDEGREE_ACCESS_TOKEN=$(degree auth token)
degree whoami

# Check token in Terraform
terraform console
> var.sixdegree_access_token

Provider Not Found:

# Clear plugin cache
rm -rf .terraform

# Reinitialize
terraform init

Resource Already Exists:

# Import existing resource
terraform import sixdegree_discovery_provider.github dp_existing123

# Or remove from state and recreate with different name
terraform state rm sixdegree_discovery_provider.github

Configuration Drift:

# Check for drift
terraform plan

# Refresh state
terraform refresh

# Force recreation
terraform taint sixdegree_discovery_provider.github
terraform apply

Debugging

Enable debug logging:

export TF_LOG=DEBUG
export TF_LOG_PATH=terraform.log

terraform apply

View provider requests:

export TF_LOG_PROVIDER=TRACE
terraform apply

Advanced Patterns

Dynamic Configuration

Use for_each for multiple similar resources:

variable "discovery_providers" {
type = map(object({
type = string
interval = number
config = map(string)
}))
}

resource "sixdegree_discovery_provider" "providers" {
for_each = var.discovery_providers

name = each.key
provider_type = each.value.type
enabled = true
interval = each.value.interval
config = jsonencode(each.value.config)
}

Conditional Resources

variable "enable_github_discovery" {
type = bool
default = true
}

resource "sixdegree_discovery_provider" "github" {
count = var.enable_github_discovery ? 1 : 0

name = "GitHub"
provider_type = "github"
enabled = true
interval = 300
config = jsonencode({ token = var.github_token })
}

Module Composition

module "discovery" {
source = "./modules/discovery"

github_token = var.github_token
gitlab_token = var.gitlab_token
argo_token = var.argo_token
}

module "models" {
source = "./modules/models"

anthropic_api_key = var.anthropic_api_key
openai_api_key = var.openai_api_key
}

module "mcp" {
source = "./modules/mcp"

database_token = var.database_token
slack_token = var.slack_token
}

Development

Local Development Setup

To use a locally built provider:

  1. Build the provider:

    cd terraform-provider-sixdegree
    go build -o terraform-provider-sixdegree
  2. Create ~/.terraformrc:

    provider_installation {
    dev_overrides {
    "sixdegreeai/sixdegree" = "/path/to/terraform-provider-sixdegree"
    }
    direct {}
    }
  3. Run Terraform commands as usual. Terraform will use your local build.

Documentation Generation

The provider uses tfplugindocs to auto-generate documentation from schema and examples:

# Generate docs
make docs

# Validate docs
make docs-validate

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Run tests: make test
  6. Submit pull request

Additional Resources