mirror of
https://github.com/Dokploy/templates.git
synced 2026-11-10 01:33:12 -06:00
Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3fb632006a | ||
|
|
63b0eef948 | ||
|
|
e429bff0c2 | ||
|
|
6425052f98 | ||
|
|
62c2f0ed73 | ||
|
|
830d6bbc8d |
@@ -0,0 +1,197 @@
|
||||
services:
|
||||
libsql:
|
||||
image: ghcr.io/tursodatabase/libsql-server:v0.24.33
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- 8080
|
||||
volumes:
|
||||
- libsql-data:/var/lib/sqld
|
||||
environment:
|
||||
- SQLD_NODE=primary
|
||||
# Increase limits to handle multiple services without connection pooling
|
||||
- SQLD_MAX_CONCURRENT_CONNECTIONS=512
|
||||
- SQLD_MAX_CONCURRENT_REQUESTS=1024
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
'perl -e ''use IO::Socket::INET; exit(IO::Socket::INET->new(PeerAddr=>"127.0.0.1:8080",Timeout=>1) ? 0 : 1);''',
|
||||
]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
|
||||
# One-shot migration runner (idempotent — drizzle skips applied migrations).
|
||||
# No published image exists for it upstream, so it is built from the pinned
|
||||
# commit the ghcr.io app images were built from.
|
||||
db-migrate:
|
||||
build:
|
||||
context: https://github.com/openstatusHQ/openstatus.git#e1a98255e39c9cc9f6d4853dbce30c3f6c42514a
|
||||
dockerfile: packages/db/Dockerfile
|
||||
restart: on-failure:3
|
||||
environment:
|
||||
- DATABASE_URL=http://libsql:8080
|
||||
- DATABASE_AUTH_TOKEN=
|
||||
depends_on:
|
||||
libsql:
|
||||
condition: service_healthy
|
||||
|
||||
workflows:
|
||||
image: ghcr.io/openstatushq/openstatus-workflows:e1a9825
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- 3000
|
||||
volumes:
|
||||
- workflows-data:/app/data
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- PORT=3000
|
||||
- DATABASE_URL=http://libsql:8080
|
||||
- DATABASE_AUTH_TOKEN=
|
||||
- CRON_SECRET=${CRON_SECRET}
|
||||
- RESEND_API_KEY=${RESEND_API_KEY:-re_selfhost_placeholder}
|
||||
- SITE_URL=https://${DASHBOARD_HOST}
|
||||
- TINYBIRD_NOOP=true
|
||||
depends_on:
|
||||
db-migrate:
|
||||
condition: service_completed_successfully
|
||||
libsql:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3000/ping"]
|
||||
interval: 15s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
|
||||
server:
|
||||
image: ghcr.io/openstatushq/openstatus-server:e1a9825
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- 3000
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- PORT=3000
|
||||
- DATABASE_URL=http://libsql:8080
|
||||
- DATABASE_AUTH_TOKEN=
|
||||
- CRON_SECRET=${CRON_SECRET}
|
||||
- RESEND_API_KEY=${RESEND_API_KEY:-re_selfhost_placeholder}
|
||||
- SUPER_ADMIN_TOKEN=${SUPER_ADMIN_TOKEN}
|
||||
- SELF_HOST=true
|
||||
- FLY_REGION=self-hosted
|
||||
- TINYBIRD_NOOP=true
|
||||
- UPSTASH_REDIS_REST_URL=http://localhost:6379
|
||||
- UPSTASH_REDIS_REST_TOKEN=placeholder
|
||||
depends_on:
|
||||
db-migrate:
|
||||
condition: service_completed_successfully
|
||||
workflows:
|
||||
condition: service_healthy
|
||||
libsql:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3000/ping"]
|
||||
interval: 15s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
|
||||
dashboard:
|
||||
image: ghcr.io/openstatushq/openstatus-dashboard:e1a9825
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- 3000
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- PORT=3000
|
||||
- HOSTNAME=0.0.0.0
|
||||
- AUTH_TRUST_HOST=true
|
||||
- DATABASE_URL=http://libsql:8080
|
||||
- DATABASE_AUTH_TOKEN=
|
||||
- AUTH_SECRET=${AUTH_SECRET}
|
||||
- SELF_HOST=true
|
||||
- NEXT_PUBLIC_URL=https://${DASHBOARD_HOST}
|
||||
- CRON_SECRET=${CRON_SECRET}
|
||||
- RESEND_API_KEY=${RESEND_API_KEY:-re_selfhost_placeholder}
|
||||
- TINYBIRD_NOOP=true
|
||||
- UPSTASH_REDIS_REST_URL=http://localhost:6379
|
||||
- UPSTASH_REDIS_REST_TOKEN=placeholder
|
||||
depends_on:
|
||||
db-migrate:
|
||||
condition: service_completed_successfully
|
||||
workflows:
|
||||
condition: service_healthy
|
||||
libsql:
|
||||
condition: service_healthy
|
||||
server:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3000/"]
|
||||
interval: 15s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 45s
|
||||
|
||||
status-page:
|
||||
image: ghcr.io/openstatushq/openstatus-status-page:e1a9825
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- 3000
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
- PORT=3000
|
||||
- HOSTNAME=0.0.0.0
|
||||
- AUTH_TRUST_HOST=true
|
||||
- DATABASE_URL=http://libsql:8080
|
||||
- DATABASE_AUTH_TOKEN=
|
||||
- AUTH_SECRET=${AUTH_SECRET}
|
||||
- SELF_HOST=true
|
||||
- NEXT_PUBLIC_URL=https://${DASHBOARD_HOST}
|
||||
- CRON_SECRET=${CRON_SECRET}
|
||||
- RESEND_API_KEY=${RESEND_API_KEY:-re_selfhost_placeholder}
|
||||
- TINYBIRD_NOOP=true
|
||||
depends_on:
|
||||
db-migrate:
|
||||
condition: service_completed_successfully
|
||||
workflows:
|
||||
condition: service_healthy
|
||||
libsql:
|
||||
condition: service_healthy
|
||||
server:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-f", "http://localhost:3000/"]
|
||||
interval: 15s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 45s
|
||||
|
||||
# Ingest server for private-location probes (the probe itself,
|
||||
# ghcr.io/openstatushq/private-location, runs wherever you monitor from).
|
||||
private-location:
|
||||
image: ghcr.io/openstatushq/openstatus-private-location:e1a9825
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- 8080
|
||||
environment:
|
||||
- PORT=8080
|
||||
- GIN_MODE=release
|
||||
- DB_URL=http://libsql:8080
|
||||
- WORKFLOWS_URL=http://workflows:3000
|
||||
- CRON_SECRET=${CRON_SECRET}
|
||||
- TINYBIRD_URL=${TINYBIRD_URL}
|
||||
- TINYBIRD_TOKEN=${TINYBIRD_TOKEN}
|
||||
depends_on:
|
||||
server:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--spider", "-q", "http://localhost:8080/health"]
|
||||
interval: 15s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
start_period: 30s
|
||||
|
||||
volumes:
|
||||
libsql-data:
|
||||
workflows-data:
|
||||
@@ -0,0 +1,60 @@
|
||||
# OpenStatus
|
||||
|
||||
OpenStatus is deployed here in self-hosted mode following the official Docker
|
||||
setup (`DOCKER.md` / `docker-compose.github-packages.yaml` upstream), with all
|
||||
app images pinned to the same upstream commit (`e1a9825`).
|
||||
|
||||
## Services
|
||||
|
||||
| Service | Purpose |
|
||||
|---|---|
|
||||
| dashboard | Admin UI (your first domain) |
|
||||
| status-page | Public status pages (your second domain, pages served at `/<slug>`) |
|
||||
| server | API backend (tRPC / public API) |
|
||||
| workflows | Background jobs / alerting |
|
||||
| libsql | Local libSQL (Turso) database — no cloud account needed |
|
||||
| db-migrate | One-shot migration runner (built from the pinned upstream commit, exits after applying) |
|
||||
| private-location | Ingest server that receives check results from your monitoring probes |
|
||||
|
||||
Database migrations run automatically on every deploy (the one-shot
|
||||
`db-migrate` service is idempotent).
|
||||
|
||||
Note: `db-migrate` is built from source (upstream publishes no image for it),
|
||||
so the first deployment takes a few extra minutes while it builds.
|
||||
|
||||
## First login
|
||||
|
||||
1. Open the dashboard domain and choose **magic link** login with your e-mail.
|
||||
2. If you did not configure `RESEND_API_KEY`, the magic link is not e-mailed —
|
||||
it is printed to the **dashboard service logs**. Open the dashboard
|
||||
container logs in Dokploy and copy the `>>> Magic Link: ...` URL into your
|
||||
browser. If the printed link starts with `http://0.0.0.0:3000`, replace that
|
||||
host with your dashboard domain before opening it. (Optionally, once HTTPS
|
||||
is enabled on your dashboard domain, you can add
|
||||
`AUTH_URL=https://<your-dashboard-domain>` to the dashboard service in the
|
||||
compose file so links are generated with the right host — do not set it to
|
||||
an empty value or a plain-HTTP domain, as that breaks the auth flow.)
|
||||
3. Create a workspace and a status page with a slug; it becomes available at
|
||||
`https://<status-page-domain>/<slug>`.
|
||||
|
||||
## Running checks (probes)
|
||||
|
||||
Self-hosted OpenStatus runs monitors through **private location probes**
|
||||
(`ghcr.io/openstatushq/private-location`) that you deploy wherever you want to
|
||||
monitor from. Point the probe at this stack's ingest server:
|
||||
|
||||
- Expose the `private-location` service (port 8080) on a domain in Dokploy, and
|
||||
- set `OPENSTATUS_INGEST_URL` on the probe to that URL, together with the
|
||||
`OPENSTATUS_KEY` you create in the dashboard.
|
||||
|
||||
See the upstream guide: https://www.openstatus.dev/docs (Guides → How to
|
||||
Self-Host openstatus).
|
||||
|
||||
## Analytics (optional)
|
||||
|
||||
Tinybird analytics are disabled by default (`TINYBIRD_NOOP=true`), so charts
|
||||
show no data but everything else works. To enable analytics, run a Tinybird
|
||||
Local container or use Tinybird Cloud, deploy the `packages/tinybird` project
|
||||
with the `tb` CLI, and set `TINYBIRD_URL` / `TINYBIRD_TOKEN` in the
|
||||
environment (plus `TINY_BIRD_API_KEY` and remove `TINYBIRD_NOOP`) — see the
|
||||
upstream self-hosting guide.
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"id": "openstatus",
|
||||
"name": "OpenStatus",
|
||||
"version": "e1a9825",
|
||||
"description": "OpenStatus is an open-source synthetic monitoring platform with beautiful status pages, uptime and API monitoring as code, and alerting.",
|
||||
"logo": "openstatus.png",
|
||||
"links": {
|
||||
"github": "https://github.com/openstatusHQ/openstatus",
|
||||
"website": "https://www.openstatus.dev",
|
||||
"docs": "https://www.openstatus.dev/docs"
|
||||
},
|
||||
"tags": [
|
||||
"monitoring",
|
||||
"status-page",
|
||||
"uptime"
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 5.8 KiB |
@@ -0,0 +1,34 @@
|
||||
[variables]
|
||||
dashboard_domain = "${domain}"
|
||||
status_page_domain = "${domain}"
|
||||
auth_secret = "${base64:32}"
|
||||
cron_secret = "${password:32}"
|
||||
super_admin_token = "${password:32}"
|
||||
|
||||
[config]
|
||||
|
||||
# Dashboard (admin UI — log in here)
|
||||
[[config.domains]]
|
||||
serviceName = "dashboard"
|
||||
port = 3000
|
||||
host = "${dashboard_domain}"
|
||||
|
||||
# Public status pages (served at /<page-slug>)
|
||||
[[config.domains]]
|
||||
serviceName = "status-page"
|
||||
port = 3000
|
||||
host = "${status_page_domain}"
|
||||
|
||||
[config.env]
|
||||
DASHBOARD_HOST = "${dashboard_domain}"
|
||||
STATUS_PAGE_HOST = "${status_page_domain}"
|
||||
AUTH_SECRET = "${auth_secret}"
|
||||
CRON_SECRET = "${cron_secret}"
|
||||
SUPER_ADMIN_TOKEN = "${super_admin_token}"
|
||||
# Optional: Resend API key for outgoing e-mails. Without it, magic-link
|
||||
# login URLs are printed to the dashboard container logs instead.
|
||||
RESEND_API_KEY = ""
|
||||
# Optional: Tinybird analytics for the private-location ingest server
|
||||
# (see instructions — analytics are disabled/no-op by default)
|
||||
TINYBIRD_URL = ""
|
||||
TINYBIRD_TOKEN = ""
|
||||
@@ -0,0 +1,230 @@
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18-alpine@sha256:9a8afca54e7861fd90fab5fdf4c42477a6b1cb7d293595148e674e0a3181de15
|
||||
environment:
|
||||
POSTGRES_USER: orbit
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?required}
|
||||
POSTGRES_DB: orbit
|
||||
volumes:
|
||||
- postgres:/var/lib/postgresql
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- pg_isready -U orbit -d orbit
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 20
|
||||
restart: unless-stopped
|
||||
redis:
|
||||
image: redis:8-alpine@sha256:978f0e01593e65eed801f2402944efcd936d43b5027e4908a7897baf88ed6241
|
||||
command:
|
||||
- redis-server
|
||||
- --appendonly
|
||||
- 'yes'
|
||||
volumes:
|
||||
- redis:/data
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- redis-cli
|
||||
- ping
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 20
|
||||
restart: unless-stopped
|
||||
storage:
|
||||
# SeaweedFS S3 gateway (MinIO images are no longer publicly pullable).
|
||||
image: chrislusf/seaweedfs:4.48
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
- -c
|
||||
command:
|
||||
- |
|
||||
set -e
|
||||
printf '{"identities":[{"name":"orbit","credentials":[{"accessKey":"orbit","secretKey":"%s"}],"actions":["Admin","Read","Write","List","Tagging"]}]}' "$$MINIO_PASSWORD" > /tmp/s3.json
|
||||
exec weed server -dir=/data -ip.bind=0.0.0.0 -s3 -s3.port=9000 -s3.config=/tmp/s3.json
|
||||
environment:
|
||||
MINIO_PASSWORD: ${MINIO_PASSWORD:?required}
|
||||
volumes:
|
||||
- storage:/data
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- wget -q -O /dev/null http://127.0.0.1:9000/healthz || exit 1
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 30
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- '9000'
|
||||
bucket:
|
||||
# Reuses the mc client from orbit-bucket to create the bucket and its CORS rule on SeaweedFS.
|
||||
image: ghcr.io/noveum/orbit-bucket:2026.09.24
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
- -c
|
||||
command:
|
||||
- |
|
||||
set -eu
|
||||
until mc alias set orbit http://storage:9000 orbit "$$MINIO_PASSWORD" --api S3v4; do sleep 2; done
|
||||
until mc mb --ignore-existing orbit/orbit-uploads; do sleep 2; done
|
||||
printf '<CORSConfiguration><CORSRule><AllowedOrigin>%s</AllowedOrigin><AllowedMethod>GET</AllowedMethod><AllowedMethod>PUT</AllowedMethod><AllowedMethod>HEAD</AllowedMethod><AllowedHeader>*</AllowedHeader><ExposeHeader>ETag</ExposeHeader><MaxAgeSeconds>3600</MaxAgeSeconds></CORSRule></CORSConfiguration>' "$$ORBIT_APP_URL" > /tmp/cors.xml
|
||||
until mc cors set orbit/orbit-uploads /tmp/cors.xml; do sleep 2; done
|
||||
touch /tmp/initialized
|
||||
exec tail -f /dev/null
|
||||
environment:
|
||||
MINIO_PASSWORD: ${MINIO_PASSWORD:?required}
|
||||
ORBIT_APP_URL: ${ORBIT_APP_URL:?required}
|
||||
depends_on:
|
||||
storage:
|
||||
condition: service_healthy
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- test -f /tmp/initialized
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 30
|
||||
web:
|
||||
image: ghcr.io/noveum/orbit-runtime:2026.09.24
|
||||
environment:
|
||||
DATABASE_URL: postgres://orbit:${POSTGRES_PASSWORD:?required}@postgres:5432/orbit
|
||||
DIRECT_URL: postgres://orbit:${POSTGRES_PASSWORD:?required}@postgres:5432/orbit
|
||||
DATABASE_PREPARED_STATEMENTS: 'true'
|
||||
REDIS_URL: redis://redis:6379
|
||||
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET:?required}
|
||||
BETTER_AUTH_URL: ${ORBIT_APP_URL:?required}
|
||||
NEXT_PUBLIC_APP_URL: ${ORBIT_APP_URL:?required}
|
||||
ORBIT_PASSWORD_AUTH: ${ORBIT_PASSWORD_AUTH:-true}
|
||||
ALLOWED_EMAIL_DOMAINS: ${ALLOWED_EMAIL_DOMAINS:-}
|
||||
RESEND_API_KEY: ${RESEND_API_KEY:-}
|
||||
EMAIL_FROM: ${EMAIL_FROM:-Orbit <auth@orbit.local>}
|
||||
GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-}
|
||||
GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-}
|
||||
GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID:-}
|
||||
GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET:-}
|
||||
GITHUB_APP_SLUG: ${GITHUB_APP_SLUG:-}
|
||||
GITHUB_APP_ID: ${GITHUB_APP_ID:-}
|
||||
GITHUB_APP_PRIVATE_KEY: ${GITHUB_APP_PRIVATE_KEY:-}
|
||||
GITHUB_APP_CLIENT_ID: ${GITHUB_APP_CLIENT_ID:-}
|
||||
GITHUB_APP_CLIENT_SECRET: ${GITHUB_APP_CLIENT_SECRET:-}
|
||||
GITHUB_WEBHOOK_SECRET: ${GITHUB_WEBHOOK_SECRET:-}
|
||||
SLACK_ENABLED: ${SLACK_ENABLED:-false}
|
||||
SLACK_CLIENT_ID: ${SLACK_CLIENT_ID:-}
|
||||
SLACK_CLIENT_SECRET: ${SLACK_CLIENT_SECRET:-}
|
||||
SLACK_SIGNING_SECRET: ${SLACK_SIGNING_SECRET:-}
|
||||
SLACK_APP_ID: ${SLACK_APP_ID:-}
|
||||
CRON_SECRET: ${CRON_SECRET:-}
|
||||
ORBIT_SELF_HOSTED: 'true'
|
||||
S3_ENDPOINT: ${ORBIT_STORAGE_URL:?required}
|
||||
S3_REGION: us-east-1
|
||||
S3_BUCKET: orbit-uploads
|
||||
S3_ACCESS_KEY_ID: orbit
|
||||
S3_SECRET_ACCESS_KEY: ${MINIO_PASSWORD:?required}
|
||||
NEXT_TELEMETRY_DISABLED: '1'
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- node
|
||||
- -e
|
||||
- fetch('http://127.0.0.1:3000/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
start_period: 30s
|
||||
retries: 5
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
bucket:
|
||||
condition: service_healthy
|
||||
restart: unless-stopped
|
||||
realtime:
|
||||
image: ghcr.io/noveum/orbit-runtime:2026.09.24
|
||||
command:
|
||||
- node
|
||||
- apps/web/realtime.mjs
|
||||
environment:
|
||||
DATABASE_URL: postgres://orbit:${POSTGRES_PASSWORD:?required}@postgres:5432/orbit
|
||||
DIRECT_URL: postgres://orbit:${POSTGRES_PASSWORD:?required}@postgres:5432/orbit
|
||||
DATABASE_PREPARED_STATEMENTS: 'true'
|
||||
REDIS_URL: redis://redis:6379
|
||||
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET:?required}
|
||||
BETTER_AUTH_URL: ${ORBIT_APP_URL:?required}
|
||||
NEXT_PUBLIC_APP_URL: ${ORBIT_APP_URL:?required}
|
||||
ORBIT_PASSWORD_AUTH: ${ORBIT_PASSWORD_AUTH:-true}
|
||||
ALLOWED_EMAIL_DOMAINS: ${ALLOWED_EMAIL_DOMAINS:-}
|
||||
RESEND_API_KEY: ${RESEND_API_KEY:-}
|
||||
EMAIL_FROM: ${EMAIL_FROM:-Orbit <auth@orbit.local>}
|
||||
GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID:-}
|
||||
GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET:-}
|
||||
GITHUB_CLIENT_ID: ${GITHUB_CLIENT_ID:-}
|
||||
GITHUB_CLIENT_SECRET: ${GITHUB_CLIENT_SECRET:-}
|
||||
GITHUB_APP_SLUG: ${GITHUB_APP_SLUG:-}
|
||||
GITHUB_APP_ID: ${GITHUB_APP_ID:-}
|
||||
GITHUB_APP_PRIVATE_KEY: ${GITHUB_APP_PRIVATE_KEY:-}
|
||||
GITHUB_APP_CLIENT_ID: ${GITHUB_APP_CLIENT_ID:-}
|
||||
GITHUB_APP_CLIENT_SECRET: ${GITHUB_APP_CLIENT_SECRET:-}
|
||||
GITHUB_WEBHOOK_SECRET: ${GITHUB_WEBHOOK_SECRET:-}
|
||||
SLACK_ENABLED: ${SLACK_ENABLED:-false}
|
||||
SLACK_CLIENT_ID: ${SLACK_CLIENT_ID:-}
|
||||
SLACK_CLIENT_SECRET: ${SLACK_CLIENT_SECRET:-}
|
||||
SLACK_SIGNING_SECRET: ${SLACK_SIGNING_SECRET:-}
|
||||
SLACK_APP_ID: ${SLACK_APP_ID:-}
|
||||
CRON_SECRET: ${CRON_SECRET:-}
|
||||
ORBIT_SELF_HOSTED: 'true'
|
||||
S3_ENDPOINT: ${ORBIT_STORAGE_URL:?required}
|
||||
S3_REGION: us-east-1
|
||||
S3_BUCKET: orbit-uploads
|
||||
S3_ACCESS_KEY_ID: orbit
|
||||
S3_SECRET_ACCESS_KEY: ${MINIO_PASSWORD:?required}
|
||||
NEXT_TELEMETRY_DISABLED: '1'
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- node
|
||||
- -e
|
||||
- fetch('http://127.0.0.1:3100/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
depends_on:
|
||||
web:
|
||||
condition: service_healthy
|
||||
bucket:
|
||||
condition: service_healthy
|
||||
restart: unless-stopped
|
||||
scheduler:
|
||||
image: ghcr.io/noveum/orbit-runtime:2026.09.24
|
||||
command:
|
||||
- node
|
||||
- apps/web/scheduler.mjs
|
||||
environment:
|
||||
CRON_SECRET: ${CRON_SECRET:?required}
|
||||
ORBIT_INTERNAL_URL: http://web:3000
|
||||
stop_grace_period: 310s
|
||||
depends_on:
|
||||
web:
|
||||
condition: service_healthy
|
||||
restart: unless-stopped
|
||||
orbit:
|
||||
image: ghcr.io/noveum/orbit-gateway:2026.09.24
|
||||
environment:
|
||||
ORBIT_TRUSTED_PROXIES: ${ORBIT_TRUSTED_PROXIES:-private_ranges}
|
||||
depends_on:
|
||||
web:
|
||||
condition: service_healthy
|
||||
realtime:
|
||||
condition: service_healthy
|
||||
scheduler:
|
||||
condition: service_started
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- '3000'
|
||||
volumes:
|
||||
postgres: null
|
||||
redis: null
|
||||
storage: null
|
||||
version: '3.8'
|
||||
@@ -0,0 +1,13 @@
|
||||
# Orbit by Noveum
|
||||
|
||||
Deploy, then enable HTTPS with a valid certificate for both generated domains
|
||||
in Dokploy's Domains tab. Open the Orbit HTTPS domain and create your account
|
||||
and workspace. Both the app and storage domains require working HTTPS. Database migrations,
|
||||
bucket creation and the storage CORS allowlist are configured automatically.
|
||||
PostgreSQL, Redis and SeaweedFS (S3 storage) use persistent volumes. Preserve generated secrets
|
||||
and back up PostgreSQL and the SeaweedFS storage volume before upgrades. Run one scheduler instance.
|
||||
Configure Resend and EMAIL_FROM on web to send invitations and password recovery.
|
||||
Configure ALLOWED_EMAIL_DOMAINS to restrict signup to your team.
|
||||
|
||||
Hosted MCP: https://orbit.noveum.ai/mcp
|
||||
Self-hosted MCP: your Orbit HTTPS domain followed by /mcp.
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"id": "orbit",
|
||||
"name": "Orbit by Noveum",
|
||||
"version": "2026.09.24",
|
||||
"description": "Open-source task management with issues, projects, sprints, docs, files, realtime collaboration and an OAuth MCP endpoint.",
|
||||
"logo": "orbit.png",
|
||||
"links": {
|
||||
"github": "https://github.com/Noveum/orbit",
|
||||
"website": "https://orbit.noveum.ai",
|
||||
"docs": "https://github.com/Noveum/orbit/blob/containers-2026.09.24/docs/container-catalogs.md"
|
||||
},
|
||||
"tags": [
|
||||
"productivity",
|
||||
"project-management",
|
||||
"collaboration",
|
||||
"mcp"
|
||||
]
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
@@ -0,0 +1,27 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
storage_domain = "${domain}"
|
||||
postgres_password = "${password:48}"
|
||||
minio_password = "${password:48}"
|
||||
auth_secret = "${password:64}"
|
||||
cron_secret = "${password:64}"
|
||||
|
||||
[config]
|
||||
env = [
|
||||
"ORBIT_APP_URL=https://${main_domain}",
|
||||
"ORBIT_STORAGE_URL=https://${storage_domain}",
|
||||
"POSTGRES_PASSWORD=${postgres_password}",
|
||||
"MINIO_PASSWORD=${minio_password}",
|
||||
"BETTER_AUTH_SECRET=${auth_secret}",
|
||||
"CRON_SECRET=${cron_secret}",
|
||||
]
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "orbit"
|
||||
port = 3000
|
||||
host = "${main_domain}"
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "storage"
|
||||
port = 9000
|
||||
host = "${storage_domain}"
|
||||
Reference in New Issue
Block a user