Skip to content

Configuration

The one-line Swarm installation is deployment-managed. Non-secret runtime settings live in /opt/koakademy/runtime.env with mode 0600; credentials live only in Docker Secrets. Do not edit that file or a container .env by hand. Use the koakademy command so a change is validated, secrets are rotated, and FrankenPHP workers restart.

Terminal window
koakademy status
koakademy configure storage local
koakademy configure storage s3
koakademy configure storage r2
koakademy configure storage library-r2
koakademy configure mail log
koakademy configure mail smtp
koakademy configure mail sequenzy
koakademy configure search enable
koakademy configure search disable

The operator self-elevates with sudo when it needs root-owned runtime files, so these commands do not need a manual sudo prefix. The installer also adds the invoking user to Docker’s docker group. Activate the change in the current shell with newgrp docker, or log out and back in, before using Docker without sudo; Docker-group membership is equivalent to root access on the host.

Commands prompt for values and hide secrets. For unattended use, supply the documented KOAKADEMY_* environment variable for each prompt; do not put credential values in shared shell history or source control.

Fresh installs use FILESYSTEM_DISK=public on the persistent app volume. This keeps first boot simple but is tied to one VPS. Move uploads to S3 or Cloudflare R2 before relying on the server as production infrastructure:

Terminal window
koakademy configure storage r2

The command collects the endpoint, bucket, region, optional public/CDN URL, access key, and secret key. It stores only the two keys as Docker Secrets. R2 selects region auto and path-style requests by default; generic S3 asks for those provider-specific values.

Digital Library editions require a separate private bucket. Configure it separately:

Terminal window
koakademy configure storage library-r2

Never expose that bucket through a public URL. Limit credentials to its bucket, retain the existing reader/download authorization controls, and configure exact-origin CORS for PDF range requests.

First boot uses Laravel’s log mailer. Configure external delivery only through the operator command:

Terminal window
koakademy configure mail smtp

SMTP accepts host, port, scheme, username, password, and sender identity. Sequenzy accepts its API endpoint and API key. The password or API key becomes a Docker Secret; the System Management page intentionally shows only the active mailer and sender identity. It cannot edit or test credentials from the web application.

Meilisearch is external-only:

Terminal window
koakademy configure search enable

Provide the external HTTPS endpoint and API key. KoAkademy enables the Scout Meilisearch driver, rolls the app service, synchronizes index settings, and imports the registered searchable models. No Meilisearch service is added to the Swarm stack. Disable it with koakademy configure search disable.

The Marketplace reads the signed KoAkademy module catalog and combines it with the modules installed in the current application image. It is enabled by default in the installer and Swarm templates:

MODULE_MARKETPLACE_ENABLED=true
MODULE_REGISTRY_URL=https://yukazakiri.github.io/koakademy-modules/registry.json
MODULE_REGISTRY_CACHE_TTL=3600
MODULE_REGISTRY_REQUIRE_SIGNATURE=true
MODULE_REGISTRY_PUBLIC_KEY=gnGm74yPDu7umv6sF0lzepJnEVEx7b9_HYDrAxjxYYs
MODULE_REGISTRY_PUBLIC_KEY_FILE=
MODULE_SCAN_VENDOR=true

MODULE_REGISTRY_PUBLIC_KEY_FILE can provide the public key from a mounted secret; use it when the deployment does not keep the key inline. Keep the public key aligned with the registry trust root and never put the private signing key in the application or its image.

The Marketplace is read-only. It can enable or disable an installed module, but it does not run Composer or install code into a live container. To add a standalone module, declare the Composer package in the application, commit the lockfile, rebuild the image, run its migrations, and then enable it from Administrators → Marketplace. See the module registry guide for the contributor and maintainer release process.

The persistent module status file is initialized without overwriting existing choices. This preserves enabled bundled modules and administrator decisions during upgrades. A package that was not present in the previous image may appear disabled until an administrator enables it.

The release ships only the CHED E-Form B/C regulatory report provider. It is enabled by default for Philippine schools with the CHED PSG curriculum capability. To hide it without removing code, data, or existing installation state, set this application environment variable and restart the workers:

REGULATORY_REPORT_CHED_ENABLED=false

Compatible providers can be added by an application or Composer module through the RegulatoryReportAdapter contract and the configuration registry. They are not auto-discovered or implied to be supported. See the Regulatory Report Provider guide for the adapter, scope, route, frontend, and test requirements.

Caddy terminates HTTPS and is the only public service. It forwards to the internal FrankenPHP app over the Swarm overlay. The installer sets:

APP_URL=https://school.example
PORTAL_HOST=school.example
ADMIN_HOST=school.example
TRUSTED_PROXIES=*
SESSION_SECURE_COOKIE=true
OCTANE_SERVER=frankenphp

The wildcard proxy trust is valid because the app service is not published outside the overlay. If the topology is changed to expose the app directly, replace it with explicit proxy addresses or CIDRs.

.env.production.example remains the public interface for compose.production.yaml. Compose operators must create a protected .env, generate one APP_KEY per installation, configure a dedicated PostgreSQL/Redis password and external S3-compatible storage, then restart the app after any environment change. Under FrankenPHP, an environment or configuration change does not reach already booted workers until a restart.

AUTO_MIGRATE=true is the default and runs pending application migrations when the container starts. The installer and koakademy update still run an explicit migration before rollout; set AUTO_MIGRATE=false only when your deployment process deliberately owns that startup behavior.