Open-source software for Joomla, Gitea, and web platforms. Home of MokoSuite, MokoGitea, and MokoCLI.
Tennessee
architecture/twelve-factor.-
Twelve-Factor App Principles
How the 12-factor methodology applies to MokoConsulting projects.
I. Codebase
One codebase tracked in version control, many deploys.
- Each product has a single Gitea repository
- Same codebase deploys to dev, demo, and live environments
- No shared code between repos via copy-paste — use packages/dependencies
II. Dependencies
Explicitly declare and isolate dependencies.
- PHP:
composer.jsonwithcomposer.lockcommitted - Node.js:
package.jsonwithpackage-lock.jsoncommitted - Go:
go.modwithgo.sumcommitted - Never rely on system-wide packages — everything in the dependency manifest
III. Config
Store config in the environment.
- MCP servers: config in
~/.mcp_moko*.jsonfiles, path via env var - Joomla: configuration in
configuration.php(per-environment) - API tokens, credentials: environment variables or config files, never in code
.envfiles for local development, never committed to git
IV. Backing Services
Treat backing services as attached resources.
- Database (MySQL): connection string in config, swappable per environment
- File storage: configurable path, can be local or remote (S3, FTP)
- Email: SMTP config in Joomla, swappable between environments
- External APIs (Discord, Telegram, etc.): credentials in config
V. Build, Release, Run
Strictly separate build and run stages.
- Build:
make buildproduces installable artifact (ZIP, Docker image) - Release: Gitea release with tag, version-stamped artifact
- Run: Install/deploy the release artifact to the environment
- Never modify running code directly on servers
VI. Processes
Execute the app as stateless processes.
- Joomla sessions stored in database, not filesystem
- No sticky sessions — any web server can handle any request
- File uploads stored in well-known directories, not temp
- Background processing via Joomla Scheduled Tasks (cron)
VII. Port Binding
Export services via port binding.
- MokoGitea: ports 3000 (web), 2222 (SSH), 2918 (shell)
- Grafana: port 3100
- Prometheus: port 9091
- ntfy: port 8080
- Services are self-contained — no dependency on external app servers
VIII. Concurrency
Scale out via the process model.
- Web requests handled by PHP-FPM worker pool
- Background tasks via Joomla Task Scheduler (separate process)
- Gitea Actions runners as separate containers (4 runners)
- Each runner handles one job at a time
IX. Disposability
Maximize robustness with fast startup and graceful shutdown.
- Docker containers start in seconds
- Graceful shutdown: finish current request before stopping
- MokoGitea: Docker healthcheck ensures readiness
- Backup jobs are resumable (stepped engine with checkpoints)
X. Dev/Prod Parity
Keep development, staging, and production as similar as possible.
- Same PHP version across dev/demo/live
- Same Joomla version and extensions
- Same database engine (MySQL 8.0)
- WaaS tiers mirror each other in configuration
XI. Logs
Treat logs as event streams.
- Joomla logs to
administrator/logs/ - Gitea logs to Docker stdout (collected by Docker logging)
- Prometheus scrapes metrics endpoints
- Grafana aggregates and visualizes
- No log rotation in application code — handled by infrastructure
XII. Admin Processes
Run admin/management tasks as one-off processes.
- Database migrations: SQL update scripts run during Joomla extension update
- Backup: CLI commands via
plg_console_mokosuitebackup - Data import: one-off scripts via Joomla CLI framework
- Never run admin tasks by modifying production database directly
Pages