This note is for Head office staff who will own or approve hosting for NGX Ramblers. It is not a guide for a group or area webmaster. Creating, cloning, moving or destroying an environment is Platform Administration only. Groups and areas never see these screens.
The work is done on NGX Staging, which is the site you are reading this on, not on the group or area site being moved. Staging is an environment with Platform Admin turned on. It stores the list of every group and area environment (each environment's fly.io app, MongoDB database, S3 bucket and credentials). Read Where the credentials live today (below) before treating this site as the long-term home for those credentials. It is also the documentation centre for the project (release notes and these technical articles). It is the only environment with Platform Admin turned on at the moment, but nothing stops there being more than one later, each looking after a subset of the estate. Platform Administration is the admin menu that exposes tools ordinary group and area sites do not have: Environment Migration, Move Fly organisation, Move Brevo, Platform Configuration Values, Environment Setup (create, clone, destroy), and related estate screens. A committee login on a group site will not show those menus, because that site does not have Platform Admin turned on.
Head office operators will need a login on this site, on a member record carrying the Committee Member privilege. That can be arranged. There is no separate Environment Admin privilege to grant on a member. These menus are content marked with the Environment Admin access level. The app reveals that content only when the environment has Platform Admin turned on and the member is a Committee Member. Opening the Platform Administration screens themselves needs Platform Admin plus any one of the administrator privileges. Member Privileges explains what each privilege grants and who can set it.
Each group or area site is not one box. It is several independent services, each with its own account and credentials:
flowchart LR
subgraph site["Each group or area site"]
FLY@{ icon: "logos:fly-icon", label: "fly.io app", pos: "b", h: 48 }
MONGO@{ icon: "ngx:mongodb", label: "MongoDB", pos: "b", h: 48 }
S3@{ icon: "ngx:aws", label: "S3 bucket", pos: "b", h: 48 }
BREVO@{ icon: "ngx:brevo", label: "Brevo mail", pos: "b", h: 48 }
CF@{ icon: "ngx:cloudflare", label: "DNS and SSL", pos: "b", h: 48 }
end
style site fill:#E8F5EE,stroke:#9BC8AB,stroke-width:2px,rx:12,ry:12,color:#404143
Head office requires that anything using the Team Emails API must run in an environment Ramblers controls. That is not only “the website”. The site database is MongoDB. CMS media is stored in an S3 bucket. The process that serves the site runs on fly.io. Outbound mail is Brevo. The public hostname is DNS (often Cloudflare). If only the fly.io app moves, MongoDB and S3 can still sit on accounts Ramblers does not hold. If only MongoDB is pointed at a new cluster, the running app still uses the old connection until it is restarted.
Choose the scope and sequence for each environment. MongoDB, S3, Fly, Brevo and DNS ownership can move separately, in stages or within one agreed window. Account readiness, access, downtime and rollback requirements determine the order.
MongoDB only. Copy the site’s database onto a destination cluster, validate the copy, then switch the stored connection and restart or redeploy the app so it uses it. S3 and the Fly organisation can stay where they are while this is done.
MongoDB and S3 together. Add a live copy of the current S3 bucket into the destination AWS account to the MongoDB move. On cutover, the environment record is pointed at the new AWS and MongoDB credentials. Restart or redeploy the app to load those values and verify that it reads from the destination stores.
Fly organisation. Recreate the running app in the destination Fly organisation using the dedicated Fly move guide. This can happen before or after the data move. A Fly move can continue using the existing MongoDB, S3 and Brevo accounts; it does not transfer ownership of those services.
DNS ownership and Brevo. Move the DNS zone account if its ownership needs to change, and use Move Brevo if outbound mail needs to move accounts. These can be separate pieces of work. Coordinate DNS access with any hostname, certificate or mail-domain changes that depend on it.
flowchart TB
PLAN["Choose the scope and sequence<br/>for this environment"]
DATA["Environment Migration<br/>MongoDB, and optionally S3"]
FLY@{ icon: "logos:fly-icon", label: "Move Fly organisation", pos: "b", h: 48 }
MAIL@{ icon: "ngx:brevo", label: "Move Brevo", pos: "b", h: 48 }
DNS@{ icon: "ngx:cloudflare", label: "Move DNS zone ownership if required", pos: "b", h: 48 }
PLAN --> DATA
PLAN --> FLY
PLAN --> MAIL
PLAN --> DNS
DATA --> RELOAD["After credential cutover:<br/>restart or redeploy, then verify the app uses the new stores"]
For example, Fly first is a valid trial while the database, files and mail stay in their existing accounts. Data first is also valid, with the hosting move scheduled later. Platform Configuration Values is automatically kept up to date with configuration changes, showing what has moved and which services still use the previous accounts.
Keep the dependencies within each chosen move:
Routine AWS storage creation, removal, backup and restore are administered through Platform Management, without an AWS console login once the account and credentials are configured.
See Managing AWS through Platform Management for diagrams of the parent account, provisioning identity and each environment’s bucket, service user and permissions, plus what creation, cleanup, backup and restore do.
Recreate the app in the destination Fly organisation using the Platform Management UI on NGX staging. MongoDB, S3 and Brevo are separate moves.
Follow Moving an environment between Fly organisations for the complete illustrated procedure: organisation tokens, a trial cutover, public HTTPS checks, restoring the final app name and checking the saved configuration.
Pasting a new Brevo API key into Mail Settings → API (or into environment setup) would point the site at an empty Brevo account. Senders, the sending domain, lists and contacts live in Brevo under that key. Environment Migration and Move Fly organisation do not copy them.
Move Brevo is a Platform Administration action on NGX Staging. It takes what NGX already holds, plus a snapshot from the current Brevo account, and recreates it against a destination API key in one run. Operators carry on editing role addresses in Committee Settings and list checkboxes in Mail Settings. Move Brevo does not replace those screens. It propagates their data.
Each list on Mail Settings → Lists keeps Auto-subscribe new members, Member-subscribable, Only Auto-subscribe members that have given email marketing consent via Ramblers Head Office Website, the numeric Brevo list id, and the list name. The name is stored with the id so lists can be recreated if the old key is no longer available.
| Item | Where it lives | How Move Brevo uses it |
|---|---|---|
| Destination API key | Supplied on the Move Brevo form | All destination calls use this key. |
| Role From addresses (name + email, default sender) | Committee Settings, outbound email on each role | Creates senders. NGX looks senders up by email. It does not store Brevo’s sender id. |
| Sending domain | Group site URL / mail domain | Creates and authenticates the domain (SPF/DKIM/DMARC). DNS must already exist. |
| Per-list checkboxes and list name | Mail Settings → Lists (listSettings) |
Recreates lists (and folders) by name. Writes new ids back. |
| Who is on which list | Each member subscriptions[] |
Subscribes members on the remapped ids. |
| Brevo contact id | Each member mail.id |
Creates contacts, then writes the new id onto the member. |
| Email content, banners, which role sends | Notification configs, banners, local templates | Left in NGX. Mail is sent as htmlContent, not as Brevo templates. |
| Default list on a notification | notificationConfigs.defaultListId |
Remapped after lists are recreated. |
| Brevo events webhook | URL and token in Mail Settings → API (brevoEventsWebhookSecret) |
Registers the events webhook (unsubscribed, blocked, hard_bounce, spam, complaint) on the destination account. inboundWebhookSecret is the Cloudflare Email Worker path, not a Brevo webhook. |
What stays in NGX (in that group's MongoDB, so Environment Migration copies it):
emailCompositions with status draft. The composer state lives here, not in Brevo.inboxThreads / inboxMessages with outbound direction (bodies and attachment keys). Sent composer records are also kept as emailCompositions with status sent.ngxBrevoCampaigns: Brevo campaign id, name, created time). That is a pointer, not the campaign content or stats.What stays on the old Brevo account and is not copied to the new key:
Move Brevo does not recreate old campaigns on the destination account. Drafts and sent/inbound mail remain because they were already in MongoDB. After the move, Mail Reports will only show stats for mail sent under the new key.
Steps within a Brevo move:
listSettings.name if the snapshot was taken earlier).listSettings and defaultListId.mail.id.Do not drop the old API key until senders are validated and a test mail has gone out. Validate Plan lists what would be created without writing. Restore / propagate is the write. Same shape as Environment Migration.
Today one document in this site's database holds, for every group or area environment, the MongoDB connection, the AWS keys and the fly.io token, plus the platform-wide AWS, Cloudflare and worker values. Deploy reads that document to push each environment's secrets onto its fly.io app. Platform Configuration Values reads the same document to build the inventory, and Show secret values and Offline export can reveal it in full. Secrets, deployment, Fly tokens, and Cloudflare configuration describes the storage and the deploy path in detail.
The secret fields in that document (passwords, secret keys, tokens and the per-environment secrets) are encrypted at rest with a key that is held only on this site's fly.io app, in the GitHub Actions secrets used by deploy, and by a developer running the platform locally. Identifiers such as hosts, bucket names, app names and usernames stay readable so the inventory works without decrypting anything. A copy of the database on its own, or its connection string on its own, does not give up the secrets. Each group site also holds its own fly.io, MongoDB and AWS credentials in its own database, in the clear; those are that site's keys only, not the estate's.
Reading them today needs administrator-level access to this application, or to both its database connection and its encryption key. There is no separate platform-administrator privilege, so any administrator role on this site currently qualifies. The GitHub Actions deploy runner also reads the document, on every deploy.
Every reveal of secret values on this site, whether on screen, as a with-secrets export, or through the configuration API, is logged against the member who asked for it.
That was a reasonable shape while one person ran the estate and needed one place to look. It also means that a compromise of this site itself still exposes credentials for every environment, because the site can decrypt them. Head office should decide that trust boundary rather than inherit it.
What I would propose, for discussion rather than as a decision already made:
The questions for Head office are which store, who holds it, and what NGX itself is allowed to read back from it.
Platform Configuration Values is the Head office picture of the estate. It exists so knowledge is not locked in one operator’s head: what each group or area site uses, which vendor consoles to sign into, and an optional pack you can store outside the app.
It has three modes (the tabs at the top of the page):
Configuration inventory (tab=inventory) is a live read. It reads the saved environments configuration and each site’s settings. Changes made through the platform are recorded automatically; there is no separate migration record to maintain. Tick Show secret values only when you need the actual keys (include-secrets=true). That control is proposed for removal once credentials move out of this site, as described above.
System logins (tab=system-logins) is the human side: Atlas website login, fly.io dashboard, AWS console, Brevo, and so on. Those are not the runtime API keys the app uses. Save writes them into the environments list under consoleAccess. That save does not push credentials onto fly.io, does not change a group or area site’s running config, and does not take effect on the live app. It exists so Head office can find the right vendor website and account without a scavenger hunt: account ids, organisation names and console links. Today it can also hold a login and password. Once Ramblers owns the accounts, those passwords should live in Ramblers' password manager, not here, and the password field should go. GitHub and Docker Hub are stored once as platform-shared.
Offline export (tab=offline-export) downloads spreadsheet, HTML or Markdown of the same inventory. Treat files that include secrets as password-manager material. Do not email them. The with-secrets export is proposed for removal along with Show secret values; the presence-only export stays.
The inventory tables are read-only. You cannot change Mongo, AWS, fly.io or Brevo runtime values from this page. Those change when you use Environment Migration, Move Fly organisation, environment setup, or the site’s own mail/system settings.
When you Save on System logins, the only thing that changes is the stored console logins on this environment. The group or area fly.io app is unaffected. There is no deploy and no restart.
When Environment Migration rotates credentials, the environments list is updated immediately. The live app still uses the old connection until it is restarted (or redeployed) so it reloads config. Platform Configuration Values already reflects the saved Mongo/AWS placement; the restart applies those values to the running app.
All of these open on this site, and need a Committee Member login on an environment with Platform Admin turned on.
| What you need to see | Link |
|---|---|
| The whole tool | Platform Configuration Values |
| Directory of every group or area environment (fly.io app, Mongo, S3 bucket) | Sites directory |
| Mongo connection fields across sites | Site values · MongoDB |
| AWS / S3 fields across sites | Site values · AWS |
| fly.io organisation and token fields | Site values · fly.io |
| Brevo API key per site | Site values · Brevo |
| Shared platform AWS, Cloudflare, worker, AI | Platform values |
| Human Atlas logins | System logins · MongoDB Atlas |
| Human fly.io logins | System logins · fly.io |
| Human AWS logins | System logins · AWS |
| Human Brevo logins | System logins · Brevo |
| Offline pack | Offline export |
The inventory loads the current saved configuration when opened.
NGX will not create Ramblers vendor accounts. For each destination you want, someone at Head office (or a nominated operator) must be able to issue:
| Piece | What we need | Notes |
|---|---|---|
| Logins on this site | A member record with the Committee Member privilege | Required to see and open Platform Administration. See Member Privileges. Can be arranged. |
| MongoDB Atlas | Cluster host, database name, user, password | Per group or area database. The cluster can be shared. The credentials should only see that database. |
| AWS | Account (or bucket) plus an access key that can create the bucket and write objects | Environment Migration live-copies the S3 bucket with these keys. Do not reuse the source account’s admin key as the destination. |
| fly.io | An organisation-scoped API token for the destination org, and the current token that still owns the app | Both are required to start a cutover. Saving only the new token would leave the old app unreachable from the new token. |
| DNS | Confirmation of who owns the zone, and that custom hostnames may be re-attached | The fly.io move re-points certificates on the destination app. Changing Cloudflare account ownership is a separate job. |
| Brevo | API key for the destination account, if mail must move | Move Brevo uses this key to recreate domain, senders, lists, contacts and the events webhook. |
A disposable test AWS account and a disposable Atlas database are enough to prove the data path before any production group or area is touched. A second fly.io organisation (or a Ramblers org token) is enough to prove the app path.
Environment Migration: choose the environment, paste destination Mongo, and for an S3 move paste destination AWS (bucket, region, access key, secret). Validate Plan lists and counts without writing. Restore with Drop copies Mongo and, when AWS is filled in, live-copies the S3 bucket into that account. Rotate Credentials is a separate, typed confirmation: until that step, the live site is unchanged. An interrupted run is marked so it is not left half-done in silence.
Move Fly organisation: old and new tokens, status badges, Resume cutover if a run stopped mid-way, optional destroy of the previous app, optional free NGX subdomain, custom domain DNS/SSL on the destination.
Move Brevo: destination API key, Validate Plan, then propagate domain, senders, lists, contacts, subscriptions and the events webhook as above. Role addresses and list settings are still edited in Committee Settings and Mail Settings → Lists.
The first use of any of these on Ramblers-held accounts should be an environment you can afford to break, or a clone, not the first production group or area.
Use this as a checklist for the scope you choose, rather than a fixed service-by-service sequence.
The plan should make clear what “hosting inside a Ramblers environment” means for this site at each stage, including any services that have deliberately stayed where they are.
Platform Admin belongs to the environment, not to a person, and it is not a setting on a group’s own system settings page. The server decides it, and says yes only when both of these hold:
PLATFORM_ADMIN_ENABLED is true for that environment. How that secret is stored, imported onto fly.io, and read at runtime is in Secrets, deployment, Fly tokens, and Cloudflare configuration.Both are per-environment, so turning Platform Admin on for a second site is a deliberate act: set the secret, leave Lite off, restart.
Environment Migration and Move Fly organisation are not the same thing. Migration copies MongoDB (and optionally the S3 bucket) and then, if you confirm, points the stored credentials at the destination. Move Fly organisation leaves that data where it is and recreates the running app under a different fly.io organisation. You can do one without the other.
Platform Configuration Values is not a third move. It does not copy MongoDB, S3 or a fly.io app. It is an inventory of what is already configured, plus a place to record human vendor logins. The configuration values are automatically kept up to date as changes are made through the platform.
PLATFORM_ADMIN_ENABLED is stored, imported onto fly.io, and read at runtime.