Goals
- Move `updates.deeztek.com` to the same physical host as `validate.hermesseg.io` and `activate.hermesseg.io` (consolidation, simplifies cert and ops management).
- Add a JSON response endpoint for Docker clients alongside the existing `@`-delimited endpoint that legacy installs depend on.
Server code lives in this repo's working tree under `updates-server/updates.deeztek.com/` (gitignored, mirrors the existing `license-server/` pattern).
Relocation (operations)
DNS-only move: keep the public hostname `updates.deeztek.com` so every existing legacy install in the field keeps working untouched. Repoint A record to the validate host. Add `updates.deeztek.com` as a SAN on the validate host's existing cert.
Steps:
- Drop DNS TTL ahead of cutover.
- Stand up nginx vhost for `updates.deeztek.com` on the validate host.
- Migrate content: `update_comm.cfm`, release-notes HTML pages, update tarballs, `.hash` files, the `updates` MariaDB table.
- Add SAN to certbot, deploy.
- Repoint DNS, monitor.
- Decommission old server after grace period.
Updates table — already encodes everything
The existing `updates` table (currently 18 rows for legacy 16.04/18.04/20.04) drives both legacy and Docker upgrades from a single schema:
- `install_order` is the sequential upgrade chain — server returns next row in order. Dropping a release = delete the row. Hotfix between releases = decimal install_order.
- `build` column distinguishes Docker (`v260119`) from legacy (`260119`) via the `v` prefix — no separate column needed.
- `version` is cosmetic display (e.g., `docker-amd-64`); doesn't drive logic.
Server query for the next update for a given client:
```sql
-- Docker client at build='v260119'
SELECT * FROM updates
WHERE build LIKE 'v%'
AND install_order > (SELECT install_order FROM updates WHERE build = 'v260119')
AND dev = <client_dev>
ORDER BY install_order ASC LIMIT 1;
-- Legacy client at build='240815'
SELECT * FROM updates
WHERE build NOT LIKE 'v%'
AND install_order > (SELECT install_order FROM updates WHERE build = '240815')
AND dev = <client_dev>
ORDER BY install_order ASC LIMIT 1;
```
The `v%` / `NOT LIKE 'v%'` filter keeps the two trains separate within one global install_order sequence. Docker rows pick up at install_order=20+ continuing from where legacy left off.
Endpoint split
Two endpoints, not one endpoint that branches its response format. Zero blast radius to legacy.
| Endpoint |
Audience |
Response |
Status |
| `update_comm.cfm` |
Legacy installs |
`@`-delimited (current format) |
Frozen — never modified again |
| `update_comm_v2.cfm` (or `update_check.cfm`) |
Docker installs |
JSON |
New, can evolve freely |
Pull the SQL query into a shared include `inc/query_next_update.cfm`. Each endpoint calls the include, then formats for its consumer:
```
update_comm.cfm → cfinclude query_next_update.cfm → output @-delimited (legacy)
update_comm_v2.cfm → cfinclude query_next_update.cfm → output JSON (Docker)
```
Docker JSON response shape
```json
{
"status": "SUCCESS",
"next_version": "v260120",
"released": "2026-01-15",
"release_notes_url": "https://updates.deeztek.com/releasenotes/hermes-v260120-release.html\",
"platform": "docker"
}
```
```json
{ "status": "NOUPDATE" }
```
```json
{ "status": "INVALIDREQUEST", "message": "Build v260999 not found" }
```
- `status` — same enum role as legacy
- `next_version` — the git tag + Docker image tag (single value, since they line up)
- `platform` — echoes back the `version` column, lets clients sanity-check arch/platform mismatch
- No tarball filename or `mysql_root_prompt` — Docker doesn't need them
Multi-arch images (single train)
Docker builds use `buildx` to publish multi-arch image manifests under a single tag (`v260119` contains both amd64 and arm64). `docker pull` auto-grabs the right arch. One row per release, `version='docker'`, both archs share. No client-side arch detection needed in v1.
If separate amd64/arm64 trains are ever needed later, the `version` column is already there for that filter.
Blocks
- system_update.sh Docker rewrite (needs the JSON endpoint to exist before testing)
Goals
Server code lives in this repo's working tree under `updates-server/updates.deeztek.com/` (gitignored, mirrors the existing `license-server/` pattern).
Relocation (operations)
DNS-only move: keep the public hostname `updates.deeztek.com` so every existing legacy install in the field keeps working untouched. Repoint A record to the validate host. Add `updates.deeztek.com` as a SAN on the validate host's existing cert.
Steps:
Updates table — already encodes everything
The existing `updates` table (currently 18 rows for legacy 16.04/18.04/20.04) drives both legacy and Docker upgrades from a single schema:
Server query for the next update for a given client:
```sql
-- Docker client at build='v260119'
SELECT * FROM updates
WHERE build LIKE 'v%'
AND install_order > (SELECT install_order FROM updates WHERE build = 'v260119')
AND dev = <client_dev>
ORDER BY install_order ASC LIMIT 1;
-- Legacy client at build='240815'
SELECT * FROM updates
WHERE build NOT LIKE 'v%'
AND install_order > (SELECT install_order FROM updates WHERE build = '240815')
AND dev = <client_dev>
ORDER BY install_order ASC LIMIT 1;
```
The `v%` / `NOT LIKE 'v%'` filter keeps the two trains separate within one global install_order sequence. Docker rows pick up at install_order=20+ continuing from where legacy left off.
Endpoint split
Two endpoints, not one endpoint that branches its response format. Zero blast radius to legacy.
Pull the SQL query into a shared include `inc/query_next_update.cfm`. Each endpoint calls the include, then formats for its consumer:
```
update_comm.cfm → cfinclude query_next_update.cfm → output @-delimited (legacy)
update_comm_v2.cfm → cfinclude query_next_update.cfm → output JSON (Docker)
```
Docker JSON response shape
```json
{
"status": "SUCCESS",
"next_version": "v260120",
"released": "2026-01-15",
"release_notes_url": "https://updates.deeztek.com/releasenotes/hermes-v260120-release.html\",
"platform": "docker"
}
```
```json
{ "status": "NOUPDATE" }
```
```json
{ "status": "INVALIDREQUEST", "message": "Build v260999 not found" }
```
Multi-arch images (single train)
Docker builds use `buildx` to publish multi-arch image manifests under a single tag (`v260119` contains both amd64 and arm64). `docker pull` auto-grabs the right arch. One row per release, `version='docker'`, both archs share. No client-side arch detection needed in v1.
If separate amd64/arm64 trains are ever needed later, the `version` column is already there for that filter.
Blocks