docs: replace private deployment topology with configuration
This commit is contained in:
+51
-60
@@ -1,80 +1,85 @@
|
|||||||
# Unraid deployment
|
# Unraid deployment
|
||||||
|
|
||||||
MobilityOps is deployed from a committed source archive; the server does not need Gitea
|
MobilityOps is deployed from a committed source archive; the server does not need Gitea credentials. The portable `compose.yaml` is combined with `compose.unraid.yaml`. Of the MobilityOps-owned services, only the web application should be reachable from the trusted network. PostgreSQL and the API remain on the Compose network.
|
||||||
credentials. The portable `compose.yaml` is combined with `compose.unraid.yaml`; of the
|
|
||||||
MobilityOps-owned services, only the web application is reachable from the LAN. The host's
|
All hostnames, ports, paths and public domains below are operator-controlled configuration. Do not commit a production `.env`, SSH target or infrastructure inventory.
|
||||||
existing shared n8n remains available on its established port 5678.
|
|
||||||
|
|
||||||
## Server layout
|
## Server layout
|
||||||
|
|
||||||
- Directory: `/mnt/user/appdata/mobilityops`
|
Define a local appdata root and URLs before following the examples:
|
||||||
- Compose project: `mobilityops`
|
|
||||||
- Public web: `https://fleetops.itworx.tech` (TLS reverse proxy to host port `1236`)
|
|
||||||
- API and PostgreSQL: Compose network only
|
|
||||||
- Shared n8n: `http://192.168.10.150:5678` (outside the MobilityOps Compose project)
|
|
||||||
|
|
||||||
## Deploy
|
```bash
|
||||||
|
export MOBILITYOPS_APPDATA_DIR=/mnt/user/appdata/mobilityops
|
||||||
|
export MOBILITYOPS_PUBLIC_URL=https://fleetops.example.com
|
||||||
|
export N8N_BASE_URL=https://automation.example.com
|
||||||
|
```
|
||||||
|
|
||||||
Create `.env` from `.env.example`, replace every placeholder secret, set
|
The `/mnt/user/appdata/...` value is an illustrative Unraid convention, not a repository requirement. Use a different persistent directory where appropriate.
|
||||||
`MOBILITYOPS_ENV=production`, set both public URLs to
|
|
||||||
`https://fleetops.itworx.tech`, set `SESSION_COOKIE_SECURE=true`, and configure
|
|
||||||
`KNOWLEDGE_PROVIDER=ragcore` only after the RAGcore health and source inventory checks pass.
|
|
||||||
The internal `1236` listener is
|
|
||||||
an upstream for the TLS proxy, not a user-facing URL.
|
|
||||||
|
|
||||||
When RAGcore runs as a separate Compose project on the same host, keep its HTTP listener
|
- application directory: `${MOBILITYOPS_APPDATA_DIR}`;
|
||||||
private and configure Fleet Ops through the existing shared Docker network, for example:
|
- Compose project: `mobilityops`;
|
||||||
|
- public web URL: `${MOBILITYOPS_PUBLIC_URL}`;
|
||||||
|
- API and PostgreSQL: Compose network only;
|
||||||
|
- shared n8n: `${N8N_BASE_URL}`, outside the MobilityOps Compose project.
|
||||||
|
|
||||||
|
## Configure
|
||||||
|
|
||||||
|
Create `.env` from `.env.example`, replace every placeholder secret and set:
|
||||||
|
|
||||||
|
```dotenv
|
||||||
|
MOBILITYOPS_ENV=production
|
||||||
|
MOBILITYOPS_PUBLIC_URL=https://fleetops.example.com
|
||||||
|
MOBILITYOPS_API_PUBLIC_URL=https://fleetops.example.com/api
|
||||||
|
N8N_WEBHOOK_URL=https://automation.example.com/webhook/mobilityops-return
|
||||||
|
SESSION_COOKIE_SECURE=true
|
||||||
|
```
|
||||||
|
|
||||||
|
Configure `KNOWLEDGE_PROVIDER=ragcore` only after the RAGcore health and source-inventory checks pass. When RAGcore runs as a separate Compose project on the same host, keep its HTTP listener private and configure Fleet Ops through a shared Docker network, for example:
|
||||||
|
|
||||||
```dotenv
|
```dotenv
|
||||||
RAGCORE_BASE_URL=http://ragcore-app:8080
|
RAGCORE_BASE_URL=http://ragcore-app:8080
|
||||||
RAGCORE_DOCKER_NETWORK=ragcore-proxy
|
RAGCORE_DOCKER_NETWORK=ragcore-proxy
|
||||||
```
|
```
|
||||||
|
|
||||||
The release deployer validates the network, attaches only the API replicas and takes the
|
The release deployer takes non-secret integration URLs from the server `.env` on every promotion. Tokens and resolved API environment remain server-side and must not be printed.
|
||||||
non-secret RAGcore URL from the server `.env` on every promotion. Tokens and the remaining
|
|
||||||
resolved API environment continue to be inherited without being printed.
|
## Deploy
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /mnt/user/appdata/mobilityops
|
cd "${MOBILITYOPS_APPDATA_DIR}"
|
||||||
./deploy/unraid/configure-env.sh \
|
./deploy/unraid/configure-env.sh \
|
||||||
https://fleetops.itworx.tech \
|
"${MOBILITYOPS_PUBLIC_URL}" \
|
||||||
https://n8n.itworx.tech/webhook/mobilityops-return
|
"${N8N_BASE_URL}/webhook/mobilityops-return"
|
||||||
|
|
||||||
git archive --format=tar.gz -o /tmp/mobilityops-source.tar.gz HEAD
|
git archive --format=tar.gz -o /tmp/mobilityops-source.tar.gz HEAD
|
||||||
sha256sum /tmp/mobilityops-source.tar.gz
|
sha256sum /tmp/mobilityops-source.tar.gz
|
||||||
# Copy the archive and run deploy-release.sh with its SHA-256 and full Git SHA.
|
# Copy the archive and run deploy-release.sh with its SHA-256 and full Git SHA.
|
||||||
```
|
```
|
||||||
|
|
||||||
`deploy-release.sh` stages a clean, commit-named release, builds OCI-labelled immutable
|
`deploy-release.sh` stages a clean, commit-named release, builds OCI-labelled immutable API/web images, starts candidate replicas behind a stable gateway and removes previous replicas only after public readiness passes. It promotes without a seed/reset and leaves the database, backups and monitoring untouched during routine releases.
|
||||||
API/web images, starts two candidate replicas per stateless service behind a stable gateway,
|
|
||||||
and removes the previous replicas only after public readiness passes. It promotes without a
|
|
||||||
seed/reset and leaves the database, backups and monitoring untouched during routine app
|
|
||||||
releases. Run `python -m app.cli seed --reset` only for initial setup or
|
|
||||||
an explicit synthetic-demo reset; it is never part of a routine deployment.
|
|
||||||
|
|
||||||
Refresh the pinned stateful and monitoring containers explicitly after reviewing their
|
Run `python -m app.cli seed --reset` only for initial setup or an explicit synthetic-demo reset; it is never part of a routine deployment.
|
||||||
version/configuration changes:
|
|
||||||
|
Refresh pinned stateful and monitoring containers explicitly after reviewing version and configuration changes:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./deploy/unraid/refresh-infrastructure.sh
|
./deploy/unraid/refresh-infrastructure.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Migrations run automatically in the API entrypoint. Import and publish the MobilityOps
|
Import and publish the MobilityOps workflow into an existing n8n container:
|
||||||
workflow into the existing n8n container:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./deploy/unraid/setup-existing-n8n.sh \
|
./deploy/unraid/setup-existing-n8n.sh \
|
||||||
n8n \
|
n8n \
|
||||||
https://fleetops.itworx.tech/api/v1/integrations/n8n/return-callback
|
"${MOBILITYOPS_PUBLIC_URL}/api/v1/integrations/n8n/return-callback"
|
||||||
```
|
```
|
||||||
|
|
||||||
The callback token remains server-side and is never written to the repository. The
|
The callback token remains server-side and is never written to the repository. The bundled n8n service is a standalone fallback behind the explicit `bundled-n8n` Compose profile and is not started by the standard deployment.
|
||||||
bundled n8n service is retained only as a standalone fallback behind the explicit
|
|
||||||
`bundled-n8n` Compose profile; it is not started in this deployment.
|
|
||||||
|
|
||||||
## Operate
|
## Operate
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cd /mnt/user/appdata/mobilityops
|
cd "${MOBILITYOPS_APPDATA_DIR}"
|
||||||
docker compose -p mobilityops -f compose.yaml -f compose.unraid.yaml ps
|
docker compose -p mobilityops -f compose.yaml -f compose.unraid.yaml ps
|
||||||
docker compose -p mobilityops -f compose.yaml -f compose.unraid.yaml logs --tail=200
|
docker compose -p mobilityops -f compose.yaml -f compose.unraid.yaml logs --tail=200
|
||||||
docker compose -p mobilityops -f compose.yaml -f compose.unraid.yaml exec api alembic current
|
docker compose -p mobilityops -f compose.yaml -f compose.unraid.yaml exec api alembic current
|
||||||
@@ -83,29 +88,18 @@ docker logs --tail=200 n8n
|
|||||||
|
|
||||||
## Backup and restore
|
## Backup and restore
|
||||||
|
|
||||||
The `backup` service creates a backup immediately and then every 24 hours. Every dump is
|
The `backup` service creates a backup immediately and every 24 hours. Each dump is checked by SHA-256 and `pg_restore --list`; at least weekly the newest dump is restored into a disposable database and its migration revision and core table counts are verified. Backups are retained for 30 days with at least seven copies protected from pruning. Health becomes unhealthy when the daily backup or eight-day restore-drill SLA is missed.
|
||||||
checked by SHA-256 and `pg_restore --list`; at least weekly the newest dump is also restored
|
|
||||||
into a disposable database and its migration revision and core table counts are verified.
|
|
||||||
Backups are retained for 30 days with at least seven copies protected from pruning. Its
|
|
||||||
healthcheck becomes unhealthy when the daily backup or eight-day restore-drill SLA is missed.
|
|
||||||
|
|
||||||
For this synthetic demo, OneDrive is the supported real off-site target. The optional worker
|
For a synthetic demo, an operator-configured rclone remote may be used as an off-site target. OAuth material belongs in an untracked, mode-0600 rclone configuration directory:
|
||||||
uploads the newest locally verified dump and checksum, downloads both again, verifies the
|
|
||||||
round trip, and performs a weekly restore into a disposable database. Its OAuth token remains
|
|
||||||
in the untracked mode-0600 rclone configuration directory. Configure it once from an
|
|
||||||
interactive server terminal (Microsoft browser authorization is required):
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./deploy/unraid/configure-onedrive-backup.sh onedrive
|
./deploy/unraid/configure-onedrive-backup.sh <rclone-remote>
|
||||||
docker inspect --format '{{.State.Health.Status}}' mobilityops-offsite-backup-1
|
docker inspect --format '{{.State.Health.Status}}' mobilityops-offsite-backup-1
|
||||||
```
|
```
|
||||||
|
|
||||||
Set `RCLONE_ONEDRIVE_PATH` to change the default `FleetOps/backups` folder. Do not set
|
Do not point `BACKUP_SECONDARY_DESTINATION` to another directory on the same storage system and describe it as off-site.
|
||||||
`BACKUP_SECONDARY_DESTINATION` to another path on the same server and call that off-site;
|
|
||||||
that legacy mount remains available only for an independently mounted filesystem.
|
|
||||||
|
|
||||||
Create an additional on-demand backup, verify the newest backup, or execute the isolated
|
Create an on-demand backup, verify the newest backup or execute an isolated restore drill:
|
||||||
restore drill:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./deploy/unraid/backup-postgres.sh
|
./deploy/unraid/backup-postgres.sh
|
||||||
@@ -114,8 +108,7 @@ docker compose -p mobilityops -f compose.yaml -f compose.unraid.yaml exec -T bac
|
|||||||
/opt/mobilityops/restore-drill-postgres.sh /backups/<backup>.dump
|
/opt/mobilityops/restore-drill-postgres.sh /backups/<backup>.dump
|
||||||
```
|
```
|
||||||
|
|
||||||
A restore is deliberately guarded and creates an additional safety backup before
|
A restore is guarded and creates an additional safety backup before replacing the database:
|
||||||
replacing the database:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./deploy/unraid/restore-postgres.sh \
|
./deploy/unraid/restore-postgres.sh \
|
||||||
@@ -123,6 +116,4 @@ replacing the database:
|
|||||||
RESTORE-MOBILITYOPS
|
RESTORE-MOBILITYOPS
|
||||||
```
|
```
|
||||||
|
|
||||||
The restore stops the API, recreates only the configured MobilityOps database, restarts
|
Test restores in a disposable environment before using a production backup for incident recovery.
|
||||||
API/web and verifies the active Alembic revision. Test restores in a disposable environment
|
|
||||||
before using a production backup for incident recovery.
|
|
||||||
|
|||||||
Reference in New Issue
Block a user