What's the best way to add a default admin user in Node.js/MongoDB app?

You can use a script, say seed.js, to safely insert as many users with admin role as required.

//seed.js
var User = require('../path/to/user.js');

var user = {
    name: "Admin User",
    email: "[email protected]",
    role: "admin"
}

User.create(user, function(e) {
    if (e) {
        throw e;
    }
});

Require seed.js in your server.js or app.js script right after the connection to mongodb is made. Comment or remove this line when you are done seeding.

require('../path/to/seed');

If you want to set up the admin with a password, you can define a folder, which contains some deployment files (which you obviously don't want to track using your cvs) and add the users in a JSON file:

mkdir .deploy
echo '.deploy' >> .gitignore
cd .deploy
touch users.json

and add the users config there:

{
  "users": [{
    name: "Admin User",
    username: "admin",
    email: "[email protected]",
    role: "admin",
    password: "some-long-password"
  }]
}

Then in your code at startup you check the project's filesystem for the users.json file. If it exists, create the new users and delete it, otherwise continue:

import fs from 'fs'

const User = require('../path/to/user.js');

const startup = () => {
  const path = '/path/to/users.json'
  fs.readFile(path, 'utf8', function (err, data) {
    if (err) return console.error(err)
    const usersConf = JSON.parse(data);
    usersConf.users.forEach(user => User.create(user))
    deleteUsers(path)
  })
}

const deleteUsers = (path) => {
  fs.unlink(path, (err) => {
    if (err) console.error(err)
  })
}

startup()

Of course this could also be written using async / await to prevent these nested callback.

You should write a check, if the user exists and ignore the user, because you may provide the users.json again the next time you deploy and update.