# 15-Sep-2026 — Moving existing NGX groups and areas onto Ramblers-held infrastructure

_____

> 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). It is also the documentation centre for the project ([release notes](https://ngx-ramblers.org.uk/how-to/committee/release-notes) and [these technical articles](https://ngx-ramblers.org.uk/how-to/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](https://ngx-ramblers.org.uk/admin/platform)** is the admin menu that exposes tools ordinary group and area sites do not have: [Environment Migration](https://ngx-ramblers.org.uk/admin/platform/environment-management/migration?tab=plan-restore), [Move Fly organisation](https://ngx-ramblers.org.uk/admin/platform/environment-management/setup?tab=create-or-modify&setup-mode=manage&manage-action=migrate-fly-org), [Move Brevo](https://ngx-ramblers.org.uk/admin/platform/environment-management/move-brevo), [Platform Configuration Values](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=inventory), [Environment Setup](https://ngx-ramblers.org.uk/admin/platform/environment-management/setup?tab=create-or-modify) (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](https://ngx-ramblers.org.uk/admin/platform) screens themselves needs Platform Admin plus any one of the administrator privileges. [Member Privileges](https://ngx-ramblers.org.uk/how-to/committee/member-admin/member-privileges) explains what each privilege grants and who can set it.

### How Platform Admin gets turned on

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](https://ngx-ramblers.org.uk/how-to/technical-articles/2026-04-12-secrets-deployment-and-cloudflare-config#platform-admin-platform_admin_enabled).
- **NGX-Lite Mode is off** for that environment. That is a checkbox on the same [Environment Setup](https://ngx-ramblers.org.uk/admin/platform/environment-management/setup?tab=create-or-modify) screen. Lite is the email-only mode for groups that do not run a full public site. It hides Platform Admin even when the secret is set.

Both are per-environment, so turning Platform Admin on for a second site is a deliberate act: set the secret, leave Lite off, restart.

The tools that matter for a move are:

- [Environment Migration](https://ngx-ramblers.org.uk/admin/platform/environment-management/migration?tab=plan-restore) — MongoDB, and optionally the S3 bucket
- [Move Fly organisation](https://ngx-ramblers.org.uk/admin/platform/environment-management/setup?tab=create-or-modify&setup-mode=manage&manage-action=migrate-fly-org) — the running app (Create or Modify, change existing, **Move Fly organisation**)
- [Move Brevo](https://ngx-ramblers.org.uk/admin/platform/environment-management/move-brevo) — sending domain, senders, lists, contacts and the events webhook onto a destination API key
- [Platform Configuration Values](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=inventory) — the live inventory of every environment, human console logins, and an offline export

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. Refresh it after a move if you want the tables to match the new credentials.

## What has to move

Each group or area site is not one box. It is several independent services, each with its own account and credentials:

```mermaid
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.

## Four flavours of work

Treat these as separate jobs that can be combined. Do not assume one button does all of them.

**1. MongoDB only.** Copy the site’s database onto a cluster Ramblers holds, prove the copy, then switch the stored connection. Use this when the S3 bucket and the fly.io app can stay where they are for a while.

**2. MongoDB and S3 together.** Same as (1), plus a **live copy** of the current S3 bucket into a destination AWS account you supply (bucket, region, access key, secret). On cutover, the environment record is pointed at those new AWS credentials as well as the new Mongo credentials. Use this when Head office has (or will create) an AWS account for that group or area, or a shared Ramblers AWS account with a dedicated bucket.

**3. fly.io organisation.** Recreate the running app under a Ramblers fly.io organisation. fly.io cannot rename an app from one organisation to another, so NGX uses a dual-token cutover: old token to drain the current app, new org-scoped token to create and deploy, then optional destroy of the old app, and re-point of custom domain DNS and certificates. The free NGX subdomain is optional and off by default when the site already uses a custom domain.

**4. Restart, DNS zone, and Move Brevo.** **Restart** the fly.io app after Mongo/S3 cutover so the process loads the new connection strings. **Cloudflare** (or other DNS) if the DNS zone itself must sit under a Ramblers login, beyond what the fly.io custom-domain step already re-points. **Move Brevo** if mail must not stay on the previous Brevo account: a new API key is not enough on its own. See below.

```mermaid
flowchart TB
    DATA["Environment Migration<br/>Mongo, 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: "Zone ownership if required", pos: "b", h: 48 }
    DATA --> RESTART["Restart the app so it uses the new Mongo and S3"]
    RESTART --> FLY
    FLY --> MAIL
    MAIL --> DNS
```

Recommended order for a full move onto Ramblers-held accounts: **copy data first, cut over credentials, restart, then move the fly.io app, then move Brevo.** If you move the fly.io app first, you still have to copy data, and you have two moving parts at once.

### Move Brevo

Pasting a new Brevo API key into Mail Settings (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](https://ngx-ramblers.org.uk/admin/platform/environment-management/move-brevo)** is a [Platform Administration](https://ngx-ramblers.org.uk/admin/platform) 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. [Committee Settings](https://ngx-ramblers.org.uk/how-to/committee/member-admin/committee-roles) and [Mail Settings](https://ngx-ramblers.org.uk/how-to/committee/email-articles/mail-settings/email-configurations) stay the places operators edit role addresses and list checkboxes. 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 (`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):

- **Drafts** in the Inbox Drafts folder. These are `emailCompositions` with status draft. The composer state lives here, not in Brevo.
- **Sent items** in the Inbox Sent folder. These are `inboxThreads` / `inboxMessages` with outbound direction (bodies and attachment keys). Sent composer records are also kept as `emailCompositions` with status sent.
- **Inbound mail** in Inbox, Junk and Deleted. Same inbox collections.
- A thin NGX record of campaigns it created (`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:

- The campaign objects themselves (schedule, HTML as stored by Brevo, recipient lists used at send time).
- Open, click and bounce statistics. Mail Reports reads those live from Brevo.
- Suppression / block state that exists only in Brevo.

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.

**Order against the destination key:**

1. Snapshot list and folder names from the current account (or from stored `listSettings.name` if the snapshot was taken earlier).
2. Create and authenticate the sending domain.
3. Create senders for every committee role address and extras.
4. Recreate folders and lists. Write new ids into `listSettings` and `defaultListId`.
5. Create contacts from members. Write new `mail.id`.
6. Subscribe each member to the remapped lists.
7. Register the Brevo events webhook.
8. Store SMTP credentials for the new account if Brevo returns them.

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.

## Platform Configuration Values

[Platform Configuration Values](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=inventory) 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**. Load audit (or Refresh) reads the environments list on this environment and probes each group or area database. It is not a background feed. If someone changes a secret on a site, or Environment Migration rotates Mongo/AWS, this page does **not** update until you load again. Tick **Show secret values** only when you need the actual keys (`include-secrets=true`).

**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 is a shared notebook so Head office can open the right vendor website. 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.

### Does editing here apply to an environment?

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. After that restart, Refresh on Platform Configuration Values should show the new Mongo/AWS placement.

### Deep links for a hosting move

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](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=inventory) |
| Directory of every group or area environment (fly.io app, Mongo, S3 bucket) | [Sites directory](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=inventory&section=sites) |
| Mongo connection fields across sites | [Site values · MongoDB](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=inventory&section=fields&system=mongodb-atlas) |
| AWS / S3 fields across sites | [Site values · AWS](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=inventory&section=fields&system=aws-s3) |
| fly.io organisation and token fields | [Site values · fly.io](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=inventory&section=fields&system=fly-io) |
| Brevo API key per site | [Site values · Brevo](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=inventory&section=fields&system=brevo) |
| Shared platform AWS, Cloudflare, worker, AI | [Platform values](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=inventory&section=platform) |
| Human Atlas logins | [System logins · MongoDB Atlas](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=system-logins&system=mongodb-atlas) |
| Human fly.io logins | [System logins · fly.io](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=system-logins&system=fly-io) |
| Human AWS logins | [System logins · AWS](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=system-logins&system=aws) |
| Human Brevo logins | [System logins · Brevo](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=system-logins&system=brevo) |
| Offline pack | [Offline export](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=offline-export) |

Load audit on the inventory tab before relying on the field tables. The first open does not fetch every site until you ask.

## What Head office needs to provide

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](https://ngx-ramblers.org.uk/admin/platform). See [Member Privileges](https://ngx-ramblers.org.uk/how-to/committee/member-admin/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.

## The Platform Administration screens

**[Environment Migration](https://ngx-ramblers.org.uk/admin/platform/environment-management/migration?tab=plan-restore):** 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](https://ngx-ramblers.org.uk/admin/platform/environment-management/setup?tab=create-or-modify&setup-mode=manage&manage-action=migrate-fly-org):** 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](https://ngx-ramblers.org.uk/admin/platform/environment-management/move-brevo):** destination API key, Validate Plan, then propagate domain, senders, lists, contacts, subscriptions and the events webhook as above. Committee Settings and Mail Settings remain the editors.

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.

## What we should not pretend is automatic

- **One “transfer tool” that does AWS, Mongo and fly.io in a single click.** That work is two screens plus a restart.
- **Creating the Atlas cluster or the AWS account.** You create those. NGX copies into them.
- **Brevo fully moved by pasting an API key.** Use Move Brevo. Committee Settings and Mail Settings stay the editors.
- **Estate-wide bulk move of every group or area.** Same facilities, one environment at a time.
- **Other website platforms.** This note is NGX only.
- **Platform Configuration Values pushing secrets into live apps.** Inventory is a snapshot you refresh. System-login Save does not deploy.

## Suggested first run

1. Agree who owns Atlas, AWS and fly.io after the move. A useful test: could Ramblers withdraw the previous operator’s access and the site still serve API data?
2. Issue logins on this site, on member records with the **Committee Member** privilege ([Member Privileges](https://ngx-ramblers.org.uk/how-to/committee/member-admin/member-privileges)).
3. Open [Sites directory](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=inventory&section=sites), load the audit, and confirm which fly.io app, Mongo database and S3 bucket the trial environment uses today.
4. Create a test Atlas database and a test AWS account (or bucket). Run [Environment Migration](https://ngx-ramblers.org.uk/admin/platform/environment-management/migration?tab=plan-restore). Confirm object counts and that the site, after restart, reads from the new store. Refresh inventory and check [Mongo](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=inventory&section=fields&system=mongodb-atlas) and [AWS](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=inventory&section=fields&system=aws-s3) fields.
5. With a Ramblers fly.io organisation token, run [Move Fly organisation](https://ngx-ramblers.org.uk/admin/platform/environment-management/setup?tab=create-or-modify&setup-mode=manage&manage-action=migrate-fly-org) on that same environment (or a clone). Confirm the public hostname still answers. Refresh [fly.io site values](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=inventory&section=fields&system=fly-io).
6. Record human console logins for the destination accounts under [System logins](https://ngx-ramblers.org.uk/admin/platform/environment-management/estate-rebuild-capture?tab=system-logins) so the next operator can open Atlas, fly.io, AWS and Brevo without a scavenger hunt.
7. Only then pick a production group or area, and write down whether mail and the DNS zone move in the same window or later.

Until those steps are written down, “hosting inside a Ramblers environment” will keep meaning different things in different meetings.

## Related

- [Secrets, deployment, Fly tokens, and Cloudflare configuration](https://ngx-ramblers.org.uk/how-to/technical-articles/2026-04-12-secrets-deployment-and-cloudflare-config#platform-admin-platform_admin_enabled) — how `PLATFORM_ADMIN_ENABLED` is stored, imported onto fly.io, and read at runtime.
- [Member Privileges](https://ngx-ramblers.org.uk/how-to/committee/member-admin/member-privileges) — what each administrator privilege grants, including Committee Member.
- [Committee Roles](https://ngx-ramblers.org.uk/how-to/committee/member-admin/committee-roles) — how role addresses are set up on a group or area site.
- [Email Configurations](https://ngx-ramblers.org.uk/how-to/committee/email-articles/mail-settings/email-configurations) — the Mail Settings screens referred to above.
- [NGX-Ramblers Architecture](https://ngx-ramblers.org.uk/how-to/technical-articles/2026-02-11-ngx-ramblers-architecture) — how a single environment is put together.
- [Platform Overview](https://ngx-ramblers.org.uk/how-to/technical-articles/2026-03-18-single-instance-multi-tenant-exploration/platform-overview) — why the estate is one app per group or area rather than one shared instance.
- [Release notes](https://ngx-ramblers.org.uk/how-to/committee/release-notes) and [technical articles](https://ngx-ramblers.org.uk/how-to/technical-articles) — both published from this site.
- All of the above live under [Platform Administration](https://ngx-ramblers.org.uk/admin/platform/environment-management). They are not on group or area committee menus.
