Config backup, a Docker dev/prod split, and a Gitea-built release image.
Added
- /settings -> General -> "Configuration backup": JSON export/import of the
panel's general settings + attribute definitions
(App\Services\ConfigBackupService); audited as config.export / config.import.
Export can leave out the attribute-encryption key. No AD data included.
- docker/compose.dev.yaml: live-reload dev stack that bind-mounts the working
tree. docker/php/Dockerfile is now multi-stage (base -> dev / prod).
- .github/workflows/release.yml: on every vX.Y.Z tag, builds the prod image and
pushes gitea.kzbikowski.pl/kzbkowski/adconsole:{X.Y.Z,X.Y,latest}.
Changed
- docker/compose.yaml: self-contained prod image (app code + composer install
--no-dev baked in via COPY); persistent state in docker/data/{app_storage,db};
defaults to the released image (ADCONSOLE_VERSION pins a tag, ADCONSOLE_IMAGE
replaces the ref). Apache now honours public/.htaccess (AllowOverride All).
Run from the repo root with --env-file .env.
- Repo root now holds only README.md; CHANGELOG / CONTRIBUTING / SECURITY /
CODE_OF_CONDUCT moved under docs/.
Upgrade notes: docs/upgrading.md#v110--docker-layout. Full log: docs/CHANGELOG.md.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKT9p3bfP8RZesExdYCS52
109 lines
4.4 KiB
Markdown
109 lines
4.4 KiB
Markdown
# Upgrading
|
|
|
|
## Versioning
|
|
|
|
From `v1.0.0` on, releases are [semantic](https://semver.org/) git tags
|
|
`vX.Y.Z`:
|
|
|
|
- **MAJOR** — incompatible change: a required new `.env` key, a schema change
|
|
that is not auto-migrated, or a new AD permission the service account needs.
|
|
Read this page before upgrading.
|
|
- **MINOR** — new, backwards-compatible feature. Safe to pull; still run
|
|
`php artisan migrate`.
|
|
- **PATCH** — backwards-compatible fix only.
|
|
|
|
The latest tag on `main` is the supported version; there are no long-term-support
|
|
branches. Per-version notes are under [Version notes](#version-notes) below and
|
|
in [`CHANGELOG.md`](CHANGELOG.md).
|
|
|
|
## General procedure
|
|
|
|
```sh
|
|
# back up the DB first (panel_settings + panel_attributes hold your config)
|
|
mysqldump adconsole > adconsole-$(date +%F).sql
|
|
|
|
git pull # or fetch a new release
|
|
composer install --no-dev --optimize-autoloader
|
|
php artisan migrate --force
|
|
php artisan optimize:clear
|
|
php artisan optimize # config + route + view + event cache
|
|
```
|
|
|
|
Docker (from the repo root): bump `ADCONSOLE_VERSION` in `.env`, then
|
|
`docker compose --env-file .env -f docker/compose.yaml pull` and
|
|
`… up -d`. The entrypoint runs `migrate --force` and `optimize` for you.
|
|
|
|
Roll back = restore the DB dump and either check out the previous revision or set
|
|
`ADCONSOLE_VERSION` back to the previous tag.
|
|
|
|
## Version notes
|
|
|
|
### v1.1.0 — Docker layout
|
|
|
|
The Docker files moved and the production image changed shape. One-time steps
|
|
for an **existing** Docker install:
|
|
|
|
1. `git pull` — `docker/compose.yaml` now lives in `docker/`, builds a
|
|
self-contained image, and reads persistent state from **`docker/data/`**
|
|
bind mounts instead of the `adconsole_db_data` / `adconsole_app_storage`
|
|
named volumes.
|
|
2. Stop the old stack: `docker compose -f docker/compose.yaml down` (old file).
|
|
3. Copy the volume contents into `docker/data/` **before** the first new `up`:
|
|
|
|
```sh
|
|
mkdir -p docker/data/db docker/data/app_storage
|
|
docker run --rm -v adconsole_db_data:/from -v "$PWD/docker/data/db":/to \
|
|
alpine cp -a /from/. /to/
|
|
docker run --rm -v adconsole_app_storage:/from -v "$PWD/docker/data/app_storage":/to \
|
|
alpine cp -a /from/. /to/
|
|
```
|
|
|
|
4. Start it, always from the repo root and with `--env-file .env`:
|
|
|
|
```sh
|
|
docker compose --env-file .env -f docker/compose.yaml up -d
|
|
```
|
|
|
|
(`export COMPOSE_FILE=docker/compose.yaml COMPOSE_ENV_FILES=.env` once to drop
|
|
the flags.) `up -d` now **pulls** the released image; add `--build` to build
|
|
from the working tree.
|
|
|
|
Rootless Docker can't `chown` a bind-mounted MariaDB datadir — run the daemon
|
|
rootful, or switch the `mariadb` volume in `docker/compose.yaml` to a named
|
|
volume. Nothing changes for a **bare-metal** install.
|
|
|
|
### Panel configuration moved into the database
|
|
|
|
Two migrations, both automatic — just run `php artisan migrate` (the Docker
|
|
entrypoint does this for you).
|
|
|
|
1. **`create_panel_settings_table`** — general settings (password policy &
|
|
generator, reset-dialog defaults, encryption key) move out of the old
|
|
`storage/app/panel_settings.json`. The migration **imports that file if
|
|
present** and renames it `panel_settings.json.migrated`.
|
|
2. **`create_panel_attributes_table`** — the AD attribute / column definitions
|
|
move from the JSON blob into their own table, one row per attribute with
|
|
real columns (`key`, `label`, `ldap`, `category`, `type`, `is_column`,
|
|
`position`). The migration copies the existing list across and strips the
|
|
now-unused `attributes` (and dead `domains` / `users_table`) keys from the
|
|
`panel_settings` row.
|
|
|
|
- After migrating, open `/settings` and confirm the **General** tab and the
|
|
**Attributes** tab still show your settings, then delete any
|
|
`storage/app/panel_settings.json.migrated`.
|
|
- Fresh installs have empty tables and run on `PanelSettingsService::defaults()`
|
|
/ `defaultAttributes()` until you save something.
|
|
- The legacy file and its `.migrated` rename are git-ignored.
|
|
|
|
### New `.env` keys
|
|
|
|
`LDAP_SSL`, `LDAP_TLS_VERIFY`, `APP_DOMAIN`. Existing installs keep working with
|
|
the defaults (`LDAP_SSL=true`, `LDAP_TLS_VERIFY=false`); add explicit values when
|
|
you next edit `.env`. See [configuration.md](configuration.md).
|
|
|
|
## After any upgrade
|
|
|
|
- `php artisan test` if you carry local patches.
|
|
- Re-check the [hardening checklist](deployment.md#hardening-checklist).
|
|
- Watch `storage/logs/laravel.log` on the first real use.
|