feat: signed releases, release feed, notification (read-only)
This commit is contained in:
1 parent
a49eec909c
commit
834493a4f5
49 files changed
+4191
-18
No files matched your search
@@ -30,6 +30,7 @@ Copy [`.env.example`](../.env.example) to `.env` to get started. When a required
|
||||
| `AUTH_RATE_LIMIT_MAX_ATTEMPTS` | `5` | Maximum number of requests a single client IP may send to `POST /v1/auth/login`, `POST /v1/auth/password-reset` or the invite-accept pair (`GET /v1/auth/invite` and `POST /v1/auth/invite/accept`, sharing one counter) within the window, tracked independently per route. |
|
||||
| `AUTH_RATE_LIMIT_WINDOW_SECONDS` | `60` | Length, in seconds, of the fixed rate-limit window for the routes above. |
|
||||
| `TRUSTED_PROXIES` | *(empty)* | Semicolon-separated list of exact IP addresses (no CIDR) of reverse proxies allowed to supply the client IP via `X-Real-IP` for the rate limiting of the routes above. When a request's connection address is not in this list, any `X-Real-IP` or `X-Forwarded-For` header it sends is ignored and the connection address is used instead. See [deployment.md](deployment.md). |
|
||||
| `UPDATE_FEED_URL` | `https://git.floriansylvain.fr` | Base URL of the Gitea server that publishes RenewCMS releases. The Settings page asks `{UPDATE_FEED_URL}/api/v1/repos/fsylvain/RenewCMS/releases` when the owner checks for updates. The last result is kept in `update-status.json`, next to `DB_FILE`. |
|
||||
|
||||
Relative paths are resolved against the process's working directory. In production, use absolute paths (see [deployment.md](deployment.md)).
|
||||
|
||||
|
||||
@@ -19,8 +19,22 @@ task build # this OS/arch → bin/renewcms[.exe]
|
||||
task release # all targets → bin/renewcms_<version>_<os>_<arch>[.exe]
|
||||
```
|
||||
|
||||
`task release` also signs the release: it writes `bin/checksums.txt` (SHA-256 of the six binaries) and signs it into `bin/checksums.txt.sig` with an Ed25519 key. It refuses to start, before building anything, unless `RELEASE_SIGNING_KEY` points to the private key file and that key matches the public key committed as `internal/infrastructure/update/release.pub`. The one-time setup is below.
|
||||
|
||||
The frontend is built once and embedded into every binary. The binaries are static (`CGO_ENABLED=0`), so a Linux build runs on any distribution. The version comes from `git describe`: tag a release (`git tag v1.2.0`) before building, and the binary logs its version at startup.
|
||||
|
||||
### Release signing key (maintainers, once)
|
||||
|
||||
1. Run `task release:keygen -- <path>` with a path outside the repository (for example `~/.renewcms/release.key`). The private key is written there and never leaves your machine; keygen refuses a path inside the work tree.
|
||||
2. Commit the printed public key as `internal/infrastructure/update/release.pub`. Until you do, the file holds a placeholder (32 zero bytes) and `task release` fails with a message saying so.
|
||||
3. Export `RELEASE_SIGNING_KEY=<path to the private key>` before every `task release`.
|
||||
|
||||
To check a download by hand: `go run ./cmd/releasesign verify checksums.txt`, with `checksums.txt.sig` next to it, then compare the binary's hash with the matching line of `checksums.txt`.
|
||||
|
||||
### Update checks
|
||||
|
||||
The owner's Settings page asks the release feed for the newest release (see `UPDATE_FEED_URL` in [configuration.md](configuration.md)) and keeps the last result in `update-status.json`, next to `DB_FILE`. Back it up with the rest of the data directory if you like; it is rebuilt by the next check when missing. The Settings page only reports a newer version for now: the site does not update itself.
|
||||
|
||||
## 2. Lay out the server
|
||||
|
||||
The following is a suggested layout for Linux:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
- **Route:** `/settings`
|
||||
- **API:** GET /v1/settings (version) · GET /v1/system/update · POST /v1/system/update/check · POST /v1/system/update/download · POST /v1/system/update/restart
|
||||
- **Visual reference:** `source/RenewCMS Screens Back-office.dc.html`, group "Settings: Updates", drawn by `source/AppFrame.dc.html` (open it in a browser; each state is drawn at desktop and mobile, with a light/dark toggle).
|
||||
- **Visual reference:** `source/RenewCMS Screens Back-office.dc.html`, group "Settings", drawn by `source/AppFrame.dc.html` (open it in a browser; each state is drawn at desktop and mobile, with a light/dark toggle).
|
||||
|
||||
Opened from the sidebar (Settings, settings icon, after Integration) and from the mobile drawer. Every verified user sees it. It holds two sections: Version (everyone) and Updates (the owner has the buttons, admins read the status).
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ Rules: bullets are full sentences ending with a period; user-facing wording, no
|
||||
|
||||
## Published releases
|
||||
|
||||
Each body lives in `docs/releases/<tag>.md`. Publish with `tea releases create --tag <tag> --title "<name>" --note-file docs/releases/<tag>.md --prerelease --asset <binary>` (one `--asset` per binary), after `task release`.
|
||||
Each body lives in `docs/releases/<tag>.md`. Publish with `tea releases create --tag <tag> --title "<name>" --note-file docs/releases/<tag>.md --prerelease --asset <file>` after `task release`, with one `--asset` per file: the six binaries, `bin/checksums.txt` and `bin/checksums.txt.sig`. `task release` produces all eight and fails before building when the signing key is missing or wrong (see [deployment.md](deployment.md#release-signing-key-maintainers-once)). Never publish a release without the two checksum files.
|
||||
|
||||
| Tag | Name |
|
||||
| --- | --- |
|
||||
|
||||
Reference in new issue
Block a user