diff --git a/apps/dokploy/components/dashboard/monitoring/free/container/show-free-compose-monitoring.tsx b/apps/dokploy/components/dashboard/monitoring/free/container/show-free-compose-monitoring.tsx
index 99be6d9d96..25c72bab70 100644
--- a/apps/dokploy/components/dashboard/monitoring/free/container/show-free-compose-monitoring.tsx
+++ b/apps/dokploy/components/dashboard/monitoring/free/container/show-free-compose-monitoring.tsx
@@ -1,3 +1,5 @@
+import { badgeStateColor } from "@/components/dashboard/application/logs/show";
+import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Card,
@@ -96,7 +98,10 @@ export const ComposeFreeMonitoring = ({
key={container.containerId}
value={container.name}
>
- {container.name} ({container.containerId}) {container.state}
+ {container.name} ({container.containerId}){" "}
+
+ {container.state}
+
))}
Containers ({data?.length})
diff --git a/apps/dokploy/components/dashboard/monitoring/paid/container/show-paid-compose-monitoring.tsx b/apps/dokploy/components/dashboard/monitoring/paid/container/show-paid-compose-monitoring.tsx
index 580d7ea1c4..4ca461c215 100644
--- a/apps/dokploy/components/dashboard/monitoring/paid/container/show-paid-compose-monitoring.tsx
+++ b/apps/dokploy/components/dashboard/monitoring/paid/container/show-paid-compose-monitoring.tsx
@@ -1,3 +1,5 @@
+import { badgeStateColor } from "@/components/dashboard/application/logs/show";
+import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import {
Card,
@@ -102,7 +104,9 @@ export const ComposePaidMonitoring = ({
value={container.name}
>
{container.name} ({container.containerId}){" "}
- {container.state}
+
+ {container.state}
+
))}
Containers ({data?.length})
diff --git a/apps/dokploy/package.json b/apps/dokploy/package.json
index 30666f83dc..d66a6e67f5 100644
--- a/apps/dokploy/package.json
+++ b/apps/dokploy/package.json
@@ -1,6 +1,6 @@
{
"name": "dokploy",
- "version": "v0.18.3",
+ "version": "v0.18.4",
"private": true,
"license": "Apache-2.0",
"type": "module",
diff --git a/apps/dokploy/pages/dashboard/project/[projectId].tsx b/apps/dokploy/pages/dashboard/project/[projectId].tsx
index 26317ca926..ea23ad3a89 100644
--- a/apps/dokploy/pages/dashboard/project/[projectId].tsx
+++ b/apps/dokploy/pages/dashboard/project/[projectId].tsx
@@ -70,9 +70,9 @@ import type {
} from "next";
import Head from "next/head";
import { useRouter } from "next/router";
-import { useMemo, useState, type ReactElement } from "react";
-import superjson from "superjson";
+import { type ReactElement, useMemo, useState } from "react";
import { toast } from "sonner";
+import superjson from "superjson";
export type Services = {
appName: string;
diff --git a/apps/dokploy/public/templates/appwrite.svg b/apps/dokploy/public/templates/appwrite.svg
new file mode 100644
index 0000000000..2034a812a0
--- /dev/null
+++ b/apps/dokploy/public/templates/appwrite.svg
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/apps/dokploy/public/templates/convex.svg b/apps/dokploy/public/templates/convex.svg
new file mode 100644
index 0000000000..8622c4c072
--- /dev/null
+++ b/apps/dokploy/public/templates/convex.svg
@@ -0,0 +1,5 @@
+
diff --git a/apps/dokploy/public/templates/outline.png b/apps/dokploy/public/templates/outline.png
new file mode 100644
index 0000000000..b241f01d77
Binary files /dev/null and b/apps/dokploy/public/templates/outline.png differ
diff --git a/apps/dokploy/public/templates/registry.png b/apps/dokploy/public/templates/registry.png
new file mode 100644
index 0000000000..39418022e3
Binary files /dev/null and b/apps/dokploy/public/templates/registry.png differ
diff --git a/apps/dokploy/public/templates/trilium.png b/apps/dokploy/public/templates/trilium.png
new file mode 100644
index 0000000000..f6afe82f80
Binary files /dev/null and b/apps/dokploy/public/templates/trilium.png differ
diff --git a/apps/dokploy/templates/appwrite/docker-compose.yml b/apps/dokploy/templates/appwrite/docker-compose.yml
new file mode 100644
index 0000000000..163cb3d03f
--- /dev/null
+++ b/apps/dokploy/templates/appwrite/docker-compose.yml
@@ -0,0 +1,887 @@
+version: "3.8"
+
+x-logging: &x-logging
+ logging:
+ driver: "json-file"
+ options:
+ max-file: "5"
+ max-size: "10m"
+
+services:
+ appwrite:
+ image: appwrite/appwrite:1.6.0
+ container_name: appwrite
+ <<: *x-logging
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ labels:
+ - traefik.enable=true
+ - traefik.constraint-label-stack=appwrite
+ volumes:
+ - appwrite-uploads:/storage/uploads:rw
+ - appwrite-cache:/storage/cache:rw
+ - appwrite-config:/storage/config:rw
+ - appwrite-certificates:/storage/certificates:rw
+ - appwrite-functions:/storage/functions:rw
+ depends_on:
+ - mariadb
+ - redis
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_LOCALE
+ - _APP_CONSOLE_WHITELIST_ROOT
+ - _APP_CONSOLE_WHITELIST_EMAILS
+ - _APP_CONSOLE_SESSION_ALERTS
+ - _APP_CONSOLE_WHITELIST_IPS
+ - _APP_CONSOLE_HOSTNAMES
+ - _APP_SYSTEM_EMAIL_NAME
+ - _APP_SYSTEM_EMAIL_ADDRESS
+ - _APP_EMAIL_SECURITY
+ - _APP_SYSTEM_RESPONSE_FORMAT
+ - _APP_OPTIONS_ABUSE
+ - _APP_OPTIONS_ROUTER_PROTECTION
+ - _APP_OPTIONS_FORCE_HTTPS
+ - _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS
+ - _APP_OPENSSL_KEY_V1
+ - _APP_DOMAIN
+ - _APP_DOMAIN_TARGET
+ - _APP_DOMAIN_FUNCTIONS
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_SMTP_HOST
+ - _APP_SMTP_PORT
+ - _APP_SMTP_SECURE
+ - _APP_SMTP_USERNAME
+ - _APP_SMTP_PASSWORD
+ - _APP_USAGE_STATS
+ - _APP_STORAGE_LIMIT
+ - _APP_STORAGE_PREVIEW_LIMIT
+ - _APP_STORAGE_ANTIVIRUS
+ - _APP_STORAGE_ANTIVIRUS_HOST
+ - _APP_STORAGE_ANTIVIRUS_PORT
+ - _APP_STORAGE_DEVICE
+ - _APP_STORAGE_S3_ACCESS_KEY
+ - _APP_STORAGE_S3_SECRET
+ - _APP_STORAGE_S3_REGION
+ - _APP_STORAGE_S3_BUCKET
+ - _APP_STORAGE_DO_SPACES_ACCESS_KEY
+ - _APP_STORAGE_DO_SPACES_SECRET
+ - _APP_STORAGE_DO_SPACES_REGION
+ - _APP_STORAGE_DO_SPACES_BUCKET
+ - _APP_STORAGE_BACKBLAZE_ACCESS_KEY
+ - _APP_STORAGE_BACKBLAZE_SECRET
+ - _APP_STORAGE_BACKBLAZE_REGION
+ - _APP_STORAGE_BACKBLAZE_BUCKET
+ - _APP_STORAGE_LINODE_ACCESS_KEY
+ - _APP_STORAGE_LINODE_SECRET
+ - _APP_STORAGE_LINODE_REGION
+ - _APP_STORAGE_LINODE_BUCKET
+ - _APP_STORAGE_WASABI_ACCESS_KEY
+ - _APP_STORAGE_WASABI_SECRET
+ - _APP_STORAGE_WASABI_REGION
+ - _APP_STORAGE_WASABI_BUCKET
+ - _APP_FUNCTIONS_SIZE_LIMIT
+ - _APP_FUNCTIONS_TIMEOUT
+ - _APP_FUNCTIONS_BUILD_TIMEOUT
+ - _APP_FUNCTIONS_CPUS
+ - _APP_FUNCTIONS_MEMORY
+ - _APP_FUNCTIONS_RUNTIMES
+ - _APP_EXECUTOR_SECRET
+ - _APP_EXECUTOR_HOST
+ - _APP_LOGGING_CONFIG
+ - _APP_MAINTENANCE_INTERVAL
+ - _APP_MAINTENANCE_DELAY
+ - _APP_MAINTENANCE_RETENTION_EXECUTION
+ - _APP_MAINTENANCE_RETENTION_CACHE
+ - _APP_MAINTENANCE_RETENTION_ABUSE
+ - _APP_MAINTENANCE_RETENTION_AUDIT
+ - _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
+ - _APP_MAINTENANCE_RETENTION_SCHEDULES
+ - _APP_SMS_PROVIDER
+ - _APP_SMS_FROM
+ - _APP_GRAPHQL_MAX_BATCH_SIZE
+ - _APP_GRAPHQL_MAX_COMPLEXITY
+ - _APP_GRAPHQL_MAX_DEPTH
+ - _APP_VCS_GITHUB_APP_NAME
+ - _APP_VCS_GITHUB_PRIVATE_KEY
+ - _APP_VCS_GITHUB_APP_ID
+ - _APP_VCS_GITHUB_WEBHOOK_SECRET
+ - _APP_VCS_GITHUB_CLIENT_SECRET
+ - _APP_VCS_GITHUB_CLIENT_ID
+ - _APP_MIGRATIONS_FIREBASE_CLIENT_ID
+ - _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
+ - _APP_ASSISTANT_OPENAI_API_KEY
+
+ appwrite-console:
+ image: appwrite/console:5.0.12
+ container_name: appwrite-console
+ <<: *x-logging
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ labels:
+ - "traefik.enable=true"
+ - "traefik.constraint-label-stack=appwrite"
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_LOCALE
+ - _APP_CONSOLE_WHITELIST_ROOT
+ - _APP_CONSOLE_WHITELIST_EMAILS
+ - _APP_CONSOLE_SESSION_ALERTS
+ - _APP_CONSOLE_WHITELIST_IPS
+ - _APP_CONSOLE_HOSTNAMES
+ - _APP_SYSTEM_EMAIL_NAME
+ - _APP_SYSTEM_EMAIL_ADDRESS
+ - _APP_EMAIL_SECURITY
+ - _APP_SYSTEM_RESPONSE_FORMAT
+ - _APP_OPTIONS_ABUSE
+ - _APP_OPTIONS_ROUTER_PROTECTION
+ - _APP_OPTIONS_FORCE_HTTPS
+ - _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS
+ - _APP_OPENSSL_KEY_V1
+ - _APP_DOMAIN
+ - _APP_DOMAIN_TARGET
+ - _APP_DOMAIN_FUNCTIONS
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_SMTP_HOST
+ - _APP_SMTP_PORT
+ - _APP_SMTP_SECURE
+ - _APP_SMTP_USERNAME
+ - _APP_SMTP_PASSWORD
+ - _APP_USAGE_STATS
+ - _APP_STORAGE_LIMIT
+ - _APP_STORAGE_PREVIEW_LIMIT
+ - _APP_STORAGE_ANTIVIRUS
+ - _APP_STORAGE_ANTIVIRUS_HOST
+ - _APP_STORAGE_ANTIVIRUS_PORT
+ - _APP_STORAGE_DEVICE
+ - _APP_STORAGE_S3_ACCESS_KEY
+ - _APP_STORAGE_S3_SECRET
+ - _APP_STORAGE_S3_REGION
+ - _APP_STORAGE_S3_BUCKET
+ - _APP_STORAGE_DO_SPACES_ACCESS_KEY
+ - _APP_STORAGE_DO_SPACES_SECRET
+ - _APP_STORAGE_DO_SPACES_REGION
+ - _APP_STORAGE_DO_SPACES_BUCKET
+ - _APP_STORAGE_BACKBLAZE_ACCESS_KEY
+ - _APP_STORAGE_BACKBLAZE_SECRET
+ - _APP_STORAGE_BACKBLAZE_REGION
+ - _APP_STORAGE_BACKBLAZE_BUCKET
+ - _APP_STORAGE_LINODE_ACCESS_KEY
+ - _APP_STORAGE_LINODE_SECRET
+ - _APP_STORAGE_LINODE_REGION
+ - _APP_STORAGE_LINODE_BUCKET
+ - _APP_STORAGE_WASABI_ACCESS_KEY
+ - _APP_STORAGE_WASABI_SECRET
+ - _APP_STORAGE_WASABI_REGION
+ - _APP_STORAGE_WASABI_BUCKET
+
+ appwrite-realtime:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: realtime
+ container_name: appwrite-realtime
+ <<: *x-logging
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ depends_on:
+ - mariadb
+ - redis
+ labels:
+ - "traefik.enable=true"
+ - "traefik.constraint-label-stack=appwrite"
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPTIONS_ABUSE
+ - _APP_OPTIONS_ROUTER_PROTECTION
+ - _APP_OPENSSL_KEY_V1
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_USAGE_STATS
+ - _APP_LOGGING_CONFIG
+
+ appwrite-worker-audits:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: worker-audits
+ <<: *x-logging
+ container_name: appwrite-worker-audits
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ depends_on:
+ - redis
+ - mariadb
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_LOGGING_CONFIG
+
+ appwrite-worker-webhooks:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: worker-webhooks
+ <<: *x-logging
+ container_name: appwrite-worker-webhooks
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ depends_on:
+ - redis
+ - mariadb
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_EMAIL_SECURITY
+ - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_LOGGING_CONFIG
+
+ appwrite-worker-deletes:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: worker-deletes
+ <<: *x-logging
+ container_name: appwrite-worker-deletes
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ depends_on:
+ - redis
+ - mariadb
+ volumes:
+ - appwrite-uploads:/storage/uploads:rw
+ - appwrite-cache:/storage/cache:rw
+ - appwrite-functions:/storage/functions:rw
+ - appwrite-builds:/storage/builds:rw
+ - appwrite-certificates:/storage/certificates:rw
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_STORAGE_DEVICE
+ - _APP_STORAGE_S3_ACCESS_KEY
+ - _APP_STORAGE_S3_SECRET
+ - _APP_STORAGE_S3_REGION
+ - _APP_STORAGE_S3_BUCKET
+ - _APP_STORAGE_DO_SPACES_ACCESS_KEY
+ - _APP_STORAGE_DO_SPACES_SECRET
+ - _APP_STORAGE_DO_SPACES_REGION
+ - _APP_STORAGE_DO_SPACES_BUCKET
+ - _APP_STORAGE_BACKBLAZE_ACCESS_KEY
+ - _APP_STORAGE_BACKBLAZE_SECRET
+ - _APP_STORAGE_BACKBLAZE_REGION
+ - _APP_STORAGE_BACKBLAZE_BUCKET
+ - _APP_STORAGE_LINODE_ACCESS_KEY
+ - _APP_STORAGE_LINODE_SECRET
+ - _APP_STORAGE_LINODE_REGION
+ - _APP_STORAGE_LINODE_BUCKET
+ - _APP_STORAGE_WASABI_ACCESS_KEY
+ - _APP_STORAGE_WASABI_SECRET
+ - _APP_STORAGE_WASABI_REGION
+ - _APP_STORAGE_WASABI_BUCKET
+ - _APP_LOGGING_CONFIG
+ - _APP_EXECUTOR_SECRET
+ - _APP_EXECUTOR_HOST
+ - _APP_MAINTENANCE_RETENTION_ABUSE
+ - _APP_MAINTENANCE_RETENTION_AUDIT
+ - _APP_MAINTENANCE_RETENTION_EXECUTION
+
+ appwrite-worker-databases:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: worker-databases
+ <<: *x-logging
+ container_name: appwrite-worker-databases
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ depends_on:
+ - redis
+ - mariadb
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_LOGGING_CONFIG
+
+ appwrite-worker-builds:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: worker-builds
+ <<: *x-logging
+ container_name: appwrite-worker-builds
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ depends_on:
+ - redis
+ - mariadb
+ volumes:
+ - appwrite-functions:/storage/functions:rw
+ - appwrite-builds:/storage/builds:rw
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_EXECUTOR_SECRET
+ - _APP_EXECUTOR_HOST
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_LOGGING_CONFIG
+ - _APP_VCS_GITHUB_APP_NAME
+ - _APP_VCS_GITHUB_PRIVATE_KEY
+ - _APP_VCS_GITHUB_APP_ID
+ - _APP_FUNCTIONS_TIMEOUT
+ - _APP_FUNCTIONS_BUILD_TIMEOUT
+ - _APP_FUNCTIONS_CPUS
+ - _APP_FUNCTIONS_MEMORY
+ - _APP_FUNCTIONS_SIZE_LIMIT
+ - _APP_OPTIONS_FORCE_HTTPS
+ - _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS
+ - _APP_DOMAIN
+ - _APP_STORAGE_DEVICE
+ - _APP_STORAGE_S3_ACCESS_KEY
+ - _APP_STORAGE_S3_SECRET
+ - _APP_STORAGE_S3_REGION
+ - _APP_STORAGE_S3_BUCKET
+ - _APP_STORAGE_DO_SPACES_ACCESS_KEY
+ - _APP_STORAGE_DO_SPACES_SECRET
+ - _APP_STORAGE_DO_SPACES_REGION
+ - _APP_STORAGE_DO_SPACES_BUCKET
+ - _APP_STORAGE_BACKBLAZE_ACCESS_KEY
+ - _APP_STORAGE_BACKBLAZE_SECRET
+ - _APP_STORAGE_BACKBLAZE_REGION
+ - _APP_STORAGE_BACKBLAZE_BUCKET
+ - _APP_STORAGE_LINODE_ACCESS_KEY
+ - _APP_STORAGE_LINODE_SECRET
+ - _APP_STORAGE_LINODE_REGION
+ - _APP_STORAGE_LINODE_BUCKET
+ - _APP_STORAGE_WASABI_ACCESS_KEY
+ - _APP_STORAGE_WASABI_SECRET
+ - _APP_STORAGE_WASABI_REGION
+ - _APP_STORAGE_WASABI_BUCKET
+
+ appwrite-worker-certificates:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: worker-certificates
+ <<: *x-logging
+ container_name: appwrite-worker-certificates
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ depends_on:
+ - redis
+ - mariadb
+ volumes:
+ - appwrite-config:/storage/config:rw
+ - appwrite-certificates:/storage/certificates:rw
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_DOMAIN
+ - _APP_DOMAIN_TARGET
+ - _APP_DOMAIN_FUNCTIONS
+ - _APP_EMAIL_CERTIFICATES
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_LOGGING_CONFIG
+
+ appwrite-worker-functions:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: worker-functions
+ <<: *x-logging
+ container_name: appwrite-worker-functions
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ depends_on:
+ - redis
+ - mariadb
+ - openruntimes-executor
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_DOMAIN
+ - _APP_OPTIONS_FORCE_HTTPS
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_FUNCTIONS_TIMEOUT
+ - _APP_FUNCTIONS_BUILD_TIMEOUT
+ - _APP_FUNCTIONS_CPUS
+ - _APP_FUNCTIONS_MEMORY
+ - _APP_EXECUTOR_SECRET
+ - _APP_EXECUTOR_HOST
+ - _APP_USAGE_STATS
+ - _APP_DOCKER_HUB_USERNAME
+ - _APP_DOCKER_HUB_PASSWORD
+ - _APP_LOGGING_CONFIG
+
+ appwrite-worker-mails:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: worker-mails
+ <<: *x-logging
+ container_name: appwrite-worker-mails
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ depends_on:
+ - redis
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_SYSTEM_EMAIL_NAME
+ - _APP_SYSTEM_EMAIL_ADDRESS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_SMTP_HOST
+ - _APP_SMTP_PORT
+ - _APP_SMTP_SECURE
+ - _APP_SMTP_USERNAME
+ - _APP_SMTP_PASSWORD
+ - _APP_LOGGING_CONFIG
+
+ appwrite-worker-messaging:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: worker-messaging
+ container_name: appwrite-worker-messaging
+ <<: *x-logging
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ volumes:
+ - appwrite-uploads:/storage/uploads:rw
+ depends_on:
+ - redis
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_LOGGING_CONFIG
+ - _APP_SMS_FROM
+ - _APP_SMS_PROVIDER
+ - _APP_STORAGE_DEVICE
+ - _APP_STORAGE_S3_ACCESS_KEY
+ - _APP_STORAGE_S3_SECRET
+ - _APP_STORAGE_S3_REGION
+ - _APP_STORAGE_S3_BUCKET
+ - _APP_STORAGE_DO_SPACES_ACCESS_KEY
+ - _APP_STORAGE_DO_SPACES_SECRET
+ - _APP_STORAGE_DO_SPACES_REGION
+ - _APP_STORAGE_DO_SPACES_BUCKET
+ - _APP_STORAGE_BACKBLAZE_ACCESS_KEY
+ - _APP_STORAGE_BACKBLAZE_SECRET
+ - _APP_STORAGE_BACKBLAZE_REGION
+ - _APP_STORAGE_BACKBLAZE_BUCKET
+ - _APP_STORAGE_LINODE_ACCESS_KEY
+ - _APP_STORAGE_LINODE_SECRET
+ - _APP_STORAGE_LINODE_REGION
+ - _APP_STORAGE_LINODE_BUCKET
+ - _APP_STORAGE_WASABI_ACCESS_KEY
+ - _APP_STORAGE_WASABI_SECRET
+ - _APP_STORAGE_WASABI_REGION
+ - _APP_STORAGE_WASABI_BUCKET
+
+ appwrite-worker-migrations:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: worker-migrations
+ <<: *x-logging
+ container_name: appwrite-worker-migrations
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ depends_on:
+ - mariadb
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_DOMAIN
+ - _APP_DOMAIN_TARGET
+ - _APP_EMAIL_SECURITY
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_LOGGING_CONFIG
+ - _APP_MIGRATIONS_FIREBASE_CLIENT_ID
+ - _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
+
+ appwrite-task-maintenance:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: maintenance
+ <<: *x-logging
+ container_name: appwrite-task-maintenance
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ depends_on:
+ - redis
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_DOMAIN
+ - _APP_DOMAIN_TARGET
+ - _APP_DOMAIN_FUNCTIONS
+ - _APP_OPENSSL_KEY_V1
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_MAINTENANCE_INTERVAL
+ - _APP_MAINTENANCE_RETENTION_EXECUTION
+ - _APP_MAINTENANCE_RETENTION_CACHE
+ - _APP_MAINTENANCE_RETENTION_ABUSE
+ - _APP_MAINTENANCE_RETENTION_AUDIT
+ - _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
+ - _APP_MAINTENANCE_RETENTION_SCHEDULES
+
+ appwrite-worker-usage:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: worker-usage
+ container_name: appwrite-worker-usage
+ <<: *x-logging
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ depends_on:
+ - redis
+ - mariadb
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_USAGE_STATS
+ - _APP_LOGGING_CONFIG
+ - _APP_USAGE_AGGREGATION_INTERVAL
+
+ appwrite-worker-usage-dump:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: worker-usage-dump
+ container_name: appwrite-worker-usage-dump
+ <<: *x-logging
+ networks:
+ - dokploy-network
+ depends_on:
+ - redis
+ - mariadb
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_USAGE_STATS
+ - _APP_LOGGING_CONFIG
+ - _APP_USAGE_AGGREGATION_INTERVAL
+
+ appwrite-task-scheduler-functions:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: schedule-functions
+ container_name: appwrite-task-scheduler-functions
+ <<: *x-logging
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ depends_on:
+ - mariadb
+ - redis
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+
+ appwrite-task-scheduler-executions:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: schedule-executions
+ container_name: appwrite-task-scheduler-executions
+ <<: *x-logging
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ depends_on:
+ - mariadb
+ - redis
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+
+ appwrite-task-scheduler-messages:
+ image: appwrite/appwrite:1.6.0
+ entrypoint: schedule-messages
+ container_name: appwrite-task-scheduler-messages
+ <<: *x-logging
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ depends_on:
+ - mariadb
+ - redis
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+
+ appwrite-assistant:
+ image: appwrite/assistant:0.4.0
+ container_name: appwrite-assistant
+ <<: *x-logging
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ environment:
+ - _APP_ASSISTANT_OPENAI_API_KEY
+
+ openruntimes-executor:
+ container_name: openruntimes-executor
+ hostname: exc1
+ <<: *x-logging
+ restart: unless-stopped
+ stop_signal: SIGINT
+ image: openruntimes/executor:0.6.11
+ networks:
+ - dokploy-network
+ volumes:
+ - /var/run/docker.sock:/var/run/docker.sock
+ - appwrite-builds:/storage/builds:rw
+ - appwrite-functions:/storage/functions:rw
+ - /tmp:/tmp:rw
+ environment:
+ - OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_FUNCTIONS_INACTIVE_THRESHOLD
+ - OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_FUNCTIONS_MAINTENANCE_INTERVAL
+ - OPR_EXECUTOR_NETWORK=$_APP_FUNCTIONS_RUNTIMES_NETWORK
+ - OPR_EXECUTOR_DOCKER_HUB_USERNAME=$_APP_DOCKER_HUB_USERNAME
+ - OPR_EXECUTOR_DOCKER_HUB_PASSWORD=$_APP_DOCKER_HUB_PASSWORD
+ - OPR_EXECUTOR_ENV=$_APP_ENV
+ - OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES
+ - OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET
+ - OPR_EXECUTOR_LOGGING_CONFIG=$_APP_LOGGING_CONFIG
+ - OPR_EXECUTOR_STORAGE_DEVICE=$_APP_STORAGE_DEVICE
+ - OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=$_APP_STORAGE_S3_ACCESS_KEY
+ - OPR_EXECUTOR_STORAGE_S3_SECRET=$_APP_STORAGE_S3_SECRET
+ - OPR_EXECUTOR_STORAGE_S3_REGION=$_APP_STORAGE_S3_REGION
+ - OPR_EXECUTOR_STORAGE_S3_BUCKET=$_APP_STORAGE_S3_BUCKET
+ - OPR_EXECUTOR_STORAGE_DO_SPACES_ACCESS_KEY=$_APP_STORAGE_DO_SPACES_ACCESS_KEY
+ - OPR_EXECUTOR_STORAGE_DO_SPACES_SECRET=$_APP_STORAGE_DO_SPACES_SECRET
+ - OPR_EXECUTOR_STORAGE_DO_SPACES_REGION=$_APP_STORAGE_DO_SPACES_REGION
+ - OPR_EXECUTOR_STORAGE_DO_SPACES_BUCKET=$_APP_STORAGE_DO_SPACES_BUCKET
+ - OPR_EXECUTOR_STORAGE_BACKBLAZE_ACCESS_KEY=$_APP_STORAGE_BACKBLAZE_ACCESS_KEY
+ - OPR_EXECUTOR_STORAGE_BACKBLAZE_SECRET=$_APP_STORAGE_BACKBLAZE_SECRET
+ - OPR_EXECUTOR_STORAGE_BACKBLAZE_REGION=$_APP_STORAGE_BACKBLAZE_REGION
+ - OPR_EXECUTOR_STORAGE_BACKBLAZE_BUCKET=$_APP_STORAGE_BACKBLAZE_BUCKET
+ - OPR_EXECUTOR_STORAGE_LINODE_ACCESS_KEY=$_APP_STORAGE_LINODE_ACCESS_KEY
+ - OPR_EXECUTOR_STORAGE_LINODE_SECRET=$_APP_STORAGE_LINODE_SECRET
+ - OPR_EXECUTOR_STORAGE_LINODE_REGION=$_APP_STORAGE_LINODE_REGION
+ - OPR_EXECUTOR_STORAGE_LINODE_BUCKET=$_APP_STORAGE_LINODE_BUCKET
+ - OPR_EXECUTOR_STORAGE_WASABI_ACCESS_KEY=$_APP_STORAGE_WASABI_ACCESS_KEY
+ - OPR_EXECUTOR_STORAGE_WASABI_SECRET=$_APP_STORAGE_WASABI_SECRET
+ - OPR_EXECUTOR_STORAGE_WASABI_REGION=$_APP_STORAGE_WASABI_REGION
+ - OPR_EXECUTOR_STORAGE_WASABI_BUCKET=$_APP_STORAGE_WASABI_BUCKET
+
+ mariadb:
+ image: mariadb:10.11
+ container_name: appwrite-mariadb
+ <<: *x-logging
+ restart: unless-stopped
+ networks:
+ - dokploy-network
+ volumes:
+ - appwrite-mariadb:/var/lib/mysql:rw
+ environment:
+ - MYSQL_ROOT_PASSWORD=${_APP_DB_ROOT_PASS}
+ - MYSQL_DATABASE=${_APP_DB_SCHEMA}
+ - MYSQL_USER=${_APP_DB_USER}
+ - MYSQL_PASSWORD=${_APP_DB_PASS}
+ - MARIADB_AUTO_UPGRADE=1
+ command: "mysqld --innodb-flush-method=fsync"
+
+ redis:
+ image: redis:7.2.4-alpine
+ container_name: appwrite-redis
+ <<: *x-logging
+ restart: unless-stopped
+ command: >
+ redis-server
+ --maxmemory 512mb
+ --maxmemory-policy allkeys-lru
+ --maxmemory-samples 5
+ networks:
+ - dokploy-network
+ volumes:
+ - appwrite-redis:/data:rw
+
+# Uncomment and configure if ClamAV is needed
+# clamav:
+# image: appwrite/clamav:1.2.0
+# container_name: appwrite-clamav
+# restart: unless-stopped
+# networks:
+# - dokploy-network
+# volumes:
+# - appwrite-uploads:/storage/uploads
+
+volumes:
+ appwrite-mariadb:
+ appwrite-redis:
+ appwrite-cache:
+ appwrite-uploads:
+ appwrite-certificates:
+ appwrite-functions:
+ appwrite-builds:
+ appwrite-config:
+
+networks:
+ dokploy-network:
+ external: true
diff --git a/apps/dokploy/templates/appwrite/index.ts b/apps/dokploy/templates/appwrite/index.ts
new file mode 100644
index 0000000000..4e671324fd
--- /dev/null
+++ b/apps/dokploy/templates/appwrite/index.ts
@@ -0,0 +1,153 @@
+import {
+ type DomainSchema,
+ type Schema,
+ type Template,
+ generateRandomDomain,
+} from "../utils";
+
+export function generate(schema: Schema): Template {
+ const mainDomain = generateRandomDomain(schema);
+
+ const domains: DomainSchema[] = [
+ { host: mainDomain, port: 80, serviceName: "appwrite", path: "/" },
+ {
+ host: mainDomain,
+ port: 80,
+ serviceName: "appwrite-console",
+ path: "/console",
+ },
+ {
+ host: mainDomain,
+ port: 80,
+ serviceName: "appwrite-realtime",
+ path: "/v1/realtime",
+ },
+ ];
+
+ const envs = [
+ "_APP_ENV=production",
+ "_APP_LOCALE=en",
+ "_APP_OPTIONS_ABUSE=enabled",
+ "_APP_OPTIONS_FORCE_HTTPS=disabled",
+ "_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=disabled",
+ "_APP_OPTIONS_ROUTER_PROTECTION=disabled",
+ "_APP_OPENSSL_KEY_V1=your-secret-key",
+ `_APP_DOMAIN=${mainDomain}`,
+ `_APP_DOMAIN_FUNCTIONS=${mainDomain}`,
+ `_APP_DOMAIN_TARGET=${mainDomain}`,
+ "_APP_CONSOLE_WHITELIST_ROOT=enabled",
+ "_APP_CONSOLE_WHITELIST_EMAILS=",
+ "_APP_CONSOLE_WHITELIST_IPS=",
+ "_APP_CONSOLE_HOSTNAMES=",
+ "_APP_SYSTEM_EMAIL_NAME=Appwrite",
+ "_APP_SYSTEM_EMAIL_ADDRESS=noreply@appwrite.io",
+ "_APP_SYSTEM_TEAM_EMAIL=team@appwrite.io",
+ "_APP_SYSTEM_RESPONSE_FORMAT=",
+ "_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=certs@appwrite.io",
+ "_APP_EMAIL_SECURITY=",
+ "_APP_EMAIL_CERTIFICATES=",
+ "_APP_USAGE_STATS=enabled",
+ "_APP_LOGGING_PROVIDER=",
+ "_APP_LOGGING_CONFIG=",
+ "_APP_USAGE_AGGREGATION_INTERVAL=30",
+ "_APP_USAGE_TIMESERIES_INTERVAL=30",
+ "_APP_USAGE_DATABASE_INTERVAL=900",
+ "_APP_WORKER_PER_CORE=6",
+ "_APP_CONSOLE_SESSION_ALERTS=disabled",
+ "_APP_REDIS_HOST=redis",
+ "_APP_REDIS_PORT=6379",
+ "_APP_REDIS_USER=",
+ "_APP_REDIS_PASS=",
+ "_APP_DB_HOST=mariadb",
+ "_APP_DB_PORT=3306",
+ "_APP_DB_SCHEMA=appwrite",
+ "_APP_DB_USER=user",
+ "_APP_DB_PASS=password",
+ "_APP_DB_ROOT_PASS=rootsecretpassword",
+ "_APP_INFLUXDB_HOST=influxdb",
+ "_APP_INFLUXDB_PORT=8086",
+ "_APP_STATSD_HOST=telegraf",
+ "_APP_STATSD_PORT=8125",
+ "_APP_SMTP_HOST=",
+ "_APP_SMTP_PORT=",
+ "_APP_SMTP_SECURE=",
+ "_APP_SMTP_USERNAME=",
+ "_APP_SMTP_PASSWORD=",
+ "_APP_SMS_PROVIDER=",
+ "_APP_SMS_FROM=",
+ "_APP_STORAGE_LIMIT=30000000",
+ "_APP_STORAGE_PREVIEW_LIMIT=20000000",
+ "_APP_STORAGE_ANTIVIRUS=disabled",
+ "_APP_STORAGE_ANTIVIRUS_HOST=clamav",
+ "_APP_STORAGE_ANTIVIRUS_PORT=3310",
+ "_APP_STORAGE_DEVICE=local",
+ "_APP_STORAGE_S3_ACCESS_KEY=",
+ "_APP_STORAGE_S3_SECRET=",
+ "_APP_STORAGE_S3_REGION=us-east-1",
+ "_APP_STORAGE_S3_BUCKET=",
+ "_APP_STORAGE_DO_SPACES_ACCESS_KEY=",
+ "_APP_STORAGE_DO_SPACES_SECRET=",
+ "_APP_STORAGE_DO_SPACES_REGION=us-east-1",
+ "_APP_STORAGE_DO_SPACES_BUCKET=",
+ "_APP_STORAGE_BACKBLAZE_ACCESS_KEY=",
+ "_APP_STORAGE_BACKBLAZE_SECRET=",
+ "_APP_STORAGE_BACKBLAZE_REGION=us-west-004",
+ "_APP_STORAGE_BACKBLAZE_BUCKET=",
+ "_APP_STORAGE_LINODE_ACCESS_KEY=",
+ "_APP_STORAGE_LINODE_SECRET=",
+ "_APP_STORAGE_LINODE_REGION=eu-central-1",
+ "_APP_STORAGE_LINODE_BUCKET=",
+ "_APP_STORAGE_WASABI_ACCESS_KEY=",
+ "_APP_STORAGE_WASABI_SECRET=",
+ "_APP_STORAGE_WASABI_REGION=eu-central-1",
+ "_APP_STORAGE_WASABI_BUCKET=",
+ "_APP_FUNCTIONS_SIZE_LIMIT=30000000",
+ "_APP_FUNCTIONS_BUILD_SIZE_LIMIT=2000000000",
+ "_APP_FUNCTIONS_TIMEOUT=900",
+ "_APP_FUNCTIONS_BUILD_TIMEOUT=900",
+ "_APP_FUNCTIONS_CONTAINERS=10",
+ "_APP_FUNCTIONS_CPUS=0",
+ "_APP_FUNCTIONS_MEMORY=0",
+ "_APP_FUNCTIONS_MEMORY_SWAP=0",
+ "_APP_FUNCTIONS_RUNTIMES=node-16.0,php-8.0,python-3.9,ruby-3.0",
+ "_APP_EXECUTOR_SECRET=your-secret-key",
+ "_APP_EXECUTOR_HOST=http://exc1/v1",
+ "_APP_EXECUTOR_RUNTIME_NETWORK=appwrite_runtimes",
+ "_APP_FUNCTIONS_ENVS=node-16.0,php-7.4,python-3.9,ruby-3.0",
+ "_APP_FUNCTIONS_INACTIVE_THRESHOLD=60",
+ "DOCKERHUB_PULL_USERNAME=",
+ "DOCKERHUB_PULL_PASSWORD=",
+ "DOCKERHUB_PULL_EMAIL=",
+ "OPEN_RUNTIMES_NETWORK=appwrite_runtimes",
+ "_APP_FUNCTIONS_RUNTIMES_NETWORK=runtimes",
+ "_APP_DOCKER_HUB_USERNAME=",
+ "_APP_DOCKER_HUB_PASSWORD=",
+ "_APP_FUNCTIONS_MAINTENANCE_INTERVAL=3600",
+ "_APP_VCS_GITHUB_APP_NAME=",
+ "_APP_VCS_GITHUB_PRIVATE_KEY=",
+ "_APP_VCS_GITHUB_APP_ID=",
+ "_APP_VCS_GITHUB_CLIENT_ID=",
+ "_APP_VCS_GITHUB_CLIENT_SECRET=",
+ "_APP_VCS_GITHUB_WEBHOOK_SECRET=",
+ "_APP_MAINTENANCE_INTERVAL=86400",
+ "_APP_MAINTENANCE_DELAY=0",
+ "_APP_MAINTENANCE_RETENTION_CACHE=2592000",
+ "_APP_MAINTENANCE_RETENTION_EXECUTION=1209600",
+ "_APP_MAINTENANCE_RETENTION_AUDIT=1209600",
+ "_APP_MAINTENANCE_RETENTION_ABUSE=86400",
+ "_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000",
+ "_APP_MAINTENANCE_RETENTION_SCHEDULES=86400",
+ "_APP_GRAPHQL_MAX_BATCH_SIZE=10",
+ "_APP_GRAPHQL_MAX_COMPLEXITY=250",
+ "_APP_GRAPHQL_MAX_DEPTH=3",
+ "_APP_MIGRATIONS_FIREBASE_CLIENT_ID=",
+ "_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=",
+ "_APP_ASSISTANT_OPENAI_API_KEY=",
+ ];
+
+ return {
+ domains,
+ envs,
+ mounts: [],
+ };
+}
diff --git a/apps/dokploy/templates/convex/docker-compose.yml b/apps/dokploy/templates/convex/docker-compose.yml
new file mode 100644
index 0000000000..12e2b5adaa
--- /dev/null
+++ b/apps/dokploy/templates/convex/docker-compose.yml
@@ -0,0 +1,37 @@
+services:
+ backend:
+ image: ghcr.io/get-convex/convex-backend:6c974d219776b753cd23d26f4a296629ff7c2cad
+ ports:
+ - "${PORT:-3210}:3210"
+ - "${SITE_PROXY_PORT:-3211}:3211"
+ volumes:
+ - data:/convex/data
+ environment:
+ - INSTANCE_NAME=${INSTANCE_NAME:-}
+ - INSTANCE_SECRET=${INSTANCE_SECRET:-}
+ - CONVEX_RELEASE_VERSION_DEV=${CONVEX_RELEASE_VERSION_DEV:-}
+ - ACTIONS_USER_TIMEOUT_SECS=${ACTIONS_USER_TIMEOUT_SECS:-}
+ - CONVEX_CLOUD_ORIGIN=${CONVEX_CLOUD_ORIGIN:-http://127.0.0.1:3210}
+ - CONVEX_SITE_ORIGIN=${CONVEX_SITE_ORIGIN:-http://127.0.0.1:3211}
+ - DATABASE_URL=${DATABASE_URL:-}
+ - DISABLE_BEACON=${DISABLE_BEACON:-}
+ - REDACT_LOGS_TO_CLIENT=${REDACT_LOGS_TO_CLIENT:-}
+ - RUST_LOG=${RUST_LOG:-info}
+ - RUST_BACKTRACE=${RUST_BACKTRACE:-}
+ healthcheck:
+ test: curl -f http://localhost:3210/version
+ interval: 5s
+ start_period: 5s
+
+ dashboard:
+ image: ghcr.io/get-convex/convex-dashboard:4499dd4fd7f2148687a7774599c613d052950f46
+ ports:
+ - "${DASHBOARD_PORT:-6791}:6791"
+ environment:
+ - NEXT_PUBLIC_DEPLOYMENT_URL=${NEXT_PUBLIC_DEPLOYMENT_URL:-http://127.0.0.1:3210}
+ depends_on:
+ backend:
+ condition: service_healthy
+
+volumes:
+ data:
diff --git a/apps/dokploy/templates/convex/index.ts b/apps/dokploy/templates/convex/index.ts
new file mode 100644
index 0000000000..6a112cdeef
--- /dev/null
+++ b/apps/dokploy/templates/convex/index.ts
@@ -0,0 +1,38 @@
+import {
+ type DomainSchema,
+ type Schema,
+ type Template,
+ generateRandomDomain,
+} from "../utils";
+
+export function generate(schema: Schema): Template {
+ const dashboardDomain = generateRandomDomain(schema);
+ const backendDomain = generateRandomDomain(schema);
+ const actionsDomain = generateRandomDomain(schema);
+
+ const domains: DomainSchema[] = [
+ {
+ host: dashboardDomain,
+ port: 6791,
+ serviceName: "dashboard",
+ },
+ {
+ host: backendDomain,
+ port: 3210,
+ serviceName: "backend",
+ },
+ {
+ host: actionsDomain,
+ port: 3211,
+ serviceName: "backend",
+ },
+ ];
+
+ const envs = [
+ `NEXT_PUBLIC_DEPLOYMENT_URL=http://${backendDomain}`,
+ `CONVEX_CLOUD_ORIGIN=http://${backendDomain}`,
+ `CONVEX_SITE_ORIGIN=http://${actionsDomain}`,
+ ];
+
+ return { envs, domains };
+}
diff --git a/apps/dokploy/templates/outline/docker-compose.yml b/apps/dokploy/templates/outline/docker-compose.yml
new file mode 100644
index 0000000000..aaf98ac0b5
--- /dev/null
+++ b/apps/dokploy/templates/outline/docker-compose.yml
@@ -0,0 +1,57 @@
+services:
+ outline:
+ image: outlinewiki/outline:0.82.0
+ restart: always
+ depends_on:
+ - postgres
+ - redis
+ - dex
+ ports:
+ - 3000
+ environment:
+ NODE_ENV: production
+ URL: ${URL}
+ FORCE_HTTPS: 'false'
+ SECRET_KEY: ${SECRET_KEY}
+ UTILS_SECRET: ${UTILS_SECRET}
+ DATABASE_URL: postgres://outline:${POSTGRES_PASSWORD}@postgres:5432/outline
+ PGSSLMODE: disable
+ REDIS_URL: redis://redis:6379
+ OIDC_CLIENT_ID: outline
+ OIDC_CLIENT_SECRET: ${CLIENT_SECRET}
+ OIDC_AUTH_URI: ${DEX_URL}/auth
+ OIDC_TOKEN_URI: ${DEX_URL}/token
+ OIDC_USERINFO_URI: ${DEX_URL}/userinfo
+
+ dex:
+ image: ghcr.io/dexidp/dex:v2.37.0
+ restart: always
+ volumes:
+ - ../files/etc/dex/config.yaml:/etc/dex/config.yaml
+ command:
+ - dex
+ - serve
+ - /etc/dex/config.yaml
+ ports:
+ - 5556
+
+ postgres:
+ image: postgres:15
+ restart: always
+ environment:
+ POSTGRES_DB: outline
+ POSTGRES_USER: outline
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
+ volumes:
+ - postgres_data-test-outline-khufpx:/var/lib/postgresql/data
+
+ redis:
+ image: redis:latest
+ restart: always
+ command: redis-server --appendonly yes
+ volumes:
+ - redis_data-test-outline-khufpx:/data
+
+volumes:
+ postgres_data-test-outline-khufpx:
+ redis_data-test-outline-khufpx:
\ No newline at end of file
diff --git a/apps/dokploy/templates/outline/index.ts b/apps/dokploy/templates/outline/index.ts
new file mode 100644
index 0000000000..8431e56871
--- /dev/null
+++ b/apps/dokploy/templates/outline/index.ts
@@ -0,0 +1,90 @@
+import {
+ type DomainSchema,
+ type Schema,
+ type Template,
+ generateBase64,
+ generatePassword,
+ generateRandomDomain,
+} from "../utils";
+
+export function generate(schema: Schema): Template {
+ const mainDomain = generateRandomDomain(schema);
+ const dexDomain = generateRandomDomain(schema);
+ const SECRET_KEY = generateBase64(32);
+ const UTILS_SECRET = generateBase64(32);
+ const CLIENT_SECRET = generateBase64(32);
+ const POSTGRES_PASSWORD = generatePassword();
+
+ const mainURL = `http://${mainDomain}`;
+ const dexURL = `http://${dexDomain}`;
+
+ const domains: DomainSchema[] = [
+ {
+ host: mainDomain,
+ port: 3000,
+ serviceName: "outline",
+ },
+ {
+ host: dexDomain,
+ port: 5556,
+ serviceName: "dex",
+ },
+ ];
+
+ const mounts: Template["mounts"] = [
+ {
+ filePath: "/etc/dex/config.yaml",
+ content: `issuer: ${dexURL}
+
+web:
+ http: 0.0.0.0:5556
+
+storage:
+ type: memory
+
+enablePasswordDB: true
+
+frontend:
+ issuer: Outline
+
+logger:
+ level: debug
+
+staticPasswords:
+ - email: "admin@example.com"
+ # bcrypt hash of the string "password": $(echo password | htpasswd -BinC 10 admin | cut -d: -f2)
+ hash: "$2y$10$jsRWHw54uxTUIfhjgUrB9u8HSzPk7TUuQri9sXZrKzRXcScvwYor."
+ username: "admin"
+ userID: "1"
+
+
+oauth2:
+ skipApprovalScreen: true
+ alwaysShowLoginScreen: false
+ passwordConnector: local
+
+staticClients:
+ - id: "outline"
+ redirectURIs:
+ - ${mainURL}/auth/oidc.callback
+ name: "Outline"
+ secret: "${CLIENT_SECRET}"`,
+ },
+ ];
+
+ const envs = [
+ `URL=${mainURL}`,
+ `DEX_URL=${dexURL}`,
+ `DOMAIN_NAME=${mainDomain}`,
+ `POSTGRES_PASSWORD=${POSTGRES_PASSWORD}`,
+ `SECRET_KEY=${SECRET_KEY}`,
+ `UTILS_SECRET=${UTILS_SECRET}`,
+ `CLIENT_SECRET=${CLIENT_SECRET}`,
+ ];
+
+ return {
+ domains,
+ envs,
+ mounts,
+ };
+}
diff --git a/apps/dokploy/templates/plausible/docker-compose.yml b/apps/dokploy/templates/plausible/docker-compose.yml
index f17bdfa311..ad483ecf66 100644
--- a/apps/dokploy/templates/plausible/docker-compose.yml
+++ b/apps/dokploy/templates/plausible/docker-compose.yml
@@ -1,4 +1,3 @@
-version: "3.8"
services:
plausible_db:
image: postgres:16-alpine
@@ -24,7 +23,7 @@ services:
hard: 262144
plausible:
- image: ghcr.io/plausible/community-edition:v2.1.4
+ image: ghcr.io/plausible/community-edition:v2.1.5
restart: always
command: sh -c "sleep 10 && /entrypoint.sh db createdb && /entrypoint.sh db migrate && /entrypoint.sh run"
depends_on:
diff --git a/apps/dokploy/templates/registry/docker-compose.yml b/apps/dokploy/templates/registry/docker-compose.yml
new file mode 100644
index 0000000000..08c5c36889
--- /dev/null
+++ b/apps/dokploy/templates/registry/docker-compose.yml
@@ -0,0 +1,19 @@
+services:
+ registry:
+ restart: always
+ image: registry:2
+ ports:
+ - 5000
+ volumes:
+ - ../files/auth/registry.password:/auth/registry.password
+ - registry-data:/var/lib/registry
+ environment:
+ REGISTRY_STORAGE_DELETE_ENABLED: true
+ REGISTRY_HEALTH_STORAGEDRIVER_ENABLED: false
+ REGISTRY_HTTP_SECRET: ${REGISTRY_HTTP_SECRET}
+ REGISTRY_AUTH: htpasswd
+ REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
+ REGISTRY_AUTH_HTPASSWD_PATH: /auth/registry.password
+
+volumes:
+ registry-data:
\ No newline at end of file
diff --git a/apps/dokploy/templates/registry/index.ts b/apps/dokploy/templates/registry/index.ts
new file mode 100644
index 0000000000..81965e6e28
--- /dev/null
+++ b/apps/dokploy/templates/registry/index.ts
@@ -0,0 +1,35 @@
+import {
+ type DomainSchema,
+ type Schema,
+ type Template,
+ generatePassword,
+ generateRandomDomain,
+} from "../utils";
+
+export function generate(schema: Schema): Template {
+ const domains: DomainSchema[] = [
+ {
+ host: generateRandomDomain(schema),
+ port: 5000,
+ serviceName: "registry",
+ },
+ ];
+
+ const registryHttpSecret = generatePassword(30);
+
+ const envs = [`REGISTRY_HTTP_SECRET=${registryHttpSecret}`];
+
+ const mounts: Template["mounts"] = [
+ {
+ filePath: "/auth/registry.password",
+ content:
+ "# from: docker run --rm --entrypoint htpasswd httpd:2 -Bbn docker password\ndocker:$2y$10$qWZoWev/u5PV7WneFoRAMuoGpRcAQOgUuIIdLnU7pJXogrBSY23/2\n",
+ },
+ ];
+
+ return {
+ domains,
+ envs,
+ mounts,
+ };
+}
diff --git a/apps/dokploy/templates/superset/docker-compose.yml b/apps/dokploy/templates/superset/docker-compose.yml
index 8dd1cd2d40..b73bf55e5f 100644
--- a/apps/dokploy/templates/superset/docker-compose.yml
+++ b/apps/dokploy/templates/superset/docker-compose.yml
@@ -1,5 +1,8 @@
-# Note: this is an UNOFFICIAL production docker image build for Superset:
+# This is an UNOFFICIAL production docker image build for Superset:
# - https://github.com/amancevice/docker-superset
+
+
+# ## SETUP INSTRUCTIONS
#
# After deploying this image, you will need to run one of the two
# commands below in a terminal within the superset container:
@@ -7,11 +10,30 @@
# $ superset-init # Initialise database only
#
# You will be prompted to enter the credentials for the admin user.
+
+
+# ## NETWORK INSTRUCTIONS
+#
+# If you want to connect superset with other internal databases managed by
+# Dokploy (on dokploy-network) using internal hostnames, you will need to
+# uncomment the `networks` section, both for the superset container and
+# at the very bottom of this docker-compose template.
+#
+# Note that the `superset` service name/hostname will not be unique on the
+# global `dokploy-network`. If you plan to:
+#
+# 1. deploy a second instance of superset on dokploy-network, and
+# 2. have other containers on dokploy-network utilise the second instance's
+# Superset API (https://superset.apache.org/docs/api)
+#
+# Please change the service name of the second instance.
services:
superset:
image: amancevice/superset
restart: always
+ #networks:
+ # - dokploy-network
depends_on:
- superset_postgres
- superset_redis
@@ -44,8 +66,7 @@ services:
timeout: 10s
retries: 3
-
- superset_redis:
+superset_redis:
image: redis
restart: always
volumes:
@@ -57,6 +78,9 @@ services:
timeout: 10s
retries: 3
+#networks:
+# dokploy-network:
+# external: true
volumes:
superset_postgres_data:
diff --git a/apps/dokploy/templates/templates.ts b/apps/dokploy/templates/templates.ts
index a2d28d1574..31668a6f90 100644
--- a/apps/dokploy/templates/templates.ts
+++ b/apps/dokploy/templates/templates.ts
@@ -1,6 +1,37 @@
import type { TemplateData } from "./types/templates-data.type";
export const templates: TemplateData[] = [
+ {
+ id: "appwrite",
+ name: "Appwrite",
+ version: "1.6.0",
+ description:
+ "Appwrite is an end-to-end backend server for Web, Mobile, Native, or Backend apps. Appwrite abstracts the complexity and repetitiveness required to build a modern backend API from scratch and allows you to build secure apps faster.\n" +
+ "Using 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",
+ website: "https://appwrite.io/",
+ docs: "https://appwrite.io/docs",
+ },
+ logo: "appwrite.svg",
+ tags: ["database", "firebase", "postgres"],
+ load: () => import("./appwrite/index").then((m) => m.generate),
+ },
+ {
+ id: "outline",
+ name: "Outline",
+ version: "0.82.0",
+ description:
+ "Outline is a self-hosted knowledge base and documentation platform that allows you to build and manage your own knowledge base applications.",
+ links: {
+ github: "https://github.com/outline/outline",
+ website: "https://outline.com/",
+ docs: "https://docs.outline.com/",
+ },
+ logo: "outline.png",
+ load: () => import("./outline/index").then((m) => m.generate),
+ tags: ["documentation", "knowledge-base", "self-hosted"],
+ },
{
id: "supabase",
name: "SupaBase",
@@ -34,7 +65,7 @@ export const templates: TemplateData[] = [
{
id: "plausible",
name: "Plausible",
- version: "v2.1.4",
+ version: "v2.1.5",
description:
"Plausible is a open source, self-hosted web analytics platform that lets you track website traffic and user behavior.",
logo: "plausible.svg",
@@ -170,7 +201,7 @@ export const templates: TemplateData[] = [
{
id: "wordpress",
name: "Wordpress",
- version: "5.8.3",
+ version: "6.7.1",
description:
"Wordpress is a free and open source content management system (CMS) for publishing and managing websites.",
logo: "wordpress.png",
@@ -1408,6 +1439,21 @@ export const templates: TemplateData[] = [
tags: ["file-manager", "vdfs", "storage"],
load: () => import("./spacedrive/index").then((m) => m.generate),
},
+ {
+ id: "registry",
+ name: "Docker Registry",
+ version: "2",
+ description:
+ "Distribution implementation for storing and distributing of Docker container images and artifacts.",
+ links: {
+ github: "https://github.com/distribution/distribution",
+ website: "https://hub.docker.com/_/registry",
+ docs: "https://distribution.github.io/distribution/",
+ },
+ logo: "registry.png",
+ tags: ["registry", "docker", "self-hosted"],
+ load: () => import("./registry/index").then((m) => m.generate),
+ },
{
id: "alist",
name: "AList",
@@ -1483,4 +1529,34 @@ export const templates: TemplateData[] = [
tags: ["forms", "analytics"],
load: () => import("./formbricks/index").then((m) => m.generate),
},
+ {
+ id: "trilium",
+ name: "Trilium",
+ description:
+ "Trilium Notes is a hierarchical note taking application with focus on building large personal knowledge bases.",
+ logo: "trilium.png",
+ version: "latest",
+ links: {
+ github: "https://github.com/zadam/trilium",
+ website: "https://github.com/zadam/trilium",
+ docs: "https://github.com/zadam/trilium/wiki/",
+ },
+ tags: ["self-hosted", "productivity", "personal-use"],
+ load: () => import("./trilium/index").then((m) => m.generate),
+ },
+ {
+ id: "convex",
+ name: "Convex",
+ version: "latest",
+ description:
+ "Convex is an open-source reactive database designed to make life easy for web app developers.",
+ logo: "convex.svg",
+ links: {
+ github: "https://github.com/get-convex/convex",
+ website: "https://www.convex.dev/",
+ docs: "https://www.convex.dev/docs",
+ },
+ tags: ["backend", "database", "api"],
+ load: () => import("./convex/index").then((m) => m.generate),
+ },
];
diff --git a/apps/dokploy/templates/trilium/docker-compose.yml b/apps/dokploy/templates/trilium/docker-compose.yml
new file mode 100644
index 0000000000..f549d8204e
--- /dev/null
+++ b/apps/dokploy/templates/trilium/docker-compose.yml
@@ -0,0 +1,14 @@
+services:
+ trilium:
+ image: zadam/trilium:latest
+ ports:
+ - 8080
+ networks:
+ - dokploy-network
+ restart: always
+ volumes:
+ - /root/trilium-backups:/home/node/trilium-data/backup
+
+networks:
+ dokploy-network:
+ external: true
diff --git a/apps/dokploy/templates/trilium/index.ts b/apps/dokploy/templates/trilium/index.ts
new file mode 100644
index 0000000000..acac984130
--- /dev/null
+++ b/apps/dokploy/templates/trilium/index.ts
@@ -0,0 +1,22 @@
+import {
+ type DomainSchema,
+ type Schema,
+ type Template,
+ generateRandomDomain,
+} from "../utils";
+
+export function generate(schema: Schema): Template {
+ const triliumDomain = generateRandomDomain(schema);
+
+ const domains: DomainSchema[] = [
+ {
+ host: triliumDomain,
+ port: 8080,
+ serviceName: "trilium",
+ },
+ ];
+
+ return {
+ domains,
+ };
+}
diff --git a/apps/dokploy/templates/utils/index.ts b/apps/dokploy/templates/utils/index.ts
index b5369b9161..941afc806f 100644
--- a/apps/dokploy/templates/utils/index.ts
+++ b/apps/dokploy/templates/utils/index.ts
@@ -12,7 +12,9 @@ export interface Schema {
projectName: string;
}
-export type DomainSchema = Pick;
+export type DomainSchema = Pick & {
+ path?: string;
+};
export interface Template {
envs?: string[];
diff --git a/packages/server/src/setup/postgres-setup.ts b/packages/server/src/setup/postgres-setup.ts
index b5794c2b2a..8e11e8cc9a 100644
--- a/packages/server/src/setup/postgres-setup.ts
+++ b/packages/server/src/setup/postgres-setup.ts
@@ -54,10 +54,16 @@ export const initializePostgres = async () => {
version: Number.parseInt(inspect.Version.Index),
...settings,
});
-
console.log("Postgres Started ✅");
} catch (error) {
- await docker.createService(settings);
+ try {
+ await docker.createService(settings);
+ } catch (error: any) {
+ if (error?.statusCode !== 409) {
+ throw error;
+ }
+ console.log("Postgres service already exists, continuing...");
+ }
console.log("Postgres Not Found: Starting ✅");
}
};
diff --git a/packages/server/src/setup/redis-setup.ts b/packages/server/src/setup/redis-setup.ts
index 1c3b545a52..0a191d11b8 100644
--- a/packages/server/src/setup/redis-setup.ts
+++ b/packages/server/src/setup/redis-setup.ts
@@ -53,7 +53,14 @@ export const initializeRedis = async () => {
});
console.log("Redis Started ✅");
} catch (error) {
- await docker.createService(settings);
+ try {
+ await docker.createService(settings);
+ } catch (error: any) {
+ if (error?.statusCode !== 409) {
+ throw error;
+ }
+ console.log("Redis service already exists, continuing...");
+ }
console.log("Redis Not Found: Starting ✅");
}
};
diff --git a/packages/server/src/setup/traefik-setup.ts b/packages/server/src/setup/traefik-setup.ts
index 1d60e577cc..21caa5cf23 100644
--- a/packages/server/src/setup/traefik-setup.ts
+++ b/packages/server/src/setup/traefik-setup.ts
@@ -128,7 +128,14 @@ export const initializeTraefik = async ({
console.log("Traefik Started ✅");
} catch (error) {
- await docker.createService(settings);
+ try {
+ await docker.createService(settings);
+ } catch (error: any) {
+ if (error?.statusCode !== 409) {
+ throw error;
+ }
+ console.log("Traefik service already exists, continuing...");
+ }
console.log("Traefik Not Found: Starting ✅");
}
};
diff --git a/packages/server/src/utils/traefik/domain.ts b/packages/server/src/utils/traefik/domain.ts
index a6c878e72c..1ae3c05a14 100644
--- a/packages/server/src/utils/traefik/domain.ts
+++ b/packages/server/src/utils/traefik/domain.ts
@@ -122,13 +122,25 @@ export const createRouterConfig = async (
if ((entryPoint === "websecure" && https) || !https) {
// redirects
for (const redirect of redirects) {
- const middlewareName = `redirect-${appName}-${redirect.uniqueConfigKey}`;
+ let middlewareName = `redirect-${appName}-${redirect.uniqueConfigKey}`;
+ if (domain.domainType === "preview") {
+ middlewareName = `redirect-${appName.replace(
+ /^preview-(.+)-[^-]+$/,
+ "$1",
+ )}-${redirect.uniqueConfigKey}`;
+ }
routerConfig.middlewares?.push(middlewareName);
}
// security
if (security.length > 0) {
- const middlewareName = `auth-${appName}`;
+ let middlewareName = `auth-${appName}`;
+ if (domain.domainType === "preview") {
+ middlewareName = `auth-${appName.replace(
+ /^preview-(.+)-[^-]+$/,
+ "$1",
+ )}`;
+ }
routerConfig.middlewares?.push(middlewareName);
}
}