The stack
- frontend — ClojureScript SPA served by nginx
- backend — Clojure JVM application; REST + WebSocket API
- exporter — Node + headless Chromium for rendering exports (PDF, PNG)
- postgres — the data store
- redis — pub/sub for collaboration events + caches
Install via docker compose
Penpot publishes an official compose file. Adapted minimally:
# docker-compose.yml
services:
penpot-frontend:
image: penpotapp/frontend:latest
restart: unless-stopped
ports:
- "127.0.0.1:9001:80"
volumes:
- penpot-assets:/opt/data/assets
depends_on: [ penpot-backend, penpot-exporter ]
environment:
PENPOT_FLAGS: enable-registration enable-login-with-password
penpot-backend:
image: penpotapp/backend:latest
restart: unless-stopped
volumes:
- penpot-assets:/opt/data/assets
depends_on: [ penpot-postgres, penpot-redis ]
environment:
PENPOT_FLAGS: enable-registration enable-login-with-password disable-email-verification enable-smtp
PENPOT_PUBLIC_URI: https://design.example.com
PENPOT_DATABASE_URI: postgresql://penpot-postgres/penpot
PENPOT_DATABASE_USERNAME: penpot
PENPOT_DATABASE_PASSWORD: ${DB_PASSWORD}
PENPOT_REDIS_URI: redis://penpot-redis/0
PENPOT_ASSETS_STORAGE_BACKEND: assets-fs
PENPOT_STORAGE_ASSETS_FS_DIRECTORY: /opt/data/assets
PENPOT_TELEMETRY_ENABLED: false
# SMTP for invites / password resets
PENPOT_SMTP_HOST: smtp.example.com
PENPOT_SMTP_PORT: 587
PENPOT_SMTP_DEFAULT_FROM: penpot@example.com
PENPOT_SMTP_DEFAULT_REPLY_TO: penpot@example.com
PENPOT_SMTP_USERNAME: penpot@example.com
PENPOT_SMTP_PASSWORD: ${SMTP_PW}
PENPOT_SMTP_TLS: true
penpot-exporter:
image: penpotapp/exporter:latest
restart: unless-stopped
environment:
PENPOT_PUBLIC_URI: http://penpot-frontend
penpot-postgres:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_USER: penpot
POSTGRES_DB: penpot
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- penpot-postgres:/var/lib/postgresql/data
penpot-redis:
image: redis:7-alpine
restart: unless-stopped
volumes:
penpot-postgres:
penpot-assets:
docker compose up -d
docker compose logs -f penpot-backend
Reverse proxy
# Caddy
design.example.com {
reverse_proxy 127.0.0.1:9001
request_body { max_size 100MB }
}
WebSockets for collaboration; Caddy handles them automatically.
First-run setup
Browse to https://design.example.com. Register the first user (will be the team admin). Penpot prompts to create a team; everything below is per-team.
After bootstrap, set PENPOT_FLAGS to drop enable-registration (so the instance stops accepting new public signups) and require invites instead.
What Penpot can do
- Vector editor — rectangles, ellipses, paths, text, boolean ops, shape morphing. SVG-native primitives, so every shape is a real path you could inspect.
- Components — reusable design elements with overrides. Edit the master, instances update. Variants for component states.
- Auto-layout — flex-style automatic spacing and resizing.
- Libraries — share components, color styles, typography across files; manage as design systems.
- Design tokens — W3C-spec-compliant tokens for colors, spacing, typography. Exportable as JSON for engineering consumption.
- Prototype — flows, interactions, transitions, scrolling, hover states. Shareable preview links.
- Real-time collaboration — multiple users editing the same file with live cursors.
- Inspector — developer hand-off view showing CSS, sizes, colors, assets.
- Export — SVG (the native format), PNG, JPG, PDF, individual layers or entire boards.
Plugins (2.x+)
Penpot 2.x added a plugin API. Plugins run sandboxed in the user's browser, can read / modify files via the public API. Notable picks:
- HTML/CSS export — turn a board into a hand-coded HTML + CSS snippet.
- Lorem Ipsum / placeholder data — fill in mockups.
- Color palette extractors — from images.
- Design token import/export — sync with code repos.
- Translation — bulk-translate text layers.
Install via the Plugins panel in any file; per-team plugin policy in Team Settings → Plugins.
Import from Figma
Penpot's importer reads .fig files (export your Figma file as .fig via the desktop Figma app or paid plan). Most layers translate; component variants, advanced auto-layout, and certain prototype interactions are imperfect. For one-off file migrations, it's good enough; for active project migration, plan to re-create complex components.
Penpot's own file format is .penpot (a zip of JSON + binary assets); the API also supports raw import/export of project trees.
SSO
Penpot supports OIDC out of the box — Authentik (see that tutorial), Keycloak, Google, GitHub. Set the OIDC env vars and disable password auth for SSO-only flows:
PENPOT_FLAGS: disable-registration enable-login-with-oidc enable-oidc-registration
PENPOT_OIDC_CLIENT_ID: <client-id>
PENPOT_OIDC_CLIENT_SECRET: <client-secret>
PENPOT_OIDC_BASE_URI: https://auth.example.com/application/o/penpot/
PENPOT_OIDC_SCOPES: "openid profile email"
PENPOT_OIDC_NAME: "Authentik"
Object storage for big projects
For large teams, swap the filesystem backend for S3-compatible storage (MinIO; see that tutorial):
PENPOT_ASSETS_STORAGE_BACKEND: assets-s3
PENPOT_STORAGE_ASSETS_S3_REGION: us-east-1
PENPOT_STORAGE_ASSETS_S3_BUCKET: penpot-assets
PENPOT_STORAGE_ASSETS_S3_ENDPOINT: https://s3.example.com
AWS_ACCESS_KEY_ID: <key>
AWS_SECRET_ACCESS_KEY: <secret>
Files and assets stay in S3; Postgres holds metadata only.
Backups
- Postgres — the project / team / file structure, comments, versions.
pg_dumpnightly. - Assets storage — the actual file blobs. Either restic on the local volume or snapshots / replication on the S3 bucket.
- Penpot can also export a project tree via API as a single archive — useful for per-team backups.
Penpot vs Figma in 2026
- Penpot is materially less polished on the most-advanced features (some complex auto-layout, certain prototype interactions, the multi-file design-system experience). Improving every release.
- Performance on very-large files is workable but slower than Figma's native client.
- For self-hosted requirement, source availability, or "we want to own our design files in an open format," Penpot is the only credible option.
- Roadmap and core team are funded and active (Kaleidos, a Spanish company); not a project at risk of abandonment.
For sovereignty over design files, regulated industries where SaaS isn't permitted, or simply not paying per-seat for design tools, Penpot is the answer.