Penpot è una piattaforma di design open-source che si propone come alternativa self-hosted a strumenti come Figma e Adobe XD. È sviluppata da un team spagnolo (Kaleidos) e supportata da una community in costante crescita, con il codice sorgente disponibile su GitHub sotto licenza MPL 2.0. La piattaforma permette di creare interfacce utente, prototipi interattivi e sistemi di design completi, il tutto direttamente dal browser senza installare alcun software sui dispositivi dei designer.
A differenza di molte alternative, Penpot utilizza standard web aperti come SVG per la grafica e CSS per il layout, rendendo i progetti facilmente esportabili e riutilizzabili al di fuori della piattaforma stessa. Questo approccio lo rende particolarmente interessante per team che vogliono mantenere il pieno controllo sui propri asset di design senza vincolarsi a formati proprietari.
Processo di Installazione
Dopo aver installato Docker Engine e Docker Compose, è possibile procedere con l’installazione di Penpot. L’architettura del servizio è composta da diversi container che lavorano insieme: il frontend che serve l’interfaccia web, il backend che gestisce la logica applicativa, un servizio di esportazione per generare file PDF e SVG, un database PostgreSQL per la persistenza dei dati e Valkey (fork open-source di Redis) per la gestione delle notifiche WebSocket, delle sessioni e delle code di esportazione.
Il diagramma seguente illustra come i servizi comunicano tra loro all’interno della rete Docker:
Nginx · :8080"] Backend["Backend
Clojure/JVM"] Exporter["Exporter
Chromium headless"] Postgres["PostgreSQL 15
Database"] Valkey["Valkey 8.1
Cache / WebSocket"] Assets[("📁 Volume
penpot_assets")] end User -- "porta 9001" --> Frontend Frontend -- "API proxy" --> Backend Frontend -. "serve file statici" .-> Assets Backend -- "query SQL" --> Postgres Backend -- "notifiche real-time" --> Valkey Backend -. "legge/scrive asset" .-> Assets Exporter -- "renderizza progetti" --> Frontend Exporter -- "gestione code" --> Valkey
Creiamo il File Docker Compose
Il file docker-compose.yml qui sotto configura l’intero stack di Penpot seguendo le ultime raccomandazioni ufficiali. Il servizio sarà raggiungibile sulla porta 9001.
services:
penpot-frontend:
image: penpotapp/frontend:${PENPOT_VERSION:-latest}
container_name: penpot_frontend
restart: always
ports:
- 9001:8080
volumes:
- penpot_assets:/opt/data/assets
depends_on:
- penpot-backend
- penpot-exporter
penpot-backend:
image: penpotapp/backend:${PENPOT_VERSION:-latest}
container_name: penpot_backend
restart: always
volumes:
- penpot_assets:/opt/data/assets
depends_on:
penpot-postgres:
condition: service_healthy
penpot-valkey:
condition: service_healthy
environment:
PENPOT_FLAGS: ${PENPOT_FLAGS}
PENPOT_PUBLIC_URI: ${PENPOT_PUBLIC_URI}
PENPOT_SECRET_KEY: ${PENPOT_SECRET_KEY}
PENPOT_DATABASE_URI: postgresql://penpot-postgres/${PENPOT_DATABASE_NAME}
PENPOT_DATABASE_USERNAME: ${PENPOT_DATABASE_USER}
PENPOT_DATABASE_PASSWORD: ${PENPOT_DATABASE_PASSWORD}
PENPOT_REDIS_URI: redis://penpot-valkey/0
# Configurazione Storage (Versione 2.11+)
PENPOT_OBJECTS_STORAGE_BACKEND: fs
PENPOT_OBJECTS_STORAGE_FS_DIRECTORY: /opt/data/assets
PENPOT_HTTP_SERVER_MAX_BODY_SIZE: 384000000
PENPOT_TELEMETRY_ENABLED: "false"
PENPOT_TELEMETRY_REFERER: compose
## Configurazione SMTP (opzionale, vedi sezione dedicata)
# PENPOT_SMTP_DEFAULT_FROM: no-reply@example.com
# PENPOT_SMTP_HOST: penpot-mailcatch
# PENPOT_SMTP_PORT: 1025
penpot-exporter:
image: penpotapp/exporter:${PENPOT_VERSION:-latest}
container_name: penpot_exporter
restart: always
depends_on:
penpot-valkey:
condition: service_healthy
environment:
PENPOT_PUBLIC_URI: http://penpot-frontend:8080
PENPOT_SECRET_KEY: ${PENPOT_SECRET_KEY}
PENPOT_REDIS_URI: redis://penpot-valkey/0
penpot-postgres:
image: postgres:15
container_name: penpot_postgres
restart: always
stop_signal: SIGINT
volumes:
- penpot_database:/var/lib/postgresql/data
environment:
POSTGRES_INITDB_ARGS: --data-checksums
POSTGRES_DB: ${PENPOT_DATABASE_NAME}
POSTGRES_USER: ${PENPOT_DATABASE_USER}
POSTGRES_PASSWORD: ${PENPOT_DATABASE_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${PENPOT_DATABASE_USER} -d ${PENPOT_DATABASE_NAME}"]
interval: 5s
timeout: 5s
retries: 5
penpot-valkey:
image: valkey/valkey:8.1
container_name: penpot_valkey
restart: always
environment:
- VALKEY_EXTRA_FLAGS=--maxmemory 128mb --maxmemory-policy volatile-lfu
healthcheck:
test: ["CMD-SHELL", "valkey-cli ping | grep PONG"]
interval: 2s
timeout: 3s
retries: 5
# Servizio opzionale per testare le email localmente
penpot-mailcatch:
image: sj26/mailcatcher:latest
container_name: penpot_mailcatch
restart: always
ports:
- "1080:1080" # Interfaccia Web per leggere le email
volumes:
penpot_database:
penpot_assets:Servizio Frontend
Il frontend è un server Nginx che serve l’interfaccia web e fa da proxy verso il backend. Il volume penpot_assets è condiviso per servire direttamente file statici, immagini e font caricati dagli utenti.
Servizio Backend
È il cuore dell’applicazione. Dalla versione 2.11, Penpot utilizza le variabili PENPOT_OBJECTS_STORAGE_* per gestire i file binari. La variabile PENPOT_PUBLIC_URI è fondamentale per la corretta generazione dei link nelle email e per le operazioni dell’exporter.
Servizio Exporter
Gestisce la generazione di PDF e immagini. Ora richiede l’accesso a Valkey (PENPOT_REDIS_URI) e la PENPOT_SECRET_KEY per coordinare le code di esportazione in modo sicuro.
Servizio Database
PostgreSQL 15 con checksum dei dati abilitato. Il database non è esposto all’esterno per sicurezza.
Servizio Valkey
Viene utilizzata l’ultima versione di Valkey (8.1), un fork open-source di Redis ad alte prestazioni. Gestisce le notifiche real-time, le sessioni e le code di lavoro.
Creiamo il File .env
Il file .env contiene le credenziali e le impostazioni fondamentali.
Per generare la PENPOT_SECRET_KEY (stringa di almeno 64 caratteri), puoi usare:
python3 -c "import secrets; print(secrets.token_urlsafe(64))"PENPOT_VERSION=latest
PENPOT_PUBLIC_URI=http://localhost:9001
PENPOT_FLAGS=disable-registration enable-login-with-password disable-secure-session-cookies
PENPOT_SECRET_KEY=SOSTITUIRE-CON-CHIAVE-GENERATA
PENPOT_DATABASE_NAME=penpot
PENPOT_DATABASE_USER=penpot
PENPOT_DATABASE_PASSWORD=5up3r_P4s5w0rd_DBLa variabile PENPOT_FLAGS controlla le funzionalità attive. In questa configurazione la registrazione pubblica è disabilitata (disable-registration) e i cookie sicuri sono disattivati per l’uso in locale senza HTTPS.
Cookie sicuri e HTTPS
Una volta configurato un reverse proxy con HTTPS, rimuovi il flagdisable-secure-session-cookies e assicurati che PENPOT_PUBLIC_URI utilizzi il protocollo https://.
Primo Avvio
Una volta creati i file docker-compose.yml e .env, è possibile avviare lo stack con il comando:
docker compose up -dAl primo avvio i container impiegheranno qualche secondo in più per inizializzare il database e scaricare le dipendenze interne. Una volta pronto, il servizio sarà raggiungibile all’indirizzo http://<indirizzo-server>:9001.
Dato che la registrazione è disabilitata nella configurazione proposta, il primo utente va creato manualmente tramite il terminale con il seguente comando:
docker exec -ti penpot_backend python3 manage.py create-profileLo script chiederà interattivamente email, nome completo e password per il nuovo account. Una volta completata la procedura sarà possibile effettuare il login dall’interfaccia web.
Registrazione aperta
Se si preferisce consentire la registrazione direttamente dall’interfaccia web, è sufficiente rimuovere il flagdisable-registration dal file .env e riavviare lo stack. In questo caso il primo utente potrà registrarsi normalmente dal browser. È consigliabile riaggiungere il flag dopo aver creato tutti gli account necessari, soprattutto se il servizio è esposto su internet.
Configurazione SMTP
L’invio di email non è strettamente necessario per il funzionamento di Penpot, ma diventa importante se si vuole abilitare la verifica degli indirizzi email, il recupero password o le notifiche di invito ai team. Per attivare l’SMTP è sufficiente decommentare le variabili nel file docker-compose.yml e compilarle con i dati del proprio server di posta.
Dopo aver configurato l’SMTP, aggiungere il flag enable-email-verification alla variabile PENPOT_FLAGS nel file .env per attivare la verifica degli indirizzi email alla registrazione.
Troubleshooting & Consigli
Di seguito alcuni consigli utili per risolvere i problemi di configurazione più comuni:
- Se Penpot mostra una pagina bianca dopo il login, verificare che la
PENPOT_SECRET_KEYsia la stessa per tutti gli avvii. Se la chiave cambia, i token di sessione esistenti diventano invalidi. Rigenerare la chiave significa che tutti gli utenti dovranno effettuare nuovamente il login. - Se l’exporter non funziona e le esportazioni in PDF restano in attesa, verificare che il container
penpot_exportersia attivo e che la variabilePENPOT_PUBLIC_URIpunti correttamente al frontend sulla rete Docker interna. - Per esporre Penpot su internet, configurare un reverse proxy (es. Caddy
o NGINX Proxy Manager
) con HTTPS e un certificato SSL valido. Dopo la configurazione, rimuovere il flag
disable-secure-session-cookiesdal file.enve riavviare lo stack. - Per eseguire il backup del database, è possibile utilizzare
pg_dumpdirettamente dal container PostgreSQL con il comando:Oltre al database, è consigliabile effettuare il backup anche del volumebashdocker exec penpot_postgres pg_dump -U penpot penpot > backup_penpot.sqlpenpot_assetsche contiene tutti i file caricati dagli utenti. - Per aggiornare Penpot, modificare la variabile
PENPOT_VERSIONnel file.envcon la versione desiderata (o lasciarelatest) ed eseguiredocker compose pull && docker compose up -d.