mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-09-25 01:53:03 +02:00
feat(provision): idempotent setup for local dev and remote server
This commit is contained in:
+35
-17
@@ -19,38 +19,56 @@ Deployment is orchestrated through the `justfile` (`deploy` group).
|
||||
|
||||
## One-time server setup
|
||||
|
||||
From a machine with `ssh` access to the `xamxam` host, run the full remote
|
||||
provisioning once:
|
||||
|
||||
```bash
|
||||
ssh xamxam
|
||||
sudo mkdir -p /var/www/xamxam
|
||||
sudo chown www-data:xamxam /var/www/xamxam
|
||||
sudo chmod 775 /var/www/xamxam
|
||||
exit
|
||||
just provision-server
|
||||
```
|
||||
|
||||
Then from local, deploy once and apply the nginx config + verify permissions:
|
||||
This chains (each step is also runnable individually):
|
||||
|
||||
1. `scripts/provision-server-env.sh` — ensure the server has an `APP_KEY` in
|
||||
`/var/www/xamxam/.env` (idempotent; see below).
|
||||
2. `just deploy` — code + Composer deps + migrations + permissions.
|
||||
3. `just deploy-nginx` — install + apply the nginx config and fix permissions.
|
||||
4. `just deploy-backup`, `just deploy-cleanup-cron`, `just deploy-logrotate` —
|
||||
install backup + cleanup cron jobs and log rotation.
|
||||
|
||||
It finishes by telling you what's left to do in `/admin/account` (set the admin
|
||||
password — a fresh DB starts unauthenticated — and configure SMTP/PeerTube
|
||||
credentials and Nextcloud sync).
|
||||
|
||||
If you'd rather do it step by step (e.g. you already provisioned nginx):
|
||||
|
||||
```bash
|
||||
just deploy
|
||||
just deploy-nginx
|
||||
```
|
||||
|
||||
For a full initial rollout including backup + cleanup cron jobs:
|
||||
For a full initial rollout *without* the env/nginx steps (backup + cleanup cron
|
||||
only), when those are already handled:
|
||||
|
||||
```bash
|
||||
just deploy-all-first # deploy + deploy-backup + deploy-cleanup-cron
|
||||
just deploy-all-first # deploy + deploy-backup + deploy-cleanup-cron + deploy-logrotate
|
||||
```
|
||||
|
||||
### First-time `APP_KEY` on a brand-new server
|
||||
### Server `APP_KEY` — idempotent, never overwrites
|
||||
|
||||
`deploy-env` uploads the **local** `app/.env` only when the remote has none. Do
|
||||
**not** rely on a committed `.env` — generate a fresh key per environment and put
|
||||
it on the server before first `deploy`: create `app/.env` locally (see
|
||||
[development.md](development.md#appkey-and-the-appenv-file)) so `deploy-env`
|
||||
uploads it, or create `/var/www/xamxam/.env` on the server directly:
|
||||
`just provision-server` (via `scripts/provision-server-env.sh`) ensures the
|
||||
server has an `APP_KEY` in `/var/www/xamxam/.env`. It is **idempotent** and will
|
||||
**never overwrite an existing key**:
|
||||
|
||||
```bash
|
||||
ssh xamxam 'sudo -u www-data bash -c "echo APP_KEY=\$(php -r \"echo base64_encode(random_bytes(32));\") > /var/www/xamxam/.env; chmod 640 /var/www/xamxam/.env; chown www-data:xamxam /var/www/xamxam/.env"'
|
||||
```
|
||||
- If `/var/www/xamxam/.env` already has an `APP_KEY=…` → it is left untouched
|
||||
and the script prints that the key already exists (so encrypted credentials
|
||||
stay decryptable). It exits `0`.
|
||||
- If the file exists but has no `APP_KEY` → a fresh key is appended, existing
|
||||
lines untouched.
|
||||
- If the file is absent → it is created with a fresh key.
|
||||
|
||||
Ownership (`www-data:xamxam`) and permissions (`640`) are normalised after any
|
||||
write. `deploy-env` also refuses to overwrite a remote `.env` that already has
|
||||
`APP_KEY`.
|
||||
|
||||
If you ever rotate `APP_KEY`, re-encrypt the SMTP password with
|
||||
`just reencrypt-password <new_base64_key>` and push the new key via
|
||||
|
||||
+25
-9
@@ -13,8 +13,23 @@ Setup, workflow, building assets, and testing for XAMXAM development.
|
||||
|
||||
## One-time setup
|
||||
|
||||
From the repo root, install dependencies (manually — there is no `just` recipe
|
||||
for these):
|
||||
From the repo root, run the provisioning script:
|
||||
|
||||
```bash
|
||||
just provision
|
||||
```
|
||||
|
||||
This is **idempotent** and safe to re-run. It:
|
||||
|
||||
1. Ensures `app/.env` has an `APP_KEY` — **never overwrites an existing key**
|
||||
(it prints a message and keeps the current one so encrypted credentials stay
|
||||
decryptable).
|
||||
2. Installs Composer deps (`composer install`) and JS deps (`npm ci`).
|
||||
3. Runs the DB schema + migrations (`just migrate`).
|
||||
4. Checks the first-admin-password state and tells you if `/admin/` is still
|
||||
unauthenticated.
|
||||
|
||||
If you prefer to run the steps manually, or `just` isn't installed yet:
|
||||
|
||||
```bash
|
||||
composer install # PHP deps (vendor/)
|
||||
@@ -26,8 +41,7 @@ just migrate # create/update the SQLite DB from schema + migration
|
||||
— it still clones the old `php-live-reload` library and creates legacy
|
||||
`admin/data/` directories. Live-reload now ships inside the app
|
||||
(`app/public/live-reload.php`), and assets are built with rolldown/lightningcss,
|
||||
not the live-reload watcher. Prefer the explicit `composer install` + `npm ci`
|
||||
above.
|
||||
not the live-reload watcher. Prefer `just provision`.
|
||||
|
||||
### APP_KEY and the app/.env file
|
||||
|
||||
@@ -40,17 +54,19 @@ password, PeerTube credentials, and Nextcloud WebDAV sync) requires an
|
||||
APP_KEY=<base64-encoded 32 random bytes>
|
||||
```
|
||||
|
||||
Generate one with:
|
||||
Generate one manually with:
|
||||
|
||||
```bash
|
||||
php -r 'echo "APP_KEY=" . base64_encode(random_bytes(32)) . PHP_EOL;' > app/.env
|
||||
chmod 600 app/.env
|
||||
```
|
||||
|
||||
`app/.env` must **never** be committed. If the file is missing, the public site
|
||||
still runs but any path that reads encrypted credentials throws
|
||||
`RuntimeException: APP_KEY not found`. On a fresh clone, create it before
|
||||
relying on SMTP/PeerTube/Nextcloud features.
|
||||
`app/.env` must **never** be committed. `just provision` only creates `app/.env`
|
||||
(or appends `APP_KEY`) when the key is absent — if the value already exists it
|
||||
is left untouched so existing encrypted credentials (SMTP password, PeerTube
|
||||
OAuth, Nextcloud WebDAV) remain decryptable. If the file is missing, the public
|
||||
site still runs but any path that reads encrypted credentials throws
|
||||
`RuntimeException: APP_KEY not found`.
|
||||
|
||||
### First admin login
|
||||
|
||||
|
||||
Reference in New Issue
Block a user