From 021d957016eae3d9621851edb621255b904a3339 Mon Sep 17 00:00:00 2001 From: Yuki <60097976+binaryYuki@users.noreply.github.com> Date: Sat, 21 Dec 2024 12:59:07 +0000 Subject: [PATCH 1/2] Enhance security by changing default host and adding rate-limiting Enhance server security by defaulting to 127.0.0.1:3000 and adding rate-limiting. * Change the default host to `127.0.0.1` in `apps/api/src/index.ts` and `apps/dokploy/server/server.ts`. * Add a rate-limiting middleware to the `app` instance in `apps/api/src/index.ts`. * Introduce an environment variable `EXPOSE_ALL_INTERFACES` to toggle exposing `0.0.0.0` in `apps/dokploy/server/server.ts` and `apps/dokploy/.env.example`. * Add a toggle for `EXPOSE_ALL_INTERFACES` in the `WebServer` component in `apps/dokploy/components/dashboard/settings/web-server.tsx` with a warning about the associated risks. --- apps/api/src/index.ts | 12 +++++++- apps/dokploy/.env.example | 3 +- .../dashboard/settings/web-server.tsx | 28 ++++++++++++++++++- apps/dokploy/server/server.ts | 3 +- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/apps/api/src/index.ts b/apps/api/src/index.ts index bf91b0400..7fe8cfe8d 100644 --- a/apps/api/src/index.ts +++ b/apps/api/src/index.ts @@ -7,12 +7,21 @@ import { createClient } from "redis"; import { logger } from "./logger"; import { type DeployJob, deployJobSchema } from "./schema"; import { deploy } from "./utils"; +import rateLimit from "express-rate-limit"; const app = new Hono(); const redisClient = createClient({ url: process.env.REDIS_URL, }); +const limiter = rateLimit({ + windowMs: 15 * 60 * 1000, // 15 minutes + max: 100, // limit each IP to 100 requests per windowMs + message: "Too many requests from this IP, please try again later.", +}); + +app.use(limiter); + app.use(async (c, next) => { if (c.req.path === "/health") { return next(); @@ -57,5 +66,6 @@ const queue = new Queue({ })(); const port = Number.parseInt(process.env.PORT || "3000"); +const host = process.env.EXPOSE_ALL_INTERFACES === "true" ? "0.0.0.0" : "127.0.0.1"; logger.info("Starting Deployments Server ✅", port); -serve({ fetch: app.fetch, port }); +serve({ fetch: app.fetch, port, host }); diff --git a/apps/dokploy/.env.example b/apps/dokploy/.env.example index ba57ec7be..acb49c7f8 100644 --- a/apps/dokploy/.env.example +++ b/apps/dokploy/.env.example @@ -1,3 +1,4 @@ DATABASE_URL="postgres://dokploy:amukds4wi9001583845717ad2@localhost:5432/dokploy" PORT=3000 -NODE_ENV=development \ No newline at end of file +NODE_ENV=development +EXPOSE_ALL_INTERFACES=false diff --git a/apps/dokploy/components/dashboard/settings/web-server.tsx b/apps/dokploy/components/dashboard/settings/web-server.tsx index 2ac88d9ae..14ba736c0 100644 --- a/apps/dokploy/components/dashboard/settings/web-server.tsx +++ b/apps/dokploy/components/dashboard/settings/web-server.tsx @@ -8,12 +8,14 @@ import { import { cn } from "@/lib/utils"; import { api } from "@/utils/api"; import { useTranslation } from "next-i18next"; -import React from "react"; +import React, { useState } from "react"; import { ShowDokployActions } from "./servers/actions/show-dokploy-actions"; import { ShowStorageActions } from "./servers/actions/show-storage-actions"; import { ShowTraefikActions } from "./servers/actions/show-traefik-actions"; import { ToggleDockerCleanup } from "./servers/actions/toggle-docker-cleanup"; import { UpdateServer } from "./web-server/update-server"; +import { Switch } from "@/components/ui/switch"; +import { Alert } from "@/components/ui/alert"; interface Props { className?: string; @@ -24,6 +26,14 @@ export const WebServer = ({ className }: Props) => { const { data: dokployVersion } = api.settings.getDokployVersion.useQuery(); + const [exposeAllInterfaces, setExposeAllInterfaces] = useState( + process.env.EXPOSE_ALL_INTERFACES === "true" + ); + + const handleToggleChange = () => { + setExposeAllInterfaces(!exposeAllInterfaces); + }; + return ( @@ -53,6 +63,22 @@ export const WebServer = ({ className }: Props) => { + +
+ + Expose 0.0.0.0:3000 + + +
+ + {exposeAllInterfaces && ( + + {t("settings.server.webServer.exposeWarning")} + + )}
); diff --git a/apps/dokploy/server/server.ts b/apps/dokploy/server/server.ts index b13e5df5f..91819f2b0 100644 --- a/apps/dokploy/server/server.ts +++ b/apps/dokploy/server/server.ts @@ -28,6 +28,7 @@ const app = next({ dev, turbopack: process.env.TURBOPACK === "1" }); const handle = app.getRequestHandler(); void app.prepare().then(async () => { try { + const host = process.env.EXPOSE_ALL_INTERFACES === "true" ? "0.0.0.0" : "127.0.0.1"; const server = http.createServer((req, res) => { handle(req, res); }); @@ -63,7 +64,7 @@ void app.prepare().then(async () => { await migration(); } - server.listen(PORT); + server.listen(PORT, host); console.log("Server Started:", PORT); if (!IS_CLOUD) { console.log("Starting Deployment Worker"); From 10f6b94e975afe73969a85a3924e985b253d3a09 Mon Sep 17 00:00:00 2001 From: Yuki <60097976+binaryYuki@users.noreply.github.com> Date: Sat, 21 Dec 2024 13:00:27 +0000 Subject: [PATCH 2/2] Update web-server.tsx --- apps/dokploy/components/dashboard/settings/web-server.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dokploy/components/dashboard/settings/web-server.tsx b/apps/dokploy/components/dashboard/settings/web-server.tsx index 14ba736c0..38449a9ca 100644 --- a/apps/dokploy/components/dashboard/settings/web-server.tsx +++ b/apps/dokploy/components/dashboard/settings/web-server.tsx @@ -66,7 +66,7 @@ export const WebServer = ({ className }: Props) => {
- Expose 0.0.0.0:3000 + Expose server port