Merge branch 'canary' into feat/shared-ssh

This commit is contained in:
Mauricio Siu
2024-07-26 01:14:55 -06:00
committed by GitHub
21 changed files with 253 additions and 427 deletions

View File

@@ -1,8 +1,8 @@
import { domain } from "@/server/db/validations";
import { relations } from "drizzle-orm";
import { boolean, integer, pgTable, serial, text } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { nanoid } from "nanoid";
import { z } from "zod";
import { applications } from "./application";
import { certificateType } from "./shared";
@@ -31,27 +31,17 @@ export const domainsRelations = relations(domains, ({ one }) => ({
references: [applications.applicationId],
}),
}));
const hostnameRegex = /^[a-zA-Z0-9][a-zA-Z0-9\.-]*\.[a-zA-Z]{2,}$/;
const createSchema = createInsertSchema(domains, {
domainId: z.string().min(1),
host: z.string().min(1),
path: z.string().min(1),
port: z.number(),
https: z.boolean(),
applicationId: z.string(),
certificateType: z.enum(["letsencrypt", "none"]),
});
export const apiCreateDomain = createSchema
.pick({
host: true,
path: true,
port: true,
https: true,
applicationId: true,
certificateType: true,
})
.required();
const createSchema = createInsertSchema(domains, domain._def.schema.shape);
export const apiCreateDomain = createSchema.pick({
host: true,
path: true,
port: true,
https: true,
applicationId: true,
certificateType: true,
});
export const apiFindDomain = createSchema
.pick({
@@ -59,19 +49,16 @@ export const apiFindDomain = createSchema
})
.required();
export const apiFindDomainByApplication = createSchema
.pick({
applicationId: true,
})
.required();
export const apiFindDomainByApplication = createSchema.pick({
applicationId: true,
});
export const apiUpdateDomain = createSchema
.pick({
domainId: true,
host: true,
path: true,
port: true,
https: true,
certificateType: true,
})
.required();
.merge(createSchema.pick({ domainId: true }).required());

View File

@@ -33,3 +33,28 @@ export const sshKeyUpdate = sshKeyCreate.pick({
});
export const sshKeyType = z.enum(["rsa", "ed25519"]).optional();
export const domain = z
.object({
host: z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9\.-]*\.[a-zA-Z]{2,}$/, {
message: "Invalid hostname",
}),
path: z.string().min(1).optional(),
port: z
.number()
.min(1, { message: "Port must be at least 1" })
.max(65535, { message: "Port must be 65535 or below" })
.optional(),
https: z.boolean().optional(),
certificateType: z.enum(["letsencrypt", "none"]).optional(),
})
.superRefine((input, ctx) => {
if (input.https && !input.certificateType) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ["certificateType"],
message: "Required",
});
}
});

View File

@@ -1,4 +1,4 @@
import { existsSync, mkdirSync } from "node:fs";
import { chmodSync, existsSync, mkdirSync } from "node:fs";
import {
APPLICATIONS_PATH,
BASE_PATH,
@@ -32,6 +32,9 @@ export const setupDirectories = () => {
for (const dir of directories) {
try {
createDirectoryIfNotExist(dir);
if (dir === SSH_PATH) {
chmodSync(SSH_PATH, "600");
}
} catch (error) {
console.log(error, " On path: ", dir);
}

View File

@@ -1,4 +1,4 @@
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
import { chmodSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
import path from "node:path";
import type { CreateServiceOptions } from "dockerode";
import { dump } from "js-yaml";
@@ -86,6 +86,7 @@ export const initializeTraefik = async () => {
export const createDefaultServerTraefikConfig = () => {
const configFilePath = path.join(DYNAMIC_TRAEFIK_PATH, "dokploy.yml");
if (existsSync(configFilePath)) {
console.log("Default traefik config already exists");
return;
@@ -125,6 +126,11 @@ export const createDefaultServerTraefikConfig = () => {
export const createDefaultTraefikConfig = () => {
const mainConfig = path.join(MAIN_TRAEFIK_PATH, "traefik.yml");
const acmeJsonPath = path.join(DYNAMIC_TRAEFIK_PATH, "acme.json");
if (existsSync(acmeJsonPath)) {
chmodSync(acmeJsonPath, "600");
}
if (existsSync(mainConfig)) {
console.log("Main config already exists");
return;

View File

@@ -1,9 +1,8 @@
import type { WriteStream } from "node:fs";
import { docker } from "@/server/constants";
import { prepareBuildArgs } from "@/server/utils/docker/utils";
import * as tar from "tar-fs";
import { prepareEnvironmentVariables } from "@/server/utils/docker/utils";
import type { ApplicationNested } from ".";
import { getBuildAppDirectory } from "../filesystem/directory";
import { spawnAsync } from "../process/spawnAsync";
import { createEnvFile } from "./utils";
export const buildCustomDocker = async (
@@ -14,29 +13,30 @@ export const buildCustomDocker = async (
const dockerFilePath = getBuildAppDirectory(application);
try {
const image = `${appName}`;
const contextPath =
dockerFilePath.substring(0, dockerFilePath.lastIndexOf("/") + 1) || ".";
const tarStream = tar.pack(contextPath);
const args = prepareEnvironmentVariables(buildArgs);
const commandArgs = ["build", "-t", image, "-f", dockerFilePath, "."];
for (const arg of args) {
commandArgs.push("--build-arg", arg);
}
createEnvFile(dockerFilePath, env);
const stream = await docker.buildImage(tarStream, {
t: image,
buildargs: prepareBuildArgs(buildArgs),
dockerfile: dockerFilePath.substring(dockerFilePath.lastIndexOf("/") + 1),
});
await new Promise((resolve, reject) => {
docker.modem.followProgress(
stream,
(err, res) => (err ? reject(err) : resolve(res)),
(event) => {
if (event.stream) {
writeStream.write(event.stream);
}
},
);
});
await spawnAsync(
"docker",
commandArgs,
(data) => {
if (writeStream.writable) {
writeStream.write(data);
}
},
{
cwd: contextPath,
},
);
} catch (error) {
throw error;
}