Penpot is an open-source platform designed for product design and code collaboration. Self-hosted is not a single-container drawing tool: the official Compose runs frontend, backend, Exporter, MCP, Postgres, Valkey, and other services simultaneously, and stores the database and uploaded materials in persistent volumes. Therefore, after deployment, container health, HTTP access, registration policies, persistent volumes, and recovery processes must be verified simultaneously.
Project Address:
https://github.com/penpot/penpot
Official website:
Quick Conclusion
- Personal trials can directly access Penpot SaaS; Self-hosting is required for data control, intranet deployment, or compliance boundaries.
- The official Docker method requires Compose V2 and listens on
http://localhost:9001by default. - The downloaded sample Compose is for local trial and must be replaced before public network deployment
PENPOT_SECRET_KEY, Public URI, email, and security cookie settings. - Backups cannot be saved alone
docker-compose.yaml, and also cover Postgres withpenpot_assetsEndurance roll.
Download the official Compose and verify it first
|
|
config must exit with code zero. The service list should include the frontend, backend, database, and supporting components; the volume list should include Postgres data and assets. If YAML parsing fails, do not continue to up -d.
Keep the original file before modification to facilitate recovery:
|
|
Modifying Default Security Configuration Before Launch
The official example warns that public deployments must not retain disable-secure-session-cookies or disable-email-verification. Replace these placeholders as well:
PENPOT_PUBLIC_URI: Change to the final HTTPS domain.PENPOT_SECRET_KEY: do not leave it aschange-this-insecure-key.PENPOT_FLAGS: Decide whether to allow registration, verify emails, and enable MCP.- SMTP: In formal environments, do not treat Mailcatch as a real email service.
Generate random secrets using Python:
|
|
Run againdocker compose ... config, confirm that the variable can still be parsed after replacement. Do not submit Compose files containing Secret to public repositories.
Start and validate each service
|
|
Acceptance cannot be based solely on frontend return 200.docker compose psThere should be no services that continuously restart or exit, and backend logs should not repeatedly show database connection, migration, or secret errors.
If the page cannot be opened, check in order:
|
|
If the frontend is normal but login or save fails, you should usually continue to check the backend and Postgres, rather than just restarting the browser.
Create the first controlled account
Public network instances are not recommended to keep anonymous registration open for a long time. After closing registration, you can use the backend management command to create an account. First, find the actual container name:
|
|
Compose versions may use hyphens or underscores in container names, so do not copy the second command blindly. If the container is not found, use the name shown by docker compose ps. The management command also requires prepl-server on the backend.
Validate the HTTPS reverse proxy
Penpot’s public URI, browser-actually accessed domain name, and reverse proxy TLS domain must be consistent. After deploying the proxy, check from the external network:
|
|
When a redirect loop occurs, check firstPENPOT_PUBLIC_URIprotocol headers passed with the proxy; If you disconnect immediately after logging in, focus on checking for secure cookies and HTTPS. Do not reopen insecure cookies just for temporary use.
Validate design delivery with a minimal project
After completing the basic deployment, create a new testing team and documentation to at least verify:
- Two accounts can join the same team and see changes in real time.
- Create a component, a variant, and at least one Design Token.
- Development accounts can read SVG, CSS, or layout information in Inspect Mode.
- Export one
.penpotfile, then imported into the test space. - After uploading an image, refresh the page, but the material remains accessible.
These operations cover collaboration, the database, and the asset volume. Creating an empty file alone does not prove that the self-hosted data path works.
Back up the database and asset volume
The default Compose file uses two key volumes: Postgres data and penpot_assets. First, read their actual names:
|
|
Pausing writing and recording version before backup:
|
|
Then, follow the official Docker volume backup process to archive the database volume and the material volume separately. The backup files must be stored on the host or remote server, not in the container. After completion, restart and recheck:
|
|
Only archives that have actually been restored in the isolated environment are considered usable backups. Restoration acceptance should open the original test file, check the components, and confirm that the uploaded image still exists.
Prepare rollback points before updating
Do not overwrite the Compose file and immediately run pull. Preserve the current configuration, image information, and volume backups first:
|
|
Major version migrations may continue to run after startup. At this point, a page temporarily unavailable does not mean you should restart repeatedly; First, look at the migration logs. If the new version continues to fail, service should be stopped, the old Compose and matching image versions restored, and then the pre-upgrade volume backup should be restored. After the database has been migrated, simply reverting to the old image may not be safe.
Build a long-term design-to-development workflow
Teams can implement the process as follows:
- Designers create a Design System, with component names as closely as possible matching the frontend component library.
- Use Design Tokens for color, font size, and spacing, rather than scattered hand-filled values.
- Develop SVG, CSS, and layout information through Inspect Mode.
- Use test files to validate plugins, APIs, or MCPs to avoid directly operating with formal design assets.
- Before major version upgrades, export key files and back up server-side persistent volumes.
Fault Diagnosis Table
| Phenomenon | Key Examination | Recovery of Movement |
|---|---|---|
localhost:9001No response |
Frontend port, container state, host firewall | Recreate the container after restoring the original Compose |
| Page can be opened but cannot be logged in | Backend logs, Secret, Cookie, public URI | Restoring consistent domain name and security cookie configuration |
| Invitation emails not received | SMTP and email verification flags | Fix SMTP, do not disable authentication for long-term bypassing |
| Files can be opened but images are missing | penpot_assetsVolume or object storage |
Restore a backup of materials at the same time point in time as the database |
| Backend repeatedly restarts after upgrade | Database migration and image version | Stop writing and use the complete backup and recovery set before upgrade |
Penpot self-hosted completion criteria are: HTTPS domain availability, clear registration boundaries, two test users collaborating, Inspect Mode delivering styles, successful import and export, and both databases and materials having completed recovery drills. If any of these are missing, you should not migrate directly into the team’s only formal design files.