mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-09-14 10:52:34 +00:00
Introducing the Setup Wizard for creating the first user
- no longer setup a default - still able to do that with env vars however
This commit is contained in:
197
backend/setup.js
197
backend/setup.js
@@ -7,65 +7,68 @@ import settingModel from "./models/setting.js";
|
||||
import userModel from "./models/user.js";
|
||||
import userPermissionModel from "./models/user_permission.js";
|
||||
|
||||
export const isSetup = async () => {
|
||||
const row = await userModel.query().select("id").where("is_deleted", 0).first();
|
||||
return row?.id > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a default admin users if one doesn't already exist in the database
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
const setupDefaultUser = () => {
|
||||
return userModel
|
||||
.query()
|
||||
.select("id")
|
||||
.where("is_deleted", 0)
|
||||
.first()
|
||||
.then((row) => {
|
||||
if (!row || !row.id) {
|
||||
// Create a new user and set password
|
||||
const email = (process.env.INITIAL_ADMIN_EMAIL || 'admin@example.com').toLowerCase();
|
||||
const password = process.env.INITIAL_ADMIN_PASSWORD || "changeme";
|
||||
const setupDefaultUser = async () => {
|
||||
const initialAdminEmail = process.env.INITIAL_ADMIN_EMAIL;
|
||||
const initialAdminPassword = process.env.INITIAL_ADMIN_PASSWORD;
|
||||
|
||||
logger.info(`Creating a new user: ${email} with password: ${password}`);
|
||||
// This will only create a new user when there are no active users in the database
|
||||
// and the INITIAL_ADMIN_EMAIL and INITIAL_ADMIN_PASSWORD environment variables are set.
|
||||
// Otherwise, users should be shown the setup wizard in the frontend.
|
||||
// I'm keeping this legacy behavior in case some people are automating deployments.
|
||||
|
||||
const data = {
|
||||
is_deleted: 0,
|
||||
email: email,
|
||||
name: "Administrator",
|
||||
nickname: "Admin",
|
||||
avatar: "",
|
||||
roles: ["admin"],
|
||||
};
|
||||
if (!initialAdminEmail || !initialAdminPassword) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return userModel
|
||||
.query()
|
||||
.insertAndFetch(data)
|
||||
.then((user) => {
|
||||
return authModel
|
||||
.query()
|
||||
.insert({
|
||||
user_id: user.id,
|
||||
type: "password",
|
||||
secret: password,
|
||||
meta: {},
|
||||
})
|
||||
.then(() => {
|
||||
return userPermissionModel.query().insert({
|
||||
user_id: user.id,
|
||||
visibility: "all",
|
||||
proxy_hosts: "manage",
|
||||
redirection_hosts: "manage",
|
||||
dead_hosts: "manage",
|
||||
streams: "manage",
|
||||
access_lists: "manage",
|
||||
certificates: "manage",
|
||||
});
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
logger.info("Initial admin setup completed");
|
||||
});
|
||||
}
|
||||
logger.debug("Admin user setup not required");
|
||||
const userIsetup = await isSetup();
|
||||
if (!userIsetup) {
|
||||
// Create a new user and set password
|
||||
logger.info(`Creating a new user: ${initialAdminEmail} with password: ${initialAdminPassword}`);
|
||||
|
||||
const data = {
|
||||
is_deleted: 0,
|
||||
email: email,
|
||||
name: "Administrator",
|
||||
nickname: "Admin",
|
||||
avatar: "",
|
||||
roles: ["admin"],
|
||||
};
|
||||
|
||||
const user = await userModel
|
||||
.query()
|
||||
.insertAndFetch(data);
|
||||
|
||||
await authModel
|
||||
.query()
|
||||
.insert({
|
||||
user_id: user.id,
|
||||
type: "password",
|
||||
secret: password,
|
||||
meta: {},
|
||||
});
|
||||
|
||||
await userPermissionModel.query().insert({
|
||||
user_id: user.id,
|
||||
visibility: "all",
|
||||
proxy_hosts: "manage",
|
||||
redirection_hosts: "manage",
|
||||
dead_hosts: "manage",
|
||||
streams: "manage",
|
||||
access_lists: "manage",
|
||||
certificates: "manage",
|
||||
});
|
||||
logger.info("Initial admin setup completed");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -73,29 +76,25 @@ const setupDefaultUser = () => {
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
const setupDefaultSettings = () => {
|
||||
return settingModel
|
||||
const setupDefaultSettings = async () => {
|
||||
const row = await settingModel
|
||||
.query()
|
||||
.select("id")
|
||||
.where({ id: "default-site" })
|
||||
.first()
|
||||
.then((row) => {
|
||||
if (!row || !row.id) {
|
||||
settingModel
|
||||
.query()
|
||||
.insert({
|
||||
id: "default-site",
|
||||
name: "Default Site",
|
||||
description: "What to show when Nginx is hit with an unknown Host",
|
||||
value: "congratulations",
|
||||
meta: {},
|
||||
})
|
||||
.then(() => {
|
||||
logger.info("Default settings added");
|
||||
});
|
||||
}
|
||||
logger.debug("Default setting setup not required");
|
||||
});
|
||||
.first();
|
||||
|
||||
if (!row?.id) {
|
||||
await settingModel
|
||||
.query()
|
||||
.insert({
|
||||
id: "default-site",
|
||||
name: "Default Site",
|
||||
description: "What to show when Nginx is hit with an unknown Host",
|
||||
value: "congratulations",
|
||||
meta: {},
|
||||
});
|
||||
logger.info("Default settings added");
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -103,43 +102,41 @@ const setupDefaultSettings = () => {
|
||||
*
|
||||
* @returns {Promise}
|
||||
*/
|
||||
const setupCertbotPlugins = () => {
|
||||
return certificateModel
|
||||
const setupCertbotPlugins = async () => {
|
||||
const certificates = await certificateModel
|
||||
.query()
|
||||
.where("is_deleted", 0)
|
||||
.andWhere("provider", "letsencrypt")
|
||||
.then((certificates) => {
|
||||
if (certificates?.length) {
|
||||
const plugins = [];
|
||||
const promises = [];
|
||||
.andWhere("provider", "letsencrypt");
|
||||
|
||||
certificates.map((certificate) => {
|
||||
if (certificate.meta && certificate.meta.dns_challenge === true) {
|
||||
if (plugins.indexOf(certificate.meta.dns_provider) === -1) {
|
||||
plugins.push(certificate.meta.dns_provider);
|
||||
}
|
||||
if (certificates?.length) {
|
||||
const plugins = [];
|
||||
const promises = [];
|
||||
|
||||
// Make sure credentials file exists
|
||||
const credentials_loc = `/etc/letsencrypt/credentials/credentials-${certificate.id}`;
|
||||
// Escape single quotes and backslashes
|
||||
const escapedCredentials = certificate.meta.dns_provider_credentials
|
||||
.replaceAll("'", "\\'")
|
||||
.replaceAll("\\", "\\\\");
|
||||
const credentials_cmd = `[ -f '${credentials_loc}' ] || { mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo '${escapedCredentials}' > '${credentials_loc}' && chmod 600 '${credentials_loc}'; }`;
|
||||
promises.push(utils.exec(credentials_cmd));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
certificates.map((certificate) => {
|
||||
if (certificate.meta && certificate.meta.dns_challenge === true) {
|
||||
if (plugins.indexOf(certificate.meta.dns_provider) === -1) {
|
||||
plugins.push(certificate.meta.dns_provider);
|
||||
}
|
||||
|
||||
return installPlugins(plugins).then(() => {
|
||||
if (promises.length) {
|
||||
return Promise.all(promises).then(() => {
|
||||
logger.info(`Added Certbot plugins ${plugins.join(", ")}`);
|
||||
});
|
||||
}
|
||||
});
|
||||
// Make sure credentials file exists
|
||||
const credentials_loc = `/etc/letsencrypt/credentials/credentials-${certificate.id}`;
|
||||
// Escape single quotes and backslashes
|
||||
const escapedCredentials = certificate.meta.dns_provider_credentials
|
||||
.replaceAll("'", "\\'")
|
||||
.replaceAll("\\", "\\\\");
|
||||
const credentials_cmd = `[ -f '${credentials_loc}' ] || { mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo '${escapedCredentials}' > '${credentials_loc}' && chmod 600 '${credentials_loc}'; }`;
|
||||
promises.push(utils.exec(credentials_cmd));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
await installPlugins(plugins);
|
||||
|
||||
if (promises.length) {
|
||||
await Promise.all(promises);
|
||||
logger.info(`Added Certbot plugins ${plugins.join(", ")}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user