Applications AWS

Penpot on AWS User Guide

| Product: Penpot on AWS

Overview

This image runs Penpot, the open source design and prototyping platform for building user interfaces and design systems. A self hostable alternative to Figma, Penpot runs entirely in the browser, is collaborative by default, and works with open, standards based files so designers and developers can work from the same source of truth.

Penpot is deployed from the official self host Docker Compose stack, pinned at build time to the Penpot 2.5.4 image set so the image ships a fixed release and never silently upgrades. Five containers make up the stack: 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 is published to the host; every backing service stays on the internal Docker network and is never exposed on any external interface.

All stateful data, the PostgreSQL database, the Redis data and your uploaded design assets, lives 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 land on their own independently resizable disk rather than the operating system disk. The volume is captured into the image and re-provisioned on every instance.

On the first boot of every deployed instance, a one shot service 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. The sign-in details are recorded in /root/penpot-credentials.txt with mode 0600. Open self registration is disabled and no shared or default credentials ship in the image.

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 allowing 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

Step 1: 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 cloudimg listing and choose Select, then 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, and either 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 initialisation takes a few minutes after the instance state becomes Running and the status checks pass, while the stack starts on a fresh database and the administrator account is created.

Step 2: Launch the Instance from the AWS CLI

The following block launches an instance from the cloudimg Penpot Marketplace AMI into an existing subnet and security group. Replace ami-0example00000000 with the AMI ID shown on the Marketplace listing, <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}]'

Step 3: 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>

The per instance administrator email, password and URL are written to a root only file on first boot. Print them with:

sudo cat /root/penpot-credentials.txt

The file lists PENPOT_URL, PENPOT_ADMIN_EMAIL and PENPOT_ADMIN_PASSWORD. Keep these safe; they are unique to this instance and are the only administrator credentials for it.

Step 4: First Sign-in

Open the PENPOT_URL from the credentials file in your browser (for example http://<public-ip>/). Penpot presents its sign-in page. Enter the administrator email and password from the credentials file and choose Login.

The Penpot sign-in page, prompting for the per instance administrator email and password generated on first boot

After signing in you land on the Penpot dashboard, where projects and draft files live and where you start new designs. Open self registration is disabled, so you invite additional team members from the team settings rather than letting them register themselves.

The Penpot dashboard showing projects, drafts and the template library

Step 5: Create a Design File

From the dashboard, choose + New File in the Drafts area (or import one of the built-in templates) to open the design workspace. The workspace gives you the pages and layers panel on the left, the design and prototype panels on the right, and the canvas in the centre where you compose boards, shapes, text and components.

The Penpot design workspace with a file open, showing pages, layers and boards on the canvas

Step 6: 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, where you can click through the flows exactly as an end user would and share a read only link with stakeholders.

The Penpot prototype viewer presenting a multi screen navigation flow in View mode

Step 7: Verify the Service Is Healthy

Penpot is managed by systemd 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 200

You can also confirm the administrator credential authenticates end to end without revealing the password. This block 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.

Step 8: Enable HTTPS with Your Own Domain

Penpot is served on plain HTTP port 80 out of the box. Before exposing it to production traffic, terminate TLS in front of it and use your own domain. Two common approaches:

  • 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.
  • Or install a reverse proxy on the instance and obtain a certificate with Let's Encrypt. After pointing a DNS A record at the instance and opening port 443 in the security group, a typical certbot run looks like the block 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-email

After enabling HTTPS, update PENPOT_PUBLIC_URI in /opt/penpot/.env to your https://<your-domain> URL and restart the stack with sudo systemctl restart penpot.service so generated links use the correct address.

Step 9: 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 and copy the file off the instance:

cd /opt/penpot
sudo docker compose exec -T penpot-postgres pg_dump -U penpot penpot > penpot-db-backup.sql

Keep the operating system patched with your normal AWS patch process. Because the Penpot images are pinned by version, the stack itself does not change until you deliberately update the image tags in /opt/penpot/docker-compose.yaml and /opt/penpot/.env.

Step 10: 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 via /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

This image is published by cloudimg with 24/7 technical support by email and chat. Our engineers can help with deployment, TLS termination, backups, user management and scaling. Penpot itself is open source software licensed under the Mozilla Public License 2.0; this image bundles it unmodified alongside PostgreSQL and Redis, whose licences ship in /usr/share/doc/cloudimg/third-party-licences on the instance.