# Manage Update and backup server for PHP projects, plus a redistributable client package. ## Purpose Multiple independent PHP projects need the same two things: a way to roll out new versions, and regular backups of operational data. `manage` provides both centrally instead of building them into each project again. One installation serves **one product** with a manageable number of instances. For another product, `manage` is deployed again. ## Core features - Release management: upload packages, checksums computed server-side, set the current release - Backup reception per instance, with two retention tiers and an optional S3 archive - Instance registry with token authentication, deactivation and token rotation - Overview of installed versions, latest backups and pending migrations - Client package with a command line, a ready-made admin UI and a function API ## Requirements - PHP 8.x - a web server (Apache with `.htaccess` enabled, or nginx with the equivalent locks set) - write access to `storage/` No database, no Composer, no build step, no external libraries. ## Key files - Configuration: `config.php` (from `config.sample.php`) - UI: `admin/` - Client interface: `api/v1/` - Shared library: `includes/` - State: `storage/` (not public) - Redistributable client package: `client-package/` ## Setup 1. Copy `config.sample.php` to `config.php`. 2. Generate a password hash and enter it as `MANAGE_ADMIN_PASSWORD_HASH`: `php -r 'echo password_hash("…", PASSWORD_DEFAULT), PHP_EOL;'` 3. Set `MANAGE_PUBLIC_URL` to the absolute address of this installation. 4. Set `MANAGE_PRODUCT_NAME` and `MANAGE_PACKAGE_PREFIX` to the product being served. 5. Make sure `storage/` is writable. 6. Open `admin/login.php` and check under **Settings → Diagnostics** that everything essential checks out. Details: [docs/SERVER_SETUP.md](docs/SERVER_SETUP.md). ## Connecting a project 1. In the Manage server under **Instances**, create an instance and note the token shown once. 2. Build and hand over the client package: `./scripts/build-client-package.sh --server-url https://manage.example.org` 3. In the project: copy in `manage-client/`, create `config.php`, run `php manage-client/bin/manage-client.php status`. The complete guide for this lives **inside the package itself** ([client-package/README.md](client-package/README.md)), so the receiving side needs no access to this repository. ## Documentation Server-side, in `docs/`: - [ARCHITECTURE.md](docs/ARCHITECTURE.md) – structure, data flow, storage formats - [SERVER_SETUP.md](docs/SERVER_SETUP.md) – installation, web server, limits, S3 - [INSTANCE_MANAGEMENT.md](docs/INSTANCE_MANAGEMENT.md) – instances, tokens, handing over the client package - [RELEASING.md](docs/RELEASING.md) – building and publishing packages - [CONFIG_REFERENCE.md](docs/CONFIG_REFERENCE.md) – every server constant For projects, in `client-package/docs/`: quickstart, integration, configuration, function API, backup sources, packaging, post-update hooks, protocol, troubleshooting, security. Readable in the browser via `docs/index.php` and `client-package/docs/index.php` respectively (Markdown rendered with the bundled [marked](https://marked.js.org/)). ### Public client handbook `client-docs/` publishes the content of `client-package/` over HTTP: every chapter and every source file as its own page, plus the interface as OpenAPI. Unlike `admin/` and `api/v1/`, this folder is reachable without logging in — it exists to be handed out, so a project can be integrated without shipping a ZIP first. | Address | Content | |---|---| | `client-docs/` | overview, from there a chapter or a source file | | `client-docs/index.php?doc=01_QUICKSTART` | one chapter | | `client-docs/index.php?code=manage-client/lib/updater.php` | one source file | | `client-docs/api.php` | protocol v1 in Swagger UI | | `client-docs/openapi.php` | the OpenAPI document alone, for code generators | For programs, the same pages exist as plain Markdown under `llms.php`, with `llms.php?doc=…` and `llms.php?code=…` alongside. `client-docs/llms.php` is the index: it names every page with a one-sentence description and its size, and for the usual tasks — integrate the client, backups only, updater only, write your own client, troubleshooting — lists the short set of pages that suffices. That is the point of the split: load only what is needed. This is the address to hand to an LLM. Apache additionally answers `llms.txt`; `llms.php` is canonical, because that works without `mod_rewrite`. The pages for humans render their Markdown in the browser and carry a comment and an invisible element in the source that point to the Markdown version of the same page — a program that lands there by accident finds its way. The content is read from `client-package/` on every request; there is nothing to build and nothing to regenerate. `manage-client/config.php` is excluded from publication, so a locally created token never becomes public. marked and Swagger UI live under `client-docs/assets/` in the repository. No external server is contacted, not even for fonts or icons. ## What is deliberately missing - **No restore.** Backups are created, transferred and made available for download, but never played back automatically. An update backs up the files it overwrites, but cannot bring them back. - **No automatic updates.** The server offers; the instance decides. - **No package signing.** The checksum and the package come from the same server; the safeguard is TLS plus the token. The Manage server must be secured accordingly. - **No per-instance channels.** There is one current release for all instances of a server. ## Notes - No automated test/CI setup is provided.