Install & Setup
Environment variables
Configure required values, secrets, your community address, email, and security options before the first start.
Installation
Prepare the host and start the deployment after reviewing configuration.
Docker Compose
Review commands, ports, and volumes for the standard deployment.
Configuration
Configure settings stored in the application after installation.
Security
Protect secrets, sessions, and account-recovery procedures.
Troubleshooting
Resolve connection, realtime, email, and storage problems.
Before you begin
Copy `.env.example` to `.env` and replace the required values before the first start. Keep `.env` private and use an independent secret for each security purpose.
Quick start
Create the private file, then set the production domain, required secrets, and PostgreSQL password. Configure SMTP only when you want a deployment-level email fallback. Add setup protection when initialization is reachable from the internet.
- Set APP_DOMAIN and WEB_ORIGIN to the address used by members.
- Replace every secret placeholder with an independent random value.
- Set POSTGRES_PASSWORD to a strong URL-safe value.
- Review the production example before continuing to Installation.
cp .env.example .envRequired production configuration
| Variable | Requirement | Purpose |
|---|---|---|
| APP_DOMAIN | Required | Public hostname, such as community.example.com. Use :80 only for direct HTTP deployment. |
| WEB_ORIGIN | Required | Exact address opened by users, including the scheme and without a trailing slash. |
| POSTGRES_PASSWORD | Required | Private, stable password for the PostgreSQL role. Use a strong URL-safe value. |
| JWT_SECRET | Required | Private, stable secret that protects sessions. Changing it invalidates active sessions. |
| PASSWORD_PEPPER | Required | Private, stable secret of at least 32 bytes for password protection. |
| COMPOSE_PROJECT_NAME | Recommended | Stable deployment and volume identity. Keep pe-community unless you have a specific reason to change it. |
Recommended security configuration
| Variable | Requirement | Purpose |
|---|---|---|
| EMAIL_ENCRYPTION_KEY | Recommended | Private, stable key that protects saved SMTP and CAPTCHA credentials. |
| REGISTRATION_KEY_HASH_SECRET | Recommended | Private, stable secret that strengthens registration rate-limit protection. |
| SETUP_TOKEN | Recommended before initialization | Protects first-run setup when it is reachable from an untrusted network. |
| OWNER_BREAK_GLASS_SECRET | Optional | Adds secret proof to the emergency Owner 2FA recovery procedure. |
Application address
For the standard deployment, use a public hostname, match WEB_ORIGIN to the exact HTTPS address opened by users, keep the same-origin API path, and leave the explicit realtime origin empty.
- APP_DOMAIN contains the hostname without a path.
- WEB_ORIGIN includes the scheme and must not end with a slash.
- NEXT_PUBLIC_API_URL and NEXT_PUBLIC_REALTIME_ORIGIN are browser-visible. Rebuild the application after changing them.
- Set NEXT_PUBLIC_REALTIME_ORIGIN only when realtime uses a different origin.
APP_DOMAIN=community.example.com
WEB_ORIGIN=https://community.example.com
NEXT_PUBLIC_API_URL=/api/v1
NEXT_PUBLIC_REALTIME_ORIGIN=Database and Redis
Set POSTGRES_PASSWORD before the first start. The standard deployment configures PostgreSQL and Redis connections automatically, so you normally do not need to change DATABASE_URL or REDIS_URL.
If you use an external database or Redis service, set the advanced addresses and verify connectivity before startup.
Authentication and sessions
Sessions expire after 20 minutes of inactivity and no later than seven days after creation. These durations are currently fixed.
| Variable | Requirement | Purpose |
|---|---|---|
| JWT_SECRET | Required | Keep it private and stable. Rotation signs out active sessions. |
| PASSWORD_PEPPER | Required | Keep it private and stable. It must contain at least 32 bytes. |
| PASSWORD_PEPPER_PREVIOUS | Rotation only | Temporarily set the old pepper during a planned rotation, then remove it after active accounts have migrated. |
| SESSION_COOKIE_NAME | Optional | Session cookie name. The default is pe_session; changing it abandons existing cookies. |
| SESSION_COOKIE_SECURE | Optional | Use true or false to force Secure behavior. Leave it empty to follow WEB_ORIGIN and production mode. |
Generate secure secrets
This command produces a 32-byte hexadecimal value suitable for the secrets on this page. Run it separately for every variable so the values remain independent.
openssl rand -hex 32Email delivery
You can configure email from the administration interface. SMTP environment variables provide a deployment-level fallback when no active community setting overrides them.
| Variable | Requirement | Purpose |
|---|---|---|
| SMTP_HOST | Required with SMTP fallback | Hostname supplied by your SMTP provider. |
| SMTP_PORT | Optional, default 587 | Use 587 with STARTTLS or 465 with implicit TLS. |
| SMTP_USER | Required with SMTP fallback | SMTP username. |
| SMTP_PASSWORD | Required with SMTP fallback, private | SMTP password or credential. Never commit it to version control. |
| SMTP_SECURE | Optional, default false | Use false for port 587 and true for port 465. |
| SMTP_FROM_EMAIL | Required with SMTP fallback | Sender address used for email. |
| SMTP_FROM_NAME | Required with SMTP fallback | Displayed sender name. |
| EMAIL_ENCRYPTION_KEY | Recommended, private, stable | Protects SMTP and CAPTCHA credentials saved through administration. |
Registration protection
Configure CAPTCHA/Turnstile from administration settings rather than `.env`. Set REGISTRATION_KEY_HASH_SECRET to a private, stable value to strengthen registration rate-limit protection.
First-run protection
Set SETUP_TOKEN when first-run setup is reachable from the internet. Then open `/setup?token=<value>` in a trusted session. After successful initialization, first-run setup cannot be repeated.
Owner account recovery
OWNER_BREAK_GLASS_SECRET is optional additional protection for the server-side emergency Owner 2FA recovery procedure. Keep it private and see Security for the complete procedure. Changing it affects only future recovery operations.
File uploads
The standard deployment keeps uploaded files in a persistent volume and sets UPLOADS_DIR automatically. You normally do not need to change this path. Include both the uploads volume and PostgreSQL in your backup plan.
Advanced and custom deployments
The standard deployment manages internal addresses, process ports, and the uploads path automatically. Change the values below only for host development, an external service, or a custom topology.
| Variable | Use |
|---|---|
| DATABASE_URL | Custom PostgreSQL connection or host development. Format: postgresql://user:password@host:5432/database?schema=public. |
| REDIS_URL | Custom Redis connection or host development. The usual local value is redis://localhost:6379. |
| INTERNAL_API_URL | Internal address used by server rendering. The standard deployment sets it automatically. |
| API_PUBLIC_URL | Custom public base for generated media URLs. The deployment uses WEB_ORIGIN by default. |
| API_PORT | Application process port for host execution. Default: 4000. |
| WEB_PORT | Interface process port for host execution. Default: 3000. |
| HTTP_PORT | HTTP port published by Docker Compose. Default: 80. |
| HTTPS_PORT | HTTPS port published by Docker Compose. Default: 443. |
| UPLOADS_DIR | Custom uploaded-file path. The standard deployment uses /app/uploads. |
| REALTIME_DIAGNOSTICS | Set true temporarily to add realtime connection diagnostics to logs. |
Development-only settings
EMAIL_DEV_LOG=true replaces missing SMTP delivery with email logging outside production only. Do not use it to validate real delivery.
Changing configuration later
| Variable | Impact when changed |
|---|---|
| JWT_SECRET | Invalidates active sessions. |
| PASSWORD_PEPPER | Requires a planned rotation with PASSWORD_PEPPER_PREVIOUS. |
| EMAIL_ENCRYPTION_KEY | Makes previously saved SMTP and CAPTCHA credentials unreadable. |
| POSTGRES_PASSWORD | Must remain synchronized with PostgreSQL credentials. |
| COMPOSE_PROJECT_NAME | Can select a different volume set and make existing data appear absent. |
| APP_DOMAIN / WEB_ORIGIN | Requires DNS/TLS review and a restart or redeployment of affected services. |
| NEXT_PUBLIC_API_URL / NEXT_PUBLIC_REALTIME_ORIGIN | Requires rebuilding application assets. |
| OWNER_BREAK_GLASS_SECRET | Changes the proof requested for future Owner recovery. |
Production example
Use this as a starting point and replace every placeholder. Leave SMTP values empty when email is configured only through administration.
COMPOSE_PROJECT_NAME=pe-community
APP_DOMAIN=community.example.com
WEB_ORIGIN=https://community.example.com
NEXT_PUBLIC_API_URL=/api/v1
NEXT_PUBLIC_REALTIME_ORIGIN=
POSTGRES_PASSWORD=<strong-url-safe-database-password>
JWT_SECRET=<strong-independent-secret>
PASSWORD_PEPPER=<strong-independent-secret-at-least-32-bytes>
EMAIL_ENCRYPTION_KEY=<strong-independent-stable-secret>
REGISTRATION_KEY_HASH_SECRET=<strong-independent-secret>
SETUP_TOKEN=<optional-setup-secret>
OWNER_BREAK_GLASS_SECRET=<optional-recovery-secret>
SMTP_HOST=
SMTP_PORT=587
SMTP_USER=
SMTP_PASSWORD=
SMTP_SECURE=false
SMTP_FROM_EMAIL=
SMTP_FROM_NAME=Validation checklist
- The `.env` file is not committed and every required placeholder is replaced.
- Each security purpose uses an independent secret.
- APP_DOMAIN and WEB_ORIGIN match the address opened by users.
- POSTGRES_PASSWORD is set to a strong URL-safe value.
- Email configuration has been tested when email features are required.
- SETUP_TOKEN protects an empty installation exposed to the internet.
- PostgreSQL and uploaded files are included in backups.
Troubleshooting
- Sign-in or browser requests fail: check APP_DOMAIN, WEB_ORIGIN, DNS, HTTPS, and the reverse proxy.
- Realtime features disconnect: check NEXT_PUBLIC_REALTIME_ORIGIN if set, then proxy connectivity and browser errors.
- Email is not sent: check host, port, TLS mode, credentials, sender identity, and outbound SMTP restrictions from your host.
- The database is unavailable: check POSTGRES_PASSWORD and deployment status; check DATABASE_URL only for a custom deployment.
- Saved email or CAPTCHA credentials are unreadable: restore the previous EMAIL_ENCRYPTION_KEY or re-enter credentials under the new key.
- Uploaded files are unavailable: verify that the persistent uploads volume is mounted and restored.