# Technical documentation — evolve-infra

Evidence date: 2026-10-15. Source: `git@bitbucket.org:overdrive/evolve-infra.git`, `master` at `35effc1` (2019-03-15).

Only branch: `master`. Every commit is by Mandus Momberg (`git@momberg.me`) on 2019-03-15. The stack was not built or started for this document.

Application internals (Zend routes, models, schema) are in `silicon_ark/magus-core/technical-documentation.md`.

## Stack

| Item | Evidence |
|---|---|
| Orchestration | Docker Compose file format `version: '3'` |
| Web | `nginx:stable-alpine`, host `8080` → container `80` |
| PHP | Image built from `php/Dockerfile`, tagged `php:fpm-evolve`. Base `php:fpm-alpine`. Extensions `pdo_mysql` and `gd` (`libpng-dev`) |
| Database | Image `mariadb` with no tag. `MYSQL_DATABASE=magus_dev`, `MYSQL_ROOT_PASSWORD=root` |
| Admin UI | `phpmyadmin/phpmyadmin` with no tag. Host `8081` → container `80` |
| Application | Git submodule, not a tree in this repo |
| Tests | None. `php-test/public/index.php` is a manual script and is not mounted |
| CI | No pipeline file |
| Languages in this repo | YAML, nginx config, a short Dockerfile, one PHP script, Markdown |

No Composer file, no lockfile, no `.env`, no Makefile, no Helm chart, no Terraform.

## Repository layout

```text
evolve-infra/
  .gitmodules                 # magus-core URL and branch = master
  Readme.md
  docker-compose.yml
  nginx.conf                  # not mounted
  nginx-site.conf             # mounted over conf.d/default.conf
  php/Dockerfile
  php-test/public/index.php   # not mounted
  magus-core                  # gitlink 9b5b3e2 (empty until submodule update)
```

Tracked file list at `35effc1` is those paths. `magus-core` is mode `160000`.

## Services

| Service | Image | Ports | Volumes | Links | Environment |
|---|---|---|---|---|---|
| `http` | `nginx:stable-alpine` | `8080:80` | `./magus-core:/code`, `./nginx-site.conf:/etc/nginx/conf.d/default.conf` | `php` | none |
| `php` | `php:fpm-evolve` (build `./php`) | none published | `./magus-core:/code` | `database` | `APPLICATION_ENV=development` |
| `database` | `mariadb` | none published | `./magus-core/admin_magus.sql:/docker-entrypoint-initdb.d/dump.sql` | none | `MYSQL_ROOT_PASSWORD=root`, `MYSQL_DATABASE=magus_dev` |
| `phpmyadmin` | `phpmyadmin/phpmyadmin` | `8081:80` | none | `database:db` | `PMA_USER=root`, `PMA_PASSWORD=root` |

No `container_name`, `depends_on`, `restart`, `healthcheck`, `networks`, or named volume is set.

`links` is the legacy Compose key. On a default Compose network, service DNS names exist even without `links`. The phpMyAdmin alias `db` is created by `links: database:db`. phpMyAdmin's image looks for host `db` when `PMA_HOST` is unset. That last sentence is **Inferred** from the alias the file bothers to set, and from the image's usual default. `PMA_HOST` is not set in this file. It was not executed.

## Request path

1. Host `http://localhost:8080` reaches nginx in service `http`.
2. `nginx-site.conf` `root` is `/code/public`, which is `magus-core/public` on the host.
3. A URL that is not a file or directory is internally redirected to `/index.php`.
4. `location ~ \.php$` refuses missing files, then FastCGI to `php:9000`.
5. `SCRIPT_FILENAME` is `$document_root$fastcgi_script_name`. `PATH_INFO` is set from `$fastcgi_path_info`. This file does not set `fastcgi_split_path_info`, so `$fastcgi_path_info` stays empty unless the base image defines it. Provenance: **Inferred** from the directives present.
6. PHP-FPM runs the script. Magus `public/index.php` sees `APPLICATION_ENV=development`.

`include fastcgi_params` comes from the nginx image, not from this repo.

Zend's own rewrite lives in Magus `public/.htaccess` (and, at pin `9b5b3e2`, a root `.htaccess` that also redirects to `https://www.{host}`). nginx does not read `.htaccess`. The site file denies that filename and uses `try_files` instead. Whether the internal redirect preserves the path Zend expects was not executed.

## PHP image

`php/Dockerfile` in full:

```dockerfile
FROM php:fpm-alpine
RUN apk add --update-cache libpng-dev
RUN docker-php-ext-install -j$(nproc) pdo_mysql && docker-php-ext-install -j$(nproc) gd
```

History of the install line:

| Commit | Extensions |
|---|---|
| `2cf321b` | `mysqli`, `gd` |
| `3b4de76` and `35effc1` | `pdo_mysql`, `gd` |

`apk add --update-cache` does not `apk del` the build packages. Image size and leftover packages were not measured.

The base tag `php:fpm-alpine` is not a version. Official PHP Alpine tags moved for years after 2019. A build today is not the image a build on 2019-03-15 would have produced. The Dockerfile does not install `mcrypt`. Magus code calls `mcrypt_create_iv` (`silicon_ark/magus-core/`). Provenance of the gap: **Implemented** absence in this Dockerfile, **Implemented** call in the application repo. Whether the 2019 base image already contained `mcrypt` is **Unknown**.

Compose sets `image: php:fpm-evolve` and `build.context: ./php`. The tag is local. It is not an official library tag.

## Database init

Mount target `/docker-entrypoint-initdb.d/dump.sql` is the MariaDB image's init directory. The file name ends in `.sql`.

`admin_magus.sql` at Magus `9b5b3e2` (the revision this infra pin includes):

- phpMyAdmin 4.8.3 dump, generated 15 March 2019 11:04, host `localhost:3306`, server `5.7.23-0ubuntu0.16.04.1`, PHP `7.1.14`.
- Comment line names database `admin_magus`.
- No `CREATE DATABASE` statement in the file.
- The blob is not the same object as at Magus `d5d0227` (the commit that added the dump). The diff is three lines: a trailing non-ASCII character on the comment above `CREATE TABLE Accreditation_Loading_Zones`, and one extra `INSERT` into `users`. Row values are personal data and are not copied here.

The server image is `mariadb`, not `mysql:5.7`. Compatibility of that dump with an unpinned MariaDB image was not tested.

No volume is mounted on the data directory (the image default is `/var/lib/mysql`). **Inferred:** removing the container discards loaded data, and the init script runs again on the next empty data directory. Not executed.

## Submodule

`.gitmodules`:

```ini
[submodule "magus-core"]
	path = magus-core
	url = git@github.com:EvolveAV/magus-core.git
	branch = master
```

| Infra commit | Gitlink |
|---|---|
| `a5b8870` | `d5d0227` |
| `3b4de76` through `35effc1` | `9b5b3e2` |

`d5d0227` is the Magus commit that added `admin_magus.sql`. `9b5b3e2` is "Updating Database Connection Details". Bitbucket `overdrive/magus-core` `master` at the time of the Magus Silicon Ark pass was `f806a7e` (2019-08-19), which is not pinned here.

`9b5b3e2` `application/configs/application.ini` `[development : production]` database keys: host `database`, user `root`, password `root`, name `magus_dev`. That is the section `APPLICATION_ENV=development` selects. The `[production]` section in the same file points at host `localhost`, database `admin_magus`, and a different user. The production password is a committed secret in `magus-core`. It is not repeated in Silicon Ark.

`f806a7e` changes both sections' database name to `magus`, host to `localhost`, user to `root`, password empty, and removes the HTTPS/`www` redirect from root `.htaccess`. Following the README's `git submodule update --recursive --remote` would move a clone toward that tip if the remote `master` is `f806a7e`, and the development INI would then disagree with this Compose file.

The README clone URL for this infra repo is `git@github.com:EvolveAV/evolve-infra.git`. The copy inspected is `git@bitbucket.org:overdrive/evolve-infra.git`. The GitHub remotes were not fetched.

## nginx.conf

`nginx.conf` is the usual stock main file: `user nginx`, `worker_processes 1`, `worker_connections 1024`, `include /etc/nginx/conf.d/*.conf`. It has been unchanged since `a5b8870`. Compose does not mount it. The `http` service uses the main config baked into `nginx:stable-alpine`, plus `nginx-site.conf` mounted as `conf.d/default.conf`.

## php-test

`php-test/public/index.php` uses `new mysqli("database", "root", "root", "magus_dev")`, queries `users` by a hardcoded email, prints the associative row, then calls `phpinfo()`. The email is not copied here.

`a5b8870` had `php-test/index.php` containing only `phpinfo()`. `2cf321b` replaced it with the script above. Nothing in later commits mounts the directory or switches the script to PDO.

## Security findings (no secret values beyond the published dev password)

The development password `root` is already printed in the README, Compose, and `php-test`. It is part of the operator contract, not an undisclosed production secret.

- Host ports 8080 and 8081 are published on all interfaces.
- phpMyAdmin is on 8081 with the MariaDB root password in the service environment.
- There is no TLS terminator in this repo.
- `phpinfo()` in `php-test` would expose the PHP environment if that script were placed on the document root. Compose does not do that.
- The Magus production database password and other application secrets are in the submodule, not in these infra files. See the Magus technical document. Do not copy them into this directory.
- `admin_magus.sql` contains operational personal data. It is not stored in evolve-infra; it is pulled in by the submodule. This document does not quote rows from it.

## Background work, queues, storage, monitoring

No worker, cron, queue, or log shipper is defined.

Persistent storage is not configured. Source is a bind mount. Database bytes stay in the container writable layer unless an operator adds a volume that this file does not declare.

Access and error logs are the paths in `nginx-site.conf` (`/var/log/nginx/access.log` and `error.log`) inside the nginx container. Nothing forwards them.

## Development and testing

README procedure:

1. Install Docker, docker-compose, and git.
2. Clone (URL in the README is the GitHub one).
3. `git submodule init` and `git submodule update --recursive --remote`.
4. `docker-compose up`.
5. Open `http://localhost:8080` and `http://localhost:8081`.
6. Optional: `docker exec -ti evolve-infra_database_1 mysql -h localhost -u root -proot magus_dev`.

There is no automated test. The README shell example uses a Compose v1 container name (underscores, `_1` suffix). Compose v2 names containers with hyphens. The file does not set `container_name`, so the example depends on the Compose release. **Unknown** which release was used in 2019. The README invokes `docker-compose` (hyphen), which is the v1 binary name.

A PHP source edit under `magus-core` is visible immediately because of the bind mount. A Dockerfile change needs an image rebuild. The README does not say to pass `--build`.

## Sonar files from the onboarding scan

`sonar-project.properties` and `sonarqube_scan.bat` were reported at the root of the scan-host checkout. They are not in `master`.

## Discrepancies to keep in view

1. README GitHub clone URL versus Bitbucket `overdrive/evolve-infra`.
2. README `--remote` submodule update versus gitlink `9b5b3e2`.
3. Gitlink `9b5b3e2` development database settings match Compose. Magus tip `f806a7e` development settings do not.
4. Dump comment database `admin_magus`, Compose database `magus_dev`, no `CREATE DATABASE` in the dump.
5. `mysqli` removed from the image; `php-test` still uses `mysqli` and is not mounted.
6. `mcrypt` is not installed here; Magus calls it.
7. `nginx.conf` is unused. Apache `.htaccess` in Magus does not run under this nginx site.
8. Image tags are not pinned. The stack was not run for this document.
9. Sonar files from the scan host are not in git.
