Self-Host Penpot — Open Source Figma Alternative 2026
What Is Penpot?
Penpot is the first open source design and prototyping platform built for product teams. It runs in the browser, supports real-time collaboration, exports production-ready CSS/SVG, and stores all your design files on your own infrastructure.
Figma costs $15/seat/month for teams (and $75/seat/month for the Organization tier). Penpot is free when self-hosted — you pay only for the server ($5-20/month on Hetzner or DigitalOcean for a small team).
Key features:
- Vector design + prototyping in the browser
- Real-time multiplayer collaboration
- Components, assets, and shared libraries
- CSS inspection panel for developers
- SVG-first format (files are just SVGs + metadata)
- REST API for automation
- LDAP/OIDC SSO support
Prerequisites
- VPS with 2 vCPU, 4GB RAM minimum (Hetzner CX32 at €5.49/month works great)
- Docker + Docker Compose installed
- A domain name with DNS pointing to your server
- Optional: Traefik or Caddy as a reverse proxy
Quick Deploy with Docker Compose
Penpot ships an official Docker Compose configuration:
# 1. Download official docker-compose
curl -o docker-compose.yaml \
https://raw.githubusercontent.com/penpot/penpot/main/docker/images/docker-compose.yaml
# 2. Download environment template
curl -o config.env \
https://raw.githubusercontent.com/penpot/penpot/main/docker/images/config.env
Edit config.env
# config.env — key settings to configure
## Public URL — must match your domain
PENPOT_PUBLIC_URI=https://design.yourdomain.com
## Feature flags
PENPOT_FLAGS=enable-registration enable-login enable-smtp
## Email (for invitations and password resets)
PENPOT_SMTP_ENABLED=true
PENPOT_SMTP_DEFAULT_FROM=noreply@yourdomain.com
PENPOT_SMTP_DEFAULT_REPLY_TO=noreply@yourdomain.com
PENPOT_SMTP_HOST=smtp.yourdomain.com
PENPOT_SMTP_PORT=587
PENPOT_SMTP_USERNAME=your-smtp-user
PENPOT_SMTP_PASSWORD=your-smtp-password
PENPOT_SMTP_TLS=true
## Storage — local filesystem (default)
PENPOT_STORAGE_BACKEND=fs
## Telemetry (disable for privacy)
PENPOT_TELEMETRY_ENABLED=false
The docker-compose.yaml
version: "3"
networks:
penpot:
volumes:
penpot_postgres_v15:
penpot_assets:
penpot_redis:
services:
penpot-frontend:
image: "penpotapp/frontend:latest"
restart: always
ports:
- 9001:80
volumes:
- penpot_assets:/opt/data/assets
depends_on:
- penpot-backend
- penpot-exporter
networks:
- penpot
environment:
- PENPOT_FLAGS=${PENPOT_FLAGS}
penpot-backend:
image: "penpotapp/backend:latest"
restart: always
volumes:
- penpot_assets:/opt/data/assets
depends_on:
- penpot-postgres
- penpot-redis
networks:
- penpot
environment:
- PENPOT_FLAGS=${PENPOT_FLAGS}
- PENPOT_SECRET_KEY=${PENPOT_SECRET_KEY}
- PENPOT_PUBLIC_URI=${PENPOT_PUBLIC_URI}
- PENPOT_DATABASE_URI=postgresql://penpot/penpot
- PENPOT_DATABASE_USERNAME=penpot
- PENPOT_DATABASE_PASSWORD=${PENPOT_DATABASE_PASSWORD}
- PENPOT_REDIS_URI=redis://penpot-redis/0
- PENPOT_STORAGE_BACKEND=${PENPOT_STORAGE_BACKEND}
- PENPOT_STORAGE_FS_DIRECTORY=/opt/data/assets
- PENPOT_TELEMETRY_ENABLED=${PENPOT_TELEMETRY_ENABLED}
- PENPOT_SMTP_ENABLED=${PENPOT_SMTP_ENABLED}
- PENPOT_SMTP_DEFAULT_FROM=${PENPOT_SMTP_DEFAULT_FROM}
- PENPOT_SMTP_HOST=${PENPOT_SMTP_HOST}
- PENPOT_SMTP_PORT=${PENPOT_SMTP_PORT}
- PENPOT_SMTP_USERNAME=${PENPOT_SMTP_USERNAME}
- PENPOT_SMTP_PASSWORD=${PENPOT_SMTP_PASSWORD}
- PENPOT_SMTP_TLS=${PENPOT_SMTP_TLS}
penpot-exporter:
image: "penpotapp/exporter:latest"
restart: always
networks:
- penpot
environment:
- PENPOT_PUBLIC_URI=${PENPOT_PUBLIC_URI}
- PENPOT_REDIS_URI=redis://penpot-redis/0
penpot-postgres:
image: "postgres:15"
restart: always
volumes:
- penpot_postgres_v15:/var/lib/postgresql/data
networks:
- penpot
environment:
- POSTGRES_INITDB_ARGS=--data-checksums
- POSTGRES_DB=penpot
- POSTGRES_USER=penpot
- POSTGRES_PASSWORD=${PENPOT_DATABASE_PASSWORD}
penpot-redis:
image: redis:7
restart: always
networks:
- penpot
volumes:
- penpot_redis:/data
Start Penpot
docker compose -f docker-compose.yaml --env-file config.env up -d
Verify containers are running:
docker compose ps
# NAME STATUS
# penpot-frontend Up
# penpot-backend Up
# penpot-exporter Up
# penpot-postgres Up
# penpot-redis Up
Configure Caddy as Reverse Proxy (Recommended)
# /etc/caddy/Caddyfile
design.yourdomain.com {
reverse_proxy localhost:9001
# Large file uploads for design assets
request_body {
max_size 100MB
}
}
systemctl reload caddy
Or with Traefik Labels
# Add to the penpot-frontend service
labels:
- "traefik.enable=true"
- "traefik.http.routers.penpot.rule=Host(`design.yourdomain.com`)"
- "traefik.http.routers.penpot.entrypoints=websecure"
- "traefik.http.routers.penpot.tls.certresolver=letsencrypt"
- "traefik.http.services.penpot.loadbalancer.server.port=80"
Create Your First Admin User
After Penpot is running, register your admin account at https://design.yourdomain.com:
1. Visit https://design.yourdomain.com
2. Click "Create new account"
3. Use your email — you'll receive a verification email
4. If SMTP isn't configured yet, run:
# Manually verify email without SMTP
docker compose exec penpot-backend \
app.main/handle-command verify-profile \
--email your@email.com
Disable Open Registration (After Setup)
Once your team is set up, disable public registration:
# config.env — remove enable-registration
PENPOT_FLAGS=enable-login enable-smtp
docker compose -f docker-compose.yaml --env-file config.env up -d
Enable LDAP / SSO
Penpot supports LDAP and OIDC (OpenID Connect) for enterprise SSO:
OIDC (Authentik, Keycloak, Google)
# config.env
PENPOT_FLAGS=enable-login-with-oidc
PENPOT_OIDC_CLIENT_ID=your-client-id
PENPOT_OIDC_CLIENT_SECRET=your-client-secret
PENPOT_OIDC_BASE_URI=https://auth.yourdomain.com/application/o/penpot/
PENPOT_OIDC_SCOPES=openid profile email
LDAP
PENPOT_FLAGS=enable-login-with-ldap
PENPOT_LDAP_HOST=ldap.yourdomain.com
PENPOT_LDAP_PORT=389
PENPOT_LDAP_SSL=false
PENPOT_LDAP_STARTTLS=false
PENPOT_LDAP_BASE_DN=ou=users,dc=yourdomain,dc=com
PENPOT_LDAP_USERNAME_ATTRIBUTE=uid
PENPOT_LDAP_EMAIL_ATTRIBUTE=mail
PENPOT_LDAP_FULLNAME_ATTRIBUTE=cn
PENPOT_LDAP_BIND_DN=cn=admin,dc=yourdomain,dc=com
PENPOT_LDAP_BIND_PASSWORD=your-ldap-password
Use S3-Compatible Storage for Assets
For production teams, store design assets in object storage:
# config.env
PENPOT_STORAGE_BACKEND=s3
PENPOT_STORAGE_S3_REGION=eu-central-1
PENPOT_STORAGE_S3_BUCKET=penpot-assets
PENPOT_STORAGE_S3_ENDPOINT=https://s3.yourdomain.com # or leave blank for AWS
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
Works with any S3-compatible storage: MinIO, Hetzner Object Storage, Cloudflare R2, Backblaze B2.
Migrating from Figma
Penpot can import Figma files via the Figma API:
1. In Figma, get a Personal Access Token
(Figma → Settings → Security → Personal access tokens)
2. In Penpot, open a project
3. Click "New file" → "Import from Figma"
4. Paste your Figma file URL + Personal Access Token
5. Penpot imports components, styles, and layout
What imports well:
- Vector shapes and SVG paths
- Text layers and fonts
- Component definitions
- Color styles
Known limitations:
- Auto-layout import is approximate
- Some advanced Figma plugins don't transfer
- Complex boolean operations may need manual adjustment
Backup Strategy
#!/bin/bash
# backup-penpot.sh
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups/penpot"
mkdir -p $BACKUP_DIR
# Backup PostgreSQL
docker compose exec -T penpot-postgres pg_dump \
-U penpot penpot | gzip > $BACKUP_DIR/db_$DATE.sql.gz
# Backup file assets
tar -czf $BACKUP_DIR/assets_$DATE.tar.gz \
$(docker volume inspect penpot_assets --format '{{ .Mountpoint }}')
# Rotate: keep 7 days
find $BACKUP_DIR -mtime +7 -delete
echo "Backup complete: $DATE"
chmod +x backup-penpot.sh
# Add to cron: 0 3 * * * /opt/penpot/backup-penpot.sh
Penpot vs Figma: Is It Ready?
| Feature | Figma | Penpot |
|---|---|---|
| Vector design | ✅ | ✅ |
| Real-time collaboration | ✅ | ✅ |
| Prototyping | ✅ | ✅ |
| Components/libraries | ✅ | ✅ |
| Dev inspect (CSS) | ✅ | ✅ |
| Auto-layout | ✅ Advanced | ⚠️ Basic |
| Variables/tokens | ✅ | ✅ (v2) |
| Plugins | ✅ Extensive | ⚠️ Growing |
| Mobile app | ✅ | ❌ |
| AI features | ✅ | ❌ |
| Self-hosting | ❌ | ✅ |
| Price (10 seats) | $150/mo | ~$10/mo server |
Penpot is ready for teams that value ownership, privacy, and cost — especially if you're building products that don't rely heavily on Figma's plugin ecosystem.
Troubleshooting
Backend not starting:
docker compose logs penpot-backend | tail -50
# Common: database connection failure — check PENPOT_DATABASE_URI
Assets not loading after reverse proxy:
# Ensure the reverse proxy passes the correct headers
# X-Forwarded-Proto: https
# X-Forwarded-Host: design.yourdomain.com
Exporter crashes:
docker compose logs penpot-exporter | tail -20
# Exporter uses Chromium internally — needs 512MB+ RAM headroom
Penpot is one of the most popular open source tools on OSSAlt — see all self-hosted Figma alternatives.