Penpot
Overview
Penpot is the open source design and prototyping platform, a self-hostable alternative to Figma. It gives design and product teams a complete browser-based workspace for UI design, vector illustration, interactive prototyping and developer hand-off, all under your own control.
The SecureAnyCloud image installs Penpot 2.5.4 as the official self-host Docker Compose stack and runs it as a systemd service. A complete design platform is online within minutes of launch.
What you get:
- Penpot 2.5.4 (Mozilla Public License 2.0), deployed from the official self-host Docker Compose stack and pinned so the image never silently upgrades at build time
- Docker Engine (Docker CE) and the Docker Compose plugin, installed from the official Docker package repository
- The Penpot Compose stack:
penpot-frontend(the nginx-based SPA and reverse proxy),penpot-backend(the application server),penpot-exporter(the headless-browser export and render service),penpot-postgres(PostgreSQL 15, the primary database) andpenpot-redis(the cache, queue and realtime pub/sub) - The bundled nginx frontend publishing the Penpot UI, the REST/RPC API (
/api) and a static unauthenticated health endpoint (/health) on port 80 - All stateful data (the PostgreSQL database, the Redis data and every uploaded design asset) on a dedicated 40 GiB data disk mounted at
/var/lib/penpot, with Docker's data-root relocated there. The disk is independently resizable and re-provisioned on every VM - Open self-registration disabled, and a per-VM admin account (email and a generated password) created at first boot
- Two systemd units:
penpot.service(a oneshot wrapper arounddocker compose up -d) andpenpot-firstboot.service - 24/7 SecureAnyCloud support
Prerequisites
You need an active Azure subscription, an SSH key, and a VNet and subnet.
Standard_B4ms (4 vCPU / 16 GB RAM) is the recommended size. It is comfortable for the five-container Penpot stack.
Configure the NSG to allow 22/tcp from your management CIDR for SSH and 80/tcp from the CIDR that needs the Penpot UI. Add 443/tcp if you enable HTTPS.
Connect over SSH
Replace <vm-ip> with the public IP address of your VM. The default login user is azureuser.
ssh azureuser@<vm-ip>Confirm the services are active
sudo systemctl is-active docker.service penpot.service docker --version docker compose versionThe output shows active twice, then the Docker Engine version and the Docker Compose v2 plugin version.
Confirm the Penpot containers are running
sudo docker ps --format "table {{.Names}}\t{{.Status}}"You should see all five Penpot containers in the Up / healthy state: penpot-frontend, penpot-backend, penpot-exporter, penpot-postgres and penpot-redis.
Confirm the data disk is mounted
All stateful Penpot data lives on a dedicated data disk mounted at /var/lib/penpot. Check the mount:
findmnt /var/lib/penpot df -h /var/lib/penpotfindmnt shows the device that backs /var/lib/penpot, and df confirms the 40 GiB volume.
Check the Penpot health endpoint
The bundled nginx frontend serves the health endpoint on port 80 without authentication. Request it:
curl -s -o /dev/null -w "%{http_code}\n" http://localhost/healthA 200 response confirms that the frontend is up and serving.
Read the per-VM admin credentials
On first boot, your instance generates a unique admin email and password and writes them to a root-only file. Open self-registration is disabled, so this admin is the only login until you invite more users from inside Penpot.
sudo cat /root/penpot-credentials.txtThe file lists PENPOT_URL (where to sign in), PENPOT_ADMIN_EMAIL and PENPOT_ADMIN_PASSWORD. Store the password somewhere safe.
Sign in to Penpot
Browse to http://<vm-ip>/. Sign in with the PENPOT_ADMIN_EMAIL and PENPOT_ADMIN_PASSWORD from Step 6. The bundled nginx frontend serves the Penpot UI and API on port 80.
After you sign in, the projects dashboard opens, scoped to your default team. Create a project and your first file to start designing.
Design and prototype
Open a file to enter the Penpot design workspace. It is a full vector design and layout canvas with layers, components, shared libraries, flex and grid layout, and real-time multiplayer editing.
Switch to the prototype view to wire boards together into interactive flows. You can play the flows back and share them for review.
Invite your team
Open registration is disabled on this appliance, so new users join by invitation instead of self-signup. In your team's Members settings inside Penpot, send email invitations to add designers and stakeholders.
Penpot supports per-team roles, so you control who can edit and who can only view.
Manage the stack
The penpot.service systemd unit manages the whole stack. It wraps docker compose under /opt/penpot.
sudo systemctl restart penpot.service
sudo docker compose -f /opt/penpot/docker-compose.yaml pssystemctl restart cleanly recreates the Compose stack, and docker compose ps lists the containers and their health.
Enable HTTPS for production (recommended)
The image serves plain HTTP on port 80, so it works out of the box on the VM's public IP. For production, put Penpot behind TLS with your own domain.
Point a DNS record at the VM and open 443/tcp in the NSG. Terminate TLS with a reverse proxy such as Caddy or nginx, or obtain a certificate with certbot. Then set PENPOT_PUBLIC_URI to your https:// URL in /opt/penpot/.env and restart penpot.service.
Until you do, use the plain-HTTP endpoint for evaluation only.
Support
SecureAnyCloud provides 24/7 support for this image. Penpot is a trademark of its respective owners. SecureAnyCloud packages and supports the open source distribution and is not affiliated with or endorsed by the Penpot project. The software is licensed under the Mozilla Public License 2.0.
Deploy on Azure
Launch Penpot 2.5.4 on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
This image runs Penpot, the open source design and prototyping platform for building user interfaces and design systems. Penpot is a self-hostable alternative to Figma. It runs entirely in the browser, is collaborative by default, and uses open, standards-based files, so designers and developers can work from the same source of truth.
The image deploys Penpot from the official self-host Docker Compose stack, pinned at build time to the Penpot 2.5.4 image set. It ships a fixed release and never silently upgrades.
What you get:
- Five containers: the frontend (a bundled nginx that publishes the single-page application and proxies the API on port 80), the backend application server, the exporter (a headless render and export service), PostgreSQL 15 (the primary database) and Redis (cache, queue and realtime)
- Only port 80 published to the host. Every backing service stays on the private Docker network and is never exposed on any external interface
- All stateful data (the PostgreSQL database, the Redis data and your uploaded design assets) on a dedicated EBS data volume. The Docker data root and the containerd root are both relocated onto that volume, so container image layers and named volumes live on their own independently resizable disk instead of the operating system disk. The volume is captured into the image and re-provisioned on every instance
- A one-shot first-boot service that generates a unique per-instance secret key and database password, points the public URL at the instance address, recreates the stack on a fresh database, and creates a single per-instance administrator account with a random password
- Sign-in details recorded in
/root/penpot-credentials.txtwith mode 0600 - Open self-registration disabled, and no shared or default credentials in the image
- 24/7 technical support from SecureAnyCloud
Prerequisites
Before you deploy this image, you need:
- An Amazon Web Services account where you can launch EC2 instances
- IAM permissions to launch instances, create security groups, and subscribe to AWS Marketplace products
- An EC2 key pair in the target Region for SSH access to the instance
- A VPC and subnet in the target Region, with a security group that allows inbound port 22 from your management network and inbound port 80 (and 443 once you add TLS) from the networks your users will reach Penpot on
- An instance type with at least 8 GB of memory. The five-container stack needs headroom, so m5.large or larger is recommended
- The AWS CLI (version 2) installed locally, if you plan to deploy from the command line
Launch the instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images, choose AWS Marketplace AMIs and search for Penpot. Select the SecureAnyCloud listing, choose Select, then choose Continue on the subscription summary.
Pick an instance type of m5.large or larger. Choose your EC2 key pair under Key pair (login). Under Network settings, select your VPC and subnet, then create or select a security group that allows inbound port 22 from your management network and inbound port 80 from the networks your users use.
Leave the root volume at the default size or larger. The image adds a separate data volume for the database, cache and design assets automatically.
Select Launch instance. First-boot initialization takes a few minutes after the instance state becomes Running and the status checks pass. During that time the stack starts on a fresh database and the administrator account is created.
Launch the instance from the AWS CLI
The following command launches an instance from the SecureAnyCloud Penpot Marketplace AMI into an existing subnet and security group.
Replace ami-0example00000000 with the AMI ID shown on the Marketplace listing. Replace <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, and <security-group-id> with a security group that opens ports 22 and 80 as described above.
aws ec2 run-instances \
--image-id ami-0example00000000 \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":30,"VolumeType":"gp3"}}]' \
--metadata-options 'HttpTokens=required' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=penpot}]'Connect and retrieve the admin password
Connect over SSH with the key pair you selected and the public IP address of the instance. The SSH login user depends on the operating system of the AMI variant you launched (see the table at the end of this guide). On the Ubuntu variant it is ubuntu. Replace <public-ip> with your instance's public IP address:
ssh -i /path/to/your-key.pem ubuntu@<public-ip>On first boot, the instance writes its unique administrator email, password and URL to a root-only file. Print them with:
sudo cat /root/penpot-credentials.txtThe file lists PENPOT_URL, PENPOT_ADMIN_EMAIL and PENPOT_ADMIN_PASSWORD. Keep these safe. They are unique to this instance and are its only administrator credentials.
First sign-in
Open the PENPOT_URL from the credentials file in your browser, for example http://<public-ip>/. Penpot shows its sign-in page. Enter the administrator email and password from the credentials file and choose Login.
After you sign in, the Penpot dashboard opens. Your projects and files live there, and you start new designs from it.
Open self-registration is disabled, so invite additional team members from the team settings.
Create a design file
From the dashboard, choose + New File, or import one of the built-in templates, to open the design workspace.
The workspace has the pages and layers panel on the left and the design and prototype panels on the right. The canvas in the center is where you compose boards, shapes, text and components.
Preview a prototype
Penpot lets you wire boards together into interactive prototypes and preview them in View mode. Choose the View mode control (the play icon, top right of the workspace) to open the viewer.
In the viewer, you can click through the flows exactly as an end user would. You can also share a read-only link with stakeholders.
Verify the service is healthy
systemd manages Penpot as penpot.service, which brings the Docker Compose stack up and down. Docker itself runs as docker.service. To confirm the stack is up, connect over SSH and run:
sudo systemctl is-active docker.service penpot.service cd /opt/penpot && sudo docker compose ps --status running --format '{{.Service}}' for i in $(seq 1 60); do
CODE=$(curl -s -o /dev/null -w '%{http_code}' http://localhost/health || echo 000) [ "$CODE" = "200" ] && break sleep 5 done echo "health endpoint: HTTP ${CODE}"A healthy instance reports active for both services, lists the five running containers, and returns HTTP 200 from the health endpoint:
active active penpot-frontend penpot-backend penpot-exporter penpot-postgres penpot-redis health endpoint: HTTP 200You can also confirm that the administrator credential authenticates end to end without revealing the password. This command reads the email and password from the root-only credentials file, posts them to the login endpoint, and prints only the resulting HTTP status (200 on success):
EMAIL=$(sudo grep '^PENPOT_ADMIN_EMAIL=' /root/penpot-credentials.txt | cut -d= -f2-)
PASS=$(sudo grep '^PENPOT_ADMIN_PASSWORD=' /root/penpot-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'login: HTTP %{http_code}\n' -X POST \
http://localhost/api/rpc/command/login-with-password \
-H 'Content-Type: application/json' \
-d "{\"email\":\"${EMAIL}\",\"password\":\"${PASS}\"}"A correct per-instance credential returns login: HTTP 200.
Enable HTTPS with your own domain
Penpot is served on plain HTTP port 80 out of the box. Before you expose it to production traffic, terminate TLS in front of it and use your own domain. Two common approaches work:
- Put an AWS Application Load Balancer or Amazon CloudFront in front of the instance, attach an AWS Certificate Manager certificate, and forward to the instance on port 80.
- Install a reverse proxy on the instance and obtain a certificate with Let's Encrypt. Point a DNS
Arecord at the instance and open port 443 in the security group. A typical certbot run then looks like the commands below (replace<your-domain>and<your-email>):
sudo apt-get update && sudo apt-get install -y nginx certbot python3-certbot-nginx
# proxy_pass http://127.0.0.1:80 in your nginx server block for <your-domain>, then:
sudo certbot --nginx -d <your-domain> -m <your-email> --agree-tos --no-eff-emailAfter you enable HTTPS, update PENPOT_PUBLIC_URI in /opt/penpot/.env to your https://<your-domain> URL. Then restart the stack with sudo systemctl restart penpot.service so generated links use the correct address.
Backups and maintenance
All Penpot state (the PostgreSQL database, Redis data and uploaded assets) lives on the dedicated data volume mounted at /var/lib/docker. The simplest backup is a point-in-time EBS snapshot of that volume, taken from the AWS console or CLI:
# identify the data volume attached to the instance, then snapshot it:
aws ec2 create-snapshot --volume-id <data-volume-id> --description "penpot data backup"For a logical database backup, dump the PostgreSQL database from inside its container, then copy the file off the instance:
cd /opt/penpot
sudo docker compose exec -T penpot-postgres pg_dump -U penpot penpot > penpot-db-backup.sqlKeep the operating system patched with your normal AWS patch process. The Penpot images are pinned by version, so the stack does not change until you deliberately update the image tags in /opt/penpot/docker-compose.yaml and /opt/penpot/.env.
Scaling and operations
Penpot runs comfortably on a single instance for most teams.
To scale vertically, stop the instance, change the instance type to one with more memory and vCPU, and start it again. The data volume and configuration are preserved. To grow storage, expand the data volume in the AWS console and grow the filesystem on the instance.
For high availability, you can move PostgreSQL and Redis to managed services (Amazon RDS for PostgreSQL and Amazon ElastiCache for Redis) and point the backend at them through /opt/penpot/.env.
Connecting to your instance
The SSH login user depends on the operating system of the AMI variant you launched:
AMI variant SSH login user
Ubuntu 24.04 ubuntu
Support
SecureAnyCloud publishes this image with 24/7 technical support by email and chat. Our engineers can help with deployment, TLS termination, backups, user management and scaling.
Penpot is open source software licensed under the Mozilla Public License 2.0. This image bundles it unmodified alongside PostgreSQL and Redis. Their licenses ship in /usr/share/doc/sac/third-party-licences on the instance.
Deploy on AWS
Launch Penpot on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com