From bd053b073ca3ec931f3c27720c307436bd56e6dd Mon Sep 17 00:00:00 2001 From: b0txec Date: Thu, 20 Aug 2026 12:10:59 +0300 Subject: [PATCH] Document temporary VPS staging plan --- docs/ARCHITECTURE.md | 14 ++- docs/DEVELOPMENT_AND_STAGING.md | 23 +++- docs/README.md | 2 + docs/UPDATE_ROADMAP.md | 20 ++- docs/VPS_STAGING_PLAN.md | 214 ++++++++++++++++++++++++++++++++ 5 files changed, 265 insertions(+), 8 deletions(-) create mode 100644 docs/VPS_STAGING_PLAN.md diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index e647700..0f085a3 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -36,7 +36,7 @@ Staging currently exercises the PostgreSQL → API → frontend path with synthe ### SolidJS frontend - Queries the backend using the same origin in production builds. -- Provides Stations, City Analysis, Faktiskā, Latvia overview, Database, HARMONIE, and LVGMC forecast workspaces. A separate Ūdens temperatūra production workspace is planned. +- Provides Stations, City Analysis, Faktiskā, Ūdens temperatūra, Latvia overview, Database, HARMONIE, and LVGMC forecast workspaces. - Uses HTML canvas for broadcast maps and PNG export. - Uses normalized transparent PNG assets for weather symbols; the internal letter codes remain stable identifiers and are not rendered as text or emoji. @@ -92,3 +92,15 @@ Monda Regular and Bold are bundled locally and used by the interface and generat - Production monitoring, backups, incident handling, or a reviewed security boundary. See `UPDATE_ROADMAP.md` before considering workplace deployment. + +## Proposed temporary public-testing edge + +WeatherTool has not yet been deployed publicly. The proposed month-long user-acceptance environment adds a removable edge layer without changing the application into the authentication authority: + +```text +Cloudflare -> VPS Nginx -> Authelia authorization -> WeatherTool -> PostgreSQL +``` + +Rocky remains the trusted build and verification host. The VPS receives a commit-addressed immutable image and release metadata rather than pulling and building the development repository. WeatherTool, its database, and Authelia must use a dedicated Compose project, private network, storage paths, and loopback-only upstream port so the existing VPS services remain untouched. + +See `VPS_STAGING_PLAN.md` for the proposed topology and release procedure. diff --git a/docs/DEVELOPMENT_AND_STAGING.md b/docs/DEVELOPMENT_AND_STAGING.md index 31fe6c1..e645c9f 100644 --- a/docs/DEVELOPMENT_AND_STAGING.md +++ b/docs/DEVELOPMENT_AND_STAGING.md @@ -6,7 +6,7 @@ |---|---|---| | Windows | Source editing and Git workflow only | Not applicable | | Rocky Linux | Docker development and production-like staging | `http://192.168.1.101:9190` | -| Future VPS | Planned deployment environment | Not provisioned yet | +| Temporary VPS | Proposed month-long user-acceptance staging behind Cloudflare, Nginx, and Authelia | Not provisioned; hostname pending | | Workplace production | Out of scope until reviewed and approved | Not documented here | Rocky checkout: @@ -96,9 +96,10 @@ At minimum, verify: 3. The home navigation loads. 4. City Analysis can query synthetic observations. 5. Each map resolution renders and downloads. -6. Faktiskā automatically loads the latest fixed-station temperatures, allows overrides, assigns font symbols, supports exceptions, and downloads a 3840×1440 PNG. +6. Faktiskā automatically loads the latest fixed-station temperatures, allows overrides, assigns normalized image symbols, supports exceptions, and downloads a 3840×1440 PNG. 7. Faktiskā symbols remain automatically attached to their corresponding temperature badges when several different image assets are tested. -8. Browser developer tools show no new runtime errors. +8. Ūdens temperatūra accepts all six manual ranges and exports both 1920×1080 and 3840×1440 PNGs. +9. Browser developer tools show no new runtime errors. Known limitation: direct browser refreshes on newer client-side routes such as `/faktiska` can return 404 because the backend static-route list does not yet provide a general SPA fallback. Navigate from the home page until that backend behavior is fixed. @@ -108,8 +109,18 @@ Prefer a normal Git revert rather than manually copying old files: 1. Identify the faulty commit with `git log --oneline`. 2. On the development checkout, run `git revert `. -3. Push the revert and build and test it on Rocky. -4. Push the revert commit. -5. Pull it on Rocky and run the appropriate frontend-only or full-stack deployment command. +3. Build and test the revert on Rocky. +4. Push the verified revert commit. +5. Pull it into the Rocky staging checkout and run the appropriate frontend-only or full-stack deployment command. Database rollback is a separate operation and must not be inferred from a source rollback. Database backup and restore procedures are not yet defined. + +## Proposed VPS release boundary + +The temporary VPS must not become another development checkout. The proposed release flow is: + +```text +Windows source and Git -> Rocky build and verification -> immutable image + checksum -> VPS deployment +``` + +Releases are manual during user acceptance and are identified by the source commit SHA. The VPS keeps WeatherTool in its own `/srv/weathertool` tree, publishes the application only to a loopback port, and relies on Nginx plus Authelia at the public boundary. See `VPS_STAGING_PLAN.md` before provisioning or changing the VPS. diff --git a/docs/README.md b/docs/README.md index 194c971..2ee6e84 100644 --- a/docs/README.md +++ b/docs/README.md @@ -13,6 +13,7 @@ This directory contains the working documentation for the WeatherTool modernizat - Faktiskā symbol placement is automatic after manual image selection and is anchored to each rendered temperature badge. - The first **Ūdens temperatūra** workspace is implemented with manual Latvian-named fields and required 1920×1080 and 3840×1440 exports; visual calibration remains in progress. - Confirmed local Monda Regular/Bold files provide interface and generated-graphic typography; weather symbols use normalized transparent image assets. +- The next proposed environment is a temporary, isolated VPS user-acceptance deployment built on Rocky, protected by Cloudflare, Nginx, and removable Authelia authentication. It has not yet been provisioned. - This is not yet approved or hardened for workplace production. ## Documents @@ -22,6 +23,7 @@ This directory contains the working documentation for the WeatherTool modernizat - [Product workflows](PRODUCT_WORKFLOWS.md) — the intended purpose and current status of each visible workspace. - [Update roadmap](UPDATE_ROADMAP.md) — phased technical, security, dependency, testing, and UI work. - [Third-party notices](THIRD_PARTY_NOTICES.md) — licenses and attribution for adapted interface components. +- [Temporary VPS staging plan](VPS_STAGING_PLAN.md) — proposed isolation, authentication, release, backup, verification, and rollback model for external user testing. ## Documentation rules diff --git a/docs/UPDATE_ROADMAP.md b/docs/UPDATE_ROADMAP.md index a97c011..9846402 100644 --- a/docs/UPDATE_ROADMAP.md +++ b/docs/UPDATE_ROADMAP.md @@ -7,7 +7,8 @@ This document tracks proposed WeatherTool improvements. Work should be delivered - **Windows development:** source editing and Git workflow only; Docker runtime testing is performed on Rocky. - **Rocky staging:** production-like Docker deployment at `http://192.168.1.101:9190`. - **Git over SSH:** Windows pushes reviewed commits to a private bare repository on Rocky; the Rocky staging checkout pulls those commits and rebuilds. -- **Production:** remains separate until changes are reviewed, tested, and explicitly approved for workplace use. +- **Temporary VPS staging:** proposed month-long external user acceptance behind Cloudflare, Nginx, and Authelia; not yet provisioned. +- **Workplace production:** remains separate until changes are reviewed, tested, and explicitly approved for workplace use. Do not synchronize `.env`, database directories, generated dependencies, build output, or provider credentials between machines. @@ -140,6 +141,20 @@ Status: pending - [ ] Rehearse deployment and rollback using sanitized data. - [ ] Obtain technical and operational review before workplace rollout. +## Phase 8 — Temporary VPS user acceptance + +Status: planned + +- [x] Document the proposed isolated VPS topology and trusted Rocky-to-VPS release flow. +- [ ] Choose the WeatherTool and Authelia hostnames and create their Cloudflare DNS records. +- [ ] Record a read-only VPS inventory before provisioning and confirm ports, networks, storage, and capacity do not collide with existing services. +- [ ] Provision a dedicated `/srv/weathertool` tree, Compose project, private network, database storage, and loopback-only application port. +- [ ] Configure Authelia with one temporary shared account, Argon2id password storage, rate limiting, and temporary IP bans. +- [ ] Add host-specific TLS certificates and Nginx authorization routing without weakening the existing Cloudflare-only firewall boundary. +- [ ] Build and verify a commit-addressed immutable image on Rocky, then transfer its image archive and checksum to the VPS. +- [ ] Verify authentication, direct-origin blocking, application health, generated PNG downloads, backups, logs, and rollback. +- [ ] Run the month-long user test with manual releases and record feedback before any workplace-production decision. + ## Known current limitations - Staging uses synthetic PostgreSQL station data. @@ -165,3 +180,6 @@ Record completed work here by date and commit after the Git workflow is establis | 2026-08-19 | `5913217` | Add Valmiera to the deterministic Faktiskā development data | Yes | | 2026-08-19 | `632f377` | Arrange manual Faktiskā wind controls horizontally | Yes | | 2026-08-19 | `340c370`–`3aba9b4` | Anchor and visually calibrate manually selected Faktiskā symbols | Yes | +| 2026-08-19 | `1868041`–`6c9290b` | Add Ūdens temperatūra, bundle and load Monda, fix overlay scaling, and center its locked nameplate | Yes | +| 2026-08-19 | `0d641bd` | Replace runtime Daira glyph rendering with normalized transparent image assets | Yes | +| 2026-08-20 | `754415a` | Match editable title/source overlays to production-safe right margins | Yes | diff --git a/docs/VPS_STAGING_PLAN.md b/docs/VPS_STAGING_PLAN.md new file mode 100644 index 0000000..62d6477 --- /dev/null +++ b/docs/VPS_STAGING_PLAN.md @@ -0,0 +1,214 @@ +# Temporary VPS staging plan + +Status: **Proposed; WeatherTool has not been provisioned on the VPS** + +This document defines the next deployment stage for approximately one month of +newsroom-user testing. It records the intended boundary before any VPS changes +are made. The existing HOP/Adaco documentation was reviewed as an infrastructure +reference; WeatherTool must remain independent from that application and all +other VPS workloads. + +## Objectives + +- Keep Rocky Linux as the development, Docker-test, and trusted release-build + environment. +- Publish a committed WeatherTool revision for three invited testers through a + separate Cloudflare-proxied hostname. +- Protect the complete WeatherTool hostname with a self-hosted Authelia + username/password portal during public testing. +- Make releases traceable and reversible without giving the VPS access to the + Rocky Git repository or the home network. +- Keep removal of public authentication simple when the eventual workplace + deployment is local-only. + +This temporary environment is user-acceptance staging, not workplace +production. It continues to use synthetic data until authorized provider +credentials and the actual data contract are available. + +## Reused VPS infrastructure boundary + +The reviewed VPS documentation records an existing Ubuntu host with Nginx, +Docker Compose, Cloudflare-restricted public HTTP/HTTPS, restored Cloudflare +client addresses, Tailscale administration, log rotation, and unrelated live +workloads. These shared host facilities may be reused, but existing virtual +hosts, containers, networks, databases, firewall behavior, and service units +must not be replaced or restarted merely to deploy WeatherTool. + +Before provisioning, perform a read-only VPS inventory and confirm: + +- free memory, swap, disk space, and current container resource usage; +- current Nginx include and certificate layout; +- Cloudflare trusted-address and UFW configuration; +- an unused loopback application port; +- the SSH/Tailscale administration and recovery path; and +- sufficient backup capacity. + +## Environment and trust flow + +```text +Windows source workspace + -> commit and push over SSH +Rocky bare repository and working checkout + -> build, test, and visually accept the exact commit +Rocky trusted release build + -> export versioned image + SHA-256 checksum over authenticated SSH/Tailscale +Temporary VPS + -> verify and load image; never pull from the home Git host +Cloudflare -> Nginx -> Authelia authorization -> WeatherTool +``` + +The VPS receives a built release artifact, not a development checkout. It gets +no credential or route for the Rocky Git repository, the private Forgejo +instance, or the home LAN. + +## VPS isolation layout + +Proposed application root: + +```text +/srv/weathertool/ + compose.yml + .env.staging # untracked, root-owned, mode 0600 + config/ + authelia/ + configuration.yml # no secret values committed + users.yml # Argon2id hash; protected on the VPS + data/ + postgres/ + authelia/ + backups/ + releases/ +``` + +WeatherTool will use: + +- a unique Compose project name; +- a private application network; +- its own PostgreSQL service and persistent storage; +- its own Authelia configuration and storage; +- a loopback-only application binding, with the final port chosen after the + VPS inventory; and +- no shared Docker volumes, database, or application network with HOP or any + other service. + +Only Nginx may expose WeatherTool publicly. PostgreSQL and Authelia's internal +service port must not be published to the internet. Docker port bindings must +not be allowed to bypass the intended firewall boundary. + +## Authentication boundary + +Authelia is a removable reverse-proxy authentication layer; no WeatherTool +route or data model will be changed to implement the temporary shared account. + +Initial proposed policy: + +- one generated shared test username and a random 20-24 character password; +- password stored only as an Argon2id hash; +- secrets and plaintext credentials excluded from Git, images, documentation, + shell history where practical, and deployment logs; +- approximately 12-hour authenticated sessions; +- three failed attempts from one client address within two minutes results in + a temporary 15-minute IP ban; +- no permanent or username-wide three-attempt ban, because an attacker could + otherwise lock out all users of the shared account; +- generic login errors and retained, rotated authentication logs; and +- a working logout route. + +Nginx must ask Authelia to authorize every WeatherTool route. Client-address +regulation is meaningful only when Nginx trusts `CF-Connecting-IP` exclusively +from Cloudflare proxy networks and direct public origin traffic is rejected. + +For a future local-only workplace deployment, remove the Nginx authorization +include and Authelia service. The application remains unchanged. + +## Domain, TLS, and Nginx + +The WeatherTool hostname is not yet selected. Before DNS publication: + +1. Add an isolated Nginx virtual host without changing existing hosts. +2. Install a certificate valid for the exact WeatherTool/Authelia hostname or + hostnames; do not assume an existing non-wildcard certificate covers them. +3. Bind the upstream application to loopback only. +4. Verify the application and Authelia privately. +5. Create a proxied Cloudflare DNS record. +6. Apply strict origin TLS for the WeatherTool hostname. +7. Redirect HTTP to HTTPS and begin with a short staging HSTS lifetime such as + 3,600 seconds. +8. Avoid caching authenticated HTML and API responses at Cloudflare. +9. Confirm TLS, static assets, login, logout, API calls, PNG downloads, real + client addresses, and direct-origin rejection. + +Whether Authelia uses a dedicated `auth.` hostname or a subpath remains +an explicit deployment decision. A dedicated hostname is conventional; a +same-host subpath reduces DNS and certificate entries for this single app. + +## Manual release procedure + +Continuous deployment is deliberately out of scope for the first testing +month. Each release requires an operator checkpoint. + +1. Require a clean, committed source tree and record the full Git SHA. +2. Push and deploy that commit on Rocky. +3. Run the frontend build, available checks, and critical workflow smoke tests. +4. Build a production-only application image on Rocky and tag it with the full + Git SHA. +5. Export/compress the image and create a SHA-256 checksum. +6. Transfer the artifact and checksum to a temporary VPS release location over + authenticated SSH/Tailscale. +7. Verify the checksum before loading the image. +8. Back up WeatherTool PostgreSQL before database-affecting releases. +9. Select the new immutable image tag in the VPS environment configuration. +10. Recreate only the affected WeatherTool service. +11. Verify container health, loopback HTTP, Authelia, public HTTPS, APIs, and + representative graphic exports. +12. Record release time, Git SHA, image tag, checksum, backup, verification, + operator, and rollback tag without recording secrets. +13. Remove temporary transfer copies after acceptance and retain the previous + compatible image for rollback. + +Frontend-only source changes may still require a new immutable application +image on the VPS. The existing Rocky bind-mounted frontend workflow is a +development convenience, not the proposed VPS release model. + +## Acceptance checklist + +- Existing VPS workloads remain healthy and unchanged. +- WeatherTool services use only their dedicated project/network/storage. +- PostgreSQL is not publicly published. +- Direct origin web access is rejected; Cloudflare HTTPS succeeds. +- Unauthenticated requests reach the Authelia portal, not WeatherTool. +- Valid login, session persistence, logout, throttling, and temporary ban + recovery work. +- `/`, City Analysis, Faktiskā, and Ūdens temperatūra work with synthetic data. +- Required PNG dimensions and filenames remain correct after deployment. +- Browser developer tools and container/Nginx/Authelia logs show no unexpected + errors or secret values. +- The preceding image can be selected without rebuilding it. + +## Rollback and backup minimum + +For an application-only fault, select the previous image tag and recreate only +the WeatherTool application service. A source or image rollback does not undo a +database migration; database-affecting releases require a matching backup and +an explicit restore decision. + +Proposed temporary-staging minimum: + +- daily WeatherTool PostgreSQL backup; +- pre-deployment backup before database-affecting changes; +- seven daily backups retained initially; +- at least one encrypted off-VPS copy once tester-entered data matters; and +- a documented and tested restoration exercise. + +## Decisions and prerequisites still open + +- Final public hostname and Cloudflare zone. +- Dedicated Authelia hostname versus same-host subpath. +- Confirmed VPS capacity and unused loopback port. +- Deployment account and whether normal releases use public SSH or Tailscale. +- Final session and backup-retention values. +- Secure operator-side generation and delivery of the shared credential. +- A production Dockerfile/Compose definition validated independently from the + Rocky development Compose file. +- Health/readiness behavior suitable for automated release verification. +