mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
Merge branch 'canary' into feat/requests
This commit is contained in:
BIN
.github/sponsors/hostinger.jpg
vendored
Normal file
BIN
.github/sponsors/hostinger.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 173 KiB |
@@ -9,7 +9,7 @@
|
||||
<div align="center">
|
||||
<div>Join us on Discord for help, feedback, and discussions!</div>
|
||||
</br>
|
||||
<a href="https://discord.gg/ZXwG32bw">
|
||||
<a href="https://discord.gg/2tBnJ3jDJc">
|
||||
<img src="https://discordapp.com/api/guilds/1234073262418563112/widget.png?style=banner2" alt="Discord Shield"/>
|
||||
</a>
|
||||
</div>
|
||||
@@ -56,6 +56,10 @@ For detailed documentation, visit [docs.dokploy.com](https://docs.dokploy.com).
|
||||
|
||||
<!-- Add Hero Sponsors here -->
|
||||
|
||||
### Hero Sponsors 🎖
|
||||
|
||||
<a href="https://www.hostinger.com/?ref=dokploy" target="_blank" ><img src=".github/sponsors/hostinger.jpg" alt="Hostinger" width="200"/></a>
|
||||
|
||||
### Premium Supporters 🥇
|
||||
|
||||
<div style="display: flex; gap: 30px; flex-wrap: wrap;">
|
||||
|
||||
@@ -69,4 +69,4 @@ Open your web browser and navigate to `http://your-ip-from-your-vps:3000`. You w
|
||||
|
||||
1. **Create an Admin Account:** Fill in the necessary details to set up your administrator account. This account will be the admin account for Dokploy.
|
||||
|
||||
<ImageZoom src="/assets/images/setup.png" width={1300} height={630} alt='home og image' className="rounded-lg" />
|
||||
<ImageZoom src="/assets/images/setup.png" width={1300} height={650} alt='home og image' className="rounded-lg" />
|
||||
@@ -32,22 +32,22 @@ Please go to get started.
|
||||
|
||||
<Cards>
|
||||
<Card
|
||||
href="/get-started/installation"
|
||||
href="/docs/core/get-started/installation"
|
||||
title="Installation"
|
||||
description="Learn how to install Dokploy."
|
||||
/>
|
||||
<Card
|
||||
href="/application/overview"
|
||||
href="/docs/core/application/overview"
|
||||
title="Applications"
|
||||
description="Learn how to deploy applications."
|
||||
/>
|
||||
<Card
|
||||
href="/databases/overview"
|
||||
href="/docs/core/databases/overview"
|
||||
title="Databases"
|
||||
description="Learn how to deploy databases."
|
||||
/>
|
||||
<Card
|
||||
href="/traefik/overview"
|
||||
href="/docs/core/traefik/overview"
|
||||
title="Traefik"
|
||||
description="Learn how to deploy Traefik."
|
||||
/>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 101 KiB |
@@ -71,7 +71,10 @@ export const ShowDomains = ({ applicationId }: Props) => {
|
||||
key={item.domainId}
|
||||
className="flex w-full items-center gap-4 max-sm:flex-wrap border p-4 rounded-lg"
|
||||
>
|
||||
<Link target="_blank" href={`http://${item.host}`}>
|
||||
<Link
|
||||
target="_blank"
|
||||
href={`${item.https ? "https" : "http"}://${item.host}${item.path}`}
|
||||
>
|
||||
<ExternalLink className="size-5" />
|
||||
</Link>
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ TRAEFIK_CERTIFICATESRESOLVERS_LETSENCRYPT_HTTP_CHALLENGE_DNS_PROVIDER=cloudflare
|
||||
<DialogFooter>
|
||||
<Button
|
||||
isLoading={isLoading}
|
||||
disabled={canEdit}
|
||||
disabled={canEdit || isLoading}
|
||||
form="hook-form-update-server-traefik-config"
|
||||
type="submit"
|
||||
>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dokploy",
|
||||
"version": "v0.7.1",
|
||||
"version": "v0.7.3",
|
||||
"private": true,
|
||||
"license": "Apache-2.0",
|
||||
"type": "module",
|
||||
|
||||
13
apps/dokploy/public/templates/typebot.svg
Normal file
13
apps/dokploy/public/templates/typebot.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<svg viewBox="0 0 800 800" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="800" height="800" rx="80" fill="#0042DA" style="--darkreader-inline-fill:#0035ae" />
|
||||
<rect x="650" y="293" width="85.47" height="384.617" rx="20" transform="rotate(90 650 293)" fill="#FF8E20"
|
||||
style="--darkreader-inline-fill:#ff9630" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M192.735 378.47c23.602 0 42.735-19.133 42.735-42.735S216.337 293 192.735 293 150 312.133 150 335.735s19.133 42.735 42.735 42.735Z"
|
||||
fill="#FF8E20" style="--darkreader-inline-fill:#ff9630" />
|
||||
<rect x="150" y="506.677" width="85.47" height="384.617" rx="20" transform="rotate(-90 150 506.677)" fill="#fff"
|
||||
style="--darkreader-inline-fill:#e8e6e3" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M607.265 421.206c-23.602 0-42.735 19.134-42.735 42.736 0 23.602 19.133 42.735 42.735 42.735S650 487.544 650 463.942s-19.133-42.736-42.735-42.736Z"
|
||||
fill="#fff" style="--darkreader-inline-fill:#e8e6e3" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1000 B |
BIN
apps/dokploy/public/templates/zipline.png
Normal file
BIN
apps/dokploy/public/templates/zipline.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
@@ -12,6 +12,7 @@ import {
|
||||
} from "@/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import * as bcrypt from "bcrypt";
|
||||
import { db } from "../../db";
|
||||
import {
|
||||
createAdmin,
|
||||
createUser,
|
||||
@@ -33,6 +34,14 @@ export const authRouter = createTRPCRouter({
|
||||
.input(apiCreateAdmin)
|
||||
.mutation(async ({ ctx, input }) => {
|
||||
try {
|
||||
const admin = await db.query.admins.findFirst({});
|
||||
|
||||
if (admin) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Admin already exists",
|
||||
});
|
||||
}
|
||||
const newAdmin = await createAdmin(input);
|
||||
const session = await lucia.createSession(newAdmin.id || "", {});
|
||||
ctx.res.appendHeader(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { chmodSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import type { CreateServiceOptions } from "dockerode";
|
||||
import type { ContainerTaskSpec, CreateServiceOptions } from "dockerode";
|
||||
import { dump } from "js-yaml";
|
||||
import { DYNAMIC_TRAEFIK_PATH, MAIN_TRAEFIK_PATH, docker } from "../constants";
|
||||
import { pullImage } from "../utils/docker/utils";
|
||||
@@ -18,7 +18,7 @@ interface TraefikOptions {
|
||||
|
||||
export const initializeTraefik = async ({
|
||||
enableDashboard = false,
|
||||
env = [],
|
||||
env,
|
||||
}: TraefikOptions = {}) => {
|
||||
const imageName = "traefik:v2.5";
|
||||
const containerName = "dokploy-traefik";
|
||||
@@ -85,9 +85,23 @@ export const initializeTraefik = async ({
|
||||
|
||||
const service = docker.getService(containerName);
|
||||
const inspect = await service.inspect();
|
||||
|
||||
const existingEnv = inspect.Spec.TaskTemplate.ContainerSpec.Env || [];
|
||||
const updatedEnv = !env ? existingEnv : env;
|
||||
|
||||
const updatedSettings = {
|
||||
...settings,
|
||||
TaskTemplate: {
|
||||
...settings.TaskTemplate,
|
||||
ContainerSpec: {
|
||||
...(settings?.TaskTemplate as ContainerTaskSpec).ContainerSpec,
|
||||
Env: updatedEnv,
|
||||
},
|
||||
},
|
||||
};
|
||||
await service.update({
|
||||
version: Number.parseInt(inspect.Version.Index),
|
||||
...settings,
|
||||
...updatedSettings,
|
||||
});
|
||||
|
||||
console.log("Traefik Started ✅");
|
||||
|
||||
@@ -109,7 +109,7 @@ export const cleanStoppedContainers = async () => {
|
||||
|
||||
export const cleanUpUnusedVolumes = async () => {
|
||||
try {
|
||||
await execAsync("docker volume prune --force");
|
||||
await execAsync("docker volume prune --all --force");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
throw error;
|
||||
|
||||
@@ -18,7 +18,7 @@ services:
|
||||
start_period: 10s
|
||||
|
||||
documenso:
|
||||
image: documenso/documenso:1.5.6-rc.2
|
||||
image: documenso/documenso:v1.5.6-rc.2
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
|
||||
@@ -423,6 +423,21 @@ export const templates: TemplateData[] = [
|
||||
tags: ["database", "spreadsheet", "low-code", "nocode"],
|
||||
load: () => import("./teable/index").then((m) => m.generate),
|
||||
},
|
||||
{
|
||||
id: "zipline",
|
||||
name: "Zipline",
|
||||
version: "v3.7.9",
|
||||
description:
|
||||
"A ShareX/file upload server that is easy to use, packed with features, and with an easy setup!",
|
||||
logo: "zipline.png",
|
||||
links: {
|
||||
github: "https://github.com/diced/zipline",
|
||||
website: "https://zipline.diced.sh/",
|
||||
docs: "https://zipline.diced.sh/docs/",
|
||||
},
|
||||
tags: ["media system", "storage"],
|
||||
load: () => import("./zipline/index").then((m) => m.generate),
|
||||
},
|
||||
{
|
||||
id: "soketi",
|
||||
name: "Soketi",
|
||||
@@ -453,4 +468,18 @@ export const templates: TemplateData[] = [
|
||||
tags: ["analytics", "self-hosted"],
|
||||
load: () => import("./aptabase/index").then((m) => m.generate),
|
||||
},
|
||||
{
|
||||
id: "typebot",
|
||||
name: "Typebot",
|
||||
version: "2.27.0",
|
||||
description: "Typebot is an open-source chatbot builder platform.",
|
||||
logo: "typebot.svg",
|
||||
links: {
|
||||
github: "https://github.com/baptisteArno/typebot.io",
|
||||
website: "https://typebot.io/",
|
||||
docs: "https://docs.typebot.io/get-started/introduction",
|
||||
},
|
||||
tags: ["chatbot", "builder", "open-source"],
|
||||
load: () => import("./typebot/index").then((m) => m.generate),
|
||||
},
|
||||
];
|
||||
|
||||
49
apps/dokploy/templates/typebot/docker-compose.yml
Normal file
49
apps/dokploy/templates/typebot/docker-compose.yml
Normal file
@@ -0,0 +1,49 @@
|
||||
version: '3.3'
|
||||
|
||||
volumes:
|
||||
db-data:
|
||||
|
||||
services:
|
||||
typebot-db:
|
||||
image: postgres:14-alpine
|
||||
restart: always
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_USER: typebot
|
||||
POSTGRES_DB: typebot
|
||||
POSTGRES_PASSWORD: typebot
|
||||
networks:
|
||||
- dokploy-network
|
||||
|
||||
typebot-builder:
|
||||
image: baptistearno/typebot-builder:2.27
|
||||
restart: always
|
||||
depends_on:
|
||||
- typebot-db
|
||||
environment:
|
||||
ENCRYPTION_SECRET: '${ENCRYPTION_SECRET}'
|
||||
DATABASE_URL: 'postgresql://typebot:typebot@typebot-db:5432/typebot'
|
||||
NEXTAUTH_URL: '${NEXTAUTH_URL}'
|
||||
NEXT_PUBLIC_VIEWER_URL: '${NEXT_PUBLIC_VIEWER_URL}'
|
||||
ADMIN_EMAIL: '${ADMIN_EMAIL}'
|
||||
SMTP_HOST: '${SMTP_HOST}'
|
||||
NEXT_PUBLIC_SMTP_FROM: '${NEXT_PUBLIC_SMTP_FROM}'
|
||||
SMTP_USERNAME: '${SMTP_USERNAME}'
|
||||
SMTP_PASSWORD: '${SMTP_PASSWORD}'
|
||||
DEFAULT_WORKSPACE_PLAN: '${DEFAULT_WORKSPACE_PLAN}'
|
||||
|
||||
typebot-viewer:
|
||||
image: baptistearno/typebot-viewer:2.27.0
|
||||
restart: always
|
||||
environment:
|
||||
ENCRYPTION_SECRET: '${ENCRYPTION_SECRET}'
|
||||
DATABASE_URL: postgresql://typebot:typebot@typebot-db:5432/typebot
|
||||
NEXTAUTH_URL: '${NEXTAUTH_URL}'
|
||||
NEXT_PUBLIC_VIEWER_URL: '${NEXT_PUBLIC_VIEWER_URL}'
|
||||
ADMIN_EMAIL: '${ADMIN_EMAIL}'
|
||||
SMTP_HOST: '${SMTP_HOST}'
|
||||
NEXT_PUBLIC_SMTP_FROM: '${NEXT_PUBLIC_SMTP_FROM}'
|
||||
SMTP_USERNAME: '${SMTP_USERNAME}'
|
||||
SMTP_PASSWORD: '${SMTP_PASSWORD}'
|
||||
DEFAULT_WORKSPACE_PLAN: '${DEFAULT_WORKSPACE_PLAN}'
|
||||
44
apps/dokploy/templates/typebot/index.ts
Normal file
44
apps/dokploy/templates/typebot/index.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import {
|
||||
type DomainSchema,
|
||||
type Schema,
|
||||
type Template,
|
||||
generateBase64,
|
||||
generateRandomDomain,
|
||||
} from "../utils";
|
||||
|
||||
export function generate(schema: Schema): Template {
|
||||
const builderDomain = generateRandomDomain(schema);
|
||||
const viewerDomain = generateRandomDomain(schema);
|
||||
const encryptionSecret = generateBase64(24);
|
||||
|
||||
const domains: DomainSchema[] = [
|
||||
{
|
||||
host: builderDomain,
|
||||
port: 3000,
|
||||
serviceName: "typebot-builder",
|
||||
},
|
||||
{
|
||||
host: viewerDomain,
|
||||
port: 3000,
|
||||
serviceName: "typebot-viewer",
|
||||
},
|
||||
];
|
||||
|
||||
const envs = [
|
||||
`ENCRYPTION_SECRET=${encryptionSecret}`,
|
||||
`NEXTAUTH_URL=http://${builderDomain}`,
|
||||
`NEXT_PUBLIC_VIEWER_URL=http://${viewerDomain}`,
|
||||
"ADMIN_EMAIL=typebot@example.com",
|
||||
"SMTP_HOST='Fill'",
|
||||
"SMTP_PORT=25",
|
||||
"SMTP_USERNAME='Fill'",
|
||||
"SMTP_PASSWORD='Fill'",
|
||||
"NEXT_PUBLIC_SMTP_FROM=typebot@example.com",
|
||||
"DEFAULT_WORKSPACE_PLAN=UNLIMITED",
|
||||
];
|
||||
|
||||
return {
|
||||
envs,
|
||||
domains,
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
umami:
|
||||
image: ghcr.io/umami-software/umami:postgresql-v2.12.1
|
||||
image: ghcr.io/umami-software/umami:postgresql-v2.13.2
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "curl http://localhost:3000/api/heartbeat"]
|
||||
|
||||
37
apps/dokploy/templates/zipline/docker-compose.yml
Normal file
37
apps/dokploy/templates/zipline/docker-compose.yml
Normal file
@@ -0,0 +1,37 @@
|
||||
version: "3"
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15
|
||||
networks:
|
||||
- dokploy-network
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=postgres
|
||||
- POSTGRES_DATABASE=postgres
|
||||
volumes:
|
||||
- pg_data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
zipline:
|
||||
image: ghcr.io/diced/zipline:3.7.9
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- CORE_RETURN_HTTPS=${ZIPLINE_RETURN_HTTPS}
|
||||
- CORE_SECRET=${ZIPLINE_SECRET}
|
||||
- CORE_HOST=0.0.0.0
|
||||
- CORE_PORT=${ZIPLINE_PORT}
|
||||
- CORE_DATABASE_URL=postgres://postgres:postgres@postgres/postgres
|
||||
- CORE_LOGGER=${ZIPLINE_LOGGER}
|
||||
volumes:
|
||||
- "../files/uploads:/zipline/uploads"
|
||||
- "../files/public:/zipline/public"
|
||||
depends_on:
|
||||
- "postgres"
|
||||
|
||||
volumes:
|
||||
pg_data:
|
||||
32
apps/dokploy/templates/zipline/index.ts
Normal file
32
apps/dokploy/templates/zipline/index.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import {
|
||||
type DomainSchema,
|
||||
type Schema,
|
||||
type Template,
|
||||
generateBase64,
|
||||
generateRandomDomain,
|
||||
} from "@/templates/utils";
|
||||
|
||||
export function generate(schema: Schema): Template {
|
||||
const randomDomain = generateRandomDomain(schema);
|
||||
const secretBase = generateBase64(64);
|
||||
|
||||
const domains: DomainSchema[] = [
|
||||
{
|
||||
host: randomDomain,
|
||||
port: 3000,
|
||||
serviceName: "zipline",
|
||||
},
|
||||
];
|
||||
|
||||
const envs = [
|
||||
"ZIPLINE_PORT=3000",
|
||||
`ZIPLINE_SECRET=${secretBase}`,
|
||||
"ZIPLINE_RETURN_HTTPS=false",
|
||||
"ZIPLINE_LOGGER=true",
|
||||
];
|
||||
|
||||
return {
|
||||
envs,
|
||||
domains,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user