mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
Merge branch 'canary' into i18n-kazakh
This commit is contained in:
@@ -1,56 +1,94 @@
|
|||||||
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogDescription,
|
DialogDescription,
|
||||||
DialogHeader,
|
DialogFooter,
|
||||||
DialogTitle,
|
DialogHeader,
|
||||||
DialogTrigger,
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
const Terminal = dynamic(
|
const Terminal = dynamic(
|
||||||
() => import("./docker-terminal").then((e) => e.DockerTerminal),
|
() => import("./docker-terminal").then((e) => e.DockerTerminal),
|
||||||
{
|
{
|
||||||
ssr: false,
|
ssr: false,
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
containerId: string;
|
containerId: string;
|
||||||
serverId?: string;
|
serverId?: string;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DockerTerminalModal = ({
|
export const DockerTerminalModal = ({
|
||||||
children,
|
children,
|
||||||
containerId,
|
containerId,
|
||||||
serverId,
|
serverId,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
return (
|
const [mainDialogOpen, setMainDialogOpen] = useState(false);
|
||||||
<Dialog>
|
const [confirmDialogOpen, setConfirmDialogOpen] = useState(false);
|
||||||
<DialogTrigger asChild>
|
|
||||||
<DropdownMenuItem
|
|
||||||
className="w-full cursor-pointer space-x-3"
|
|
||||||
onSelect={(e) => e.preventDefault()}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</DropdownMenuItem>
|
|
||||||
</DialogTrigger>
|
|
||||||
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-7xl">
|
|
||||||
<DialogHeader>
|
|
||||||
<DialogTitle>Docker Terminal</DialogTitle>
|
|
||||||
<DialogDescription>
|
|
||||||
Easy way to access to docker container
|
|
||||||
</DialogDescription>
|
|
||||||
</DialogHeader>
|
|
||||||
|
|
||||||
<Terminal
|
const handleMainDialogOpenChange = (open: boolean) => {
|
||||||
id="terminal"
|
if (!open) {
|
||||||
containerId={containerId}
|
setConfirmDialogOpen(true);
|
||||||
serverId={serverId || ""}
|
} else {
|
||||||
/>
|
setMainDialogOpen(true);
|
||||||
</DialogContent>
|
}
|
||||||
</Dialog>
|
};
|
||||||
);
|
|
||||||
|
const handleConfirm = () => {
|
||||||
|
setConfirmDialogOpen(false);
|
||||||
|
setMainDialogOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
setConfirmDialogOpen(false);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Dialog open={mainDialogOpen} onOpenChange={handleMainDialogOpenChange}>
|
||||||
|
<DialogTrigger asChild>
|
||||||
|
<DropdownMenuItem
|
||||||
|
className="w-full cursor-pointer space-x-3"
|
||||||
|
onSelect={(e) => e.preventDefault()}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="max-h-screen overflow-y-auto sm:max-w-7xl">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Docker Terminal</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
Easy way to access to docker container
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
|
||||||
|
<Terminal
|
||||||
|
id="terminal"
|
||||||
|
containerId={containerId}
|
||||||
|
serverId={serverId || ""}
|
||||||
|
/>
|
||||||
|
<Dialog open={confirmDialogOpen} onOpenChange={setConfirmDialogOpen}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Are you sure you want to close the terminal?</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
By clicking the confirm button, the terminal will be closed.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button variant="outline" onClick={handleCancel}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleConfirm}>Confirm</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -38,7 +38,20 @@ const appearanceFormSchema = z.object({
|
|||||||
required_error: "Please select a theme.",
|
required_error: "Please select a theme.",
|
||||||
}),
|
}),
|
||||||
language: z.enum(
|
language: z.enum(
|
||||||
["en", "pl", "ru", "fr", "de", "tr", "kz", "zh-Hant", "zh-Hans", "fa", "ko"],
|
[
|
||||||
|
"en",
|
||||||
|
"pl",
|
||||||
|
"ru",
|
||||||
|
"fr",
|
||||||
|
"de",
|
||||||
|
"tr",
|
||||||
|
"zh-Hant",
|
||||||
|
"kz",
|
||||||
|
"zh-Hans",
|
||||||
|
"fa",
|
||||||
|
"ko",
|
||||||
|
"pt-br",
|
||||||
|
],
|
||||||
{
|
{
|
||||||
required_error: "Please select a language.",
|
required_error: "Please select a language.",
|
||||||
},
|
},
|
||||||
@@ -185,8 +198,10 @@ export function AppearanceForm() {
|
|||||||
{ label: "简体中文", value: "zh-Hans" },
|
{ label: "简体中文", value: "zh-Hans" },
|
||||||
{ label: "Türkçe", value: "tr" },
|
{ label: "Türkçe", value: "tr" },
|
||||||
{ label: "Қазақ", value: "tr" },
|
{ label: "Қазақ", value: "tr" },
|
||||||
|
{ label: "Kazakh", value: "kz" },
|
||||||
{ label: "Persian", value: "fa" },
|
{ label: "Persian", value: "fa" },
|
||||||
{ label: "한국어", value: "ko" },
|
{ label: "한국어", value: "ko" },
|
||||||
|
{ label: "Português", value: "pt-br" },
|
||||||
].map((preset) => (
|
].map((preset) => (
|
||||||
<SelectItem key={preset.label} value={preset.value}>
|
<SelectItem key={preset.label} value={preset.value}>
|
||||||
{preset.label}
|
{preset.label}
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
|
import { Button } from "@/components/ui/button";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogDescription,
|
DialogDescription,
|
||||||
DialogHeader,
|
DialogFooter,
|
||||||
DialogTitle,
|
DialogHeader,
|
||||||
DialogTrigger,
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
SelectGroup,
|
SelectGroup,
|
||||||
SelectItem,
|
SelectItem,
|
||||||
SelectLabel,
|
SelectLabel,
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/ui/select";
|
||||||
import { api } from "@/utils/api";
|
import { api } from "@/utils/api";
|
||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
@@ -23,80 +25,118 @@ import type React from "react";
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
|
||||||
const Terminal = dynamic(
|
const Terminal = dynamic(
|
||||||
() =>
|
() =>
|
||||||
import("@/components/dashboard/docker/terminal/docker-terminal").then(
|
import("@/components/dashboard/docker/terminal/docker-terminal").then(
|
||||||
(e) => e.DockerTerminal,
|
(e) => e.DockerTerminal
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
ssr: false,
|
ssr: false,
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
appName: string;
|
appName: string;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
serverId?: string;
|
serverId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DockerTerminalModal = ({ children, appName, serverId }: Props) => {
|
export const DockerTerminalModal = ({ children, appName, serverId }: Props) => {
|
||||||
const { data, isLoading } = api.docker.getContainersByAppNameMatch.useQuery(
|
const { data, isLoading } = api.docker.getContainersByAppNameMatch.useQuery(
|
||||||
{
|
{
|
||||||
appName,
|
appName,
|
||||||
serverId,
|
serverId,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: !!appName,
|
enabled: !!appName,
|
||||||
},
|
}
|
||||||
);
|
);
|
||||||
const [containerId, setContainerId] = useState<string | undefined>();
|
const [containerId, setContainerId] = useState<string | undefined>();
|
||||||
|
const [mainDialogOpen, setMainDialogOpen] = useState(false);
|
||||||
|
const [confirmDialogOpen, setConfirmDialogOpen] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
const handleMainDialogOpenChange = (open: boolean) => {
|
||||||
if (data && data?.length > 0) {
|
if (!open) {
|
||||||
setContainerId(data[0]?.containerId);
|
setConfirmDialogOpen(true);
|
||||||
}
|
} else {
|
||||||
}, [data]);
|
setMainDialogOpen(true);
|
||||||
return (
|
}
|
||||||
<Dialog>
|
};
|
||||||
<DialogTrigger asChild>{children}</DialogTrigger>
|
|
||||||
<DialogContent className="max-h-[85vh] overflow-y-auto sm:max-w-7xl">
|
const handleConfirm = () => {
|
||||||
<DialogHeader>
|
setConfirmDialogOpen(false);
|
||||||
<DialogTitle>Docker Terminal</DialogTitle>
|
setMainDialogOpen(false);
|
||||||
<DialogDescription>
|
};
|
||||||
Easy way to access to docker container
|
|
||||||
</DialogDescription>
|
const handleCancel = () => {
|
||||||
</DialogHeader>
|
setConfirmDialogOpen(false);
|
||||||
<Label>Select a container to view logs</Label>
|
};
|
||||||
<Select onValueChange={setContainerId} value={containerId}>
|
|
||||||
<SelectTrigger>
|
useEffect(() => {
|
||||||
{isLoading ? (
|
if (data && data?.length > 0) {
|
||||||
<div className="flex flex-row gap-2 items-center justify-center text-sm text-muted-foreground">
|
setContainerId(data[0]?.containerId);
|
||||||
<span>Loading...</span>
|
}
|
||||||
<Loader2 className="animate-spin size-4" />
|
}, [data]);
|
||||||
</div>
|
|
||||||
) : (
|
return (
|
||||||
<SelectValue placeholder="Select a container" />
|
<Dialog open={mainDialogOpen} onOpenChange={handleMainDialogOpenChange}>
|
||||||
)}
|
<DialogTrigger asChild>{children}</DialogTrigger>
|
||||||
</SelectTrigger>
|
<DialogContent className="max-h-[85vh] overflow-y-auto sm:max-w-7xl">
|
||||||
<SelectContent>
|
<DialogHeader>
|
||||||
<SelectGroup>
|
<DialogTitle>Docker Terminal</DialogTitle>
|
||||||
{data?.map((container) => (
|
<DialogDescription>
|
||||||
<SelectItem
|
Easy way to access to docker container
|
||||||
key={container.containerId}
|
</DialogDescription>
|
||||||
value={container.containerId}
|
</DialogHeader>
|
||||||
>
|
<Label>Select a container to view logs</Label>
|
||||||
{container.name} ({container.containerId}) {container.state}
|
<Select onValueChange={setContainerId} value={containerId}>
|
||||||
</SelectItem>
|
<SelectTrigger>
|
||||||
))}
|
{isLoading ? (
|
||||||
<SelectLabel>Containers ({data?.length})</SelectLabel>
|
<div className="flex flex-row gap-2 items-center justify-center text-sm text-muted-foreground">
|
||||||
</SelectGroup>
|
<span>Loading...</span>
|
||||||
</SelectContent>
|
<Loader2 className="animate-spin size-4" />
|
||||||
</Select>
|
</div>
|
||||||
<Terminal
|
) : (
|
||||||
serverId={serverId || ""}
|
<SelectValue placeholder="Select a container" />
|
||||||
id="terminal"
|
)}
|
||||||
containerId={containerId || "select-a-container"}
|
</SelectTrigger>
|
||||||
/>
|
<SelectContent>
|
||||||
</DialogContent>
|
<SelectGroup>
|
||||||
</Dialog>
|
{data?.map((container) => (
|
||||||
);
|
<SelectItem
|
||||||
|
key={container.containerId}
|
||||||
|
value={container.containerId}
|
||||||
|
>
|
||||||
|
{container.name} ({container.containerId}) {container.state}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
<SelectLabel>Containers ({data?.length})</SelectLabel>
|
||||||
|
</SelectGroup>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
<Terminal
|
||||||
|
serverId={serverId || ""}
|
||||||
|
id="terminal"
|
||||||
|
containerId={containerId || "select-a-container"}
|
||||||
|
/>
|
||||||
|
<Dialog open={confirmDialogOpen} onOpenChange={setConfirmDialogOpen}>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>
|
||||||
|
Are you sure you want to close the terminal?
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogDescription>
|
||||||
|
By clicking the confirm button, the terminal will be closed.
|
||||||
|
</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogFooter>
|
||||||
|
<Button variant="outline" onClick={handleCancel}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button onClick={handleConfirm}>Confirm</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
/** @type {import('next-i18next').UserConfig} */
|
/** @type {import('next-i18next').UserConfig} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
fallbackLng: "en",
|
||||||
|
keySeparator: false,
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultLocale: "en",
|
defaultLocale: "en",
|
||||||
locales: [
|
locales: [
|
||||||
@@ -14,9 +16,8 @@ module.exports = {
|
|||||||
"zh-Hans",
|
"zh-Hans",
|
||||||
"fa",
|
"fa",
|
||||||
"ko",
|
"ko",
|
||||||
|
"pt-br",
|
||||||
],
|
],
|
||||||
localeDetection: false,
|
localeDetection: false,
|
||||||
},
|
},
|
||||||
fallbackLng: "en",
|
|
||||||
keySeparator: false,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -83,6 +83,7 @@ export default api.withTRPC(
|
|||||||
"zh-Hans",
|
"zh-Hans",
|
||||||
"fa",
|
"fa",
|
||||||
"ko",
|
"ko",
|
||||||
|
"pt-br",
|
||||||
],
|
],
|
||||||
localeDetection: false,
|
localeDetection: false,
|
||||||
},
|
},
|
||||||
|
|||||||
1
apps/dokploy/public/locales/pt-br/common.json
Normal file
1
apps/dokploy/public/locales/pt-br/common.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
44
apps/dokploy/public/locales/pt-br/settings.json
Normal file
44
apps/dokploy/public/locales/pt-br/settings.json
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"settings.common.save": "Salvar",
|
||||||
|
"settings.server.domain.title": "Domínio do Servidor",
|
||||||
|
"settings.server.domain.description": "Configure o domínio do servidor",
|
||||||
|
"settings.server.domain.form.domain": "Domínio",
|
||||||
|
"settings.server.domain.form.letsEncryptEmail": "Email do Let's Encrypt",
|
||||||
|
"settings.server.domain.form.certificate.label": "Certificado",
|
||||||
|
"settings.server.domain.form.certificate.placeholder": "Selecione um Certificado",
|
||||||
|
"settings.server.domain.form.certificateOptions.none": "Nenhum",
|
||||||
|
"settings.server.domain.form.certificateOptions.letsencrypt": "Let's Encrypt (Padrão)",
|
||||||
|
|
||||||
|
"settings.server.webServer.title": "Servidor web",
|
||||||
|
"settings.server.webServer.description": "Limpar e recarregar servidor web.",
|
||||||
|
"settings.server.webServer.actions": "Ações",
|
||||||
|
"settings.server.webServer.reload": "Recarregar",
|
||||||
|
"settings.server.webServer.watchLogs": "Ver logs",
|
||||||
|
"settings.server.webServer.updateServerIp": "Atualizar IP do Servidor",
|
||||||
|
"settings.server.webServer.server.label": "Servidor",
|
||||||
|
"settings.server.webServer.traefik.label": "Traefik",
|
||||||
|
"settings.server.webServer.traefik.modifyEnv": "Alterar Env",
|
||||||
|
"settings.server.webServer.storage.label": "Armazenamento",
|
||||||
|
"settings.server.webServer.storage.cleanUnusedImages": "Limpar imagens não utilizadas",
|
||||||
|
"settings.server.webServer.storage.cleanUnusedVolumes": "Limpar volumes não utilizados",
|
||||||
|
"settings.server.webServer.storage.cleanStoppedContainers": "Limpar containers parados",
|
||||||
|
"settings.server.webServer.storage.cleanDockerBuilder": "Limpar Docker Builder & System",
|
||||||
|
"settings.server.webServer.storage.cleanMonitoring": "Limpar Monitoramento",
|
||||||
|
"settings.server.webServer.storage.cleanAll": "Limpar Tudo",
|
||||||
|
|
||||||
|
"settings.profile.title": "Conta",
|
||||||
|
"settings.profile.description": "Altere os detalhes do seu perfil aqui.",
|
||||||
|
"settings.profile.email": "Email",
|
||||||
|
"settings.profile.password": "Senha",
|
||||||
|
"settings.profile.avatar": "Avatar",
|
||||||
|
|
||||||
|
"settings.appearance.title": "Aparência",
|
||||||
|
"settings.appearance.description": "Personalize o tema do seu dashboard.",
|
||||||
|
"settings.appearance.theme": "Tema",
|
||||||
|
"settings.appearance.themeDescription": "Selecione um tema para o dashboard",
|
||||||
|
"settings.appearance.themes.light": "Claro",
|
||||||
|
"settings.appearance.themes.dark": "Escuro",
|
||||||
|
"settings.appearance.themes.system": "Automático",
|
||||||
|
"settings.appearance.language": "Linguagem",
|
||||||
|
"settings.appearance.languageDescription": "Selecione o idioma do dashboard"
|
||||||
|
}
|
||||||
2
apps/dokploy/public/templates/triggerdotdev.svg
Normal file
2
apps/dokploy/public/templates/triggerdotdev.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 7.2 KiB |
File diff suppressed because it is too large
Load Diff
107
apps/dokploy/templates/triggerdotdev/docker-compose.yml
Normal file
107
apps/dokploy/templates/triggerdotdev/docker-compose.yml
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
x-webapp-env: &webapp-env
|
||||||
|
LOGIN_ORIGIN: &trigger-url ${TRIGGER_PROTOCOL:-http}://${TRIGGER_DOMAIN:-localhost:3040}
|
||||||
|
APP_ORIGIN: *trigger-url
|
||||||
|
DEV_OTEL_EXPORTER_OTLP_ENDPOINT: &trigger-otel ${TRIGGER_PROTOCOL:-http}://${TRIGGER_DOMAIN:-localhost:3040}/otel
|
||||||
|
ELECTRIC_ORIGIN: http://electric:3000
|
||||||
|
|
||||||
|
x-worker-env: &worker-env
|
||||||
|
PLATFORM_HOST: webapp
|
||||||
|
PLATFORM_WS_PORT: 3030
|
||||||
|
SECURE_CONNECTION: "false"
|
||||||
|
OTEL_EXPORTER_OTLP_ENDPOINT: *trigger-otel
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
postgres-data:
|
||||||
|
redis-data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
webapp:
|
||||||
|
|
||||||
|
services:
|
||||||
|
webapp:
|
||||||
|
image: ghcr.io/triggerdotdev/trigger.dev:${TRIGGER_IMAGE_TAG:-v3}
|
||||||
|
restart: ${RESTART_POLICY:-unless-stopped}
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
<<: *webapp-env
|
||||||
|
ports:
|
||||||
|
- 3000
|
||||||
|
depends_on:
|
||||||
|
- postgres
|
||||||
|
- redis
|
||||||
|
networks:
|
||||||
|
- webapp
|
||||||
|
|
||||||
|
postgres:
|
||||||
|
image: postgres:${POSTGRES_IMAGE_TAG:-16}
|
||||||
|
restart: ${RESTART_POLICY:-unless-stopped}
|
||||||
|
volumes:
|
||||||
|
- postgres-data:/var/lib/postgresql/data/
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
networks:
|
||||||
|
- webapp
|
||||||
|
ports:
|
||||||
|
- 5432
|
||||||
|
command:
|
||||||
|
- -c
|
||||||
|
- wal_level=logical
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis:${REDIS_IMAGE_TAG:-7}
|
||||||
|
restart: ${RESTART_POLICY:-unless-stopped}
|
||||||
|
volumes:
|
||||||
|
- redis-data:/data
|
||||||
|
networks:
|
||||||
|
- webapp
|
||||||
|
ports:
|
||||||
|
- 6379
|
||||||
|
|
||||||
|
docker-provider:
|
||||||
|
image: ghcr.io/triggerdotdev/provider/docker:${TRIGGER_IMAGE_TAG:-v3}
|
||||||
|
restart: ${RESTART_POLICY:-unless-stopped}
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
user: root
|
||||||
|
networks:
|
||||||
|
- webapp
|
||||||
|
depends_on:
|
||||||
|
- webapp
|
||||||
|
ports:
|
||||||
|
- 9020
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
<<: *worker-env
|
||||||
|
PLATFORM_SECRET: $PROVIDER_SECRET
|
||||||
|
|
||||||
|
coordinator:
|
||||||
|
image: ghcr.io/triggerdotdev/coordinator:${TRIGGER_IMAGE_TAG:-v3}
|
||||||
|
restart: ${RESTART_POLICY:-unless-stopped}
|
||||||
|
volumes:
|
||||||
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
|
user: root
|
||||||
|
networks:
|
||||||
|
- webapp
|
||||||
|
depends_on:
|
||||||
|
- webapp
|
||||||
|
ports:
|
||||||
|
- 9020
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
<<: *worker-env
|
||||||
|
PLATFORM_SECRET: $COORDINATOR_SECRET
|
||||||
|
|
||||||
|
electric:
|
||||||
|
image: electricsql/electric:${ELECTRIC_IMAGE_TAG:-latest}
|
||||||
|
restart: ${RESTART_POLICY:-unless-stopped}
|
||||||
|
environment:
|
||||||
|
DATABASE_URL: ${DATABASE_URL}?sslmode=disable
|
||||||
|
networks:
|
||||||
|
- webapp
|
||||||
|
depends_on:
|
||||||
|
- postgres
|
||||||
|
ports:
|
||||||
|
- 3000
|
||||||
93
apps/dokploy/templates/triggerdotdev/index.ts
Normal file
93
apps/dokploy/templates/triggerdotdev/index.ts
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
import { Secrets } from "@/components/ui/secrets";
|
||||||
|
import {
|
||||||
|
type DomainSchema,
|
||||||
|
type Schema,
|
||||||
|
type Template,
|
||||||
|
generateBase64,
|
||||||
|
generateRandomDomain,
|
||||||
|
} from "../utils";
|
||||||
|
|
||||||
|
export function generate(schema: Schema): Template {
|
||||||
|
const triggerDomain = generateRandomDomain(schema);
|
||||||
|
|
||||||
|
const magicLinkSecret = generateBase64(16);
|
||||||
|
const sessionSecret = generateBase64(16);
|
||||||
|
const encryptionKey = generateBase64(32);
|
||||||
|
const providerSecret = generateBase64(32);
|
||||||
|
const coordinatorSecret = generateBase64(32);
|
||||||
|
|
||||||
|
const dbPassword = generateBase64(24);
|
||||||
|
const dbUser = "triggeruser";
|
||||||
|
const dbName = "triggerdb";
|
||||||
|
|
||||||
|
const domains: DomainSchema[] = [
|
||||||
|
{
|
||||||
|
host: triggerDomain,
|
||||||
|
port: 3000,
|
||||||
|
serviceName: "webapp",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const envs = [
|
||||||
|
`NODE_ENV=production`,
|
||||||
|
`RUNTIME_PLATFORM=docker-compose`,
|
||||||
|
`V3_ENABLED=true`,
|
||||||
|
|
||||||
|
`# Domain configuration`,
|
||||||
|
`TRIGGER_DOMAIN=${triggerDomain}`,
|
||||||
|
`TRIGGER_PROTOCOL=http`,
|
||||||
|
|
||||||
|
`# Database configuration with secure credentials`,
|
||||||
|
`POSTGRES_USER=${dbUser}`,
|
||||||
|
`POSTGRES_PASSWORD=${dbPassword}`,
|
||||||
|
`POSTGRES_DB=${dbName}`,
|
||||||
|
`DATABASE_URL=postgresql://${dbUser}:${dbPassword}@postgres:5432/${dbName}`,
|
||||||
|
|
||||||
|
`# Secrets`,
|
||||||
|
`MAGIC_LINK_SECRET=${magicLinkSecret}`,
|
||||||
|
`SESSION_SECRET=${sessionSecret}`,
|
||||||
|
`ENCRYPTION_KEY=${encryptionKey}`,
|
||||||
|
`PROVIDER_SECRET=${providerSecret}`,
|
||||||
|
`COORDINATOR_SECRET=${coordinatorSecret}`,
|
||||||
|
|
||||||
|
`# TRIGGER_TELEMETRY_DISABLED=1`,
|
||||||
|
`INTERNAL_OTEL_TRACE_DISABLED=1`,
|
||||||
|
`INTERNAL_OTEL_TRACE_LOGGING_ENABLED=0`,
|
||||||
|
|
||||||
|
`DEFAULT_ORG_EXECUTION_CONCURRENCY_LIMIT=300`,
|
||||||
|
`DEFAULT_ENV_EXECUTION_CONCURRENCY_LIMIT=100`,
|
||||||
|
|
||||||
|
`DIRECT_URL=\${DATABASE_URL}`,
|
||||||
|
`REDIS_HOST=redis`,
|
||||||
|
`REDIS_PORT=6379`,
|
||||||
|
`REDIS_TLS_DISABLED=true`,
|
||||||
|
|
||||||
|
`# If this is set, emails that are not specified won't be able to log in`,
|
||||||
|
`# WHITELISTED_EMAILS="authorized@yahoo.com|authorized@gmail.com"`,
|
||||||
|
`# Accounts with these emails will become admins when signing up and get access to the admin panel`,
|
||||||
|
`# ADMIN_EMAILS="admin@example.com|another-admin@example.com"`,
|
||||||
|
|
||||||
|
`# If this is set, your users will be able to log in via GitHub`,
|
||||||
|
`# AUTH_GITHUB_CLIENT_ID=`,
|
||||||
|
`# AUTH_GITHUB_CLIENT_SECRET=`,
|
||||||
|
|
||||||
|
`# E-mail settings`,
|
||||||
|
`# Ensure the FROM_EMAIL matches what you setup with Resend.com`,
|
||||||
|
`# If these are not set, emails will be printed to the console`,
|
||||||
|
`# FROM_EMAIL=`,
|
||||||
|
`# REPLY_TO_EMAIL=`,
|
||||||
|
`# RESEND_API_KEY=`,
|
||||||
|
|
||||||
|
`# Worker settings`,
|
||||||
|
`HTTP_SERVER_PORT=9020`,
|
||||||
|
`COORDINATOR_HOST=127.0.0.1`,
|
||||||
|
`COORDINATOR_PORT=\${HTTP_SERVER_PORT}`,
|
||||||
|
`# REGISTRY_HOST=\${DEPLOY_REGISTRY_HOST}`,
|
||||||
|
`# REGISTRY_NAMESPACE=\${DEPLOY_REGISTRY_NAMESPACE}`,
|
||||||
|
];
|
||||||
|
|
||||||
|
return {
|
||||||
|
envs,
|
||||||
|
domains,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ const SUPPORTED_LOCALES = [
|
|||||||
"zh-Hans",
|
"zh-Hans",
|
||||||
"fa",
|
"fa",
|
||||||
"ko",
|
"ko",
|
||||||
|
"pt-br",
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
type Locale = (typeof SUPPORTED_LOCALES)[number];
|
type Locale = (typeof SUPPORTED_LOCALES)[number];
|
||||||
|
|||||||
Reference in New Issue
Block a user