Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 8 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ NEXT_SERVER_API_URL=${INTERNAL_API_URL}
TRACECAT__APP_ENV=development
# Used to encrypt/decrypt sensitive keys in the database
# Can be generated using `python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"`
# Required
TRACECAT__DB_ENCRYPTION_KEY=your-tracecat-db-fernet-key
# Used to authenticate with Tracecat services
# Can be generated using `openssl rand -hex 32`
# Required
TRACECAT__SERVICE_KEY=your-tracecat-service-key
TRACECAT__EXECUTOR_TOKEN_TTL_SECONDS=900
# Used to generate private webhook URLs
# Can be generated using `openssl rand -hex 32`
# Required
TRACECAT__SIGNING_SECRET=your-tracecat-signing-secret
# API Service URL
TRACECAT__API_URL=${INTERNAL_API_URL}
Expand Down Expand Up @@ -74,8 +77,11 @@ TRACECAT__AUTH_ALLOWED_DOMAINS=
TRACECAT__AUTH_MIN_PASSWORD_LENGTH=12

# OIDC / OAuth
# Required when `TRACECAT__AUTH_TYPES` includes `oidc`
OIDC_ISSUER=
# Required when `TRACECAT__AUTH_TYPES` includes `oidc`
OIDC_CLIENT_ID=
# Required when `TRACECAT__AUTH_TYPES` includes `oidc`
OIDC_CLIENT_SECRET=
OIDC_SCOPES="openid profile email"

Expand All @@ -93,8 +99,9 @@ TRACECAT_MCP__STARTUP_RETRY_DELAY_SECONDS=2
OAUTH_CLIENT_ID=
OAUTH_CLIENT_SECRET=

# Used for password reset and email verification tokens
# Used for password reset, email verification, and OIDC/OAuth state tokens
# Can be generated using `openssl rand -hex 32`
# Required
USER_AUTH_SECRET=your-auth-secret

# SAML SSO settings
Expand Down
74 changes: 37 additions & 37 deletions deployments/fargate/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -122,28 +122,28 @@ module "ecs" {
temporal_api_key_arn = var.temporal_api_key_arn

# Compute / memory
api_cpu = var.api_cpu
api_memory = var.api_memory
worker_cpu = var.worker_cpu
worker_memory = var.worker_memory
worker_desired_count = var.worker_desired_count
agent_worker_cpu = var.agent_worker_cpu
agent_worker_memory = var.agent_worker_memory
agent_worker_desired_count = var.agent_worker_desired_count
agent_queue = var.agent_queue
executor_cpu = var.executor_cpu
executor_memory = var.executor_memory
executor_desired_count = var.executor_desired_count
executor_client_timeout = var.executor_client_timeout
executor_queue = var.executor_queue
executor_worker_pool_size = var.executor_worker_pool_size
agent_executor_cpu = var.agent_executor_cpu
agent_executor_memory = var.agent_executor_memory
agent_executor_desired_count = var.agent_executor_desired_count
agent_executor_queue = var.agent_executor_queue
agent_executor_max_concurrent_activities = var.agent_executor_max_concurrent_activities
agent_executor_worker_pool_size = var.agent_executor_worker_pool_size
llm_proxy_read_timeout = var.llm_proxy_read_timeout
api_cpu = var.api_cpu
api_memory = var.api_memory
worker_cpu = var.worker_cpu
worker_memory = var.worker_memory
worker_desired_count = var.worker_desired_count
agent_worker_cpu = var.agent_worker_cpu
agent_worker_memory = var.agent_worker_memory
agent_worker_desired_count = var.agent_worker_desired_count
agent_queue = var.agent_queue
executor_cpu = var.executor_cpu
executor_memory = var.executor_memory
executor_desired_count = var.executor_desired_count
executor_client_timeout = var.executor_client_timeout
executor_queue = var.executor_queue
executor_worker_pool_size = var.executor_worker_pool_size
agent_executor_cpu = var.agent_executor_cpu
agent_executor_memory = var.agent_executor_memory
agent_executor_desired_count = var.agent_executor_desired_count
agent_executor_queue = var.agent_executor_queue
agent_executor_max_concurrent_activities = var.agent_executor_max_concurrent_activities
agent_executor_worker_pool_size = var.agent_executor_worker_pool_size
llm_proxy_read_timeout = var.llm_proxy_read_timeout
llm_gateway_credential_cache_ttl_seconds = var.llm_gateway_credential_cache_ttl_seconds
llm_gateway_healthcheck_interval_seconds = var.llm_gateway_healthcheck_interval_seconds
llm_gateway_healthcheck_timeout_seconds = var.llm_gateway_healthcheck_timeout_seconds
Expand All @@ -153,21 +153,21 @@ module "ecs" {
llm_gateway_healthcheck_pool_timeout_seconds = var.llm_gateway_healthcheck_pool_timeout_seconds
llm_gateway_healthcheck_failure_threshold = var.llm_gateway_healthcheck_failure_threshold
llm_gateway_status_log_interval_seconds = var.llm_gateway_status_log_interval_seconds
ui_cpu = var.ui_cpu
ui_memory = var.ui_memory
temporal_cpu = var.temporal_cpu
temporal_memory = var.temporal_memory
temporal_num_history_shards = var.temporal_num_history_shards
temporal_db_tls_enabled = var.temporal_db_tls_enabled
temporal_db_tls_enable_host_verification = var.temporal_db_tls_enable_host_verification
temporal_db_force_ssl = var.temporal_db_force_ssl
caddy_cpu = var.caddy_cpu
caddy_memory = var.caddy_memory
tracecat_db_instance_class = local.tracecat_db_instance_class
temporal_db_instance_class = local.temporal_db_instance_class
tracecat_db_allocated_storage = local.tracecat_db_allocated_storage
temporal_db_allocated_storage = local.temporal_db_allocated_storage
db_engine_version = var.db_engine_version
ui_cpu = var.ui_cpu
ui_memory = var.ui_memory
temporal_cpu = var.temporal_cpu
temporal_memory = var.temporal_memory
temporal_num_history_shards = var.temporal_num_history_shards
temporal_db_tls_enabled = var.temporal_db_tls_enabled
temporal_db_tls_enable_host_verification = var.temporal_db_tls_enable_host_verification
temporal_db_force_ssl = var.temporal_db_force_ssl
caddy_cpu = var.caddy_cpu
caddy_memory = var.caddy_memory
tracecat_db_instance_class = local.tracecat_db_instance_class
temporal_db_instance_class = local.temporal_db_instance_class
tracecat_db_allocated_storage = local.tracecat_db_allocated_storage
temporal_db_allocated_storage = local.temporal_db_allocated_storage
db_engine_version = var.db_engine_version

# MCP Service
enable_mcp = var.enable_mcp
Expand Down
25 changes: 12 additions & 13 deletions deployments/fargate/modules/ecs/secrets.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# 1. TRACECAT__DB_ENCRYPTION_KEY
# 2. TRACECAT__SERVICE_KEY
# 3. TRACECAT__SIGNING_SECRET
# 4. USER_AUTH_SECRET
#
# Optional secrets:
# 1. OAUTH_CLIENT_ID (legacy OIDC alias)
Expand All @@ -20,6 +21,10 @@ data "aws_secretsmanager_secret" "tracecat_signing_secret" {
arn = var.tracecat_signing_secret_arn
}

data "aws_secretsmanager_secret" "user_auth_secret" {
arn = var.user_auth_secret_arn
}

### Optional secrets

# Tracecat authentication
Expand All @@ -44,11 +49,6 @@ data "aws_secretsmanager_secret" "oidc_client_secret" {
arn = var.oidc_client_secret_arn
}

data "aws_secretsmanager_secret" "user_auth_secret" {
count = var.user_auth_secret_arn != null ? 1 : 0
arn = var.user_auth_secret_arn
}

data "aws_secretsmanager_secret" "saml_idp_metadata_url" {
count = var.saml_idp_metadata_url_arn != null ? 1 : 0
arn = var.saml_idp_metadata_url_arn
Expand Down Expand Up @@ -97,6 +97,10 @@ data "aws_secretsmanager_secret_version" "tracecat_signing_secret" {
secret_id = data.aws_secretsmanager_secret.tracecat_signing_secret.id
}

data "aws_secretsmanager_secret_version" "user_auth_secret" {
secret_id = data.aws_secretsmanager_secret.user_auth_secret.id
}

data "aws_secretsmanager_secret_version" "oauth_client_id" {
count = var.oauth_client_id_arn != null ? 1 : 0
secret_id = data.aws_secretsmanager_secret.oauth_client_id[0].id
Expand All @@ -117,11 +121,6 @@ data "aws_secretsmanager_secret_version" "oidc_client_secret" {
secret_id = data.aws_secretsmanager_secret.oidc_client_secret[0].id
}

data "aws_secretsmanager_secret_version" "user_auth_secret" {
count = var.user_auth_secret_arn != null ? 1 : 0
secret_id = data.aws_secretsmanager_secret.user_auth_secret[0].id
}

data "aws_secretsmanager_secret_version" "saml_idp_metadata_url" {
count = var.saml_idp_metadata_url_arn != null ? 1 : 0
secret_id = data.aws_secretsmanager_secret.saml_idp_metadata_url[0].id
Expand Down Expand Up @@ -236,12 +235,12 @@ locals {
}
] : []

user_auth_secret_secret = var.user_auth_secret_arn != null ? [
user_auth_secret_secret = [
{
name = "USER_AUTH_SECRET"
valueFrom = data.aws_secretsmanager_secret_version.user_auth_secret[0].arn
valueFrom = data.aws_secretsmanager_secret_version.user_auth_secret.arn
}
] : []
]

saml_idp_metadata_url_secret = var.saml_idp_metadata_url_arn != null ? [
{
Expand Down
3 changes: 1 addition & 2 deletions deployments/fargate/modules/ecs/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -335,8 +335,7 @@ variable "oidc_client_secret_arn" {

variable "user_auth_secret_arn" {
type = string
description = "The ARN of the secret containing USER_AUTH_SECRET (optional)"
default = null
description = "The ARN of the secret containing USER_AUTH_SECRET"
}

variable "saml_idp_metadata_url_arn" {
Expand Down
6 changes: 5 additions & 1 deletion deployments/fargate/scripts/create-aws-secrets.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ if [ -z "$AWS_DEFAULT_REGION" ]; then
exit 1
fi

# Create service key and signing secret
# Create service key, signing secret, and user auth secret
SERVICE_KEY=$(openssl rand -hex 32)
SIGNING_SECRET=$(openssl rand -hex 32)
USER_AUTH_SECRET=$(openssl rand -hex 32)

# Create database encryption key
DB_ENCRYPTION_KEY=$(openssl rand 32 | base64 | tr -d '\n' | tr '+/' '-_')
Expand All @@ -20,13 +21,16 @@ DB_ENCRYPTION_KEY=$(openssl rand 32 | base64 | tr -d '\n' | tr '+/' '-_')
DB_ENCRYPTION_KEY_NAME=${DB_ENCRYPTION_KEY_NAME:-"${APP_ENV:-prod}/tracecat/db-encryption-key"}
SERVICE_KEY_NAME=${SERVICE_KEY_NAME:-"${APP_ENV:-prod}/tracecat/service-key"}
SIGNING_SECRET_NAME=${SIGNING_SECRET_NAME:-"${APP_ENV:-prod}/tracecat/signing-secret"}
USER_AUTH_SECRET_NAME=${USER_AUTH_SECRET_NAME:-"${APP_ENV:-prod}/tracecat/user-auth-secret"}

# Create AWS Secrets
aws secretsmanager create-secret --name "$DB_ENCRYPTION_KEY_NAME" --secret-string "$DB_ENCRYPTION_KEY" --region "$AWS_DEFAULT_REGION" --no-cli-pager
aws secretsmanager create-secret --name "$SERVICE_KEY_NAME" --secret-string "$SERVICE_KEY" --region "$AWS_DEFAULT_REGION" --no-cli-pager
aws secretsmanager create-secret --name "$SIGNING_SECRET_NAME" --secret-string "$SIGNING_SECRET" --region "$AWS_DEFAULT_REGION" --no-cli-pager
aws secretsmanager create-secret --name "$USER_AUTH_SECRET_NAME" --secret-string "$USER_AUTH_SECRET" --region "$AWS_DEFAULT_REGION" --no-cli-pager

echo "AWS Secrets created successfully."
echo "DB_ENCRYPTION_KEY_NAME: $DB_ENCRYPTION_KEY_NAME"
echo "SERVICE_KEY_NAME: $SERVICE_KEY_NAME"
echo "SIGNING_SECRET_NAME: $SIGNING_SECRET_NAME"
echo "USER_AUTH_SECRET_NAME: $USER_AUTH_SECRET_NAME"
3 changes: 1 addition & 2 deletions deployments/fargate/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,7 @@ variable "oidc_client_secret_arn" {

variable "user_auth_secret_arn" {
type = string
description = "The ARN of the secret containing USER_AUTH_SECRET (optional)"
default = null
description = "The ARN of the secret containing USER_AUTH_SECRET"
}

variable "saml_idp_metadata_url_arn" {
Expand Down
1 change: 1 addition & 0 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@
"group": "Self-hosting",
"icon": "server",
"pages": [
"self-hosting/overview",
"self-hosting/docker-compose",
"self-hosting/aws-fargate"
]
Expand Down
2 changes: 1 addition & 1 deletion docs/overview/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ You can also sign up manually via [https://platform.tracecat.com](https://platfo
## Self-host

Docker Compose is the easiest way to self-host.
Check out the full guide [here](/self-hosting/docker-compose) or follow the quickstart below.
Start with the [self-hosting overview](/self-hosting/overview), then follow the [Docker Compose guide](/self-hosting/docker-compose) or use the quickstart below.

```bash
# Setup environment variables and secrets
Expand Down
2 changes: 1 addition & 1 deletion docs/overview/introduction.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ The AI-native security automation platform.
<Card title="Deploy MCP servers" icon="boxes" href="/automations/integrations/mcp-integrations">
Host your own sandboxed MCP server in Tracecat.
</Card>
<Card title="Self-hosting" icon="server" href="/self-hosting/docker-compose">
<Card title="Self-hosting" icon="server" href="/self-hosting/overview">
Host your Tracecat in your own infrastructure.
</Card>
</Columns>
Expand Down
3 changes: 2 additions & 1 deletion docs/self-hosting/aws-fargate.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ cd tracecat/deployments/fargate

## Create core secrets

Create the required secrets (`TRACECAT__DB_ENCRYPTION_KEY`, `TRACECAT__SERVICE_KEY`, `TRACECAT__SIGNING_SECRET`) in AWS Secrets Manager.
Create the required secrets (`TRACECAT__DB_ENCRYPTION_KEY`, `TRACECAT__SERVICE_KEY`, `TRACECAT__SIGNING_SECRET`, `USER_AUTH_SECRET`) in AWS Secrets Manager.

```bash
export AWS_DEFAULT_REGION=<aws-region>
Expand Down Expand Up @@ -59,6 +59,7 @@ export TF_VAR_hosted_zone_id=<hosted-zone-id>
export TF_VAR_tracecat_db_encryption_key_arn=<secret-arn>
export TF_VAR_tracecat_service_key_arn=<secret-arn>
export TF_VAR_tracecat_signing_secret_arn=<secret-arn>
export TF_VAR_user_auth_secret_arn=<secret-arn>

# Optional but recommended
export TF_VAR_tracecat_image_tag=1.0.0-beta.35
Expand Down
22 changes: 6 additions & 16 deletions docs/self-hosting/docker-compose.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ title: Docker Compose
description: Deploy Tracecat using Docker Compose.
---

import DockerComposeRequirements from "/snippets/self-hosting-requirements.mdx";

<Warning>
Docker Compose deployments default to basic email / password authentication.
Production deployments should use [OIDC](/authentication/oidc) or [SAML](/authentication/saml) SSO.
Expand Down Expand Up @@ -98,25 +100,13 @@ After the stack starts, verify that your containers are healthy and that you can
Docker Compose runs all services on a single host.
These are recommended minimums for different workload sizes.

| Resource | Small | Standard | Production |
| :------- | :---- | :------- | :--------- |
| CPU | 8 cores | 16 cores | 32+ cores |
| RAM | 16 GB | 32 GB | 64+ GB |
| Storage | 20 GB SSD | 50 GB SSD | 100+ GB SSD |
| Docker | 26.0.0+ | 26.0.0+ | 26.0.0+ |
| Workflow starts/sec | ~5 | ~15 | ~40 |
| Concurrent seats | 1-10 | 10-50 | 50+ |
| Concurrent agents/sec | 1-2 | 5-10 | 10+ |

- **Small**: Development, testing, small teams (1-10 users)
- **Standard**: Mid-size teams (10-50 users), moderate workflow execution
- **Production**: Large teams (50+ users), high throughput
<DockerComposeRequirements />

Memory is typically the constraining factor.
Workflow throughput is lower than dedicated Kubernetes deployments where services have guaranteed resources and can scale independently.
Workflow throughput is lower than dedicated clustered deployments where services have guaranteed resources and can scale independently.

<Note>
For production workloads that exceed single-host capacity, consider [converting to Docker Swarm](#convert-to-docker-swarm) or deploying on Kubernetes.
If you need more than the limits above, contact us about the Enterprise Kubernetes deployment.
For larger single-host deployments, you can also consider [converting to Docker Swarm](#convert-to-docker-swarm).
</Note>

## Convert to Docker Swarm
Expand Down
Loading
Loading