diff --git a/backend/deps.edn b/backend/deps.edn index 31b5e48096..cbf1176953 100644 --- a/backend/deps.edn +++ b/backend/deps.edn @@ -97,8 +97,8 @@ :jmx-remote {:jvm-opts ["-Dcom.sun.management.jmxremote" - "-Dcom.sun.management.jmxremote.port=9090" - "-Dcom.sun.management.jmxremote.rmi.port=9090" + "-Dcom.sun.management.jmxremote.port=9000" + "-Dcom.sun.management.jmxremote.rmi.port=9000" "-Dcom.sun.management.jmxremote.local.only=false" "-Dcom.sun.management.jmxremote.authenticate=false" "-Dcom.sun.management.jmxremote.ssl=false" diff --git a/backend/scripts/_env b/backend/scripts/_env index f5cca5538b..16ea0b8248 100644 --- a/backend/scripts/_env +++ b/backend/scripts/_env @@ -53,6 +53,7 @@ export AWS_ACCESS_KEY_ID=penpot-devenv export AWS_SECRET_ACCESS_KEY=penpot-devenv export PENPOT_OBJECTS_STORAGE_BACKEND=s3 export PENPOT_OBJECTS_STORAGE_S3_ENDPOINT=http://minio:9000 +export PENPOT_OBJECTS_STORAGE_S3_PUBLIC_URI=https://localhost:9090 export PENPOT_OBJECTS_STORAGE_S3_BUCKET=penpot export JAVA_OPTS="\ diff --git a/backend/src/app/config.clj b/backend/src/app/config.clj index de030f2e11..a499755819 100644 --- a/backend/src/app/config.clj +++ b/backend/src/app/config.clj @@ -59,7 +59,6 @@ :auth-token-cookie-name "auth-token" - :assets-path "/internal/assets/" :smtp-default-reply-to "Penpot " :smtp-default-from "Penpot " @@ -220,7 +219,6 @@ [:media-directory {:optional true} :string] ;; REVIEW [:media-uri {:optional true} :string] - [:assets-path {:optional true} :string] [:netty-io-threads {:optional true} ::sm/int] [:executor-threads {:optional true} ::sm/int] @@ -236,7 +234,8 @@ [:objects-storage-fs-directory {:optional true} :string] [:objects-storage-s3-bucket {:optional true} :string] [:objects-storage-s3-region {:optional true} :keyword] - [:objects-storage-s3-endpoint {:optional true} ::sm/uri]])) + [:objects-storage-s3-endpoint {:optional true} ::sm/uri] + [:objects-storage-s3-public-uri {:optional true} ::sm/uri]])) (defn- parse-flags [config] diff --git a/backend/src/app/http/assets.clj b/backend/src/app/http/assets.clj index c716ce8b85..c772d010b6 100644 --- a/backend/src/app/http/assets.clj +++ b/backend/src/app/http/assets.clj @@ -20,7 +20,7 @@ (ct/duration {:hours 24})) (def ^:private signature-max-age - (ct/duration {:hours 24 :minutes 15})) + (ct/duration {:hours 36})) (defn get-id [{:keys [path-params]}] @@ -34,7 +34,8 @@ (defn- serve-object-from-s3 [{:keys [::sto/storage] :as cfg} obj] - (let [{:keys [host port] :as url} (sto/get-object-url storage obj {:max-age signature-max-age})] + (let [{:keys [host port] :as url} + (sto/get-object-url storage obj {:max-age signature-max-age})] {::yres/status 307 ::yres/headers {"location" (str url) "x-host" (cond-> host port (str ":" port)) @@ -42,11 +43,11 @@ "cache-control" (str "max-age=" (inst-ms cache-max-age))}})) (defn- serve-object-from-fs - [{:keys [::path]} obj] - (let [purl (u/join (u/uri path) - (sto/object->relative-path obj)) - mdata (meta obj) - headers {"x-accel-redirect" (:path purl) + [_ obj] + (let [mdata (meta obj) + path (sto/object->relative-path obj) + headers {"x-accel-redirect" (str "/internal/assets/" path) + "x-internal-redirect" path "content-type" (:content-type mdata) "cache-control" (str "max-age=" (inst-ms cache-max-age))}] {::yres/status 204 @@ -95,8 +96,7 @@ (defmethod ig/assert-key ::routes [_ params] - (assert (sto/valid-storage? (::sto/storage params)) "expected valid storage instance") - (assert (string? (::path params)))) + (assert (sto/valid-storage? (::sto/storage params)) "expected valid storage instance")) (defmethod ig/init-key ::routes [_ cfg] diff --git a/backend/src/app/main.clj b/backend/src/app/main.clj index 1fa26fabe1..093de09da3 100644 --- a/backend/src/app/main.clj +++ b/backend/src/app/main.clj @@ -305,8 +305,7 @@ ::session/manager (ig/ref ::session/manager)} :app.http.assets/routes - {::http.assets/path (cf/get :assets-path) - ::http.assets/cache-max-age (ct/duration {:hours 24}) + {::http.assets/cache-max-age (ct/duration {:hours 24}) ::http.assets/cache-max-agesignature-max-age (ct/duration {:hours 24 :minutes 5}) ::sto/storage (ig/ref ::sto/storage)} @@ -488,6 +487,9 @@ (cf/get :objects-storage-s3-region)) ::sto.s3/endpoint (or (cf/get :storage-assets-s3-endpoint) (cf/get :objects-storage-s3-endpoint)) + + ::sto.s3/public-uri (cf/get :objects-storage-s3-public-uri) + ::sto.s3/bucket (or (cf/get :storage-assets-s3-bucket) (cf/get :objects-storage-s3-bucket)) ::sto.s3/io-threads (or (cf/get :storage-assets-s3-io-threads) diff --git a/backend/src/app/storage/s3.clj b/backend/src/app/storage/s3.clj index 8d28a9a9f3..0e8b616e5c 100644 --- a/backend/src/app/storage/s3.clj +++ b/backend/src/app/storage/s3.clj @@ -91,7 +91,8 @@ [::region {:optional true} :keyword] [::bucket {:optional true} ::sm/text] [::prefix {:optional true} ::sm/text] - [::endpoint {:optional true} ::sm/uri]]) + [::endpoint {:optional true} ::sm/uri] + [::public-uri {:optional true} ::sm/uri]]) (defmethod ig/expand-key ::backend [k v] @@ -236,13 +237,13 @@ (.close ^S3AsyncClient client))))) (defn- build-s3-presigner - [{:keys [::region ::endpoint]}] - (let [config (-> (S3Configuration/builder) - (cond-> (some? endpoint) (.pathStyleAccessEnabled true)) + [{:keys [::region ::endpoint ::public-uri]}] + (let [uri (or public-uri endpoint) + config (-> (S3Configuration/builder) + (cond-> (some? uri) (.pathStyleAccessEnabled true)) (.build))] - (-> (S3Presigner/builder) - (cond-> (some? endpoint) (.endpointOverride (URI. (str endpoint)))) + (cond-> (some? uri) (.endpointOverride (URI. (str uri)))) (.region (lookup-region region)) (.serviceConfiguration ^S3Configuration config) (.build)))) diff --git a/docker/devenv/docker-compose.yaml b/docker/devenv/docker-compose.yaml index 3ed5c3cdd7..3973eea3b4 100644 --- a/docker/devenv/docker-compose.yaml +++ b/docker/devenv/docker-compose.yaml @@ -41,7 +41,10 @@ services: - 6062:6062 - 6063:6063 - 6064:6064 + - 9000:9000 + - 9001:9001 - 9090:9090 + - 9091:9091 environment: - EXTERNAL_UID=${CURRENT_USER_ID} diff --git a/docker/devenv/files/Caddyfile b/docker/devenv/files/Caddyfile index 719ed142ae..51f4fb9221 100644 --- a/docker/devenv/files/Caddyfile +++ b/docker/devenv/files/Caddyfile @@ -1,16 +1,169 @@ { - auto_https off + auto_https off } -localhost:3449 { - reverse_proxy localhost:4449 - tls /home/selfsigned.crt /home/selfsigned.key +(common_routes) { + root * /home/penpot/penpot/frontend/resources/public + + encode zstd gzip + + file_server { + browse + precompressed br zstd gzip + } + + request_body { + max_size 300MB + } + + handle_path /assets* { + rewrite * /assets{path} + reverse_proxy http://127.0.0.1:6060 { + + header_up Host {http.request.host} + header_up X-Real-IP {http.request.remote} + + @accel header X-Internal-Redirect * + @redirectAsset status 307 + + handle_response @accel { + root * /home/penpot/penpot/backend/assets + rewrite * {rp.header.X-Internal-Redirect} + header Cache-Control "max-age=86400" + method * GET + file_server + } + + handle_response @redirectAsset { + header Location {rp.header.Location} + header Cache-Control "max-age=86400" + respond "" 302 + } + } + } + + handle_path /api/export* { + rewrite * /api/export{path} + reverse_proxy http://127.0.0.1:6061 + } + + handle_path /api* { + rewrite * /api{path} + reverse_proxy http://127.0.0.1:6060 { + header_up Host {http.request.host} + header_up X-Real-IP {http.request.remote} + } + } + + handle_path /ws* { + rewrite * /ws{path} + reverse_proxy http://127.0.0.1:6060 { + flush_interval -1 + } + } + + handle_path /webhooks* { + rewrite * /webhooks{path} + reverse_proxy http://127.0.0.1:6060 + } + + handle_path /dbg* { + rewrite * /dbg{path} + reverse_proxy http://127.0.0.1:6060 + } + + handle_path /telemetry* { + rewrite * /telemetry{path} + reverse_proxy http://127.0.0.1:6070 + } + + handle_path /payments* { + rewrite * /payments{path} + reverse_proxy http://127.0.0.1:5000 + } + + handle_path /nitrate/* { + rewrite * /nitrate{path} + reverse_proxy http://127.0.0.1:3000 + } + + handle_path /storybook* { + root * /home/penpot/penpot/frontend/storybook-static + file_server browse + } + + # ------------------------------- + # GitHub proxy + # ------------------------------- + @githubFiles path_regexp github ^/github/penpot-files/(.+)$ + handle @githubFiles { + rewrite * /penpot/penpot-files/refs/heads/main/{re.github.1} + reverse_proxy https://raw.githubusercontent.com { + header_up User-Agent "curl/8.5.0" + header_up Host "raw.githubusercontent.com" + header_up Accept "*/*" + header_down Access-Control-Allow-Origin {http.request.header.Origin} + header_down -Cookies + } + } + + # ------------------------------- + # Google Fonts proxy + # ------------------------------- + @gfontsStatic path_regexp fs ^/internal/gfonts/font/(.+)$ + handle @gfontsStatic { + rewrite * /s/{re.fs.1} + + reverse_proxy https://fonts.gstatic.com { + header_up User-Agent "Mozilla/5.0" + header_up Host "fonts.gstatic.com" + + header_down Access-Control-Allow-Origin {http.request.header.Origin} + header_down -Cache-Control + } + } + + handle_path /internal/gfonts/css* { + rewrite * /css?{query} + + reverse_proxy https://fonts.googleapis.com { + header_up User-Agent "Mozilla/5.0" + header_up Host "fonts.googleapis.com" + + header_down Access-Control-Allow-Origin {http.request.header.Origin} + header_down Cache-Control "max-age=86400" + } + } + + @staticExts path_regexp staticExts \.(jpg|png|svg|ttf|woff|woff2)$ + header @staticExts Cache-Control "public, max-age=604800" + + @jsExts path_regexp jsExts \.(js|css|wasm|html)$ + header @jsExts Cache-Control "no-store" + + handle { + try_files {path} /index.html + } } -http://localhost:3450 { - reverse_proxy localhost:4449 +:3449 { + tls /home/selfsigned.crt /home/selfsigned.key + import common_routes } -http://penpot-devenv-main:3450 { - reverse_proxy localhost:4449 +:3450 { + import common_routes +} + +# This is a workaround for make the MINIO available on https://localhost:9090 +# and http://localhost:9000. On normal use case, the object storage provider +# should be publicy available and no specific settings used + +:9090 { + reverse_proxy http://minio:9000 + tls /home/selfsigned.crt /home/selfsigned.key +} + +:9091 { + reverse_proxy http://minio:9000 }