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.
Runtime commands
Section titled “Runtime commands”koakademy statuskoakademy configure storage localkoakademy configure storage s3koakademy configure storage r2koakademy configure storage library-r2koakademy configure mail logkoakademy configure mail smtpkoakademy configure mail sequenzykoakademy configure search enablekoakademy configure search disableThe 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.
Storage
Section titled “Storage”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:
koakademy configure storage r2The 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:
koakademy configure storage library-r2Never 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:
koakademy configure mail smtpSMTP 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.
Search
Section titled “Search”Meilisearch is external-only:
koakademy configure search enableProvide 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.
Module Marketplace
Section titled “Module Marketplace”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=trueMODULE_REGISTRY_URL=https://yukazakiri.github.io/koakademy-modules/registry.jsonMODULE_REGISTRY_CACHE_TTL=3600MODULE_REGISTRY_REQUIRE_SIGNATURE=trueMODULE_REGISTRY_PUBLIC_KEY=gnGm74yPDu7umv6sF0lzepJnEVEx7b9_HYDrAxjxYYsMODULE_REGISTRY_PUBLIC_KEY_FILE=MODULE_SCAN_VENDOR=trueMODULE_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.
Regulatory reporting
Section titled “Regulatory reporting”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=falseCompatible 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.
Application and routing
Section titled “Application and routing”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.examplePORTAL_HOST=school.exampleADMIN_HOST=school.exampleTRUSTED_PROXIES=*SESSION_SECURE_COOKIE=trueOCTANE_SERVER=frankenphpThe 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.
Manual Compose configuration
Section titled “Manual Compose configuration”.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.