docs: what a site needs that no page answered
Four gaps a second site hits and cannot resolve by reading. **Restoring on Windows** was one sentence - "the standard mysql < dump.sql" - with no ordering. Restoring a database under running code that expects a different schema turns a restore into a second incident, so the steps are now ordered and each says why. It also says what `.env` costs if it is lost, which is the part nobody discovers until they are already rebuilding: the dump does not contain it, and without the JWT secrets every issued token dies, so every collector and every GE-Enforce client on the fleet needs a new key. **Rolling back** had a paragraph saying downgrades are refused and a backup is the way back, but not the procedure. Rollback is restoring a matched pair, code and the schema it expects, in that order - and the doc now separates it from the case it gets confused with: a migration that failed mid-update has already been rolled back by the installer, and fixing forward is the only move. **Sizing, acquisition and support** were absent from the install guide entirely. A reader could not learn how big a server to ask for, where the .exe comes from, or where to raise a problem. The sizing is small and the reasons are stated, so a site does not over-provision a VM for a load that is a few dozen users. **Credentials** were described in three documents from three ends, so three answers existed for where a key lives. One table, both ends - server and PC - plus the two rules behind it: what a shop-floor PC holds is scoped to exactly what it does, and a credential is delivered rather than typed, because a value entered per machine is a value that is wrong on some machine.
This commit is contained in:
@@ -166,10 +166,53 @@ Two Windows-specific notes:
|
||||
using a remote MySQL needs `mysqlclient\` in its installer bundle, or the
|
||||
pre-upgrade backup is skipped. `shopdb-admin.ps1 check` reports this.
|
||||
|
||||
Restoring is the standard `mysql < dump.sql`, then
|
||||
`.\shopdb-admin.ps1 restart`. Also restore `C:\shopdb-flask\instance\` if you are
|
||||
rebuilding a server - it holds uploaded branding and map blueprints, which the
|
||||
database does not.
|
||||
### Restoring on Windows, in order
|
||||
|
||||
Order matters. Restoring the database under running code that expects a
|
||||
different schema is how a restore turns into a second incident.
|
||||
|
||||
```powershell
|
||||
cd C:\shopdb-flask
|
||||
|
||||
# 1. Stop serving. The pool, not the whole site: other applications on this
|
||||
# IIS server are unaffected.
|
||||
.\shopdb-admin.ps1 stop
|
||||
|
||||
# 2. Restore the database. Use the dump taken closest BEFORE the problem,
|
||||
# not the newest one - the newest may already contain it.
|
||||
mysql -u root -p shopdb_flask < C:\ProgramData\ShopDB-Flask\backups\shopdb_flask-pre-upgrade-20260814-0730.sql
|
||||
|
||||
# 3. Restore instance\ if you are rebuilding a server rather than just
|
||||
# reverting data. It holds uploaded branding, map blueprints, application
|
||||
# images and warranty proofs - none of which are in the database.
|
||||
robocopy D:\backups\instance C:\shopdb-flask\instance /MIR
|
||||
|
||||
# 4. Start, then prove it.
|
||||
.\shopdb-admin.ps1 start
|
||||
.\shopdb-admin.ps1 check -Json
|
||||
```
|
||||
|
||||
`check -Json` reports version, publishing method, IIS and pool state, HTTP
|
||||
reachability, database reachability, Python version and installed plugins. If it
|
||||
passes, the restore worked; if the version it reports is not the version you
|
||||
expect, see "Rolling back a release" in [UPDATES-WINDOWS.md](UPDATES-WINDOWS.md),
|
||||
because a restored database and newer code is the one combination the installer
|
||||
cannot fix for you.
|
||||
|
||||
### What is lost if `.env` is lost
|
||||
|
||||
`.env` is not in the database dump, and rebuilding it is not simply retyping it:
|
||||
|
||||
| Value | If it is lost |
|
||||
|---|---|
|
||||
| `SECRET_KEY`, `JWT_SECRET_KEY` | Every issued token and session becomes invalid. Users log in again; managed API tokens must be reissued, which means every collector and GE-Enforce client needs its key replaced. Recoverable, but it is a fleet-wide job. |
|
||||
| `DATABASE_URL` password | Recoverable: reset the MySQL user's password and write the new one in. |
|
||||
| `MYSQL_ROOT_PASSWORD` | Recoverable through MySQL's own reset procedure, which requires stopping the server. |
|
||||
| `ZABBIX_TOKEN` and similar integration tokens | Reissue at the far end. Nothing else breaks. |
|
||||
|
||||
So back it up with the database, to somewhere as protected as the dump - it is
|
||||
ACL'd to Administrators and SYSTEM on the server for the same reason. A dump
|
||||
without its `.env` restores the data and locks everyone out of it.
|
||||
|
||||
See [OPERATE-WINDOWS.md](OPERATE-WINDOWS.md).
|
||||
|
||||
|
||||
@@ -68,6 +68,25 @@ takes everything over HTTPS, because those PCs have no share.
|
||||
credentials at all, because a screensaver and a wall display have nowhere to
|
||||
keep one. They are read-only and carry nothing a floor visitor should not see.
|
||||
|
||||
## Where the credentials live
|
||||
|
||||
Three documents each named a different place, which is what happens when a
|
||||
credential is described from whichever end the author was working on. Both ends
|
||||
are here.
|
||||
|
||||
| Credential | On the server | On the PC | Rotate by |
|
||||
|---|---|---|---|
|
||||
| Collector key | A managed token scoped to `collector.ingest` only. `COLLECTOR_API_KEY` in `.env` also works and is simpler for a pilot, but cannot be revoked per fleet. | `HKLM:\SOFTWARE\GE\ShopDB` value `CollectorKey` | Replacing the token file the fleet reads from, so every PC picks it up on its next cycle. Never put it in the manifest - manifests sync broadly. |
|
||||
| GE-Enforce fetch token | A managed service token scoped to the GE-Enforce fetch scope | `HKLM:\SOFTWARE\GE\ShopDB` value `ApiToken` | Same path as the collector key |
|
||||
| Server URL | n/a | `HKLM:\SOFTWARE\GE\ShopDB` value `BaseUrl` | Setting it once at install; nothing should overwrite a bay's own value |
|
||||
| Application secrets | `.env`: `SECRET_KEY`, `JWT_SECRET_KEY`, `DATABASE_URL`, integration tokens | n/a | See [BACKUP-RESTORE](BACKUP-RESTORE.md) - losing these invalidates every issued token |
|
||||
|
||||
Two rules behind that table. A shop-floor PC is not a trusted place, so what it
|
||||
holds is scoped to exactly what it does: a collector key that leaks buys the
|
||||
reader the ability to file a PC report, not to read the asset register. And a
|
||||
credential is delivered, never typed - a value that has to be entered per machine
|
||||
is a value that is wrong on some machine.
|
||||
|
||||
## What owns what
|
||||
|
||||
The question that decides most arguments: **who is allowed to change this?**
|
||||
|
||||
@@ -27,6 +27,47 @@ Installing IIS, if it is missing (this needs no internet):
|
||||
Install-WindowsFeature -Name Web-Server -IncludeManagementTools
|
||||
```
|
||||
|
||||
### Sizing the server
|
||||
|
||||
Small, and the reasons are worth stating so a site does not over-provision.
|
||||
ShopDB serves one plant's own staff, not the internet: a busy instance handles a
|
||||
few dozen concurrent users and a fleet reporting a few hundred PCs a day, and
|
||||
both are trivial loads. What actually consumes resources is MySQL and the
|
||||
uploads.
|
||||
|
||||
| | Minimum | Comfortable | Why |
|
||||
|---|---|---|---|
|
||||
| Disk | 5 GB free (the installer refuses below this) | 40 GB | The application and Python are about 1 GB. The rest is MySQL, config-backup revisions, and uploads - branding, floor-plan blueprints, application installers and warranty proofs, which are the only ones that grow without bound. |
|
||||
| RAM | 4 GB | 8 GB | MySQL wants most of it. The application itself is a Python worker per request. |
|
||||
| CPU | 2 cores | 4 cores | Reports and the map are the heaviest reads and are cached. |
|
||||
|
||||
A VM is entirely normal. The one thing worth insisting on is that the database
|
||||
directory and the backup directory are not on the same disk as anything you
|
||||
would be sad to fill up.
|
||||
|
||||
### Getting the installer
|
||||
|
||||
The `.exe` is a release asset on the GitHub repository, not a file in it - it is
|
||||
around 240 MB, which is well past what a repository accepts and well inside what
|
||||
a release asset does. Take it from the release page for the version you want,
|
||||
and keep it: you need the previous one to roll a release back, and you cannot
|
||||
download it from your own server.
|
||||
|
||||
Every build is stamped with its version and ships a CycloneDX SBOM onto the
|
||||
server, so `shopdb-admin.ps1 verify -Path <name>` answers "does this server
|
||||
carry component X" without a network call - which is the question that arrives
|
||||
on a Friday afternoon after a CVE announcement.
|
||||
|
||||
### If you get stuck
|
||||
|
||||
Raise an issue on the repository. Include the output of
|
||||
`shopdb-admin.ps1 check -Json`, which reports version, IIS and pool state,
|
||||
database reachability, Python version and installed plugins, and contains no
|
||||
secrets - it is the single most useful thing you can attach, and it is designed
|
||||
to be pasted.
|
||||
|
||||
---
|
||||
|
||||
The installer **checks all of this before it changes anything**, and it will not
|
||||
let you continue until the check passes. You do not have to get it right first
|
||||
time.
|
||||
|
||||
@@ -83,8 +83,45 @@ Installing an older build over a newer one is blocked outright. Once migrations
|
||||
have moved the schema forward, older code cannot read it, and the failures are
|
||||
difficult to unpick.
|
||||
|
||||
To go back you restore a backup taken before the update. Keep the previous
|
||||
`.exe` until you are satisfied with a release.
|
||||
Keep the previous `.exe` until you are satisfied with a release. You cannot
|
||||
download it again from the server, and it is what a rollback needs.
|
||||
|
||||
### Rolling back a release
|
||||
|
||||
Rolling back is restoring a matched pair: the code AND the database it expects.
|
||||
Doing one without the other is the state the installer refuses to create, and it
|
||||
is worth understanding why - newer code against an older schema fails at the
|
||||
first query that touches a new column, while older code against a newer schema
|
||||
often appears to work until something silently misreads a column that changed
|
||||
meaning.
|
||||
|
||||
The update takes its own backup before touching the schema, so the pair you need
|
||||
already exists.
|
||||
|
||||
```powershell
|
||||
cd C:\shopdb-flask
|
||||
.\shopdb-admin.ps1 stop
|
||||
|
||||
# 1. Database first, from the pre-upgrade dump the update took.
|
||||
mysql -u root -p shopdb_flask < C:\ProgramData\ShopDB-Flask\backups\shopdb_flask-pre-upgrade-<stamp>.sql
|
||||
|
||||
# 2. Then the code: run the PREVIOUS installer .exe. It is an install over a
|
||||
# restored older schema, which is the ordinary case, not a downgrade.
|
||||
.\ShopDBFlask_Installer_<previous-version>.exe
|
||||
|
||||
# 3. Prove the pair matches.
|
||||
.\shopdb-admin.ps1 check -Json
|
||||
```
|
||||
|
||||
If a migration failed mid-update, the installer has already restored its own
|
||||
backup and there is nothing to roll back - read the log it names and fix
|
||||
forward. Rollback is for a release that installed cleanly and then behaved
|
||||
badly, which is a different situation and the only one this procedure is for.
|
||||
|
||||
**Uploaded files are not in the dump.** If the release you are leaving behind
|
||||
accepted uploads, restore `instance\` from your own backup as well, or those
|
||||
files stay while the rows referring to them do not. See
|
||||
[BACKUP-RESTORE.md](BACKUP-RESTORE.md).
|
||||
|
||||
## Will an update affect other sites on the same IIS server?
|
||||
|
||||
|
||||
Reference in New Issue
Block a user