DNS Inventory & Cutover Runbook
Built from a Route53 hosted-zone export for bioconductor.org (166 records, reviewed 2026-09) plus a direct HTTPS probe of every resolvable hostname in it — not just the DNS target, but what each one actually serves today. Satisfies the M1 tasks “decide www./secure. and satellite hostnames” and “cutover runbook page (DNS, verification, rollback)” from the roadmap. Not yet walked with the core team — treat every status and finding below as the reviewer’s read, not a decision. Probes were run from the open internet with no VPN/internal access, so “no response” below means not reachable from outside, not necessarily dead.
Updated 2026-09-17: the apex mechanism is settled — the zone’s nameservers move to Cloudflare — and the migration plan below was added. The plan is a proposal; no step in it has been executed.
What M1 actually changes
Two records carry the entire cutover:
| Hostname | Type | Current target | Note |
|---|---|---|---|
bioconductor.org (apex) |
A, Route53 Alias | d3hzwifbu1gvt4.cloudfront.net. |
The CloudFront distribution being retired |
www.bioconductor.org |
A, Route53 Alias | bioconductor.org. |
Aliases to the apex, not to CloudFront directly |
Both are live and serve the production site (“Bioconductor - Home”) today. Everything else in the zone is satellite: conference sites, mailing-list infrastructure, build machines, DKIM keys. None of it needs to change for the site itself to move — it either already points off AWS, or points at AWS/Jetstream2 resources this cutover doesn’t touch.
The apex is the hard part
Route53 “Alias” records — the mechanism used for the apex today — only resolve to AWS resources (CloudFront, ELB, S3, another record in the same zone, etc.). They cannot target an arbitrary external host like bioc-dev.cancerdatasci.org, and a plain CNAME isn’t legal at a zone apex per the DNS spec. www.bioconductor.org doesn’t have this problem — it’s not the apex, so it can become a normal CNAME to the new edge once the zone is ready. Decision (2026-09-17): move the zone’s nameservers to Cloudflare. Cloudflare flattens a CNAME at the apex, so the apex can target the Worker directly, and AWS leaves the DNS path entirely. The domain registration stays at AWS; only the nameservers change.
Rejected: a thin CloudFront distribution as a pass-through, origin set to bioc-dev.cancerdatasci.org, with the Route53 Alias repointed at it. It moves no records, but keeps AWS in the request path indefinitely and adds a cache-miss origin-fetch charge (~$0.02/GB) on top of viewer egress.
Migration plan
Two separately reversible steps. Step one moves the zone to Cloudflare as an exact copy, apex still resolving to today’s CloudFront distribution — users see nothing, and anything that breaks is a mis-copied record. Step two, later, repoints the apex and www at the new edge — one record each, rolled back by editing them back.
0. A dedicated Cloudflare account, first
The Worker, R2 buckets and dev hostname currently live in a personal account shared with unrelated domains. Recommended: create a Bioconductor-owned account before the zone is added anywhere, because a Worker custom domain must be in the same account as the Worker, and moving a live zone later means a second nameserver change on the production domain plus a data copy under load.
Why separate: Workers and R2 permissions are account-wide (a Bioconductor co-admin would otherwise hold rights over unrelated infrastructure, and vice versa); billing, grants and sponsorships attach to an account; and a project account with 2–3 super administrators survives any one person leaving.
It is a redeploy, not a rebuild — everything is declared in wrangler.jsonc:
| Piece | Effort | Notes |
|---|---|---|
Workers, cron triggers, Workflows (bioc-site, bioc-registry, bioc-prop) |
minutes | Redeploy with the new account ID; code unchanged |
| Secrets, API tokens | ~1 hour | Do not transfer; re-set, and reissue CI tokens |
R2 buckets bioc-site, bioc-prop |
~1 day, mostly waiting | No cross-account bucket move exists; copy with Super Slurper or rclone. R2 egress is free, so the cost is write operations — driven by object count, which hasn’t been pulled |
| Producers writing to R2 | 1–2 hours | The S3 endpoint embeds the account ID; every sync job needs a new endpoint and keys |
Analytics Engine dataset bioc_site_requests_v3 |
not movable | History restarts; retention is ~3 months and dev traffic has little value |
| Logpush job | minutes | Recreate |
| In-flight Workflow instances | lost | Let them finish, or accept a rerun |
Order: create the account and add a second super administrator → create buckets and start the copy → deploy Workers to a preview hostname and run the full-crawl diff → repoint producers, then a final sync for anything written since the copy began → add the bioconductor.org zone there.
If the account move is declined, the minimum hedge is a second super administrator on the current account and keeping everything in config, as now.
1. Prepare the zone copy (no user-visible change)
- Export from Route53 itself, not from the review spreadsheet — the spreadsheet is already stale (the live apex carries a TXT value
acevhogcbpv6dssaq15fbe1ek8it doesn’t list). - Hand-create the Alias records. They don’t survive a zone-file export: the apex (as a flattened CNAME to
d3hzwifbu1gvt4.cloudfront.net),www, andtestweb. - Import everything DNS-only — nothing proxied.
gitserves SSH andrabbitmqis a message broker, so proxying breaks both; the GitHub Pages and Netlify CNAMEs need unproxied records to renew certificates; several builder records hold private addresses that can’t be proxied at all. - Keep the three ACM validation CNAMEs. Without them CloudFront’s certificate stops renewing, and CloudFront is the rollback target.
- Copy mail records byte for byte — MX, SPF,
_dmarc(p=reject), every DKIM selector, the_amazonsesverification TXTs. A mistake here drops mail silently. - Lower the NS record TTL in Route53 (currently 172800 s) at least two days ahead.
- Diff every record between Route53 and Cloudflare’s assigned nameservers (
dig @<cf-ns>vsdig @<aws-ns>, every name and type). Cut over on an empty diff.
Do the agreed deletions before or after the move, never during. Deleting first makes the diff smaller; records tagged “delete end of 2026” get copied across for now.
2. Change the nameservers
- Change the nameservers at the AWS registrar. Do not transfer the registration — a transfer adds a lock period and buys no safety.
- DNSSEC is off today (no DS record published), so there is no signing hazard. Enable it on Cloudflare after things settle, not during.
- Leave the Route53 zone untouched for at least two weeks.
- Freeze record changes in that window, or make each change in both places.
Rollback: revert the nameservers at the registrar. Works only while the Route53 zone is still correct — hence the freeze.
3. Flip the site (M1 proper)
- Attach the Worker to a spare hostname in the new zone first and run
cutover-diff.shagainst it — this catches anywhere the Worker assumes the dev hostname. - HTTP behaviour differs today: production answers
http://with a 301 to HTTPS; the new edge answers 200 over plain HTTP. Pick one deliberately — older R clients still request plain HTTP. - Point the apex and
wwwat the Worker. Keep CloudFront andmasterrunning until M2 retires them.
Rollback: edit the two records back to CloudFront. Minutes.
Found along the way — fix separately, not during the move
- The spreadsheet lists a TXT record on a literal
@.bioconductor.orglabel carryingv=spf1 include:spf.forwardemail.net -all. It doesn’t resolve publicly — a data-entry mistake for the apex. The SPF actually in force at the apex isv=spf1 a mx include:_spf.mlsend.com ?all: neutral, and omitting forwardemail. - The apex TXT value
acevhogcbpv6dssaq15fbe1ek8has no recorded owner.
Full inventory, with detail links
Every non-apex hostname the review reached a status on, linked to what was actually found at each one. The 27 conference/event CNAMEs, the 25 confirmed-dead delete candidates, and the mail/cert/wildcard plumbing are tabulated further down without individual detail sections — their purpose is self-evident from the hostname and target, and a paragraph each would add noise, not information. Say the word if you want those expanded too.
Core infrastructure, staying put (27)
Marked “keep” in the source review, not touched by the M1 apex/www flip. Visited each directly (curl -sI https://<host>/) rather than assuming from the hostname.
master.bioconductor.org
A → 52.71.54.154. Live — full production bioconductor.org mirror. This is the legacy master webserver being retired by the M1/M2 migration.
staging.bioconductor.org
A → 52.4.245.79. No public HTTPS response. Confirmed elsewhere in this repo (see the decommission plan) that no web server listens here — this is the legacy build host, not a public site.
git.bioconductor.org
A → 34.192.48.227. Confirmed live: gitolite3 v3.6.6 serving the package git repos directly (admin/…, packages/ABAData, …) — this is the canonical package source, not a redirect target.
chat.bioconductor.org
A → 34.192.48.227. Same redirect target as zulip.bioconductor.org — an alias into the same Zulip Cloud instance.
zulip.bioconductor.org
A → 34.192.48.227. Redirects to the team’s hosted Zulip Cloud instance (community-bioc.zulipchat.com) — the real chat entry point.
www.zulip.bioconductor.org
A → 34.192.48.227. No public response. Shares its target IP with zulip/chat/git/packages — routing for www.-prefixed vhosts on that box looks inconsistent.
www.chat.bioconductor.org
A → 34.192.48.227. No public response, same shared-IP pattern as www.zulip.
packages.bioconductor.org
A → 34.192.48.227. Redirects to the Open Storage Network archive bucket — a convenience alias so people don’t need the full OSN URL to browse package archives.
support.bioconductor.org
A → 54.164.10.157. Live — the Bioconductor Support Forum (Django app, Biostars-derived).
issues.bioconductor.org
A → 52.4.116.154. Responds but the body is literally “Nothing to see here” — currently a stub. Worth checking whether the real issue tracker moved elsewhere, or this is mid-decommission.
code.bioconductor.org
A → 194.94.45.72. No public HTTPS response — purpose unconfirmed from outside; worth a direct look.
rabbitmq.bioconductor.org
A → 52.20.79.236. No public HTTPS response — a message broker (STOMP/AMQP), expected to not answer on plain HTTPS; the SPB build-results pipeline depends on it (see the decommission plan).
pkgmaintainers.bioconductor.org
A → 44.218.162.37. Live — “API Summary,” a maintainer-facing API service.
annotationhub.bioconductor.org
A → 52.73.93.102. Live — “BiocHub Server API,” the AnnotationHub backend.
experimenthub.bioconductor.org
A → 52.73.93.102. Live — same BiocHub Server API, serving ExperimentHub instead of AnnotationHub.
nebbiolo1.bioconductor.org
A → 155.52.47.135. No public HTTPS response — a dedicated Linux package-build machine (release), not a webserver.
nebbiolo2.bioconductor.org
A → 155.52.47.146. No public HTTPS response — same role as nebbiolo1, devel branch.
kjohnson3.bioconductor.org
A → 172.24.216.75. No public HTTPS response — a macOS package-build machine.
workshop.bioconductor.org
A → 149.165.171.210. No public HTTPS response — workshop compute cluster, likely gated (auth or VPN) rather than dead.
workshopauth.bioconductor.org
A → 149.165.154.124. No public HTTPS response — the auth front-end for the workshop cluster above.
webr.bioconductor.org
A → 149.165.154.124. No public HTTPS response despite “keep” status — serves a WebR package repository; each version needs its own path (e.g. /3.23) rather than a splash page at the root, which may explain the empty response at /.
run.webr.bioconductor.org
A → 149.165.154.124. No public HTTPS response — reserved for a planned in-browser WebR demo page (fully client-side, eventually movable to GitHub Pages).
discourse.dev.bioconductor.org
A → 149.165.153.32. No public HTTPS response despite “keep” status — a dev/staging Discourse instance; may only answer on a non-standard port or be gated.
isee.bioconductor.org
A → 149.165.171.200. Live Shiny app — linked to the Bioconductor/isee.bioconductor.org GitHub repo. The wildcard *.isee.bioconductor.org is kept for the same app; check with the app’s maintainer before touching either.
hubsingest.bioconductor.org
A → 149.165.171.200. No public HTTPS response — an ingestion endpoint, not a browsable site. Kept for an active hub-ingestion workflow; confirm it’s still in use before any change.
certs.bioconductor.org
A → 149.165.171.200. Live — the BiocCertificate Shiny app for issuing training certificates.
workinggroups.bioconductor.org
CNAME → bioconductor.github.io. Live — GitHub Pages site for Bioconductor Working Groups.
training.bioconductor.org
CNAME → bioconductor.github.io. Live, but the page title is just “index” — likely a generic template; content itself may still be fine, the title tag just isn’t descriptive.
contributions.bioconductor.org
CNAME → bioconductor.github.io. Live — “Bioconductor Packages: Development, Maintenance, and Peer Review,” the package contribution/review site.
blog.bioconductor.org
CNAME → bioconductor.github.io. Live — the community blog, GitHub Pages.
Undecided — needs an owner (18 with live content or a clear guess; 24 more listed in the appendix table are wildcards or mail/cert plumbing)
testweb.bioconductor.org
A → d3h1507zzd6849.cloudfront.net.. No public HTTPS response. Points at a second, separate CloudFront distribution (d3h1507zzd6849.cloudfront.net, different from production) — worth checking what that distribution is before the main cutover, in case it needs retiring alongside it.
testinggit.bioconductor.org
A → 44.207.152.77. No public HTTPS response — looks like a test git host, name suggests safe to retire once confirmed unused.
support.test.bioconductor.org
A → 44.210.209.116. No public HTTPS response — test instance of the support forum.
slack.bioconductor.org
A → 34.192.48.227. Serves a generic “Countdown with Embedded Blog” template — not Slack-branded content. Whatever this vhost used to do, it no longer matches its hostname; worth a direct look before deciding keep/delete.
posters.bioconductor.org
CNAME → bioconductor.github.io. No public HTTPS response despite pointing at GitHub Pages — check whether the underlying Pages site still exists.
pm-bounces.bioconductor.org
CNAME → pm.mtasv.net. No public HTTPS response — mailing-list bounce handling (Postmark), not meant to be browsed.
osca.bioconductor.org
CNAME → bioconductor.github.io. Live — redirects into “the OSCA book” (Orchestrating Single-Cell Analysis), an external teaching resource.
osca-dev.bioconductor.org
CNAME → bioconductor.github.io. Same pattern as osca, development version.
new.bioconductor.org
A → 52.71.54.154. Live, and resolves to the same IP as master.bioconductor.org, serving an identical “Bioconductor - Home” page. Looks like a leftover alias rather than a distinct site — worth confirming with the team before assuming it can be dropped.
meet.bioconductor.org
A → 54.82.236.113. No public HTTPS response — purpose unconfirmed; hostname suggests a meeting/scheduling tool.
gitdevtest2.bioconductor.org
A → 149.165.171.129. No public HTTPS response — second test git host, same IP as the first.
gitdevtest.bioconductor.org
A → 149.165.171.129. No public HTTPS response — test git host.
federated-packages.bioconductor.org
A → 149.165.155.146. No public HTTPS response — purpose unconfirmed; name suggests an experimental federated package-serving effort.
courses.bioconductor.org
A → 52.54.47.64. No public HTTPS response — purpose unconfirmed.
core-sops.bioconductor.org
CNAME → victorious-wave-0b018b710.4.azurestaticapps.net. Live, redirects to a /login/ page — internal SOPs site (Azure Static Web Apps), access-gated as expected.
cfp.bioconductor.org
A → 3.139.155.94. No public HTTPS response — hostname suggests a call-for-proposals form, possibly tied to a past conference and safe to retire, but unconfirmed.
auth.bioconductor.org
A → 149.165.153.78. No public HTTPS response — likely an internal auth service (the wildcard *.auth.bioconductor.org mirrors it). Undecided status suggests this needs an owner check.
anvil.bioconductor.org
CNAME → bioconductor.github.io. Live — BiocAnVIL project pages, part of the AnVIL cloud-genomics collaboration.
Already off AWS — no action (27, one table)
Event-site CNAMEs (bioc20{18..26}, biocasia20{20..26}, eurobioc20{19..26}, gbcc2025) plus dev.status, and fe-bounces — all confirmed live, all pointing at GitHub Pages, Netlify, or forwardemail.net. None resolve through CloudFront, master, or staging — the cutover is invisible to them.
Delete candidates (25) — confirmed unreachable
Every host in this list returned no public HTTPS response in the probe, consistent with being retired already: tokay1/2, merida1/2, malbec1/2, machv2, celaya2, monitor, docbuilder, kjohnson1, k8slaunch, js2launch, bbr (×2), yescure(cluster), prodaks — plus seven tagged “delete end of 2026” (workshopk8s, workshopcluster, prodk8s, hsdsdev, cloudman.kubeinstall, ci-mirror, biocworkshop), presumably tied to a class or grant ending. The probe is supporting evidence for the delete call, not proof — “no public HTTPS” doesn’t rule out an internal-only service still in use.
Mail/cert plumbing and wildcards, undecided (24)
Not individually probed — none of these are meant to serve HTTP content. ACM certificate-validation CNAMEs (_....acm-validations.aws.) and DKIM selector CNAMEs need re-verification against whatever currently sends mail as bioconductor.org, not assumption of obsolescence. The wildcard records (*.workshop, *.auth, *.bbr, …) mirror a decision already made on their base hostname above but weren’t themselves tagged — worth confirming they’re meant to inherit it rather than being reviewed independently.
Open questions for the core team
Apex mechanism— settled 2026-09-17: nameserver migration to Cloudflare, see the migration plan.- Dedicated Bioconductor Cloudflare account: agree, and name the super administrators and the billing owner.
- R2 object count for
bioc-siteandbioc-prop— sizes the account-move copy (time and write-operation cost). - Plain-HTTP behaviour on the new edge: redirect to HTTPS like production, or serve 200?
- Which SPF record is intended at the apex, and who owns the unlisted apex TXT value?
new.bioconductor.orgmirrorsmaster.bioconductor.orgexactly (same IP, same content) — leftover alias or intentional?slack.bioconductor.orgserves a generic template unrelated to its name — check what this vhost is actually for.issues.bioconductor.orgresponds with a bare “Nothing to see here” — confirm whether the real tracker moved.- Confirm the 18 undecided hosts above, especially the stale-looking test hosts (
testweb,testinggit,gitdevtest,gitdevtest2,support.test) and the second CloudFront distribution behindtestweb(d3h1507zzd6849.cloudfront.net, distinct from production — does it need retiring too?).