Compare commits

..
Author SHA1 Message Date
Mauricio SiuandClaude Fable 5 fef2bfbfce feat: add Whatomate template
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 04:59:22 -06:00
995 changed files with 3596 additions and 29454 deletions
+6 -5
View File
@@ -123,12 +123,13 @@ This document provides essential context for AI models interacting with this pro
- Ensure the `id` in `blueprints/<id>/meta.json` exactly matches the blueprint folder name (lowercase kebab-case).
- **Docker Compose Conventions (CRITICAL):**
- **Version:** MUST be `3.8`
- **NEVER include:** `ports` (use `expose` only), `container_name`, `networks` (Dokploy handles isolation)
- **ALWAYS include:** `restart: unless-stopped` or `restart: always`, persistent volumes
- **Service naming:** MUST match blueprint folder name exactly
- **Image source:** Prefer pinned Docker images from registries (`image: ghost:6-alpine`). When no official published images are available, use Docker Compose `build` with a Git context (e.g., `context: "https://github.com/..."#main`, see `blueprints/opendots` for an example building both `app` and `browser` targets from the upstream repository).
- **Example (with pinned image):**
- **Example:**
```yaml
version: "3.8"
services:
ghost:
image: ghost:6-alpine
@@ -161,7 +162,7 @@ This document provides essential context for AI models interacting with this pro
- **Required fields:** `id`, `name`, `version`, `description`, `links` (with `github`), `logo`, `tags` (array)
- **Tags:** Lowercase strings (e.g., `["monitoring", "database"]`)
- **Version:** MUST match Docker image version in docker-compose.yml when using `image:`. When building from source (using `build:` with a Git context), the version should reflect the template's own version or the upstream project's version (e.g., `"latest"` for tracking `main` branch).
- **Version:** MUST match Docker image version in docker-compose.yml
- **Logo:** Filename only (e.g., `"ghost.jpeg"`), file must exist in blueprint folder
- **Frontend Development:**
@@ -182,8 +183,8 @@ This document provides essential context for AI models interacting with this pro
- **Dependencies:**
- When adding new templates, prefer pinned Docker images to specific versions when available
- Update meta.json with exact version matching Docker Compose image version (for `image:`), or the template/upstream version (for `build:` from source)
- When adding new templates, ensure Docker images are pinned to specific versions
- Update meta.json with exact version matching Docker Compose image version
- For frontend dependencies: Use `pnpm add <package>` in `app/` directory
- For root dependencies: Use `npm install <package>` in root directory
+2
View File
@@ -32,11 +32,13 @@ To add a new template, follow these steps:
1. **Create a Folder in `blueprints/`**: Name it after the template (e.g., `grafana`). Use lowercase with hyphens for multi-word names.
2. **Add `docker-compose.yml`**: Define the services, volumes, and other Compose configurations. Key guidelines:
- Use `version: "3.8"` or later.
- Avoid exposing ports explicitly (e.g., no `ports: - "3000:3000"`; just `- 3000` if needed for internal reference).
- Do not use `container_name`.
- Avoid custom networks like `dokploy-network`; Dokploy handles isolation automatically.
- Example for Grafana:
```yaml
version: "3.8"
services:
grafana:
image: grafana/grafana-enterprise:9.5.20
+1
View File
@@ -35,6 +35,7 @@ Let's suppose you want to add the [Grafana](https://grafana.com/) template to th
2. Add the `docker-compose.yml` file to the folder
```yaml
version: "3.8"
services:
grafana:
image: grafana/grafana-enterprise:9.5.20
+1 -10
View File
@@ -4,16 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="canonical" href="https://dokploy.com/templates" />
<meta name="description" content="Browse 500+ open source Docker templates and one-click self-hosted apps to deploy with Dokploy – databases, CMS, analytics, AI tools and more." />
<meta property="og:title" content="Dokploy Templates: 500+ Open Source Apps" />
<meta property="og:description" content="Browse 500+ open source Docker templates and one-click self-hosted apps to deploy with Dokploy – databases, CMS, analytics, AI tools and more." />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://templates.dokploy.com" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Dokploy Templates: 500+ Open Source Apps" />
<meta name="twitter:description" content="Browse 500+ open source Docker templates and one-click self-hosted apps to deploy with Dokploy – databases, CMS, analytics, AI tools and more." />
<title>Dokploy Templates: 500+ Open Source Apps</title>
<title>Dokploy Blueprints</title>
</head>
<body>
<div id="root"></div>
+3 -3
View File
@@ -35,13 +35,13 @@
"next-themes": "^0.4.6",
"react": "^19.2.0",
"react-dom": "^19.2.0",
"react-router-dom": "^7.18.0",
"react-router-dom": "^7.9.4",
"sonner": "^2.0.7",
"tailwind-merge": "^3.3.1",
"tailwindcss": "^4.1.16",
"tailwindcss-animate": "^1.0.7",
"vite-plugin-static-copy": "^2.3.2",
"yaml": "2.8.3",
"yaml": "2.7.1",
"zustand": "^5.0.8"
},
"devDependencies": {
@@ -51,6 +51,6 @@
"@vitejs/plugin-react": "^4.7.0",
"globals": "^15.15.0",
"typescript": "~5.7.3",
"vite": "^6.4.3"
"vite": "^6.4.1"
}
}
+284 -350
View File
File diff suppressed because it is too large Load Diff
+15 -17
View File
@@ -109,22 +109,20 @@ const Search = () => {
</div>
</div>
<div className="relative">
<Input
type="text"
placeholder="Search templates..."
value={searchQuery}
onChange={handleSearchChange}
className="w-full"
/>
{searchQuery.length > 0 ? (
<div className="cursor-pointer" onClick={handleClearSearch}>
<XIcon className="absolute end-3 top-1/2 -translate-y-1/2 h-5 w-5 text-gray-400" />
</div>
) : (
<SearchIcon className="absolute end-3 top-1/2 -translate-y-1/2 lg:size-5 size-4 text-gray-400" />
)}
</div>
<Input
type="text"
placeholder="Search templates..."
value={searchQuery}
onChange={handleSearchChange}
className="w-full p-6"
/>
{searchQuery.length > 0 ? (
<div className="cursor-pointer" onClick={handleClearSearch}>
<XIcon className="absolute end-3 translate-y-3.5 top-1/2 h-5 w-5 text-gray-400" />
</div>
) : (
<SearchIcon className="absolute end-3 translate-y-2 top-1/2 lg:size-5 size-4 text-gray-400" />
)}
</div>
<div className="flex flex-row gap-2 justify-between">
@@ -156,7 +154,7 @@ const Search = () => {
<ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent className="w-50 p-0">
<PopoverContent className="w-[200px] p-0">
<Command shouldFilter={false}>
<CommandInput
placeholder="Search tags...."
+2 -2
View File
@@ -5,7 +5,7 @@ import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
DropdownMenuTrigger,
} from "./components/ui/dropdown-menu"
import { useTheme } from "./theme-provider"
@@ -13,7 +13,7 @@ export function ModeToggle() {
const { setTheme } = useTheme()
return (
<DropdownMenu modal={false}>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="icon">
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
-22
View File
@@ -1,22 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#101a3a"/><stop offset="1" stop-color="#050913"/></linearGradient>
<linearGradient id="rim" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stop-color="#7c6cff"/><stop offset="1" stop-color="#2de2ff"/></linearGradient>
</defs>
<rect x="6" y="6" width="500" height="500" rx="116" fill="url(#bg)" stroke="url(#rim)" stroke-width="12"/>
<polygon points="256.0,181.5 442.0,288.8 256.0,396.2 70.0,288.8" fill="#2de2ff" fill-opacity="0.12" stroke="#2de2ff" stroke-width="9" stroke-linejoin="round"/>
<polygon points="195.5,237.8 256.0,272.7 256.0,197.6 195.5,162.7" fill="#4f3fd0"/>
<polygon points="316.5,237.8 256.0,272.7 256.0,197.6 316.5,162.7" fill="#7c6cff"/>
<polygon points="256.0,127.8 316.5,162.7 256.0,197.6 195.5,162.7" fill="#b3abff"/>
<line x1="208.8" y1="219.2" x2="242.7" y2="238.8" stroke="#2bff9a" stroke-width="11" stroke-linecap="round"/>
<line x1="208.8" y1="194.4" x2="242.7" y2="213.9" stroke="#2bff9a" stroke-width="11" stroke-linecap="round"/>
<polygon points="283.9,288.8 344.3,323.7 344.3,211.0 283.9,176.1" fill="#0f9cbb"/>
<polygon points="404.8,288.8 344.3,323.7 344.3,211.0 404.8,176.1" fill="#2de2ff"/>
<polygon points="344.4,141.2 404.8,176.1 344.3,211.0 283.9,176.1" fill="#b3f6ff"/>
<line x1="297.2" y1="257.1" x2="331.1" y2="276.6" stroke="#2bff9a" stroke-width="11" stroke-linecap="round"/>
<line x1="297.2" y1="219.9" x2="331.1" y2="239.4" stroke="#2bff9a" stroke-width="11" stroke-linecap="round"/>
<polygon points="195.6,339.9 256.0,374.8 256.0,315.7 195.6,280.8" fill="#2856c8"/>
<polygon points="316.4,339.9 256.0,374.8 256.0,315.7 316.4,280.8" fill="#4f8bff"/>
<polygon points="256.0,245.9 316.4,280.8 256.0,315.7 195.6,280.8" fill="#a8c8ff"/>
<line x1="208.8" y1="318.0" x2="242.7" y2="337.5" stroke="#2bff9a" stroke-width="11" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

-10
View File
@@ -1,10 +0,0 @@
services:
3dokploy:
image: ghcr.io/suleyman/3dokploy:0.1.1
restart: unless-stopped
environment:
- DOKPLOY_URL=${DOKPLOY_URL}
- DOKPLOY_API_KEY=${DOKPLOY_API_KEY}
- BASIC_AUTH=${BASIC_AUTH}
extra_hosts:
- host.docker.internal:host-gateway
-13
View File
@@ -1,13 +0,0 @@
{
"id": "3dokploy",
"name": "3Dokploy",
"version": "0.1.1",
"description": "A live, isometric 3D view of your Dokploy: projects as buildings, services as racks, deploys rolling in on carts, network traffic as packets. Read-only.",
"logo": "3dokploy.svg",
"links": {
"github": "https://github.com/suleyman/3dokploy",
"website": "",
"docs": "https://github.com/suleyman/3dokploy#readme"
},
"tags": ["monitoring", "dashboard", "devops"]
}
-19
View File
@@ -1,19 +0,0 @@
[variables]
main_domain = "${domain}"
auth_password = "${password:24}"
[config]
mounts = []
[[config.domains]]
serviceName = "3dokploy"
port = 3_000
host = "${main_domain}"
[config.env]
# The Dokploy on this same server. If its port 3000 is closed, use its public URL instead.
DOKPLOY_URL = "http://host.docker.internal:3000"
# Required: an API key from Settings → Profile → API/CLI. It stays on the server.
DOKPLOY_API_KEY = ""
# Site login (user admin).
BASIC_AUTH = "admin:${auth_password}"
+7 -19
View File
@@ -1,6 +1,8 @@
version: "3.8"
services:
9router:
image: decolua/9router:0.5.59
image: decolua/9router:0.5.40
restart: unless-stopped
environment:
DATA_DIR: /app/data
@@ -11,34 +13,20 @@ services:
INITIAL_PASSWORD: ${INITIAL_PASSWORD}
API_KEY_SECRET: ${API_KEY_SECRET}
MACHINE_ID_SALT: ${MACHINE_ID_SALT}
BASE_URL: https://${ROUTER_HOST}
NEXT_PUBLIC_BASE_URL: https://${ROUTER_HOST}
BASE_URL: http://${ROUTER_HOST}
NEXT_PUBLIC_BASE_URL: http://${ROUTER_HOST}
HEADROOM_URL: http://headroom:8787
AUTH_COOKIE_SECURE: "true"
REQUIRE_API_KEY: "true"
AUTH_COOKIE_SECURE: "false"
volumes:
- 9router-data:/app/data
depends_on:
headroom:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:20128/api/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
- headroom
# Optional token-reduction proxy that 9Router calls through HEADROOM_URL.
# Shipped as a sidecar because the 9Router image does not bundle it.
headroom:
image: ghcr.io/chopratejas/headroom:0.6.7
restart: unless-stopped
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8787/health')"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
volumes:
9router-data:
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "9router",
"name": "9Router",
"version": "0.5.59",
"version": "0.5.40",
"description": "Self-hosted AI model router that rotates requests across 40+ providers with automatic fallback, exposing an OpenAI-compatible endpoint for coding agents.",
"logo": "9router.png",
"links": {
+2
View File
@@ -1,3 +1,5 @@
version: "3"
services:
ackee:
image: electerious/ackee:3.4.2
+4 -2
View File
@@ -1,6 +1,8 @@
version: "3.8"
services:
activepieces:
image: activepieces/activepieces:0.91.2
image: activepieces/activepieces:0.35.0
restart: unless-stopped
depends_on:
@@ -30,7 +32,7 @@ services:
AP_TEMPLATES_SOURCE_URL: https://cloud.activepieces.com/api/v1/flow-templates
postgres:
image: postgres:17
image: postgres:14
restart: unless-stopped
environment:
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "activepieces",
"name": "Activepieces",
"version": "0.91.2",
"version": "0.35.0",
"description": "Open-source no-code business automation tool. An alternative to Zapier, Make.com, and Tray.",
"logo": "activepieces.svg",
"links": {
+2 -3
View File
@@ -1,4 +1,4 @@
# dokploy: allow-host-ports — DNS (53/tcp+udp), DHCP (67/68) and DNS-over-TLS/QUIC (853) are not HTTP protocols; clients must reach them directly on the host, Traefik cannot route them.
version: "3.8"
services:
adguardhome:
image: adguard/adguardhome:latest
@@ -10,8 +10,7 @@ services:
- "68:68/tcp" # DHCP Client
- "853:853/tcp" # DNS over TLS, DNS-over-QUIC
- "853:853/udp" # DNS over TLS, DNS-over-QUIC
expose:
- 6060 # HTTP (pprof) — debug endpoint, no need to publish it on the host
- "6060:6060/tcp" # HTTP (pprof)
volumes:
- adguardhome-work:/opt/adguardhome/work
- adguardhome-conf:/opt/adguardhome/conf
+2 -5
View File
@@ -2,7 +2,7 @@
"id": "adguardhome",
"name": "AdGuard Home",
"version": "latest",
"description": "AdGuard Home is a network-wide ad and tracker blocker. Self-host it on your own server with Dokploy, which deploys AdGuard Home as a Docker Compose service in a few clicks.",
"description": "AdGuard Home is a comprehensive solution designed to enhance your online browsing experience by eliminating all kinds of ads, from annoying banners and pop-ups to intrusive video ads. It provides privacy protection, browsing security, and parental control features while maintaining website functionality.",
"logo": "logo.svg",
"links": {
"github": "https://github.com/AdguardTeam/AdGuardHome",
@@ -14,8 +14,5 @@
"security",
"dns",
"ad-blocking"
],
"seoTitle": "AdGuard Home Docker Compose Setup",
"seoDescription": "Network-wide ad and tracker blocker. Deploy AdGuard Home with Docker Compose on Dokploy in minutes – free, open source, self-hosted.",
"newConfig": true
]
}
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
adminer:
image: adminer:4.8.1
+2 -5
View File
@@ -2,7 +2,7 @@
"id": "adminer",
"name": "Adminer",
"version": "4.8.1",
"description": "Adminer is a lightweight, web-based database management tool. Self-host it on your own server with Dokploy, which deploys Adminer as a Docker Compose service in a few clicks.",
"description": "Adminer is a comprehensive database management tool that supports MySQL, MariaDB, PostgreSQL, SQLite, MS SQL, Oracle, Elasticsearch, MongoDB and others. It provides a clean interface for efficient database operations, with strong security features and extensive customization options.",
"logo": "logo.svg",
"links": {
"github": "https://github.com/vrana/adminer",
@@ -14,8 +14,5 @@
"developer-tools",
"mysql",
"postgresql"
],
"seoTitle": "Adminer Docker Compose Setup",
"seoDescription": "Lightweight database management tool. Deploy Adminer with Docker Compose on Dokploy in minutes – free, open source, self-hosted.",
"newConfig": true
]
}
@@ -1,3 +1,5 @@
version: "3.8"
services:
web:
image: ghcr.io/seanmorley15/adventurelog-frontend:latest
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
affinepro:
image: ghcr.io/toeverything/affine:stable
+2 -4
View File
@@ -2,7 +2,7 @@
"id": "affinepro",
"name": "Affine Pro",
"version": "stable",
"description": "AFFiNE is a workspace for notes, docs, and whiteboards, and an alternative to Notion. Self-host it on your own server with Dokploy, which deploys AFFiNE as a Docker Compose service in a few clicks.",
"description": "Affine Pro is a modern, self-hosted platform designed for collaborative content creation and project management. It offers an intuitive interface, seamless real-time collaboration, and powerful tools for organizing tasks, notes, and ideas.",
"logo": "logo.png",
"links": {
"github": "https://github.com/toeverything/Affine",
@@ -14,7 +14,5 @@
"self-hosted",
"productivity",
"project-management"
],
"seoTitle": "Self-Host Affine in minutes",
"seoDescription": "Workspace for notes and docs, an alternative to Notion. Self-host Affine on Dokploy in minutes – no manual setup needed."
]
}
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
agent-zero:
image: agent0ai/agent-zero:v1.9
+2 -1
View File
@@ -3,7 +3,6 @@ main_domain = "${domain}"
timezone = "America/New_York"
[config]
mounts = []
[[config.domains]]
serviceName = "agentdvr"
port = 8090
@@ -11,3 +10,5 @@ host = "${main_domain}"
[config.env]
TIMEZONE = "${timezone}"
[[config.mounts]]
-29
View File
@@ -1,29 +0,0 @@
<svg version="1.1" id="Layer_1" xmlns:x="ns_extend;" xmlns:i="ns_ai;" xmlns:graph="ns_graphs;"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 95.7 99" style="enable-background:new 0 0 95.7 99;" xml:space="preserve">
<title>Airbyte</title>
<style type="text/css">
.st0{fill-rule:evenodd;clip-rule:evenodd;fill:#615EFF;}
</style>
<metadata>
<sfw xmlns="ns_sfw;">
<slices>
</slices>
<sliceSourceBounds bottomLeftOrigin="true" height="99" width="95.7" x="77.2" y="75">
</sliceSourceBounds>
</sfw>
</metadata>
<g>
<path class="st0" d="M32.6,12C43.2,0.1,60.8-3.4,75.2,3.5c19.2,9.1,26.1,32.4,15.7,50.3L67.4,94.1c-1.3,2.3-3.5,3.9-6,4.6
c-2.5,0.7-5.2,0.3-7.5-1l28.4-48.8c7.6-13,2.5-29.9-11.4-36.5c-10.4-5-23.2-2.5-30.9,6.1c-4.2,4.7-6.6,10.8-6.7,17.1
c-0.1,6.3,2.2,12.5,6.3,17.3c0.7,0.9,1.5,1.7,2.4,2.4L25.5,83.8c-0.6,1.1-1.5,2.1-2.5,2.9c-1,0.8-2.2,1.4-3.5,1.7
c-1.3,0.3-2.6,0.4-3.8,0.3c-1.3-0.2-2.5-0.6-3.6-1.2l18-31c-2.6-3.7-4.4-7.9-5.5-12.2l-11,19c-1.3,2.3-3.5,3.9-6,4.6S2.3,68,0,66.7
l28.5-49.1C29.7,15.7,31.1,13.8,32.6,12z M65.6,27.6c6.9,3.9,9.2,12.7,5.3,19.5L43.5,94.1c-1.3,2.3-3.5,3.9-6,4.6
c-2.5,0.7-5.2,0.3-7.5-1L55.4,54c-2-0.4-4-1.3-5.6-2.5c-1.7-1.2-3.1-2.8-4-4.6c-1-1.8-1.6-3.8-1.7-5.9c-0.1-2.1,0.2-4.1,0.9-6.1
c0.7-1.9,1.9-3.7,3.4-5.1c1.5-1.4,3.3-2.5,5.2-3.2c2-0.7,4.1-0.9,6.1-0.8C61.8,26,63.8,26.6,65.6,27.6z M55.6,36.5
c-0.5,0.4-0.9,0.8-1.2,1.3h0c-0.4,0.8-0.7,1.7-0.6,2.5c0.1,0.9,0.4,1.7,0.9,2.4c0.5,0.7,1.3,1.2,2.1,1.5c0.8,0.3,1.8,0.3,2.6,0.1
c0.9-0.2,1.6-0.7,2.2-1.4c0.6-0.7,1-1.5,1.1-2.4c0.1-0.9,0-1.8-0.4-2.6c-0.4-0.8-1-1.5-1.8-1.9c-0.5-0.3-1.1-0.5-1.7-0.6
s-1.2,0-1.8,0.1C56.6,35.8,56.1,36.1,55.6,36.5z">
</path>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

-428
View File
@@ -1,428 +0,0 @@
# The following template is not officially supported by the Airbyte team, as
# docker compose deployment has been superseded by abctl. It was made based
# on the community-maintained example below:
#
# - https://github.com/nktnet1/airbyte-compose
#
# NOTE: make sure to change the AIRBYTE_URL and AIRBYTE_API_HOST environment
# variables to match that of your public domain. The URL must be publicly
# accessible (for example, it cannot be auth-protected by Cloudflare).
#
# Once you've completed the setup via the web UI, you can log in using the
# password defined in the AIRBYTE_ADMIN_PASSWORD environment variable.
#
# To connect internal databases, ensure that they are on the same network as
# the k3s container. This is available in Dokploy's UI starting from v0.30.0.
name: airbyte
x-airbyte-environment: &airbyte-environment
AIRBYTE_VERSION: ${AIRBYTE_VERSION:?Set AIRBYTE_VERSION in .env}
AIRBYTE_URL: ${AIRBYTE_URL:?Set AIRBYTE_URL in .env}
AIRBYTE_API_HOST: ${AIRBYTE_API_HOST:?Set AIRBYTE_API_HOST in .env}
AIRBYTE_SERVER_HOST: server:8001
INTERNAL_API_HOST: http://server:8001
MANIFEST_SERVER_API_HOST: http://manifest-server:8080
CONTROL_PLANE_TOKEN_ENDPOINT: http://server:8001/api/v1/dataplanes/token
WORKLOAD_API_HOST: http://workload-api-server:8007
TEMPORAL_HOST: temporal:7233
MINIO_ENDPOINT: http://minio:9000
DATABASE_HOST: db
DATABASE_DB: ${DATABASE_DB:?Set DATABASE_DB in .env}
DATABASE_USER: ${DATABASE_USER:?Set DATABASE_USER in .env}
DATABASE_PASSWORD: ${DATABASE_PASSWORD:?Set DATABASE_PASSWORD in .env}
DATABASE_URL: jdbc:postgresql://db:5432/${DATABASE_DB}
CONFIG_DATABASE_REPLICA_URL: jdbc:postgresql://db:5432/${DATABASE_DB}
CONFIG_DATABASE_REPLICA_USER: ${DATABASE_USER}
CONFIG_DATABASE_REPLICA_PASSWORD: ${DATABASE_PASSWORD}
AWS_ACCESS_KEY_ID: ${MINIO_ROOT_USER:?Set MINIO_ROOT_USER in .env}
AWS_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD:?Set MINIO_ROOT_PASSWORD in .env}
AB_INSTANCE_ADMIN_PASSWORD: ${AIRBYTE_ADMIN_PASSWORD:?Set AIRBYTE_ADMIN_PASSWORD in .env}
AB_INSTANCE_ADMIN_CLIENT_ID: ${AIRBYTE_ADMIN_CLIENT_ID:?Set AIRBYTE_ADMIN_CLIENT_ID in .env}
AB_INSTANCE_ADMIN_CLIENT_SECRET: ${AIRBYTE_ADMIN_CLIENT_SECRET:?Set AIRBYTE_ADMIN_CLIENT_SECRET in .env}
AB_JWT_SIGNATURE_SECRET: ${AIRBYTE_JWT_SIGNATURE_SECRET:?Set AIRBYTE_JWT_SIGNATURE_SECRET in .env}
CONNECTOR_PROFILER_IMAGE: airbyte/async-profiler:${AIRBYTE_VERSION}
CONNECTOR_SIDECAR_IMAGE: airbyte/connector-sidecar:${AIRBYTE_VERSION}
CONTAINER_ORCHESTRATOR_IMAGE: airbyte/container-orchestrator:${AIRBYTE_VERSION}
WORKLOAD_INIT_IMAGE: airbyte/workload-init-container:${AIRBYTE_VERSION}
JAVA_OPTS: -XX:+ExitOnOutOfMemoryError -XX:MaxRAMPercentage=75.0 -XX:FlightRecorderOptions=stackdepth=256
x-airbyte-service: &airbyte-service
env_file:
- ../files/config/airbyte.env
environment: *airbyte-environment
restart: unless-stopped
services:
db:
image: airbyte/db:${AIRBYTE_VERSION}
environment:
POSTGRES_DB: ${DATABASE_DB}
POSTGRES_USER: ${DATABASE_USER}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
PGDATA: /var/lib/postgresql/data/pgdata
healthcheck:
test: [CMD-SHELL, 'pg_isready -U "$${POSTGRES_USER}" -d "$${POSTGRES_DB}"']
interval: 5s
timeout: 5s
retries: 30
start_period: 10s
volumes:
- db-data:/var/lib/postgresql/data
restart: unless-stopped
minio:
# S3-compatible storage (SeaweedFS). The service keeps the "minio" name so
# Airbyte's MINIO_ENDPOINT (http://minio:9000) and the k3s ExternalName
# service keep working unchanged.
image: chrislusf/seaweedfs:${SEAWEEDFS_VERSION}
entrypoint: [/bin/sh, -ec]
command:
- |
mkdir -p /etc/seaweedfs
printf '{"identities":[{"name":"airbyte","credentials":[{"accessKey":"%s","secretKey":"%s"}],"actions":["Admin","Read","Write","List","Tagging"]}]}' \
"$${MINIO_ROOT_USER}" "$${MINIO_ROOT_PASSWORD}" > /etc/seaweedfs/s3.json
exec weed server -dir=/storage -ip.bind=0.0.0.0 \
-master.volumeSizeLimitMB=1024 -volume.max=0 \
-s3 -s3.port=9000 -s3.config=/etc/seaweedfs/s3.json
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
volumes:
- minio-data:/storage
restart: unless-stopped
healthcheck:
test: [CMD-SHELL, "wget -q -O /dev/null http://127.0.0.1:9000/healthz"]
interval: 10s
timeout: 5s
retries: 30
start_period: 20s
minio-init:
image: chrislusf/seaweedfs:${SEAWEEDFS_VERSION}
entrypoint: [/bin/sh, /scripts/init-minio.sh]
environment:
SEAWEEDFS_MASTER: minio:9333
volumes:
- ../files/scripts/init-minio.sh:/scripts/init-minio.sh:ro
depends_on:
minio:
condition: service_healthy
restart: on-failure
temporal:
image: temporalio/auto-setup:${TEMPORAL_VERSION}
environment:
AUTO_SETUP: "true"
DB: postgres12
DB_PORT: "5432"
POSTGRES_SEEDS: db
POSTGRES_USER: ${DATABASE_USER}
POSTGRES_PWD: ${DATABASE_PASSWORD}
POSTGRES_TLS_ENABLED: "false"
POSTGRES_TLS_DISABLE_HOST_VERIFICATION: "false"
SQL_TLS_ENABLED: "false"
SQL_TLS_DISABLE_HOST_VERIFICATION: "false"
DYNAMIC_CONFIG_FILE_PATH: config/dynamicconfig/development.yaml
PROMETHEUS_ENDPOINT: 0.0.0.0:9090
BIND_ON_IP: 0.0.0.0
TEMPORAL_BROADCAST_ADDRESS: 0.0.0.0
volumes:
- ../files/config/temporal-dynamicconfig.yaml:/etc/temporal/config/dynamicconfig/development.yaml:ro
depends_on:
db:
condition: service_healthy
restart: unless-stopped
healthcheck:
test:
- CMD
- /bin/bash
- -ec
- exec 3<>/dev/tcp/127.0.0.1/7233
interval: 10s
timeout: 5s
retries: 30
start_period: 30s
k3s:
image: rancher/k3s:${K3S_VERSION}
command:
- server
- --node-name=airbyte-k3s
- --disable=traefik
- --disable=servicelb
- --disable=metrics-server
- --disable=coredns
- --tls-san=k3s
privileged: true
environment:
K3S_KUBECONFIG_OUTPUT: /output/kubeconfig.yaml
K3S_KUBECONFIG_MODE: "0644"
tmpfs:
- /run
- /var/run
volumes:
- k3s-data:/var/lib/rancher/k3s
- k3s-kubeconfig:/output
healthcheck:
test: [CMD, /bin/kubectl, get, --raw=/readyz]
interval: 5s
timeout: 5s
retries: 60
start_period: 20s
restart: unless-stopped
docker-dns:
image: rancher/mirrored-coredns-coredns:${COREDNS_VERSION}
command: [-conf, /etc/coredns/Corefile]
volumes:
- ../files/config/docker-dns.Corefile:/etc/coredns/Corefile:ro
network_mode: service:k3s
depends_on:
k3s:
condition: service_started
restart: unless-stopped
healthcheck:
test: [CMD, /coredns, -version]
interval: 10s
timeout: 5s
retries: 3
k3s-bootstrap:
image: rancher/k3s:${K3S_VERSION}
entrypoint: [/bin/sh, /scripts/bootstrap-k3s.sh]
environment:
AIRBYTE_ADMIN_PASSWORD: ${AIRBYTE_ADMIN_PASSWORD}
AIRBYTE_ADMIN_CLIENT_ID: ${AIRBYTE_ADMIN_CLIENT_ID}
AIRBYTE_ADMIN_CLIENT_SECRET: ${AIRBYTE_ADMIN_CLIENT_SECRET}
AIRBYTE_JWT_SIGNATURE_SECRET: ${AIRBYTE_JWT_SIGNATURE_SECRET}
DATABASE_USER: ${DATABASE_USER}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
volumes:
- k3s-kubeconfig:/kube
- ../files/config/k3s-resources.yaml:/config/k3s-resources.yaml:ro
- ../files/scripts/bootstrap-k3s.sh:/scripts/bootstrap-k3s.sh:ro
depends_on:
k3s:
condition: service_healthy
docker-dns:
condition: service_started
restart: on-failure
dataplane-credentials:
image: rancher/k3s:${K3S_VERSION}
entrypoint: [/bin/sh, /scripts/export-dataplane-credentials.sh]
volumes:
- k3s-kubeconfig:/kube:ro
- dataplane-credentials:/credentials
- ../files/scripts/export-dataplane-credentials.sh:/scripts/export-dataplane-credentials.sh:ro
depends_on:
bootloader:
condition: service_completed_successfully
restart: on-failure
bootloader:
<<: *airbyte-service
image: airbyte/bootloader:${AIRBYTE_VERSION}
environment:
<<: *airbyte-environment
KUBECONFIG: /kube/config.yaml
MICRONAUT_ENVIRONMENTS: k8s,control-plane,edition-community
JOB_KUBE_NAMESPACE: default
DD_SERVICE: airbyte-bootloader
volumes:
- k3s-kubeconfig:/kube:ro
depends_on:
db:
condition: service_healthy
k3s-bootstrap:
condition: service_completed_successfully
restart: on-failure
server:
<<: *airbyte-service
image: airbyte/server:${AIRBYTE_VERSION}
environment:
<<: *airbyte-environment
DD_SERVICE: airbyte-server
expose:
- 8001
healthcheck:
test:
- CMD
- /bin/bash
- -ec
- |
exec 3<>/dev/tcp/127.0.0.1/8001
printf 'GET /api/v1/health HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n' >&3
read -r status <&3
[[ "$$status" == *" 200 "* ]]
interval: 5s
timeout: 10s
retries: 60
start_period: 10s
depends_on:
bootloader:
condition: service_completed_successfully
minio-init:
condition: service_completed_successfully
temporal:
condition: service_started
manifest-server:
<<: *airbyte-service
image: airbyte/manifest-server:${MANIFEST_SERVER_VERSION}
environment:
<<: *airbyte-environment
DD_SERVICE: airbyte-manifest-server
AIRBYTE_ENABLE_UNSAFE_CODE: ${AIRBYTE_ENABLE_UNSAFE_CODE:-false}
depends_on:
bootloader:
condition: service_completed_successfully
minio-init:
condition: service_completed_successfully
healthcheck:
test:
- CMD
- python
- -c
- import urllib.request; response = urllib.request.urlopen("http://127.0.0.1:8080/health/", timeout=5); assert response.status == 200
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
workload-api-server:
<<: *airbyte-service
image: airbyte/workload-api-server:${AIRBYTE_VERSION}
environment:
<<: *airbyte-environment
DD_SERVICE: airbyte-workload-api
depends_on:
bootloader:
condition: service_completed_successfully
minio-init:
condition: service_completed_successfully
temporal:
condition: service_started
healthcheck:
test:
- CMD
- /bin/bash
- -ec
- |
exec 3<>/dev/tcp/127.0.0.1/8085
printf 'GET /health/liveness HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n' >&3
read -r status <&3
[[ "$$status" == *" 200 "* ]]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
worker:
<<: *airbyte-service
image: airbyte/worker:${AIRBYTE_VERSION}
environment:
<<: *airbyte-environment
DD_SERVICE: airbyte-worker
depends_on:
bootloader:
condition: service_completed_successfully
temporal:
condition: service_started
workload-api-server:
condition: service_started
healthcheck:
test:
- CMD
- /bin/bash
- -ec
- |
exec 3<>/dev/tcp/127.0.0.1/9000
printf 'GET / HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n' >&3
read -r status <&3
[[ "$$status" == *" 200 "* ]]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
cron:
<<: *airbyte-service
image: airbyte/cron:${AIRBYTE_VERSION}
environment:
<<: *airbyte-environment
DD_SERVICE: airbyte-cron
depends_on:
bootloader:
condition: service_completed_successfully
temporal:
condition: service_started
workload-api-server:
condition: service_started
healthcheck:
test:
- CMD
- /bin/bash
- -ec
- |
exec 3<>/dev/tcp/127.0.0.1/8085
printf 'GET /health HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n' >&3
read -r status <&3
[[ "$$status" == *" 200 "* ]]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
workload-launcher:
<<: *airbyte-service
image: airbyte/workload-launcher:${AIRBYTE_VERSION}
entrypoint: [/bin/sh, /scripts/start-workload-launcher.sh]
command: [/bin/bash, -c, 'airbyte-app/bin/$${APPLICATION}']
environment:
<<: *airbyte-environment
KUBECONFIG: /kube/config.yaml
MICRONAUT_ENVIRONMENTS: k8s,control-plane,edition-community
JOB_KUBE_NAMESPACE: default
DD_SERVICE: airbyte-workload-launcher
AIRBYTE_ENABLE_UNSAFE_CODE: ${AIRBYTE_ENABLE_UNSAFE_CODE:-false}
volumes:
- k3s-kubeconfig:/kube:ro
- dataplane-credentials:/credentials:ro
- ../files/scripts/start-workload-launcher.sh:/scripts/start-workload-launcher.sh:ro
depends_on:
dataplane-credentials:
condition: service_completed_successfully
k3s-bootstrap:
condition: service_completed_successfully
server:
condition: service_healthy
workload-api-server:
condition: service_started
temporal:
condition: service_started
healthcheck:
test:
- CMD
- /bin/bash
- -ec
- |
exec 3<>/dev/tcp/127.0.0.1/8085
printf 'GET /health/readiness HTTP/1.0\r\nHost: localhost\r\nConnection: close\r\n\r\n' >&3
read -r status <&3
[[ "$$status" == *" 200 "* ]]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
volumes:
db-data:
minio-data:
k3s-data:
k3s-kubeconfig:
dataplane-credentials:
-18
View File
@@ -1,18 +0,0 @@
{
"id": "airbyte",
"name": "Airbyte",
"version": "2.2.0",
"description": "Open-source data movement for ELT pipelines and AI agents.",
"logo": "airbyte.svg",
"links": {
"github": "https://github.com/airbytehq/airbyte",
"website": "https://airbyte.com",
"docs": "https://docs.airbyte.com"
},
"tags": [
"analytics",
"data",
"elt",
"pipeline"
]
}
-656
View File
@@ -1,656 +0,0 @@
[variables]
main_domain = "${domain}"
database_password = "${password:32}"
minio_root_password = "${password:32}"
airbyte_admin_password = "${password:32}"
airbyte_admin_client_id = "${password:32}"
airbyte_admin_client_secret = "${password:32}"
airbyte_jwt_signature_secret = "${password:32}"
[[config.domains]]
serviceName = "server"
port = 8_001
host = "${main_domain}"
[config.env]
AIRBYTE_URL = "http://${main_domain}"
AIRBYTE_API_HOST = "http://${main_domain}/api/public"
AIRBYTE_VERSION = "2.2.0"
MANIFEST_SERVER_VERSION = "7.23.7"
TEMPORAL_VERSION = "1.27.2"
SEAWEEDFS_VERSION = "4.48"
K3S_VERSION = "v1.36.3-k3s1"
COREDNS_VERSION = "1.14.7"
DATABASE_DB = "db-airbyte"
DATABASE_USER = "airbyte"
DATABASE_PASSWORD = "${database_password}"
MINIO_ROOT_USER = "minio"
MINIO_ROOT_PASSWORD = "${minio_root_password}"
AIRBYTE_ADMIN_PASSWORD = "${airbyte_admin_password}"
AIRBYTE_ADMIN_CLIENT_ID = "${airbyte_admin_client_id}"
AIRBYTE_ADMIN_CLIENT_SECRET = "${airbyte_admin_client_secret}"
AIRBYTE_JWT_SIGNATURE_SECRET = "${airbyte_jwt_signature_secret}"
AIRBYTE_ENABLE_UNSAFE_CODE = "false"
[[config.mounts]]
filePath = "./config/airbyte.env"
content = """
AB_AUTH_SECRET_CREATION_ENABLED=true
AB_KUBERNETES_SECRET_NAME=airbyte-auth-secrets
AB_INSTANCE_ADMIN_PASSWORD_SECRET_KEY=instance-admin-password
AB_INSTANCE_ADMIN_CLIENT_ID_SECRET_KEY=instance-admin-client-id
AB_INSTANCE_ADMIN_CLIENT_SECRET_SECRET_KEY=instance-admin-client-secret
AB_JWT_SIGNATURE_SECRET_KEY=jwt-signature-secret
DATAPLANE_CLIENT_ID_SECRET_NAME=airbyte-auth-secrets
DATAPLANE_CLIENT_ID_SECRET_KEY=dataplane-client-id
DATAPLANE_CLIENT_SECRET_SECRET_NAME=airbyte-auth-secrets
DATAPLANE_CLIENT_SECRET_SECRET_KEY=dataplane-client-secret
IDENTITY_PROVIDER_TYPE=simple
AB_AIRBYTE_AUTH_IDENTITY_PROVIDER_VERIFY_ISSUER=false
AB_AIRBYTE_AUTH_IDENTITY_PROVIDER_VERIFY_AUDIENCE=false
AB_COOKIE_SECURE=false
AB_COOKIE_SAME_SITE=Lax
AIRBYTE_EDITION=community
AIRBYTE_CLUSTER_TYPE=hybrid
CLUSTER_TYPE=hybrid
API_AUTHORIZATION_ENABLED=true
LOCAL=false
DEPLOYMENT_ENV=docker-compose
AIRBYTE_DUMMY_SECRET=dummy
CONNECTOR_REGISTRY_SEED_PROVIDER=remote
ENTERPRISE_SOURCE_STUBS_URL=https://connectors.airbyte.com/files/resources/connector_stubs/v1/connector_stubs.json
UPDATE_DEFINITIONS_CRON_ENABLED=true
RUN_DECLARATIVE_SOURCES_UPDATER=false
CONNECTOR_ROLLOUT_EXPIRATION_SECONDS=604800
CONNECTOR_ROLLOUT_WAIT_BETWEEN_ROLLOUTS_SECONDS=10800
CONNECTOR_ROLLOUT_WAIT_BETWEEN_SYNC_RESULTS_QUERIES_SECONDS=3600
DATABASE_PORT=5432
RUN_DATABASE_MIGRATION_ON_STARTUP=true
CONFIGS_DATABASE_MINIMUM_FLYWAY_MIGRATION_VERSION=0.35.15.001
JOBS_DATABASE_MINIMUM_FLYWAY_MIGRATION_VERSION=0.29.15.001
FEATURE_FLAG_CLIENT=configfile
FEATURE_FLAG_PATH=/etc/launchdarkly/flags.yml
JOB_KUBE_SERVICEACCOUNT=airbyte-admin
JOB_KUBE_NAMESPACE=default
JOB_KUBE_LOCAL_VOLUME_ENABLED=false
JOB_ERROR_REPORTING_STRATEGY=logging
LOG_LEVEL=info
MICROMETER_METRICS_ENABLED=false
MICROMETER_METRICS_STEP=PT1M
MICROMETER_METRICS_STATSD_FLAVOR=datadog
MICROMETER_METRICS_OTLP_ENABLED=false
MICROMETER_METRICS_STATSD_ENABLED=false
PUBLISH_METRICS=true
STATSD_HOST=127.0.0.1
STATSD_PORT=8125
OTEL_SDK_DISABLED=true
DD_ENABLED=false
DD_INTEGRATIONS_ENABLED=false
DD_PROFILING_ENABLED=false
STIGG_ENABLED=false
AUDIT_LOGGING_ENABLED=false
STORAGE_TYPE=minio
STORAGE_BUCKET_ACTIVITY_PAYLOAD=airbyte-bucket
STORAGE_BUCKET_AUDIT_LOGGING=airbyte-bucket
STORAGE_BUCKET_LOG=airbyte-bucket
STORAGE_BUCKET_STATE=airbyte-bucket
STORAGE_BUCKET_WORKLOAD_OUTPUT=airbyte-bucket
S3_PATH_STYLE_ACCESS=true
AUTO_SETUP=true
DYNAMIC_CONFIG_FILE_PATH=config/dynamicconfig/development.yaml
PROMETHEUS_ENDPOINT=0.0.0.0:9090
BIND_ON_IP=0.0.0.0
TEMPORAL_BROADCAST_ADDRESS=0.0.0.0
TEMPORAL_CLOUD_ENABLED=false
TEMPORAL_SDK_RPC_TIMEOUT=120s
TEMPORAL_SDK_RPC_LONG_POLL_TIMEOUT=140s
TEMPORAL_SDK_RPC_QUERY_TIMEOUT=20s
TEMPORAL_WORKER_PORTS=9000 9001 9002 9003 9004 9005 9006 9007 9008 9009 9010 9011 9012 9013 9014 9015 9016 9017 9018 9019 9020 9021 9022 9023 9024 9025 9026 9027 9028 9029 9030 9031 9032 9033 9034 9035 9036 9037 9038 9039 9040
TRACKING_ENABLED=true
TRACKING_STRATEGY=segment
SEGMENT_WRITE_KEY=7UDdp5K55CyiGgsauOr2pNNujGvmhaeu
API_URL=/api/v1
CONFIG_ROOT=/configs
MAX_CHECK_WORKERS=30
MAX_NOTIFY_WORKERS=30
MAX_SYNC_WORKERS=5
SYNC_JOB_MAX_ATTEMPTS=3
SYNC_JOB_MAX_TIMEOUT_DAYS=3
SYNC_JOB_INIT_RETRY_TIMEOUT_MINUTES=5
USE_CUSTOM_NODE_SELECTOR=false
USE_STREAM_CAPABLE_STATE=true
WORKSPACE_DOCKER_MOUNT=airbyte_workspace
WORKSPACE_ROOT=/workspace
WORKER_ENVIRONMENT=kubernetes
WORKLOAD_API_SERVER_ENABLED=true
WORKLOAD_LAUNCHER_ENABLED=true
WORKLOAD_LAUNCHER_PARALLELISM=10
CONTAINER_ORCHESTRATOR_ENABLED=true
KUBERNETES_CLIENT_MAX_IDLE_CONNECTIONS=100
PUB_SUB_ENABLED=false
DATA_CHECK_TASK_QUEUES=CHECK_CONNECTION
DATA_DISCOVER_TASK_QUEUES=DISCOVER_SCHEMA
DATA_SYNC_TASK_QUEUES=SYNC
CONNECTOR_SPECIFIC_RESOURCE_DEFAULTS_ENABLED=true
FILE_TRANSFER_EPHEMERAL_STORAGE_LIMIT=5G
FILE_TRANSFER_EPHEMERAL_STORAGE_REQUEST=5G
MICRONAUT_ENVIRONMENTS=k8s,control-plane,edition-community
LAUNCHER_MICRONAUT_ENVIRONMENTS=control-plane,oss
WORKERS_MICRONAUT_ENVIRONMENTS=control-plane
CRON_MICRONAUT_ENVIRONMENTS=control-plane
SERVER_MICRONAUT_ENVIRONMENTS=control-plane
"""
[[config.mounts]]
filePath = "./config/docker-dns.Corefile"
content = """
.:53 {
bind eth0
errors
cache 30
forward . 127.0.0.11
}
"""
[[config.mounts]]
filePath = "./config/k3s-resources.yaml"
content = """
apiVersion: v1
kind: ServiceAccount
metadata:
name: airbyte-admin
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: airbyte-admin-role
namespace: default
rules:
- apiGroups: ["*"]
resources:
- configmaps
- endpoints
- jobs
- pods
- pods/log
- pods/exec
- pods/attach
- secrets
verbs: [get, list, watch, create, update, patch, delete]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: airbyte-admin-binding
namespace: default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: airbyte-admin-role
subjects:
- kind: ServiceAccount
name: airbyte-admin
namespace: default
---
apiVersion: v1
kind: Service
metadata:
name: airbyte-db-svc
namespace: default
spec:
type: ExternalName
externalName: db
ports:
- name: postgresql
port: 5432
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: airbyte-minio-svc
namespace: default
spec:
type: ExternalName
externalName: minio
ports:
- name: api
port: 9000
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: airbyte-temporal
namespace: default
spec:
type: ExternalName
externalName: temporal
ports:
- name: grpc
port: 7233
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: airbyte-airbyte-server-svc
namespace: default
spec:
type: ExternalName
externalName: server
ports:
- name: http
port: 8001
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: airbyte-workload-api-server-svc
namespace: default
spec:
type: ExternalName
externalName: workload-api-server
ports:
- name: http
port: 8007
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: airbyte-airbyte-manifest-server-svc
namespace: default
spec:
type: ExternalName
externalName: manifest-server
ports:
- name: http
port: 8080
protocol: TCP
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: coredns
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: system:coredns
rules:
- apiGroups: [""]
resources: [endpoints, services, pods, namespaces]
verbs: [list, watch]
- apiGroups: [discovery.k8s.io]
resources: [endpointslices]
verbs: [list, watch]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: system:coredns
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:coredns
subjects:
- kind: ServiceAccount
name: coredns
namespace: kube-system
---
apiVersion: v1
kind: ConfigMap
metadata:
name: coredns
namespace: kube-system
data:
Corefile: |
.:53 {
errors
health
ready
kubernetes cluster.local in-addr.arpa ip6.arpa {
pods insecure
fallthrough
}
cache 30
loop
reload
loadbalance
forward . 127.0.0.1:1053
}
.:1053 {
bind 127.0.0.1
errors
rewrite stop name regex ^(.+?)(\\.[^.]+\\.svc\\.cluster\\.local|\\.svc\\.cluster\\.local|\\.cluster\\.local)\\.$ {1} answer auto
forward . {$AIRBYTE_K3S_IP}
}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: coredns
namespace: kube-system
labels:
k8s-app: kube-dns
spec:
replicas: 1
selector:
matchLabels:
k8s-app: kube-dns
template:
metadata:
labels:
k8s-app: kube-dns
spec:
priorityClassName: system-cluster-critical
serviceAccountName: coredns
nodeSelector:
kubernetes.io/os: linux
tolerations:
- key: CriticalAddonsOnly
operator: Exists
- key: node-role.kubernetes.io/control-plane
operator: Exists
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: coredns
image: rancher/mirrored-coredns-coredns:1.14.7
imagePullPolicy: IfNotPresent
args: [-conf, /etc/coredns/Corefile]
env:
- name: AIRBYTE_K3S_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
resources:
limits:
memory: 170Mi
requests:
cpu: 100m
memory: 70Mi
ports:
- name: dns
containerPort: 53
protocol: UDP
- name: dns-tcp
containerPort: 53
protocol: TCP
volumeMounts:
- name: config
mountPath: /etc/coredns
readOnly: true
securityContext:
allowPrivilegeEscalation: false
capabilities:
add: [NET_BIND_SERVICE]
drop: [ALL]
readOnlyRootFilesystem: true
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8181
periodSeconds: 2
dnsPolicy: Default
volumes:
- name: config
configMap:
name: coredns
---
apiVersion: v1
kind: Service
metadata:
name: kube-dns
namespace: kube-system
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: CoreDNS
spec:
selector:
k8s-app: kube-dns
clusterIP: 10.43.0.10
ports:
- name: dns
port: 53
protocol: UDP
- name: dns-tcp
port: 53
protocol: TCP
"""
[[config.mounts]]
filePath = "./config/temporal-dynamicconfig.yaml"
content = """
frontend.enableClientVersionCheck:
- value: true
constraints: {}
history.persistenceMaxQPS:
- value: 3000
constraints: {}
frontend.persistenceMaxQPS:
- value: 3000
constraints: {}
frontend.historyMgrNumConns:
- value: 30
constraints: {}
frontend.throttledLogRPS:
- value: 20
constraints: {}
frontend.enableUpdateWorkflowExecution:
- value: true
frontend.enableUpdateWorkflowExecutionAsyncAccepted:
- value: true
history.historyMgrNumConns:
- value: 50
constraints: {}
system.advancedVisibilityWritingMode:
- value: "off"
constraints: {}
history.defaultActivityRetryPolicy:
- value:
InitialIntervalInSeconds: 1
MaximumIntervalCoefficient: 100.0
BackoffCoefficient: 2.0
MaximumAttempts: 0
history.defaultWorkflowRetryPolicy:
- value:
InitialIntervalInSeconds: 1
MaximumIntervalCoefficient: 100.0
BackoffCoefficient: 2.0
MaximumAttempts: 0
limit.blobSize.error:
- value: 15728640
constraints: {}
limit.blobSize.warn:
- value: 10485760
constraints: {}
"""
[[config.mounts]]
filePath = "./scripts/bootstrap-k3s.sh"
content = """
#!/bin/sh
set -eu
source_config=/kube/kubeconfig.yaml
client_config=/kube/config.yaml
until [ -s "$source_config" ]; do
sleep 1
done
sed 's|server: https://127.0.0.1:6443|server: https://k3s:6443|' \
"$source_config" > "$client_config"
chmod 0644 "$client_config"
/bin/kubectl --kubeconfig "$client_config" \
config set-context --current --namespace=default >/dev/null
until /bin/kubectl --kubeconfig "$client_config" get --raw=/readyz >/dev/null 2>&1; do
sleep 2
done
/bin/kubectl --kubeconfig "$client_config" apply -f /config/k3s-resources.yaml
/bin/kubectl --kubeconfig "$client_config" \
--namespace kube-system rollout status deployment/coredns --timeout=180s
/bin/kubectl --kubeconfig "$client_config" create secret generic airbyte-auth-secrets \
--namespace default \
--from-literal=instance-admin-password="$AIRBYTE_ADMIN_PASSWORD" \
--from-literal=instance-admin-client-id="$AIRBYTE_ADMIN_CLIENT_ID" \
--from-literal=instance-admin-client-secret="$AIRBYTE_ADMIN_CLIENT_SECRET" \
--from-literal=jwt-signature-secret="$AIRBYTE_JWT_SIGNATURE_SECRET" \
--from-literal=dataplane-client-id= \
--from-literal=dataplane-client-secret= \
--dry-run=client -o yaml | \
/bin/kubectl --kubeconfig "$client_config" apply -f -
/bin/kubectl --kubeconfig "$client_config" create secret generic airbyte-airbyte-secrets \
--namespace default \
--from-literal=AIRBYTE_DUMMY_SECRET=dummy \
--from-literal=AB_INSTANCE_ADMIN_PASSWORD="$AIRBYTE_ADMIN_PASSWORD" \
--from-literal=AB_INSTANCE_ADMIN_CLIENT_ID="$AIRBYTE_ADMIN_CLIENT_ID" \
--from-literal=AB_INSTANCE_ADMIN_CLIENT_SECRET="$AIRBYTE_ADMIN_CLIENT_SECRET" \
--from-literal=AB_JWT_SIGNATURE_SECRET="$AIRBYTE_JWT_SIGNATURE_SECRET" \
--from-literal=DATABASE_USER="$DATABASE_USER" \
--from-literal=DATABASE_PASSWORD="$DATABASE_PASSWORD" \
--from-literal=CONFIG_DATABASE_REPLICA_USER="$DATABASE_USER" \
--from-literal=CONFIG_DATABASE_REPLICA_PASSWORD="$DATABASE_PASSWORD" \
--from-literal=AWS_ACCESS_KEY_ID="$MINIO_ROOT_USER" \
--from-literal=AWS_SECRET_ACCESS_KEY="$MINIO_ROOT_PASSWORD" \
--from-literal=DATAPLANE_CLIENT_ID= \
--from-literal=DATAPLANE_CLIENT_SECRET= \
--dry-run=client -o yaml | \
/bin/kubectl --kubeconfig "$client_config" apply -f -
"""
[[config.mounts]]
filePath = "./scripts/export-dataplane-credentials.sh"
content = """
#!/bin/sh
set -eu
kubeconfig=/kube/config.yaml
namespace=default
secret_name=airbyte-auth-secrets
credentials_dir=/credentials
client_id_file="$credentials_dir/dataplane-client-id"
client_secret_file="$credentials_dir/dataplane-client-secret"
client_id_tmp="$credentials_dir/.dataplane-client-id.$$"
client_secret_tmp="$credentials_dir/.dataplane-client-secret.$$"
umask 022
mkdir -p "$credentials_dir"
trap 'rm -f "$client_id_tmp" "$client_secret_tmp"' 0 1 2 15
client_id_b64=$(
/bin/kubectl --kubeconfig "$kubeconfig" \
--namespace "$namespace" \
get secret "$secret_name" \
-o 'jsonpath={.data.dataplane-client-id}'
)
client_secret_b64=$(
/bin/kubectl --kubeconfig "$kubeconfig" \
--namespace "$namespace" \
get secret "$secret_name" \
-o 'jsonpath={.data.dataplane-client-secret}'
)
[ -n "$client_id_b64" ] || {
echo "The bootloader did not create a data-plane client ID." >&2
exit 1
}
[ -n "$client_secret_b64" ] || {
echo "The bootloader did not create a data-plane client secret." >&2
exit 1
}
printf '%s' "$client_id_b64" | base64 -d > "$client_id_tmp"
printf '%s' "$client_secret_b64" | base64 -d > "$client_secret_tmp"
client_id=$(cat "$client_id_tmp")
if ! printf '%s' "$client_id" | grep -Eq \
'^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$'; then
echo "The bootloader returned an invalid data-plane client ID." >&2
exit 1
fi
mv -f "$client_id_tmp" "$client_id_file"
mv -f "$client_secret_tmp" "$client_secret_file"
trap - 0 1 2 15
"""
[[config.mounts]]
filePath = "./scripts/init-minio.sh"
content = """
#!/bin/sh
set -eu
for bucket in airbyte-bucket state-storage airbyte-dev-logs; do
until echo "s3.bucket.list" | weed shell -master="$SEAWEEDFS_MASTER" 2>/dev/null | grep -q "^[[:space:]]*$bucket[[:space:]]"; do
echo "s3.bucket.create -name $bucket" | weed shell -master="$SEAWEEDFS_MASTER" >/dev/null 2>&1 || true
sleep 2
done
echo "bucket $bucket ready"
done
"""
[[config.mounts]]
filePath = "./scripts/start-workload-launcher.sh"
content = """
#!/bin/sh
set -eu
client_id_file=/credentials/dataplane-client-id
client_secret_file=/credentials/dataplane-client-secret
[ -s "$client_id_file" ] || {
echo "Missing generated data-plane client ID." >&2
exit 1
}
[ -s "$client_secret_file" ] || {
echo "Missing generated data-plane client secret." >&2
exit 1
}
DATAPLANE_CLIENT_ID=$(cat "$client_id_file")
DATAPLANE_CLIENT_SECRET=$(cat "$client_secret_file")
export DATAPLANE_CLIENT_ID DATAPLANE_CLIENT_SECRET
exec /entrypoint.sh "$@"
"""
+2
View File
@@ -1,3 +1,5 @@
version: "3.8"
services:
akaunting:
image: docker.io/akaunting/akaunting:latest
+2 -2
View File
@@ -24,7 +24,6 @@ port = 80
host = "${main_domain}"
[config]
mounts = []
env = [
# App
"APP_URL=${main_domain}",
@@ -51,4 +50,5 @@ env = [
"MYSQL_RANDOM_ROOT_PASSWORD=yes"
]
# No custom mounts needed; volumes are already defined in compose.
# No custom mounts needed; volumes are already defined in compose.
[[config.mounts]]
+1
View File
@@ -1,3 +1,4 @@
version: '3.3'
services:
alist:
image: xhofe/alist:v3.55.0
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
alltube:
image: dnomd343/alltube:latest
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
ampache:
image: ampache/ampache:latest
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
anonupload:
image: ghcr.io/supernova3339/anonfiles:1
+2
View File
@@ -1,3 +1,5 @@
version: "3.8"
services:
anse-demo:
image: ddiu8081/anse:latest
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
anubis:
image: ghcr.io/techarohq/anubis:latest
@@ -1,3 +1,4 @@
version: "3.8"
services:
anythingllm:
image: mintplexlabs/anythingllm:latest
+2 -4
View File
@@ -2,7 +2,7 @@
"id": "anythingllm",
"name": "AnythingLLM",
"version": "latest",
"description": "AnythingLLM is a private AI chat app for working with your own documents. Self-host it on your own server with Dokploy, which deploys AnythingLLM as a Docker Compose service in a few clicks.",
"description": "AnythingLLM is a private, self-hosted, and local document chatbot platform that allows you to chat with your documents using various LLM providers.",
"logo": "logo.png",
"links": {
"github": "https://github.com/Mintplex-Labs/anything-llm",
@@ -13,7 +13,5 @@
"ai",
"llm",
"chatbot"
],
"seoTitle": "Self-Host AnythingLLM in minutes",
"seoDescription": "Private AI chatbot for your documents. Self-host AnythingLLM on Dokploy in minutes – no manual setup needed."
]
}
-1
View File
@@ -1,4 +1,3 @@
# dokploy: allow-host-ports — Anytype clients speak the any-sync protocol (TCP 33010, UDP/QUIC 33020) directly against the server; it is not HTTP, so Traefik cannot route it.
# Example: Any-Sync-Bundle with embedded MongoDB and Redis (all-in-one image)
#
# Usage:
+2 -4
View File
@@ -2,7 +2,7 @@
"id": "anytype",
"name": "Anytype",
"version": "latest",
"description": "Anytype is a private, offline-first app for notes and personal knowledge. Self-host it on your own server with Dokploy, which deploys Anytype as a Docker Compose service in a few clicks.",
"description": "Anytype is a personal knowledge base—your digital brain—that lets you gather, connect and remix all kinds of information. Create pages, tasks, wikis, journals—even entire apps—and define your own data model while your data stays offline-first, private and encrypted across devices.\n\nAfter installation, you can view the Anytype client configuration by running `cat /data/client-config.yml` inside the service container.",
"logo": "logo.png",
"links": {
"github": "https://github.com/grishy/any-sync-bundle",
@@ -13,7 +13,5 @@
"note-taking",
"local-first",
"peer-to-peer"
],
"seoTitle": "Self-Host Anytype with Dokploy",
"seoDescription": "Private, offline-first personal knowledge base. Self-host Anytype on Dokploy – view your client config afterward with a quick command inside the container."
]
}
+2 -4
View File
@@ -2,7 +2,7 @@
"id": "appflowy",
"name": "App Flowy",
"version": "0.9.3",
"description": "AppFlowy is a workspace app for notes, docs, and projects, and an open-source alternative to Notion. Self-host it on your own server with Dokploy, which deploys AppFlowy as a Docker Compose service in a few clicks.",
"description": "AppFlowy is an open-source alternative to Notion. You are in charge of your data and customizations.",
"links": {
"github": "https://github.com/AppFlowy-IO/AppFlowy",
"website": "https://appflowy.io/",
@@ -15,7 +15,5 @@
"notes",
"knowledge-base",
"notion-alternative"
],
"seoTitle": "Self-Host AppFlowy in minutes",
"seoDescription": "Workspace app, an alternative to Notion. Self-host AppFlowy on Dokploy in minutes – no manual setup needed."
]
}
@@ -1,3 +1,4 @@
version: "3.8"
services:
apprise-api:
image: linuxserver/apprise-api:latest
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
appsmith:
image: appsmith/appsmith-ee:v1.94
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -1,7 +1,7 @@
{
"id": "appwrite",
"name": "Appwrite",
"version": "2.7.0",
"version": "1.9.5",
"description": "Appwrite is an end-to-end platform for building Web, Mobile, Native, or Backend apps, packaged as a set of Docker microservices. It includes both a backend server and a fully integrated hosting solution for deploying static and server-side rendered frontends. Appwrite abstracts the complexity and repetitiveness required to build modern apps from scratch and allows you to build secure, full-stack applications faster.\nUsing Appwrite, you can easily integrate your app with user authentication and multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, messaging, and more services.",
"links": {
"github": "https://github.com/appwrite/appwrite",
@@ -12,7 +12,7 @@
"tags": [
"database",
"firebase",
"postgresql",
"mariadb",
"mongodb",
"hosting",
"self-hosted"
+48 -308
View File
@@ -2,78 +2,42 @@
main_domain = "${domain}"
functions_domain = "functions.${main_domain}"
sites_domain = "sites.${main_domain}"
mqtt_domain = "mqtt.${main_domain}"
openssl_key = "${password:32}"
notifications_tracking_secret = "${password:32}"
db_pw = "${password:32}"
db_root_pw = "${password:32}"
db_user_pw = "${password:32}"
usage_pw = "${password:32}"
executor_secret = "${password:32}"
jobs_secret = "${password:32}"
geo_secret = "${password:32}"
# Optional AI code review of GitHub pull requests. Uncomment together with the
# _APP_REVIEWS_* variables and the appwrite-hansi service in docker-compose.yml.
# reviews_secret = "${password:32}"
console_domain = "console.${main_domain}"
[config]
# Build jobs and runtimes join <appName>_default, which isolated deployments never create
# (every service sits on the external <appName> network instead).
isolated = false
env = [
"_APP_ENV=production",
"_APP_VERSION=2.7.0",
"_APP_MEMORY_LIMIT=512M",
"_APP_EDITION=self-hosted",
"_APP_LOCALE=en",
"_APP_POOL_ADAPTER=stack",
"_APP_WORKER_PER_CORE=6",
"_APP_OPTIONS_ABUSE=enabled",
"_APP_OPTIONS_ABUSE_INCREASED_LIMIT_PROJECTS=",
"_APP_OPTIONS_FORCE_HTTPS=disabled",
"_APP_OPTIONS_ROUTER_FORCE_HTTPS=disabled",
"_APP_OPTIONS_ROUTER_PROTECTION=disabled",
"_APP_ROUTER_AUTO_CERTIFICATES=enabled",
"_APP_LOCKING_ENABLED=enabled",
"_APP_OPENSSL_KEY_V1=${openssl_key}",
"_APP_OPENSSL_KEY_V2=",
"_APP_OPENSSL_KEY_CURRENT=1",
"_APP_OPENSSL_KEY_OLDEST=1",
"_APP_NOTIFICATIONS_TRACKING_SECRET=${notifications_tracking_secret}",
"_APP_NOTIFICATIONS_PUSH_APNS=",
"_APP_NOTIFICATIONS_PUSH_APNS_KEY=",
"_APP_DOMAIN=${main_domain}",
"_APP_CONSOLE_DOMAIN=${console_domain}",
"_APP_CONSOLE_URL=https://${console_domain}",
"_APP_CONSOLE_HOSTNAMES=${console_domain}",
"_APP_CONSOLE_DOMAIN=${main_domain}",
"_APP_CONSOLE_TRUSTED_PROJECTS=",
"_APP_CUSTOM_DOMAIN_DENY_LIST=example.com,test.com,app.example.com",
"_APP_DOMAIN_FUNCTIONS=${functions_domain}",
"_APP_DOMAIN_FUNCTIONS_FALLBACK=",
"_APP_DOMAIN_SITES=${sites_domain}",
"_APP_DOMAIN_TARGET_CNAME=localhost",
"_APP_DOMAIN_TARGET_AAAA=::1",
"_APP_DOMAIN_TARGET_A=127.0.0.1",
"_APP_DOMAIN_TARGET_CAA=",
"_APP_DNS=8.8.8.8",
"_APP_DNS_EXTERNAL=",
"_APP_ALLOWED_INTERNAL_ADDRESSES=",
"_APP_TRUSTED_HEADERS=x-forwarded-for",
"_APP_CONSOLE_WHITELIST_ROOT=enabled",
"_APP_CONSOLE_WHITELIST_EMAILS=",
"_APP_CONSOLE_WHITELIST_IPS=",
"_APP_CONSOLE_HOSTNAMES=",
"_APP_CONSOLE_SCHEMA=appwriteio",
"_APP_CONSOLE_SESSION_ALERTS=disabled",
"_APP_CONSOLE_COUNTRIES_DENYLIST=",
"_APP_CONSOLE_GITHUB_APP_ID=",
"_APP_CONSOLE_GITHUB_SECRET=",
"_APP_CONSOLE_GITLAB_APP_ID=",
"_APP_CONSOLE_GITLAB_SECRET=",
"_APP_CONSOLE_GITLAB_ENDPOINT=",
"_APP_CONSOLE_BITBUCKET_APP_ID=",
"_APP_CONSOLE_BITBUCKET_SECRET=",
"_APP_CONSOLE_GOOGLE_APP_ID=",
"_APP_CONSOLE_GOOGLE_SECRET=",
"_APP_SYSTEM_EMAIL_NAME=Appwrite",
"_APP_SYSTEM_EMAIL_ADDRESS=noreply@appwrite.io",
"_APP_SYSTEM_TEAM_EMAIL=team@appwrite.io",
@@ -82,58 +46,33 @@ env = [
"_APP_EMAIL_CERTIFICATES=",
"_APP_COMPRESSION_ENABLED=enabled",
"_APP_COMPRESSION_MIN_SIZE_BYTES=1024",
"_APP_USAGE_STATS=enabled",
"_APP_USAGE_AGGREGATION_INTERVAL=30",
"_APP_STATS_RESOURCES_INTERVAL=30",
"_APP_LOGGING_PROVIDER=",
"_APP_LOGGING_CONFIG=",
"_APP_LOGGING_FORMAT=pretty",
"_APP_GEO_ENDPOINT=http://appwrite-geo/v1",
"_APP_GEO_SECRET=${geo_secret}",
"_APP_LOGGING_CONFIG_REALTIME=",
"_APP_EXPERIMENT_LOGGING_PROVIDER=",
"_APP_EXPERIMENT_LOGGING_CONFIG=",
"_APP_REDIS_HOST=redis",
"_APP_REDIS_PORT=6379",
"_APP_REDIS_USER=",
"_APP_REDIS_PASS=",
"_APP_DB_ADAPTER=postgresql",
"_APP_DB_HOST=postgresql",
"_APP_DB_PORT=5432",
"_APP_DB_ADAPTER=mongodb",
"_APP_DB_HOST=mongodb",
"_APP_DB_PORT=27017",
"_APP_DB_SCHEMA=appwrite",
"_APP_DB_USER=user",
"_APP_DB_PASS=${db_pw}",
"_APP_DB_PASS=${db_user_pw}",
"_APP_DB_ROOT_PASS=${db_root_pw}",
"_APP_DATABASE_SHARED_TABLES=",
"_APP_DATABASE_SHARED_NAMESPACE=",
"_APP_LIMIT_DATABASE_BATCH=100",
"_APP_DOCUMENTSDB=enabled",
"_APP_DB_ADAPTER_DOCUMENTSDB=mongodb",
"_APP_DB_HOST_DOCUMENTSDB=mongodb",
"_APP_DB_PORT_DOCUMENTSDB=27017",
"_APP_DB_SCHEMA_DOCUMENTSDB=",
"_APP_DB_USER_DOCUMENTSDB=",
"_APP_DB_PASS_DOCUMENTSDB=",
"_APP_CONNECTIONS_DATABASE_DOCUMENTSDB=",
"_APP_VECTORSDB=enabled",
"_APP_DB_ADAPTER_VECTORSDB=postgresql",
"_APP_DB_HOST_VECTORSDB=postgresql",
"_APP_DB_PORT_VECTORSDB=5432",
"_APP_DB_ADAPTER_VECTORSDB=",
"_APP_DB_HOST_VECTORSDB=",
"_APP_DB_PORT_VECTORSDB=",
"_APP_DB_SCHEMA_VECTORSDB=",
"_APP_DB_USER_VECTORSDB=",
"_APP_DB_PASS_VECTORSDB=",
"_APP_CONNECTIONS_DATABASE_VECTORSDB=",
"_APP_EMBEDDING=disabled",
"_APP_USAGE_STATS=enabled",
"_APP_USAGE_PASS=${usage_pw}",
"_APP_CONNECTIONS_DB_USAGE=http://appwrite:${usage_pw}@clickhouse:8123/appwrite",
"_APP_POOL_SIZE_USAGE=2",
"_APP_CONNECTIONS_DB_EXECUTIONS=http://appwrite:${usage_pw}@clickhouse:8123/appwrite",
"_APP_POOL_SIZE_EXECUTIONS=2",
"_APP_MAINTENANCE_RETENTION_USAGE_TTL=180",
"_APP_STATS_USAGE_QUEUE_NAME=v1-stats-usage",
"_APP_STATS_RESOURCES_QUEUE_NAME=v1-stats-resources",
"_APP_MAINTENANCE_QUEUE_NAME=v1-maintenance",
"_APP_STATS_RESOURCES_INTERVAL=3600",
"_APP_ALERTS_INTERVAL=60",
"_APP_ALERTS_USAGE_LAG=120",
"_APP_MQTT_REPLAY_DEPTH=5",
"_APP_MQTT_MAX_PACKET_SIZE=64000",
"_APP_LIMIT_REALTIME_SUBSCRIPTIONS=100",
"_APP_LIMIT_REALTIME_CHANNELS=100",
"_APP_LIMIT_REALTIME_QUERIES=100",
"_APP_SMTP_HOST=",
"_APP_SMTP_PORT=",
"_APP_SMTP_SECURE=",
@@ -142,11 +81,8 @@ env = [
"_APP_SMS_PROVIDER=",
"_APP_SMS_FROM=",
"_APP_SMS_PROJECTS_DENY_LIST=",
"_APP_PWNED_PASSWORDS_DSN=none://localhost",
"_APP_STORAGE_LIMIT=30000000",
"_APP_STORAGE_PREVIEW_LIMIT=20000000",
"_APP_AUTOGRAVITY_HOST=http://appwrite-autogravity:8080",
"_APP_EXIFTOOL_HOST=http://appwrite-exiftool:8080",
"_APP_STORAGE_ANTIVIRUS=disabled",
"_APP_STORAGE_ANTIVIRUS_HOST=clamav",
"_APP_STORAGE_ANTIVIRUS_PORT=3310",
@@ -156,7 +92,6 @@ env = [
"_APP_STORAGE_S3_REGION=us-east-1",
"_APP_STORAGE_S3_BUCKET=",
"_APP_STORAGE_S3_ENDPOINT=",
"_APP_STORAGE_S3_PATH_STYLE=",
"_APP_STORAGE_DO_SPACES_ACCESS_KEY=",
"_APP_STORAGE_DO_SPACES_SECRET=",
"_APP_STORAGE_DO_SPACES_REGION=us-east-1",
@@ -174,46 +109,34 @@ env = [
"_APP_STORAGE_WASABI_REGION=eu-central-1",
"_APP_STORAGE_WASABI_BUCKET=",
"_APP_COMPUTE_SIZE_LIMIT=30000000",
"_APP_COMPUTE_BUILD_SIZE_LIMIT=2000000000",
"_APP_COMPUTE_BUILD_TIMEOUT=2700",
"_APP_COMPUTE_BUILD_TIMEOUT=900",
"_APP_COMPUTE_CPUS=0",
"_APP_COMPUTE_MEMORY=0",
"_APP_COMPUTE_INACTIVE_THRESHOLD=60",
"_APP_COMPUTE_MAINTENANCE_INTERVAL=3600",
"_APP_OPEN_RUNTIMES_NFT=enabled",
"_APP_COMPUTE_RUNTIMES_NETWORK=dokploy-network",
"_APP_FUNCTIONS_TIMEOUT=900",
"_APP_FUNCTIONS_CREATION_ABUSE_LIMIT=5000",
"_APP_FUNCTIONS_SCHEDULE_SPREAD=0",
"_APP_FUNCTIONS_RUNTIMES=node-22,node-24,node-26,python-3.12,php-8.3,ruby-3.3,dart-3.5,go-1.23,rust-1.83,bun-1.1,deno-1.46,java-21.0,dotnet-8.0",
"_APP_FUNCTIONS_RUNTIMES=node-22,python-3.12,php-8.3,ruby-3.3,dart-3.5,go-1.23,rust-1.83,bun-1.1,deno-1.46,java-21.0,dotnet-8.0",
"_APP_SITES_TIMEOUT=900",
"_APP_SITES_RUNTIMES=static-1,node-22",
"_APP_EXECUTOR_SECRET=${executor_secret}",
"_APP_EXECUTOR_HOST=http://openruntimes-executor/v1",
"_APP_EXECUTOR_IMAGES=openruntimes/node:v5-22,openruntimes/python:v5-3.12,openruntimes/php:v5-8.3,openruntimes/static:v5-1",
"_APP_EXECUTOR_CONNECTION_STORAGE=local://localhost",
"_APP_JOBS_HOST=http://orchestrator:8080",
"_APP_JOBS_SECRET=${jobs_secret}",
"_APP_JOBS_ENDPOINT=http://appwrite",
# Reviews are opt-in: the shared secret turns the /v1/reviews API on, and the
# console hides the screen in the self-hosted profile regardless.
# "_APP_REVIEWS_SECRET=${reviews_secret}",
# "_APP_REVIEWS_MODEL=anthropic/claude-sonnet-4.5",
# "_APP_REVIEWS_VERIFY_MODEL=",
# "_APP_REVIEWS_AI_GATEWAY_KEY=",
"_APP_OPEN_RUNTIMES_NFT=enabled",
"_APP_BROWSER_HOST=http://appwrite-browser:3000/v1",
"_APP_WORKER_SCREENSHOTS_ROUTER=http://appwrite",
"_APP_DOCKER_HUB_USERNAME=",
"_APP_DOCKER_HUB_PASSWORD=",
"_APP_MAINTENANCE_INTERVAL=86400",
"_APP_MAINTENANCE_INACTIVE_INTERVAL=604800",
"_APP_MAINTENANCE_START_TIME=00:00",
"_APP_MAINTENANCE_RETENTION_CACHE=2592000",
"_APP_MAINTENANCE_RETENTION_EXECUTION=1209600",
"_APP_MAINTENANCE_RETENTION_AUDIT=1209600",
"_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=15778800",
"_APP_MAINTENANCE_RETENTION_ABUSE=86400",
"_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000",
"_APP_MAINTENANCE_RETENTION_SCHEDULES=86400",
"_APP_MAINTENANCE_RETENTION_ALERTS=7776000",
"_APP_INTERVAL_DOMAIN_VERIFICATION=120",
"_APP_INTERVAL_CLEANUP_STALE_EXECUTIONS=300",
"_APP_GRAPHQL_INTROSPECTION=enabled",
@@ -227,55 +150,32 @@ env = [
"_APP_VCS_GITHUB_CLIENT_ID=",
"_APP_VCS_GITHUB_CLIENT_SECRET=",
"_APP_VCS_GITHUB_WEBHOOK_SECRET=",
"_APP_VCS_GITEA_ENDPOINT=",
"_APP_VCS_GITEA_BROWSER_ENDPOINT=",
"_APP_VCS_GITEA_CLIENT_ID=",
"_APP_VCS_GITEA_CLIENT_SECRET=",
"_APP_VCS_GITEA_WEBHOOK_SECRET=",
"_APP_VCS_GITLAB_ENDPOINT=",
"_APP_VCS_GITLAB_CLIENT_ID=",
"_APP_VCS_GITLAB_CLIENT_SECRET=",
"_APP_VCS_GITLAB_WEBHOOK_SECRET=",
"_APP_VCS_BITBUCKET_CLIENT_ID=",
"_APP_VCS_BITBUCKET_CLIENT_SECRET=",
"_APP_VCS_BITBUCKET_WEBHOOK_SECRET=",
"_APP_VCS_ORIGIN_CLIENT_ID=",
"_APP_VCS_ORIGIN_PRIVATE_KEY=",
"_APP_VCS_ENTIRE_PLUGIN=",
"_APP_VCS_ENTIRE_PRIVATE_KEY=",
"_APP_VCS_ENTIRE_ISSUER=",
"_APP_VCS_ENTIRE_ENDPOINT=",
"_APP_VCS_WEBHOOK_URL=",
"_APP_MIGRATION_HOST=appwrite",
"_APP_MIGRATIONS_FIREBASE_CLIENT_ID=",
"_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=",
"_APP_DB_ROOT_PASS=${db_root_pw}",
"_APP_DB_USER_PASS=${db_user_pw}",
"_APP_DB_MAX_CONNECTIONS=500",
"_APP_ASSISTANT_OPENAI_API_KEY=",
]
[[config.mounts]]
filePath = "mongo-init.js"
content = """// mongo-init.js
// Switch to the admin database
const adminDb = db.getSiblingDB('admin');
// Get username and password from environment variables
const username = process.env.MONGO_INITDB_USERNAME;
const password = process.env.MONGO_INITDB_PASSWORD;
const database = process.env.MONGO_INITDB_DATABASE;
// Idempotent: the official entrypoint races the real server on port 27017 when
// initialising a fresh volume (appwrite/appwrite#13593), so this script may run
// more than once. Skip if the user already exists.
if (adminDb.getUser(username) === null) {
adminDb.createUser({
user: username,
pwd: password,
roles: [
{ role: 'readWrite', db: database }
]
});
}
// Create the user
adminDb.createUser({
user: username,
pwd: password,
roles: [
{ role: 'readWrite', db: database }
]
});
"""
[[config.mounts]]
@@ -283,6 +183,7 @@ filePath = "mongo-entrypoint.sh"
content = """#!/bin/bash
set -e
# Fix keyfile permissions if mounted from volume
KEYFILE_PATH="/data/keyfile/mongo-keyfile"
if [ ! -f "$KEYFILE_PATH" ]; then
@@ -294,183 +195,16 @@ fi
chmod 400 "$KEYFILE_PATH"
chown mongodb:mongodb "$KEYFILE_PATH" 2>/dev/null || chown 999:999 "$KEYFILE_PATH"
# The standard entrypoint initialises an empty data directory with a second
# mongod on 27017, stopped with `mongod --shutdown`. That returns once the
# server clears <dbpath>/mongod.lock, several steps before it exits and
# releases the port, and the real server binds a millisecond after it starts --
# so a slow shutdown tail leaves it exiting 48, "Address already in use",
# taking the container with it (appwrite/appwrite#13593). Initialise here
# instead, on a port the real server never binds, and hand over a directory
# the standard entrypoint has nothing left to do.
INIT_MARKER=/data/db/.appwrite-initialised
if [ ! -e "$INIT_MARKER" ]; then
INIT_PORT=27018
echo "Initialising MongoDB data directory..."
find -L /data/db \\! -user mongodb -exec chown mongodb '{}' +
export MONGO_INITDB_DATABASE="${MONGO_INITDB_DATABASE:-test}"
gosu mongodb mongod --dbpath /data/db --bind_ip 127.0.0.1 --port "$INIT_PORT" &
INIT_SERVER=$!
READY=
for _ in $(seq 1 30); do
if mongosh --host 127.0.0.1 --port "$INIT_PORT" --quiet --eval 'quit(0)' > /dev/null 2>&1; then
READY=1
break
fi
if ! kill -0 "$INIT_SERVER" 2>/dev/null; then
break
fi
sleep 1
done
if [ -z "$READY" ]; then
echo "MongoDB did not accept connections for initialisation" >&2
exit 1
fi
mongosh --host 127.0.0.1 --port "$INIT_PORT" --quiet admin --eval '
const username = process.env.MONGO_INITDB_ROOT_USERNAME;
if (db.getUser(username) === null) {
db.createUser({
user: username,
pwd: process.env.MONGO_INITDB_ROOT_PASSWORD,
roles: [{ role: "root", db: "admin" }]
});
}
'
mongosh --host 127.0.0.1 --port "$INIT_PORT" --quiet "$MONGO_INITDB_DATABASE" /mongo-init.js
touch "$INIT_MARKER"
kill -TERM "$INIT_SERVER"
wait "$INIT_SERVER"
echo "MongoDB data directory initialised."
fi
# Use MongoDB's standard entrypoint with our command
exec docker-entrypoint.sh mongod --replSet rs0 --bind_ip_all --auth --keyFile "$KEYFILE_PATH"
"""
[[config.mounts]]
filePath = "clickhouse-config.xml"
content = """<?xml version="1.0"?>
<!--
Retention for ClickHouse's own system log tables.
Every <ttl> in the image's config.xml sits inside an XML comment, so these
tables keep every row forever, and the metric ones add a row per second
whether or not the instance serves traffic. Left alone they outgrow the
usage data they sit next to and fill the volume.
When a window here changes, ClickHouse replaces the table on the next
restart and keeps the old one, rows and all, as <log>_<N>.
clickhouse-init.sh gives those old tables the same window.
-->
<clickhouse>
<!-- The metric, trace and profile logs sample the server every second whether
or not Appwrite serves traffic, and nothing reads them back, so their
writes and the merges behind them are pure overhead. -->
<asynchronous_metric_log remove="1"/>
<metric_log remove="1"/>
<histogram_metric_log remove="1"/>
<query_metric_log remove="1"/>
<processors_profile_log remove="1"/>
<trace_log remove="1"/>
<!-- text_log repeats the server log the container already writes. -->
<text_log remove="1"/>
<!-- Kept for debugging, capped so they cannot fill the volume. -->
<asynchronous_insert_log><ttl>event_date + INTERVAL 3 DAY DELETE</ttl></asynchronous_insert_log>
<query_log><ttl>event_date + INTERVAL 7 DAY DELETE</ttl></query_log>
<query_views_log><ttl>event_date + INTERVAL 7 DAY DELETE</ttl></query_views_log>
<query_thread_log><ttl>event_date + INTERVAL 7 DAY DELETE</ttl></query_thread_log>
<part_log><ttl>event_date + INTERVAL 7 DAY DELETE</ttl></part_log>
<background_schedule_pool_log><ttl>event_date + INTERVAL 7 DAY DELETE</ttl></background_schedule_pool_log>
<!-- Longer, so it still covers a report that reaches us late. crash_log is
deliberately left alone: it is tiny and worth keeping. -->
<error_log><ttl>event_date + INTERVAL 14 DAY DELETE</ttl></error_log>
</clickhouse>
"""
[[config.mounts]]
filePath = "clickhouse-init.sh"
content = """#!/bin/bash
# The ClickHouse entrypoint sources this file, so a subshell keeps these options out of it.
(
set -euo pipefail
client() {
clickhouse-client --host 127.0.0.1 --user "$CLICKHOUSE_USER" --password "$CLICKHOUSE_PASSWORD" "$@"
}
# Flushing replaces log tables whose definition changed, keeping each old table as <log>_<N>.
client --query 'SYSTEM FLUSH LOGS'
# Tables left behind never expire on their own: take the TTL of the log that
# replaced this one, or a week when the log is no longer written at all.
# The named logs must match the ones clickhouse-config.xml removes: a log that
# is still written gets replaced on the next restart if its TTL is altered here.
client --format TSVRaw <<'SQL' | client --multiquery
SELECT concat('ALTER TABLE system.', stale.name, ' MODIFY TTL ', if(active.name = '', 'event_date + INTERVAL 7 DAY DELETE', splitByString(' SETTINGS ', splitByString(' TTL ', active.engine_full)[2])[1]), ';')
FROM (
SELECT name, splitByChar('_', name)[-1] AS suffix, arrayStringConcat(arrayPopBack(splitByChar('_', name)), '_') AS log
FROM system.tables
WHERE database = 'system'
AND position(engine_full, ' TTL ') = 0
AND endsWith(engine, 'MergeTree')
AND name IN (SELECT table FROM system.columns WHERE database = 'system' AND name = 'event_date' AND type = 'Date')
) AS stale
LEFT JOIN system.tables AS active
ON active.database = 'system'
AND active.name = stale.log
AND position(active.engine_full, ' TTL ') > 0
WHERE (endsWith(stale.log, '_log') AND toUInt64OrNull(stale.suffix) IS NOT NULL)
OR stale.name IN ('asynchronous_metric_log', 'metric_log', 'histogram_metric_log', 'query_metric_log', 'processors_profile_log', 'trace_log', 'text_log')
SQL
)
"""
[[config.domains]]
serviceName = "appwrite-console"
port = 3000
serviceName = "appwrite"
port = 80
host = "${main_domain}"
path = "/"
[[config.domains]]
serviceName = "appwrite"
port = 80
host = "${main_domain}"
path = "/v1"
[[config.domains]]
serviceName = "appwrite"
port = 80
host = "${main_domain}"
path = "/.well-known"
[[config.domains]]
serviceName = "appwrite-realtime"
port = 80
host = "${main_domain}"
path = "/v1/realtime"
# --- Dedicated Console domain ---
# The Console SPA is served at the root of ${console_domain}, with /v1 and
# /v1/realtime proxied to the API and Realtime so the Console reaches the API
# on its own origin.
[[config.domains]]
serviceName = "appwrite-console"
port = 3000
host = "${console_domain}"
path = "/"
[[config.domains]]
serviceName = "appwrite"
port = 80
host = "${console_domain}"
path = "/v1"
[[config.domains]]
serviceName = "appwrite-realtime"
port = 80
host = "${console_domain}"
path = "/v1/realtime"
[[config.domains]]
serviceName = "appwrite"
port = 80
@@ -484,7 +218,13 @@ host = "${functions_domain}"
path = "/"
[[config.domains]]
serviceName = "appwrite-mqtt"
port = 8083
host = "${mqtt_domain}"
path = "/"
serviceName = "appwrite-console"
port = 80
host = "${main_domain}"
path = "/console"
[[config.domains]]
serviceName = "appwrite-realtime"
port = 80
host = "${main_domain}"
path = "/v1/realtime"
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
arangodb:
image: arangodb:3.12.4
+2
View File
@@ -1,3 +1,5 @@
version: "3.8"
# Arche — AI workspace platform that spawns per-user OpenCode containers
# via a Docker socket proxy.
#
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
argilla-web:
image: argilla/argilla-server:latest
@@ -1,3 +1,4 @@
version: "3.8"
services:
audiobookshelf:
image: ghcr.io/advplyr/audiobookshelf:2.19.4
+2 -5
View File
@@ -2,7 +2,7 @@
"id": "authelia",
"name": "Authelia",
"version": "latest",
"description": "Authelia is an open-source authentication portal for single sign-on (SSO) and two-factor authentication. Self-host it on your own server with Dokploy, which deploys Authelia as a Docker Compose service in a few clicks.",
"description": "The Single Sign-On Multi-Factor portal for web apps. An open-source authentication and authorization server providing 2FA and SSO via web portal.",
"logo": "authelia.png",
"links": {
"github": "https://github.com/authelia/authelia",
@@ -17,8 +17,5 @@
"security",
"reverse-proxy",
"ldap"
],
"seoTitle": "Authelia Docker Compose Setup",
"seoDescription": "Single sign-on and two-factor auth portal. Deploy Authelia with Docker Compose on Dokploy in minutes – free, open source, self-hosted.",
"newConfig": true
]
}
+30 -13
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
postgresql:
image: docker.io/library/postgres:18-alpine
@@ -17,20 +18,34 @@ services:
expose:
- 5432
redis:
image: docker.io/library/redis:alpine
command: --save 60 1 --loglevel warning
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
start_period: 20s
interval: 30s
retries: 5
timeout: 3s
volumes:
- redis:/data
expose:
- 6379
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.8.2}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.2.2}
restart: unless-stopped
command: server
shm_size: 512mb
environment:
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
AUTHENTIK_WEB__BASE_URL: ${AUTHENTIK_WEB__BASE_URL}
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: ${PG_USER}
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB}
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
volumes:
- data:/data
- media:/media
- custom-templates:/templates
expose:
- 9000
@@ -38,36 +53,38 @@ services:
depends_on:
postgresql:
condition: service_healthy
redis:
condition: service_healthy
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.8.2}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2026.2.2}
restart: unless-stopped
command: worker
shm_size: 512mb
environment:
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
AUTHENTIK_WEB__BASE_URL: ${AUTHENTIK_WEB__BASE_URL}
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: ${PG_USER}
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB}
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
user: root
volumes:
- data:/data
- /var/run/docker.sock:/var/run/docker.sock
- media:/media
- certs:/certs
- custom-templates:/templates
depends_on:
postgresql:
condition: service_healthy
# Create the worker after the server so both don't populate the fresh
# shared "data" volume from the image at the same time (race on /data/media).
server:
condition: service_started
redis:
condition: service_healthy
volumes:
database:
driver: local
data:
redis:
driver: local
media:
driver: local
certs:
driver: local
+3 -6
View File
@@ -1,8 +1,8 @@
{
"id": "authentik",
"name": "Authentik",
"version": "2026.8.2",
"description": "Authentik is an identity provider for single sign-on (SSO) authorization and authentication, with support for SAML, OAuth2, OIDC, and more. Self-host it on your own server with Dokploy, which deploys Authentik as a Docker Compose service in a few clicks.",
"version": "2026.2.2",
"description": "Authentik is an open-source Identity Provider for authentication and authorization. It provides a comprehensive solution for managing user authentication, authorization, and identity federation with support for SAML, OAuth2, OIDC, and more.",
"links": {
"github": "https://github.com/goauthentik/authentik",
"website": "https://goauthentik.io/",
@@ -17,8 +17,5 @@
"saml",
"oauth2",
"self-hosted"
],
"seoTitle": "Authentik Docker Compose Setup",
"seoDescription": "Identity provider for SSO and authentication. Deploy Authentik with Docker Compose on Dokploy in minutes – free, open source, self-hosted.",
"newConfig": true
]
}
+1 -2
View File
@@ -22,6 +22,5 @@ PG_USER = "${pg_user}"
PG_DB = "${pg_db}"
PG_PASS = "${password:32}" # Password for PostgreSQL authentication
AUTHENTIK_SECRET_KEY = "${password:64}" # Secret key for Authentik authentication
AUTHENTIK_WEB__BASE_URL = "https://${main_domain}"
AUTHENTIK_IMAGE = "ghcr.io/goauthentik/server"
AUTHENTIK_TAG = "2026.8.2"
AUTHENTIK_TAG = "2026.2.2"
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
authorizer:
image: lakhansamani/authorizer:1.4.4
+1 -1
View File
@@ -1,6 +1,6 @@
services:
autobase-console:
image: autobase/console:2.11.0
image: autobase/console:2.7.2
restart: unless-stopped
expose:
- "80"
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "autobase",
"name": "Autobase",
"version": "2.11.0",
"version": "2.7.2",
"description": "Autobase for PostgreSQL® is an open-source alternative to cloud-managed databases (self-hosted DBaaS).",
"links": {
"github": "https://github.com/vitabaks/autobase",
-57
View File
@@ -1,57 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="868.000000pt" height="868.000000pt" viewBox="0 0 868.000000 868.000000"
preserveAspectRatio="xMidYMid meet">
<metadata>
Created by potrace 1.11, written by Peter Selinger 2001-2013
</metadata>
<g transform="translate(0.000000,868.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M4184 7124 c-89 -99 -106 -117 -173 -190 -31 -33 -88 -96 -127 -140
-40 -44 -85 -94 -100 -110 -34 -37 -161 -177 -187 -208 -10 -11 -58 -64 -106
-116 -48 -52 -139 -151 -201 -220 -62 -69 -134 -148 -159 -175 -25 -28 -66
-73 -91 -100 -39 -43 -173 -191 -249 -274 -12 -14 -60 -66 -105 -115 -44 -50
-88 -97 -96 -106 -8 -9 -49 -54 -90 -100 -41 -46 -82 -91 -90 -100 -8 -9 -55
-61 -105 -115 -49 -55 -111 -122 -136 -150 -25 -27 -65 -72 -90 -99 -24 -27
-53 -59 -64 -70 -11 -12 -56 -61 -100 -110 -44 -50 -91 -101 -105 -116 -14
-14 -56 -61 -94 -103 -76 -85 -75 -84 -196 -216 -47 -52 -93 -103 -103 -115
-10 -11 -58 -63 -105 -115 -48 -51 -95 -103 -105 -115 -18 -21 -138 -152 -187
-206 -14 -15 -56 -62 -95 -105 -38 -42 -83 -92 -100 -109 -16 -18 -66 -72
-110 -121 -79 -88 -189 -209 -210 -231 -5 -6 -44 -48 -85 -95 -41 -46 -84 -93
-95 -104 -11 -12 -38 -41 -59 -66 -22 -24 -82 -90 -133 -146 -52 -56 -103
-113 -113 -126 l-19 -24 72 -76 c40 -41 162 -169 272 -283 231 -239 400 -415
509 -529 l77 -79 22 26 c26 29 173 192 202 222 11 12 56 62 100 111 44 50 83
92 86 95 3 3 54 59 114 125 60 66 126 138 146 160 77 85 93 102 153 169 33 37
72 80 86 95 41 45 193 213 241 266 24 27 53 59 64 70 11 12 58 64 105 115 47
52 96 105 109 119 13 14 53 59 90 100 36 41 73 81 81 90 9 9 56 61 105 116 50
55 92 102 95 105 3 3 52 57 110 120 57 63 144 160 194 214 50 55 100 110 111
122 70 77 192 212 326 359 138 152 173 191 244 269 11 13 61 67 110 121 50 54
98 107 108 119 10 12 35 39 55 61 21 22 78 85 127 140 50 54 113 123 140 153
l51 54 139 -147 c77 -80 165 -172 195 -204 86 -90 352 -369 420 -441 85 -89
357 -376 400 -421 19 -20 100 -105 180 -189 80 -84 165 -174 190 -200 25 -26
115 -120 200 -210 210 -221 223 -235 400 -421 227 -238 245 -257 323 -339 163
-172 428 -450 513 -540 50 -52 135 -142 190 -199 54 -58 147 -154 206 -215
l106 -111 40 45 c22 25 57 64 78 86 22 23 75 81 119 129 44 48 94 102 110 119
17 18 73 79 125 136 52 57 106 116 120 131 14 15 62 67 106 115 45 49 109 118
143 154 33 36 61 70 61 75 0 6 -37 48 -83 95 -80 83 -342 359 -447 470 -53 56
-329 346 -476 500 -45 47 -96 101 -114 120 -18 19 -105 111 -194 204 -88 93
-181 190 -206 216 -25 26 -113 119 -196 206 -84 88 -171 179 -194 204 -23 25
-115 122 -204 215 -90 94 -174 182 -187 196 -13 15 -97 102 -185 195 -89 93
-176 185 -194 204 -18 19 -104 109 -190 200 -87 91 -182 190 -210 220 -51 54
-291 307 -380 400 -25 26 -115 121 -200 210 -85 90 -175 185 -200 211 -95 99
-350 367 -419 439 -58 62 -77 76 -105 78 -30 2 -40 -5 -102 -74z"/>
<path d="M4254 4264 c-111 -123 -117 -130 -149 -166 -16 -18 -56 -62 -90 -98
-33 -36 -94 -103 -135 -149 -41 -45 -88 -98 -105 -116 -97 -105 -240 -264
-300 -331 -5 -6 -48 -53 -95 -104 -47 -51 -95 -104 -107 -118 -67 -73 -183
-202 -220 -242 -24 -25 -43 -49 -43 -53 0 -4 15 -23 33 -41 17 -18 124 -128
237 -245 113 -118 234 -244 270 -281 36 -37 157 -163 270 -280 113 -117 239
-247 280 -290 41 -43 119 -123 172 -179 l96 -101 74 81 c91 101 93 103 204
225 51 54 109 119 130 143 22 24 55 60 74 81 19 21 64 70 100 110 86 96 92
102 190 210 107 118 118 129 198 218 37 41 80 88 97 106 16 18 66 73 110 121
44 49 95 105 112 124 18 20 32 39 30 42 -2 6 -239 255 -452 474 -49 51 -144
149 -210 218 -66 68 -208 215 -315 326 -107 112 -236 245 -285 297 -50 52 -93
94 -96 94 -3 0 -37 -34 -75 -76z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.7 KiB

-108
View File
@@ -1,108 +0,0 @@
# dokploy: allow-host-ports — WoW clients connect directly over raw TCP (3724 authentication, 8085 world); Traefik cannot route the game protocol.
services:
azerothcore-database:
image: mysql:8.4.11
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
volumes:
- azerothcore-database:/var/lib/mysql
healthcheck:
test:
[
"CMD-SHELL",
"mysqladmin ping --host=127.0.0.1 --protocol=TCP --user=root --password=$${MYSQL_ROOT_PASSWORD}",
]
interval: 5s
timeout: 10s
retries: 40
start_period: 20s
azerothcore-db-import:
image: acore/ac-wotlk-db-import:17.0.0-dev
restart: "no"
environment:
AC_DATA_DIR: /azerothcore/env/dist/data
AC_LOGS_DIR: /azerothcore/env/dist/logs
AC_LOGIN_DATABASE_INFO: azerothcore-database;3306;root;${MYSQL_ROOT_PASSWORD};acore_auth
AC_WORLD_DATABASE_INFO: azerothcore-database;3306;root;${MYSQL_ROOT_PASSWORD};acore_world
AC_CHARACTER_DATABASE_INFO: azerothcore-database;3306;root;${MYSQL_ROOT_PASSWORD};acore_characters
volumes:
- azerothcore-config:/azerothcore/env/dist/etc
- azerothcore-logs:/azerothcore/env/dist/logs
depends_on:
azerothcore-database:
condition: service_healthy
azerothcore-client-data:
image: acore/ac-wotlk-client-data:17.0.0-dev
restart: "no"
volumes:
- azerothcore-client-data:/azerothcore/env/dist/data
azerothcore-realm-config:
image: mysql:8.4.11
restart: "no"
environment:
MYSQL_PWD: ${MYSQL_ROOT_PASSWORD}
REALM_ADDRESS: ${REALM_ADDRESS}
entrypoint: ["/bin/sh", "-c"]
command:
- >-
mysql --host=azerothcore-database --user=root
--execute="UPDATE acore_auth.realmlist
SET name = 'AzerothCore', address = '$${REALM_ADDRESS}',
localAddress = '127.0.0.1', localSubnetMask = '255.255.255.0', port = 8085
WHERE id = 1;"
depends_on:
azerothcore-database:
condition: service_healthy
azerothcore-db-import:
condition: service_completed_successfully
azerothcore-auth:
image: acore/ac-wotlk-authserver:17.0.0-dev
restart: unless-stopped
tty: true
environment:
AC_LOGS_DIR: /azerothcore/env/dist/logs
AC_TEMP_DIR: /azerothcore/env/dist/temp
AC_LOGIN_DATABASE_INFO: azerothcore-database;3306;root;${MYSQL_ROOT_PASSWORD};acore_auth
ports:
- "3724:3724/tcp"
volumes:
- azerothcore-config:/azerothcore/env/dist/etc
- azerothcore-logs:/azerothcore/env/dist/logs
depends_on:
azerothcore-realm-config:
condition: service_completed_successfully
azerothcore:
image: acore/ac-wotlk-worldserver:17.0.0-dev
restart: unless-stopped
stdin_open: true
tty: true
stop_grace_period: 2m
environment:
AC_DATA_DIR: /azerothcore/env/dist/data
AC_LOGS_DIR: /azerothcore/env/dist/logs
AC_LOGIN_DATABASE_INFO: azerothcore-database;3306;root;${MYSQL_ROOT_PASSWORD};acore_auth
AC_WORLD_DATABASE_INFO: azerothcore-database;3306;root;${MYSQL_ROOT_PASSWORD};acore_world
AC_CHARACTER_DATABASE_INFO: azerothcore-database;3306;root;${MYSQL_ROOT_PASSWORD};acore_characters
ports:
- "8085:8085/tcp"
volumes:
- azerothcore-config:/azerothcore/env/dist/etc
- azerothcore-logs:/azerothcore/env/dist/logs
- azerothcore-client-data:/azerothcore/env/dist/data:ro
depends_on:
azerothcore-realm-config:
condition: service_completed_successfully
azerothcore-client-data:
condition: service_completed_successfully
volumes:
azerothcore-database:
azerothcore-client-data:
azerothcore-config:
azerothcore-logs:
-42
View File
@@ -1,42 +0,0 @@
# AzerothCore setup
## Before deploying
AzerothCore's published server images currently support `amd64` hosts only.
AzerothCore uses raw TCP connections rather than HTTP. Make sure TCP ports `3724` (authentication) and `8085` (world server) are free on the Dokploy host and allowed through its firewall.
The template generates `REALM_ADDRESS` with Dokploy's domain helper. Verify that this hostname resolves publicly to the Dokploy server. If it does not, replace `REALM_ADDRESS` in the service environment with the server's public IP address or another public DNS name, then redeploy.
## First startup
The first deployment downloads the client data and imports the authentication, character, and world databases. This can take several minutes. The `azerothcore-client-data`, `azerothcore-db-import`, and `azerothcore-realm-config` containers are initialization jobs and should exit successfully after completing their work.
## Create the first game account
After the `azerothcore` world server is running, attach to its console from the Dokploy host:
```bash
docker attach <azerothcore-worldserver-container-id>
```
Create an account and grant it administrator permissions:
```text
account create <username> <password>
account set gmlevel <username> 3 -1
```
Detach without stopping the server by pressing `Ctrl-p`, then `Ctrl-q`.
## Connect a 3.3.5a client
Set the client's `Data/<locale>/realmlist.wtf` file to the same hostname or IP stored in `REALM_ADDRESS`:
```text
set realmlist <REALM_ADDRESS>
```
Restart the client, sign in with the account created above, and select the AzerothCore realm. If authentication works but the realm connection fails, confirm that TCP port `8085` is reachable and that `REALM_ADDRESS` points to the Dokploy host.
For updates, backups, configuration, and troubleshooting, see the [AzerothCore Docker documentation](https://www.azerothcore.org/wiki/install-with-docker).
-17
View File
@@ -1,17 +0,0 @@
{
"id": "azerothcore",
"name": "AzerothCore",
"version": "17.0.0-dev",
"description": "A modular open source World of Warcraft: Wrath of the Lich King 3.3.5a game server emulator.",
"logo": "azerothcore.svg",
"links": {
"github": "https://github.com/azerothcore/azerothcore-wotlk",
"website": "https://www.azerothcore.org/",
"docs": "https://www.azerothcore.org/wiki/install-with-docker"
},
"tags": [
"gaming",
"mmorpg",
"server"
]
}
-11
View File
@@ -1,11 +0,0 @@
[variables]
mysql_root_password = "${password:32}"
realm_address = "${domain}"
[config]
domains = []
mounts = []
env = [
"MYSQL_ROOT_PASSWORD=${mysql_root_password}",
"REALM_ADDRESS=${realm_address}",
]
+2 -1
View File
@@ -4,7 +4,6 @@ mysql_root_password = "${password:32}"
mysql_password = "${password:16}"
[config]
mounts = []
[[config.domains]]
serviceName = "azuracast"
port = 80
@@ -28,3 +27,5 @@ NGINX_RADIO_PORTS = "8000,8010,8020,8030,8040,8050"
PREFER_RELEASE_BUILDS = "true"
COMPOSER_PLUGIN_MODE = "false"
ADDITIONAL_MEDIA_SYNC_WORKER_COUNT = "0"
[[config.mounts]]
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
babybuddy:
image: linuxserver/babybuddy:2.7.0
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
baikal:
image: ckulka/baikal:nginx-php8.2
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
barrage:
image: maulik9898/barrage:0.3.0
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
baserow:
image: baserow/baserow:1.25.2
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
bazarr:
image: lscr.io/linuxserver/bazarr:1.5.1
+4 -2
View File
@@ -1,6 +1,8 @@
version: "3.8"
services:
bentopdf:
image: ghcr.io/alam00000/bentopdf-simple:sha-72d20bb
image: bentopdf/bentopdf:latest
restart: unless-stopped
expose:
- 8080
- 80
+1 -1
View File
@@ -4,6 +4,6 @@ main_domain = "${domain}"
[config]
[[config.domains]]
serviceName = "bentopdf"
port = 8080
port = 80
host = "${main_domain}"
path = "/"
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
beszel:
image: henrygd/beszel:0.10.2
+4 -1
View File
@@ -72,7 +72,7 @@ s3_endpoint = ""
s3_bucket = ""
[config]
mounts = []
[[config.domains]]
serviceName = "webapp"
port = 80
@@ -165,3 +165,6 @@ MYSQL_DATABASE = "${system_db_name}"
MYSQL_USER = "${db_user}"
MYSQL_PASSWORD = "${db_password}"
MYSQL_ROOT_PASSWORD = "${db_root_password}"
[[config.mounts]]
+2
View File
@@ -1,3 +1,5 @@
version: "3.8"
services:
billmora-app:
image: ghcr.io/billmora/billmora:latest
+2
View File
@@ -1,3 +1,5 @@
version: "3.8"
services:
blender:
image: lscr.io/linuxserver/blender:latest
-12
View File
@@ -1,12 +0,0 @@
# BlogFactory on Dokploy
Dokploy creates independent database, storage, JWT, encryption, and scheduler secrets during import. Only the `web` service receives a public domain; the API, scheduler, PostgreSQL, and MinIO remain private.
## First administrator
1. Open the Compose service's environment settings and copy the generated `ADMIN_EMAILS` value.
2. Open the generated BlogFactory domain and register with that exact email address.
3. Return to the Compose environment settings, change `BLOGFACTORY_ALLOW_SIGNUP` to `false`, and redeploy.
4. Add OpenRouter, CMS, or Google Search Console credentials from BlogFactory only when you need those optional integrations.
BlogFactory sends reviewed content to connected CMS providers as drafts. The template does not grant live-publish or delete authority.
-8
View File
@@ -1,8 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<rect width="64" height="64" rx="8" fill="#fff"/>
<rect x="1" y="1" width="62" height="62" rx="7" fill="none" stroke="#d7d8d4" stroke-width="2"/>
<circle cx="50" cy="14" r="5" fill="#ff5a1f"/>
<rect x="13" y="31" width="10" height="18" fill="#202224"/>
<rect x="27" y="20" width="10" height="29" fill="#202224"/>
<rect x="41" y="26" width="10" height="23" fill="#202224"/>
</svg>

Before

Width:  |  Height:  |  Size: 453 B

-100
View File
@@ -1,100 +0,0 @@
services:
postgres:
image: postgres:17.6-alpine3.22
restart: unless-stopped
environment:
POSTGRES_DB: blogfactory
POSTGRES_USER: blogfactory
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U blogfactory -d blogfactory"]
interval: 5s
timeout: 5s
retries: 20
minio:
image: minio/minio:RELEASE.2025-09-07T16-13-09Z
restart: unless-stopped
command: server /data --console-address :9001
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
volumes:
- minio-data:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 5s
timeout: 5s
retries: 20
api:
image: ghcr.io/blogfactoryhq/blogfactory-api:v0.1.0
restart: unless-stopped
command: >-
sh -c "bun run src/init-s3-bucket.ts && bun run src/db/migrate.ts && exec bun run src/index.ts"
depends_on:
postgres:
condition: service_healthy
minio:
condition: service_healthy
expose:
- 3000
environment:
NODE_ENV: production
PORT: 3000
BLOGFACTORY_SELF_HOSTED: "true"
DATABASE_URL: postgresql://blogfactory:${POSTGRES_PASSWORD}@postgres:5432/blogfactory
JWT_SECRET: ${JWT_SECRET}
API_KEY_ENCRYPTION_SECRET: ${API_KEY_ENCRYPTION_SECRET}
ADMIN_EMAILS: ${ADMIN_EMAILS}
BLOGFACTORY_ALLOW_SIGNUP: ${BLOGFACTORY_ALLOW_SIGNUP}
CRON_SECRET: ${CRON_SECRET}
WEB_APP_URL: ${BLOGFACTORY_URL}
MCP_APP_URL: http://web/mcp-review.html
MCP_ALLOWED_ORIGINS: ${BLOGFACTORY_URL}
S3_ENDPOINT: http://minio:9000
S3_ACCESS_KEY_ID: ${MINIO_ROOT_USER}
S3_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD}
S3_BUCKET: blogfactory
S3_REGION: us-east-1
healthcheck:
test: ["CMD", "bun", "-e", "fetch('http://localhost:3000/api/ready').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))"]
interval: 10s
timeout: 5s
retries: 20
web:
image: ghcr.io/blogfactoryhq/blogfactory-web:v0.1.0
restart: unless-stopped
depends_on:
api:
condition: service_healthy
expose:
- 80
environment:
API_UPSTREAM: http://api:3000
healthcheck:
test: ["CMD-SHELL", "nginx -t >/dev/null 2>&1 && wget -q -O /dev/null http://api:3000/api/ready"]
interval: 10s
timeout: 5s
retries: 20
scheduler:
image: curlimages/curl:8.15.0
restart: unless-stopped
depends_on:
api:
condition: service_healthy
environment:
CRON_SECRET: ${CRON_SECRET}
CRON_INTERVAL_SECONDS: 21600
entrypoint: ["/bin/sh", "-c"]
command:
- >-
while true; do curl --fail --silent --show-error --output /dev/null -H "Authorization: Bearer $${CRON_SECRET}" http://api:3000/api/cron/drain && echo "Scheduler drain completed"; sleep "$${CRON_INTERVAL_SECONDS}"; done
volumes:
postgres-data:
minio-data:
-13
View File
@@ -1,13 +0,0 @@
{
"id": "blogfactory",
"name": "BlogFactory",
"version": "v0.1.0",
"description": "Self-hosted control plane for AI-assisted content operations and human-approved CMS draft delivery.",
"logo": "blogfactory.svg",
"links": {
"github": "https://github.com/BlogFactoryHQ/blogfactory",
"website": "https://blogfactory.io/",
"docs": "https://github.com/BlogFactoryHQ/blogfactory/blob/main/docs/self-hosting.md"
},
"tags": ["ai", "automation", "content-management"]
}
-28
View File
@@ -1,28 +0,0 @@
[variables]
main_domain = "${domain}"
postgres_password = "${password:48}"
minio_root_user = "blogfactory"
minio_root_password = "${password:48}"
jwt_secret = "${base64:48}"
encryption_secret = "${base64:48}"
cron_secret = "${base64:48}"
admin_email = "${email}"
[config]
env = [
"POSTGRES_PASSWORD=${postgres_password}",
"MINIO_ROOT_USER=${minio_root_user}",
"MINIO_ROOT_PASSWORD=${minio_root_password}",
"JWT_SECRET=${jwt_secret}",
"API_KEY_ENCRYPTION_SECRET=${encryption_secret}",
"CRON_SECRET=${cron_secret}",
"ADMIN_EMAILS=${admin_email}",
"BLOGFACTORY_ALLOW_SIGNUP=true",
"BLOGFACTORY_URL=https://${main_domain}",
]
mounts = []
[[config.domains]]
serviceName = "web"
port = 80
host = "${main_domain}"
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
bonfire:
image: bonfirenetworks/bonfire:1.0.5-social-amd64
+2 -1
View File
@@ -4,7 +4,6 @@ app_password = "${password:32}"
db_root_password = "${password:32}"
[config]
mounts = []
[[config.domains]]
serviceName = "booklore"
port = 6060
@@ -21,3 +20,5 @@ MYSQL_USER = "booklore"
MYSQL_PASSWORD = "${app_password}"
# API Key
MYSQL_ROOT_PASSWORD = "${db_root_password}"
[[config.mounts]]
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
bookstack:
image: lscr.io/linuxserver/bookstack:24.12.1
+2 -5
View File
@@ -2,7 +2,7 @@
"id": "bookstack",
"name": "BookStack",
"version": "24.12.1",
"description": "BookStack is a wiki platform for organizing documentation. Self-host it on your own server with Dokploy, which deploys BookStack as a Docker Compose service in a few clicks.",
"description": "BookStack is a self-hosted platform for creating beautiful, feature-rich documentation sites.",
"logo": "logo.svg",
"links": {
"github": "https://github.com/BookStackApp/BookStack",
@@ -12,8 +12,5 @@
"tags": [
"documentation",
"self-hosted"
],
"seoTitle": "BookStack Docker Compose Setup",
"seoDescription": "Platform for building documentation wikis. Deploy BookStack with Docker Compose on Dokploy in minutes – free, open source, self-hosted.",
"newConfig": true
]
}
+2
View File
@@ -1,3 +1,5 @@
version: "3.8"
services:
borgitory:
image: mlapaglia/borgitory:latest
+15 -1
View File
@@ -2,10 +2,24 @@
main_domain = "${domain}"
[config]
mounts = []
[[config.domains]]
serviceName = "borgitory"
port = 8000
host = "${main_domain}"
[config.env]
[[config.mounts]]
name = "borgitory-data"
mountPath = "/app/data"
description = "Database and encryption key storage"
[[config.mounts]]
name = "borgitory-sources"
mountPath = "/mnt/sources"
description = "Sources to back up (read-only)"
[[config.mounts]]
name = "borgitory-repos"
mountPath = "/mnt/repos"
description = "Borg repositories (read-only)"
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
botpress:
image: botpress/server:12.31.9
@@ -1,3 +1,4 @@
version: "3.8"
services:
budget-board-server:
restart: unless-stopped
+7 -1
View File
@@ -3,12 +3,18 @@ main_domain = "${domain}"
postgres_password = "${password:32}"
[config]
mounts = []
[[config.domains]]
serviceName = "budget-board-client"
port = 6253
host = "${main_domain}"
path = "/"
[config.env]
POSTGRES_PASSWORD = "${postgres_password}"
[[config.mounts]]
source = "../files/db-data"
target = "/var/lib/postgresql/data"
type = "bind"
+2
View File
@@ -1,3 +1,5 @@
version: "3.8"
services:
db:
image: postgres:17-alpine
+1
View File
@@ -1,3 +1,4 @@
version: "3.8"
services:
bytebase:
image: bytebase/bytebase:3.3.0
+2
View File
@@ -1,3 +1,5 @@
version: '3.8'
services:
bytestash:
image: ghcr.io/jordan-dalby/bytestash:1.5.6
-8
View File
@@ -1,8 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="215.4 140.7 88.5 121.2" width="88.5" height="121.2" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round"><title>Cachkey</title><g transform="matrix(0.438976,0,0,0.438976,42.010431,104.979097)">
<path d="M395.498,189.719C392.92,130.442 446.372,81.593 500,81.593C553.628,81.593 596.106,143.186 596.106,143.186L538.761,163.717C538.761,163.717 532.035,130.442 500,130.442C467.965,130.442 443.186,162.302 443.186,174.336C443.186,186.37 500,155.221 500,155.221L521.062,200L418.407,241.593C418.407,241.593 398.076,248.995 395.498,189.719Z" style="fill:rgb(249,115,22);" />
<g transform="matrix(-1,-0,0,-1,991.514557,438.848596)">
<path d="M395.498,189.719C392.92,130.442 446.372,81.593 500,81.593C553.628,81.593 596.106,143.186 596.106,143.186L538.761,163.717C538.761,163.717 532.035,130.442 500,130.442C467.965,130.442 443.186,162.302 443.186,174.336C443.186,186.37 500,155.221 500,155.221L521.062,200L418.407,241.593C418.407,241.593 398.076,248.995 395.498,189.719Z" style="fill:rgb(249,115,22);" />
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

-56
View File
@@ -1,56 +0,0 @@
services:
# Web app (public): named after the template, as Dokploy requires.
cachkey:
image: ghcr.io/joyboy-dy/cachkey-web:0.2.0
restart: unless-stopped
expose:
- 3000
environment:
APP_URL: ${APP_URL}
# Unique name: Dokploy also attaches this service to its shared network, where a
# plain `api` could resolve to another application's container.
API_INTERNAL_URL: http://cachkey-api:3001
depends_on:
cachkey-api:
condition: service_healthy
# Applies pending database migrations at startup, then serves /api.
cachkey-api:
image: ghcr.io/joyboy-dy/cachkey-api:0.2.0
restart: unless-stopped
expose:
- 3001
environment:
APP_URL: ${APP_URL}
DATABASE_URL: postgresql://cachkey:${POSTGRES_PASSWORD}@postgres:5432/cachkey
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
EMAIL_PROVIDER: ${EMAIL_PROVIDER}
EMAIL_FROM: ${EMAIL_FROM}
SMTP_HOST: ${SMTP_HOST}
SMTP_PORT: ${SMTP_PORT}
SMTP_SECURE: ${SMTP_SECURE}
SMTP_USER: ${SMTP_USER}
SMTP_PASSWORD: ${SMTP_PASSWORD}
RESEND_API_KEY: ${RESEND_API_KEY}
depends_on:
postgres:
condition: service_healthy
postgres:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_USER: cachkey
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: cachkey
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U cachkey -d cachkey"]
interval: 5s
timeout: 5s
retries: 20
volumes:
postgres-data: {}
-14
View File
@@ -1,14 +0,0 @@
{
"id": "cachkey",
"name": "Cachkey",
"version": "0.2.0",
"description": "Cachkey is an open-source, self-hosted manager for secrets and environment variables: encrypted values, per-environment access for your team, a CLI and a read-only API for servers and CI.",
"logo": "cachkey.svg",
"links": {
"github": "https://github.com/Joyboy-dy/cachkey",
"website": "https://github.com/Joyboy-dy/cachkey",
"docs": "https://github.com/Joyboy-dy/cachkey/tree/main/docs"
},
"tags": ["security", "secrets", "self-hosted"],
"license": "AGPL-3.0"
}
-34
View File
@@ -1,34 +0,0 @@
[variables]
main_domain = "${domain}"
# Hexadecimal: safe inside the database URL (no @, #, / or $).
postgres_password = "${hash:32}"
better_auth_secret = "${base64:48}"
# 32 random bytes, base64-encoded: the master key encrypting every stored value.
# Back it up outside the server: without it, stored values cannot be read.
encryption_key = "${base64:32}"
[config]
mounts = []
env = [
# Exact public address. With your own domain or HTTPS, update it (https://…) and
# redeploy: sign-in is refused when the address does not match.
"APP_URL=http://${main_domain}",
"POSTGRES_PASSWORD=${postgres_password}",
"BETTER_AUTH_SECRET=${better_auth_secret}",
"ENCRYPTION_KEY=${encryption_key}",
# Required: Cachkey confirms every address by email before the first sign-in.
# Fill in SMTP_* (EMAIL_PROVIDER=smtp) or RESEND_API_KEY (EMAIL_PROVIDER=resend).
"EMAIL_PROVIDER=smtp",
"EMAIL_FROM=Cachkey <no-reply@example.com>",
"SMTP_HOST=",
"SMTP_PORT=587",
"SMTP_SECURE=false",
"SMTP_USER=",
"SMTP_PASSWORD=",
"RESEND_API_KEY=",
]
[[config.domains]]
serviceName = "cachkey"
port = 3000
host = "${main_domain}"
-111
View File
@@ -1,111 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="230px" height="24.673px" viewBox="0 0 230 24.673" enable-background="new 0 0 230 24.673" xml:space="preserve">
<g>
<g>
<path fill="#FFFFFF" d="M133.629,15.422c1.175,0,1.926-0.515,1.926-1.304c0-0.619-0.489-0.957-1.343-0.957h-1.849l-0.601,2.261
H133.629z M133.161,18.398c1.183,0,1.924-0.498,1.924-1.313c0-0.667-0.629-1.005-1.511-1.005h-1.99l-0.619,2.318H133.161z
M131.819,12.495h2.458c1.285,0,2.037,0.601,2.037,1.53c0,0.938-0.714,1.539-1.643,1.726c0.647,0.197,1.163,0.619,1.163,1.361
c0,1.135-1.031,1.952-2.759,1.952h-3.021L131.819,12.495z"/>
<path fill="#FFFFFF" d="M137.138,17.666c0-0.226,0.058-0.498,0.123-0.751l0.713-2.702h0.723l-0.741,2.749
c-0.038,0.16-0.064,0.386-0.064,0.545c0,0.637,0.411,1.013,1.078,1.013c0.751,0,1.511-0.647,1.754-1.577l0.732-2.73h0.723
l-1.295,4.851h-0.724l0.217-0.788c-0.441,0.497-0.957,0.892-1.698,0.892C137.749,19.167,137.138,18.585,137.138,17.666"/>
</g>
<path fill="#FFFFFF" d="M144.419,12.355h0.826l-0.217,0.797h-0.824L144.419,12.355z M143.97,14.212h0.722l-1.305,4.852h-0.722
L143.97,14.212z"/>
<polygon fill="#FFFFFF" points="147.075,12.214 147.797,12.214 145.958,19.064 145.235,19.064 "/>
<g>
<path fill="#FFFFFF" d="M152.339,16.249c0-0.845-0.61-1.501-1.502-1.501c-1.154,0-2.026,1.07-2.026,2.309
c0,0.901,0.562,1.482,1.37,1.482C151.26,18.539,152.339,17.441,152.339,16.249 M148.051,17.122c0-1.718,1.304-3.012,2.722-3.012
c0.994,0,1.558,0.562,1.819,1.201l0.826-3.097h0.723l-1.83,6.85h-0.723l0.216-0.826c-0.46,0.525-1.051,0.938-1.83,0.938
C148.876,19.176,148.051,18.351,148.051,17.122"/>
<path fill="#FFFFFF" d="M158.333,14.851h-0.667l0.171-0.638h0.666l0.159-0.582c0.253-0.976,0.825-1.436,1.661-1.436
c0.375,0,0.712,0.075,0.966,0.207l-0.17,0.619c-0.28-0.132-0.516-0.197-0.796-0.197c-0.46,0-0.808,0.282-0.977,0.92l-0.123,0.469
h1.588l-0.18,0.638h-1.577l-1.134,4.213h-0.724L158.333,14.851z"/>
<path fill="#FFFFFF" d="M164.057,17.159l0.093-0.337c-0.421-0.122-0.976-0.216-1.576-0.216c-0.863,0-1.454,0.469-1.454,1.135
c0,0.517,0.403,0.863,1.032,0.863C162.968,18.604,163.821,18.013,164.057,17.159 M160.388,17.825c0-1.088,0.909-1.755,2.157-1.755
c0.648,0,1.258,0.131,1.727,0.263l0.028-0.112c0.038-0.141,0.066-0.319,0.066-0.45c0-0.629-0.432-0.986-1.313-0.986
c-0.518,0-0.939,0.103-1.37,0.253l-0.123-0.601c0.479-0.178,0.976-0.291,1.605-0.291c1.22,0,1.904,0.563,1.904,1.501
c0,0.207-0.037,0.441-0.103,0.666l-0.732,2.75h-0.704l0.207-0.76c-0.45,0.516-1.041,0.863-1.812,0.863
C161.11,19.167,160.388,18.688,160.388,17.825"/>
<path fill="#FFFFFF" d="M165.651,18.323l0.469-0.469c0.525,0.507,1.106,0.713,1.689,0.713c0.553,0,1.069-0.32,1.069-0.807
c0-0.319-0.217-0.554-0.921-0.826c-0.872-0.338-1.37-0.657-1.37-1.333c0-0.825,0.714-1.492,1.84-1.492
c0.714,0,1.389,0.32,1.792,0.667l-0.422,0.497c-0.403-0.328-0.91-0.563-1.436-0.563c-0.685,0-1.052,0.366-1.052,0.77
c0,0.319,0.198,0.525,0.968,0.826c0.873,0.356,1.322,0.704,1.322,1.333c0,0.901-0.825,1.53-1.857,1.53
C166.992,19.167,166.214,18.886,165.651,18.323"/>
<path fill="#FFFFFF" d="M171.074,18.191c0-0.169,0.027-0.356,0.064-0.507l0.761-2.834h-0.666l0.169-0.638h0.675l0.396-1.464h0.713
l-0.395,1.464h1.529l-0.169,0.638h-1.529l-0.751,2.797c-0.019,0.112-0.037,0.253-0.037,0.356c0,0.337,0.253,0.497,0.665,0.497
c0.217,0,0.441-0.046,0.705-0.149l-0.179,0.656c-0.254,0.103-0.488,0.141-0.77,0.141C171.562,19.148,171.074,18.82,171.074,18.191
"/>
<path fill="#FFFFFF" d="M173.794,19.881c0.545-0.141,0.807-0.414,0.882-0.817h-0.348l0.272-0.985h0.855l-0.227,0.845
c-0.226,0.816-0.61,1.135-1.36,1.276L173.794,19.881z"/>
<path fill="#FFFFFF" d="M184.378,16.118c0-0.713-0.562-1.37-1.492-1.37c-1.032,0-1.998,0.854-1.998,2.018
c0,0.863,0.676,1.304,1.416,1.304C183.401,18.069,184.378,17.112,184.378,16.118 M179.489,19.74l0.45-0.507
c0.516,0.441,1.173,0.732,1.914,0.732c0.61,0,1.069-0.197,1.36-0.498c0.301-0.291,0.47-0.666,0.61-1.163l0.131-0.488
c-0.487,0.497-1.061,0.872-1.857,0.872c-1.013,0-1.971-0.666-1.971-1.83c0-1.614,1.36-2.749,2.722-2.749
c1.041,0,1.511,0.582,1.782,1.163l0.282-1.06h0.723l-1.107,4.157c-0.207,0.75-0.441,1.182-0.789,1.53
c-0.45,0.45-1.051,0.685-1.877,0.685C180.972,20.584,180.09,20.265,179.489,19.74"/>
<path fill="#FFFFFF" d="M187.343,14.212h0.723l-0.33,1.267c0.593-0.845,1.343-1.408,2.31-1.352l-0.207,0.779h-0.047
c-1.06,0-2.12,0.779-2.506,2.243l-0.515,1.914h-0.724L187.343,14.212z"/>
<path fill="#FFFFFF" d="M194.491,16.305c0-0.985-0.619-1.558-1.52-1.558c-1.117,0-2.075,1.107-2.075,2.234
c0,0.985,0.62,1.547,1.521,1.547C193.506,18.529,194.491,17.459,194.491,16.305 M190.166,17c0-1.511,1.303-2.891,2.852-2.891
c1.333,0,2.214,0.911,2.214,2.168c0,1.549-1.342,2.9-2.861,2.9C191.038,19.177,190.166,18.257,190.166,17"/>
</g>
<polygon fill="#FFFFFF" points="196.459,14.212 197.19,14.212 197.444,18.079 199.791,14.194 200.391,14.194 200.663,18.079
202.999,14.212 203.75,14.212 200.728,19.102 200.091,19.102 199.809,15.273 197.473,19.102 196.845,19.102 "/>
<g>
<path fill="#FFFFFF" d="M206.461,18.323l0.469-0.469c0.525,0.507,1.106,0.713,1.688,0.713c0.554,0,1.07-0.32,1.07-0.807
c0-0.319-0.216-0.554-0.92-0.826c-0.873-0.338-1.37-0.657-1.37-1.333c0-0.825,0.713-1.492,1.84-1.492
c0.713,0,1.389,0.32,1.791,0.667l-0.422,0.497c-0.403-0.328-0.91-0.563-1.436-0.563c-0.685,0-1.051,0.366-1.051,0.77
c0,0.319,0.197,0.525,0.967,0.826c0.873,0.356,1.323,0.704,1.323,1.333c0,0.901-0.826,1.53-1.857,1.53
C207.802,19.167,207.022,18.886,206.461,18.323"/>
<path fill="#FFFFFF" d="M216.05,16.305c0-0.985-0.619-1.558-1.521-1.558c-1.116,0-2.073,1.107-2.073,2.234
c0,0.985,0.619,1.547,1.521,1.547C215.065,18.529,216.05,17.459,216.05,16.305 M211.723,17c0-1.511,1.306-2.891,2.854-2.891
c1.333,0,2.216,0.911,2.216,2.168c0,1.549-1.343,2.9-2.862,2.9C212.596,19.177,211.723,18.257,211.723,17"/>
</g>
<polygon fill="#FFFFFF" points="219.408,12.214 220.131,12.214 218.291,19.064 217.568,19.064 "/>
<path fill="#FFFFFF" d="M221.895,12.355h0.826l-0.217,0.797h-0.825L221.895,12.355z M221.443,14.212h0.724l-1.305,4.852h-0.724
L221.443,14.212z"/>
<g>
<path fill="#FFFFFF" d="M227.243,16.249c0-0.845-0.61-1.501-1.503-1.501c-1.154,0-2.026,1.07-2.026,2.309
c0,0.901,0.563,1.482,1.37,1.482C226.163,18.539,227.243,17.441,227.243,16.249 M222.954,17.122c0-1.718,1.304-3.012,2.722-3.012
c0.994,0,1.558,0.562,1.821,1.201l0.825-3.097h0.721l-1.829,6.85h-0.723l0.216-0.826c-0.46,0.525-1.051,0.938-1.83,0.938
C223.779,19.176,222.954,18.351,222.954,17.122"/>
</g>
<polygon fill="#FFFFFF" points="229.146,18.079 228.874,19.064 229.738,19.064 230,18.079 "/>
<g>
<path fill="#FFFFFF" d="M15.806,9.873l12.366,3.07c2.152-0.84,3.445-1.911,3.445-3.07V4.935C31.617,2.213,24.537,0,15.806,0
C7.076,0,0,2.213,0,4.935v4.938c0,2.723,7.076,4.933,15.806,4.933V9.873z"/>
<path fill="#FFFFFF" d="M28.171,17.879l-12.366-3.073v4.934l12.366,3.074c2.153-0.844,3.446-1.911,3.446-3.074v-4.934
C31.618,15.969,30.324,17.036,28.171,17.879"/>
<path fill="#FFFFFF" d="M0,14.806v4.935c0,2.724,7.076,4.933,15.806,4.933v-4.933C7.076,19.741,0,17.53,0,14.806"/>
<path fill="#FFFFFF" d="M45.185,19.29c-3.861,0-6.727-2.98-6.727-6.747v-0.036c0-3.728,2.81-6.784,6.838-6.784
c2.473,0,3.955,0.826,5.172,2.024l-1.836,2.117c-1.012-0.918-2.043-1.48-3.354-1.48c-2.212,0-3.803,1.836-3.803,4.084v0.039
c0,2.248,1.554,4.122,3.803,4.122c1.499,0,2.416-0.599,3.446-1.537l1.836,1.854C49.213,18.39,47.714,19.29,45.185,19.29"/>
<path fill="#FFFFFF" d="M58.506,15.017c-0.486-0.227-1.125-0.375-1.817-0.375c-1.218,0-1.969,0.487-1.969,1.387v0.037
c0,0.767,0.638,1.217,1.555,1.217c1.33,0,2.231-0.728,2.231-1.761V15.017z M58.448,19.064v-1.086
c-0.692,0.768-1.647,1.274-3.035,1.274c-1.891,0-3.447-1.087-3.447-3.073v-0.039c0-2.193,1.667-3.205,4.046-3.205
c1.013,0,1.744,0.169,2.457,0.412V13.18c0-1.179-0.731-1.836-2.156-1.836c-1.086,0-1.854,0.207-2.772,0.543l-0.713-2.173
c1.106-0.489,2.193-0.806,3.897-0.806c3.111,0,4.48,1.611,4.48,4.33v5.826H58.448z"/>
</g>
<polygon fill="#FFFFFF" points="70.123,19.064 67.499,14.961 66.505,16.01 66.505,19.064 63.659,19.064 63.659,5.384 66.505,5.384
66.505,12.676 69.842,9.021 73.251,9.021 69.429,12.973 73.382,19.064 "/>
<g>
<path fill="#FFFFFF" d="M78.757,11.12c-1.18,0-1.95,0.843-2.174,2.135h4.292C80.705,11.98,79.956,11.12,78.757,11.12
M83.61,15.037h-6.989c0.28,1.292,1.18,1.966,2.455,1.966c0.956,0,1.648-0.301,2.435-1.031l1.632,1.444
c-0.939,1.162-2.288,1.874-4.105,1.874c-3.017,0-5.249-2.117-5.249-5.19v-0.039c0-2.867,2.044-5.228,4.967-5.228
c3.354,0,4.891,2.605,4.891,5.454v0.037C83.647,14.605,83.629,14.774,83.61,15.037"/>
<path fill="#FFFFFF" d="M93.521,10.538c0-1.292-0.898-1.985-2.342-1.985H88.95v4.012h2.286c1.442,0,2.285-0.865,2.285-1.987
V10.538z M91.141,15.129h-2.19v3.935h-2.886V5.947h5.359c3.128,0,5.021,1.855,5.021,4.537v0.036
C96.444,13.555,94.083,15.129,91.141,15.129"/>
</g>
<polygon fill="#FFFFFF" points="106.787,19.064 106.787,13.796 101.465,13.796 101.465,19.064 98.58,19.064 98.58,5.947
101.465,5.947 101.465,11.138 106.787,11.138 106.787,5.947 109.672,5.947 109.672,19.064 "/>
<g>
<path fill="#FFFFFF" d="M120.277,10.538c0-1.292-0.899-1.985-2.342-1.985h-2.23v4.012h2.285c1.444,0,2.287-0.865,2.287-1.987
V10.538z M117.899,15.129h-2.194v3.935h-2.886V5.947h5.359c3.128,0,5.022,1.855,5.022,4.537v0.036
C123.201,13.555,120.84,15.129,117.899,15.129"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.4 KiB

-30
View File
@@ -1,30 +0,0 @@
services:
cakephp:
image: ghcr.io/themusicdev/cakephp-hello:1.0.0
restart: unless-stopped
depends_on:
- mariadb
environment:
# CakePHP skeleton reads its app config from these env vars
# (config/app_local.php in the starter repo is env-driven)
- DEBUG=${DEBUG}
- SECURITY_SALT=${SECURITY_SALT}
- DATABASE_URL=mysql://${MARIADB_USER}:${MARIADB_PASSWORD}@mariadb:3306/${MARIADB_DATABASE}?encoding=utf8mb4
expose:
- 80
mariadb:
image: mariadb:11
restart: unless-stopped
environment:
- MARIADB_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD}
- MARIADB_DATABASE=${MARIADB_DATABASE}
- MARIADB_USER=${MARIADB_USER}
- MARIADB_PASSWORD=${MARIADB_PASSWORD}
volumes:
- mariadb-data:/var/lib/mysql
expose:
- 3306
volumes:
mariadb-data:
-21
View File
@@ -1,21 +0,0 @@
{
"id": "cakephp",
"name": "CakePHP 5",
"version": "1.0.0",
"description": "CakePHP 5 starter app running on the themusicdev/php-apache 8.5 Apache + PHP runtime image, backed by MariaDB. Fork the starter repo, build your app, and deploy it on Dokploy in a few clicks.",
"logo": "cakephp.svg",
"links": {
"github": "https://github.com/TheMusicDev/cakephp-hello",
"website": "https://cakephp.org/",
"docs": "https://book.cakephp.org/5/en/index.html"
},
"tags": [
"php",
"framework",
"cakephp",
"website"
],
"seoTitle": "CakePHP 5 Docker Compose Setup",
"seoDescription": "Deploy a CakePHP 5 application with MariaDB on Dokploy in minutes — runs on the themusicdev/php-apache Apache + PHP 8.5 runtime image with Traefik proxy awareness built in.",
"newConfig": true
}

Some files were not shown because too many files have changed in this diff Show More