diff --git a/RELEASE-TESTING.md b/RELEASE-TESTING.md index aaaa585d..2564fa63 100644 --- a/RELEASE-TESTING.md +++ b/RELEASE-TESTING.md @@ -140,17 +140,17 @@ rows, the rows are right: this line has drifted twice from being edited by hand. ## Downloads and figures -| Item | Status | -| ------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Every diagram format produces a file of the type it claims | **auto** — `downloads.spec.ts` checks magic bytes, not just that a file arrived | -| Illustrated pathways export the whole illustration | **auto** — `downloads.spec.ts` | -| GIF animates one frame per analysis sample | **auto** — `downloads.spec.ts`, skipped with a message when the render service is not running | -| PPTX opens in PowerPoint and converts to editable shapes | **human** — needs PowerPoint. This is the one item we cannot close | -| Sub-pathway highlighting checkbox changes the exported figure | **auto** — `downloads.spec.ts` | -| Animated SVG timeline: play/pause, click to seek, hover names the sample | **human** — the timeline scrubs a canvas, so seeking and hovering can only be judged by eye. Asserting pixels fails on font rendering rather than on behaviour, as with the sub-pathway hover row | -| A pathway page's figure is drawn by the site's own renderer | **auto** — `detail-contents.spec.ts`, for a cytoscape diagram and an illustration. _It came from the old server-side exporter until 21 Aug, so the picture on the page and the one the download gave you were in different styles_ | -| Figures on entity pages render, from the release bucket | **auto** — `e2e/release/download-files.spec.ts` checks the host and that the image really drew. _Every figure on the site was broken before 21 Aug: they were served from the legacy Joomla root, and our origin answers those paths with index.html — a 200 that is not an image_ | -| PNG quality tiers produce three different sizes | **auto** — `downloads.spec.ts` reads the width out of each PNG's header and checks all three differ | +| Item | Status | +| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Every diagram format produces a file of the type it claims | **auto** — `downloads.spec.ts` checks magic bytes, not just that a file arrived | +| Illustrated pathways export the whole illustration | **auto** — `downloads.spec.ts` | +| GIF animates one frame per analysis sample | **auto** — `downloads.spec.ts`, skipped with a message when the render service is not running | +| PPTX opens in PowerPoint and converts to editable shapes | **human** — needs PowerPoint. This is the one item we cannot close | +| Sub-pathway highlighting checkbox changes the exported figure | **auto** — `downloads.spec.ts` | +| Animated SVG timeline: play/pause, click to seek, hover names the sample | **human** — the timeline scrubs a canvas, so seeking and hovering can only be judged by eye. Asserting pixels fails on font rendering rather than on behaviour, as with the sub-pathway hover row | +| A pathway page's figure is drawn by the site's own renderer | **auto** — `detail-contents.spec.ts`, for a cytoscape diagram and an illustration. _It came from the old server-side exporter until 21 Aug, so the picture on the page and the one the download gave you were in different styles_ | +| Figures on entity pages render, from the release bucket | **auto** — `e2e/release/download-files.spec.ts` checks the host and that the image really drew. _Every figure on the site was broken before 21 Aug: they were served from a legacy path, and our origin answers those paths with index.html — a 200 that is not an image_ | +| PNG quality tiers produce three different sizes | **auto** — `downloads.spec.ts` reads the width out of each PNG's header and checks all three differ | ## Post-release diff --git a/deploy/nginx/README.md b/deploy/nginx/README.md index b2c36459..78af30fb 100644 --- a/deploy/nginx/README.md +++ b/deploy/nginx/README.md @@ -118,29 +118,36 @@ verified, it starts with nothing mounted at `/etc/letsencrypt`. Running the site on your own machine should not require obtaining a certificate for a hostname you do not own. -Deployed environments present certificates the server already holds. This box -needs exactly two: - -| | | -| ------------------- | ----------------------------------------------------------- | -| `beta.reactome.org` | the site | -| `dev.reactome.org` | the retired host, so its 503 is not a TLS error | -| `reactome.org` | the same, for the two aliases the retired vhost answers for | - -The wikis lived here as leftovers and were deleted on 2026-09-16, along with the -long-expired `login.dev`. - -The third is easy to talk yourself out of. Production serves `reactome.org`, so -it is tempting to drop the certificate — but this box still _answers_ for that -name and for `www`, because the retired vhost lists them as aliases. Drop the -certificate and those names get beta's instead: a name mismatch, so a browser -security warning where there is currently a clean 503. A worse retirement than -the one being replaced. - -So all three certificates must renew without Apache before the cutover, not two. -`reactome.org` was still on the apache authenticator after the first migration -pass — worth checking rather than assuming, since the script only moves what it -is told to. +On the dev box, what is _presented_ and what _exists_ are different things, and +the difference cost a detour worth recording: + +| Name | Presents | Renewed by | +| --------------------- | --------------------------------- | ----------------------------------- | +| `beta.reactome.org` | its Let's Encrypt certificate | certbot, dns-cloudflare | +| `dev.reactome.org` | **Cloudflare Origin certificate** | Cloudflare; long-lived, not certbot | +| `reactome.org`, `www` | **Cloudflare Origin certificate** | as above | + +Established by asking the running server what it serves for each name, not by +listing what is on disk. `001-reactome.conf` sets +`SSLCertificateFile /etc/ssl/cloudflare/reactome-origin.crt` with the Let's +Encrypt line commented out beneath it, so **only beta's Let's Encrypt certificate +is actually in use**. + +`reactome.org`'s Let's Encrypt certificate was deleted on 2026-09-16: nothing +presented it, and it shared `dev.reactome.org` as a name with the certificate +below, which made combined renewals fight over the same +`_acme-challenge.dev.reactome.org` record and fail unpredictably. + +**`dev.reactome.org`'s Let's Encrypt certificate is kept deliberately**, even +though nothing presents it today. The Angular site is expected to move from +`beta.reactome.org` to `dev.reactome.org` when it is ready, and the certificate +is there for that. It renews via `dns-cloudflare`; that renewal was silently +broken until the token was replaced on 2026-09-16. + +When that move happens, the `dev.reactome.org` server block below stops being a +503 and becomes the site — at which point it needs a certificate a browser will +accept if anything reaches it other than through Cloudflare, which is what the +Let's Encrypt one is for. ## Before any of this serves traffic diff --git a/deploy/nginx/dev.conf b/deploy/nginx/dev.conf index d3596349..79e5b772 100644 --- a/deploy/nginx/dev.conf +++ b/deploy/nginx/dev.conf @@ -67,56 +67,41 @@ include /etc/nginx/common/block-all-automation.conf; limit_req_zone $binary_remote_addr zone=dev_rate:10m rate=100r/s; limit_conn_zone $binary_remote_addr zone=dev_conn:10m; -# dev.reactome.org stays retired, and so does anything else pointed here. +# The retired hostnames stay retired, and so does anything else pointed here. # -# This box needs exactly two certificates -- dev.reactome.org and -# beta.reactome.org -- and eventually only one, when the Angular site is the one -# going forward. The wikis are on the release machine and login.dev is gone. +# This box needs exactly one Let's Encrypt certificate -- beta.reactome.org -- +# and keeps dev.reactome.org's for a planned move. The wikis are on the release +# machine. # -# That vhost is a Joomla 3.10.12 stack, end of life since 2023, which was the -# entry vector on production and release in September 2026. Under Apache the only -# thing making this host safe is that it returns 503 for everything. If nginx -# answered only for beta, a request for dev.reactome.org — or reactome.org, which -# is an alias of that same vhost — would fall to the default server. +# Every name other than beta answers 503. That matters more than it looks: if +# nginx served only beta, a request for one of the retired names would fall to +# the default server and could be answered with beta's content under a name +# meant to be gone. The explicit block below makes that impossible. # -# It is also the best argument for this migration: that vhost still carries -# `Options +Includes` and `XBitHack on` with mod_include loaded. nginx has no -# mod_include, so the Server-Side Includes hole cannot exist here at all. -# dev.reactome.org, retired, with its own certificate. -# -# It has one, and it already renews via dns-cloudflare -- the only certificate on -# this box that does. Presenting beta's certificate for this name would be a TLS -# mismatch, which is a worse answer than the clean 503 the retired host is meant -# to give. -server { - listen 80; - listen 443 ssl; - server_name dev.reactome.org; - ssl_certificate /etc/letsencrypt/live/dev.reactome.org/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/dev.reactome.org/privkey.pem; - include /etc/nginx/common/tls.conf; - return 503; -} +# It is also a reason to prefer nginx here. The retired site runs on an Apache +# loading modules this configuration does not load at all, so a class of problem +# that currently has to be held shut stops being reachable. The specifics belong +# in internal notes, not in a public repository. -# reactome.org and www.reactome.org, if anything points them here. +# The retired names: dev.reactome.org, and the two aliases the old vhost answers +# for. # -# Production serves these names. This box answers for them only because the -# retired Apache vhost lists them as aliases, and it presents the reactome.org -# certificate when it does. Without this block they would fall to the catch-all -# below and be shown *beta's* certificate -- a name mismatch, so a browser -# security warning where Apache gives a clean 503. That is a worse retirement -# than the one being replaced. +# They present the **Cloudflare Origin certificate**, because that is what Apache +# presents -- `SSLCertificateFile /etc/ssl/cloudflare/reactome-origin.crt` in +# `001-reactome.conf`, with the Let's Encrypt line commented out beneath it. +# Verified by asking the running server what it serves for each name, which is +# how this was found: an earlier draft presented Let's Encrypt certificates here +# because the certificates existed, not because anything used them. # -# The certificate must therefore keep existing and keep renewing. It renewed via -# the apache authenticator until 2026-09-16; moving it to dns-cloudflare is part -# of the cutover, not optional, because after the cutover there is no Apache for -# it to authenticate through. +# All traffic arrives through Cloudflare, so an Origin certificate is the right +# thing on this leg. It is issued by Cloudflare, long-lived, and not renewed by +# certbot at all -- which is why none of the certbot work touches it. server { listen 80; listen 443 ssl; - server_name reactome.org www.reactome.org; - ssl_certificate /etc/letsencrypt/live/reactome.org/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/reactome.org/privkey.pem; + server_name dev.reactome.org reactome.org www.reactome.org; + ssl_certificate /etc/ssl/cloudflare/reactome-origin.crt; + ssl_certificate_key /etc/ssl/cloudflare/reactome-origin.key; include /etc/nginx/common/tls.conf; return 503; }