From cc390364793122c818a5fcc5d5c4f763372b6cbc Mon Sep 17 00:00:00 2001 From: Lorenzo Migliorero Date: Mon, 29 Jul 2024 16:21:50 +0200 Subject: [PATCH] fix: server traefik config --- .../server/update-server-config.test.ts | 79 +++++++++++++++++++ package.json | 1 + pnpm-lock.yaml | 74 +++++++++++++++++ server/setup/traefik-setup.ts | 3 +- server/utils/traefik/web-server.ts | 20 +++-- 5 files changed, 168 insertions(+), 9 deletions(-) create mode 100644 __test__/traefik/server/update-server-config.test.ts diff --git a/__test__/traefik/server/update-server-config.test.ts b/__test__/traefik/server/update-server-config.test.ts new file mode 100644 index 00000000..662c1ad7 --- /dev/null +++ b/__test__/traefik/server/update-server-config.test.ts @@ -0,0 +1,79 @@ +import { fs, vol } from "memfs"; + +vi.mock("node:fs", () => ({ + ...fs, + default: fs, +})); + +import type { Admin } from "@/server/api/services/admin"; +import { createDefaultServerTraefikConfig } from "@/server/setup/traefik-setup"; +import { loadOrCreateConfig } from "@/server/utils/traefik/application"; +import type { FileConfig } from "@/server/utils/traefik/file-types"; +import { updateServerTraefik } from "@/server/utils/traefik/web-server"; +import { beforeEach, expect, test, vi } from "vitest"; + +const baseAdmin: Admin = { + createdAt: "", + authId: "", + adminId: "string", + githubAppId: null, + githubAppName: null, + serverIp: null, + certificateType: "none", + host: null, + githubClientId: null, + githubClientSecret: null, + githubInstallationId: null, + githubPrivateKey: null, + githubWebhookSecret: null, + letsEncryptEmail: null, + sshPrivateKey: null, + enableDockerCleanup: false, +}; + +beforeEach(() => { + vol.reset(); + createDefaultServerTraefikConfig(); +}); + +test("Should read the configuration file", () => { + const config: FileConfig = loadOrCreateConfig("dokploy"); + + expect(config.http?.routers?.["dokploy-router-app"]?.service).toBe( + "dokploy-service-app", + ); +}); + +test("Should apply redirect-to-https", () => { + updateServerTraefik( + { + ...baseAdmin, + certificateType: "letsencrypt", + }, + "example.com", + ); + + const config: FileConfig = loadOrCreateConfig("dokploy"); + + expect(config.http?.routers?.["dokploy-router-app"]?.middlewares).toContain( + "redirect-to-https", + ); +}); + +test("Should change only host when no certificate", () => { + updateServerTraefik(baseAdmin, "example.com"); + + const config: FileConfig = loadOrCreateConfig("dokploy"); + + expect(config.http?.routers?.["dokploy-router-app-secure"]).toBeUndefined(); +}); + +test("Should not touch config without host", () => { + const originalConfig: FileConfig = loadOrCreateConfig("dokploy"); + + updateServerTraefik(baseAdmin, null); + + const config: FileConfig = loadOrCreateConfig("dokploy"); + + expect(originalConfig).toEqual(config); +}); diff --git a/package.json b/package.json index aa32fc3a..222e52e4 100644 --- a/package.json +++ b/package.json @@ -154,6 +154,7 @@ "husky": "^9.0.11", "lint-staged": "^15.2.7", "localtunnel": "2.0.2", + "memfs": "^4.11.0", "postcss": "^8.4.31", "prettier": "^3.2.4", "prettier-plugin-tailwindcss": "^0.5.11", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a636c768..7719cdf3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -360,6 +360,9 @@ importers: localtunnel: specifier: 2.0.2 version: 2.0.2 + memfs: + specifier: ^4.11.0 + version: 4.11.0 postcss: specifier: ^8.4.31 version: 8.4.35 @@ -1232,6 +1235,24 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jsonjoy.com/base64@1.1.2': + resolution: {integrity: sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/json-pack@1.0.4': + resolution: {integrity: sha512-aOcSN4MeAtFROysrbqG137b7gaDDSmVrl5mpo6sT/w+kcXpWnzhMjmY/Fh/sDx26NBxyIE7MB1seqLeCAzy9Sg==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + + '@jsonjoy.com/util@1.3.0': + resolution: {integrity: sha512-Cebt4Vk7k1xHy87kHY7KSPLT77A7Ev7IfOblyLZhtYEhrdQ6fX4EoLq3xOQ3O/DRMEh2ok5nyC180E+ABS8Wmw==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + '@juggle/resize-observer@3.4.0': resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==} @@ -4375,6 +4396,10 @@ packages: engines: {node: '>=18'} hasBin: true + hyperdyperid@1.2.0: + resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} + engines: {node: '>=10.18'} + iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -4763,6 +4788,10 @@ packages: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} + memfs@4.11.0: + resolution: {integrity: sha512-+6kz90/YQoZuHvg3rn1CGPMZfEMaU5xe7xIavZMNiom2RNesiI8S37p9O9n+PlIUnUgretjLdM6HnqpZYl3X2g==} + engines: {node: '>= 4.0.0'} + memoizee@0.4.15: resolution: {integrity: sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==} @@ -5958,6 +5987,12 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + thingies@1.21.0: + resolution: {integrity: sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==} + engines: {node: '>=10.18'} + peerDependencies: + tslib: ^2 + through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} @@ -5996,6 +6031,12 @@ packages: resolution: {integrity: sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==} engines: {node: '>= 0.4'} + tree-dump@1.0.2: + resolution: {integrity: sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==} + engines: {node: '>=10.0'} + peerDependencies: + tslib: '2' + tree-sitter-json@0.20.2: resolution: {integrity: sha512-eUxrowp4F1QEGk/i7Sa+Xl8Crlfp7J0AXxX1QdJEQKQYMWhgMbCIgyQvpO3Q0P9oyTrNQxRLlRipDS44a8EtRw==} @@ -7444,6 +7485,22 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 + '@jsonjoy.com/base64@1.1.2(tslib@2.6.2)': + dependencies: + tslib: 2.6.2 + + '@jsonjoy.com/json-pack@1.0.4(tslib@2.6.2)': + dependencies: + '@jsonjoy.com/base64': 1.1.2(tslib@2.6.2) + '@jsonjoy.com/util': 1.3.0(tslib@2.6.2) + hyperdyperid: 1.2.0 + thingies: 1.21.0(tslib@2.6.2) + tslib: 2.6.2 + + '@jsonjoy.com/util@1.3.0(tslib@2.6.2)': + dependencies: + tslib: 2.6.2 + '@juggle/resize-observer@3.4.0': {} '@leichtgewicht/ip-codec@2.0.5': {} @@ -11087,6 +11144,8 @@ snapshots: husky@9.0.11: {} + hyperdyperid@1.2.0: {} + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 @@ -11447,6 +11506,13 @@ snapshots: media-typer@0.3.0: {} + memfs@4.11.0: + dependencies: + '@jsonjoy.com/json-pack': 1.0.4(tslib@2.6.2) + '@jsonjoy.com/util': 1.3.0(tslib@2.6.2) + tree-dump: 1.0.2(tslib@2.6.2) + tslib: 2.6.2 + memoizee@0.4.15: dependencies: d: 1.0.2 @@ -12675,6 +12741,10 @@ snapshots: dependencies: any-promise: 1.3.0 + thingies@1.21.0(tslib@2.6.2): + dependencies: + tslib: 2.6.2 + through@2.3.8: {} timers-ext@0.1.7: @@ -12702,6 +12772,10 @@ snapshots: traverse@0.6.8: {} + tree-dump@1.0.2(tslib@2.6.2): + dependencies: + tslib: 2.6.2 + tree-sitter-json@0.20.2: dependencies: nan: 2.19.0 diff --git a/server/setup/traefik-setup.ts b/server/setup/traefik-setup.ts index f36d982a..2b44cf40 100644 --- a/server/setup/traefik-setup.ts +++ b/server/setup/traefik-setup.ts @@ -104,8 +104,7 @@ export const createDefaultServerTraefikConfig = () => { [`${appName}-router-app`]: { rule: `Host(\`${appName}.docker.localhost\`) && PathPrefix(\`/\`)`, service: `${appName}-service-app`, - entryPoints: ["web", "websecure"], - tls: {}, + entryPoints: ["web"], }, }, services: { diff --git a/server/utils/traefik/web-server.ts b/server/utils/traefik/web-server.ts index 86a1e366..fc2a1fc0 100644 --- a/server/utils/traefik/web-server.ts +++ b/server/utils/traefik/web-server.ts @@ -19,14 +19,20 @@ export const updateServerTraefik = ( const currentRouterConfig = config.http.routers[`${appName}-router-app`]; - if (currentRouterConfig) { - if (newHost) { - currentRouterConfig.rule = `Host(\`${newHost}\`)`; - } + if (currentRouterConfig && newHost) { + currentRouterConfig.rule = `Host(\`${newHost}\`)`; + if (admin?.certificateType === "letsencrypt") { - currentRouterConfig.tls = { certResolver: "letsencrypt" }; - } else if (admin?.certificateType === "none") { - currentRouterConfig.tls = undefined; + config.http.routers[`${appName}-router-app-secure`] = { + ...currentRouterConfig, + entryPoints: ["web-secure"], + tls: + admin?.certificateType === "letsencrypt" + ? { certResolver: "letsencrypt" } + : undefined, + }; + + currentRouterConfig.middlewares = ["redirect-to-https"]; } }