diff --git a/MeshCentralServer.njsproj b/MeshCentralServer.njsproj
index 3fca9f59..ed66a52d 100644
--- a/MeshCentralServer.njsproj
+++ b/MeshCentralServer.njsproj
@@ -227,6 +227,7 @@
+
diff --git a/meshcentral-config-schema.json b/meshcentral-config-schema.json
new file mode 100644
index 00000000..d07c611f
--- /dev/null
+++ b/meshcentral-config-schema.json
@@ -0,0 +1,412 @@
+{
+ "id": "http://info.meshcentral.com/download/meshcentral-config-schema.json",
+ "$schema": "http://json-schema.org/draft-04/schema#",
+ "description": "MeshCentral configuration file schema",
+ "type": "object",
+ "properties": {
+ "settings": {
+ "type": "object",
+ "properties": {
+ "Cert": { "type": "string" },
+ "MongoDb": { "type": "string" },
+ "MongoDbName": { "type": "string" },
+ "MongoDbChangeStream": { "type": "boolean" },
+ "MongoDumpPath": { "type": "string" },
+ "WANonly": { "type": "boolean", "default": false },
+ "LANonly": { "type": "boolean", "default": false },
+ "SessionTime": { "type": "integer" },
+ "SessionKey": { "type": "string" },
+ "SessionSameSite": { "type": "string" },
+ "DbEncryptKey": { "type": "string" },
+ "DbRecordsEncryptKey": { "type": "string" },
+ "DbRecordsDecryptKey": { "type": "string" },
+ "DbExpire": {
+ "type": "object",
+ "properties": {
+ "events": { "type": "integer" },
+ "powerevents": { "type": "integer" },
+ "statsevents": { "type": "integer" }
+ }
+ },
+ "Port": { "type": "integer", "minimum": 1, "maximum": 65535 },
+ "PortBind": { "type": "string" },
+ "AliasPort": { "type": "integer", "minimum": 1, "maximum": 65535 },
+ "RedirPort": { "type": "integer", "minimum": 1, "maximum": 65535 },
+ "RedirPortBind": { "type": "string" },
+ "RedirAliasPort": { "type": "integer", "minimum": 1, "maximum": 65535 },
+ "AgentPort": { "type": "integer", "minimum": 1, "maximum": 65535 },
+ "AgentPortBind": { "type": "string" },
+ "AgentAliasPort": { "type": "integer", "minimum": 1, "maximum": 65535 },
+ "AgentAliasDNS": { "type": "string", "format": "hostname" },
+ "AgentPortTls": { "type": "boolean", "default": true },
+ "ExactPorts": { "type": "boolean", "default": false },
+ "AllowLoginToken": { "type": "boolean", "default": false },
+ "AllowFraming": { "type": "boolean", "default": false },
+ "CookieIpCheck": { "type": "boolean" },
+ "CookieEncoding": { "type": "string", "enum": [ "hex", "base64" ], "default": "base64" },
+ "WebRTC": { "type": "boolean", "default": false },
+ "Nice404": { "type": "boolean" },
+ "ClickOnce": { "type": "boolean" },
+ "SelfUpdate": { "type": "boolean", "default": false, "description": "When true, this server will attempt to self-update everyday after midnight." },
+ "BrowserPing": { "type": "integer", "minimum": 1, "description": "When specified, sends data to the browser at x seconds interval and expects a response from the browser." },
+ "BrowserPong": { "type": "integer", "minimum": 1, "description": "When specified, sends data to the browser at x seconds interval." },
+ "AgentPing": { "type": "integer", "minimum": 1, "description": "When specified, sends data to the agent at x seconds interval and expects a response from the agent." },
+ "AgentPong": { "type": "integer", "minimum": 1, "description": "When specified, sends data to the agent at x seconds interval." },
+ "AgentIdleTimeout": { "type": "integer", "minimum": 1 },
+ "MeshErrorLogPath": { "type": "string" },
+ "NpmPath": { "type": "string" },
+ "NpmProxy": { "type": "string" },
+ "AllowHighQualityDesktop": { "type": "boolean" },
+ "DesktopMultiplex": { "type": "boolean" },
+ "UserAllowedIP": { "type": "string" },
+ "UserBlockedIP": { "type": "string" },
+ "AgentAllowedIP": { "type": "string" },
+ "AgentBlockedIP": { "type": "string" },
+ "AuthLog": { "type": "string" },
+ "ManageAllDeviceGroups": { "type": "array", "items": [ { "type": "string" } ] },
+ "ManageCrossDomain": { "type": "array", "items": [ { "type": "string" } ] },
+ "LocalDiscovery": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "name": { "type": "string" },
+ "info": { "type": "string" }
+ },
+ "required": [ "name", "info" ]
+ },
+ "TlsOffload": { "type": "string" },
+ "TrustedProxy": { "type": "string" },
+ "MpsPort": { "type": "integer", "minimum": 1, "maximum": 65535 },
+ "MpsPortBind": { "type": "string" },
+ "MpsAliasPort": { "type": "integer", "minimum": 1, "maximum": 65535 },
+ "MpsAliasHost": { "type": "string" },
+ "MpsTlsOffload": { "type": "boolean" },
+ "No2FactorAuth": { "type": "boolean" },
+ "Log": { "type": "string" },
+ "syslog": { "type": "string" },
+ "syslogauth": { "type": "string" },
+ "syslogjson": { "type": "string" },
+ "WebRtConfig": {
+ "type": "object",
+ "properties": {
+ "iceServers": {
+ "type": "array",
+ "items": [ { "type": "object", "properties": { "urls": { "type": "string" } }, "required": [ "urls" ] } ]
+ }
+ },
+ "required": [ "iceServers" ]
+ },
+ "AutoBackup": {
+ "type": "object",
+ "properties": {
+ "backupIntervalHours": { "type": "integer" },
+ "keepLastDaysBackup": { "type": "integer" },
+ "zipPassword": { "type": "string" },
+ "backupPath": { "type": "string" }
+ }
+ },
+ "Redirects": { "type": "object" },
+ "MaxInvalidLogin": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "time": { "type": "integer" },
+ "count": { "type": "integer" },
+ "coolofftime": { "type": "integer" }
+ }
+ },
+ "Plugins": {
+ "type": "object",
+ "properties": { "enabled": { "type": "boolean" } },
+ "required": [ "enabled" ]
+ }
+ }
+ },
+ "domaindefaults": { "type": "object" },
+ "domains": {
+ "type": "object",
+ "properties": {
+ "": {
+ "type": "object",
+ "properties": {
+ "Title": { "type": "string" },
+ "Title2": { "type": "string" },
+ "TitlePicture": { "type": "string" },
+ "UserQuota": { "type": "integer" },
+ "MeshQuota": { "type": "integer" },
+ "Minify": { "type": "boolean" },
+ "NewAccounts": { "type": "boolean" },
+ "NewAccountsUserGroups": { "type": "array", "items": [ { "type": "string" } ] },
+ "UserNameIsEmail": { "type": "boolean" },
+ "NewAccountEmailDomains": { "type": "array", "items": [ { "type": "string" } ] },
+ "NewAccountsRights": { "type": "array", "items": [ { "type": "string" } ] },
+ "WelcomeText": { "type": "string" },
+ "WelcomePicture": { "type": "string" },
+ "Hide": { "type": "integer" },
+ "Footer": { "type": "string" },
+ "CertUrl": { "type": "string", "format": "uri" },
+ "PasswordRequirements": {
+ "type": "object",
+ "properties": {
+ "min": { "type": "integer" },
+ "max": { "type": "integer" },
+ "upper": { "type": "integer" },
+ "lower": { "type": "integer" },
+ "numeric": { "type": "integer" },
+ "nonalpha": { "type": "integer" },
+ "reset": { "type": "integer" },
+ "force2factor": { "type": "boolean" },
+ "skip2factor": { "type": "string" }
+ }
+ },
+ "AgentInviteCodes": { "type": "boolean", "default": false },
+ "AgentNoProxy": { "type": "boolean", "default": false },
+ "GeoLocation": { "type": "boolean", "default": false },
+ "novnc": { "type": "boolean", "default": true },
+ "mstsc": {
+ "type": "boolean",
+ "default": false
+ },
+ "CustomUI": { "type": "object" },
+ "ConsentMessages": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "Title": { "type": "string" },
+ "Desktop": { "type": "string" },
+ "Terminal": { "type": "string" },
+ "Files": { "type": "string" }
+ }
+ },
+ "NotificationMessages": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "Title": { "type": "string" },
+ "Desktop": { "type": "string" },
+ "Terminal": { "type": "string" },
+ "Files": { "type": "string" }
+ }
+ },
+ "UserAllowedIP": { "type": "string" },
+ "UserBlockedIP": { "type": "string" },
+ "AgentAllowedIP": { "type": "string" },
+ "AgentBlockedIP": { "type": "string" },
+ "UserSessionIdleTimeout": { "type": "integer" },
+ "UserConsentFlags": { "type": "integer" },
+ "UrlSwitching": { "type": "boolean" },
+ "DesktopPrivacyBarText": { "type": "string" },
+ "Limits": {
+ "type": "object",
+ "properties": {
+ "MaxDevices": { "type": "integer" },
+ "MaxUserAccounts": { "type": "integer" },
+ "MaxUserSessions": { "type": "integer" },
+ "MaxAgentSessions": { "type": "integer" },
+ "MaxSingleUserSessions": { "type": "integer" }
+ }
+ },
+ "AmtAcmActivation": {
+ "type": "object",
+ "properties": {
+ "log": { "type": "string" },
+ "certs": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object",
+ "properties": {
+ "certfiles": { "type": "array", "items": [ { "type": "string" } ] },
+ "keyfile": { "type": "string" }
+ },
+ "required": [ "certfiles", "keyfile" ]
+ }
+ }
+ }
+ },
+ "Redirects": {
+ "type": "object",
+ "additionalProperties": { "type": "string" }
+ },
+ "Yubikey": {
+ "type": "object",
+ "properties": {
+ "id": { "type": "string" },
+ "secret": { "type": "string" },
+ "proxy": { "type": "string" }
+ },
+ "required": [ "id", "secret" ]
+ },
+ "AgentConfig": {
+ "type": "array",
+ "items": [ { "type": "string" } ]
+ },
+ "SessionRecording": {
+ "type": "object",
+ "properties": {
+ "filepath": { "type": "string" },
+ "index": { "type": "boolean", "default": false },
+ "maxRecordings": { "type": "integer" },
+ "maxRecordingSizeMegabytes": { "type": "integer" },
+ "protocols": {
+ "type": "array",
+ "items": [ { "type": "integer" } ]
+ }
+ },
+ "required": [ "protocols" ]
+ },
+ "AuthStrategies": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "twitter": {
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "callbackurl": { "type": "string", "format": "uri" },
+ "newAccounts": { "type": "boolean" },
+ "newAccountsUserGroups": { "type": "array", "items": [ { "type": "string" } ] },
+ "clientid": { "type": "string" },
+ "clientsecret": { "type": "string" }
+ },
+ "required": [ "clientid", "clientsecret" ]
+ },
+ "google": {
+ "type": "object",
+ "properties": {
+ "callbackurl": { "type": "string", "format": "uri" },
+ "newAccounts": { "type": "boolean" },
+ "newAccountsUserGroups": { "type": "array", "items": [ { "type": "string" } ] },
+ "clientid": { "type": "string" },
+ "clientsecret": { "type": "string" }
+ },
+ "required": [ "clientid", "clientsecret" ]
+ },
+ "github": {
+ "type": "object",
+ "properties": {
+ "callbackurl": { "type": "string", "format": "uri" },
+ "newAccounts": { "type": "boolean" },
+ "newAccountsUserGroups": { "type": "array", "items": [ { "type": "string" } ] },
+ "clientid": { "type": "string" },
+ "clientsecret": { "type": "string" }
+ },
+ "required": [ "clientid", "clientsecret" ]
+ },
+ "reddit": {
+ "type": "object",
+ "properties": {
+ "callbackurl": { "type": "string", "format": "uri" },
+ "newAccounts": { "type": "boolean" },
+ "newAccountsUserGroups": { "type": "array", "items": [ { "type": "string" } ] },
+ "clientid": { "type": "string" },
+ "clientsecret": { "type": "string" }
+ },
+ "required": [ "clientid", "clientsecret" ]
+ },
+ "azure": {
+ "type": "object",
+ "properties": {
+ "callbackurl": { "type": "string", "format": "uri" },
+ "newAccounts": { "type": "boolean" },
+ "newAccountsUserGroups": { "type": "array", "items": [ { "type": "string" } ] },
+ "clientid": { "type": "string" },
+ "clientsecret": { "type": "string" },
+ "tenantid": { "type": "string" }
+ },
+ "required": [ "clientid", "clientsecret", "tenantid" ]
+ },
+ "jumpcloud": {
+ "type": "object",
+ "properties": {
+ "callbackurl": { "type": "string", "format": "uri" },
+ "newAccounts": { "type": "boolean" },
+ "newAccountsUserGroups": { "type": "array", "items": [ { "type": "string" } ] },
+ "entityid": { "type": "string" },
+ "idpurl": { "type": "string" },
+ "cert": { "type": "string" }
+ },
+ "required": [ "entityid", "idpurl", "cert" ]
+ },
+ "saml": {
+ "type": "object",
+ "properties": {
+ "callbackurl": { "type": "string", "format": "uri" },
+ "disableRequestedAuthnContext": { "type": "boolean" },
+ "newAccounts": { "type": "boolean" },
+ "newAccountsUserGroups": { "type": "array", "items": [ { "type": "string" } ] },
+ "newAccountsRights": { "type": "array", "items": [ { "type": "string" } ] },
+ "entityid": { "type": "string" },
+ "idpurl": { "type": "string" },
+ "cert": { "type": "string" }
+ },
+ "required": [ "entityid", "idpurl", "cert" ]
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "letsencrypt": {
+ "title" : "Built-in Let's Encrypt support",
+ "description": "If your server has a proper DNS name and it public facing on the Internet with a public facing HTTP server on port 80, you can get a free TLS certificate.",
+ "type": "object",
+ "additionalProperties": false,
+ "properties": {
+ "email": { "type": "string", "format": "email" },
+ "names": { "type": "string" },
+ "production": { "type": "boolean" }
+ },
+ "required": [ "email", "names", "production" ]
+ },
+ "peers": {
+ "title" : "Server peering",
+ "description": "Setup peer server for load-balancing between many servers.",
+ "type": "object",
+ "minProperties": 1,
+ "propertyNames": { "pattern": "^[A-Za-z_][A-Za-z0-9_]*$" },
+ "additionalProperties": false,
+ "properties": {
+ "serverId": { "type": "string" },
+ "servers": {
+ "type": "object",
+ "additionalProperties": {
+ "type": "object",
+ "properties": { "url": { "type": "string", "format": "uri" } },
+ "required": [ "url" ]
+ }
+ }
+ },
+ "required": [ "serverId", "servers" ]
+ },
+ "smtp": {
+ "title" : "Email server",
+ "description": "Connects MeshCentral to a email server, allows MeshCentral to send email messages for 2FA or user notification",
+ "type": "object",
+ "properties": {
+ "host": { "type": "string", "format": "hostname" },
+ "port": { "type": "integer", "minimum": 1, "maximum": 65535 },
+ "from": { "type": "string", "format": "email" },
+ "tls": { "type": "boolean" },
+ "tlscertcheck": { "type": "boolean" },
+ "tlsstrict": { "type": "boolean" }
+ },
+ "required": [ "host", "port", "from", "tls" ]
+ },
+ "sms": {
+ "title" : "SMS provider",
+ "description": "Connects MeshCentral to a SMS text messaging provider, allows MeshCentral to send SMS messages for 2FA or user notification",
+ "type": "object",
+ "properties": {
+ "provider": { "type": "string", "enum": [ "twilio", "plivo" ] },
+ "id": { "type": "string" },
+ "sid": { "type": "string" },
+ "token": { "type": "string" },
+ "from": { "type": "string" }
+ },
+ "required": [ "provider", "token", "from" ]
+ }
+ },
+ "required": [ "settings", "domains" ]
+}
+
diff --git a/sample-config-advanced.json b/sample-config-advanced.json
index 5e2ef514..46e95c21 100644
--- a/sample-config-advanced.json
+++ b/sample-config-advanced.json
@@ -1,5 +1,6 @@
{
- "__comment__" : "This is a sample configuration file, all values and sections that start with underscore (_) are ignored. Edit a section and remove the _ in front of the name. Refer to the user's guide for details.",
+ "$schema": "http://info.meshcentral.com/downloads/meshcentral-config-schema.json",
+ "__comment__": "This is a sample configuration file, all values and sections that start with underscore (_) are ignored. Edit a section and remove the _ in front of the name. Refer to the user's guide for details.",
"settings": {
"_Cert": "myserver.mydomain.com",
"_MongoDb": "mongodb://127.0.0.1:27017",
@@ -89,7 +90,11 @@
"meshcommander": "https://www.meshcommander.com/"
},
"__MaxInvalidLogin": "Time in minutes, max amount of bad logins from a source IP in the time before logins are rejected.",
- "_MaxInvalidLogin": { "time": 10, "count": 10, "coolofftime": 10 },
+ "_MaxInvalidLogin": {
+ "time": 10,
+ "count": 10,
+ "coolofftime": 10
+ },
"_Plugins": { "enabled": true }
},
"_domaindefaults": {
@@ -117,7 +122,17 @@
"_Hide": 4,
"_Footer": "Twitter",
"_CertUrl": "https://192.168.2.106:443/",
- "_PasswordRequirements": { "min": 8, "max": 128, "upper": 1, "lower": 1, "numeric": 1, "nonalpha": 1, "reset": 90, "force2factor": true, "skip2factor": "127.0.0.1,192.168.2.0/24" },
+ "_PasswordRequirements": {
+ "min": 8,
+ "max": 128,
+ "upper": 1,
+ "lower": 1,
+ "numeric": 1,
+ "nonalpha": 1,
+ "reset": 90,
+ "force2factor": true,
+ "skip2factor": "127.0.0.1,192.168.2.0/24"
+ },
"_AgentInviteCodes": true,
"_AgentNoProxy": true,
"_GeoLocation": true,
@@ -139,10 +154,10 @@
"_UserBlockedIP": "127.0.0.1,::1,192.168.0.100",
"_AgentAllowedIP": "192.168.0.100/24",
"_AgentBlockedIP": "127.0.0.1,::1",
- "___UserSessionIdleTimeout__" : "Number of user idle minutes before auto-disconnect",
- "_UserSessionIdleTimeout" : 30,
- "__UserConsentFlags__" : "Set to: 1 for desktop, 2 for terminal, 3 for files, 7 for all",
- "_UserConsentFlags" : 7,
+ "___UserSessionIdleTimeout__": "Number of user idle minutes before auto-disconnect",
+ "_UserSessionIdleTimeout": 30,
+ "__UserConsentFlags__": "Set to: 1 for desktop, 2 for terminal, 3 for files, 7 for all",
+ "_UserConsentFlags": 7,
"_UrlSwitching": false,
"_DesktopPrivacyBarText": "Your privacy bar message",
"_Limits": {
@@ -164,7 +179,11 @@
"_Redirects": {
"meshcommander": "https://www.meshcommander.com/"
},
- "_yubikey": { "id": "0000", "secret": "xxxxxxxxxxxxxxxxxxxxx", "_proxy": "http://myproxy.domain.com:80" },
+ "_yubikey": {
+ "id": "0000",
+ "secret": "xxxxxxxxxxxxxxxxxxxxx",
+ "_proxy": "http://myproxy.domain.com:80"
+ },
"_httpheaders": {
"Strict-Transport-Security": "max-age=360000",
"x-frame-options": "SAMEORIGIN",
@@ -180,7 +199,7 @@
"protocols": [ 1, 2, 101 ]
},
"_authStrategies": {
- "__comment__" : "This section is used to allow users to login using other accounts. You will need to get an API key from the services and register callback URL's",
+ "__comment__": "This section is used to allow users to login using other accounts. You will need to get an API key from the services and register callback URL's",
"twitter": {
"_callbackurl": "https://server/auth-twitter-callback",
"newAccounts": true,
@@ -311,9 +330,9 @@
"from": "+1-555-555-5555"
},
"__sms": {
- "provider": "plivo",
- "id": "xxxxxxx",
- "token": "xxxxxxx",
- "from": "1-555-555-5555"
+ "provider": "plivo",
+ "id": "xxxxxxx",
+ "token": "xxxxxxx",
+ "from": "1-555-555-5555"
}
}
diff --git a/sample-config.json b/sample-config.json
index b57a91f5..3df3edb9 100644
--- a/sample-config.json
+++ b/sample-config.json
@@ -1,6 +1,7 @@
{
- "__comment1__" : "This is a simple configuration file, all values and sections that start with underscore (_) are ignored. Edit a section and remove the _ in front of the name. Refer to the user's guide for details.",
- "__comment2__" : "See node_modules/meshcentral/sample-config-advanced.json for a more advanced example.",
+ "$schema": "http://info.meshcentral.com/downloads/meshcentral-config-schema.json",
+ "__comment1__": "This is a simple configuration file, all values and sections that start with underscore (_) are ignored. Edit a section and remove the _ in front of the name. Refer to the user's guide for details.",
+ "__comment2__": "See node_modules/meshcentral/sample-config-advanced.json for a more advanced example.",
"settings": {
"_Cert": "myserver.mydomain.com",
"_WANonly": true,