563 lines
9.6 KiB
Markdown
563 lines
9.6 KiB
Markdown
You’ve identified the Mongo volume that’s causing the auth issue.
|
||
|
||
What this means
|
||
local mern-ludo_mongo_data
|
||
|
||
|
||
This volume still exists, so Mongo is:
|
||
|
||
reusing old, broken initialization
|
||
|
||
not recreating the admin user
|
||
|
||
continuing to fail authentication
|
||
|
||
We now need to delete this volume so Mongo can initialize cleanly.
|
||
|
||
✅ Do this EXACTLY (safe + correct)
|
||
🔴 Step 1: Stop containers
|
||
docker compose down
|
||
|
||
🔴 Step 2: Remove the Mongo volume
|
||
docker volume rm mern-ludo_mongo_data
|
||
|
||
|
||
If Docker complains it’s in use, run:
|
||
|
||
docker compose down -v
|
||
|
||
|
||
(that removes volumes automatically)
|
||
|
||
✅ Step 3: Confirm it’s gone
|
||
docker volume ls | grep ludo
|
||
|
||
|
||
👉 This should return nothing.
|
||
|
||
✅ Step 4: Start ONLY Mongo first (important)
|
||
docker compose up -d mongo
|
||
|
||
|
||
Wait 10–15 seconds.
|
||
|
||
Check logs:
|
||
|
||
docker logs ludo-mongo --tail=30
|
||
|
||
|
||
You should NOT see:
|
||
|
||
bad file
|
||
|
||
Unable to acquire security key
|
||
|
||
crash/restart loops
|
||
|
||
✅ Step 5: Test authentication (this MUST work)
|
||
docker exec -it ludo-mongo mongosh -u admin -p adminpassword --authenticationDatabase admin
|
||
|
||
|
||
If you get a > prompt → 🎉 auth is fixed
|
||
|
||
✅ Step 6: Initialize replica set (ONCE)
|
||
|
||
Inside mongosh:
|
||
|
||
rs.initiate({
|
||
_id: "rs0",
|
||
members: [{ _id: 0, host: "mongo:27017" }]
|
||
})
|
||
|
||
|
||
Then:
|
||
|
||
rs.status().members[0].stateStr
|
||
|
||
|
||
Must be:
|
||
|
||
"PRIMARY"
|
||
|
||
✅ Step 7: Start the app
|
||
docker compose up -d app
|
||
|
||
|
||
(or just)
|
||
|
||
docker compose up -d
|
||
|
||
|
||
Then:
|
||
|
||
docker restart mern-ludo-app
|
||
|
||
🎯 Expected final result
|
||
Mongo
|
||
|
||
Auth works
|
||
|
||
Replica set PRIMARY
|
||
|
||
No errors in logs
|
||
|
||
Backend
|
||
MongoDB connected
|
||
Server listening on port 18081
|
||
|
||
Browser
|
||
|
||
App loads
|
||
|
||
No crashes
|
||
|
||
No noscript / auth errors
|
||
|
||
🧾 One-line status
|
||
|
||
The Mongo volume still existed; deleting it allows Mongo to create the admin user correctly.
|
||
|
||
Once Step 5 succeeds, you are fully unblocked.
|
||
Run Step 2 now and tell me when mongosh login works 👍
|
||
|
||
|
||
You’re very close, and the remaining issue is not random.
|
||
|
||
What the two messages really mean (important)
|
||
1️⃣ These messages are NOT the main problem ❌
|
||
Collection [local.oplog.rs] not found
|
||
ReadConcernMajorityNotAvailableYet
|
||
|
||
|
||
These appear when:
|
||
|
||
replica set is not initiated yet
|
||
|
||
PRIMARY is not elected yet
|
||
|
||
They are expected noise before rs.initiate() succeeds.
|
||
|
||
👉 We’ll fix them automatically once the replica set is initialized.
|
||
|
||
2️⃣ THIS is the real blocker 🔴
|
||
MongoServerError: Authentication failed
|
||
|
||
|
||
This means 100%:
|
||
|
||
🔐 MongoDB is running with authentication enabled,
|
||
❌ but the admin user does not exist.
|
||
|
||
This is why:
|
||
|
||
backend can’t connect
|
||
|
||
mongosh -u admin fails
|
||
|
||
oplog can’t be created
|
||
|
||
replica set can’t complete
|
||
|
||
Why the admin user does NOT exist (root cause)
|
||
|
||
Mongo creates the root user only once, on first successful startup, when:
|
||
|
||
/data/db is empty
|
||
|
||
Mongo reaches a stable running state
|
||
|
||
Earlier, Mongo:
|
||
|
||
crashed due to keyFile issues
|
||
|
||
restarted several times
|
||
|
||
skipped user creation
|
||
|
||
but auth stayed enabled
|
||
|
||
Result:
|
||
|
||
Mongo requires auth, but no users exist → permanent auth failure
|
||
|
||
This is a classic Mongo + replica set + keyFile edge case.
|
||
|
||
✅ The ONLY correct fix (clean & guaranteed)
|
||
|
||
We must let Mongo start once without auth, create the user manually, then re-enable auth.
|
||
|
||
This is the official MongoDB recovery method.
|
||
|
||
🔥 DO THIS STEP-BY-STEP (no skipping)
|
||
STEP 1️⃣ Stop everything
|
||
docker compose down
|
||
|
||
STEP 2️⃣ Temporarily DISABLE auth (Mongo only)
|
||
|
||
Edit docker-compose.yml mongo service:
|
||
|
||
🔴 TEMPORARY CHANGE
|
||
|
||
Comment out these lines for now:
|
||
|
||
# environment:
|
||
# MONGO_INITDB_ROOT_USERNAME: admin
|
||
# MONGO_INITDB_ROOT_PASSWORD: adminpassword
|
||
|
||
|
||
And change the command to NO keyFile, NO auth:
|
||
|
||
command:
|
||
- mongod
|
||
- --replSet
|
||
- rs0
|
||
- --bind_ip_all
|
||
|
||
|
||
(Leave volumes as-is.)
|
||
|
||
STEP 3️⃣ Start Mongo only
|
||
docker compose up -d mongo
|
||
|
||
|
||
Wait ~10 seconds.
|
||
|
||
STEP 4️⃣ Connect WITHOUT auth (this must work)
|
||
docker exec -it ludo-mongo mongosh
|
||
|
||
|
||
If you get a prompt → good.
|
||
|
||
STEP 5️⃣ Create admin user MANUALLY
|
||
|
||
Inside mongosh:
|
||
|
||
use admin
|
||
db.createUser({
|
||
user: "admin",
|
||
pwd: "adminpassword",
|
||
roles: [ { role: "root", db: "admin" } ]
|
||
})
|
||
|
||
|
||
You must see:
|
||
|
||
{ ok: 1 }
|
||
|
||
STEP 6️⃣ Initialize replica set (NOW it will work)
|
||
rs.initiate({
|
||
_id: "rs0",
|
||
members: [{ _id: 0, host: "mongo:27017" }]
|
||
})
|
||
|
||
|
||
Wait ~5–10 seconds, then:
|
||
|
||
rs.status().members[0].stateStr
|
||
|
||
|
||
Must be:
|
||
|
||
"PRIMARY"
|
||
|
||
|
||
Exit mongosh:
|
||
|
||
exit
|
||
|
||
STEP 7️⃣ Re-enable auth + keyFile (FINAL config)
|
||
|
||
Restore your correct mongo config:
|
||
|
||
environment:
|
||
MONGO_INITDB_ROOT_USERNAME: admin
|
||
MONGO_INITDB_ROOT_PASSWORD: adminpassword
|
||
|
||
command:
|
||
- bash
|
||
- -c
|
||
- |
|
||
cp /tmp/mongo-keyfile /data/db/keyfile &&
|
||
chown mongodb:mongodb /data/db/keyfile &&
|
||
chmod 400 /data/db/keyfile &&
|
||
exec mongod --replSet rs0 --keyFile /data/db/keyfile --bind_ip_all
|
||
|
||
STEP 8️⃣ Restart clean
|
||
docker compose down
|
||
docker compose up -d
|
||
|
||
STEP 9️⃣ Test auth (this WILL work now)
|
||
docker exec -it ludo-mongo mongosh -u admin -p adminpassword --authenticationDatabase admin
|
||
|
||
STEP 🔟 Start / restart backend
|
||
docker restart mern-ludo-app
|
||
|
||
✅ What you should see now
|
||
Mongo
|
||
|
||
Auth works
|
||
|
||
PRIMARY elected
|
||
|
||
local.oplog.rs exists
|
||
|
||
No auth errors
|
||
|
||
Backend
|
||
MongoDB connected
|
||
Server listening on port 18081
|
||
|
||
App
|
||
|
||
Loads normally
|
||
|
||
No crashes
|
||
|
||
Change Streams work
|
||
|
||
🧠 One-line final diagnosis
|
||
|
||
MongoDB authentication was enabled before any user existed; manual user creation was required to recover.
|
||
|
||
This is the last MongoDB trap — once done, you will not hit this again.
|
||
|
||
MongoServerError[NotWritablePrimary]: not primary
|
||
|
||
Perfect — that error is expected at this exact moment, and it tells us precisely what to do next 👍
|
||
You didn’t break anything.
|
||
|
||
What this error means (very clear)
|
||
MongoServerError[NotWritablePrimary]: not primary
|
||
|
||
|
||
This means:
|
||
|
||
MongoDB is running as a replica set member,
|
||
but no PRIMARY has been elected yet.
|
||
|
||
Until a node becomes PRIMARY:
|
||
|
||
❌ you cannot create users
|
||
|
||
❌ you cannot write data
|
||
|
||
❌ db.createUser() will fail
|
||
|
||
So this is not an auth issue anymore.
|
||
|
||
✅ Correct order (important)
|
||
|
||
When running Mongo as a replica set, the order must be:
|
||
|
||
Start Mongo
|
||
|
||
Initiate replica set
|
||
|
||
Wait until PRIMARY
|
||
|
||
Create users
|
||
|
||
Enable auth (already planned)
|
||
|
||
Right now, you’re at step 2½.
|
||
|
||
✅ DO THIS NOW (inside mongosh)
|
||
|
||
You are already connected with:
|
||
|
||
docker exec -it ludo-mongo mongosh
|
||
|
||
|
||
At the > prompt, run THIS FIRST 👇
|
||
|
||
🔥 Step 1: Initiate replica set
|
||
rs.initiate({
|
||
_id: "rs0",
|
||
members: [
|
||
{ _id: 0, host: "mongo:27017" }
|
||
]
|
||
})
|
||
|
||
Expected output
|
||
{ ok: 1 }
|
||
|
||
🔥 Step 2: Wait a few seconds, then verify PRIMARY
|
||
rs.status().members[0].stateStr
|
||
|
||
|
||
You must see:
|
||
|
||
"PRIMARY"
|
||
|
||
|
||
If it still says STARTUP or SECONDARY, wait 5 seconds and run again.
|
||
|
||
✅ ONLY AFTER PRIMARY → create admin user
|
||
|
||
Now run:
|
||
|
||
use admin
|
||
|
||
db.createUser({
|
||
user: "admin",
|
||
pwd: "adminpassword",
|
||
roles: [ { role: "root", db: "admin" } ]
|
||
})
|
||
|
||
Expected:
|
||
{ ok: 1 }
|
||
|
||
🧠 Why this happened (important lesson)
|
||
|
||
You started Mongo with:
|
||
|
||
mongod --replSet rs0
|
||
|
||
|
||
That automatically puts Mongo into replica set mode, but:
|
||
|
||
replica set is inactive
|
||
|
||
no PRIMARY exists yet
|
||
|
||
Mongo rejects all writes until a PRIMARY is elected.
|
||
|
||
This is correct MongoDB behavior.
|
||
|
||
✅ After user creation (next steps preview)
|
||
|
||
Once { ok: 1 } appears:
|
||
|
||
Exit mongosh:
|
||
|
||
exit
|
||
|
||
|
||
Re-enable auth + keyFile in docker-compose (as discussed)
|
||
|
||
Restart containers
|
||
|
||
Verify:
|
||
|
||
docker exec -it ludo-mongo mongosh -u admin -p adminpassword --authenticationDatabase admin
|
||
|
||
🎯 One-line status update
|
||
|
||
MongoDB is in replica-set mode but not PRIMARY yet — initialize the replica set first.
|
||
|
||
👉 Action for you now
|
||
|
||
Run rs.initiate(...), wait for PRIMARY, then retry db.createUser.
|
||
|
||
Tell me what rs.status().members[0].stateStr prints, and we’ll finish this cleanly 💪
|
||
|
||
|
||
```yaml
|
||
version: "3.9"
|
||
|
||
services:
|
||
mongo:
|
||
image: mongo:7.0
|
||
container_name: ludo-mongo
|
||
restart: unless-stopped
|
||
networks:
|
||
- ludo-net
|
||
environment:
|
||
MONGO_INITDB_ROOT_USERNAME: admin
|
||
MONGO_INITDB_ROOT_PASSWORD: adminpassword
|
||
volumes:
|
||
- ludo-mongo-data:/data/db
|
||
- ./mongo-keyfile:/tmp/mongo-keyfile:ro
|
||
command:
|
||
- bash
|
||
- -c
|
||
- |
|
||
cp /tmp/mongo-keyfile /data/db/keyfile &&
|
||
chown mongodb:mongodb /data/db/keyfile &&
|
||
chmod 400 /data/db/keyfile &&
|
||
exec mongod --replSet rs0 --keyFile /data/db/keyfile --bind_ip_all
|
||
ports:
|
||
- "27017:27017"
|
||
|
||
app:
|
||
build: .
|
||
container_name: mern-ludo-app
|
||
restart: unless-stopped
|
||
networks:
|
||
- ludo-net
|
||
env_file:
|
||
- .env
|
||
ports:
|
||
- "18081:8080"
|
||
depends_on:
|
||
- mongo
|
||
|
||
networks:
|
||
ludo-net:
|
||
|
||
volumes:
|
||
ludo-mongo-data:
|
||
```
|
||
|
||
Step 2️⃣ Recreate keyfile cleanly (one last time)
|
||
cd ~/mern-ludo
|
||
rm -f mongo-keyfile
|
||
openssl rand -base64 756 > mongo-keyfile
|
||
chmod 400 mongo-keyfile
|
||
|
||
|
||
Verify:
|
||
|
||
wc -c mongo-keyfile
|
||
|
||
Step 3️⃣ Full reset (MANDATORY)
|
||
docker compose down -v
|
||
docker compose up -d --build
|
||
|
||
|
||
Wait ~10 seconds.
|
||
|
||
Step 4️⃣ Confirm Mongo is RUNNING (not restarting)
|
||
docker ps
|
||
|
||
|
||
You should NOT see Restarting.
|
||
|
||
Step 5️⃣ Now exec WILL work
|
||
docker exec -it ludo-mongo mongosh -u admin -p adminpassword --authenticationDatabase admin
|
||
|
||
|
||
If you get a shell → 🎉 Mongo is fixed
|
||
|
||
Step 6️⃣ Initialize replica set (ONCE)
|
||
rs.initiate({
|
||
_id: "rs0",
|
||
members: [{ _id: 0, host: "mongo:27017" }]
|
||
})
|
||
|
||
|
||
Check:
|
||
|
||
rs.status().members[0].stateStr
|
||
// PRIMARY
|
||
|
||
Step 7️⃣ Restart app
|
||
docker restart mern-ludo-app
|
||
|
||
|
||
Your Change Stream error will now be gone permanently.
|
||
|
||
🧠 Why ALL previous attempts failed
|
||
Attempt Why it failed
|
||
Bind mount keyfile Ownership mismatch
|
||
chmod 400 only Not enough
|
||
DietPi ARM Stricter FS behavior
|
||
Mongo 7 Enforces keyfile rules hard
|
||
|
||
This copy + chown pattern solves all of them.
|
||
|
||
✅ One-line final diagnosis
|
||
|
||
MongoDB rejected the keyfile because bind-mounted files keep host ownership, and Mongo runs as a non-root user.
|
||
|