diff --git a/.github/sponsors/mandarin.png b/.github/sponsors/mandarin.png new file mode 100644 index 000000000..f76512920 Binary files /dev/null and b/.github/sponsors/mandarin.png differ diff --git a/README.md b/README.md index 2e784812c..72620ef89 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,8 @@ Dokploy includes multiple features to make your life easier. To get started, run the following command on a VPS: +Want to skip the installation process? [Try the Dokploy Cloud](https://app.dokploy.com). + ```bash curl -sSL https://dokploy.com/install.sh | sh ``` @@ -60,12 +62,15 @@ For detailed documentation, visit [docs.dokploy.com](https://docs.dokploy.com). ### Hero Sponsors 🎖
- + Hostinger - + LX Aer + + Mandarin +
### Premium Supporters 🥇 diff --git a/apps/dokploy/__test__/compose/domain/labels.test.ts b/apps/dokploy/__test__/compose/domain/labels.test.ts index 5076a2042..4123b2877 100644 --- a/apps/dokploy/__test__/compose/domain/labels.test.ts +++ b/apps/dokploy/__test__/compose/domain/labels.test.ts @@ -26,11 +26,30 @@ describe("createDomainLabels", () => { "traefik.http.routers.test-app-1-web.entrypoints=web", "traefik.http.services.test-app-1-web.loadbalancer.server.port=8080", "traefik.http.routers.test-app-1-web.service=test-app-1-web", + "traefik.http.routers.test-app-1-web.rule=PathPrefix(`/`)", ]); }); it("should create labels for websecure entrypoint", async () => { const labels = await createDomainLabels(appName, baseDomain, "websecure"); + expect(labels).toEqual([ + "traefik.http.routers.test-app-1-websecure.rule=Host(`example.com`)", + "traefik.http.routers.test-app-1-websecure.entrypoints=websecure", + "traefik.http.services.test-app-1-websecure.loadbalancer.server.port=8080", + "traefik.http.routers.test-app-1-websecure.service=test-app-1-websecure", + "traefik.http.routers.test-app-1-websecure.rule=PathPrefix(`/`)", + ]); + }); + + it("shouldn't add the path prefix if is empty", async () => { + const labels = await createDomainLabels( + appName, + { + ...baseDomain, + path: "", + }, + "websecure", + ); expect(labels).toEqual([ "traefik.http.routers.test-app-1-websecure.rule=Host(`example.com`)", "traefik.http.routers.test-app-1-websecure.entrypoints=websecure", diff --git a/apps/dokploy/components/dashboard/application/advanced/ports/update-port.tsx b/apps/dokploy/components/dashboard/application/advanced/ports/update-port.tsx index 0ed9d2e27..a9f7f32d5 100644 --- a/apps/dokploy/components/dashboard/application/advanced/ports/update-port.tsx +++ b/apps/dokploy/components/dashboard/application/advanced/ports/update-port.tsx @@ -140,7 +140,7 @@ export const UpdatePort = ({ portId }: Props) => { Target Port - + diff --git a/apps/dokploy/components/dashboard/settings/git/github/add-github-provider.tsx b/apps/dokploy/components/dashboard/settings/git/github/add-github-provider.tsx index 58cc87238..a04a166b0 100644 --- a/apps/dokploy/components/dashboard/settings/git/github/add-github-provider.tsx +++ b/apps/dokploy/components/dashboard/settings/git/github/add-github-provider.tsx @@ -53,7 +53,7 @@ export const AddGithubProvider = () => { diff --git a/apps/dokploy/components/dashboard/settings/servers/actions/toggle-docker-cleanup.tsx b/apps/dokploy/components/dashboard/settings/servers/actions/toggle-docker-cleanup.tsx index 17edaa991..78ad12363 100644 --- a/apps/dokploy/components/dashboard/settings/servers/actions/toggle-docker-cleanup.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/actions/toggle-docker-cleanup.tsx @@ -23,29 +23,27 @@ export const ToggleDockerCleanup = ({ serverId }: Props) => { const enabled = data?.enableDockerCleanup || server?.enableDockerCleanup; const { mutateAsync } = api.settings.updateDockerCleanup.useMutation(); + + const handleToggle = async (checked: boolean) => { + try { + await mutateAsync({ + enableDockerCleanup: checked, + serverId: serverId, + }); + if (serverId) { + await refetchServer(); + } else { + await refetch(); + } + toast.success("Docker Cleanup updated"); + } catch (error) { + toast.error("Docker Cleanup Error"); + } + }; + return (
- { - await mutateAsync({ - enableDockerCleanup: e, - serverId: serverId, - }) - .then(async () => { - toast.success("Docker Cleanup Enabled"); - }) - .catch(() => { - toast.error("Docker Cleanup Error"); - }); - - if (serverId) { - refetchServer(); - } else { - refetch(); - } - }} - /> +
); diff --git a/apps/dokploy/components/icons/data-tools-icons.tsx b/apps/dokploy/components/icons/data-tools-icons.tsx index 43c2b371a..116f5d8aa 100644 --- a/apps/dokploy/components/icons/data-tools-icons.tsx +++ b/apps/dokploy/components/icons/data-tools-icons.tsx @@ -161,29 +161,27 @@ export const GitlabIcon = ({ className }: Props) => { return ( ); @@ -200,7 +198,7 @@ export const GithubIcon = ({ className }: Props) => { > @@ -209,30 +207,34 @@ export const GithubIcon = ({ className }: Props) => { export const BitbucketIcon = ({ className }: Props) => { return ( - + + + - - + + - - ); }; diff --git a/apps/dokploy/package.json b/apps/dokploy/package.json index e62bb1dd8..9573eee5d 100644 --- a/apps/dokploy/package.json +++ b/apps/dokploy/package.json @@ -1,6 +1,6 @@ { "name": "dokploy", - "version": "v0.10.10", + "version": "v0.11.0", "private": true, "license": "Apache-2.0", "type": "module", @@ -11,7 +11,7 @@ "build-next": "next build", "setup": "tsx -r dotenv/config setup.ts && sleep 5 && pnpm run migration:run", "reset-password": "node -r dotenv/config dist/reset-password.mjs", - "dev": "TURBOPACK=1 tsx -r dotenv/config ./server/server.ts --project tsconfig.server.json ", + "dev": "tsx -r dotenv/config ./server/server.ts --project tsconfig.server.json ", "studio": "drizzle-kit studio --config ./server/db/drizzle.config.ts", "migration:generate": "drizzle-kit generate --config ./server/db/drizzle.config.ts", "migration:run": "tsx -r dotenv/config migration.ts", diff --git a/apps/dokploy/public/templates/coder.svg b/apps/dokploy/public/templates/coder.svg new file mode 100644 index 000000000..56d2f77c3 --- /dev/null +++ b/apps/dokploy/public/templates/coder.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/dokploy/public/templates/docmost.png b/apps/dokploy/public/templates/docmost.png new file mode 100644 index 000000000..9bc8d2103 Binary files /dev/null and b/apps/dokploy/public/templates/docmost.png differ diff --git a/apps/dokploy/public/templates/hi-events.svg b/apps/dokploy/public/templates/hi-events.svg new file mode 100644 index 000000000..0e373509b --- /dev/null +++ b/apps/dokploy/public/templates/hi-events.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/dokploy/public/templates/infisical.jpg b/apps/dokploy/public/templates/infisical.jpg new file mode 100644 index 000000000..404f58119 Binary files /dev/null and b/apps/dokploy/public/templates/infisical.jpg differ diff --git a/apps/dokploy/public/templates/influxdb.png b/apps/dokploy/public/templates/influxdb.png new file mode 100644 index 000000000..8fc62a7fb Binary files /dev/null and b/apps/dokploy/public/templates/influxdb.png differ diff --git a/apps/dokploy/public/templates/macos.png b/apps/dokploy/public/templates/macos.png new file mode 100644 index 000000000..617122c87 Binary files /dev/null and b/apps/dokploy/public/templates/macos.png differ diff --git a/apps/dokploy/public/templates/vaultwarden.svg b/apps/dokploy/public/templates/vaultwarden.svg new file mode 100644 index 000000000..71866afd2 --- /dev/null +++ b/apps/dokploy/public/templates/vaultwarden.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/apps/dokploy/public/templates/windows.png b/apps/dokploy/public/templates/windows.png new file mode 100644 index 000000000..61ced4559 Binary files /dev/null and b/apps/dokploy/public/templates/windows.png differ diff --git a/apps/dokploy/server/server.ts b/apps/dokploy/server/server.ts index b65446f8b..bf1112333 100644 --- a/apps/dokploy/server/server.ts +++ b/apps/dokploy/server/server.ts @@ -24,7 +24,7 @@ import { setupTerminalWebSocketServer } from "./wss/terminal"; config({ path: ".env" }); const PORT = Number.parseInt(process.env.PORT || "3000", 10); const dev = process.env.NODE_ENV !== "production"; -const app = next({ dev, turbopack: dev }); +const app = next({ dev }); const handle = app.getRequestHandler(); void app.prepare().then(async () => { try { diff --git a/apps/dokploy/templates/coder/docker-compose.yml b/apps/dokploy/templates/coder/docker-compose.yml new file mode 100644 index 000000000..27bb14bd2 --- /dev/null +++ b/apps/dokploy/templates/coder/docker-compose.yml @@ -0,0 +1,39 @@ +services: + coder: + image: ghcr.io/coder/coder:v2.15.3 + networks: + - dokploy-network + volumes: + - /var/run/docker.sock:/var/run/docker.sock + group_add: + - "998" + depends_on: + db: + condition: service_healthy + environment: + - CODER_ACCESS_URL + - CODER_HTTP_ADDRESS + - CODER_PG_CONNECTION_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db/${POSTGRES_DB}?sslmode=disable + + db: + image: postgres:17 + networks: + - dokploy-network + environment: + - POSTGRES_PASSWORD + - POSTGRES_USER + - POSTGRES_DB + healthcheck: + test: + [ + "CMD-SHELL", + "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}", + ] + interval: 5s + timeout: 5s + retries: 5 + volumes: + - db_coder_data:/var/lib/postgresql/data + +volumes: + db_coder_data: \ No newline at end of file diff --git a/apps/dokploy/templates/coder/index.ts b/apps/dokploy/templates/coder/index.ts new file mode 100644 index 000000000..c3f066d63 --- /dev/null +++ b/apps/dokploy/templates/coder/index.ts @@ -0,0 +1,30 @@ +import { + type DomainSchema, + type Schema, + type Template, + generateRandomDomain, +} from "../utils"; + +export function generate(schema: Schema): Template { + const domains: DomainSchema[] = [ + { + host: generateRandomDomain(schema), + port: 7080, + serviceName: "coder", + }, + ]; + + const envs = [ + "CODER_ACCESS_URL=", + "CODER_HTTP_ADDRESS=0.0.0.0:7080", + "", + "POSTGRES_DB=coder", + "POSTGRES_USER=coder", + "POSTGRES_PASSWORD=VERY_STRONG_PASSWORD", + ]; + + return { + domains, + envs, + }; +} diff --git a/apps/dokploy/templates/docmost/docker-compose.yml b/apps/dokploy/templates/docmost/docker-compose.yml new file mode 100644 index 000000000..a6ebbd4f4 --- /dev/null +++ b/apps/dokploy/templates/docmost/docker-compose.yml @@ -0,0 +1,47 @@ +version: "3" + +services: + docmost: + image: docmost/docmost:0.4.1 + depends_on: + - db + - redis + environment: + - APP_URL + - APP_SECRET + - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}?schema=public + - REDIS_URL=redis://redis:6379 + restart: unless-stopped + networks: + - dokploy-network + volumes: + - docmost:/app/data/storage + + db: + image: postgres:16-alpine + environment: + - POSTGRES_DB + - POSTGRES_USER + - POSTGRES_PASSWORD + restart: unless-stopped + networks: + - dokploy-network + volumes: + - db_docmost_data:/var/lib/postgresql/data + + redis: + image: redis:7.2-alpine + restart: unless-stopped + networks: + - dokploy-network + volumes: + - redis_docmost_data:/data + +networks: + dokploy-network: + external: true + +volumes: + docmost: + db_docmost_data: + redis_docmost_data: \ No newline at end of file diff --git a/apps/dokploy/templates/docmost/index.ts b/apps/dokploy/templates/docmost/index.ts new file mode 100644 index 000000000..16f7afa66 --- /dev/null +++ b/apps/dokploy/templates/docmost/index.ts @@ -0,0 +1,29 @@ +import { + type DomainSchema, + type Schema, + type Template, + generateRandomDomain, +} from "../utils"; + +export function generate(schema: Schema): Template { + const domains: DomainSchema[] = [ + { + host: generateRandomDomain(schema), + port: 3000, + serviceName: "docmost", + }, + ]; + + const envs = [ + "POSTGRES_DB=docmost", + "POSTGRES_USER=docmost", + "POSTGRES_PASSWORD=STRONG_DB_PASSWORD", + "APP_URL=http://localhost:3000", + "APP_SECRET=VERY_STRONG_SECRET", + ]; + + return { + domains, + envs, + }; +} diff --git a/apps/dokploy/templates/gitea/docker-compose.yml b/apps/dokploy/templates/gitea/docker-compose.yml index 679936fb7..72e0754e2 100644 --- a/apps/dokploy/templates/gitea/docker-compose.yml +++ b/apps/dokploy/templates/gitea/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.8" services: gitea: - image: gitea/gitea:1.22.2 + image: gitea/gitea:1.22.3 environment: - USER_UID=${USER_UID} - USER_GID=${USER_GID} @@ -21,7 +21,7 @@ services: - db db: - image: postgres:16 + image: postgres:17 restart: always environment: - POSTGRES_USER=gitea diff --git a/apps/dokploy/templates/hi-events/docker-compose.yml b/apps/dokploy/templates/hi-events/docker-compose.yml new file mode 100644 index 000000000..0ce5b7e75 --- /dev/null +++ b/apps/dokploy/templates/hi-events/docker-compose.yml @@ -0,0 +1,45 @@ +services: + all-in-one: + image: daveearley/hi.events-all-in-one:v0.8.0-beta.1 + restart: always + environment: + - VITE_FRONTEND_URL=https://${DOMAIN} + - APP_FRONTEND_URL=https://${DOMAIN} + - VITE_API_URL_CLIENT=https://${DOMAIN}/api + - VITE_API_URL_SERVER=http://localhost:80/api + - VITE_STRIPE_PUBLISHABLE_KEY + - LOG_CHANNEL=stderr + - QUEUE_CONNECTION=sync + - MAIL_MAILER=array + - APP_KEY + - JWT_SECRET + - FILESYSTEM_PUBLIC_DISK=public + - FILESYSTEM_PRIVATE_DISK=local + - APP_CDN_URL=https://${DOMAIN}/storage + - DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB} + - MAIL_MAILER + - MAIL_HOST + - MAIL_PORT + - MAIL_FROM_ADDRESS + - MAIL_FROM_NAME + depends_on: + - postgres + + postgres: + image: elestio/postgres:16 + restart: always + networks: + - dokploy-network + environment: + - POSTGRES_DB + - POSTGRES_USER + - POSTGRES_PASSWORD + volumes: + - pg_hi-events_data:/var/lib/postgresql/data + +networks: + dokploy-network: + external: true + +volumes: + pg_hi-events_data: \ No newline at end of file diff --git a/apps/dokploy/templates/hi-events/index.ts b/apps/dokploy/templates/hi-events/index.ts new file mode 100644 index 000000000..f799bb737 --- /dev/null +++ b/apps/dokploy/templates/hi-events/index.ts @@ -0,0 +1,41 @@ +import { + type DomainSchema, + type Schema, + type Template, + generateRandomDomain, +} from "../utils"; + +export function generate(schema: Schema): Template { + const domains: DomainSchema[] = [ + { + host: generateRandomDomain(schema), + port: 80, + serviceName: "all-in-one", + }, + ]; + + const envs = [ + "# change domain here", + "DOMAIN=my-events.com", + "", + "POSTGRES_DB=hievents", + "POSTGRES_USER=hievents", + "POSTGRES_PASSWORD=VERY_STRONG_PASSWORD", + "", + "VITE_STRIPE_PUBLISHABLE_KEY=", + "", + "APP_KEY=my-app-key", + "JWT_SECRET=STRONG_JWT_SECRET", + "", + "MAIL_MAILER=", + "MAIL_HOST=", + "MAIL_PORT=", + "MAIL_FROM_ADDRESS=", + "MAIL_FROM_NAME=", + ]; + + return { + domains, + envs, + }; +} diff --git a/apps/dokploy/templates/infisical/docker-compose.yml b/apps/dokploy/templates/infisical/docker-compose.yml new file mode 100644 index 000000000..3baca9265 --- /dev/null +++ b/apps/dokploy/templates/infisical/docker-compose.yml @@ -0,0 +1,87 @@ +services: + db-migration: + depends_on: + db: + condition: service_healthy + image: infisical/infisical:v0.90.1-postgres + environment: + - NODE_ENV=production + - ENCRYPTION_KEY + - AUTH_SECRET + - SITE_URL + - DB_CONNECTION_URI=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB} + - REDIS_URL=redis://redis:6379 + - SMTP_HOST + - SMTP_PORT + - SMTP_FROM_NAME + - SMTP_USERNAME + - SMTP_PASSWORD + - SMTP_SECURE=true + command: npm run migration:latest + pull_policy: always + networks: + - dokploy-network + + backend: + restart: unless-stopped + depends_on: + db: + condition: service_healthy + redis: + condition: service_started + db-migration: + condition: service_completed_successfully + image: infisical/infisical:v0.90.1-postgres + pull_policy: always + environment: + - NODE_ENV=production + - ENCRYPTION_KEY + - AUTH_SECRET + - SITE_URL + - DB_CONNECTION_URI=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB} + - REDIS_URL=redis://redis:6379 + - SMTP_HOST + - SMTP_PORT + - SMTP_FROM_NAME + - SMTP_USERNAME + - SMTP_PASSWORD + - SMTP_SECURE=true + networks: + - dokploy-network + + redis: + image: redis:7.4.1 + env_file: .env + restart: always + environment: + - ALLOW_EMPTY_PASSWORD=yes + networks: + - dokploy-network + volumes: + - redis_infisical_data:/data + + db: + image: postgres:14-alpine + restart: always + environment: + - POSTGRES_PASSWORD + - POSTGRES_USER + - POSTGRES_DB + volumes: + - pg_infisical_data:/var/lib/postgresql/data + networks: + - dokploy-network + healthcheck: + test: "pg_isready --username=${POSTGRES_USER} && psql --username=${POSTGRES_USER} --list" + interval: 5s + timeout: 10s + retries: 10 + +volumes: + pg_infisical_data: + redis_infisical_data: + +networks: + dokploy-network: + external: true + diff --git a/apps/dokploy/templates/infisical/index.ts b/apps/dokploy/templates/infisical/index.ts new file mode 100644 index 000000000..6d2127740 --- /dev/null +++ b/apps/dokploy/templates/infisical/index.ts @@ -0,0 +1,93 @@ +import { + type DomainSchema, + type Schema, + type Template, + generateRandomDomain, +} from "../utils"; + +export function generate(schema: Schema): Template { + const domains: DomainSchema[] = [ + { + host: generateRandomDomain(schema), + port: 8080, + serviceName: "backend", + }, + ]; + + const envs = [ + "# THIS IS A SAMPLE ENCRYPTION KEY AND SHOULD NEVER BE USED FOR PRODUCTION", + "ENCRYPTION_KEY=6c1fe4e407b8911c104518103505b218", + "", + "# THIS IS A SAMPLE AUTH_SECRET KEY AND SHOULD NEVER BE USED FOR PRODUCTION", + "AUTH_SECRET=5lrMXKKWCVocS/uerPsl7V+TX/aaUaI7iDkgl3tSmLE=", + "# Postgres creds", + "POSTGRES_PASSWORD=infisical", + "POSTGRES_USER=infisical", + "POSTGRES_DB=infisical", + "", + "# Website URL", + "# Required", + "SITE_URL=http://localhost:8080", + "", + "# Mail/SMTP", + "SMTP_HOST=", + "SMTP_PORT=", + "SMTP_NAME=", + "SMTP_USERNAME=", + "SMTP_PASSWORD=", + "", + "# Integration", + "# Optional only if integration is used", + "CLIENT_ID_HEROKU=", + "CLIENT_ID_VERCEL=", + "CLIENT_ID_NETLIFY=", + "CLIENT_ID_GITHUB=", + "CLIENT_ID_GITHUB_APP=", + "CLIENT_SLUG_GITHUB_APP=", + "CLIENT_ID_GITLAB=", + "CLIENT_ID_BITBUCKET=", + "CLIENT_SECRET_HEROKU=", + "CLIENT_SECRET_VERCEL=", + "CLIENT_SECRET_NETLIFY=", + "CLIENT_SECRET_GITHUB=", + "CLIENT_SECRET_GITHUB_APP=", + "CLIENT_SECRET_GITLAB=", + "CLIENT_SECRET_BITBUCKET=", + "CLIENT_SLUG_VERCEL=", + "", + "CLIENT_PRIVATE_KEY_GITHUB_APP=", + "CLIENT_APP_ID_GITHUB_APP=", + "", + "# Sentry (optional) for monitoring errors", + "SENTRY_DSN=", + "", + "# Infisical Cloud-specific configs", + "# Ignore - Not applicable for self-hosted version", + "POSTHOG_HOST=", + "POSTHOG_PROJECT_API_KEY=", + "", + "# SSO-specific variables", + "CLIENT_ID_GOOGLE_LOGIN=", + "CLIENT_SECRET_GOOGLE_LOGIN=", + "", + "CLIENT_ID_GITHUB_LOGIN=", + "CLIENT_SECRET_GITHUB_LOGIN=", + "", + "CLIENT_ID_GITLAB_LOGIN=", + "CLIENT_SECRET_GITLAB_LOGIN=", + "", + "CAPTCHA_SECRET=", + "", + "NEXT_PUBLIC_CAPTCHA_SITE_KEY=", + "", + "PLAIN_API_KEY=", + "PLAIN_WISH_LABEL_IDS=", + "", + "SSL_CLIENT_CERTIFICATE_HEADER_KEY=", + ]; + + return { + domains, + envs, + }; +} diff --git a/apps/dokploy/templates/influxdb/docker-compose.yml b/apps/dokploy/templates/influxdb/docker-compose.yml new file mode 100644 index 000000000..1327c6028 --- /dev/null +++ b/apps/dokploy/templates/influxdb/docker-compose.yml @@ -0,0 +1,11 @@ +services: + influxdb: + image: influxdb:2.7.10 + restart: unless-stopped + volumes: + - influxdb2-data:/var/lib/influxdb2 + - influxdb2-config:/etc/influxdb2 + +volumes: + influxdb2-data: + influxdb2-config: \ No newline at end of file diff --git a/apps/dokploy/templates/influxdb/index.ts b/apps/dokploy/templates/influxdb/index.ts new file mode 100644 index 000000000..550b680e7 --- /dev/null +++ b/apps/dokploy/templates/influxdb/index.ts @@ -0,0 +1,19 @@ +import { + type DomainSchema, + type Schema, + type Template, + generateRandomDomain, +} from "../utils"; + +export function generate(schema: Schema): Template { + const domains: DomainSchema[] = [ + { + host: generateRandomDomain(schema), + port: 8086, + serviceName: "influxdb", + }, + ]; + return { + domains, + }; +} diff --git a/apps/dokploy/templates/macos/docker-compose.yml b/apps/dokploy/templates/macos/docker-compose.yml new file mode 100644 index 000000000..585c1bf97 --- /dev/null +++ b/apps/dokploy/templates/macos/docker-compose.yml @@ -0,0 +1,16 @@ +services: + macos: + image: dockurr/macos:1.14 + volumes: + - macos-storage:/storage + environment: + - VERSION + devices: + # If in .env string 'KVM=N' is not commented, you need to comment line below + - /dev/kvm + cap_add: + - NET_ADMIN + stop_grace_period: 2m + +volumes: + macos-storage: \ No newline at end of file diff --git a/apps/dokploy/templates/macos/index.ts b/apps/dokploy/templates/macos/index.ts new file mode 100644 index 000000000..ebda41065 --- /dev/null +++ b/apps/dokploy/templates/macos/index.ts @@ -0,0 +1,33 @@ +import { + type DomainSchema, + type Schema, + type Template, + generateRandomDomain, +} from "../utils"; + +export function generate(schema: Schema): Template { + const domains: DomainSchema[] = [ + { + host: generateRandomDomain(schema), + port: 8006, + serviceName: "macos", + }, + ]; + + const envs = [ + "# https://github.com/dockur/macos?tab=readme-ov-file#how-do-i-select-the-macos-version", + "VERSION=15", + "", + "# Uncomment this if your PC/VM or etc does not support virtualization technology", + "# KVM=N", + "", + "DISK_SIZE=64G", + "RAM_SIZE=4G", + "CPU_CORES=2", + ]; + + return { + domains, + envs, + }; +} diff --git a/apps/dokploy/templates/nocodb/docker-compose.yml b/apps/dokploy/templates/nocodb/docker-compose.yml index 726cf5e61..3d5c9ee7a 100644 --- a/apps/dokploy/templates/nocodb/docker-compose.yml +++ b/apps/dokploy/templates/nocodb/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.8" services: nocodb: - image: nocodb/nocodb:0.251.1 + image: nocodb/nocodb:0.257.2 restart: always environment: NC_DB: "pg://root_db?u=postgres&p=password&d=root_db" @@ -11,7 +11,7 @@ services: - nc_data:/usr/app/data root_db: - image: postgres:14.7 + image: postgres:17 restart: always networks: - dokploy-network diff --git a/apps/dokploy/templates/soketi/docker-compose.yml b/apps/dokploy/templates/soketi/docker-compose.yml index 1784cdc79..d38cbb086 100644 --- a/apps/dokploy/templates/soketi/docker-compose.yml +++ b/apps/dokploy/templates/soketi/docker-compose.yml @@ -2,8 +2,7 @@ version: "3" services: soketi: - image: quay.io/soketi/soketi:1.4-16-debian - container_name: soketi + image: quay.io/soketi/soketi:1.6.1-16-debian environment: SOKETI_DEBUG: "1" SOKETI_HOST: "0.0.0.0" diff --git a/apps/dokploy/templates/templates.ts b/apps/dokploy/templates/templates.ts index c43ffc200..28af7c56e 100644 --- a/apps/dokploy/templates/templates.ts +++ b/apps/dokploy/templates/templates.ts @@ -125,7 +125,7 @@ export const templates: TemplateData[] = [ { id: "uptime-kuma", name: "Uptime Kuma", - version: "1.21.4", + version: "1.23.15", description: "Uptime Kuma is a free and open source monitoring tool that allows you to monitor your websites and applications.", logo: "uptime-kuma.png", @@ -218,7 +218,6 @@ export const templates: TemplateData[] = [ version: "v1.5.6", description: "Documenso is the open source alternative to DocuSign for signing documents digitally", - links: { github: "https://github.com/documenso/documenso", website: "https://documenso.com/", @@ -231,7 +230,7 @@ export const templates: TemplateData[] = [ { id: "nocodb", name: "NocoDB", - version: "0.251.1", + version: "0.257.2", description: "NocoDB is an opensource Airtable alternative that turns any MySQL, PostgreSQL, SQL Server, SQLite & MariaDB into a smart spreadsheet.", @@ -441,7 +440,7 @@ export const templates: TemplateData[] = [ { id: "soketi", name: "Soketi", - version: "v1.4-16", + version: "v1.6.1-16", description: "Soketi is your simple, fast, and resilient open-source WebSockets server.", logo: "soketi.png", @@ -485,7 +484,7 @@ export const templates: TemplateData[] = [ { id: "gitea", name: "Gitea", - version: "1.22.2", + version: "1.22.3", description: "Git with a cup of tea! Painless self-hosted all-in-one software development service, including Git hosting, code review, team collaboration, package registry and CI/CD.", logo: "gitea.png", @@ -557,6 +556,124 @@ export const templates: TemplateData[] = [ tags: ["cloud", "monitoring"], load: () => import("./portainer/index").then((m) => m.generate), }, + { + id: "influxdb", + name: "InfluxDB", + version: "2.7.10", + description: + "InfluxDB 2.7 is the platform purpose-built to collect, store, process and visualize time series data.", + logo: "influxdb.png", + links: { + github: "https://github.com/influxdata/influxdb", + website: "https://www.influxdata.com/", + docs: "https://docs.influxdata.com/influxdb/v2/", + }, + tags: ["self-hosted", "open-source", "storage", "database"], + load: () => import("./influxdb/index").then((m) => m.generate), + }, + { + id: "infisical", + name: "Infisical", + version: "0.90.1", + description: + "All-in-one platform to securely manage application configuration and secrets across your team and infrastructure.", + logo: "infisical.jpg", + links: { + github: "https://github.com/Infisical/infisical", + website: "https://infisical.com/", + docs: "https://infisical.com/docs/documentation/getting-started/introduction", + }, + tags: ["self-hosted", "open-source"], + load: () => import("./infisical/index").then((m) => m.generate), + }, + { + id: "docmost", + name: "Docmost", + version: "0.4.1", + description: + "Docmost, is an open-source collaborative wiki and documentation software.", + logo: "docmost.png", + links: { + github: "https://github.com/docmost/docmost", + website: "https://docmost.com/", + docs: "https://docmost.com/docs/", + }, + tags: ["self-hosted", "open-source", "manager"], + load: () => import("./docmost/index").then((m) => m.generate), + }, + { + id: "vaultwarden", + name: "Vaultwarden", + version: "1.32.3", + description: + "Unofficial Bitwarden compatible server written in Rust, formerly known as bitwarden_rs", + logo: "vaultwarden.svg", + links: { + github: "https://github.com/dani-garcia/vaultwarden", + website: "", + docs: "https://github.com/dani-garcia/vaultwarden/wiki", + }, + tags: ["open-source"], + load: () => import("./vaultwarden/index").then((m) => m.generate), + }, + { + id: "hi-events", + name: "Hi.events", + version: "0.8.0-beta.1", + description: + "Hi.Events is a self-hosted event management and ticket selling platform that allows you to create, manage and promote events easily.", + logo: "hi-events.svg", + links: { + github: "https://github.com/HiEventsDev/hi.events", + website: "https://hi.events/", + docs: "https://hi.events/docs", + }, + tags: ["self-hosted", "open-source", "manager"], + load: () => import("./hi-events/index").then((m) => m.generate), + }, + { + id: "windows", + name: "Windows (dockerized)", + version: "4.00", + description: "Windows inside a Docker container.", + logo: "windows.png", + links: { + github: "https://github.com/dockur/windows", + website: "", + docs: "https://github.com/dockur/windows?tab=readme-ov-file#how-do-i-use-it", + }, + tags: ["self-hosted", "open-source", "os"], + load: () => import("./windows/index").then((m) => m.generate), + }, + { + id: "macos", + name: "MacOS (dockerized)", + version: "1.14", + description: "MacOS inside a Docker container.", + logo: "macos.png", + links: { + github: "https://github.com/dockur/macos", + website: "", + docs: "https://github.com/dockur/macos?tab=readme-ov-file#how-do-i-use-it", + }, + tags: ["self-hosted", "open-source", "os"], + load: () => import("./macos/index").then((m) => m.generate), + }, + { + id: "coder", + name: "Coder", + version: "2.15.3", + description: + "Coder is an open-source cloud development environment (CDE) that you host in your cloud or on-premises.", + logo: "coder.svg", + links: { + github: "https://github.com/coder/coder", + website: "https://coder.com/", + docs: "https://coder.com/docs", + }, + tags: ["self-hosted", "open-source", "builder"], + load: () => import("./coder/index").then((m) => m.generate), + }, { id: "stirling", name: "Stirling PDF", diff --git a/apps/dokploy/templates/uptime-kuma/docker-compose.yml b/apps/dokploy/templates/uptime-kuma/docker-compose.yml index ccd775526..0d4ade73c 100644 --- a/apps/dokploy/templates/uptime-kuma/docker-compose.yml +++ b/apps/dokploy/templates/uptime-kuma/docker-compose.yml @@ -1,7 +1,7 @@ version: "3.8" services: uptime-kuma: - image: louislam/uptime-kuma:1 + image: louislam/uptime-kuma:1.23.15 restart: always volumes: - uptime-kuma-data:/app/data diff --git a/apps/dokploy/templates/vaultwarden/docker-compose.yml b/apps/dokploy/templates/vaultwarden/docker-compose.yml new file mode 100644 index 000000000..456f585b2 --- /dev/null +++ b/apps/dokploy/templates/vaultwarden/docker-compose.yml @@ -0,0 +1,14 @@ +services: + vaultwarden: + image: vaultwarden/server:1.32.3 + restart: always + environment: + DOMAIN: ${DOMAIN} + SIGNUPS_ALLOWED: ${SIGNUPS_ALLOWED} + volumes: + - vaultwarden:/data + ports: + - 80 + +volumes: + vaultwarden: diff --git a/apps/dokploy/templates/vaultwarden/index.ts b/apps/dokploy/templates/vaultwarden/index.ts new file mode 100644 index 000000000..66aa14657 --- /dev/null +++ b/apps/dokploy/templates/vaultwarden/index.ts @@ -0,0 +1,28 @@ +import { + type DomainSchema, + type Schema, + type Template, + generateRandomDomain, +} from "../utils"; + +export function generate(schema: Schema): Template { + const domains: DomainSchema[] = [ + { + host: generateRandomDomain(schema), + port: 80, + serviceName: "vaultwarden", + }, + ]; + + const envs = [ + "# Deactivate this with 'false' after you have created your account so that no strangers can register", + "SIGNUPS_ALLOWED=true", + "# required when using a reverse proxy; your domain; vaultwarden needs to know it's https to work properly with attachments", + "DOMAIN=https://vaultwarden.example.com", + ]; + + return { + domains, + envs, + }; +} diff --git a/apps/dokploy/templates/windows/docker-compose.yml b/apps/dokploy/templates/windows/docker-compose.yml new file mode 100644 index 000000000..8a0833702 --- /dev/null +++ b/apps/dokploy/templates/windows/docker-compose.yml @@ -0,0 +1,17 @@ +services: + windows: + image: dockurr/windows:4.00 + volumes: + - win-storage:/storage + environment: + - VERSION + - KVM + devices: + # If in .env string 'KVM=N' is not commented, you need to comment line below + - /dev/kvm + cap_add: + - NET_ADMIN + stop_grace_period: 2m + +volumes: + win-storage: \ No newline at end of file diff --git a/apps/dokploy/templates/windows/index.ts b/apps/dokploy/templates/windows/index.ts new file mode 100644 index 000000000..5e2728cb0 --- /dev/null +++ b/apps/dokploy/templates/windows/index.ts @@ -0,0 +1,39 @@ +import { + type DomainSchema, + type Schema, + type Template, + generateRandomDomain, +} from "../utils"; + +export function generate(schema: Schema): Template { + const domains: DomainSchema[] = [ + { + host: generateRandomDomain(schema), + port: 8006, + serviceName: "windows", + }, + ]; + + const envs = [ + "# https://github.com/dockur/windows?tab=readme-ov-file#how-do-i-select-the-windows-version", + "VERSION=win11", + "", + "# Uncomment this if your PC/VM or etc does not support virtualization technology", + "# KVM=N", + "", + "DISK_SIZE=64G", + "RAM_SIZE=4G", + "CPU_CORES=2", + "", + "USERNAME=Dokploy", + "PASSWORD=", + "", + "# https://github.com/dockur/windows?tab=readme-ov-file#how-do-i-select-the-windows-language", + "LANGUAGE=English", + ]; + + return { + domains, + envs, + }; +} diff --git a/packages/server/src/services/mongo.ts b/packages/server/src/services/mongo.ts index 1360372da..b87ec4da9 100644 --- a/packages/server/src/services/mongo.ts +++ b/packages/server/src/services/mongo.ts @@ -14,7 +14,7 @@ export type Mongo = typeof mongo.$inferSelect; export const createMongo = async (input: typeof apiCreateMongo._type) => { input.appName = - `${input.appName}-${generatePassword(6)}` || generateAppName("postgres"); + `${input.appName}-${generatePassword(6)}` || generateAppName("mongo"); if (input.appName) { const valid = await validUniqueServerAppName(input.appName); @@ -72,12 +72,12 @@ export const findMongoById = async (mongoId: string) => { export const updateMongoById = async ( mongoId: string, - postgresData: Partial, + mongoData: Partial, ) => { const result = await db .update(mongo) .set({ - ...postgresData, + ...mongoData, }) .where(eq(mongo.mongoId, mongoId)) .returning(); diff --git a/packages/server/src/utils/docker/domain.ts b/packages/server/src/utils/docker/domain.ts index 28ede3085..a065f31c0 100644 --- a/packages/server/src/utils/docker/domain.ts +++ b/packages/server/src/utils/docker/domain.ts @@ -268,6 +268,12 @@ export const createDomainLabels = async ( `traefik.http.routers.${routerName}.service=${routerName}`, ]; + if (domain.path) { + labels.push( + `traefik.http.routers.${routerName}.rule=PathPrefix(\`${domain.path}\`)`, + ); + } + if (entrypoint === "web" && https) { labels.push( `traefik.http.routers.${routerName}.middlewares=redirect-to-https@file`,