diff --git a/apps/dokploy/public/templates/penpot.svg b/apps/dokploy/public/templates/penpot.svg
new file mode 100644
index 00000000..05454092
--- /dev/null
+++ b/apps/dokploy/public/templates/penpot.svg
@@ -0,0 +1,3 @@
+
diff --git a/apps/dokploy/templates/penpot/docker-compose.yml b/apps/dokploy/templates/penpot/docker-compose.yml
new file mode 100644
index 00000000..55abdb53
--- /dev/null
+++ b/apps/dokploy/templates/penpot/docker-compose.yml
@@ -0,0 +1,213 @@
+## Common flags:
+# demo-users
+# email-verification
+# log-emails
+# log-invitation-tokens
+# login-with-github
+# login-with-gitlab
+# login-with-google
+# login-with-ldap
+# login-with-oidc
+# login-with-password
+# prepl-server
+# registration
+# secure-session-cookies
+# smtp
+# smtp-debug
+# telemetry
+# webhooks
+##
+## You can read more about all available flags and other
+## environment variables here:
+## https://help.penpot.app/technical-guide/configuration/#advanced-configuration
+#
+# WARNING: if you're exposing Penpot to the internet, you should remove the flags
+# 'disable-secure-session-cookies' and 'disable-email-verification'
+
+volumes:
+ penpot_postgres_v15:
+ penpot_assets:
+ penpot_traefik:
+ # penpot_minio:
+
+services:
+
+ penpot-frontend:
+ image: "penpotapp/frontend:2.3.2"
+ restart: always
+ ports:
+ - 8080
+ - 9001
+
+ volumes:
+ - penpot_assets:/opt/data/assets
+
+ depends_on:
+ - penpot-backend
+ - penpot-exporter
+
+ networks:
+ - dokploy-network
+
+ environment:
+ PENPOT_FLAGS: disable-email-verification enable-smtp enable-prepl-server disable-secure-session-cookies
+
+ penpot-backend:
+ image: "penpotapp/backend:2.3.2"
+ restart: always
+
+ volumes:
+ - penpot_assets:/opt/data/assets
+
+ depends_on:
+ - penpot-postgres
+ - penpot-redis
+
+ networks:
+ - dokploy-network
+
+ ## Configuration envronment variables for the backend
+ ## container.
+
+ environment:
+ PENPOT_PUBLIC_URI: http://${DOMAIN_NAME}
+ PENPOT_FLAGS: disable-email-verification enable-smtp enable-prepl-server disable-secure-session-cookies
+
+ ## Penpot SECRET KEY. It serves as a master key from which other keys for subsystems
+ ## (eg http sessions, or invitations) are derived.
+ ##
+ ## If you leave it commented, all created sessions and invitations will
+ ## become invalid on container restart.
+ ##
+ ## If you going to uncomment this, we recommend to use a trully randomly generated
+ ## 512 bits base64 encoded string here. You can generate one with:
+ ##
+ ## python3 -c "import secrets; print(secrets.token_urlsafe(64))"
+
+ # PENPOT_SECRET_KEY: my-insecure-key
+
+ ## The PREPL host. Mainly used for external programatic access to penpot backend
+ ## (example: admin). By default it will listen on `localhost` but if you are going to use
+ ## the `admin`, you will need to uncomment this and set the host to `0.0.0.0`.
+
+ # PENPOT_PREPL_HOST: 0.0.0.0
+
+ ## Database connection parameters. Don't touch them unless you are using custom
+ ## postgresql connection parameters.
+
+ PENPOT_DATABASE_URI: postgresql://penpot-postgres/penpot
+ PENPOT_DATABASE_USERNAME: penpot
+ PENPOT_DATABASE_PASSWORD: penpot
+
+ ## Redis is used for the websockets notifications. Don't touch unless the redis
+ ## container has different parameters or different name.
+
+ PENPOT_REDIS_URI: redis://penpot-redis/0
+
+ ## Default configuration for assets storage: using filesystem based with all files
+ ## stored in a docker volume.
+
+ PENPOT_ASSETS_STORAGE_BACKEND: assets-fs
+ PENPOT_STORAGE_ASSETS_FS_DIRECTORY: /opt/data/assets
+
+ ## Also can be configured to to use a S3 compatible storage
+ ## service like MiniIO. Look below for minio service setup.
+
+ # AWS_ACCESS_KEY_ID:
+ # AWS_SECRET_ACCESS_KEY:
+ # PENPOT_ASSETS_STORAGE_BACKEND: assets-s3
+ # PENPOT_STORAGE_ASSETS_S3_ENDPOINT: http://penpot-minio:9000
+ # PENPOT_STORAGE_ASSETS_S3_BUCKET:
+
+ ## Telemetry. When enabled, a periodical process will send anonymous data about this
+ ## instance. Telemetry data will enable us to learn how the application is used,
+ ## based on real scenarios. If you want to help us, please leave it enabled. You can
+ ## audit what data we send with the code available on github.
+
+ PENPOT_TELEMETRY_ENABLED: true
+
+ ## Example SMTP/Email configuration. By default, emails are sent to the mailcatch
+ ## service, but for production usage it is recommended to setup a real SMTP
+ ## provider. Emails are used to confirm user registrations & invitations. Look below
+ ## how the mailcatch service is configured.
+
+ PENPOT_SMTP_DEFAULT_FROM: no-reply@example.com
+ PENPOT_SMTP_DEFAULT_REPLY_TO: no-reply@example.com
+ PENPOT_SMTP_HOST: penpot-mailcatch
+ PENPOT_SMTP_PORT: 1025
+ PENPOT_SMTP_USERNAME:
+ PENPOT_SMTP_PASSWORD:
+ PENPOT_SMTP_TLS: false
+ PENPOT_SMTP_SSL: false
+
+ penpot-exporter:
+ image: "penpotapp/exporter:2.3.2"
+ restart: always
+ networks:
+ - dokploy-network
+
+ environment:
+ # Don't touch it; this uses an internal docker network to
+ # communicate with the frontend.
+ PENPOT_PUBLIC_URI: http://penpot-frontend
+
+ ## Redis is used for the websockets notifications.
+ PENPOT_REDIS_URI: redis://penpot-redis/0
+
+ penpot-postgres:
+ image: "postgres:15"
+ restart: always
+ stop_signal: SIGINT
+
+ volumes:
+ - penpot_postgres_v15:/var/lib/postgresql/data
+
+ networks:
+ - dokploy-network
+
+ environment:
+ - POSTGRES_INITDB_ARGS=--data-checksums
+ - POSTGRES_DB=penpot
+ - POSTGRES_USER=penpot
+ - POSTGRES_PASSWORD=penpot
+
+ penpot-redis:
+ image: redis:7.2
+ restart: always
+ networks:
+ - dokploy-network
+
+ ## A mailcatch service, used as temporal SMTP server. You can access via HTTP to the
+ ## port 1080 for read all emails the penpot platform has sent. Should be only used as a
+ ## temporal solution while no real SMTP provider is configured.
+
+ penpot-mailcatch:
+ image: sj26/mailcatcher:latest
+ restart: always
+ expose:
+ - '1025'
+ ports:
+ - 1080
+ networks:
+ - dokploy-network
+
+ ## Example configuration of MiniIO (S3 compatible object storage service); If you don't
+ ## have preference, then just use filesystem, this is here just for the completeness.
+
+ # minio:
+ # image: "minio/minio:latest"
+ # command: minio server /mnt/data --console-address ":9001"
+ # restart: always
+ #
+ # volumes:
+ # - "penpot_minio:/mnt/data"
+ #
+ # environment:
+ # - MINIO_ROOT_USER=minioadmin
+ # - MINIO_ROOT_PASSWORD=minioadmin
+ #
+ # ports:
+ # - 9000:9000
+ # - 9001:9001
+
+
diff --git a/apps/dokploy/templates/penpot/index.ts b/apps/dokploy/templates/penpot/index.ts
new file mode 100644
index 00000000..f657c698
--- /dev/null
+++ b/apps/dokploy/templates/penpot/index.ts
@@ -0,0 +1,27 @@
+import {
+ type DomainSchema,
+ type Schema,
+ type Template,
+ generateBase64,
+ generatePassword,
+ generateRandomDomain,
+} from "../utils";
+
+export function generate(schema: Schema): Template {
+ const mainDomain = generateRandomDomain(schema);
+
+ const domains: DomainSchema[] = [
+ {
+ host: mainDomain,
+ port: 80,
+ serviceName: "penpot-frontend",
+ },
+ ];
+
+ const envs = [`DOMAIN_NAME=${mainDomain}`];
+
+ return {
+ domains,
+ envs,
+ };
+}
diff --git a/apps/dokploy/templates/templates.ts b/apps/dokploy/templates/templates.ts
index 05d8241a..9aaf1ee0 100644
--- a/apps/dokploy/templates/templates.ts
+++ b/apps/dokploy/templates/templates.ts
@@ -1062,6 +1062,21 @@ export const templates: TemplateData[] = [
tags: ["identity", "auth"],
load: () => import("./logto/index").then((m) => m.generate),
},
+ {
+ id: "penpot",
+ name: "Penpot",
+ version: "2.3.2",
+ description:
+ "Penpot is the web-based open-source design tool that bridges the gap between designers and developers.",
+ logo: "penpot.svg",
+ links: {
+ github: "https://github.com/penpot/penpot",
+ website: "https://penpot.app/",
+ docs: "https://docs.penpot.app/",
+ },
+ tags: ["desing", "collaboration"],
+ load: () => import("./penpot/index").then((m) => m.generate),
+ },
{
id: "huly",
name: "Huly",