mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-08-14 16:00:25 +02:00
201 lines
6.2 KiB
Markdown
201 lines
6.2 KiB
Markdown
# Optional remote MongoDB replica
|
|
|
|
This deployment option converts the existing standalone MongoDB container into
|
|
a replica set named `rs0` and adds a remote, hidden, non-voting secondary.
|
|
Normal single-node deployments continue to use `docker-compose.yml` alone.
|
|
|
|
The remote member is designed as a recovery and backup source:
|
|
|
|
- It cannot become primary.
|
|
- Its availability does not affect production majority writes.
|
|
- It is hidden from application traffic.
|
|
- It is delayed by one hour by default, providing a short recovery window for
|
|
accidental deletes or a bad migration.
|
|
|
|
Replication is not a backup. Destructive changes eventually reach every
|
|
member. Continue making encrypted, off-host `mongodump` archives from the
|
|
secondary.
|
|
|
|
## Requirements
|
|
|
|
1. Take and verify a `mongodump` backup before converting production.
|
|
2. Install this repository on both servers.
|
|
3. Connect the servers through a trusted private network such as WireGuard,
|
|
Tailscale, a private VLAN, or a cloud private network.
|
|
4. Create stable DNS names that resolve from both servers and from the
|
|
application container, for example:
|
|
|
|
- `mongo-primary.internal`
|
|
- `mongo-secondary.internal`
|
|
|
|
5. Permit TCP port `27017` only between the required private-network hosts.
|
|
Do not expose MongoDB to the public internet.
|
|
6. Run the exact same MongoDB version on both servers. Find the current
|
|
production version with:
|
|
|
|
```bash
|
|
docker compose exec mongodb mongod --version
|
|
```
|
|
|
|
Set the matching image in both servers' `.env` files:
|
|
|
|
```env
|
|
MONGO_IMAGE=mongo:<exact-version>
|
|
```
|
|
|
|
## 1. Generate the shared member key
|
|
|
|
On the primary server:
|
|
|
|
```bash
|
|
./scripts/mongodb-replica.sh generate-key
|
|
```
|
|
|
|
This creates `secrets/mongo-replica-keyfile` without overwriting an existing
|
|
key. Copy that exact file securely to the same repository-relative path on the
|
|
secondary server:
|
|
|
|
```bash
|
|
scp secrets/mongo-replica-keyfile \
|
|
secondary-server:/path/to/anonymous_github/secrets/mongo-replica-keyfile
|
|
```
|
|
|
|
Keep this key outside source control and backups that are accessible to
|
|
untrusted users. Every replica-set member must share the same key.
|
|
|
|
## 2. Configure production
|
|
|
|
Add these values to the primary server's `.env`:
|
|
|
|
```env
|
|
# Use the exact version already running in production.
|
|
MONGO_IMAGE=mongo:<exact-version>
|
|
|
|
# The primary server's private/VPN interface.
|
|
MONGO_BIND_ADDRESS=<primary-private-ip>
|
|
MONGO_REPLICA_KEYFILE=./secrets/mongo-replica-keyfile
|
|
|
|
# Make the replica overlay the default for future Compose commands.
|
|
COMPOSE_FILE=docker-compose.yml:docker-compose.replica-primary.yml
|
|
|
|
# URL-encode special characters in the username and password.
|
|
MONGODB_URI=mongodb://<user>:<password>@mongo-primary.internal:27017/production?authSource=admin&replicaSet=rs0&retryWrites=true&w=majority
|
|
```
|
|
|
|
Stop application writers, leaving MongoDB available:
|
|
|
|
```bash
|
|
docker compose stop anonymous_github streamer
|
|
```
|
|
|
|
Start MongoDB with replica-set support and initialize the existing database as
|
|
the primary:
|
|
|
|
```bash
|
|
./scripts/mongodb-replica.sh primary-up \
|
|
mongo-primary.internal:27017
|
|
```
|
|
|
|
`primary-up` is idempotent. If `rs0` is already initialized, it reports that
|
|
state instead of replacing the replica-set configuration.
|
|
|
|
## 3. Start the remote secondary
|
|
|
|
On the secondary server, create a minimal `.env`:
|
|
|
|
```env
|
|
MONGO_IMAGE=mongo:<same-exact-version-as-primary>
|
|
MONGO_BIND_ADDRESS=<secondary-private-ip>
|
|
MONGO_REPLICA_KEYFILE=./secrets/mongo-replica-keyfile
|
|
```
|
|
|
|
Start its empty MongoDB data volume:
|
|
|
|
```bash
|
|
./scripts/mongodb-replica.sh secondary-up
|
|
```
|
|
|
|
Do not copy the primary's live WiredTiger volume. MongoDB performs the initial
|
|
sync after the member is added.
|
|
|
|
## 4. Add and verify the secondary
|
|
|
|
Back on the primary server, add the remote member with the default one-hour
|
|
delay:
|
|
|
|
```bash
|
|
./scripts/mongodb-replica.sh add-secondary \
|
|
mongo-secondary.internal:27017
|
|
```
|
|
|
|
To keep the remote copy current instead, explicitly set a zero-second delay:
|
|
|
|
```bash
|
|
./scripts/mongodb-replica.sh add-secondary \
|
|
mongo-secondary.internal:27017 0
|
|
```
|
|
|
|
Check initial-sync and replication state:
|
|
|
|
```bash
|
|
./scripts/mongodb-replica.sh status
|
|
```
|
|
|
|
Wait until the remote member reports `SECONDARY`, then restart the application:
|
|
|
|
```bash
|
|
docker compose up -d anonymous_github streamer redis
|
|
```
|
|
|
|
## Operations
|
|
|
|
Use the primary overlay for every future operation on the production stack.
|
|
Keeping `COMPOSE_FILE` in `.env` makes ordinary commands such as
|
|
`docker compose up -d` and `docker compose logs mongodb` use it automatically.
|
|
|
|
Check replica status:
|
|
|
|
```bash
|
|
./scripts/mongodb-replica.sh status
|
|
```
|
|
|
|
If a destructive production operation occurs and the secondary is delayed,
|
|
stop the secondary container immediately before the delay window elapses:
|
|
|
|
```bash
|
|
docker compose -f docker-compose.replica-secondary.yml stop mongodb-secondary
|
|
```
|
|
|
|
Then take a copy or logical dump of the delayed data before attempting
|
|
recovery.
|
|
|
|
For automatic failover, use three voting data-bearing members instead of
|
|
turning this two-server recovery topology into a two-voter replica set. Two
|
|
voters require both servers to acknowledge a majority and can make production
|
|
unwritable during a network outage.
|
|
|
|
## Troubleshooting
|
|
|
|
- All members must use the same replica-set name (`rs0`), MongoDB version, and
|
|
shared keyfile.
|
|
- The hostnames stored in `rs.conf()` must resolve from every member.
|
|
- The application container must also resolve `mongo-primary.internal`. Use
|
|
private DNS or a Compose `extra_hosts` entry if host DNS is not propagated
|
|
into Docker.
|
|
- Check container logs with:
|
|
|
|
```bash
|
|
docker compose logs mongodb
|
|
docker compose -f docker-compose.replica-secondary.yml logs mongodb-secondary
|
|
```
|
|
|
|
- Re-run `primary-up`, `add-secondary`, or `status` safely; the management
|
|
operations do not replace existing replica-set members.
|
|
|
|
## MongoDB references
|
|
|
|
- [Convert a standalone server to a replica set](https://www.mongodb.com/docs/manual/tutorial/convert-standalone-to-replica-set/)
|
|
- [Deploy a replica set with member authentication](https://www.mongodb.com/docs/v8.0/tutorial/deploy-replica-set-with-keyfile-access-control/)
|
|
- [Configure a delayed member](https://www.mongodb.com/docs/manual/tutorial/configure-a-delayed-replica-set-member/)
|
|
- [Hidden replica-set members](https://www.mongodb.com/docs/manual/core/replica-set-hidden-member/)
|