Repository navigation
Administrator Configuration
Complete this chapter after installation and before opening registration or directing public traffic to the site. Stream Engine configuration is divided between two stores:
-
.envcontains deployment-specific infrastructure, credentials, paths, and secrets; and - the
settingsdatabase table contains site behavior managed through the administration interface.
Do not copy secrets from .env into database settings or enter infrastructure
settings as arbitrary keys in the administration interface.
Use this order so later checks depend on working earlier settings:
- Confirm the canonical URL and production environment in
.env. - Configure the database (MySQL or MariaDB) and a unique Memcached namespace.
- Configure writable temporary, cache, and upload paths.
- Configure and test SMTP.
- Set the site identity, locale, date/time formats, and upload quota.
- Upload the header logo and site icon if required.
- Choose a registration policy and optional CAPTCHA provider.
- Verify the public site, email-dependent flows, uploads, and logs.
The installer creates .env with owner-only permissions and preserves
unrelated values already present in the file. After installation, edit it only
through a controlled deployment process or a privileged shell account.
Before changing .env:
- create a protected copy or ensure that a current configuration backup exists;
- confirm that the replacement file will remain readable by PHP-FPM and the scheduler;
- keep it outside
public/; and - ensure that deployment logs do not print secret values.
PHP-FPM workers may retain process environment values. Restart or reload the
PHP-FPM service after changing .env, then run one CLI command with the same
release to confirm that it reads the new configuration. Restarting Nginx alone
does not reload PHP environment values.
Never commit .env. The committed .env.example is a key reference, not a
production configuration file and not a source of usable credentials.
| Variable | Purpose and operational rule |
|---|---|
APP_ENV |
Use prod on a deployed site. dev flushes the application cache during request startup and must not be used for production traffic. |
APP_SECRET |
Random 64-character hexadecimal signing secret generated by the installer. Preserve it across deployments and restores. Do not rotate it as a routine configuration change. |
SITE_URL |
Canonical absolute http or https URL without a trailing slash, credentials, query, or fragment. Use the public HTTPS URL in production. It is used when the application must create absolute links and when validating the expected Turnstile hostname. |
DB_HOST, DB_PORT
|
MySQL or MariaDB endpoint. The default port is 3306. |
DB_NAME |
Database containing the complete site state. |
DB_USERNAME, DB_PASSWORD
|
Dedicated application account. Keep its privileges scoped to the Stream Engine database. |
Changing a database endpoint after installation does not move any data. Copy and verify the database first, change all application and scheduler instances together, and keep a rollback path.
| Variable | Default | Purpose |
|---|---|---|
MEMCACHED_HOST |
127.0.0.1 |
Memcached hostname or private address. |
MEMCACHED_PORT |
11211 |
Memcached TCP port. |
CACHE_PREFIX |
default |
Namespace added to every Stream Engine cache key. |
Set a unique CACHE_PREFIX for every installation sharing one Memcached
service. Reusing a prefix can mix cached data between sites. Changing the
prefix effectively starts with an empty application cache; old keys remain
until Memcached evicts or expires them.
Keep Memcached on a private interface or protected network. It must not be reachable from the public internet. After a change, restart PHP-FPM, load the site twice, and check application and service logs for connection errors.
| Variable | Default behavior |
|---|---|
UPLOADS_DIR |
storage/uploads, resolved relative to the application root. An absolute path is also accepted. |
TMP_DIR |
PHP's upload_tmp_dir, falling back to the operating-system temporary directory. |
TWIG_CACHE_DIR |
A twig/ directory under the selected temporary directory. |
THEME_DIR |
Optional theme directory override. Leave unset to use the release's normal theme catalog. |
The PHP-FPM and scheduler accounts need the appropriate read/write access to
these paths. The web server must expose the active local uploads directory at
/uploads/. If UPLOADS_DIR changes, update the Nginx alias, move existing
files, preserve their relative paths, and verify them before removing the old
directory.
Stream Engine currently stores runtime uploads locally through FileStorage.
The object-storage boundary and the currently inactive S3-compatible client
are described below. Keep public and private local uploads in the backup set.
Private uploads live in UPLOADS_DIR with -private appended and must only be
served through the internal /protected-uploads/ Nginx location.
Conversation attachments require an authenticated user with access to a live
message containing the file. Configure the internal Nginx location as shown in
the installation guide, run nginx -t, and reload Nginx. See
Conversation attachments
for the sharing and revocation semantics.
Object storage is not a selectable runtime backend in the current release.
The repository contains a low-level S3ObjectStorage client and a development
MinIO service, but Stream Engine does not instantiate that client during normal
application startup. No administration setting selects it.
The active data flow remains entirely local:
| Operation | Current storage behavior |
|---|---|
| User, profile, forum, and administrator uploads |
UploadService writes through FileStorage below UPLOADS_DIR. |
| Message attachments | Stored beside UPLOADS_DIR in UPLOADS_DIR-private; authorized by the messenger and delivered using X-Accel-Redirect. |
| Header logo and site icon | Written into local subdirectories of UPLOADS_DIR. |
| File Browser | Reads and changes the configured local uploads directory. It cannot browse an object bucket. |
| Public file URLs | Stored or generated as /uploads/... paths and served by the web-server alias. |
| S3-compatible client | Available to code, but not connected to any standard upload, branding, rendering, or deletion workflow. |
Consequently, setting OBJECT_STORAGE_* does not upload, copy, migrate, mirror,
or serve existing files from a bucket. It does not change /uploads/... URLs,
the File Browser, per-user storage accounting, local disk requirements, or the
required uploads backup. Leaving these variables unset in production is the
least surprising configuration.
The inactive client reads the following group from .env when code explicitly
constructs and calls it:
| Variable | Client interpretation |
|---|---|
OBJECT_STORAGE_ENDPOINT |
S3-compatible service URL, without the bucket name. Trailing slashes are removed. |
OBJECT_STORAGE_BUCKET |
Existing bucket name appended to the endpoint as a path. |
OBJECT_STORAGE_REGION |
AWS Signature Version 4 signing region; defaults to us-east-1. |
OBJECT_STORAGE_ACCESS_KEY |
Static access-key identifier used to sign requests. |
OBJECT_STORAGE_SECRET_KEY |
Static secret used to sign requests. Treat it as a deployment secret. |
OBJECT_STORAGE_PUBLIC_BASE_URL |
Optional public or CDN base used only when constructing an object URL. If omitted, the client uses endpoint/bucket. |
Configure the group together only when developing or operating code that explicitly uses this client. A configured public base URL does not make a bucket public, create a CDN distribution, validate that an object exists, or generate a time-limited signed URL.
An explicit caller can currently:
- upload an in-memory string with a content type and optional custom metadata;
- upload a local file after reading the complete file into PHP memory;
- test one key with an authenticated
HEADrequest; - delete one key, treating an already missing key as successfully absent; and
- construct a URL for one key.
Requests use AWS Signature Version 4 and path-style URLs in the form
endpoint/bucket/key. Object keys are relative slash-separated paths and each
segment is URL-encoded. The client has a 10-second connection timeout and a
60-second total request timeout and does not follow redirects.
This is not a complete storage backend. The client does not create buckets or policies, download or list objects, perform multipart uploads, stream large files, generate private presigned URLs, discover credentials from an instance role, refresh temporary credentials, manage versions or lifecycle rules, or retry failed requests. The repository currently tests request-independent client behavior but does not run a live S3/MinIO integration suite. Treat provider compatibility as unverified until it has been exercised against the exact service and network path.
The development Compose stack starts MinIO, exposes its API on port 9000 and
console on port 9001, passes reference credentials and endpoint values to the
PHP and scheduler containers, and persists MinIO data in the minio_data
volume. This supports object-storage development; it does not activate object
storage for the site.
The stack does not automatically create the configured stream-engine bucket,
apply an access policy, or copy local uploads into MinIO. With the unmodified
application, MinIO can remain empty while uploads work normally from the local
bind mount. The published ports and example root credentials are unsuitable
for an untrusted network. docker compose down --volumes deletes the MinIO
volume along with the other Compose volumes.
Do not replace the local uploads directory, its Nginx alias, capacity alerts,
or its backup with object-storage procedures. A site-specific module that
calls S3ObjectStorage directly creates state outside the standard Stream
Engine storage lifecycle. Its operator must separately document bucket
creation, least-privilege permissions, public/private delivery, CORS when
needed, encryption, versioning, lifecycle, monitoring, backup, restore,
orphan cleanup, and behavior when object storage is unavailable. Standard File
Browser operations and database cleanup will not automatically manage those
custom objects.
Consider object storage a supported upload backend only when a future release explicitly documents backend selection, migration of existing files, URL and access behavior, administration integration, failure handling, backup and restore, and rollback to local storage.
Email is required for registration with email confirmation, password recovery, and email notification delivery. Configure all SMTP values together:
| Variable | Example | Purpose |
|---|---|---|
SMTP_HOST |
smtp.example.com |
SMTP server hostname. |
SMTP_PORT |
587 |
Provider port. |
SMTP_USERNAME |
stream-engine |
Authentication username. |
SMTP_PASSWORD |
a deployment secret | Authentication password or provider token. |
SMTP_ENCRYPTION |
tls |
PHPMailer encryption mode expected by the provider. |
SMTP_FROM |
noreply@example.com |
Valid sender address accepted by the provider. |
The current mail transport uses authenticated SMTP. Ensure the provider permits
the configured sender and that the application host can reach the SMTP port.
Store credentials only in .env or the deployment secret system.
There is no separate Send test email action in the administration interface. Test SMTP before enabling email-confirmed registration:
- restart PHP-FPM after saving
.env; - temporarily keep registration closed to the public;
- use a controlled account and password-recovery or email-verification flow;
- confirm receipt, sender identity, links, HTML and text bodies, and spam placement; and
- inspect PHP-FPM and SMTP-provider logs on failure.
Absolute email links depend on SITE_URL. A working SMTP connection with an
incorrect canonical URL can still send unusable messages.
Open Administration → Settings. These values are stored in the database and apply to the whole site.
| Setting | Available values and effect |
|---|---|
| Site name | Public site identity created during installation. Choose the final name before creating screenshots or transactional email templates. |
| Interface locale | Selects the server and administration translation catalog. Current catalogs include ar, de, en, es, fr, it, ja, ko, nl, pl, pt-br, ru, and zh-cn. Arabic also selects the RTL presentation variant. |
| Date format | Automatic from locale, DD.MM.YYYY, MM/DD/YYYY, or ISO YYYY-MM-DD. |
| Time format | Automatic from locale, 24-hour, or 12-hour. |
| User upload limit | Total stored bytes allowed for each non-administrator, entered in megabytes. The default is 500 MB. Administrators are not restricted by this per-user quota. |
The upload quota is not a per-file limit. The application separately rejects
individual user and administrator File Browser uploads larger than 50 MB, and
Nginx and PHP limits may reject a smaller request before it reaches Stream
Engine. Align client_max_body_size, upload_max_filesize, and
post_max_size with the policy you intend to enforce.
Changing locale or date/time format reloads the administration application. After saving, check both public pages and the administration interface. A missing translation falls back to English; it should still be reported as a localization defect rather than accepted silently.
The lower part of Administration → Settings manages site branding.
- Accepted input: PNG, JPEG, WebP, or GIF.
- Maximum input size: 2 MB.
- The stored result is placed under
uploads/site-brand/. - Remove logo deletes the customized file and returns the header to its no-logo state.
- Accepted input with SVG conversion support: SVG, PNG, JPEG, WebP, or GIF.
- Accepted input without SVG conversion support: PNG, JPEG, WebP, or GIF.
- Maximum input size: 2 MB.
- Stream Engine creates ICO and Apple touch PNG variants under
uploads/site-icons/; it also creates an SVG variant when the image processor supports it. -
Restore default removes customized variants and returns to the favicon
files shipped in
public/.
The optional Imagick/SVG tooling in the project image enables SVG conversion. The Settings page shows a warning when it is unavailable. Branding files are part of local uploads and must be backed up with the rest of that directory.
After changing branding, reload a public page and check the header, browser favicon, and mobile/touch icon. Browser icon caches can outlive a normal page reload; verify the published icon URL directly when necessary.
Open Administration → Registration. Registration settings are stored in the database.
| Mode | Behavior |
|---|---|
| Closed | Guests see the registration-closed page and the registration API refuses account creation. Use this until mail and anti-abuse controls have been tested. |
| Open with email confirmation | A new account requires the owner to follow the verification link before normal use. Working SMTP and a correct SITE_URL are operational requirements. This is the default mode. |
| Open without confirmation | The account is created and the new user is signed in immediately. Use only when the abuse risk is acceptable. |
Changing to Closed prevents new registrations; it does not deactivate existing accounts.
Every registration form includes a hidden field that a normal browser leaves empty. Automated form fillers often populate it and are rejected. The field name must:
- contain 3–64 Latin letters, digits, or underscores;
- start with a letter; and
- not be
emailorpassword.
Changing the default name can reduce hard-coded bot traffic, but it is not a substitute for rate limiting, CAPTCHA, email verification, or network-level abuse controls.
Supported providers are Cloudflare Turnstile and hCaptcha. For either provider:
- create a site in the provider dashboard for the production hostname;
- enter the provider's site key and secret key;
- save the registration settings;
- open the registration page in a private browser session;
- complete one controlled registration; and
- confirm that missing, invalid, and expired challenges are rejected.
The secret is stored in the database and is never returned to the browser or back to the administration interface. Leaving the secret field empty preserves the existing secret only while the same provider remains selected. Selecting Disabled clears the saved CAPTCHA keys.
CAPTCHA requires outbound HTTPS access to the selected provider. Turnstile
also checks that the provider response hostname matches the host in SITE_URL
and that the challenge action is registration.
Login and password recovery are protected by database-backed limits. Login
allows five attempts per account and 50 per client IP in 15 minutes. Password
recovery allows three requests per account and 10 per client IP in one hour.
An exceeded limit returns HTTP 429; a database failure rejects the request
rather than disabling the protection. The hourly users:cleanup scheduler task
removes expired limiter rows, so keep the scheduler running.
The application uses only PHP's REMOTE_ADDR and ignores forwarding headers.
When Stream Engine is behind a reverse proxy or load balancer, configure that
trusted proxy and the PHP-facing web server so REMOTE_ADDR contains the
verified original client address. Do not copy arbitrary X-Forwarded-For
values into it: a client could then evade per-IP limits or consume another
client's allowance.
Do not expect the administration interface to update these deployment values:
-
APP_ENV,APP_SECRET, andSITE_URL; - database or Memcached endpoints and credentials;
- SMTP credentials;
- filesystem and cache directories;
- PHP, Nginx, TLS, DNS, or firewall configuration; and
- scheduler installation.
The Scheduler page manages the application's scheduler mode and task state, but the operating-system cron entry, systemd timer, or container scheduler is still configured outside Stream Engine.
-
.envremains outside the document root and readable only by required service and deployment accounts. -
APP_ENV=prodandSITE_URLis the canonical HTTPS URL. - The application and scheduler use the intended database.
- Every site sharing Memcached has a unique
CACHE_PREFIX. - Local uploads, temporary files, and Twig cache paths are writable by the correct accounts and not broadly writable.
- A controlled transactional email arrives with correct absolute links.
- Site name, locale, and date/time display are correct on public and admin pages.
- A normal non-administrator upload succeeds and its quota is enforced.
- Header logo and site icon URLs load, if customized.
- Registration is closed or uses the intended verification policy.
- CAPTCHA succeeds and fails as expected, if enabled.
- PHP-FPM, Nginx, and provider logs contain no new configuration errors.
Back: Installation · Administrator Guide · Next: Content, pages, and routing