diff --git a/.gitignore b/.gitignore index 71a3816e..bfbda236 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ .pnp.js /redis-data traefik.yml +.docker +.env.production # testing /coverage diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8d0a2d44..84c57c7f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -54,7 +54,7 @@ feat: add new feature ```bash git clone https://github.com/dokploy/dokploy.git cd dokploy -npm install +pnpm install cp .env.example .env ``` @@ -62,28 +62,40 @@ cp .env.example .env Is required to have **Docker** installed on your machine. + +### Setup + +Run the command that will spin up all the required services and files. + ```bash -npm run dev +pnpm run setup ``` +Now run the development server. + +```bash +pnpm run dev +``` + + Go to http://localhost:3000 to see the development server ## Build ```bash -npm run build +pnpm run build ``` ## Docker To build the docker image ```bash -npm run docker:build +pnpm run docker:build ``` To push the docker image ```bash -npm run docker:push +pnpm run docker:push ``` ## Password Reset diff --git a/components/auth/login-2fa.tsx b/components/auth/login-2fa.tsx index 46d82cbe..17b2d483 100644 --- a/components/auth/login-2fa.tsx +++ b/components/auth/login-2fa.tsx @@ -65,7 +65,7 @@ export const Login2FA = ({ authId }: Props) => { duration: 2000, }); - push("/dashboard"); + push("/dashboard/projects"); }) .catch(() => { toast.error("Signin failed", { diff --git a/migration.ts b/migration.ts new file mode 100644 index 00000000..ff1b31d0 --- /dev/null +++ b/migration.ts @@ -0,0 +1,20 @@ +import { drizzle } from "drizzle-orm/postgres-js"; +import { migrate } from "drizzle-orm/postgres-js/migrator"; +import postgres from "postgres"; + +const connectionString = process.env.DATABASE_URL || ""; + +const sql = postgres(connectionString, { max: 1 }); +const db = drizzle(sql); + +await migrate(db, { migrationsFolder: "drizzle" }) + .then(() => { + console.log("Migration complete"); + sql.end(); + }) + .catch((error) => { + console.log("Migration failed", error); + }) + .finally(() => { + sql.end(); + }); diff --git a/package.json b/package.json index 5b66a28c..5a6cdfd9 100644 --- a/package.json +++ b/package.json @@ -9,12 +9,14 @@ "start": "node dist/server.mjs", "build-server": "tsx esbuild.config.ts", "build-next": "next build", + "setup": "tsx -r dotenv/config setup.ts && sleep 5 && pnpm run migration:run", "reset-password": "node dist/reset-password.mjs", "dev": "tsx watch -r dotenv/config ./server/server.ts --project tsconfig.server.json ", "migration:generate": "drizzle-kit generate:pg --config ./server/db/drizzle.config.ts", "migration:run": "tsx -r dotenv/config migration.ts", "migration:drop": "drizzle-kit drop --config ./server/db/drizzle.config.ts", "db:push": "drizzle-kit push:pg --config ./server/db/drizzle.config.ts", + "db:truncate": "tsx -r dotenv/config ./server/db/reset.ts", "db:studio": "drizzle-kit studio", "lint": "biome lint", "db:seed": "dotenv tsx ./server/db/seed.ts", @@ -127,6 +129,7 @@ "initVersion": "7.25.2" }, "engines": { - "node": "18.x" - } + "node": "^18.18.0", + "pnpm": "^8.15.4" +} } diff --git a/pages/dashboard/project/[projectId]/services/application/[applicationId].tsx b/pages/dashboard/project/[projectId]/services/application/[applicationId].tsx index 33e4dd08..2ea8a8cc 100644 --- a/pages/dashboard/project/[projectId]/services/application/[applicationId].tsx +++ b/pages/dashboard/project/[projectId]/services/application/[applicationId].tsx @@ -242,7 +242,7 @@ export async function getServerSideProps( return { redirect: { permanent: false, - destination: "/dashboard", + destination: "/dashboard/projects", }, }; } diff --git a/pages/dashboard/project/[projectId]/services/mariadb/[mariadbId].tsx b/pages/dashboard/project/[projectId]/services/mariadb/[mariadbId].tsx index 2f9d4cf3..a820b940 100644 --- a/pages/dashboard/project/[projectId]/services/mariadb/[mariadbId].tsx +++ b/pages/dashboard/project/[projectId]/services/mariadb/[mariadbId].tsx @@ -211,7 +211,7 @@ export async function getServerSideProps( return { redirect: { permanent: false, - destination: "/dashboard", + destination: "/dashboard/projects", }, }; } diff --git a/pages/dashboard/project/[projectId]/services/mongo/[mongoId].tsx b/pages/dashboard/project/[projectId]/services/mongo/[mongoId].tsx index 2b88686c..9d7f6eac 100644 --- a/pages/dashboard/project/[projectId]/services/mongo/[mongoId].tsx +++ b/pages/dashboard/project/[projectId]/services/mongo/[mongoId].tsx @@ -213,7 +213,7 @@ export async function getServerSideProps( return { redirect: { permanent: false, - destination: "/dashboard", + destination: "/dashboard/projects", }, }; } diff --git a/pages/dashboard/project/[projectId]/services/mysql/[mysqlId].tsx b/pages/dashboard/project/[projectId]/services/mysql/[mysqlId].tsx index 095fcd6c..e5c191b6 100644 --- a/pages/dashboard/project/[projectId]/services/mysql/[mysqlId].tsx +++ b/pages/dashboard/project/[projectId]/services/mysql/[mysqlId].tsx @@ -212,7 +212,7 @@ export async function getServerSideProps( return { redirect: { permanent: false, - destination: "/dashboard", + destination: "/dashboard/projects", }, }; } diff --git a/pages/dashboard/project/[projectId]/services/postgres/[postgresId].tsx b/pages/dashboard/project/[projectId]/services/postgres/[postgresId].tsx index 222a7298..9d1cda3d 100644 --- a/pages/dashboard/project/[projectId]/services/postgres/[postgresId].tsx +++ b/pages/dashboard/project/[projectId]/services/postgres/[postgresId].tsx @@ -212,7 +212,7 @@ export async function getServerSideProps( return { redirect: { permanent: false, - destination: "/dashboard", + destination: "/dashboard/projects", }, }; } diff --git a/pages/dashboard/project/[projectId]/services/redis/[redisId].tsx b/pages/dashboard/project/[projectId]/services/redis/[redisId].tsx index e2200133..f6acf186 100644 --- a/pages/dashboard/project/[projectId]/services/redis/[redisId].tsx +++ b/pages/dashboard/project/[projectId]/services/redis/[redisId].tsx @@ -205,7 +205,7 @@ export async function getServerSideProps( return { redirect: { permanent: false, - destination: "/dashboard", + destination: "/dashboard/projects", }, }; } diff --git a/pages/dashboard/settings/server.tsx b/pages/dashboard/settings/server.tsx index c08b607a..8eedf299 100644 --- a/pages/dashboard/settings/server.tsx +++ b/pages/dashboard/settings/server.tsx @@ -38,7 +38,6 @@ export async function getServerSideProps( }, }; } - console.log(user); if (user.rol === "user") { return { redirect: { diff --git a/server/constants/index.ts b/server/constants/index.ts index fe3f9fa6..4c7cd5a5 100644 --- a/server/constants/index.ts +++ b/server/constants/index.ts @@ -1,6 +1,10 @@ import Docker from "dockerode"; +import path from "node:path"; -export const BASE_PATH = "/etc/dokploy"; +export const BASE_PATH = + process.env.NODE_ENV === "production" + ? "/etc/dokploy" + : path.join(process.cwd(), ".docker"); export const MAIN_TRAEFIK_PATH = `${BASE_PATH}/traefik`; export const DYNAMIC_TRAEFIK_PATH = `${BASE_PATH}/traefik/dynamic`; export const LOGS_PATH = `${BASE_PATH}/logs`; diff --git a/server/db/reset.ts b/server/db/reset.ts index 108c1d19..dc731a20 100644 --- a/server/db/reset.ts +++ b/server/db/reset.ts @@ -10,9 +10,10 @@ const db = drizzle(pg); const clearDb = async (): Promise => { try { - const tablesQuery = sql`DROP SCHEMA public CASCADE; CREATE SCHEMA public;`; + const tablesQuery = sql`DROP SCHEMA public CASCADE; CREATE SCHEMA public; DROP schema drizzle CASCADE;`; const tables = await db.execute(tablesQuery); console.log(tables); + await pg.end(); } catch (error) { console.error("Error to clean database", error); } finally { diff --git a/server/server.ts b/server/server.ts index 92c788ac..20af88ad 100644 --- a/server/server.ts +++ b/server/server.ts @@ -34,31 +34,32 @@ void app.prepare().then(async () => { handle(req, res); }); - setupDirectories(); - createDefaultMiddlewares(); - await initializeNetwork(); - await initializeSwarm(); - createDefaultTraefikConfig(); - createDefaultServerTraefikConfig(); - await initializeTraefik(); - await initializeRedis(); - await initializePostgres(); - // WEBSOCKET setupDeploymentLogsWebSocketServer(server); setupDockerContainerLogsWebSocketServer(server); setupDockerContainerTerminalWebSocketServer(server); setupTerminalWebSocketServer(server); setupDockerStatsMonitoringSocketServer(server); + if (process.env.NODE_ENV === "production") { - // Cron Jobs + setupDirectories(); + createDefaultMiddlewares(); + await initializeSwarm(); + await initializeNetwork(); + createDefaultTraefikConfig(); + createDefaultServerTraefikConfig(); + await initializeTraefik(); + await initializeRedis(); + await initializePostgres(); initCronJobs(); welcomeServer(); + // Timeout to wait for the database to be ready await new Promise((resolve) => setTimeout(resolve, 7000)); await migration(); } server.listen(PORT); + console.log("Server Started:", PORT); deploymentWorker.run(); } catch (e) { console.error("Main Server Error", e); diff --git a/server/setup/postgres-setup.ts b/server/setup/postgres-setup.ts index dbdaaa29..ce5bfccc 100644 --- a/server/setup/postgres-setup.ts +++ b/server/setup/postgres-setup.ts @@ -56,7 +56,6 @@ export const initializePostgres = async () => { console.log("Postgres Started ✅"); } catch (error) { - console.log(error); await docker.createService(settings); console.log("Postgres Not Found: Starting ✅"); } diff --git a/server/setup/setup.ts b/server/setup/setup.ts index dd693e04..c5987702 100644 --- a/server/setup/setup.ts +++ b/server/setup/setup.ts @@ -19,7 +19,6 @@ export const dockerSwarmInitialized = async () => { return true; } catch (e) { - console.log(e); return false; } }; diff --git a/server/setup/traefik-setup.ts b/server/setup/traefik-setup.ts index 55abe3db..916495fa 100644 --- a/server/setup/traefik-setup.ts +++ b/server/setup/traefik-setup.ts @@ -133,7 +133,7 @@ export const createDefaultTraefikConfig = () => { }, }), file: { - directory: DYNAMIC_TRAEFIK_PATH, + directory: "/etc/dokploy/traefik/dynamic", watch: true, }, }, diff --git a/setup.ts b/setup.ts new file mode 100644 index 00000000..09eb57bb --- /dev/null +++ b/setup.ts @@ -0,0 +1,26 @@ +import { + createDefaultMiddlewares, + createDefaultServerTraefikConfig, + createDefaultTraefikConfig, + initializeTraefik, +} from "./server/setup/traefik-setup"; +import { initializeRedis } from "./server/setup/redis-setup"; +import { initializePostgres } from "./server/setup/postgres-setup"; +import { setupDirectories } from "./server/setup/config-paths"; +import { initializeNetwork, initializeSwarm } from "./server/setup/setup"; + +(async () => { + try { + setupDirectories(); + createDefaultMiddlewares(); + await initializeSwarm(); + await initializeNetwork(); + createDefaultTraefikConfig(); + createDefaultServerTraefikConfig(); + await initializeTraefik(); + await initializeRedis(); + await initializePostgres(); + } catch (e) { + console.error("Error to setup dokploy", e); + } +})(); diff --git a/tsconfig.json b/tsconfig.json index e766f6a2..bad94c9c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -39,5 +39,5 @@ ".next/types/**/*.ts", "env.js" , "next.config.mjs" ], - "exclude": ["node_modules", "dokploy", "config", "dist","webpack.config.server.js"] + "exclude": ["node_modules", "dokploy", "config", "dist","webpack.config.server.js","migration.ts","setup.ts"] }