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
68 changes: 68 additions & 0 deletions blueprints/multica/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: multica

services:
postgres:
image: pgvector/pgvector:pg17
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 5s
timeout: 5s
retries: 10

backend:
build:
context: "https://github.com/multica-ai/multica.git#main"
dockerfile: Dockerfile
Comment on lines +21 to +22
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Build context pinned to mutable #main ref

Both services build from https://github.com/multica-ai/multica.git#main, which always resolves to the latest commit on main. Any breaking upstream change silently breaks all future deployments of this template with no way to roll back. Pinning to a specific commit SHA or semver tag (once the project cuts releases) would make deployments reproducible and safe to re-deploy.

This matches the acknowledged firecrawl/nuq-postgres pattern; at minimum, a comment noting "pin this to a release tag once available" would help future maintainers.

restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
ports:
- "8080"
volumes:
- backend_uploads:/app/data/uploads
environment:
DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=disable
PORT: "8080"
JWT_SECRET: ${JWT_SECRET}
FRONTEND_ORIGIN: ${FRONTEND_ORIGIN}
ALLOWED_ORIGINS: ${ALLOWED_ORIGINS}
MULTICA_APP_URL: ${MULTICA_APP_URL}
RESEND_API_KEY: ${RESEND_API_KEY}
RESEND_FROM_EMAIL: ${RESEND_FROM_EMAIL}
GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET}
GOOGLE_REDIRECT_URI: ${GOOGLE_REDIRECT_URI}
COOKIE_DOMAIN: ${COOKIE_DOMAIN}
S3_BUCKET: ${S3_BUCKET}
S3_REGION: ${S3_REGION}
CLOUDFRONT_DOMAIN: ${CLOUDFRONT_DOMAIN}
CLOUDFRONT_KEY_PAIR_ID: ${CLOUDFRONT_KEY_PAIR_ID}
CLOUDFRONT_PRIVATE_KEY: ${CLOUDFRONT_PRIVATE_KEY}

frontend:
build:
context: "https://github.com/multica-ai/multica.git#main"
dockerfile: Dockerfile.web
args:
REMOTE_API_URL: http://backend:8080
NEXT_PUBLIC_WS_URL: ${NEXT_PUBLIC_WS_URL}
NEXT_PUBLIC_GOOGLE_CLIENT_ID: ${NEXT_PUBLIC_GOOGLE_CLIENT_ID}
restart: unless-stopped
depends_on:
- backend
ports:
- "3000"
environment:
HOSTNAME: "0.0.0.0"

volumes:
pgdata:
backend_uploads:
7 changes: 7 additions & 0 deletions blueprints/multica/multica.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
40 changes: 40 additions & 0 deletions blueprints/multica/template.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[variables]
app_domain = "${domain}"
api_domain = "${domain}"
jwt_secret = "${password:64}"
postgres_password = "${password:32}"

[config]
[[config.domains]]
serviceName = "frontend"
port = 3000
host = "${app_domain}"
path = "/"

[[config.domains]]
serviceName = "backend"
port = 8080
host = "${api_domain}"
path = "/"

[config.env]
POSTGRES_DB = "multica"
POSTGRES_USER = "multica"
POSTGRES_PASSWORD = "${postgres_password}"
JWT_SECRET = "${jwt_secret}"
FRONTEND_ORIGIN = "https://${app_domain}"
ALLOWED_ORIGINS = "https://${app_domain}"
MULTICA_APP_URL = "https://${app_domain}"
NEXT_PUBLIC_WS_URL = "wss://${api_domain}/ws"
RESEND_API_KEY = ""
RESEND_FROM_EMAIL = "noreply@multica.ai"
GOOGLE_CLIENT_ID = ""
GOOGLE_CLIENT_SECRET = ""
GOOGLE_REDIRECT_URI = "https://${app_domain}/auth/callback"
NEXT_PUBLIC_GOOGLE_CLIENT_ID = ""
COOKIE_DOMAIN = ""
S3_BUCKET = ""
S3_REGION = "us-west-2"
CLOUDFRONT_DOMAIN = ""
CLOUDFRONT_KEY_PAIR_ID = ""
CLOUDFRONT_PRIVATE_KEY = ""
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Multi-line PEM key may not survive plain env-var assignment

CLOUDFRONT_PRIVATE_KEY is a CloudFront signing key — an RSA-2048 private key in PEM format with embedded newlines. Setting it as a bare environment variable (e.g., pasting a PEM block in Dokploy's env editor) typically breaks because the newlines are stripped or mis-parsed. A convention comment (e.g., encode newlines as \n, or base64-encode the value and have the application decode it) would save users from silent signing failures.

Since this defaults to "" and is only needed for S3/CloudFront media uploads, it won't block the initial deployment — but documentation here would prevent a confusing runtime error later.

43 changes: 23 additions & 20 deletions blueprints/signoz/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
services:
otel-conf:
image: alpine:3.20
environment:
- CLICKHOUSE_USER=${CLICKHOUSE_USER}
- CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD}
command:
- /bin/sh
- -lc
- |
cat > /otel/config.yaml <<'YAML'
cat > /otel/config.yaml <<YAML
receivers:
otlp:
protocols:
Expand All @@ -19,22 +22,20 @@ services:

exporters:
clickhousetraces:
datasource: tcp://clickhouse:9000/signoz_traces
datasource: tcp://${CLICKHOUSE_USER}:${CLICKHOUSE_PASSWORD}@clickhouse:9000/signoz_traces
use_new_schema: true

clickhousemetricswrite:
endpoint: tcp://clickhouse:9000/signoz_metrics
signozclickhousemetrics:
dsn: tcp://${CLICKHOUSE_USER}:${CLICKHOUSE_PASSWORD}@clickhouse:9000/signoz_metrics
timeout: 15s
resource_to_telemetry_conversion:
enabled: true

clickhouselogsexporter:
dsn: tcp://clickhouse:9000/signoz_logs
dsn: tcp://${CLICKHOUSE_USER}:${CLICKHOUSE_PASSWORD}@clickhouse:9000/signoz_logs
timeout: 10s
use_new_schema: true

metadataexporter:
dsn: tcp://clickhouse:9000/signoz_metadata
dsn: tcp://${CLICKHOUSE_USER}:${CLICKHOUSE_PASSWORD}@clickhouse:9000/signoz_metadata
timeout: 10s

service:
Expand All @@ -46,7 +47,7 @@ services:
metrics:
receivers: [otlp]
processors: [batch]
exporters: [clickhousemetricswrite, metadataexporter]
exporters: [signozclickhousemetrics, metadataexporter]
logs:
receivers: [otlp]
processors: [batch]
Expand Down Expand Up @@ -91,7 +92,7 @@ services:
restart: "no"

zookeeper-1:
image: bitnami/zookeeper:3.9
image: zookeeper:3.9
restart: unless-stopped
environment:
- ALLOW_ANONYMOUS_LOGIN=yes
Expand All @@ -105,7 +106,7 @@ services:
- zookeeper-data:/bitnami/zookeeper

clickhouse:
image: clickhouse/clickhouse-server:24.1.2-alpine
image: clickhouse/clickhouse-server:24.8-alpine
restart: unless-stopped
depends_on:
ch-conf:
Expand All @@ -123,18 +124,20 @@ services:
volumes:
- clickhouse-data:/var/lib/clickhouse
- ch-config:/etc/clickhouse-server/config.d
- ../files/clickhouse/users.xml:/etc/clickhouse-server/users.d/users.xml:ro
- ../files/clickhouse/json-config.xml:/etc/clickhouse-server/config.d/json-config.xml:ro

schema-migrator-sync:
image: signoz/signoz-schema-migrator:v0.129.0
command: ["sync","--dsn=tcp://clickhouse:9000","--cluster-name=cluster","--up="]
image: signoz/signoz-schema-migrator:v0.129.7
command: ["sync","--dsn=tcp://${CLICKHOUSE_USER}:${CLICKHOUSE_PASSWORD}@clickhouse:9000","--cluster-name=cluster","--up="]
depends_on:
clickhouse:
condition: service_healthy
restart: "no"

schema-migrator-async:
image: signoz/signoz-schema-migrator:v0.129.0
command: ["async","--dsn=tcp://clickhouse:9000","--cluster-name=cluster","--up="]
image: signoz/signoz-schema-migrator:v0.129.7
command: ["async","--dsn=tcp://${CLICKHOUSE_USER}:${CLICKHOUSE_PASSWORD}@clickhouse:9000","--cluster-name=cluster","--up="]
depends_on:
clickhouse:
condition: service_healthy
Expand All @@ -143,7 +146,7 @@ services:
restart: unless-stopped

signoz:
image: signoz/signoz:v0.92.1
image: signoz/signoz:v0.98.0
depends_on:
clickhouse:
condition: service_healthy
Expand All @@ -152,7 +155,7 @@ services:
environment:
- SIGNOZ_ALERTMANAGER_PROVIDER=signoz
- STORAGE=clickhouse
- SIGNOZ_TELEMETRYSTORE_CLICKHOUSE_DSN=tcp://clickhouse:9000
- SIGNOZ_TELEMETRYSTORE_CLICKHOUSE_DSN=tcp://${CLICKHOUSE_USER}:${CLICKHOUSE_PASSWORD}@clickhouse:9000
- SIGNOZ_ANALYTICS_ENABLED=false
- SIGNOZ_JWT_SECRET=${SIGNOZ_JWT_SECRET}
ports:
Expand All @@ -162,7 +165,7 @@ services:
- signoz-data:/var/lib/signoz

signoz-otel-collector:
image: signoz/signoz-otel-collector:v0.129.0
image: signoz/signoz-otel-collector:v0.129.7
depends_on:
clickhouse:
condition: service_healthy
Expand All @@ -174,8 +177,8 @@ services:
volumes:
- otel-config:/etc/otelcol:ro
ports:
- 4317
- 4318
- 4317:4317
- 4318:4318
restart: unless-stopped

volumes:
Expand Down
47 changes: 47 additions & 0 deletions blueprints/signoz/template.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
[variables]
main_domain = "${domain}"
jwt_secret = "${password:64}"
clickhouse_user = "signoz"
clickhouse_password = "${password:32}"

[config]
[[config.domains]]
Expand All @@ -11,3 +13,48 @@ path = "/"

[config.env]
SIGNOZ_JWT_SECRET = "${jwt_secret}"
CLICKHOUSE_USER = "${clickhouse_user}"
CLICKHOUSE_PASSWORD = "${clickhouse_password}"

[[config.mounts]]
filePath = "/clickhouse/users.xml"
content = """
<?xml version="1.0"?>
<clickhouse>
<users>
<signoz>
<password>${clickhouse_password}</password>
<networks>
<ip>::/0</ip>
</networks>
<profile>default</profile>
<quota>default</quota>
<access_management>1</access_management>
<named_collection_control>1</named_collection_control>
<show_named_collections>1</show_named_collections>
<show_named_collections_secrets>1</show_named_collections_secrets>
</signoz>
<default>
<password></password>
<networks>
<ip>127.0.0.1</ip>
</networks>
<profile>default</profile>
<quota>default</quota>
</default>
</users>
</clickhouse>
"""

[[config.mounts]]
filePath = "/clickhouse/json-config.xml"
content = """
<?xml version="1.0"?>
<clickhouse>
<profiles>
<default>
<allow_experimental_json_type>1</allow_experimental_json_type>
</default>
</profiles>
</clickhouse>
"""
23 changes: 22 additions & 1 deletion meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -3509,6 +3509,27 @@
"rating"
]
},
{
"id": "multica",
"name": "Multica",
"version": "latest",
"description": "Multica is an open-source managed agents platform for teams. Assign tasks to AI coding agents (Claude Code, Codex, OpenClaw and more) that execute autonomously, report progress, and build reusable skills over time.",
"logo": "multica.svg",
"links": {
"github": "https://github.com/multica-ai/multica",
"website": "https://multica.ai",
"docs": "https://github.com/multica-ai/multica/blob/main/SELF_HOSTING.md"
},
"tags": [
"ai",
"agents",
"automation",
"self-hosted",
"claude-code",
"codex",
"developer-tools"
]
},
{
"id": "n8n",
"name": "n8n",
Expand Down Expand Up @@ -4625,7 +4646,7 @@
{
"id": "signoz",
"name": "SigNoz",
"version": "v0.92.1",
"version": "v0.98.0",
"description": "SigNoz is an open-source Datadog or New Relic alternative. Get APM, logs,traces, metrics, exceptions, & alerts in a single tool.",
"logo": "signoz.svg",
"links": {
Expand Down