From 6839b16735731fc45eae6d9f68fab09e22595d61 Mon Sep 17 00:00:00 2001 From: Francis Santiago Date: Fri, 9 Oct 2026 12:26:57 +0200 Subject: [PATCH] :books: Document subpath configuration and migration --- docs/technical-guide/configuration.md | 43 +++++++++++++++++ .../technical-guide/getting-started/docker.md | 46 +++++++++++++++++++ .../getting-started/kubernetes.md | 16 +++++++ 3 files changed, 105 insertions(+) diff --git a/docs/technical-guide/configuration.md b/docs/technical-guide/configuration.md index 95412109c9..f65127f995 100644 --- a/docs/technical-guide/configuration.md +++ b/docs/technical-guide/configuration.md @@ -372,6 +372,49 @@ PENPOT_PUBLIC_URI: https://penpot.mycompany.com If you're using the official docker-compose.yml you only need to configure the PENPOT_PUBLIC_URI envvar in the top of the file. +### Serve Penpot from a subpath + +Penpot can be served from a subpath such as `https://mycompany.com/penpot/`. +Set `PENPOT_PUBLIC_URI` to the complete public URL, including the subpath and its +trailing slash: + +```bash +PENPOT_PUBLIC_URI: https://mycompany.com/penpot/ +``` + +Your reverse proxy or Ingress must also: + +- Route requests under `/penpot/` to the Penpot frontend. +- Remove the `/penpot` prefix before forwarding each request. The frontend + continues to serve its internal routes from `/`. +- Preserve WebSocket upgrade headers for notifications and other services that + use WebSockets. + +Changing only `PENPOT_PUBLIC_URI` is not enough. Without the matching proxy +rewrite, static assets, API calls, and WebSocket connections will use routes that +the frontend does not recognize. + +#### Migrate an existing installation to a subpath + +Moving an installation from `/` to a subpath does not require a database or +asset migration. Users, teams, projects, files, and uploaded assets remain in +the existing storage. + +Before changing the public URL: + +1. Back up the database, assets, and current deployment configuration. +2. Configure the proxy or Ingress route and prefix rewrite. +3. Update `PENPOT_PUBLIC_URI` for every Penpot component that uses it. +4. Keep the existing `PENPOT_SECRET_KEY`, database, and asset storage + configuration. +5. Restart or redeploy Penpot and verify login, static assets, API requests, + WebSockets, file editing, and image uploads through the new URL. + +Existing bookmarks and integrations that use the previous root URL must be +updated. You may also configure a redirect from the previous URL. If the scheme +or hostname changes in addition to the path, review your authentication provider +callback URLs and cookie settings. Active users may need to sign in again. +

If you plan to serve Penpot under different domain than `localhost` without HTTPS, you need to disable the `secure` flag on cookies, with the `disable-secure-session-cookies` flag. diff --git a/docs/technical-guide/getting-started/docker.md b/docs/technical-guide/getting-started/docker.md index 4d192aee11..3e8f9740a8 100644 --- a/docs/technical-guide/getting-started/docker.md +++ b/docs/technical-guide/getting-started/docker.md @@ -317,6 +317,52 @@ server { For full documentation, go to the [official website][2] +#### Serve Penpot from a subpath with NGINX + +First, set the complete public URL in `docker-compose.yaml`: + +```yaml +PENPOT_PUBLIC_URI: https://mycompany.com/penpot/ +``` + +Then route the subpath to the Penpot frontend and remove the prefix before +forwarding the request: + +```nginx +server { + listen 443 ssl; + server_name mycompany.com; + + client_max_body_size 367001600; + + # Configure TLS and logs following your organization's practices. + ssl_certificate /path/to/fullchain; + ssl_certificate_key /path/to/privkey; + + location = /penpot { + return 301 /penpot/; + } + + location /penpot/ { + rewrite ^/penpot/(.*)$ /$1 break; + + proxy_set_header Host $http_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Scheme $scheme; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_redirect off; + proxy_pass http://localhost:9001; + } +} +``` + +This single location also covers the API and WebSocket endpoints because NGINX +forwards them after removing `/penpot`. Keep the trailing slash in +`PENPOT_PUBLIC_URI`. + ### Example with CADDY SERVER ```bash diff --git a/docs/technical-guide/getting-started/kubernetes.md b/docs/technical-guide/getting-started/kubernetes.md index 1582d4015b..fa0f5f8f45 100644 --- a/docs/technical-guide/getting-started/kubernetes.md +++ b/docs/technical-guide/getting-started/kubernetes.md @@ -96,6 +96,22 @@ file itself, which you can use as a basis for creating your own settings. You can also consult the list of parameters on the ArtifactHub page of the project. +### Serve Penpot from a subpath + +The chart serves Penpot from `/` by default and can also expose it from a +subpath. The required values depend on whether the cluster uses an Ingress +controller or Gateway API. + +See +Serving Penpot from a subpath +in the Helm chart documentation for the current configuration examples. + +When moving an existing release to a subpath, keep the existing database, +assets, and secret key settings. No data migration is required. Follow the +migration considerations in the [Penpot URI](/technical-guide/configuration/#penpot-uri) +section and verify the +installation through its new public URL after running `helm upgrade`. + ### Using OpenShift? If you are deploying Penpot on OpenShift, we recommend following the specific guidelines provided in our Penpot-helm documentation: