mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
Merge pull request #363 from Dokploy/fix/domains-schema-templates
refactor(templates): use domains tab instead of envs
This commit is contained in:
@@ -166,20 +166,26 @@ import {
|
|||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
type Template,
|
type Template,
|
||||||
type Schema,
|
type Schema,
|
||||||
|
type DomainSchema,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
// do your stuff here, like create a new domain, generate random passwords, mounts.
|
// do your stuff here, like create a new domain, generate random passwords, mounts.
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainServiceHash = generateHash(schema.projectName);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const secretBase = generateBase64(64);
|
const secretBase = generateBase64(64);
|
||||||
const toptKeyBase = generateBase64(32);
|
const toptKeyBase = generateBase64(32);
|
||||||
|
|
||||||
|
const domains: DomainSchema[] = [
|
||||||
|
{
|
||||||
|
host: mainDomain,
|
||||||
|
port: 8000,
|
||||||
|
serviceName: "plausible",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const envs = [
|
const envs = [
|
||||||
// If you want to show a domain in the UI, please add the prefix _HOST at the end of the variable name.
|
`BASE_URL=http://${mainDomain}`,
|
||||||
`PLAUSIBLE_HOST=${randomDomain}`,
|
|
||||||
"PLAUSIBLE_PORT=8000",
|
|
||||||
`BASE_URL=http://${randomDomain}`,
|
|
||||||
`SECRET_KEY_BASE=${secretBase}`,
|
`SECRET_KEY_BASE=${secretBase}`,
|
||||||
`TOTP_VAULT_KEY=${toptKeyBase}`,
|
`TOTP_VAULT_KEY=${toptKeyBase}`,
|
||||||
`HASH=${mainServiceHash}`,
|
`HASH=${mainServiceHash}`,
|
||||||
@@ -195,6 +201,7 @@ export function generate(schema: Schema): Template {
|
|||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
mounts,
|
mounts,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
26
LICENSE.MD
Normal file
26
LICENSE.MD
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# License
|
||||||
|
|
||||||
|
## Core License (Apache License 2.0)
|
||||||
|
|
||||||
|
Copyright 2024 Mauricio Siu.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
|
## Additional Terms for Specific Features
|
||||||
|
|
||||||
|
The following additional terms apply to the multi-node support and Docker Compose file support features of Dokploy. In the event of a conflict, these provisions shall take precedence over those in the Apache License:
|
||||||
|
|
||||||
|
- **Self-Hosted Version Free**: All features of Dokploy, including multi-node support and Docker Compose file support, will always be free to use in the self-hosted version.
|
||||||
|
- **Restriction on Resale**: The multi-node support and Docker Compose file support features cannot be sold or offered as a service by any party other than the copyright holder without prior written consent.
|
||||||
|
- **Modification Distribution**: Any modifications to the multi-node support and Docker Compose file support features must be distributed freely and cannot be sold or offered as a service.
|
||||||
|
|
||||||
|
For further inquiries or permissions, please contact us directly.
|
||||||
@@ -41,7 +41,7 @@ import {
|
|||||||
updateCompose,
|
updateCompose,
|
||||||
} from "../services/compose";
|
} from "../services/compose";
|
||||||
import { removeDeploymentsByComposeId } from "../services/deployment";
|
import { removeDeploymentsByComposeId } from "../services/deployment";
|
||||||
import { findDomainsByComposeId } from "../services/domain";
|
import { createDomain, findDomainsByComposeId } from "../services/domain";
|
||||||
import { createMount } from "../services/mount";
|
import { createMount } from "../services/mount";
|
||||||
import { findProjectById } from "../services/project";
|
import { findProjectById } from "../services/project";
|
||||||
import { addNewService, checkServiceAccess } from "../services/user";
|
import { addNewService, checkServiceAccess } from "../services/user";
|
||||||
@@ -236,7 +236,7 @@ export const composeRouter = createTRPCRouter({
|
|||||||
const project = await findProjectById(input.projectId);
|
const project = await findProjectById(input.projectId);
|
||||||
|
|
||||||
const projectName = slugify(`${project.name} ${input.id}`);
|
const projectName = slugify(`${project.name} ${input.id}`);
|
||||||
const { envs, mounts } = generate({
|
const { envs, mounts, domains } = generate({
|
||||||
serverIp: admin.serverIp,
|
serverIp: admin.serverIp,
|
||||||
projectName: projectName,
|
projectName: projectName,
|
||||||
});
|
});
|
||||||
@@ -244,7 +244,7 @@ export const composeRouter = createTRPCRouter({
|
|||||||
const compose = await createComposeByTemplate({
|
const compose = await createComposeByTemplate({
|
||||||
...input,
|
...input,
|
||||||
composeFile: composeFile,
|
composeFile: composeFile,
|
||||||
env: envs.join("\n"),
|
env: envs?.join("\n"),
|
||||||
name: input.id,
|
name: input.id,
|
||||||
sourceType: "raw",
|
sourceType: "raw",
|
||||||
appName: `${projectName}-${generatePassword(6)}`,
|
appName: `${projectName}-${generatePassword(6)}`,
|
||||||
@@ -267,6 +267,17 @@ export const composeRouter = createTRPCRouter({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (domains && domains?.length > 0) {
|
||||||
|
for (const domain of domains) {
|
||||||
|
await createDomain({
|
||||||
|
...domain,
|
||||||
|
domainType: "compose",
|
||||||
|
certificateType: "none",
|
||||||
|
composeId: compose.composeId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
|||||||
@@ -2,17 +2,5 @@ version: "3.8"
|
|||||||
services:
|
services:
|
||||||
appsmith:
|
appsmith:
|
||||||
image: index.docker.io/appsmith/appsmith-ee:v1.29
|
image: index.docker.io/appsmith/appsmith-ee:v1.29
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
ports:
|
|
||||||
- ${APP_SMITH_PORT}
|
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.${HASH}.rule=Host(`${APP_SMITH_HOST}`)"
|
|
||||||
- "traefik.http.services.${HASH}.loadbalancer.server.port=${APP_SMITH_PORT}"
|
|
||||||
volumes:
|
volumes:
|
||||||
- ../files/stacks:/appsmith-stacks
|
- ../files/stacks:/appsmith-stacks
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
generateHash,
|
||||||
@@ -7,14 +8,16 @@ import {
|
|||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainServiceHash = generateHash(schema.projectName);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
|
||||||
const envs = [
|
const domains: DomainSchema[] = [
|
||||||
`APP_SMITH_HOST=${randomDomain}`,
|
{
|
||||||
"APP_SMITH_PORT=80",
|
host: generateRandomDomain(schema),
|
||||||
`HASH=${mainServiceHash}`,
|
port: 80,
|
||||||
|
serviceName: "appsmith",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,21 +2,9 @@ version: "3.8"
|
|||||||
services:
|
services:
|
||||||
baserow:
|
baserow:
|
||||||
image: baserow/baserow:1.25.2
|
image: baserow/baserow:1.25.2
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
environment:
|
environment:
|
||||||
BASEROW_PUBLIC_URL: "http://${BASEROW_HOST}"
|
BASEROW_PUBLIC_URL: "http://${BASEROW_HOST}"
|
||||||
ports:
|
|
||||||
- ${BASEROW_PORT}
|
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.${HASH}.rule=Host(`${BASEROW_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}.loadbalancer.server.port=${BASEROW_PORT}
|
|
||||||
volumes:
|
volumes:
|
||||||
- baserow_data:/baserow/data
|
- baserow_data:/baserow/data
|
||||||
volumes:
|
volumes:
|
||||||
baserow_data:
|
baserow_data:
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
@@ -1,20 +1,24 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainHost = generateRandomDomain(schema);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
|
||||||
const envs = [
|
const domains: DomainSchema[] = [
|
||||||
`BASEROW_HOST=${randomDomain}`,
|
{
|
||||||
"BASEROW_PORT=80",
|
host: mainHost,
|
||||||
`HASH=${mainServiceHash}`,
|
port: 80,
|
||||||
|
serviceName: "baserow",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
const envs = [`BASEROW_HOST=${mainHost}`];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,16 +21,6 @@ services:
|
|||||||
- DATABASE_URL=postgres://postgres:password@postgres:5432/db
|
- DATABASE_URL=postgres://postgres:password@postgres:5432/db
|
||||||
- NEXT_PUBLIC_WEBAPP_URL=http://${CALCOM_HOST}
|
- NEXT_PUBLIC_WEBAPP_URL=http://${CALCOM_HOST}
|
||||||
- NEXTAUTH_URL=http://${CALCOM_HOST}/api/auth
|
- NEXTAUTH_URL=http://${CALCOM_HOST}/api/auth
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.${HASH}.rule=Host(`${CALCOM_HOST}`)"
|
|
||||||
- "traefik.http.services.${HASH}.loadbalancer.server.port=${CALCOM_PORT}"
|
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
calcom-data:
|
calcom-data:
|
||||||
|
|||||||
@@ -1,27 +1,32 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateBase64,
|
generateBase64,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
// https://cal.com/
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
|
||||||
const calcomEncryptionKey = generateBase64(32);
|
const calcomEncryptionKey = generateBase64(32);
|
||||||
const nextAuthSecret = generateBase64(32);
|
const nextAuthSecret = generateBase64(32);
|
||||||
|
|
||||||
|
const domains: DomainSchema[] = [
|
||||||
|
{
|
||||||
|
host: mainDomain,
|
||||||
|
port: 3000,
|
||||||
|
serviceName: "calcom",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const envs = [
|
const envs = [
|
||||||
`CALCOM_HOST=${randomDomain}`,
|
`CALCOM_HOST=${mainDomain}`,
|
||||||
"CALCOM_PORT=3000",
|
|
||||||
`HASH=${mainServiceHash}`,
|
|
||||||
`NEXTAUTH_SECRET=${nextAuthSecret}`,
|
`NEXTAUTH_SECRET=${nextAuthSecret}`,
|
||||||
`CALENDSO_ENCRYPTION_KEY=${calcomEncryptionKey}`,
|
`CALENDSO_ENCRYPTION_KEY=${calcomEncryptionKey}`,
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ services:
|
|||||||
|
|
||||||
directus:
|
directus:
|
||||||
image: directus/directus:10.12.1
|
image: directus/directus:10.12.1
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
ports:
|
ports:
|
||||||
- 8055
|
- 8055
|
||||||
volumes:
|
volumes:
|
||||||
@@ -28,10 +26,6 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- cache
|
- cache
|
||||||
- database
|
- database
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.${HASH}.rule=Host(`${DIRECTUS_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}.loadbalancer.server.port=${DIRECTUS_PORT}
|
|
||||||
environment:
|
environment:
|
||||||
SECRET: "replace-with-secure-random-value"
|
SECRET: "replace-with-secure-random-value"
|
||||||
|
|
||||||
@@ -49,8 +43,5 @@ services:
|
|||||||
|
|
||||||
ADMIN_EMAIL: "admin@example.com"
|
ADMIN_EMAIL: "admin@example.com"
|
||||||
ADMIN_PASSWORD: "d1r3ctu5"
|
ADMIN_PASSWORD: "d1r3ctu5"
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
volumes:
|
volumes:
|
||||||
directus:
|
directus:
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const domains: DomainSchema[] = [
|
||||||
const randomDomain = generateRandomDomain(schema);
|
{
|
||||||
const envs = [
|
host: generateRandomDomain(schema),
|
||||||
`DIRECTUS_HOST=${randomDomain}`,
|
port: 8055,
|
||||||
"DIRECTUS_PORT=8055",
|
serviceName: "directus",
|
||||||
`HASH=${mainServiceHash}`,
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ services:
|
|||||||
|
|
||||||
documenso:
|
documenso:
|
||||||
image: documenso/documenso:1.5.6-rc.2
|
image: documenso/documenso:1.5.6-rc.2
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
depends_on:
|
depends_on:
|
||||||
postgres:
|
postgres:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@@ -38,16 +36,8 @@ services:
|
|||||||
- NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH=/opt/documenso/cert.p12
|
- NEXT_PRIVATE_SIGNING_LOCAL_FILE_PATH=/opt/documenso/cert.p12
|
||||||
ports:
|
ports:
|
||||||
- ${DOCUMENSO_PORT}
|
- ${DOCUMENSO_PORT}
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.${HASH}.rule=Host(`${DOCUMENSO_HOST}`)"
|
|
||||||
- "traefik.http.services.${HASH}.loadbalancer.server.port=${DOCUMENSO_PORT}"
|
|
||||||
volumes:
|
volumes:
|
||||||
- /opt/documenso/cert.p12:/opt/documenso/cert.p12
|
- /opt/documenso/cert.p12:/opt/documenso/cert.p12
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
documenso-data:
|
documenso-data:
|
||||||
|
|||||||
@@ -1,24 +1,29 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateBase64,
|
generateBase64,
|
||||||
generateHash,
|
|
||||||
generatePassword,
|
generatePassword,
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
|
||||||
|
|
||||||
const nextAuthSecret = generateBase64(32);
|
const nextAuthSecret = generateBase64(32);
|
||||||
const documensoEncryptionKey = generatePassword(32);
|
const documensoEncryptionKey = generatePassword(32);
|
||||||
const documensoSecondaryEncryptionKey = generatePassword(64);
|
const documensoSecondaryEncryptionKey = generatePassword(64);
|
||||||
|
|
||||||
|
const domains: DomainSchema[] = [
|
||||||
|
{
|
||||||
|
host: mainDomain,
|
||||||
|
port: 3000,
|
||||||
|
serviceName: "documenso",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const envs = [
|
const envs = [
|
||||||
`DOCUMENSO_HOST=${randomDomain}`,
|
`DOCUMENSO_HOST=${mainDomain}`,
|
||||||
"DOCUMENSO_PORT=3000",
|
"DOCUMENSO_PORT=3000",
|
||||||
`HASH=${mainServiceHash}`,
|
|
||||||
`NEXTAUTH_SECRET=${nextAuthSecret}`,
|
`NEXTAUTH_SECRET=${nextAuthSecret}`,
|
||||||
`NEXT_PRIVATE_ENCRYPTION_KEY=${documensoEncryptionKey}`,
|
`NEXT_PRIVATE_ENCRYPTION_KEY=${documensoEncryptionKey}`,
|
||||||
`NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY=${documensoSecondaryEncryptionKey}`,
|
`NEXT_PRIVATE_ENCRYPTION_SECONDARY_KEY=${documensoSecondaryEncryptionKey}`,
|
||||||
@@ -26,5 +31,6 @@ export function generate(schema: Schema): Template {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,6 @@ services:
|
|||||||
doublezero:
|
doublezero:
|
||||||
restart: always
|
restart: always
|
||||||
image: liltechnomancer/double-zero:0.2.1
|
image: liltechnomancer/double-zero:0.2.1
|
||||||
ports:
|
|
||||||
- ${DOUBLEZERO_PORT}
|
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
volumes:
|
volumes:
|
||||||
- db-data:/var/lib/doublezero/data
|
- db-data:/var/lib/doublezero/data
|
||||||
environment:
|
environment:
|
||||||
@@ -17,15 +13,7 @@ services:
|
|||||||
SECRET_KEY_BASE: ${SECRET_KEY_BASE}
|
SECRET_KEY_BASE: ${SECRET_KEY_BASE}
|
||||||
PHX_HOST: ${DOUBLEZERO_HOST}
|
PHX_HOST: ${DOUBLEZERO_HOST}
|
||||||
DATABASE_PATH: ./00.db
|
DATABASE_PATH: ./00.db
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.${HASH}.rule=Host(`${DOUBLEZERO_HOST}`)"
|
|
||||||
- "traefik.http.services.${HASH}.loadbalancer.server.port=${DOUBLEZERO_PORT}"
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
db-data:
|
db-data:
|
||||||
driver: local
|
driver: local
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|||||||
@@ -1,20 +1,26 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateBase64,
|
generateBase64,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
|
||||||
const secretKeyBase = generateBase64(64);
|
const secretKeyBase = generateBase64(64);
|
||||||
|
|
||||||
|
const domains: DomainSchema[] = [
|
||||||
|
{
|
||||||
|
host: mainDomain,
|
||||||
|
port: 4000,
|
||||||
|
serviceName: "doublezero",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const envs = [
|
const envs = [
|
||||||
`DOUBLEZERO_HOST=${randomDomain}`,
|
`DOUBLEZERO_HOST=${mainDomain}`,
|
||||||
"DOUBLEZERO_PORT=4000",
|
"DOUBLEZERO_PORT=4000",
|
||||||
`HASH=${mainServiceHash}`,
|
|
||||||
`SECRET_KEY_BASE=${secretKeyBase}`,
|
`SECRET_KEY_BASE=${secretKeyBase}`,
|
||||||
"AWS_ACCESS_KEY_ID=your-aws-access-key",
|
"AWS_ACCESS_KEY_ID=your-aws-access-key",
|
||||||
"AWS_SECRET_ACCESS_KEY=your-aws-secret-key",
|
"AWS_SECRET_ACCESS_KEY=your-aws-secret-key",
|
||||||
@@ -25,5 +31,6 @@ export function generate(schema: Schema): Template {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,7 @@
|
|||||||
version: '3.8'
|
version: "3.8"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
excalidraw:
|
excalidraw:
|
||||||
networks:
|
networks:
|
||||||
- dokploy-network
|
- dokploy-network
|
||||||
image: excalidraw/excalidraw:latest
|
image: excalidraw/excalidraw:latest
|
||||||
ports:
|
|
||||||
- ${EXCALIDRAW_PORT}
|
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.${HASH}.rule=Host(`${EXCALIDRAW_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}.loadbalancer.server.port=${EXCALIDRAW_PORT}
|
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
generateHash,
|
||||||
@@ -6,15 +7,17 @@ import {
|
|||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
|
||||||
const envs = [
|
const domains: DomainSchema[] = [
|
||||||
`EXCALIDRAW_HOST=${randomDomain}`,
|
{
|
||||||
"EXCALIDRAW_PORT=80",
|
host: mainDomain,
|
||||||
`HASH=${mainServiceHash}`,
|
port: 80,
|
||||||
|
serviceName: "excalidraw",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
version: "3.8"
|
version: "3.8"
|
||||||
services:
|
services:
|
||||||
|
|
||||||
ghost:
|
ghost:
|
||||||
image: ghost:5-alpine
|
image: ghost:5-alpine
|
||||||
restart: always
|
restart: always
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
ports:
|
|
||||||
- ${GHOST_PORT}
|
|
||||||
environment:
|
environment:
|
||||||
database__client: mysql
|
database__client: mysql
|
||||||
database__connection__host: db
|
database__connection__host: db
|
||||||
@@ -15,10 +10,7 @@ services:
|
|||||||
database__connection__password: example
|
database__connection__password: example
|
||||||
database__connection__database: ghost
|
database__connection__database: ghost
|
||||||
url: http://${GHOST_HOST}
|
url: http://${GHOST_HOST}
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.${HASH}.rule=Host(`${GHOST_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}.loadbalancer.server.port=${GHOST_PORT}
|
|
||||||
volumes:
|
volumes:
|
||||||
- ghost:/var/lib/ghost/content
|
- ghost:/var/lib/ghost/content
|
||||||
|
|
||||||
@@ -35,7 +27,3 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
ghost:
|
ghost:
|
||||||
db:
|
db:
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
generateHash,
|
||||||
@@ -6,15 +7,19 @@ import {
|
|||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
|
||||||
const envs = [
|
const domains: DomainSchema[] = [
|
||||||
`GHOST_HOST=${randomDomain}`,
|
{
|
||||||
"GHOST_PORT=2368",
|
host: mainDomain,
|
||||||
`HASH=${mainServiceHash}`,
|
port: 2368,
|
||||||
|
serviceName: "ghost",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
const envs = [`GHOST_HOST=${mainDomain}`];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,14 @@
|
|||||||
x-environment:
|
x-environment: &default-environment
|
||||||
&default-environment
|
|
||||||
DATABASE_URL: postgres://postgres:postgres@postgres:5432/postgres
|
DATABASE_URL: postgres://postgres:postgres@postgres:5432/postgres
|
||||||
SECRET_KEY: ${SECRET_KEY}
|
SECRET_KEY: ${SECRET_KEY}
|
||||||
PORT: ${GLITCHTIP_PORT}
|
PORT: ${GLITCHTIP_PORT}
|
||||||
EMAIL_URL: consolemail://
|
EMAIL_URL: consolemail://
|
||||||
GLITCHTIP_DOMAIN: http://${GLITCHTIP_HOST}
|
GLITCHTIP_DOMAIN: http://${GLITCHTIP_HOST}
|
||||||
DEFAULT_FROM_EMAIL: email@glitchtip.com
|
DEFAULT_FROM_EMAIL: email@glitchtip.com
|
||||||
CELERY_WORKER_AUTOSCALE: "1,3"
|
CELERY_WORKER_AUTOSCALE: "1,3"
|
||||||
CELERY_WORKER_MAX_TASKS_PER_CHILD: "10000"
|
CELERY_WORKER_MAX_TASKS_PER_CHILD: "10000"
|
||||||
|
|
||||||
x-depends_on:
|
x-depends_on: &default-depends_on
|
||||||
&default-depends_on
|
|
||||||
- postgres
|
- postgres
|
||||||
- redis
|
- redis
|
||||||
|
|
||||||
@@ -18,7 +16,7 @@ services:
|
|||||||
postgres:
|
postgres:
|
||||||
image: postgres:16
|
image: postgres:16
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_HOST_AUTH_METHOD: "trust"
|
POSTGRES_HOST_AUTH_METHOD: "trust"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- pg-data:/var/lib/postgresql/data
|
- pg-data:/var/lib/postgresql/data
|
||||||
@@ -36,21 +34,15 @@ services:
|
|||||||
- ${GLITCHTIP_PORT}
|
- ${GLITCHTIP_PORT}
|
||||||
environment: *default-environment
|
environment: *default-environment
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- uploads:/code/uploads
|
- uploads:/code/uploads
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.${HASH}.rule=Host(`${GLITCHTIP_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}.loadbalancer.server.port=${GLITCHTIP_PORT}
|
|
||||||
worker:
|
worker:
|
||||||
image: glitchtip/glitchtip:v4.0
|
image: glitchtip/glitchtip:v4.0
|
||||||
command: ./bin/run-celery-with-beat.sh
|
command: ./bin/run-celery-with-beat.sh
|
||||||
depends_on: *default-depends_on
|
depends_on: *default-depends_on
|
||||||
environment: *default-environment
|
environment: *default-environment
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- uploads:/code/uploads
|
- uploads:/code/uploads
|
||||||
networks:
|
networks:
|
||||||
- dokploy-network
|
- dokploy-network
|
||||||
@@ -65,7 +57,3 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
pg-data:
|
pg-data:
|
||||||
uploads:
|
uploads:
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
@@ -1,23 +1,30 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateBase64,
|
generateBase64,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
|
||||||
const secretKey = generateBase64(32);
|
const secretKey = generateBase64(32);
|
||||||
|
|
||||||
|
const domains: DomainSchema[] = [
|
||||||
|
{
|
||||||
|
host: mainDomain,
|
||||||
|
port: 8000,
|
||||||
|
serviceName: "web",
|
||||||
|
},
|
||||||
|
];
|
||||||
const envs = [
|
const envs = [
|
||||||
`GLITCHTIP_HOST=${randomDomain}`,
|
`GLITCHTIP_HOST=${mainDomain}`,
|
||||||
"GLITCHTIP_PORT=8000",
|
"GLITCHTIP_PORT=8000",
|
||||||
`SECRET_KEY=${secretKey}`,
|
`SECRET_KEY=${secretKey}`,
|
||||||
`HASH=${mainServiceHash}`,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,9 @@
|
|||||||
version: "3.8"
|
version: "3.8"
|
||||||
services:
|
services:
|
||||||
grafana:
|
grafana:
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
image: grafana/grafana-enterprise:9.5.20
|
image: grafana/grafana-enterprise:9.5.20
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
|
||||||
- ${GRAFANA_PORT}
|
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.${HASH}.rule=Host(`${GRAFANA_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}.loadbalancer.server.port=${GRAFANA_PORT}
|
|
||||||
volumes:
|
volumes:
|
||||||
- grafana-storage:/var/lib/grafana
|
- grafana-storage:/var/lib/grafana
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
volumes:
|
volumes:
|
||||||
grafana-storage: {}
|
grafana-storage: {}
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const domains: DomainSchema[] = [
|
||||||
const randomDomain = generateRandomDomain(schema);
|
{
|
||||||
const envs = [
|
host: generateRandomDomain(schema),
|
||||||
`GRAFANA_HOST=${randomDomain}`,
|
port: 3000,
|
||||||
"GRAFANA_PORT=3000",
|
serviceName: "grafana",
|
||||||
`HASH=${mainServiceHash}`,
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,19 @@
|
|||||||
version: '3.8'
|
version: "3.8"
|
||||||
services:
|
services:
|
||||||
jellyfin:
|
jellyfin:
|
||||||
image: jellyfin/jellyfin:10
|
image: jellyfin/jellyfin:10
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
ports:
|
|
||||||
- ${JELLYFIN_PORT}
|
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.${HASH}.rule=Host(`${JELLYFIN_HOST}`)"
|
|
||||||
- "traefik.http.services.${HASH}.loadbalancer.server.port=${JELLYFIN_PORT}"
|
|
||||||
volumes:
|
volumes:
|
||||||
- config:/config
|
- config:/config
|
||||||
- cache:/cache
|
- cache:/cache
|
||||||
- media:/media
|
- media:/media
|
||||||
restart: 'unless-stopped'
|
restart: "unless-stopped"
|
||||||
# Optional - alternative address used for autodiscovery
|
# Optional - alternative address used for autodiscovery
|
||||||
environment:
|
environment:
|
||||||
- JELLYFIN_PublishedServerUrl=http://${JELLYFIN_HOST}
|
- JELLYFIN_PublishedServerUrl=http://${JELLYFIN_HOST}
|
||||||
# Optional - may be necessary for docker healthcheck to pass if running in host network mode
|
# Optional - may be necessary for docker healthcheck to pass if running in host network mode
|
||||||
extra_hosts:
|
extra_hosts:
|
||||||
- 'host.docker.internal:host-gateway'
|
- "host.docker.internal:host-gateway"
|
||||||
volumes:
|
volumes:
|
||||||
config:
|
config:
|
||||||
cache:
|
cache:
|
||||||
media:
|
media:
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|||||||
@@ -1,22 +1,25 @@
|
|||||||
// EXAMPLE
|
// EXAMPLE
|
||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const domain = generateRandomDomain(schema);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
const domains: DomainSchema[] = [
|
||||||
const port = 8096;
|
{
|
||||||
const envs = [
|
host: domain,
|
||||||
`JELLYFIN_HOST=${randomDomain}`,
|
port: 8096,
|
||||||
`HASH=${mainServiceHash}`,
|
serviceName: "jellyfin",
|
||||||
`JELLYFIN_PORT=${port}`,
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const envs = [`JELLYFIN_HOST=${domain}`];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,10 +36,6 @@ services:
|
|||||||
app:
|
app:
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
image: listmonk/listmonk:v3.0.0
|
image: listmonk/listmonk:v3.0.0
|
||||||
ports:
|
|
||||||
- "${LISTMONK_PORT}"
|
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
environment:
|
environment:
|
||||||
- TZ=Etc/UTC
|
- TZ=Etc/UTC
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -47,15 +43,7 @@ services:
|
|||||||
- setup
|
- setup
|
||||||
volumes:
|
volumes:
|
||||||
- ../files/config.toml:/listmonk/config.toml
|
- ../files/config.toml:/listmonk/config.toml
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.${HASH}.rule=Host(`${LISTMONK_HOST}`)"
|
|
||||||
- "traefik.http.services.${HASH}.loadbalancer.server.port=${LISTMONK_PORT}"
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
listmonk-data:
|
listmonk-data:
|
||||||
driver: local
|
driver: local
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generatePassword,
|
generatePassword,
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
|
||||||
const randomDomain = generateRandomDomain(schema);
|
const randomDomain = generateRandomDomain(schema);
|
||||||
const adminPassword = generatePassword(32);
|
const adminPassword = generatePassword(32);
|
||||||
|
|
||||||
|
const domains: DomainSchema[] = [
|
||||||
|
{
|
||||||
|
host: randomDomain,
|
||||||
|
port: 9000,
|
||||||
|
serviceName: "app",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const envs = [
|
const envs = [
|
||||||
`LISTMONK_HOST=${randomDomain}`,
|
|
||||||
"LISTMONK_PORT=9000",
|
|
||||||
`HASH=${mainServiceHash}`,
|
|
||||||
`# login with admin:${adminPassword}`,
|
`# login with admin:${adminPassword}`,
|
||||||
"# check config.toml in Advanced / Volumes for more options",
|
"# check config.toml in Advanced / Volumes for more options",
|
||||||
];
|
];
|
||||||
@@ -48,5 +52,6 @@ params = ""
|
|||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
mounts,
|
mounts,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,14 @@
|
|||||||
version: '3.8'
|
version: "3.8"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
meilisearch:
|
meilisearch:
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
image: getmeili/meilisearch:v1.8.3
|
image: getmeili/meilisearch:v1.8.3
|
||||||
ports:
|
|
||||||
- ${MEILISEARCH_PORT}
|
|
||||||
volumes:
|
volumes:
|
||||||
- meili_data:/meili_data
|
- meili_data:/meili_data
|
||||||
environment:
|
environment:
|
||||||
MEILI_MASTER_KEY: ${MEILI_MASTER_KEY}
|
MEILI_MASTER_KEY: ${MEILI_MASTER_KEY}
|
||||||
MEILI_ENV: ${MEILI_ENV}
|
MEILI_ENV: ${MEILI_ENV}
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.${HASH}.rule=Host(`${MEILISEARCH_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}.loadbalancer.server.port=${MEILISEARCH_PORT}
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
meili_data:
|
meili_data:
|
||||||
driver: local
|
driver: local
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|||||||
@@ -1,24 +1,26 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateBase64,
|
generateBase64,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
|
||||||
const masterKey = generateBase64(32);
|
const masterKey = generateBase64(32);
|
||||||
const envs = [
|
|
||||||
`MEILISEARCH_HOST=${randomDomain}`,
|
const domains: DomainSchema[] = [
|
||||||
"MEILISEARCH_PORT=7700",
|
{
|
||||||
"MEILI_ENV=development",
|
host: mainDomain,
|
||||||
`MEILI_MASTER_KEY=${masterKey}`,
|
port: 7700,
|
||||||
`HASH=${mainServiceHash}`,
|
serviceName: "meilisearch",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
const envs = ["MEILI_ENV=development", `MEILI_MASTER_KEY=${masterKey}`];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ services:
|
|||||||
image: metabase/metabase:v0.50.8
|
image: metabase/metabase:v0.50.8
|
||||||
volumes:
|
volumes:
|
||||||
- /dev/urandom:/dev/random:ro
|
- /dev/urandom:/dev/random:ro
|
||||||
ports:
|
|
||||||
- ${METABASE_PORT}
|
|
||||||
environment:
|
environment:
|
||||||
MB_DB_TYPE: postgres
|
MB_DB_TYPE: postgres
|
||||||
MB_DB_DBNAME: metabaseappdb
|
MB_DB_DBNAME: metabaseappdb
|
||||||
@@ -13,17 +11,11 @@ services:
|
|||||||
MB_DB_USER: metabase
|
MB_DB_USER: metabase
|
||||||
MB_DB_PASS: mysecretpassword
|
MB_DB_PASS: mysecretpassword
|
||||||
MB_DB_HOST: postgres
|
MB_DB_HOST: postgres
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: curl --fail -I http://localhost:3000/api/health || exit 1
|
test: curl --fail -I http://localhost:3000/api/health || exit 1
|
||||||
interval: 15s
|
interval: 15s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.${HASH}.rule=Host(`${METABASE_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}.loadbalancer.server.port=${METABASE_PORT}
|
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:14
|
image: postgres:14
|
||||||
environment:
|
environment:
|
||||||
@@ -32,7 +24,3 @@ services:
|
|||||||
POSTGRES_PASSWORD: mysecretpassword
|
POSTGRES_PASSWORD: mysecretpassword
|
||||||
networks:
|
networks:
|
||||||
- dokploy-network
|
- dokploy-network
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
|
||||||
const randomDomain = generateRandomDomain(schema);
|
const randomDomain = generateRandomDomain(schema);
|
||||||
const envs = [
|
|
||||||
`METABASE_HOST=${randomDomain}`,
|
const domains: DomainSchema[] = [
|
||||||
"METABASE_PORT=3000",
|
{
|
||||||
`HASH=${mainServiceHash}`,
|
host: randomDomain,
|
||||||
|
port: 3000,
|
||||||
|
serviceName: "metabase",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,31 +1,13 @@
|
|||||||
version: '3.8'
|
version: "3.8"
|
||||||
services:
|
services:
|
||||||
minio:
|
minio:
|
||||||
image: minio/minio
|
image: minio/minio
|
||||||
ports:
|
|
||||||
- ${MINIO_API_PORT}
|
|
||||||
- ${MINIO_DASHBOARD_PORT}
|
|
||||||
volumes:
|
volumes:
|
||||||
- minio-data:/data
|
- minio-data:/data
|
||||||
environment:
|
environment:
|
||||||
- MINIO_ROOT_USER=minioadmin
|
- MINIO_ROOT_USER=minioadmin
|
||||||
- MINIO_ROOT_PASSWORD=minioadmin123
|
- MINIO_ROOT_PASSWORD=minioadmin123
|
||||||
command: server /data --console-address ":9001"
|
command: server /data --console-address ":9001"
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.${HASH}.service=${HASH}
|
|
||||||
- traefik.http.routers.${HASH}.rule=Host(`${MINIO_DASHBOARD_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}.loadbalancer.server.port=${MINIO_DASHBOARD_PORT}
|
|
||||||
# API router and service
|
|
||||||
- traefik.http.routers.${HASH}-api.service=${HASH}-api
|
|
||||||
- traefik.http.routers.${HASH}-api.rule=Host(`${MINIO_API_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}-api.loadbalancer.server.port=${MINIO_API_PORT}
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
minio-data:
|
minio-data:
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|||||||
@@ -1,23 +1,28 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
|
||||||
const apiDomain = generateRandomDomain(schema);
|
const apiDomain = generateRandomDomain(schema);
|
||||||
const envs = [
|
|
||||||
`MINIO_DASHBOARD_HOST=${randomDomain}`,
|
const domains: DomainSchema[] = [
|
||||||
"MINIO_DASHBOARD_PORT=9001",
|
{
|
||||||
`MINIO_API_HOST=${apiDomain}`,
|
host: mainDomain,
|
||||||
"MINIO_API_PORT=9000",
|
port: 9001,
|
||||||
`HASH=${mainServiceHash}`,
|
serviceName: "minio",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
host: apiDomain,
|
||||||
|
port: 9000,
|
||||||
|
serviceName: "minio",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,17 +3,9 @@ services:
|
|||||||
n8n:
|
n8n:
|
||||||
image: docker.n8n.io/n8nio/n8n:1.48.1
|
image: docker.n8n.io/n8nio/n8n:1.48.1
|
||||||
restart: always
|
restart: always
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
ports:
|
|
||||||
- ${N8N_PORT}
|
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.${HASH}.rule=Host(`${N8N_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}.loadbalancer.server.port=${N8N_PORT}
|
|
||||||
environment:
|
environment:
|
||||||
- N8N_HOST=${N8N_HOST}
|
- N8N_HOST=${N8N_HOST}
|
||||||
- N8N_PORT=5678
|
- N8N_PORT=${N8N_PORT}
|
||||||
- N8N_PROTOCOL=http
|
- N8N_PROTOCOL=http
|
||||||
- NODE_ENV=production
|
- NODE_ENV=production
|
||||||
- WEBHOOK_URL=https://${N8N_HOST}/
|
- WEBHOOK_URL=https://${N8N_HOST}/
|
||||||
@@ -23,7 +15,4 @@ services:
|
|||||||
- n8n_data:/home/node/.n8n
|
- n8n_data:/home/node/.n8n
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
n8n_data:
|
n8n_data:
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|||||||
@@ -1,21 +1,28 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
|
||||||
|
const domains: DomainSchema[] = [
|
||||||
|
{
|
||||||
|
host: mainDomain,
|
||||||
|
port: 5678,
|
||||||
|
serviceName: "n8n",
|
||||||
|
},
|
||||||
|
];
|
||||||
const envs = [
|
const envs = [
|
||||||
`N8N_HOST=${randomDomain}`,
|
`N8N_HOST=${mainDomain}`,
|
||||||
"N8N_PORT=5678",
|
"N8N_PORT=5678",
|
||||||
`HASH=${mainServiceHash}`,
|
|
||||||
"GENERIC_TIMEZONE=Europe/Berlin",
|
"GENERIC_TIMEZONE=Europe/Berlin",
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,18 +3,10 @@ services:
|
|||||||
nocodb:
|
nocodb:
|
||||||
image: nocodb/nocodb:0.251.1
|
image: nocodb/nocodb:0.251.1
|
||||||
restart: always
|
restart: always
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
ports:
|
|
||||||
- ${NOCODB_PORT}
|
|
||||||
environment:
|
environment:
|
||||||
NC_DB : "pg://root_db?u=postgres&p=password&d=root_db"
|
NC_DB: "pg://root_db?u=postgres&p=password&d=root_db"
|
||||||
PORT : ${NOCODB_PORT}
|
PORT: ${NOCODB_PORT}
|
||||||
NC_REDIS_URL: ${NC_REDIS_URL}
|
NC_REDIS_URL: ${NC_REDIS_URL}
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.${HASH}.rule=Host(`${NOCODB_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}.loadbalancer.server.port=${NOCODB_PORT}
|
|
||||||
volumes:
|
volumes:
|
||||||
- nc_data:/usr/app/data
|
- nc_data:/usr/app/data
|
||||||
|
|
||||||
@@ -30,15 +22,11 @@ services:
|
|||||||
healthcheck:
|
healthcheck:
|
||||||
interval: 10s
|
interval: 10s
|
||||||
retries: 10
|
retries: 10
|
||||||
test: "pg_isready -U \"$$POSTGRES_USER\" -d \"$$POSTGRES_DB\""
|
test: 'pg_isready -U "$$POSTGRES_USER" -d "$$POSTGRES_DB"'
|
||||||
timeout: 2s
|
timeout: 2s
|
||||||
volumes:
|
volumes:
|
||||||
- "db_data:/var/lib/postgresql/data"
|
- "db_data:/var/lib/postgresql/data"
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
db_data: {}
|
db_data: {}
|
||||||
nc_data: {}
|
nc_data: {}
|
||||||
|
|||||||
@@ -1,26 +1,28 @@
|
|||||||
// EXAMPLE
|
// EXAMPLE
|
||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateBase64,
|
generateBase64,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
|
||||||
const randomDomain = generateRandomDomain(schema);
|
const randomDomain = generateRandomDomain(schema);
|
||||||
const secretBase = generateBase64(64);
|
const secretBase = generateBase64(64);
|
||||||
const toptKeyBase = generateBase64(32);
|
|
||||||
|
|
||||||
const envs = [
|
const domains: DomainSchema[] = [
|
||||||
`NOCODB_HOST=${randomDomain}`,
|
{
|
||||||
"NOCODB_PORT=8000",
|
host: randomDomain,
|
||||||
`NC_AUTH_JWT_SECRET=${secretBase}`,
|
port: 8000,
|
||||||
`HASH=${mainServiceHash}`,
|
serviceName: "nocodb",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const envs = ["NOCODB_PORT=8000", `NC_AUTH_JWT_SECRET=${secretBase}`];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,20 +2,12 @@ version: "3.8"
|
|||||||
services:
|
services:
|
||||||
web:
|
web:
|
||||||
image: odoo:16.0
|
image: odoo:16.0
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
ports:
|
|
||||||
- ${ODOO_PORT}
|
|
||||||
environment:
|
environment:
|
||||||
- HOST=db
|
- HOST=db
|
||||||
- USER=odoo
|
- USER=odoo
|
||||||
- PASSWORD=odoo
|
- PASSWORD=odoo
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.${HASH}.rule=Host(`${ODOO_HOST}`)"
|
|
||||||
- "traefik.http.services.${HASH}.loadbalancer.server.port=${ODOO_PORT}"
|
|
||||||
volumes:
|
volumes:
|
||||||
- odoo-web-data:/var/lib/odoo
|
- odoo-web-data:/var/lib/odoo
|
||||||
- ../files/config:/etc/odoo
|
- ../files/config:/etc/odoo
|
||||||
@@ -35,7 +27,3 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
odoo-web-data:
|
odoo-web-data:
|
||||||
odoo-db-data:
|
odoo-db-data:
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
|
||||||
const randomDomain = generateRandomDomain(schema);
|
const randomDomain = generateRandomDomain(schema);
|
||||||
const envs = [
|
|
||||||
`ODOO_HOST=${randomDomain}`,
|
const domains: DomainSchema[] = [
|
||||||
"ODOO_PORT=8069",
|
{
|
||||||
`HASH=${mainServiceHash}`,
|
host: randomDomain,
|
||||||
|
port: 8069,
|
||||||
|
serviceName: "web",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
version: '3.8'
|
version: "3.8"
|
||||||
services:
|
services:
|
||||||
|
|
||||||
ollama:
|
ollama:
|
||||||
volumes:
|
volumes:
|
||||||
- ollama:/root/.ollama
|
- ollama:/root/.ollama
|
||||||
@@ -13,24 +12,14 @@ services:
|
|||||||
|
|
||||||
open-webui:
|
open-webui:
|
||||||
image: ghcr.io/open-webui/open-webui:${WEBUI_DOCKER_TAG-main}
|
image: ghcr.io/open-webui/open-webui:${WEBUI_DOCKER_TAG-main}
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
volumes:
|
volumes:
|
||||||
- open-webui:/app/backend/data
|
- open-webui:/app/backend/data
|
||||||
depends_on:
|
depends_on:
|
||||||
- ollama
|
- ollama
|
||||||
environment:
|
environment:
|
||||||
- 'OLLAMA_BASE_URL=http://ollama:11434'
|
- "OLLAMA_BASE_URL=http://ollama:11434"
|
||||||
- 'WEBUI_SECRET_KEY='
|
- "WEBUI_SECRET_KEY="
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.${HASH}.rule=Host(`${OPEN_WEBUI_HOST}`)"
|
|
||||||
- "traefik.http.services.${HASH}.loadbalancer.server.port=${OPEN_WEBUI_PORT}"
|
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
ollama: {}
|
ollama: {}
|
||||||
|
|||||||
@@ -1,22 +1,24 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
|
||||||
const randomDomain = generateRandomDomain(schema);
|
const randomDomain = generateRandomDomain(schema);
|
||||||
const envs = [
|
|
||||||
`OPEN_WEBUI_HOST=${randomDomain}`,
|
const domains: DomainSchema[] = [
|
||||||
"OPEN_WEBUI_PORT=8080",
|
{
|
||||||
`HASH=${mainServiceHash}`,
|
host: randomDomain,
|
||||||
"OLLAMA_DOCKER_TAG=0.1.47",
|
port: 8080,
|
||||||
"WEBUI_DOCKER_TAG=0.3.7",
|
serviceName: "open-webui",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
const envs = ["OLLAMA_DOCKER_TAG=0.1.47", "WEBUI_DOCKER_TAG=0.3.7"];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
version: '3.8'
|
version: "3.8"
|
||||||
|
|
||||||
services:
|
services:
|
||||||
db:
|
db:
|
||||||
@@ -20,21 +20,9 @@ services:
|
|||||||
PMA_USER: ${MYSQL_USER}
|
PMA_USER: ${MYSQL_USER}
|
||||||
PMA_PASSWORD: ${MYSQL_PASSWORD}
|
PMA_PASSWORD: ${MYSQL_PASSWORD}
|
||||||
PMA_ARBITRARY: 1
|
PMA_ARBITRARY: 1
|
||||||
ports:
|
|
||||||
- ${PHPMYADMIN_PORT}
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.${HASH}.rule=Host(`${PHPMYADMIN_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}.loadbalancer.server.port=${PHPMYADMIN_PORT}
|
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
db_data:
|
db_data:
|
||||||
driver: local
|
driver: local
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|||||||
@@ -1,20 +1,24 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generatePassword,
|
generatePassword,
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
|
||||||
const rootPassword = generatePassword(32);
|
const rootPassword = generatePassword(32);
|
||||||
const password = generatePassword(32);
|
const password = generatePassword(32);
|
||||||
|
|
||||||
|
const domains: DomainSchema[] = [
|
||||||
|
{
|
||||||
|
host: mainDomain,
|
||||||
|
port: 80,
|
||||||
|
serviceName: "phpmyadmin",
|
||||||
|
},
|
||||||
|
];
|
||||||
const envs = [
|
const envs = [
|
||||||
`PHPMYADMIN_HOST=${randomDomain}`,
|
|
||||||
"PHPMYADMIN_PORT=80",
|
|
||||||
`HASH=${mainServiceHash}`,
|
|
||||||
`MYSQL_ROOT_PASSWORD=${rootPassword}`,
|
`MYSQL_ROOT_PASSWORD=${rootPassword}`,
|
||||||
"MYSQL_DATABASE=mysql",
|
"MYSQL_DATABASE=mysql",
|
||||||
"MYSQL_USER=phpmyadmin",
|
"MYSQL_USER=phpmyadmin",
|
||||||
@@ -23,5 +27,6 @@ export function generate(schema: Schema): Template {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,17 +32,9 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
- plausible_db
|
- plausible_db
|
||||||
- plausible_events_db
|
- plausible_events_db
|
||||||
ports:
|
|
||||||
- ${PLAUSIBLE_PORT}
|
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
env_file:
|
env_file:
|
||||||
- .env
|
- .env
|
||||||
|
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.${HASH}.rule=Host(`${PLAUSIBLE_HOST}`)"
|
|
||||||
- "traefik.http.services.${HASH}.loadbalancer.server.port=${PLAUSIBLE_PORT}"
|
|
||||||
volumes:
|
volumes:
|
||||||
db-data:
|
db-data:
|
||||||
driver: local
|
driver: local
|
||||||
@@ -50,7 +42,3 @@ volumes:
|
|||||||
driver: local
|
driver: local
|
||||||
event-logs:
|
event-logs:
|
||||||
driver: local
|
driver: local
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|||||||
@@ -1,24 +1,28 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateBase64,
|
generateBase64,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
|
||||||
const secretBase = generateBase64(64);
|
const secretBase = generateBase64(64);
|
||||||
const toptKeyBase = generateBase64(32);
|
const toptKeyBase = generateBase64(32);
|
||||||
|
|
||||||
|
const domains: DomainSchema[] = [
|
||||||
|
{
|
||||||
|
host: mainDomain,
|
||||||
|
port: 8000,
|
||||||
|
serviceName: "plausible",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const envs = [
|
const envs = [
|
||||||
`PLAUSIBLE_HOST=${randomDomain}`,
|
`BASE_URL=http://${mainDomain}`,
|
||||||
"PLAUSIBLE_PORT=8000",
|
|
||||||
`BASE_URL=http://${randomDomain}`,
|
|
||||||
`SECRET_KEY_BASE=${secretBase}`,
|
`SECRET_KEY_BASE=${secretBase}`,
|
||||||
`TOTP_VAULT_KEY=${toptKeyBase}`,
|
`TOTP_VAULT_KEY=${toptKeyBase}`,
|
||||||
`HASH=${mainServiceHash}`,
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const mounts: Template["mounts"] = [
|
const mounts: Template["mounts"] = [
|
||||||
@@ -62,5 +66,6 @@ export function generate(schema: Schema): Template {
|
|||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
mounts,
|
mounts,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,19 +3,7 @@ services:
|
|||||||
pocketbase:
|
pocketbase:
|
||||||
image: spectado/pocketbase:0.22.12
|
image: spectado/pocketbase:0.22.12
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
|
||||||
- ${POCKETBASE_PORT}
|
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.${HASH}.rule=Host(`${POCKETBASE_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}.loadbalancer.server.port=${POCKETBASE_PORT}
|
|
||||||
volumes:
|
volumes:
|
||||||
- /etc/dokploy/templates/${HASH}/data:/pb_data
|
- /etc/dokploy/templates/${HASH}/data:/pb_data
|
||||||
- /etc/dokploy/templates/${HASH}/public:/pb_public
|
- /etc/dokploy/templates/${HASH}/public:/pb_public
|
||||||
- /etc/dokploy/templates/${HASH}/migrations:/pb_migrations
|
- /etc/dokploy/templates/${HASH}/migrations:/pb_migrations
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
@@ -1,21 +1,22 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
|
||||||
|
|
||||||
const envs = [
|
const domains: DomainSchema[] = [
|
||||||
`POCKETBASE_HOST=${randomDomain}`,
|
{
|
||||||
"POCKETBASE_PORT=80",
|
host: mainDomain,
|
||||||
`HASH=${mainServiceHash}`,
|
port: 80,
|
||||||
|
serviceName: "pocketbase",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,18 +9,10 @@ services:
|
|||||||
ROOT_URL: ${ROOT_URL:-http://${ROCKETCHAT_HOST}:${ROCKETCHAT_PORT}}
|
ROOT_URL: ${ROOT_URL:-http://${ROCKETCHAT_HOST}:${ROCKETCHAT_PORT}}
|
||||||
PORT: ${ROCKETCHAT_PORT}
|
PORT: ${ROCKETCHAT_PORT}
|
||||||
DEPLOY_METHOD: docker
|
DEPLOY_METHOD: docker
|
||||||
DEPLOY_PLATFORM:
|
DEPLOY_PLATFORM:
|
||||||
REG_TOKEN:
|
REG_TOKEN:
|
||||||
depends_on:
|
depends_on:
|
||||||
- mongodb
|
- mongodb
|
||||||
ports:
|
|
||||||
- ${ROCKETCHAT_PORT}
|
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.${HASH}.rule=Host(`${ROCKETCHAT_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}.loadbalancer.server.port=${ROCKETCHAT_PORT}
|
|
||||||
|
|
||||||
mongodb:
|
mongodb:
|
||||||
image: docker.io/bitnami/mongodb:5.0
|
image: docker.io/bitnami/mongodb:5.0
|
||||||
@@ -41,8 +33,3 @@ services:
|
|||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
mongodb_data: { driver: local }
|
mongodb_data: { driver: local }
|
||||||
|
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
@@ -1,21 +1,25 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
const randomDomain = generateRandomDomain(schema);
|
|
||||||
|
|
||||||
const envs = [
|
const domains: DomainSchema[] = [
|
||||||
`ROCKETCHAT_HOST=${randomDomain}`,
|
{
|
||||||
"ROCKETCHAT_PORT=3000",
|
host: mainDomain,
|
||||||
`HASH=${mainServiceHash}`,
|
port: 3000,
|
||||||
|
serviceName: "rocketchat",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const envs = [`ROCKETCHAT_HOST=${mainDomain}`, "ROCKETCHAT_PORT=3000"];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ services:
|
|||||||
teable:
|
teable:
|
||||||
image: ghcr.io/teableio/teable:1.3.1-alpha-build.460
|
image: ghcr.io/teableio/teable:1.3.1-alpha-build.460
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
|
||||||
- ${TEABLE_PORT}
|
|
||||||
volumes:
|
volumes:
|
||||||
- teable-data:/app/.assets
|
- teable-data:/app/.assets
|
||||||
# you may use a bind-mounted host directory instead,
|
# you may use a bind-mounted host directory instead,
|
||||||
@@ -24,12 +22,6 @@ services:
|
|||||||
- BACKEND_MAIL_SENDER_NAME=${BACKEND_MAIL_SENDER_NAME}
|
- BACKEND_MAIL_SENDER_NAME=${BACKEND_MAIL_SENDER_NAME}
|
||||||
- BACKEND_MAIL_AUTH_USER=${BACKEND_MAIL_AUTH_USER}
|
- BACKEND_MAIL_AUTH_USER=${BACKEND_MAIL_AUTH_USER}
|
||||||
- BACKEND_MAIL_AUTH_PASS=${BACKEND_MAIL_AUTH_PASS}
|
- BACKEND_MAIL_AUTH_PASS=${BACKEND_MAIL_AUTH_PASS}
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.${HASH}.rule=Host(`${TEABLE_HOST}`)"
|
|
||||||
- "traefik.http.services.${HASH}.loadbalancer.server.port=${TEABLE_PORT}"
|
|
||||||
depends_on:
|
depends_on:
|
||||||
teable-db-migrate:
|
teable-db-migrate:
|
||||||
condition: service_completed_successfully
|
condition: service_completed_successfully
|
||||||
@@ -72,10 +64,6 @@ services:
|
|||||||
teable-db:
|
teable-db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
teable-data: {}
|
teable-data: {}
|
||||||
teable-db: {}
|
teable-db: {}
|
||||||
|
|||||||
@@ -1,25 +1,30 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generatePassword,
|
generatePassword,
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
|
||||||
const password = generatePassword();
|
const password = generatePassword();
|
||||||
const randomDomain = generateRandomDomain(schema);
|
const mainDomain = generateRandomDomain(schema);
|
||||||
|
|
||||||
const publicDbPort = ((min: number, max: number) => {
|
const publicDbPort = ((min: number, max: number) => {
|
||||||
return Math.round(Math.random() * (max - min) + min);
|
return Math.round(Math.random() * (max - min) + min);
|
||||||
})(32769, 65534);
|
})(32769, 65534);
|
||||||
|
|
||||||
|
const domains: DomainSchema[] = [
|
||||||
|
{
|
||||||
|
host: mainDomain,
|
||||||
|
port: 3000,
|
||||||
|
serviceName: "teable",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const envs = [
|
const envs = [
|
||||||
`TEABLE_HOST=${randomDomain}`,
|
`TEABLE_HOST=${mainDomain}`,
|
||||||
"TEABLE_PORT=3000",
|
|
||||||
`TEABLE_DB_PORT=${publicDbPort}`,
|
`TEABLE_DB_PORT=${publicDbPort}`,
|
||||||
`HASH=${mainServiceHash}`,
|
|
||||||
"TIMEZONE=UTC",
|
"TIMEZONE=UTC",
|
||||||
"# Postgres",
|
"# Postgres",
|
||||||
"POSTGRES_HOST=teable-db",
|
"POSTGRES_HOST=teable-db",
|
||||||
@@ -44,5 +49,6 @@ export function generate(schema: Schema): Template {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,18 +10,10 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
ports:
|
|
||||||
- ${UMAMI_PORT}
|
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
environment:
|
environment:
|
||||||
DATABASE_URL: postgresql://umami:umami@db:5432/umami
|
DATABASE_URL: postgresql://umami:umami@db:5432/umami
|
||||||
DATABASE_TYPE: postgresql
|
DATABASE_TYPE: postgresql
|
||||||
APP_SECRET: ${APP_SECRET}
|
APP_SECRET: ${APP_SECRET}
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.${HASH}.rule=Host(`${UMAMI_HOST}`)"
|
|
||||||
- "traefik.http.services.${HASH}.loadbalancer.server.port=${UMAMI_PORT}"
|
|
||||||
db:
|
db:
|
||||||
image: postgres:15-alpine
|
image: postgres:15-alpine
|
||||||
restart: always
|
restart: always
|
||||||
@@ -39,8 +31,5 @@ services:
|
|||||||
POSTGRES_USER: umami
|
POSTGRES_USER: umami
|
||||||
POSTGRES_PASSWORD: umami
|
POSTGRES_PASSWORD: umami
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
volumes:
|
volumes:
|
||||||
db-data:
|
db-data:
|
||||||
|
|||||||
@@ -1,24 +1,27 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateBase64,
|
generateBase64,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
|
||||||
const randomDomain = generateRandomDomain(schema);
|
const randomDomain = generateRandomDomain(schema);
|
||||||
const randomSecret = generateBase64();
|
const randomSecret = generateBase64();
|
||||||
|
|
||||||
const envs = [
|
const domains: DomainSchema[] = [
|
||||||
`UMAMI_HOST=${randomDomain}`,
|
{
|
||||||
"UMAMI_PORT=3000",
|
host: randomDomain,
|
||||||
`APP_SECRET=${randomSecret}`,
|
port: 3000,
|
||||||
`HASH=${mainServiceHash}`,
|
serviceName: "umami",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const envs = [`APP_SECRET=${randomSecret}`];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
envs,
|
||||||
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,10 @@
|
|||||||
version: "3.8"
|
version: "3.8"
|
||||||
services:
|
services:
|
||||||
uptime-kuma:
|
uptime-kuma:
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
image: louislam/uptime-kuma:1
|
image: louislam/uptime-kuma:1
|
||||||
restart: always
|
restart: always
|
||||||
ports:
|
|
||||||
- ${UPTIME_KUMA_PORT}
|
|
||||||
volumes:
|
volumes:
|
||||||
- uptime-kuma-data:/app/data
|
- uptime-kuma-data:/app/data
|
||||||
labels:
|
|
||||||
- traefik.enable=true
|
|
||||||
- traefik.http.routers.${HASH}.rule=Host(`${UPTIME_KUMA_HOST}`)
|
|
||||||
- traefik.http.services.${HASH}.loadbalancer.server.port=${UPTIME_KUMA_PORT}
|
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
uptime-kuma-data:
|
uptime-kuma-data:
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
@@ -1,20 +1,22 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
|
||||||
const randomDomain = generateRandomDomain(schema);
|
const randomDomain = generateRandomDomain(schema);
|
||||||
const envs = [
|
|
||||||
`UPTIME_KUMA_HOST=${randomDomain}`,
|
const domains: DomainSchema[] = [
|
||||||
"UPTIME_KUMA_PORT=3001",
|
{
|
||||||
`HASH=${mainServiceHash}`,
|
host: randomDomain,
|
||||||
|
port: 3001,
|
||||||
|
serviceName: "uptime-kuma",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { randomBytes } from "node:crypto";
|
import { randomBytes } from "node:crypto";
|
||||||
import { readFile } from "node:fs/promises";
|
import { readFile } from "node:fs/promises";
|
||||||
import { join } from "node:path";
|
import { join } from "node:path";
|
||||||
|
import type { Domain } from "@/server/api/services/domain";
|
||||||
import { TRPCError } from "@trpc/server";
|
import { TRPCError } from "@trpc/server";
|
||||||
import { templates } from "../templates";
|
import { templates } from "../templates";
|
||||||
import type { TemplatesKeys } from "../types/templates-data.type";
|
import type { TemplatesKeys } from "../types/templates-data.type";
|
||||||
@@ -10,12 +11,15 @@ export interface Schema {
|
|||||||
projectName: string;
|
projectName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type DomainSchema = Pick<Domain, "host" | "port" | "serviceName">;
|
||||||
|
|
||||||
export interface Template {
|
export interface Template {
|
||||||
envs: string[];
|
envs?: string[];
|
||||||
mounts?: {
|
mounts?: {
|
||||||
filePath: string;
|
filePath: string;
|
||||||
content?: string;
|
content?: string;
|
||||||
}[];
|
}[];
|
||||||
|
domains?: DomainSchema[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const generateRandomDomain = ({
|
export const generateRandomDomain = ({
|
||||||
|
|||||||
@@ -1,20 +1,12 @@
|
|||||||
version: '3.8'
|
version: "3.8"
|
||||||
services:
|
services:
|
||||||
wordpress:
|
wordpress:
|
||||||
image: wordpress:5.8.3
|
image: wordpress:5.8.3
|
||||||
networks:
|
|
||||||
- dokploy-network
|
|
||||||
ports:
|
|
||||||
- ${WORDPRESS_PORT}
|
|
||||||
environment:
|
environment:
|
||||||
WORDPRESS_DB_HOST: db
|
WORDPRESS_DB_HOST: db
|
||||||
WORDPRESS_DB_USER: exampleuser
|
WORDPRESS_DB_USER: exampleuser
|
||||||
WORDPRESS_DB_PASSWORD: examplepass
|
WORDPRESS_DB_PASSWORD: examplepass
|
||||||
WORDPRESS_DB_NAME: exampledb
|
WORDPRESS_DB_NAME: exampledb
|
||||||
labels:
|
|
||||||
- "traefik.enable=true"
|
|
||||||
- "traefik.http.routers.${HASH}.rule=Host(`${WORDPRESS_HOST}`)"
|
|
||||||
- "traefik.http.services.${HASH}.loadbalancer.server.port=${WORDPRESS_PORT}"
|
|
||||||
volumes:
|
volumes:
|
||||||
- wordpress_data:/var/www/html
|
- wordpress_data:/var/www/html
|
||||||
|
|
||||||
@@ -33,7 +25,3 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
wordpress_data:
|
wordpress_data:
|
||||||
db_data:
|
db_data:
|
||||||
|
|
||||||
networks:
|
|
||||||
dokploy-network:
|
|
||||||
external: true
|
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
import {
|
import {
|
||||||
|
type DomainSchema,
|
||||||
type Schema,
|
type Schema,
|
||||||
type Template,
|
type Template,
|
||||||
generateHash,
|
|
||||||
generateRandomDomain,
|
generateRandomDomain,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
|
||||||
export function generate(schema: Schema): Template {
|
export function generate(schema: Schema): Template {
|
||||||
const mainServiceHash = generateHash(schema.projectName);
|
|
||||||
const randomDomain = generateRandomDomain(schema);
|
const randomDomain = generateRandomDomain(schema);
|
||||||
const envs = [
|
|
||||||
`WORDPRESS_HOST=${randomDomain}`,
|
const domains: DomainSchema[] = [
|
||||||
"WORDPRESS_PORT=80",
|
{
|
||||||
`HASH=${mainServiceHash}`,
|
host: randomDomain,
|
||||||
|
port: 80,
|
||||||
|
serviceName: "wordpress",
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
envs,
|
domains,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user