mirror of
https://github.com/Dokploy/dokploy
synced 2025-06-26 18:27:59 +00:00
fix: resolve merge conflicts with upstream/canary
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { webcrypto } from "node:crypto";
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import { findAdminByAuthId } from "@/server/services/admin";
|
||||
import { findUserByAuthId } from "@/server/services/user";
|
||||
import { findAdminByAuthId } from "@dokploy/server/services/admin";
|
||||
import { findUserByAuthId } from "@dokploy/server/services/user";
|
||||
import { DrizzlePostgreSQLAdapter } from "@lucia-auth/adapter-drizzle";
|
||||
import { TimeSpan } from "lucia";
|
||||
import { Lucia } from "lucia/dist/core.js";
|
||||
|
||||
@@ -4,7 +4,7 @@ export default defineConfig({
|
||||
schema: "./server/db/schema/index.ts",
|
||||
dialect: "postgresql",
|
||||
dbCredentials: {
|
||||
url: process.env.DATABASE_URL || "",
|
||||
url: process.env.DATABASE_URL!,
|
||||
},
|
||||
out: "drizzle",
|
||||
migrations: {
|
||||
|
||||
@@ -7,12 +7,12 @@ declare global {
|
||||
|
||||
export let db: PostgresJsDatabase<typeof schema>;
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
db = drizzle(postgres(process.env.DATABASE_URL || ""), {
|
||||
db = drizzle(postgres(process.env.DATABASE_URL!), {
|
||||
schema,
|
||||
});
|
||||
} else {
|
||||
if (!global.db)
|
||||
global.db = drizzle(postgres(process.env.DATABASE_URL || ""), {
|
||||
global.db = drizzle(postgres(process.env.DATABASE_URL!), {
|
||||
schema,
|
||||
});
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// import { migrate } from "drizzle-orm/postgres-js/migrator";
|
||||
// import postgres from "postgres";
|
||||
|
||||
// const connectionString = process.env.DATABASE_URL || "";
|
||||
// const connectionString = process.env.DATABASE_URL!;
|
||||
|
||||
// const sql = postgres(connectionString, { max: 1 });
|
||||
// const db = drizzle(sql);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { sql } from "drizzle-orm";
|
||||
import { drizzle } from "drizzle-orm/postgres-js";
|
||||
import postgres from "postgres";
|
||||
|
||||
const connectionString = process.env.DATABASE_URL || "";
|
||||
const connectionString = process.env.DATABASE_URL!;
|
||||
|
||||
const pg = postgres(connectionString, { max: 1 });
|
||||
const db = drizzle(pg);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { boolean, pgTable, text } from "drizzle-orm/pg-core";
|
||||
import { boolean, integer, pgTable, text } from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
@@ -28,6 +28,9 @@ export const admins = pgTable("admin", {
|
||||
createdAt: text("createdAt")
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date().toISOString()),
|
||||
stripeCustomerId: text("stripeCustomerId"),
|
||||
stripeSubscriptionId: text("stripeSubscriptionId"),
|
||||
serversQuantity: integer("serversQuantity").notNull().default(0),
|
||||
});
|
||||
|
||||
export const adminsRelations = relations(admins, ({ one, many }) => ({
|
||||
|
||||
@@ -48,6 +48,10 @@ export const auth = pgTable("auth", {
|
||||
createdAt: text("createdAt")
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date().toISOString()),
|
||||
resetPasswordToken: text("resetPasswordToken"),
|
||||
resetPasswordExpiresAt: text("resetPasswordExpiresAt"),
|
||||
confirmationToken: text("confirmationToken"),
|
||||
confirmationExpiresAt: text("confirmationExpiresAt"),
|
||||
});
|
||||
|
||||
export const authRelations = relations(auth, ({ many }) => ({
|
||||
|
||||
@@ -53,7 +53,10 @@ export const apiCreateDestination = createSchema
|
||||
endpoint: true,
|
||||
secretAccessKey: true,
|
||||
})
|
||||
.required();
|
||||
.required()
|
||||
.extend({
|
||||
serverId: z.string().optional(),
|
||||
});
|
||||
|
||||
export const apiFindOneDestination = createSchema
|
||||
.pick({
|
||||
@@ -77,4 +80,7 @@ export const apiUpdateDestination = createSchema
|
||||
secretAccessKey: true,
|
||||
destinationId: true,
|
||||
})
|
||||
.required();
|
||||
.required()
|
||||
.extend({
|
||||
serverId: z.string().optional(),
|
||||
});
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import { relations, sql } from "drizzle-orm";
|
||||
import { boolean, pgEnum, pgTable, text, timestamp } from "drizzle-orm/pg-core";
|
||||
import { relations } from "drizzle-orm";
|
||||
import { pgEnum, pgTable, text } from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
import { admins } from "./admin";
|
||||
import { applications } from "./application";
|
||||
import { auth } from "./auth";
|
||||
/**
|
||||
* This is an example of how to use the multi-project schema feature of Drizzle ORM. Use the same
|
||||
* database instance for multiple projects.
|
||||
@@ -48,7 +47,7 @@ const createSchema = createInsertSchema(registry, {
|
||||
registryUrl: z.string(),
|
||||
adminId: z.string().min(1),
|
||||
registryId: z.string().min(1),
|
||||
registryType: z.enum(["selfHosted", "cloud"]),
|
||||
registryType: z.enum(["cloud"]),
|
||||
imagePrefix: z.string().nullable().optional(),
|
||||
});
|
||||
|
||||
@@ -59,7 +58,7 @@ export const apiCreateRegistry = createSchema
|
||||
username: z.string().min(1),
|
||||
password: z.string().min(1),
|
||||
registryUrl: z.string(),
|
||||
registryType: z.enum(["selfHosted", "cloud"]),
|
||||
registryType: z.enum(["cloud"]),
|
||||
imagePrefix: z.string().nullable().optional(),
|
||||
})
|
||||
.required()
|
||||
@@ -72,7 +71,7 @@ export const apiTestRegistry = createSchema.pick({}).extend({
|
||||
username: z.string().min(1),
|
||||
password: z.string().min(1),
|
||||
registryUrl: z.string(),
|
||||
registryType: z.enum(["selfHosted", "cloud"]),
|
||||
registryType: z.enum(["cloud"]),
|
||||
imagePrefix: z.string().nullable().optional(),
|
||||
serverId: z.string().optional(),
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import { boolean, integer, pgTable, text } from "drizzle-orm/pg-core";
|
||||
import { boolean, integer, pgEnum, pgTable, text } from "drizzle-orm/pg-core";
|
||||
import { createInsertSchema } from "drizzle-zod";
|
||||
import { nanoid } from "nanoid";
|
||||
import { z } from "zod";
|
||||
@@ -17,6 +17,8 @@ import { redis } from "./redis";
|
||||
import { sshKeys } from "./ssh-key";
|
||||
import { generateAppName } from "./utils";
|
||||
|
||||
export const serverStatus = pgEnum("serverStatus", ["active", "inactive"]);
|
||||
|
||||
export const server = pgTable("server", {
|
||||
serverId: text("serverId")
|
||||
.notNull()
|
||||
@@ -37,6 +39,8 @@ export const server = pgTable("server", {
|
||||
adminId: text("adminId")
|
||||
.notNull()
|
||||
.references(() => admins.adminId, { onDelete: "cascade" }),
|
||||
serverStatus: serverStatus("serverStatus").notNull().default("active"),
|
||||
|
||||
sshKeyId: text("sshKeyId").references(() => sshKeys.sshKeyId, {
|
||||
onDelete: "set null",
|
||||
}),
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// import postgres from "postgres";
|
||||
// import { users } from "./schema";
|
||||
|
||||
// const connectionString = process.env.DATABASE_URL || "";
|
||||
// const connectionString = process.env.DATABASE_URL!;
|
||||
|
||||
// const pg = postgres(connectionString, { max: 1 });
|
||||
// const db = drizzle(pg);
|
||||
|
||||
@@ -15,9 +15,7 @@ interface NotionMagicLinkEmailProps {
|
||||
loginCode?: string;
|
||||
}
|
||||
|
||||
const baseUrl = process.env.VERCEL_URL
|
||||
? `https://${process.env.VERCEL_URL}`
|
||||
: "";
|
||||
const baseUrl = process.env.VERCEL_URL!;
|
||||
|
||||
export const NotionMagicLinkEmail = ({
|
||||
loginCode,
|
||||
|
||||
@@ -15,9 +15,7 @@ interface PlaidVerifyIdentityEmailProps {
|
||||
validationCode?: string;
|
||||
}
|
||||
|
||||
const baseUrl = process.env.VERCEL_URL
|
||||
? `https://${process.env.VERCEL_URL}`
|
||||
: "";
|
||||
const baseUrl = process.env.VERCEL_URL!;
|
||||
|
||||
export const PlaidVerifyIdentityEmail = ({
|
||||
validationCode,
|
||||
|
||||
@@ -13,9 +13,7 @@ import {
|
||||
} from "@react-email/components";
|
||||
import * as React from "react";
|
||||
|
||||
const baseUrl = process.env.VERCEL_URL
|
||||
? `https://${process.env.VERCEL_URL}`
|
||||
: "";
|
||||
const baseUrl = process.env.VERCEL_URL!;
|
||||
|
||||
export const StripeWelcomeEmail = () => (
|
||||
<Html>
|
||||
|
||||
@@ -29,9 +29,7 @@ interface VercelInviteUserEmailProps {
|
||||
inviteFromLocation?: string;
|
||||
}
|
||||
|
||||
const baseUrl = process.env.VERCEL_URL
|
||||
? `https://${process.env.VERCEL_URL}`
|
||||
: "";
|
||||
const baseUrl = process.env.VERCEL_URL!;
|
||||
|
||||
export const VercelInviteUserEmail = ({
|
||||
username,
|
||||
|
||||
@@ -37,7 +37,6 @@ export * from "./services/application";
|
||||
export * from "./setup/config-paths";
|
||||
export * from "./setup/postgres-setup";
|
||||
export * from "./setup/redis-setup";
|
||||
export * from "./setup/registry-setup";
|
||||
export * from "./setup/server-setup";
|
||||
export * from "./setup/setup";
|
||||
export * from "./setup/traefik-setup";
|
||||
@@ -97,7 +96,6 @@ export * from "./utils/traefik/domain";
|
||||
export * from "./utils/traefik/file-types";
|
||||
export * from "./utils/traefik/middleware";
|
||||
export * from "./utils/traefik/redirect";
|
||||
export * from "./utils/traefik/registry";
|
||||
export * from "./utils/traefik/security";
|
||||
export * from "./utils/traefik/types";
|
||||
export * from "./utils/traefik/web-server";
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { randomBytes } from "node:crypto";
|
||||
import { db } from "@/server/db";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
admins,
|
||||
type apiCreateUserInvitation,
|
||||
auth,
|
||||
users,
|
||||
} from "@/server/db/schema";
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import * as bcrypt from "bcrypt";
|
||||
import { eq } from "drizzle-orm";
|
||||
@@ -20,7 +20,7 @@ export const createInvitation = async (
|
||||
const result = await tx
|
||||
.insert(auth)
|
||||
.values({
|
||||
email: input.email,
|
||||
email: input.email.toLowerCase(),
|
||||
rol: "user",
|
||||
password: bcrypt.hashSync("01231203012312", 10),
|
||||
})
|
||||
|
||||
@@ -1,38 +1,41 @@
|
||||
import { docker } from "@/server/constants";
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreateApplication, applications } from "@/server/db/schema";
|
||||
import { generateAppName } from "@/server/db/schema";
|
||||
import { getAdvancedStats } from "@/server/monitoring/utilts";
|
||||
import { generatePassword } from "@/server/templates/utils";
|
||||
import { docker } from "@dokploy/server/constants";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
type apiCreateApplication,
|
||||
applications,
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { generateAppName } from "@dokploy/server/db/schema";
|
||||
import { getAdvancedStats } from "@dokploy/server/monitoring/utilts";
|
||||
import { generatePassword } from "@dokploy/server/templates/utils";
|
||||
import {
|
||||
buildApplication,
|
||||
getBuildCommand,
|
||||
mechanizeDockerContainer,
|
||||
} from "@/server/utils/builders";
|
||||
import { sendBuildErrorNotifications } from "@/server/utils/notifications/build-error";
|
||||
import { sendBuildSuccessNotifications } from "@/server/utils/notifications/build-success";
|
||||
import { execAsyncRemote } from "@/server/utils/process/execAsync";
|
||||
} from "@dokploy/server/utils/builders";
|
||||
import { sendBuildErrorNotifications } from "@dokploy/server/utils/notifications/build-error";
|
||||
import { sendBuildSuccessNotifications } from "@dokploy/server/utils/notifications/build-success";
|
||||
import { execAsyncRemote } from "@dokploy/server/utils/process/execAsync";
|
||||
import {
|
||||
cloneBitbucketRepository,
|
||||
getBitbucketCloneCommand,
|
||||
} from "@/server/utils/providers/bitbucket";
|
||||
} from "@dokploy/server/utils/providers/bitbucket";
|
||||
import {
|
||||
buildDocker,
|
||||
buildRemoteDocker,
|
||||
} from "@/server/utils/providers/docker";
|
||||
} from "@dokploy/server/utils/providers/docker";
|
||||
import {
|
||||
cloneGitRepository,
|
||||
getCustomGitCloneCommand,
|
||||
} from "@/server/utils/providers/git";
|
||||
} from "@dokploy/server/utils/providers/git";
|
||||
import {
|
||||
cloneGithubRepository,
|
||||
getGithubCloneCommand,
|
||||
} from "@/server/utils/providers/github";
|
||||
} from "@dokploy/server/utils/providers/github";
|
||||
import {
|
||||
cloneGitlabRepository,
|
||||
getGitlabCloneCommand,
|
||||
} from "@/server/utils/providers/gitlab";
|
||||
import { createTraefikConfig } from "@/server/utils/traefik/application";
|
||||
} from "@dokploy/server/utils/providers/gitlab";
|
||||
import { createTraefikConfig } from "@dokploy/server/utils/traefik/application";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { encodeBase64 } from "../utils/docker/utils";
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { randomBytes } from "node:crypto";
|
||||
import { db } from "@/server/db";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
admins,
|
||||
type apiCreateAdmin,
|
||||
type apiCreateUser,
|
||||
auth,
|
||||
users,
|
||||
} from "@/server/db/schema";
|
||||
import { getPublicIpWithFallback } from "@/server/wss/terminal";
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { getPublicIpWithFallback } from "@dokploy/server/wss/terminal";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import * as bcrypt from "bcrypt";
|
||||
import { eq } from "drizzle-orm";
|
||||
@@ -24,7 +24,7 @@ export const createAdmin = async (input: typeof apiCreateAdmin._type) => {
|
||||
const newAuth = await tx
|
||||
.insert(auth)
|
||||
.values({
|
||||
email: input.email,
|
||||
email: input.email.toLowerCase(),
|
||||
password: hashedPassword,
|
||||
rol: "admin",
|
||||
})
|
||||
@@ -43,9 +43,9 @@ export const createAdmin = async (input: typeof apiCreateAdmin._type) => {
|
||||
.values({
|
||||
authId: newAuth.id,
|
||||
...(!IS_CLOUD && {
|
||||
serverIp: await getPublicIpWithFallback(),
|
||||
serverIp:
|
||||
process.env.ADVERTISE_ADDR || (await getPublicIpWithFallback()),
|
||||
}),
|
||||
serverIp: await getPublicIpWithFallback(),
|
||||
})
|
||||
.returning();
|
||||
|
||||
@@ -93,7 +93,7 @@ export const findAuthByEmail = async (email: string) => {
|
||||
if (!result) {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Auth not found",
|
||||
message: "User not found",
|
||||
});
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreateBackup, backups } from "@/server/db/schema";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { type apiCreateBackup, backups } from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { db } from "@/server/db";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
type apiCreateBitbucket,
|
||||
type apiUpdateBitbucket,
|
||||
bitbucket,
|
||||
gitProvider,
|
||||
} from "@/server/db/schema";
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreateCertificate, certificates } from "@/server/db/schema";
|
||||
import { removeDirectoryIfExistsContent } from "@/server/utils/filesystem/directory";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
type apiCreateCertificate,
|
||||
certificates,
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { removeDirectoryIfExistsContent } from "@dokploy/server/utils/filesystem/directory";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { dump } from "js-yaml";
|
||||
|
||||
@@ -1,44 +1,47 @@
|
||||
import { join } from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreateCompose, compose } from "@/server/db/schema";
|
||||
import { generateAppName } from "@/server/db/schema";
|
||||
import { generatePassword } from "@/server/templates/utils";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { type apiCreateCompose, compose } from "@dokploy/server/db/schema";
|
||||
import { generateAppName } from "@dokploy/server/db/schema";
|
||||
import { generatePassword } from "@dokploy/server/templates/utils";
|
||||
import {
|
||||
buildCompose,
|
||||
getBuildComposeCommand,
|
||||
} from "@/server/utils/builders/compose";
|
||||
import { randomizeSpecificationFile } from "@/server/utils/docker/compose";
|
||||
} from "@dokploy/server/utils/builders/compose";
|
||||
import { randomizeSpecificationFile } from "@dokploy/server/utils/docker/compose";
|
||||
import {
|
||||
cloneCompose,
|
||||
cloneComposeRemote,
|
||||
loadDockerCompose,
|
||||
loadDockerComposeRemote,
|
||||
} from "@/server/utils/docker/domain";
|
||||
import type { ComposeSpecification } from "@/server/utils/docker/types";
|
||||
import { sendBuildErrorNotifications } from "@/server/utils/notifications/build-error";
|
||||
import { sendBuildSuccessNotifications } from "@/server/utils/notifications/build-success";
|
||||
import { execAsync, execAsyncRemote } from "@/server/utils/process/execAsync";
|
||||
} from "@dokploy/server/utils/docker/domain";
|
||||
import type { ComposeSpecification } from "@dokploy/server/utils/docker/types";
|
||||
import { sendBuildErrorNotifications } from "@dokploy/server/utils/notifications/build-error";
|
||||
import { sendBuildSuccessNotifications } from "@dokploy/server/utils/notifications/build-success";
|
||||
import {
|
||||
execAsync,
|
||||
execAsyncRemote,
|
||||
} from "@dokploy/server/utils/process/execAsync";
|
||||
import {
|
||||
cloneBitbucketRepository,
|
||||
getBitbucketCloneCommand,
|
||||
} from "@/server/utils/providers/bitbucket";
|
||||
} from "@dokploy/server/utils/providers/bitbucket";
|
||||
import {
|
||||
cloneGitRepository,
|
||||
getCustomGitCloneCommand,
|
||||
} from "@/server/utils/providers/git";
|
||||
} from "@dokploy/server/utils/providers/git";
|
||||
import {
|
||||
cloneGithubRepository,
|
||||
getGithubCloneCommand,
|
||||
} from "@/server/utils/providers/github";
|
||||
} from "@dokploy/server/utils/providers/github";
|
||||
import {
|
||||
cloneGitlabRepository,
|
||||
getGitlabCloneCommand,
|
||||
} from "@/server/utils/providers/gitlab";
|
||||
} from "@dokploy/server/utils/providers/gitlab";
|
||||
import {
|
||||
createComposeFile,
|
||||
getCreateComposeFileCommand,
|
||||
} from "@/server/utils/providers/raw";
|
||||
} from "@dokploy/server/utils/providers/raw";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { encodeBase64 } from "../utils/docker/utils";
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { existsSync, promises as fsPromises } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import { db } from "@/server/db";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
type apiCreateDeployment,
|
||||
type apiCreateDeploymentCompose,
|
||||
type apiCreateDeploymentServer,
|
||||
deployments,
|
||||
} from "@/server/db/schema";
|
||||
import { removeDirectoryIfExistsContent } from "@/server/utils/filesystem/directory";
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { removeDirectoryIfExistsContent } from "@dokploy/server/utils/filesystem/directory";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { format } from "date-fns";
|
||||
import { desc, eq } from "drizzle-orm";
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
import { type Compose, findComposeById, updateCompose } from "./compose";
|
||||
import { type Server, findServerById } from "./server";
|
||||
|
||||
import { execAsyncRemote } from "@/server/utils/process/execAsync";
|
||||
import { execAsyncRemote } from "@dokploy/server/utils/process/execAsync";
|
||||
|
||||
export type Deployment = typeof deployments.$inferSelect;
|
||||
|
||||
@@ -49,7 +49,10 @@ export const createDeployment = async (
|
||||
const application = await findApplicationById(deployment.applicationId);
|
||||
|
||||
try {
|
||||
// await removeLastTenDeployments(deployment.applicationId);
|
||||
await removeLastTenDeployments(
|
||||
deployment.applicationId,
|
||||
application.serverId,
|
||||
);
|
||||
const { LOGS_PATH } = paths(!!application.serverId);
|
||||
const formattedDateTime = format(new Date(), "yyyy-MM-dd:HH:mm:ss");
|
||||
const fileName = `${application.appName}-${formattedDateTime}.log`;
|
||||
@@ -106,7 +109,10 @@ export const createDeploymentCompose = async (
|
||||
) => {
|
||||
const compose = await findComposeById(deployment.composeId);
|
||||
try {
|
||||
// await removeLastTenComposeDeployments(deployment.composeId);
|
||||
await removeLastTenComposeDeployments(
|
||||
deployment.composeId,
|
||||
compose.serverId,
|
||||
);
|
||||
const { LOGS_PATH } = paths(!!compose.serverId);
|
||||
const formattedDateTime = format(new Date(), "yyyy-MM-dd:HH:mm:ss");
|
||||
const fileName = `${compose.appName}-${formattedDateTime}.log`;
|
||||
@@ -181,36 +187,72 @@ export const removeDeploymentsByApplicationId = async (
|
||||
.returning();
|
||||
};
|
||||
|
||||
const removeLastTenDeployments = async (applicationId: string) => {
|
||||
const removeLastTenDeployments = async (
|
||||
applicationId: string,
|
||||
serverId: string | null,
|
||||
) => {
|
||||
const deploymentList = await db.query.deployments.findMany({
|
||||
where: eq(deployments.applicationId, applicationId),
|
||||
orderBy: desc(deployments.createdAt),
|
||||
});
|
||||
|
||||
if (deploymentList.length > 10) {
|
||||
const deploymentsToDelete = deploymentList.slice(10);
|
||||
for (const oldDeployment of deploymentsToDelete) {
|
||||
const logPath = path.join(oldDeployment.logPath);
|
||||
if (existsSync(logPath)) {
|
||||
await fsPromises.unlink(logPath);
|
||||
if (serverId) {
|
||||
let command = "";
|
||||
for (const oldDeployment of deploymentsToDelete) {
|
||||
const logPath = path.join(oldDeployment.logPath);
|
||||
|
||||
command += `
|
||||
rm -rf ${logPath};
|
||||
`;
|
||||
await removeDeployment(oldDeployment.deploymentId);
|
||||
}
|
||||
|
||||
await execAsyncRemote(serverId, command);
|
||||
} else {
|
||||
for (const oldDeployment of deploymentsToDelete) {
|
||||
const logPath = path.join(oldDeployment.logPath);
|
||||
if (existsSync(logPath)) {
|
||||
await fsPromises.unlink(logPath);
|
||||
}
|
||||
await removeDeployment(oldDeployment.deploymentId);
|
||||
}
|
||||
await removeDeployment(oldDeployment.deploymentId);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const removeLastTenComposeDeployments = async (composeId: string) => {
|
||||
const removeLastTenComposeDeployments = async (
|
||||
composeId: string,
|
||||
serverId: string | null,
|
||||
) => {
|
||||
const deploymentList = await db.query.deployments.findMany({
|
||||
where: eq(deployments.composeId, composeId),
|
||||
orderBy: desc(deployments.createdAt),
|
||||
});
|
||||
if (deploymentList.length > 10) {
|
||||
const deploymentsToDelete = deploymentList.slice(10);
|
||||
for (const oldDeployment of deploymentsToDelete) {
|
||||
const logPath = path.join(oldDeployment.logPath);
|
||||
if (existsSync(logPath)) {
|
||||
await fsPromises.unlink(logPath);
|
||||
if (serverId) {
|
||||
let command = "";
|
||||
const deploymentsToDelete = deploymentList.slice(10);
|
||||
for (const oldDeployment of deploymentsToDelete) {
|
||||
const logPath = path.join(oldDeployment.logPath);
|
||||
|
||||
command += `
|
||||
rm -rf ${logPath};
|
||||
`;
|
||||
await removeDeployment(oldDeployment.deploymentId);
|
||||
}
|
||||
|
||||
await execAsyncRemote(serverId, command);
|
||||
} else {
|
||||
const deploymentsToDelete = deploymentList.slice(10);
|
||||
for (const oldDeployment of deploymentsToDelete) {
|
||||
const logPath = path.join(oldDeployment.logPath);
|
||||
if (existsSync(logPath)) {
|
||||
await fsPromises.unlink(logPath);
|
||||
}
|
||||
await removeDeployment(oldDeployment.deploymentId);
|
||||
}
|
||||
await removeDeployment(oldDeployment.deploymentId);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -327,7 +369,6 @@ export const createServerDeployment = async (
|
||||
}
|
||||
return deploymentCreate[0];
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Error to create the deployment",
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreateDestination, destinations } from "@/server/db/schema";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
type apiCreateDestination,
|
||||
destinations,
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { and, eq } from "drizzle-orm";
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { execAsync, execAsyncRemote } from "@/server/utils/process/execAsync";
|
||||
import {
|
||||
execAsync,
|
||||
execAsyncRemote,
|
||||
} from "@dokploy/server/utils/process/execAsync";
|
||||
|
||||
export const getContainers = async (serverId?: string | null) => {
|
||||
try {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { db } from "@/server/db";
|
||||
import { generateRandomDomain } from "@/server/templates/utils";
|
||||
import { manageDomain } from "@/server/utils/traefik/domain";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { generateRandomDomain } from "@dokploy/server/templates/utils";
|
||||
import { manageDomain } from "@dokploy/server/utils/traefik/domain";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { type apiCreateDomain, domains } from "../db/schema";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { db } from "@/server/db";
|
||||
import { gitProvider } from "@/server/db/schema";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { gitProvider } from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreateGithub, gitProvider, github } from "@/server/db/schema";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
type apiCreateGithub,
|
||||
gitProvider,
|
||||
github,
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from "@/server/db";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
type apiCreateGitlab,
|
||||
type bitbucket,
|
||||
gitProvider,
|
||||
type github,
|
||||
gitlab,
|
||||
} from "@/server/db/schema";
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreateMariaDB, backups, mariadb } from "@/server/db/schema";
|
||||
import { generateAppName } from "@/server/db/schema";
|
||||
import { generatePassword } from "@/server/templates/utils";
|
||||
import { buildMariadb } from "@/server/utils/databases/mariadb";
|
||||
import { pullImage } from "@/server/utils/docker/utils";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
type apiCreateMariaDB,
|
||||
backups,
|
||||
mariadb,
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { generateAppName } from "@dokploy/server/db/schema";
|
||||
import { generatePassword } from "@dokploy/server/templates/utils";
|
||||
import { buildMariadb } from "@dokploy/server/utils/databases/mariadb";
|
||||
import { pullImage } from "@dokploy/server/utils/docker/utils";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq, getTableColumns } from "drizzle-orm";
|
||||
import { validUniqueServerAppName } from "./project";
|
||||
|
||||
import { execAsyncRemote } from "@/server/utils/process/execAsync";
|
||||
import { execAsyncRemote } from "@dokploy/server/utils/process/execAsync";
|
||||
|
||||
export type Mariadb = typeof mariadb.$inferSelect;
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreateMongo, backups, mongo } from "@/server/db/schema";
|
||||
import { generateAppName } from "@/server/db/schema";
|
||||
import { generatePassword } from "@/server/templates/utils";
|
||||
import { buildMongo } from "@/server/utils/databases/mongo";
|
||||
import { pullImage } from "@/server/utils/docker/utils";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { type apiCreateMongo, backups, mongo } from "@dokploy/server/db/schema";
|
||||
import { generateAppName } from "@dokploy/server/db/schema";
|
||||
import { generatePassword } from "@dokploy/server/templates/utils";
|
||||
import { buildMongo } from "@dokploy/server/utils/databases/mongo";
|
||||
import { pullImage } from "@dokploy/server/utils/docker/utils";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq, getTableColumns } from "drizzle-orm";
|
||||
import { validUniqueServerAppName } from "./project";
|
||||
|
||||
import { execAsyncRemote } from "@/server/utils/process/execAsync";
|
||||
import { execAsyncRemote } from "@dokploy/server/utils/process/execAsync";
|
||||
|
||||
export type Mongo = typeof mongo.$inferSelect;
|
||||
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
import path from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import { db } from "@/server/db";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
type ServiceType,
|
||||
type apiCreateMount,
|
||||
mounts,
|
||||
} from "@/server/db/schema";
|
||||
import { createFile, getCreateFileCommand } from "@/server/utils/docker/utils";
|
||||
import { removeFileOrDirectory } from "@/server/utils/filesystem/directory";
|
||||
import { execAsyncRemote } from "@/server/utils/process/execAsync";
|
||||
} from "@dokploy/server/db/schema";
|
||||
import {
|
||||
createFile,
|
||||
getCreateFileCommand,
|
||||
} from "@dokploy/server/utils/docker/utils";
|
||||
import { removeFileOrDirectory } from "@dokploy/server/utils/filesystem/directory";
|
||||
import { execAsyncRemote } from "@dokploy/server/utils/process/execAsync";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { type SQL, eq, sql } from "drizzle-orm";
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreateMySql, backups, mysql } from "@/server/db/schema";
|
||||
import { generateAppName } from "@/server/db/schema";
|
||||
import { generatePassword } from "@/server/templates/utils";
|
||||
import { buildMysql } from "@/server/utils/databases/mysql";
|
||||
import { pullImage } from "@/server/utils/docker/utils";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { type apiCreateMySql, backups, mysql } from "@dokploy/server/db/schema";
|
||||
import { generateAppName } from "@dokploy/server/db/schema";
|
||||
import { generatePassword } from "@dokploy/server/templates/utils";
|
||||
import { buildMysql } from "@dokploy/server/utils/databases/mysql";
|
||||
import { pullImage } from "@dokploy/server/utils/docker/utils";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq, getTableColumns } from "drizzle-orm";
|
||||
import { validUniqueServerAppName } from "./project";
|
||||
|
||||
import { execAsyncRemote } from "@/server/utils/process/execAsync";
|
||||
import { execAsyncRemote } from "@dokploy/server/utils/process/execAsync";
|
||||
|
||||
export type MySql = typeof mysql.$inferSelect;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { db } from "@/server/db";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
type apiCreateDiscord,
|
||||
type apiCreateEmail,
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
notifications,
|
||||
slack,
|
||||
telegram,
|
||||
} from "@/server/db/schema";
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreatePort, ports } from "@/server/db/schema";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { type apiCreatePort, ports } from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreatePostgres, backups, postgres } from "@/server/db/schema";
|
||||
import { generateAppName } from "@/server/db/schema";
|
||||
import { generatePassword } from "@/server/templates/utils";
|
||||
import { buildPostgres } from "@/server/utils/databases/postgres";
|
||||
import { pullImage } from "@/server/utils/docker/utils";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
type apiCreatePostgres,
|
||||
backups,
|
||||
postgres,
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { generateAppName } from "@dokploy/server/db/schema";
|
||||
import { generatePassword } from "@dokploy/server/templates/utils";
|
||||
import { buildPostgres } from "@dokploy/server/utils/databases/postgres";
|
||||
import { pullImage } from "@dokploy/server/utils/docker/utils";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq, getTableColumns } from "drizzle-orm";
|
||||
import { validUniqueServerAppName } from "./project";
|
||||
|
||||
import { execAsyncRemote } from "@/server/utils/process/execAsync";
|
||||
import { execAsyncRemote } from "@dokploy/server/utils/process/execAsync";
|
||||
|
||||
export type Postgres = typeof postgres.$inferSelect;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { db } from "@/server/db";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
type apiCreateProject,
|
||||
applications,
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
postgres,
|
||||
projects,
|
||||
redis,
|
||||
} from "@/server/db/schema";
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreateRedirect, redirects } from "@/server/db/schema";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { type apiCreateRedirect, redirects } from "@dokploy/server/db/schema";
|
||||
import {
|
||||
createRedirectMiddleware,
|
||||
removeRedirectMiddleware,
|
||||
updateRedirectMiddleware,
|
||||
} from "@/server/utils/traefik/redirect";
|
||||
} from "@dokploy/server/utils/traefik/redirect";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { desc, eq } from "drizzle-orm";
|
||||
import type { z } from "zod";
|
||||
@@ -51,7 +51,6 @@ export const createRedirect = async (
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Error to create this redirect",
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreateRedis, redis } from "@/server/db/schema";
|
||||
import { generateAppName } from "@/server/db/schema";
|
||||
import { generatePassword } from "@/server/templates/utils";
|
||||
import { buildRedis } from "@/server/utils/databases/redis";
|
||||
import { pullImage } from "@/server/utils/docker/utils";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { type apiCreateRedis, redis } from "@dokploy/server/db/schema";
|
||||
import { generateAppName } from "@dokploy/server/db/schema";
|
||||
import { generatePassword } from "@dokploy/server/templates/utils";
|
||||
import { buildRedis } from "@dokploy/server/utils/databases/redis";
|
||||
import { pullImage } from "@dokploy/server/utils/docker/utils";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { validUniqueServerAppName } from "./project";
|
||||
|
||||
import { execAsyncRemote } from "@/server/utils/process/execAsync";
|
||||
import { execAsyncRemote } from "@dokploy/server/utils/process/execAsync";
|
||||
|
||||
export type Redis = typeof redis.$inferSelect;
|
||||
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreateRegistry, registry } from "@/server/db/schema";
|
||||
import { initializeRegistry } from "@/server/setup/registry-setup";
|
||||
import { removeService } from "@/server/utils/docker/utils";
|
||||
import { execAsync, execAsyncRemote } from "@/server/utils/process/execAsync";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { type apiCreateRegistry, registry } from "@dokploy/server/db/schema";
|
||||
import {
|
||||
manageRegistry,
|
||||
removeSelfHostedRegistry,
|
||||
} from "@/server/utils/traefik/registry";
|
||||
execAsync,
|
||||
execAsyncRemote,
|
||||
} from "@dokploy/server/utils/process/execAsync";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { IS_CLOUD } from "../constants";
|
||||
|
||||
export type Registry = typeof registry.$inferSelect;
|
||||
|
||||
@@ -32,6 +30,13 @@ export const createRegistry = async (
|
||||
message: "Error input: Inserting registry",
|
||||
});
|
||||
}
|
||||
|
||||
if (IS_CLOUD && !input.serverId && input.serverId !== "none") {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Select a server to add the registry",
|
||||
});
|
||||
}
|
||||
const loginCommand = `echo ${input.password} | docker login ${input.registryUrl} --username ${input.username} --password-stdin`;
|
||||
if (input.serverId && input.serverId !== "none") {
|
||||
await execAsyncRemote(input.serverId, loginCommand);
|
||||
@@ -58,13 +63,10 @@ export const removeRegistry = async (registryId: string) => {
|
||||
});
|
||||
}
|
||||
|
||||
if (response.registryType === "selfHosted") {
|
||||
await removeSelfHostedRegistry();
|
||||
await removeService("dokploy-registry");
|
||||
if (!IS_CLOUD) {
|
||||
await execAsync(`docker logout ${response.registryUrl}`);
|
||||
}
|
||||
|
||||
await execAsync(`docker logout ${response.registryUrl}`);
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
throw new TRPCError({
|
||||
@@ -89,12 +91,19 @@ export const updateRegistry = async (
|
||||
.returning()
|
||||
.then((res) => res[0]);
|
||||
|
||||
if (response?.registryType === "selfHosted") {
|
||||
await manageRegistry(response);
|
||||
await initializeRegistry(response.username, response.password);
|
||||
}
|
||||
const loginCommand = `echo ${response?.password} | docker login ${response?.registryUrl} --username ${response?.username} --password-stdin`;
|
||||
|
||||
if (
|
||||
IS_CLOUD &&
|
||||
!registryData?.serverId &&
|
||||
registryData?.serverId !== "none"
|
||||
) {
|
||||
throw new TRPCError({
|
||||
code: "NOT_FOUND",
|
||||
message: "Select a server to add the registry",
|
||||
});
|
||||
}
|
||||
|
||||
if (registryData?.serverId && registryData?.serverId !== "none") {
|
||||
await execAsyncRemote(registryData.serverId, loginCommand);
|
||||
} else if (response?.registryType === "cloud") {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreateSecurity, security } from "@/server/db/schema";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { type apiCreateSecurity, security } from "@dokploy/server/db/schema";
|
||||
import {
|
||||
createSecurityMiddleware,
|
||||
removeSecurityMiddleware,
|
||||
} from "@/server/utils/traefik/security";
|
||||
} from "@dokploy/server/utils/traefik/security";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
import type { z } from "zod";
|
||||
@@ -48,7 +48,6 @@ export const createSecurity = async (
|
||||
return true;
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: "Error to create this security",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { db } from "@/server/db";
|
||||
import { type apiCreateServer, server } from "@/server/db/schema";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { type apiCreateServer, server } from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { desc, eq } from "drizzle-orm";
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { readdirSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { docker } from "@/server/constants";
|
||||
import { getServiceContainer } from "@/server/utils/docker/utils";
|
||||
import { execAsyncRemote } from "@/server/utils/process/execAsync";
|
||||
import { docker } from "@dokploy/server/constants";
|
||||
import { getServiceContainer } from "@dokploy/server/utils/docker/utils";
|
||||
import { execAsyncRemote } from "@dokploy/server/utils/process/execAsync";
|
||||
// import packageInfo from "../../../package.json";
|
||||
|
||||
const updateIsAvailable = async () => {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { db } from "@/server/db";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import {
|
||||
type apiCreateSshKey,
|
||||
type apiFindOneSshKey,
|
||||
type apiRemoveSshKey,
|
||||
type apiUpdateSshKey,
|
||||
sshKeys,
|
||||
} from "@/server/db/schema";
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { db } from "@/server/db";
|
||||
import { users } from "@/server/db/schema";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { users } from "@dokploy/server/db/schema";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { eq } from "drizzle-orm";
|
||||
|
||||
|
||||
@@ -32,16 +32,18 @@ export const initializePostgres = async () => {
|
||||
Replicas: 1,
|
||||
},
|
||||
},
|
||||
EndpointSpec: {
|
||||
Ports: [
|
||||
{
|
||||
TargetPort: 5432,
|
||||
PublishedPort: process.env.NODE_ENV === "development" ? 5432 : 0,
|
||||
Protocol: "tcp",
|
||||
PublishMode: "host",
|
||||
},
|
||||
],
|
||||
},
|
||||
...(process.env.NODE_ENV === "development" && {
|
||||
EndpointSpec: {
|
||||
Ports: [
|
||||
{
|
||||
TargetPort: 5432,
|
||||
PublishedPort: 5432,
|
||||
Protocol: "tcp",
|
||||
PublishMode: "host",
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
};
|
||||
try {
|
||||
await pullImage(imageName);
|
||||
|
||||
@@ -29,16 +29,18 @@ export const initializeRedis = async () => {
|
||||
Replicas: 1,
|
||||
},
|
||||
},
|
||||
EndpointSpec: {
|
||||
Ports: [
|
||||
{
|
||||
TargetPort: 6379,
|
||||
PublishedPort: process.env.NODE_ENV === "development" ? 6379 : 0,
|
||||
Protocol: "tcp",
|
||||
PublishMode: "host",
|
||||
},
|
||||
],
|
||||
},
|
||||
...(process.env.NODE_ENV === "development" && {
|
||||
EndpointSpec: {
|
||||
Ports: [
|
||||
{
|
||||
TargetPort: 6379,
|
||||
PublishedPort: 6379,
|
||||
Protocol: "tcp",
|
||||
PublishMode: "host",
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
};
|
||||
try {
|
||||
await pullImage(imageName);
|
||||
|
||||
@@ -1,91 +0,0 @@
|
||||
import type { CreateServiceOptions } from "dockerode";
|
||||
import { docker, paths } from "../constants";
|
||||
import { generatePassword } from "../templates/utils";
|
||||
import { pullImage } from "../utils/docker/utils";
|
||||
import { execAsync } from "../utils/process/execAsync";
|
||||
|
||||
export const initializeRegistry = async (
|
||||
username: string,
|
||||
password: string,
|
||||
) => {
|
||||
const { REGISTRY_PATH } = paths();
|
||||
const imageName = "registry:2.8.3";
|
||||
const containerName = "dokploy-registry";
|
||||
await generateRegistryPassword(username, password);
|
||||
const randomPass = generatePassword();
|
||||
const settings: CreateServiceOptions = {
|
||||
Name: containerName,
|
||||
TaskTemplate: {
|
||||
ContainerSpec: {
|
||||
Image: imageName,
|
||||
Env: [
|
||||
"REGISTRY_STORAGE_DELETE_ENABLED=true",
|
||||
"REGISTRY_AUTH=htpasswd",
|
||||
"REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm",
|
||||
"REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd",
|
||||
`REGISTRY_HTTP_SECRET=${randomPass}`,
|
||||
],
|
||||
Mounts: [
|
||||
{
|
||||
Type: "bind",
|
||||
Source: `${REGISTRY_PATH}/htpasswd`,
|
||||
Target: "/auth/htpasswd",
|
||||
ReadOnly: true,
|
||||
},
|
||||
{
|
||||
Type: "volume",
|
||||
Source: "registry-data",
|
||||
Target: "/var/lib/registry",
|
||||
ReadOnly: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
Networks: [{ Target: "dokploy-network" }],
|
||||
Placement: {
|
||||
Constraints: ["node.role==manager"],
|
||||
},
|
||||
},
|
||||
Mode: {
|
||||
Replicated: {
|
||||
Replicas: 1,
|
||||
},
|
||||
},
|
||||
EndpointSpec: {
|
||||
Ports: [
|
||||
{
|
||||
TargetPort: 5000,
|
||||
PublishedPort: 5000,
|
||||
Protocol: "tcp",
|
||||
PublishMode: "host",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
try {
|
||||
await pullImage(imageName);
|
||||
|
||||
const service = docker.getService(containerName);
|
||||
const inspect = await service.inspect();
|
||||
await service.update({
|
||||
version: Number.parseInt(inspect.Version.Index),
|
||||
...settings,
|
||||
});
|
||||
console.log("Registry Started ✅");
|
||||
} catch (error) {
|
||||
await docker.createService(settings);
|
||||
console.log("Registry Not Found: Starting ✅");
|
||||
}
|
||||
};
|
||||
|
||||
const generateRegistryPassword = async (username: string, password: string) => {
|
||||
try {
|
||||
const { REGISTRY_PATH } = paths();
|
||||
const command = `htpasswd -nbB ${username} "${password}" > ${REGISTRY_PATH}/htpasswd`;
|
||||
const result = await execAsync(command);
|
||||
console.log("Password generated ✅");
|
||||
return result.stdout.trim();
|
||||
} catch (error) {
|
||||
console.error("Error generating password:", error);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
@@ -1,15 +1,15 @@
|
||||
import { createWriteStream } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import {
|
||||
createServerDeployment,
|
||||
updateDeploymentStatus,
|
||||
} from "@/server/services/deployment";
|
||||
import { findServerById } from "@/server/services/server";
|
||||
} from "@dokploy/server/services/deployment";
|
||||
import { findServerById } from "@dokploy/server/services/server";
|
||||
import {
|
||||
getDefaultMiddlewares,
|
||||
getDefaultServerTraefikConfig,
|
||||
} from "@/server/setup/traefik-setup";
|
||||
} from "@dokploy/server/setup/traefik-setup";
|
||||
import { Client } from "ssh2";
|
||||
import { recreateDirectory } from "../utils/filesystem/directory";
|
||||
|
||||
@@ -101,7 +101,6 @@ const installRequirements = async (serverId: string, logPath: string) => {
|
||||
}
|
||||
stream
|
||||
.on("close", () => {
|
||||
writeStream.write("Connection closed ✅");
|
||||
client.end();
|
||||
resolve();
|
||||
})
|
||||
|
||||
@@ -9,8 +9,8 @@ import type { FileConfig } from "../utils/traefik/file-types";
|
||||
import type { MainTraefikConfig } from "../utils/traefik/types";
|
||||
|
||||
const TRAEFIK_SSL_PORT =
|
||||
Number.parseInt(process.env.TRAEFIK_SSL_PORT ?? "", 10) || 443;
|
||||
const TRAEFIK_PORT = Number.parseInt(process.env.TRAEFIK_PORT ?? "", 10) || 80;
|
||||
Number.parseInt(process.env.TRAEFIK_SSL_PORT!, 10) || 443;
|
||||
const TRAEFIK_PORT = Number.parseInt(process.env.TRAEFIK_PORT!, 10) || 80;
|
||||
|
||||
interface TraefikOptions {
|
||||
enableDashboard?: boolean;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { randomBytes } from "node:crypto";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import type { Domain } from "@/server/services/domain";
|
||||
import type { Domain } from "@dokploy/server/services/domain";
|
||||
|
||||
export interface Schema {
|
||||
serverIp: string;
|
||||
@@ -35,9 +35,15 @@ export const generateHash = (projectName: string, quantity = 3): string => {
|
||||
};
|
||||
|
||||
export const generatePassword = (quantity = 16): string => {
|
||||
return randomBytes(Math.ceil(quantity / 2))
|
||||
.toString("hex")
|
||||
.slice(0, quantity);
|
||||
const characters =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
let password = "";
|
||||
for (let i = 0; i < quantity; i++) {
|
||||
password += characters.charAt(
|
||||
Math.floor(Math.random() * characters.length),
|
||||
);
|
||||
}
|
||||
return password.toLowerCase();
|
||||
};
|
||||
|
||||
export const generateBase64 = (bytes = 32): string => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type * as schema from "@/server/db/schema";
|
||||
import type * as schema from "@dokploy/server/db/schema";
|
||||
import type {
|
||||
BuildQueryResult,
|
||||
DBQueryConfig,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { IS_CLOUD, paths } from "@/server/constants";
|
||||
import { updateAdmin } from "@/server/services/admin";
|
||||
import { IS_CLOUD, paths } from "@dokploy/server/constants";
|
||||
import { updateAdmin } from "@dokploy/server/services/admin";
|
||||
import { type RotatingFileStream, createStream } from "rotating-file-stream";
|
||||
import { db } from "../../db";
|
||||
import { execAsync } from "../process/execAsync";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { findAdmin } from "@/server/services/admin";
|
||||
import { getAllServers } from "@/server/services/server";
|
||||
import { findAdmin } from "@dokploy/server/services/admin";
|
||||
import { getAllServers } from "@dokploy/server/services/server";
|
||||
import { scheduleJob } from "node-schedule";
|
||||
import { db } from "../../db/index";
|
||||
import {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import path from "node:path";
|
||||
import type { BackupSchedule } from "@/server/services/backup";
|
||||
import type { Mariadb } from "@/server/services/mariadb";
|
||||
import { findProjectById } from "@/server/services/project";
|
||||
import type { BackupSchedule } from "@dokploy/server/services/backup";
|
||||
import type { Mariadb } from "@dokploy/server/services/mariadb";
|
||||
import { findProjectById } from "@dokploy/server/services/project";
|
||||
import {
|
||||
getRemoteServiceContainer,
|
||||
getServiceContainer,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import path from "node:path";
|
||||
import type { BackupSchedule } from "@/server/services/backup";
|
||||
import type { Mongo } from "@/server/services/mongo";
|
||||
import { findProjectById } from "@/server/services/project";
|
||||
import type { BackupSchedule } from "@dokploy/server/services/backup";
|
||||
import type { Mongo } from "@dokploy/server/services/mongo";
|
||||
import { findProjectById } from "@dokploy/server/services/project";
|
||||
import {
|
||||
getRemoteServiceContainer,
|
||||
getServiceContainer,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { unlink } from "node:fs/promises";
|
||||
import path from "node:path";
|
||||
import type { BackupSchedule } from "@/server/services/backup";
|
||||
import type { MySql } from "@/server/services/mysql";
|
||||
import { findProjectById } from "@/server/services/project";
|
||||
import type { BackupSchedule } from "@dokploy/server/services/backup";
|
||||
import type { MySql } from "@dokploy/server/services/mysql";
|
||||
import { findProjectById } from "@dokploy/server/services/project";
|
||||
import {
|
||||
getRemoteServiceContainer,
|
||||
getServiceContainer,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import path from "node:path";
|
||||
import type { BackupSchedule } from "@/server/services/backup";
|
||||
import type { Postgres } from "@/server/services/postgres";
|
||||
import { findProjectById } from "@/server/services/project";
|
||||
import type { BackupSchedule } from "@dokploy/server/services/backup";
|
||||
import type { Postgres } from "@dokploy/server/services/postgres";
|
||||
import { findProjectById } from "@dokploy/server/services/project";
|
||||
import {
|
||||
getRemoteServiceContainer,
|
||||
getServiceContainer,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { BackupSchedule } from "@/server/services/backup";
|
||||
import type { Destination } from "@/server/services/destination";
|
||||
import type { BackupSchedule } from "@dokploy/server/services/backup";
|
||||
import type { Destination } from "@dokploy/server/services/destination";
|
||||
import { scheduleJob, scheduledJobs } from "node-schedule";
|
||||
import { runMariadbBackup } from "./mariadb";
|
||||
import { runMongoBackup } from "./mongo";
|
||||
|
||||
@@ -5,8 +5,8 @@ import {
|
||||
writeFileSync,
|
||||
} from "node:fs";
|
||||
import { dirname, join } from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import type { InferResultType } from "@/server/types/with";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import type { InferResultType } from "@dokploy/server/types/with";
|
||||
import boxen from "boxen";
|
||||
import {
|
||||
writeDomainsToCompose,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { WriteStream } from "node:fs";
|
||||
import { prepareEnvironmentVariables } from "@/server/utils/docker/utils";
|
||||
import { prepareEnvironmentVariables } from "@dokploy/server/utils/docker/utils";
|
||||
import type { ApplicationNested } from ".";
|
||||
import {
|
||||
getBuildAppDirectory,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import fs from "node:fs/promises";
|
||||
import path, { join } from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import type { Application } from "@/server/services/application";
|
||||
import { findServerById } from "@/server/services/server";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import type { Application } from "@dokploy/server/services/application";
|
||||
import { findServerById } from "@dokploy/server/services/server";
|
||||
import AdmZip from "adm-zip";
|
||||
import { Client, type SFTPWrapper } from "ssh2";
|
||||
import {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { createWriteStream } from "node:fs";
|
||||
import type { InferResultType } from "@/server/types/with";
|
||||
import { join } from "node:path";
|
||||
import type { InferResultType } from "@dokploy/server/types/with";
|
||||
import type { CreateServiceOptions } from "dockerode";
|
||||
import { uploadImage } from "../cluster/upload";
|
||||
import { uploadImage, uploadImageRemoteCommand } from "../cluster/upload";
|
||||
import {
|
||||
calculateResources,
|
||||
generateBindMounts,
|
||||
@@ -69,19 +70,30 @@ export const getBuildCommand = (
|
||||
application: ApplicationNested,
|
||||
logPath: string,
|
||||
) => {
|
||||
const { buildType } = application;
|
||||
let command = "";
|
||||
const { buildType, registry } = application;
|
||||
switch (buildType) {
|
||||
case "nixpacks":
|
||||
return getNixpacksCommand(application, logPath);
|
||||
command = getNixpacksCommand(application, logPath);
|
||||
break;
|
||||
case "heroku_buildpacks":
|
||||
return getHerokuCommand(application, logPath);
|
||||
command = getHerokuCommand(application, logPath);
|
||||
break;
|
||||
case "paketo_buildpacks":
|
||||
return getPaketoCommand(application, logPath);
|
||||
command = getPaketoCommand(application, logPath);
|
||||
break;
|
||||
case "static":
|
||||
return getStaticCommand(application, logPath);
|
||||
command = getStaticCommand(application, logPath);
|
||||
break;
|
||||
case "dockerfile":
|
||||
return getDockerCommand(application, logPath);
|
||||
command = getDockerCommand(application, logPath);
|
||||
break;
|
||||
}
|
||||
if (registry) {
|
||||
command += uploadImageRemoteCommand(application, logPath);
|
||||
}
|
||||
|
||||
return command;
|
||||
};
|
||||
|
||||
export const mechanizeDockerContainer = async (
|
||||
@@ -186,11 +198,11 @@ const getImageName = (application: ApplicationNested) => {
|
||||
return dockerImage || "ERROR-NO-IMAGE-PROVIDED";
|
||||
}
|
||||
|
||||
const registryUrl = registry?.registryUrl || "";
|
||||
const imagePrefix = registry?.imagePrefix ? `${registry.imagePrefix}/` : "";
|
||||
return registry
|
||||
? `${registryUrl}/${imagePrefix}${appName}`
|
||||
: `${appName}:latest`;
|
||||
if (registry) {
|
||||
return join(registry.imagePrefix || "", appName);
|
||||
}
|
||||
|
||||
return `${appName}:latest`;
|
||||
};
|
||||
|
||||
const getAuthConfig = (application: ApplicationNested) => {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { type WriteStream, existsSync, mkdirSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { buildStatic, getStaticCommand } from "@/server/utils/builders/static";
|
||||
import {
|
||||
buildStatic,
|
||||
getStaticCommand,
|
||||
} from "@dokploy/server/utils/builders/static";
|
||||
import { nanoid } from "nanoid";
|
||||
import type { ApplicationNested } from ".";
|
||||
import { prepareEnvironmentVariables } from "../docker/utils";
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { WriteStream } from "node:fs";
|
||||
import {
|
||||
buildCustomDocker,
|
||||
getDockerCommand,
|
||||
} from "@/server/utils/builders/docker-file";
|
||||
} from "@dokploy/server/utils/builders/docker-file";
|
||||
import type { ApplicationNested } from ".";
|
||||
import { createFile, getCreateFileCommand } from "../docker/utils";
|
||||
import { getBuildAppDirectory } from "../filesystem/directory";
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { WriteStream } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import type { ApplicationNested } from "../builders";
|
||||
import { spawnAsync } from "../process/spawnAsync";
|
||||
|
||||
@@ -16,23 +17,14 @@ export const uploadImage = async (
|
||||
const { appName } = application;
|
||||
const imageName = `${appName}:latest`;
|
||||
|
||||
const finalURL =
|
||||
registryType === "selfHosted"
|
||||
? process.env.NODE_ENV === "development"
|
||||
? "localhost:5000"
|
||||
: registryUrl
|
||||
: registryUrl;
|
||||
const finalURL = registryUrl;
|
||||
|
||||
const registryTag = imagePrefix
|
||||
? `${finalURL}/${imagePrefix}/${imageName}`
|
||||
: `${finalURL}/${imageName}`;
|
||||
const registryTag = join(imagePrefix || "", imageName);
|
||||
|
||||
try {
|
||||
console.log(finalURL, registryTag);
|
||||
writeStream.write(
|
||||
`📦 [Enabled Registry] Uploading image to ${registry.registryType} | ${registryTag} | ${finalURL}\n`,
|
||||
);
|
||||
|
||||
await spawnAsync(
|
||||
"docker",
|
||||
["login", finalURL, "-u", registry.username, "-p", registry.password],
|
||||
@@ -59,7 +51,48 @@ export const uploadImage = async (
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
// docker:
|
||||
// endpoint: "unix:///var/run/docker.sock"
|
||||
// exposedByDefault: false
|
||||
// swarmMode: true
|
||||
|
||||
export const uploadImageRemoteCommand = (
|
||||
application: ApplicationNested,
|
||||
logPath: string,
|
||||
) => {
|
||||
const registry = application.registry;
|
||||
|
||||
if (!registry) {
|
||||
throw new Error("Registry not found");
|
||||
}
|
||||
|
||||
const { registryUrl, imagePrefix } = registry;
|
||||
const { appName } = application;
|
||||
const imageName = `${appName}:latest`;
|
||||
|
||||
const finalURL = registryUrl;
|
||||
|
||||
const registryTag = join(imagePrefix || "", imageName);
|
||||
|
||||
try {
|
||||
const command = `
|
||||
echo "📦 [Enabled Registry] Uploading image to '${registry.registryType}' | '${registryTag}'" >> ${logPath};
|
||||
docker login ${finalURL} -u ${registry.username} -p ${registry.password} >> ${logPath} 2>> ${logPath} || {
|
||||
echo "❌ DockerHub Failed" >> ${logPath};
|
||||
exit 1;
|
||||
}
|
||||
echo "✅ DockerHub Login Success" >> ${logPath};
|
||||
docker tag ${imageName} ${registryTag} >> ${logPath} 2>> ${logPath} || {
|
||||
echo "❌ Error tagging image" >> ${logPath};
|
||||
exit 1;
|
||||
}
|
||||
echo "✅ Image Tagged" >> ${logPath};
|
||||
|
||||
docker push ${registryTag} 2>> ${logPath} || {
|
||||
echo "❌ Error pushing image" >> ${logPath};
|
||||
exit 1;
|
||||
}
|
||||
echo "✅ Image Pushed" >> ${logPath};
|
||||
`;
|
||||
return command;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { InferResultType } from "@/server/types/with";
|
||||
import type { InferResultType } from "@dokploy/server/types/with";
|
||||
import type { CreateServiceOptions } from "dockerode";
|
||||
import {
|
||||
calculateResources,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { InferResultType } from "@/server/types/with";
|
||||
import type { InferResultType } from "@dokploy/server/types/with";
|
||||
import type { CreateServiceOptions } from "dockerode";
|
||||
import {
|
||||
calculateResources,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { InferResultType } from "@/server/types/with";
|
||||
import type { InferResultType } from "@dokploy/server/types/with";
|
||||
import type { CreateServiceOptions } from "dockerode";
|
||||
import {
|
||||
calculateResources,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { InferResultType } from "@/server/types/with";
|
||||
import type { InferResultType } from "@dokploy/server/types/with";
|
||||
import type { CreateServiceOptions } from "dockerode";
|
||||
import {
|
||||
calculateResources,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { InferResultType } from "@/server/types/with";
|
||||
import type { InferResultType } from "@dokploy/server/types/with";
|
||||
import type { CreateServiceOptions } from "dockerode";
|
||||
import {
|
||||
calculateResources,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import crypto from "node:crypto";
|
||||
import { findComposeById } from "@/server/services/compose";
|
||||
import { findComposeById } from "@dokploy/server/services/compose";
|
||||
import { dump, load } from "js-yaml";
|
||||
import { addSuffixToAllConfigs } from "./compose/configs";
|
||||
import { addSuffixToAllNetworks } from "./compose/network";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import fs, { existsSync, readFileSync } from "node:fs";
|
||||
import { writeFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import type { Compose } from "@/server/services/compose";
|
||||
import type { Domain } from "@/server/services/domain";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import type { Compose } from "@dokploy/server/services/compose";
|
||||
import type { Domain } from "@dokploy/server/services/domain";
|
||||
import { dump, load } from "js-yaml";
|
||||
import { execAsyncRemote } from "../process/execAsync";
|
||||
import {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import type { Readable } from "node:stream";
|
||||
import { docker, paths } from "@/server/constants";
|
||||
import { docker, paths } from "@dokploy/server/constants";
|
||||
import type { ContainerInfo, ResourceRequirements } from "dockerode";
|
||||
import { parse } from "dotenv";
|
||||
import type { ApplicationNested } from "../builders";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs, { promises as fsPromises } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import type { Application } from "@/server/services/application";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import type { Application } from "@dokploy/server/services/application";
|
||||
import { execAsync, execAsyncRemote } from "../process/execAsync";
|
||||
|
||||
export const recreateDirectory = async (pathFolder: string): Promise<void> => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { db } from "@/server/db";
|
||||
import { notifications } from "@/server/db/schema";
|
||||
import BuildFailedEmail from "@/server/emails/emails/build-failed";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { notifications } from "@dokploy/server/db/schema";
|
||||
import BuildFailedEmail from "@dokploy/server/emails/emails/build-failed";
|
||||
import { renderAsync } from "@react-email/components";
|
||||
import { eq } from "drizzle-orm";
|
||||
import {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { db } from "@/server/db";
|
||||
import { notifications } from "@/server/db/schema";
|
||||
import BuildSuccessEmail from "@/server/emails/emails/build-success";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { notifications } from "@dokploy/server/db/schema";
|
||||
import BuildSuccessEmail from "@dokploy/server/emails/emails/build-success";
|
||||
import { renderAsync } from "@react-email/components";
|
||||
import { eq } from "drizzle-orm";
|
||||
import {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { db } from "@/server/db";
|
||||
import { notifications } from "@/server/db/schema";
|
||||
import DatabaseBackupEmail from "@/server/emails/emails/database-backup";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { notifications } from "@dokploy/server/db/schema";
|
||||
import DatabaseBackupEmail from "@dokploy/server/emails/emails/database-backup";
|
||||
import { renderAsync } from "@react-email/components";
|
||||
import { eq } from "drizzle-orm";
|
||||
import {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { db } from "@/server/db";
|
||||
import { notifications } from "@/server/db/schema";
|
||||
import DockerCleanupEmail from "@/server/emails/emails/docker-cleanup";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { notifications } from "@dokploy/server/db/schema";
|
||||
import DockerCleanupEmail from "@dokploy/server/emails/emails/docker-cleanup";
|
||||
import { renderAsync } from "@react-email/components";
|
||||
import { eq } from "drizzle-orm";
|
||||
import {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { db } from "@/server/db";
|
||||
import { notifications } from "@/server/db/schema";
|
||||
import DokployRestartEmail from "@/server/emails/emails/dokploy-restart";
|
||||
import { db } from "@dokploy/server/db";
|
||||
import { notifications } from "@dokploy/server/db/schema";
|
||||
import DokployRestartEmail from "@dokploy/server/emails/emails/dokploy-restart";
|
||||
import { renderAsync } from "@react-email/components";
|
||||
import { eq } from "drizzle-orm";
|
||||
import {
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import type { discord, email, slack, telegram } from "@/server/db/schema";
|
||||
import type {
|
||||
discord,
|
||||
email,
|
||||
slack,
|
||||
telegram,
|
||||
} from "@dokploy/server/db/schema";
|
||||
import nodemailer from "nodemailer";
|
||||
|
||||
export const sendEmailNotification = async (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { exec } from "node:child_process";
|
||||
import util from "node:util";
|
||||
import { findServerById } from "@/server/services/server";
|
||||
import { findServerById } from "@dokploy/server/services/server";
|
||||
import { Client } from "ssh2";
|
||||
export const execAsync = util.promisify(exec);
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { createWriteStream } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import type {
|
||||
apiBitbucketTestConnection,
|
||||
apiFindBitbucketBranches,
|
||||
} from "@/server/db/schema";
|
||||
import { findBitbucketById } from "@/server/services/bitbucket";
|
||||
import type { Compose } from "@/server/services/compose";
|
||||
import type { InferResultType } from "@/server/types/with";
|
||||
} from "@dokploy/server/db/schema";
|
||||
import { findBitbucketById } from "@dokploy/server/services/bitbucket";
|
||||
import type { Compose } from "@dokploy/server/services/compose";
|
||||
import type { InferResultType } from "@dokploy/server/types/with";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { recreateDirectory } from "../filesystem/directory";
|
||||
import { execAsyncRemote } from "../process/execAsync";
|
||||
@@ -227,42 +227,42 @@ export const getBitbucketRepositories = async (bitbucketId?: string) => {
|
||||
const username =
|
||||
bitbucketProvider.bitbucketWorkspaceName ||
|
||||
bitbucketProvider.bitbucketUsername;
|
||||
const url = `https://api.bitbucket.org/2.0/repositories/${username}?pagelen=100`;
|
||||
let url = `https://api.bitbucket.org/2.0/repositories/${username}?pagelen=100`;
|
||||
let repositories: {
|
||||
name: string;
|
||||
url: string;
|
||||
owner: { username: string };
|
||||
}[] = [];
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `Basic ${Buffer.from(`${bitbucketProvider.bitbucketUsername}:${bitbucketProvider.appPassword}`).toString("base64")}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: `Failed to fetch repositories: ${response.statusText}`,
|
||||
while (url) {
|
||||
const response = await fetch(url, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `Basic ${Buffer.from(`${bitbucketProvider.bitbucketUsername}:${bitbucketProvider.appPassword}`).toString("base64")}`,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
if (!response.ok) {
|
||||
throw new TRPCError({
|
||||
code: "BAD_REQUEST",
|
||||
message: `Failed to fetch repositories: ${response.statusText}`,
|
||||
});
|
||||
}
|
||||
|
||||
const mappedData = data.values.map((repo: any) => {
|
||||
return {
|
||||
const data = await response.json();
|
||||
|
||||
const mappedData = data.values.map((repo: any) => ({
|
||||
name: repo.name,
|
||||
url: repo.links.html.href,
|
||||
owner: {
|
||||
username: repo.workspace.slug,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return mappedData as {
|
||||
name: string;
|
||||
url: string;
|
||||
owner: {
|
||||
username: string;
|
||||
};
|
||||
}[];
|
||||
}));
|
||||
repositories = repositories.concat(mappedData);
|
||||
url = data.next || null;
|
||||
}
|
||||
return repositories;
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { createWriteStream } from "node:fs";
|
||||
import path, { join } from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import type { Compose } from "@/server/services/compose";
|
||||
import { findSSHKeyById, updateSSHKeyById } from "@/server/services/ssh-key";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import type { Compose } from "@dokploy/server/services/compose";
|
||||
import {
|
||||
findSSHKeyById,
|
||||
updateSSHKeyById,
|
||||
} from "@dokploy/server/services/ssh-key";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { recreateDirectory } from "../filesystem/directory";
|
||||
import { execAsync, execAsyncRemote } from "../process/execAsync";
|
||||
@@ -55,8 +58,6 @@ export const cloneGitRepository = async (
|
||||
await addHostToKnownHosts(customGitUrl);
|
||||
}
|
||||
await recreateDirectory(outputPath);
|
||||
// const command = `GIT_SSH_COMMAND="ssh -i ${keyPath} -o UserKnownHostsFile=${knownHostsPath}" git clone --branch ${customGitBranch} --depth 1 ${customGitUrl} ${gitCopyPath} --progress`;
|
||||
// const { stdout, stderr } = await execAsync(command);
|
||||
writeStream.write(
|
||||
`\nCloning Repo Custom ${customGitUrl} to ${outputPath}: ✅\n`,
|
||||
);
|
||||
@@ -187,7 +188,6 @@ export const getCustomGitCloneCommand = async (
|
||||
command.push(`echo "Cloned Custom Git ${customGitUrl}: ✅" >> ${logPath};`);
|
||||
return command.join("\n");
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { createWriteStream } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import type { InferResultType } from "@/server/types/with";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import type { InferResultType } from "@dokploy/server/types/with";
|
||||
import { createAppAuth } from "@octokit/auth-app";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { Octokit } from "octokit";
|
||||
import { recreateDirectory } from "../filesystem/directory";
|
||||
import { spawnAsync } from "../process/spawnAsync";
|
||||
|
||||
import type { apiFindGithubBranches } from "@/server/db/schema";
|
||||
import type { Compose } from "@/server/services/compose";
|
||||
import { type Github, findGithubById } from "@/server/services/github";
|
||||
import type { apiFindGithubBranches } from "@dokploy/server/db/schema";
|
||||
import type { Compose } from "@dokploy/server/services/compose";
|
||||
import { type Github, findGithubById } from "@dokploy/server/services/github";
|
||||
import { execAsyncRemote } from "../process/execAsync";
|
||||
|
||||
export const authGithub = (githubProvider: Github): Octokit => {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { createWriteStream } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import type { apiGitlabTestConnection } from "@/server/db/schema";
|
||||
import type { Compose } from "@/server/services/compose";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import type { apiGitlabTestConnection } from "@dokploy/server/db/schema";
|
||||
import type { Compose } from "@dokploy/server/services/compose";
|
||||
import {
|
||||
type Gitlab,
|
||||
findGitlabById,
|
||||
updateGitlab,
|
||||
} from "@/server/services/gitlab";
|
||||
import type { InferResultType } from "@/server/types/with";
|
||||
} from "@dokploy/server/services/gitlab";
|
||||
import type { InferResultType } from "@dokploy/server/types/with";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
import { recreateDirectory } from "../filesystem/directory";
|
||||
import { execAsyncRemote } from "../process/execAsync";
|
||||
@@ -47,8 +47,6 @@ export const refreshGitlabToken = async (gitlabProviderId: string) => {
|
||||
|
||||
const expiresAt = Math.floor(Date.now() / 1000) + data.expires_in;
|
||||
|
||||
console.log("Refreshed token");
|
||||
|
||||
await updateGitlab(gitlabProviderId, {
|
||||
accessToken: data.access_token,
|
||||
refreshToken: data.refresh_token,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createWriteStream } from "node:fs";
|
||||
import { writeFile } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import type { Compose } from "@/server/services/compose";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import type { Compose } from "@dokploy/server/services/compose";
|
||||
import { encodeBase64 } from "../docker/utils";
|
||||
import { recreateDirectory } from "../filesystem/directory";
|
||||
import { execAsyncRemote } from "../process/execAsync";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { docker } from "@/server/constants";
|
||||
import { findServerById } from "@/server/services/server";
|
||||
import { docker } from "@dokploy/server/constants";
|
||||
import { findServerById } from "@dokploy/server/services/server";
|
||||
import Dockerode from "dockerode";
|
||||
|
||||
export const getRemoteDocker = async (serverId?: string | null) => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs, { writeFileSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import type { Domain } from "@/server/services/domain";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import type { Domain } from "@dokploy/server/services/domain";
|
||||
import { dump, load } from "js-yaml";
|
||||
import { encodeBase64 } from "../docker/utils";
|
||||
import { execAsyncRemote } from "../process/execAsync";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Domain } from "@/server/services/domain";
|
||||
import type { Domain } from "@dokploy/server/services/domain";
|
||||
import type { ApplicationNested } from "../builders";
|
||||
import {
|
||||
createServiceConfig,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import { dump, load } from "js-yaml";
|
||||
import type { ApplicationNested } from "../builders";
|
||||
import { execAsyncRemote } from "../process/execAsync";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Redirect } from "@/server/services/redirect";
|
||||
import type { Redirect } from "@dokploy/server/services/redirect";
|
||||
import type { ApplicationNested } from "../builders";
|
||||
import {
|
||||
loadOrCreateConfig,
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import type { Registry } from "@/server/services/registry";
|
||||
import { dump, load } from "js-yaml";
|
||||
import { removeDirectoryIfExistsContent } from "../filesystem/directory";
|
||||
import type { FileConfig, HttpRouter } from "./file-types";
|
||||
|
||||
export const manageRegistry = async (registry: Registry) => {
|
||||
const { REGISTRY_PATH } = paths();
|
||||
if (!existsSync(REGISTRY_PATH)) {
|
||||
mkdirSync(REGISTRY_PATH, { recursive: true });
|
||||
}
|
||||
|
||||
const appName = "dokploy-registry";
|
||||
const config: FileConfig = loadOrCreateConfig();
|
||||
|
||||
const serviceName = `${appName}-service`;
|
||||
const routerName = `${appName}-router`;
|
||||
|
||||
config.http = config.http || { routers: {}, services: {} };
|
||||
config.http.routers = config.http.routers || {};
|
||||
config.http.services = config.http.services || {};
|
||||
|
||||
config.http.routers[routerName] = await createRegistryRouterConfig(registry);
|
||||
|
||||
config.http.services[serviceName] = {
|
||||
loadBalancer: {
|
||||
servers: [{ url: `http://${appName}:5000` }],
|
||||
passHostHeader: true,
|
||||
},
|
||||
};
|
||||
|
||||
const yamlConfig = dump(config);
|
||||
const configFile = join(REGISTRY_PATH, "registry.yml");
|
||||
writeFileSync(configFile, yamlConfig);
|
||||
};
|
||||
|
||||
export const removeSelfHostedRegistry = async () => {
|
||||
const { REGISTRY_PATH } = paths();
|
||||
await removeDirectoryIfExistsContent(REGISTRY_PATH);
|
||||
};
|
||||
|
||||
const createRegistryRouterConfig = async (registry: Registry) => {
|
||||
const { registryUrl } = registry;
|
||||
const routerConfig: HttpRouter = {
|
||||
rule: `Host(\`${registryUrl}\`)`,
|
||||
service: "dokploy-registry-service",
|
||||
middlewares: ["redirect-to-https"],
|
||||
entryPoints: [
|
||||
"web",
|
||||
...(process.env.NODE_ENV === "production" ? ["websecure"] : []),
|
||||
],
|
||||
...(process.env.NODE_ENV === "production"
|
||||
? {
|
||||
tls: { certResolver: "letsencrypt" },
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
|
||||
return routerConfig;
|
||||
};
|
||||
|
||||
const loadOrCreateConfig = (): FileConfig => {
|
||||
const { REGISTRY_PATH } = paths();
|
||||
const configPath = join(REGISTRY_PATH, "registry.yml");
|
||||
if (existsSync(configPath)) {
|
||||
const yamlStr = readFileSync(configPath, "utf8");
|
||||
const parsedConfig = (load(yamlStr) as FileConfig) || {
|
||||
http: { routers: {}, services: {} },
|
||||
};
|
||||
return parsedConfig;
|
||||
}
|
||||
return { http: { routers: {}, services: {} } };
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Security } from "@/server/services/security";
|
||||
import type { Security } from "@dokploy/server/services/security";
|
||||
import * as bcrypt from "bcrypt";
|
||||
import type { ApplicationNested } from "../builders";
|
||||
import {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
import { paths } from "@/server/constants";
|
||||
import type { Admin } from "@/server/services/admin";
|
||||
import { paths } from "@dokploy/server/constants";
|
||||
import type { Admin } from "@dokploy/server/services/admin";
|
||||
import { dump, load } from "js-yaml";
|
||||
import { loadOrCreateConfig, writeTraefikConfig } from "./application";
|
||||
import type { FileConfig } from "./file-types";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type http from "node:http";
|
||||
import { findServerById } from "@/server/services/server";
|
||||
import { findServerById } from "@dokploy/server/services/server";
|
||||
import { spawn } from "node-pty";
|
||||
import { Client } from "ssh2";
|
||||
import { WebSocketServer } from "ws";
|
||||
@@ -64,7 +64,6 @@ export const setupDockerContainerLogsWebSocketServer = (
|
||||
}
|
||||
stream
|
||||
.on("close", () => {
|
||||
console.log("Connection closed ✅");
|
||||
client.end();
|
||||
resolve();
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type http from "node:http";
|
||||
import { findServerById } from "@/server/services/server";
|
||||
import { findServerById } from "@dokploy/server/services/server";
|
||||
import { spawn } from "node-pty";
|
||||
import { Client } from "ssh2";
|
||||
import { WebSocketServer } from "ws";
|
||||
@@ -63,9 +63,6 @@ export const setupDockerContainerTerminalWebSocketServer = (
|
||||
|
||||
stream
|
||||
.on("close", (code: number, signal: string) => {
|
||||
console.log(
|
||||
`Stream :: close :: code: ${code}, signal: ${signal}`,
|
||||
);
|
||||
ws.send(`\nContainer closed with code: ${code}\n`);
|
||||
conn.end();
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { spawn } from "node:child_process";
|
||||
import type http from "node:http";
|
||||
import { findServerById } from "@/server/services/server";
|
||||
import { findServerById } from "@dokploy/server/services/server";
|
||||
import { Client } from "ssh2";
|
||||
import { WebSocketServer } from "ws";
|
||||
import { validateWebSocketRequest } from "../auth/auth";
|
||||
@@ -33,7 +33,6 @@ export const setupDeploymentLogsWebSocketServer = (
|
||||
const { user, session } = await validateWebSocketRequest(req);
|
||||
|
||||
if (!logPath) {
|
||||
console.log("logPath no provided");
|
||||
ws.close(4000, "logPath no provided");
|
||||
return;
|
||||
}
|
||||
@@ -63,7 +62,6 @@ export const setupDeploymentLogsWebSocketServer = (
|
||||
}
|
||||
stream
|
||||
.on("close", () => {
|
||||
console.log("Connection closed ✅");
|
||||
client.end();
|
||||
resolve();
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type http from "node:http";
|
||||
import path from "node:path";
|
||||
import { findServerById } from "@/server/services/server";
|
||||
import { findServerById } from "@dokploy/server/services/server";
|
||||
import { spawn } from "node-pty";
|
||||
import { publicIpv4, publicIpv6 } from "public-ip";
|
||||
import { WebSocketServer } from "ws";
|
||||
|
||||
Reference in New Issue
Block a user