---
title: 2. Penpot Configuration
desc: Learn about self-hosting, configuration via environment variables, and authentication providers. Try Penpot - It's free! See Penpot's technical guide.
---
# Penpot Configuration
This section explains the configuration options, both for self-hosting and developer setup.
Penpot is configured using environment variables and flags.
## How the configuration works
Penpot is configured using environment variables and flags. **Environment variables** start
with PENPOT_. **Flags** use the format
-.
Flags are used to enable/disable a feature or behaviour (registration, feedback),
while environment variables are used to configure the settings (auth, smtp, etc).
Flags and environment variables are also used together; for example:
```bash
# This flag enables the use of SMTP email
PENPOT_FLAGS: [...] enable-smtp
# These environment variables configure the specific SMTP service
# Backend
PENPOT_SMTP_HOST:
PENPOT_SMTP_PORT: 587
```
**Flags** are configured in a single list, no matter they affect the backend, the frontend,
the exporter, or all of them; on the other hand, **environment variables** are configured for
each specific service. For example:
```bash
PENPOT_FLAGS: [...] enable-login-with-google
# Backend
PENPOT_GOOGLE_CLIENT_ID:
PENPOT_GOOGLE_CLIENT_SECRET:
```
Check the configuration guide for [Elestio][1] or [Docker][2]. Additionally, if you are using
the developer environment, you may override its values in the startup scripts,
as explained in the [Developer Guide][3].
**NOTE**: All the examples that have value represent the **default** value, and the
examples that do not have value are optional, and inactive or disabled by default.
## Telemetries
Penpot uses anonymous telemetries from the self-hosted instances to improve the platform experience.
Consider sharing these anonymous telemetries enabling the corresponding flag:
```bash
PENPOT_FLAGS: [...] enable-telemetries
```
## Registration and authentication
There are different ways of registration and authentication in Penpot:
- email/password
- Authentication providers like Google, Github or GitLab
- LDAP
You can choose one of them or combine several methods, depending on your needs.
By default, the email/password registration is enabled and the rest are disabled.
### Penpot
This method of registration and authentication is enabled by default. For a production environment,
it should be configured next to the SMTP settings, so there is a proper registration and verification
process.
You may want to restrict the registrations to a closed list of domains,
or exclude a specific list of domains:
```bash
# Backend
# comma separated list of domains
PENPOT_REGISTRATION_DOMAIN_WHITELIST:
# Backend
# or a file with a domain per line
PENPOT_EMAIL_DOMAIN_WHITELIST: path/to/whitelist.txt
PENPOT_EMAIL_DOMAIN_BLACKLIST: path/to/blacklist.txt
```
__Since version 2.1__
Email whitelisting should be explicitly
enabled with enable-email-whitelist flag. For backward compatibility, we
autoenable it when PENPOT_REGISTRATION_DOMAIN_WHITELIST is set with
not-empty content.
Penpot also comes with an option to completely disable the registration process;
for this, use the following flag:
```bash
PENPOT_FLAGS: [...] disable-registration
```
This option is only recommended for demo instances, not for production environments.
### Authentication Providers
To configure the authentication with third-party auth providers you will need to
configure Penpot and set the correct callback of your Penpot instance in the auth-provider
configuration.
The callback has the following format:
```html
https:///api/auth/oidc/callback
```
#### Google
Allows integrating with Google as OAuth provider:
```bash
PENPOT_FLAGS: [...] enable-login-with-google
# Backend only:
PENPOT_GOOGLE_CLIENT_ID:
PENPOT_GOOGLE_CLIENT_SECRET:
```
#### GitLab
Allows integrating with GitLab as OAuth provider:
```bash
PENPOT_FLAGS: [...] enable-login-with-gitlab
# Backend only
PENPOT_GITLAB_BASE_URI: https://gitlab.com
PENPOT_GITLAB_CLIENT_ID:
PENPOT_GITLAB_CLIENT_SECRET:
```
#### GitHub
Allows integrating with GitHub as OAuth provider:
```bash
PENPOT_FLAGS: [...] enable-login-with-github
# Backend only
PENPOT_GITHUB_CLIENT_ID:
PENPOT_GITHUB_CLIENT_SECRET:
```
#### OpenID Connect
__Since version 1.5.0__
Allows integrating with a generic authentication provider that implements the OIDC
protocol (usually used for SSO).
All the other options are backend only:
```bash
PENPOT_FLAGS: [...] enable-login-with-oidc
# Backend
PENPOT_OIDC_CLIENT_ID:
# Mainly used for auto discovery the openid endpoints
PENPOT_OIDC_BASE_URI:
PENPOT_OIDC_CLIENT_SECRET:
# Optional backend variables, used mainly if you want override; they are
# autodiscovered using the standard openid-connect mechanism.
PENPOT_OIDC_AUTH_URI:
PENPOT_OIDC_TOKEN_URI:
PENPOT_OIDC_USER_URI:
PENPOT_OIDC_JWKS_URI:
# Optional list of roles that users are required to have. If no role
# is provided, roles checking disabled.
PENPOT_OIDC_ROLES: "role1 role2"
# Attribute to use for lookup roles on the user object. Optional, if
# not provided, the roles checking will be disabled.
PENPOT_OIDC_ROLES_ATTR:
```
For self-hosted and containerized deployments, the autodiscovered OIDC endpoints are
not always enough. Some providers expose browser-facing endpoints through a public
hostname while the Penpot backend must reach the same provider through an
internal/container-resolvable hostname. In that case, explicitly set the OIDC endpoint
overrides above so the browser can use the public authorization endpoint while the
backend uses reachable token, userinfo, and JWKS endpoints.
If the backend needs to contact the OIDC provider through a hostname not already allowed
by SSRF protection, add it to:
```bash
# Backend
# Space separated list of allowed hosts
PENPOT_SSRF_ALLOWED_HOSTS: " "
```
This is commonly required when the provider is reachable from the browser via a public
URL but from the backend via a different internal hostname.
__Since version 1.6.0__
Added the ability to specify custom OIDC scopes.
```bash
# This settings allow overwrite the required scopes, use with caution
# because Penpot requires at least `name` and `email` attrs found on the
# user info. Optional, defaults to `openid profile`.
PENPOT_OIDC_SCOPES: "scope1 scope2"
```
__Since version 1.12.0__
Added the ability to specify the name and email attribute to use from
the userinfo object for the profile creation.
```bash
# Attribute to use for lookup the name on the user object. Optional,
# if not provided, the `name` prop will be used.
PENPOT_OIDC_NAME_ATTR:
# Attribute to use for lookup the email on the user object. Optional,
# if not provided, the `email` prop will be used.
PENPOT_OIDC_EMAIL_ATTR:
```
__Since version 1.19.0__
Introduced the ability to lookup the user info from the token instead
of making a request to the userinfo endpoint. This reduces the latency
of OIDC login operations and increases compatibility with some
providers that exposes some claims on tokens but not in userinfo
endpoint.
```bash
# Set the default USER INFO source. Can be `token` or `userinfo`. By default
# is unset (both will be tried, starting with token).
PENPOT_OIDC_USER_INFO_SOURCE:
```
__Since version 2.1.2__
Allows users to register and login with oidc without having to previously
register with another method.
```bash
PENPOT_FLAGS: [...] enable-oidc-registration
```
__Since version 2.16.0__
Allows customising the label shown on the OIDC login button (defaults to "OpenID").
```bash
# Frontend
PENPOT_OIDC_NAME:
```
#### Azure Active Directory using OpenID Connect
Allows integrating with Azure Active Directory as authentication provider:
```bash
# Backend & Frontend
PENPOT_OIDC_CLIENT_ID:
# Backend
PENPOT_OIDC_BASE_URI: https://login.microsoftonline.com//v2.0/
PENPOT_OIDC_CLIENT_SECRET:
```
### LDAP
Penpot comes with support for *Lightweight Directory Access Protocol* (LDAP). This is the
example configuration we use internally for testing this authentication backend.
```bash
PENPOT_FLAGS: [...] enable-login-with-ldap
# Backend
PENPOT_LDAP_HOST: ldap
PENPOT_LDAP_PORT: 10389
PENPOT_LDAP_SSL: false
PENPOT_LDAP_STARTTLS: false
PENPOT_LDAP_BASE_DN: ou=people,dc=planetexpress,dc=com
PENPOT_LDAP_BIND_DN: cn=admin,dc=planetexpress,dc=com
PENPOT_LDAP_BIND_PASSWORD: GoodNewsEveryone
PENPOT_LDAP_USER_QUERY: (&(|(uid=:username)(mail=:username))(memberOf=cn=penpot,ou=groups,dc=my-domain,dc=com))
PENPOT_LDAP_ATTRS_USERNAME: uid
PENPOT_LDAP_ATTRS_EMAIL: mail
PENPOT_LDAP_ATTRS_FULLNAME: cn
PENPOT_LDAP_ATTRS_PHOTO: jpegPhoto
```
## Penpot URI
You will need to set the PENPOT_PUBLIC_URI environment variable in case you go to serve Penpot to the users;
it should point to public URI where users will access the application:
```bash
# Backend
PENPOT_PUBLIC_URI: https://penpot.mycompany.com
# Frontend
PENPOT_PUBLIC_URI: https://penpot.mycompany.com
# Exporter
PENPOT_PUBLIC_URI: https://penpot.mycompany.com
```
If you're using the official docker-compose.yml you only need to configure the
PENPOT_PUBLIC_URI envvar in the top of the file.
If you plan to serve Penpot under different domain than `localhost` without HTTPS,
you need to disable the `secure` flag on cookies, with the `disable-secure-session-cookies` flag.
This is a configuration NOT recommended for production environments; as some browser APIs do
not work properly under non-https environments, this unsecure configuration
may limit the usage of Penpot; as an example, the clipboard does not work with HTTP.
## Email configuration
By default, smtp flag is disabled, the email will be
printed to the console, which means that the emails will be shown in the stdout.
Note that if you plan to invite members to a team, it is recommended that you enable SMTP
as they will need to login to their account after receiving the invite link sent an in email.
It is currently not possible to just add someone to a team without them accepting an
invitation email.
If you have an SMTP service, uncomment the appropriate settings section in
docker-compose.yml and configure those
environment variables.
Setting up the default FROM and REPLY-TO:
```bash
# Backend
PENPOT_SMTP_DEFAULT_REPLY_TO: Penpot
PENPOT_SMTP_DEFAULT_FROM: Penpot
```
Enable SMTP:
```bash
PENPOT_FLAGS: [...] enable-smtp
# Backend
PENPOT_SMTP_HOST:
PENPOT_SMTP_PORT: 587
PENPOT_SMTP_USERNAME:
PENPOT_SMTP_PASSWORD:
PENPOT_SMTP_TLS: true
```
If you are not using SMTP configuration and want to log the emails in the console, you should use the following flag:
```bash
PENPOT_FLAGS: [...] enable-log-emails
```
## Valkey
The Valkey configuration is very simple, just provide a valid redis URI. Valkey is used
mainly for websocket notifications coordination.
```bash
# Backend
PENPOT_REDIS_URI: redis://localhost/0
# Exporter
PENPOT_REDIS_URI: redis://localhost/0
```
If you are using the official docker compose file, this is already configured.
## Demo environment
Penpot comes with facilities to create a demo environment so you can test the system quickly.
This is an example of a demo configuration:
```bash
PENPOT_FLAGS: disable-registration enable-demo-users enable-demo-warning
```
**disable-registration** prevents any user from registering in the platform.
**enable-demo-users** creates users with a default expiration time of 7 days, and
once expired they are completely deleted with all the generated content.
From the registration page, there is a link with a `Create demo account` which creates one of these
users and logs in automatically.
**enable-demo-warning** is a modal in the registration and login page saying that the
environment is a testing one and the data may be wiped without notice.
Another way to work in a demo environment is allowing users to register but removing the
verification process:
```bash
PENPOT_FLAGS: disable-email-verification enable-demo-warning
```
## Air gapped environments
The current Penpot installation defaults to several external proxies:
- to Github, from where the libraries and templates are downloaded
- to Google, from where the google-fonts are downloaded.
This is implemented as specific locations in the penpot-front Nginx. If your organization needs to install Penpot
in a 100% air-gapped environment, you can use the following configuration:
```bash
PENPOT_FLAGS: [...] enable-air-gapped-conf
```
When Penpot starts, it will leave out the Nginx configuration related to external requests. This means that,
with this flag enabled, the Penpot configuration will disable as well the libraries and templates dashboard and the use of Google fonts.
## Security headers
The frontend container always emits `X-Content-Type-Options`, `Referrer-Policy`,
`Permissions-Policy` and `X-Frame-Options`. Two additional headers are configurable.
### Content Security Policy
Penpot ships a Content Security Policy in **report-only** mode by default. In this mode
browsers report violations to the developer console but do not block anything, which makes
it safe to enable everywhere while the policy is being tuned.
```bash
PENPOT_CSP_MODE: report-only # report-only (default) | enforce | disabled
```
The default policy is same-origin except for what the application genuinely requires:
`'wasm-unsafe-eval'` for the render engine, `'unsafe-inline'` styles for the inline style
attributes emitted by the UI, and `blob:`/`data:` for thumbnails, exports and fonts. The
external Google Fonts and GitHub templates endpoints do not need entries of their own
because they are reverse proxied by the frontend container.
Two known sources of violations remain, and both are the reason `enforce` is not yet the
default:
- The `index.html` inline `