Compare commits

...

68 Commits

Author SHA1 Message Date
bfb328238e Merge pull request #806 from jc21/develop
v2.7.2
2021-01-07 09:35:35 +10:00
64cc4f57d6 Version bump and acknowledgements 2021-01-06 21:48:10 +10:00
7a3c91c6a4 Merge pull request #804 from lebrou34/master
Add Gandi Live DNS to certbot-dns-plugins.js
2021-01-06 13:14:54 +10:00
508bc62852 Update certbot-dns-plugins.js 2021-01-05 18:47:22 +01:00
59e8446d47 Update certbot-dns-plugins.js 2021-01-05 18:41:26 +01:00
d13596d2f7 Update certbot-dns-plugins.js 2021-01-05 18:35:18 +01:00
9adccfa341 Update certbot-dns-plugins.js 2021-01-05 18:19:27 +01:00
5cc3b53378 Update certbot-dns-plugins.js 2021-01-05 18:11:10 +01:00
b62b0a2fb7 Update certbot-dns-plugins.js 2021-01-05 17:36:47 +01:00
1faac4edf2 Merge pull request #750 from klutchell/klutchell-patch-1
allow custom stream conf
2021-01-03 20:14:55 +10:00
4c60dce169 Merge pull request #796 from lightglitch/patch-1
Fix dead hosts verification count
2021-01-03 20:14:36 +10:00
771f31f44d Merge pull request #770 from jc21/dependabot/npm_and_yarn/backend/ini-1.3.8
Bump ini from 1.3.5 to 1.3.8 in /backend
2021-01-03 20:14:21 +10:00
8bedb95e1d Merge pull request #771 from jc21/dependabot/npm_and_yarn/test/ini-1.3.8
Bump ini from 1.3.5 to 1.3.8 in /test
2021-01-03 20:14:03 +10:00
ac4be08df2 Merge pull request #772 from jc21/dependabot/npm_and_yarn/docs/ini-1.3.8
Bump ini from 1.3.5 to 1.3.8 in /docs
2021-01-03 20:13:49 +10:00
0d6e058e23 Merge pull request #774 from chaptergy/better-custom-certificate-handling
Better custom certificate handling
2021-01-03 12:09:55 +10:00
bee2ceb667 Fix dead hosts verification count 2021-01-02 04:58:14 +00:00
6af13d4f40 Removes explicit privkeytype check and adds passphrase error 2020-12-14 12:08:39 +01:00
9dd0ebd899 Bump ini from 1.3.5 to 1.3.8 in /docs
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.8.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.8)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-12 10:17:11 +00:00
6e97bfa717 Bump ini from 1.3.5 to 1.3.8 in /test
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.8.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.8)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-12 08:23:59 +00:00
07b69f41eb Bump ini from 1.3.5 to 1.3.8 in /backend
Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.8.
- [Release notes](https://github.com/isaacs/ini/releases)
- [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.8)

Signed-off-by: dependabot[bot] <support@github.com>
2020-12-12 08:23:45 +00:00
6bd2ac7d6d Update README.md 2020-12-01 14:24:14 -05:00
528e5ef3bc allow custom stream conf
Allow a top-level custom `stream` configuration file to be loaded.
2020-12-01 14:22:31 -05:00
bc1c50ac92 Added contributor 2020-11-22 21:50:57 +10:00
8c2ab42b75 Merge pull request #738 from WaterCalm/master
add aliyun DNS plugin
2020-11-22 21:48:24 +10:00
62053d15d4 add aliyun DNS plugin
add aliyun DNS plugin
2020-11-22 16:08:56 +08:00
6fed642aba Cypress docker build should be faster and added mkcert for later 2020-11-22 16:57:12 +10:00
72ac549a58 Merge pull request #729 from jc21/develop
v2.7.1
2020-11-18 22:55:47 +10:00
9f38617135 Merge branch 'master' into develop 2020-11-18 22:55:37 +10:00
94eec805df Version bump 2020-11-18 21:46:21 +10:00
05a940e732 Fix instances where config file exists and env vars don't 2020-11-18 21:42:03 +10:00
1c43cc2181 Merge pull request #725 from jc21/develop
v2.7.0
2020-11-18 14:30:44 +10:00
657ee73ff1 Merge branch 'master' into develop 2020-11-18 12:22:34 +10:00
4ee5d993cf Bumped version 2020-11-18 12:21:35 +10:00
70a445e2d7 Merge pull request #704 from chaptergy/allow-setup-without-config-file
Removes the need of a config file and allows db config via environment
2020-11-18 12:18:45 +10:00
2115da210d Merge pull request #694 from chaptergy/visual-indicator-for-certificate-deletion
Adds visual indicator for certificate deletion
2020-11-09 10:10:55 +10:00
540554c4f6 Merge pull request #695 from chaptergy/failed-certificate-autoremove
Adds autoremove of failed certificate creations in DB
2020-11-09 10:10:00 +10:00
1337c50d28 Use latest tag in full setup instructions 2020-11-07 19:37:35 +01:00
c5ceb3b2b1 Removes obsolete file mount 2020-11-07 13:54:18 +01:00
57fc1d8f08 Removes the need of a config file and allows db config via environment 2020-11-07 13:24:01 +01:00
1518ecd1e9 Adds autoremove of failed certificate creations in DB 2020-11-06 12:29:38 +01:00
6be0343918 Adds visual indicator for certificate deletion 2020-11-06 11:51:42 +01:00
cf8812c932 Merge pull request #692 from jc21/develop
v2.6.2
2020-11-06 19:31:10 +10:00
5bc3e474a9 Merge branch 'real_ip' of github.com:jc21/nginx-proxy-manager into develop 2020-11-06 13:21:37 +10:00
13eaa346bc Use remote addr as real ip 2020-11-06 13:21:22 +10:00
d7437cc4a7 Test for real-ip header 2020-11-06 13:17:30 +10:00
ddb3c6590c Version bump 2020-11-06 13:06:15 +10:00
89d6773bda Merge branch 'develop' of github.com:jc21/nginx-proxy-manager into real_ip 2020-11-06 09:18:25 +10:00
3651b9484f Fix for pip install error when there are no plugins to install 2020-11-06 09:17:52 +10:00
2200c950b7 Merge branch 'develop' of github.com:jc21/nginx-proxy-manager into real_ip 2020-11-06 09:12:35 +10:00
14f84f01b5 Merge pull request #687 from chaptergy/allow-additional-dns-challenge-dependencies
Allow additional dns challenge dependencies
2020-11-06 09:02:35 +10:00
cb014027bb Makes sure credentials folder exist every time before saving credentials 2020-11-04 19:31:40 +01:00
32e5155783 Fixes Linting errors 2020-11-03 22:38:09 +01:00
a3159ad59e Converts tabs to spaces 2020-11-03 22:24:03 +01:00
60a40197f1 Always install additional dependencies for dns plugins 2020-11-03 21:59:18 +01:00
7d693a4271 Expands and refactors dns plugin list 2020-11-03 21:28:50 +01:00
f192748bf9 Use x-real-ip header for the real-ip module 2020-10-19 11:40:50 +10:00
96f401cba6 Merge pull request #664 from chaptergy/fixes-expiring-hosts-renewal
Adds certbot plugin installation check on startup
2020-10-19 08:50:44 +10:00
ffd2430160 Merge pull request #666 from MarceloLagos/master
Check key for RSA header otherwise use EC, and output fix.
2020-10-19 08:45:28 +10:00
190cd2d6bb Update certificate.js 2020-10-17 23:46:18 -06:00
7ba58bdbd3 Update certificate.js 2020-10-17 23:27:12 -06:00
08ab62108f Fixes eslint errors 2020-10-17 12:54:38 +02:00
1028de8158 Adds certbot plugin installation check on startup 2020-10-17 12:13:08 +02:00
301499dc52 Merge pull request #659 from jc21/develop
v2.6.1
2020-10-16 15:53:56 +10:00
5c2f13ed8e Merge branch 'master' into develop 2020-10-16 13:44:10 +10:00
e30ad81f69 Updated version 2020-10-16 13:43:13 +10:00
21f36f535f Don't spit out a ; if the preceeding value is empty 2020-10-16 13:41:08 +10:00
c14236823a Merge pull request #656 from chaptergy/fixes-custom-certificate-upload
Fixes custom certificate upload
2020-10-16 08:33:51 +10:00
551a9fe1c6 Fixes custom certificate upload 2020-10-15 14:58:05 +02:00
30 changed files with 442 additions and 422 deletions

View File

@ -1,10 +0,0 @@
{
"database": {
"engine": "mysql",
"host": "db",
"name": "npm",
"user": "npm",
"password": "npm",
"port": 3306
}
}

View File

@ -1,11 +0,0 @@
{
"database": {
"engine": "knex-native",
"knex": {
"client": "sqlite3",
"connection": {
"filename": "/data/database.sqlite"
}
}
}
}

View File

@ -1 +1 @@
2.6.0
2.7.2

View File

@ -1,7 +1,7 @@
<p align="center">
<img src="https://nginxproxymanager.com/github.png">
<br><br>
<img src="https://img.shields.io/badge/version-2.6.0-green.svg?style=for-the-badge">
<img src="https://img.shields.io/badge/version-2.7.2-green.svg?style=for-the-badge">
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge">
</a>
@ -205,6 +205,30 @@ Special thanks to the following contributors:
<br /><sub><b>Philip Mooney</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/WaterCalm">
<img src="https://avatars1.githubusercontent.com/u/23502129?s=400&v=4" width="80px;" alt=""/>
<br /><sub><b>WaterCalm</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/lebrou34">
<img src="https://avatars1.githubusercontent.com/u/16373103?s=460&v=4" width="80px;" alt=""/>
<br /><sub><b>lebrou34</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/lightglitch">
<img src="https://avatars0.githubusercontent.com/u/196953?s=460&v=4" width="80px;" alt=""/>
<br /><sub><b>Mário Franco</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/klutchell">
<img src="https://avatars3.githubusercontent.com/u/20458272?s=460&v=4" width="80px;" alt=""/>
<br /><sub><b>Kyle Harding</b></sub>
</a>
</td>
</tr>
</table>
<!-- markdownlint-enable -->

View File

@ -2,7 +2,10 @@
const logger = require('./logger').global;
function appStart () {
async function appStart () {
// Create config file db settings if environment variables have been set
await createDbConfigFromEnvironment();
const migrate = require('./migrate');
const setup = require('./setup');
const app = require('./app');
@ -39,9 +42,92 @@ function appStart () {
});
}
async function createDbConfigFromEnvironment() {
return new Promise((resolve, reject) => {
const envMysqlHost = process.env.DB_MYSQL_HOST || null;
const envMysqlPort = process.env.DB_MYSQL_PORT || null;
const envMysqlUser = process.env.DB_MYSQL_USER || null;
const envMysqlName = process.env.DB_MYSQL_NAME || null;
const envSqliteFile = process.env.DB_SQLITE_FILE || null;
if ((envMysqlHost && envMysqlPort && envMysqlUser && envMysqlName) || envSqliteFile) {
const fs = require('fs');
const filename = (process.env.NODE_CONFIG_DIR || './config') + '/' + (process.env.NODE_ENV || 'default') + '.json';
let configData = {};
try {
configData = require(filename);
} catch (err) {
// do nothing
}
if (configData.database && configData.database.engine && !configData.database.fromEnv) {
logger.info('Manual db configuration already exists, skipping config creation from environment variables');
resolve();
return;
}
if (envMysqlHost && envMysqlPort && envMysqlUser && envMysqlName) {
const newConfig = {
fromEnv: true,
engine: 'mysql',
host: envMysqlHost,
port: envMysqlPort,
user: envMysqlUser,
password: process.env.DB_MYSQL_PASSWORD,
name: envMysqlName,
};
if (JSON.stringify(configData.database) === JSON.stringify(newConfig)) {
// Config is unchanged, skip overwrite
resolve();
return;
}
logger.info('Generating MySQL db configuration from environment variables');
configData.database = newConfig;
} else {
const newConfig = {
fromEnv: true,
engine: 'knex-native',
knex: {
client: 'sqlite3',
connection: {
filename: envSqliteFile
}
}
};
if (JSON.stringify(configData.database) === JSON.stringify(newConfig)) {
// Config is unchanged, skip overwrite
resolve();
return;
}
logger.info('Generating Sqlite db configuration from environment variables');
configData.database = newConfig;
}
// Write config
fs.writeFile(filename, JSON.stringify(configData, null, 2), (err) => {
if (err) {
logger.error('Could not write db config to config file: ' + filename);
reject(err);
} else {
logger.info('Wrote db configuration to config file: ' + filename);
resolve();
}
});
} else {
resolve();
}
});
}
try {
appStart();
} catch (err) {
logger.error(err.message, err);
process.exit(1);
}

View File

@ -216,6 +216,13 @@ const internalCertificate = {
return saved_row;
});
});
}).catch(async (error) => {
// Delete the certificate from the database if it was not created successfully
await certificateModel
.query()
.deleteById(certificate.id);
throw error;
});
} else {
return certificate;
@ -608,18 +615,26 @@ const internalCertificate = {
checkPrivateKey: (private_key) => {
return tempWrite(private_key, '/tmp')
.then((filepath) => {
return utils.exec('openssl rsa -in ' + filepath + ' -check -noout')
.then((result) => {
if (!result.toLowerCase().includes('key ok')) {
throw new error.ValidationError(result);
}
fs.unlinkSync(filepath);
return true;
}).catch((err) => {
fs.unlinkSync(filepath);
throw new error.ValidationError('Certificate Key is not valid (' + err.message + ')', err);
});
return new Promise((resolve, reject) => {
const failTimeout = setTimeout(() => {
reject(new error.ValidationError('Result Validation Error: Validation timed out. This could be due to the key being passphrase-protected.'));
}, 10000);
utils
.exec('openssl pkey -in ' + filepath + ' -check -noout 2>&1 ')
.then((result) => {
clearTimeout(failTimeout);
if (!result.toLowerCase().includes('key is valid')) {
reject(new error.ValidationError('Result Validation Error: ' + result));
}
fs.unlinkSync(filepath);
resolve(true);
})
.catch((err) => {
clearTimeout(failTimeout);
fs.unlinkSync(filepath);
reject(new error.ValidationError('Certificate Key is not valid (' + err.message + ')', err));
});
});
});
},
@ -788,9 +803,9 @@ const internalCertificate = {
logger.info(`Requesting Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
const credentials_loc = '/etc/letsencrypt/credentials-' + certificate.id;
const credentials_cmd = 'echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'';
const prepare_cmd = 'pip3 install ' + dns_plugin.package_name + '==' + dns_plugin.package_version;
const credentials_loc = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
const credentials_cmd = 'mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'';
const prepare_cmd = 'pip3 install ' + dns_plugin.package_name + '==' + dns_plugin.package_version + ' ' + dns_plugin.dependencies;
// Whether the plugin has a --<name>-credentials argument
const has_config_arg = certificate.meta.dns_provider !== 'route53';
@ -818,11 +833,9 @@ const internalCertificate = {
if (certificate.meta.dns_provider === 'route53') {
main_cmd = 'AWS_CONFIG_FILE=\'' + credentials_loc + '\' ' + main_cmd;
}
const teardown_cmd = `rm '${credentials_loc}'`;
if (debug_mode) {
logger.info('Command:', `${credentials_cmd} && ${prepare_cmd} && ${main_cmd} && ${teardown_cmd}`);
logger.info('Command:', `${credentials_cmd} && ${prepare_cmd} && ${main_cmd}`);
}
return utils.exec(credentials_cmd)
@ -831,11 +844,15 @@ const internalCertificate = {
.then(() => {
return utils.exec(main_cmd)
.then(async (result) => {
await utils.exec(teardown_cmd);
logger.info(result);
return result;
});
});
}).catch(async (err) => {
// Don't fail if file does not exist
const delete_credentials_cmd = `rm -f '${credentials_loc}' || true`;
await utils.exec(delete_credentials_cmd);
throw err;
});
},
@ -922,10 +939,6 @@ const internalCertificate = {
logger.info(`Renewing Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
const credentials_loc = '/etc/letsencrypt/credentials-' + certificate.id;
const credentials_cmd = 'echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'';
const prepare_cmd = 'pip3 install ' + dns_plugin.package_name + '==' + dns_plugin.package_version;
let main_cmd =
certbot_command + ' renew --non-interactive ' +
'--cert-name "npm-' + certificate.id + '" ' +
@ -934,26 +947,18 @@ const internalCertificate = {
// Prepend the path to the credentials file as an environment variable
if (certificate.meta.dns_provider === 'route53') {
main_cmd = 'AWS_CONFIG_FILE=\'' + credentials_loc + '\' ' + main_cmd;
const credentials_loc = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
main_cmd = 'AWS_CONFIG_FILE=\'' + credentials_loc + '\' ' + main_cmd;
}
const teardown_cmd = `rm '${credentials_loc}'`;
if (debug_mode) {
logger.info('Command:', `${credentials_cmd} && ${prepare_cmd} && ${main_cmd} && ${teardown_cmd}`);
logger.info('Command:', main_cmd);
}
return utils.exec(credentials_cmd)
.then(() => {
return utils.exec(prepare_cmd)
.then(() => {
return utils.exec(main_cmd)
.then(async (result) => {
await utils.exec(teardown_cmd);
logger.info(result);
return result;
});
});
return utils.exec(main_cmd)
.then(async (result) => {
logger.info(result);
return result;
});
},
@ -965,20 +970,21 @@ const internalCertificate = {
revokeLetsEncryptSsl: (certificate, throw_errors) => {
logger.info('Revoking Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
let cmd = certbot_command + ' revoke --non-interactive ' +
const main_cmd = certbot_command + ' revoke --non-interactive ' +
'--cert-path "/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' +
'--delete-after-revoke ' +
(le_staging ? '--staging' : '');
// Don't fail command if file does not exist
const delete_credentials_cmd = `rm -f '/etc/letsencrypt/credentials/credentials-${certificate.id}' || true`;
if (debug_mode) {
logger.info('Command:', cmd);
logger.info('Command:', main_cmd + '; ' + delete_credentials_cmd);
}
return utils.exec(cmd)
.then((result) => {
if (debug_mode) {
logger.info('Command:', cmd);
}
return utils.exec(main_cmd)
.then(async (result) => {
await utils.exec(delete_credentials_cmd);
logger.info(result);
return result;
})

View File

@ -106,7 +106,7 @@ const internalHost = {
response_object.total_count += response_object.redirection_hosts.length;
}
if (promises_results[1]) {
if (promises_results[2]) {
// Dead Hosts
response_object.dead_hosts = internalHost._getHostsWithDomains(promises_results[2], domain_names);
response_object.total_count += response_object.dead_hosts.length;
@ -158,7 +158,7 @@ const internalHost = {
}
}
if (promises_results[1]) {
if (promises_results[2]) {
// Dead Hosts
if (internalHost._checkHostnameRecordsTaken(hostname, promises_results[2], ignore_type === 'dead' && ignore_id ? ignore_id : 0)) {
is_taken = true;

View File

@ -2,10 +2,13 @@ const fs = require('fs');
const NodeRSA = require('node-rsa');
const config = require('config');
const logger = require('./logger').setup;
const certificateModel = require('./models/certificate');
const userModel = require('./models/user');
const userPermissionModel = require('./models/user_permission');
const utils = require('./lib/utils');
const authModel = require('./models/auth');
const settingModel = require('./models/setting');
const dns_plugins = require('./global/certbot-dns-plugins');
const debug_mode = process.env.NODE_ENV !== 'production' || !!process.env.DEBUG;
/**
@ -155,8 +158,53 @@ const setupDefaultSettings = () => {
});
};
/**
* Installs all Certbot plugins which are required for an installed certificate
*
* @returns {Promise}
*/
const setupCertbotPlugins = () => {
return certificateModel
.query()
.where('is_deleted', 0)
.andWhere('provider', 'letsencrypt')
.then((certificates) => {
if (certificates && certificates.length) {
let plugins = [];
let promises = [];
certificates.map(function (certificate) {
if (certificate.meta && certificate.meta.dns_challenge === true) {
const dns_plugin = dns_plugins[certificate.meta.dns_provider];
const packages_to_install = `${dns_plugin.package_name}==${dns_plugin.package_version} ${dns_plugin.dependencies}`;
if (plugins.indexOf(packages_to_install) === -1) plugins.push(packages_to_install);
// Make sure credentials file exists
const credentials_loc = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
const credentials_cmd = '[ -f \'' + credentials_loc + '\' ] || { mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'; }';
promises.push(utils.exec(credentials_cmd));
}
});
if (plugins.length) {
const install_cmd = 'pip3 install ' + plugins.join(' ');
promises.push(utils.exec(install_cmd));
}
if (promises.length) {
return Promise.all(promises)
.then(() => {
logger.info('Added Certbot plugins ' + plugins.join(', '));
});
}
}
});
};
module.exports = function () {
return setupJwt()
.then(setupDefaultUser)
.then(setupDefaultSettings);
.then(setupDefaultSettings)
.then(setupCertbotPlugins);
};

View File

@ -37,7 +37,9 @@ server {
{% endfor %}deny all;
# Access checks must...
{% if access_list.satisfy %}
{{ access_list.satisfy }};
{% endif %}
{% endif %}

View File

@ -1548,9 +1548,9 @@ inherits@2.0.3:
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
version "1.3.5"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
version "1.3.8"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
inquirer@^7.0.0:
version "7.3.3"

View File

@ -34,7 +34,7 @@ EXPOSE 443
COPY docker/rootfs /
ADD backend /app
ADD frontend/dist /app/frontend
COPY global /app/global
COPY global /app/global
WORKDIR /app
RUN yarn install

View File

@ -5,11 +5,15 @@ services:
fullstack-mysql:
image: ${IMAGE}:ci-${BUILD_NUMBER}
environment:
- NODE_ENV=development
- FORCE_COLOR=1
NODE_ENV: "development"
FORCE_COLOR: 1
DB_MYSQL_HOST: "db"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: "npm"
DB_MYSQL_PASSWORD: "npm"
DB_MYSQL_NAME: "npm"
volumes:
- npm_data:/data
- ../.jenkins/config-mysql.json:/app/config/development.json
expose:
- 81
- 80
@ -20,11 +24,11 @@ services:
fullstack-sqlite:
image: ${IMAGE}:ci-${BUILD_NUMBER}
environment:
- NODE_ENV=development
- FORCE_COLOR=1
NODE_ENV: "development"
FORCE_COLOR: 1
DB_SQLITE_FILE: "/data/database.sqlite"
volumes:
- npm_data:/data
- ../.jenkins/config-sqlite.json:/app/config/development.json
expose:
- 81
- 80
@ -43,8 +47,8 @@ services:
cypress-mysql:
image: ${IMAGE}-cypress:ci-${BUILD_NUMBER}
build:
context: ../
dockerfile: test/cypress/Dockerfile
context: ../test/
dockerfile: cypress/Dockerfile
environment:
CYPRESS_baseUrl: "http://fullstack-mysql:81"
volumes:
@ -54,8 +58,8 @@ services:
cypress-sqlite:
image: ${IMAGE}-cypress:ci-${BUILD_NUMBER}
build:
context: ../
dockerfile: test/cypress/Dockerfile
context: ../test/
dockerfile: cypress/Dockerfile
environment:
CYPRESS_baseUrl: "http://fullstack-sqlite:81"
volumes:

View File

@ -14,10 +14,16 @@ services:
networks:
- nginx_proxy_manager
environment:
- NODE_ENV=development
- FORCE_COLOR=1
- DEVELOPMENT=true
#- DISABLE_IPV6=true
NODE_ENV: "development"
FORCE_COLOR: 1
DEVELOPMENT: "true"
DB_MYSQL_HOST: "db"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: "npm"
DB_MYSQL_PASSWORD: "npm"
DB_MYSQL_NAME: "npm"
# DB_SQLITE_FILE: "/data/database.sqlite"
# DISABLE_IPV6: "true"
volumes:
- npm_data:/data
- le_data:/etc/letsencrypt

View File

@ -1,196 +1,2 @@
set_real_ip_from 144.220.0.0/16;
set_real_ip_from 52.124.128.0/17;
set_real_ip_from 54.230.0.0/16;
set_real_ip_from 54.239.128.0/18;
set_real_ip_from 52.82.128.0/19;
set_real_ip_from 99.84.0.0/16;
set_real_ip_from 204.246.172.0/24;
set_real_ip_from 205.251.192.0/19;
set_real_ip_from 54.239.192.0/19;
set_real_ip_from 70.132.0.0/18;
set_real_ip_from 13.32.0.0/15;
set_real_ip_from 13.224.0.0/14;
set_real_ip_from 13.35.0.0/16;
set_real_ip_from 204.246.164.0/22;
set_real_ip_from 204.246.168.0/22;
set_real_ip_from 71.152.0.0/17;
set_real_ip_from 216.137.32.0/19;
set_real_ip_from 205.251.249.0/24;
set_real_ip_from 99.86.0.0/16;
set_real_ip_from 52.46.0.0/18;
set_real_ip_from 52.84.0.0/15;
set_real_ip_from 204.246.173.0/24;
set_real_ip_from 130.176.0.0/16;
set_real_ip_from 64.252.64.0/18;
set_real_ip_from 204.246.174.0/23;
set_real_ip_from 64.252.128.0/18;
set_real_ip_from 205.251.254.0/24;
set_real_ip_from 143.204.0.0/16;
set_real_ip_from 205.251.252.0/23;
set_real_ip_from 204.246.176.0/20;
set_real_ip_from 13.249.0.0/16;
set_real_ip_from 54.240.128.0/18;
set_real_ip_from 205.251.250.0/23;
set_real_ip_from 52.222.128.0/17;
set_real_ip_from 54.182.0.0/16;
set_real_ip_from 54.192.0.0/16;
set_real_ip_from 13.124.199.0/24;
set_real_ip_from 34.226.14.0/24;
set_real_ip_from 52.15.127.128/26;
set_real_ip_from 35.158.136.0/24;
set_real_ip_from 52.57.254.0/24;
set_real_ip_from 18.216.170.128/25;
set_real_ip_from 13.52.204.0/23;
set_real_ip_from 13.54.63.128/26;
set_real_ip_from 13.59.250.0/26;
set_real_ip_from 13.210.67.128/26;
set_real_ip_from 35.167.191.128/26;
set_real_ip_from 52.47.139.0/24;
set_real_ip_from 52.199.127.192/26;
set_real_ip_from 52.212.248.0/26;
set_real_ip_from 52.66.194.128/26;
set_real_ip_from 13.113.203.0/24;
set_real_ip_from 99.79.168.0/23;
set_real_ip_from 34.195.252.0/24;
set_real_ip_from 35.162.63.192/26;
set_real_ip_from 34.223.12.224/27;
set_real_ip_from 52.56.127.0/25;
set_real_ip_from 34.223.80.192/26;
set_real_ip_from 13.228.69.0/24;
set_real_ip_from 34.216.51.0/25;
set_real_ip_from 3.231.2.0/25;
set_real_ip_from 54.233.255.128/26;
set_real_ip_from 18.200.212.0/23;
set_real_ip_from 52.52.191.128/26;
set_real_ip_from 3.234.232.224/27;
set_real_ip_from 52.78.247.128/26;
set_real_ip_from 52.220.191.0/26;
set_real_ip_from 34.232.163.208/29;
set_real_ip_from 2600:9000:eee::/48;
set_real_ip_from 2600:9000:4000::/36;
set_real_ip_from 2600:9000:3000::/36;
set_real_ip_from 2600:9000:f000::/36;
set_real_ip_from 2600:9000:fff::/48;
set_real_ip_from 2600:9000:2000::/36;
set_real_ip_from 2600:9000:1000::/36;
set_real_ip_from 2600:9000:ddd::/48;
set_real_ip_from 2600:9000:5300::/40;
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;
# This should be left blank is it is populated programatically
# by the application backend.

View File

@ -3,4 +3,6 @@ proxy_set_header Host $host;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass $forward_scheme://$server:$port;

View File

@ -66,7 +66,7 @@ http {
# NPM generated CDN ip ranges:
include conf.d/include/ip_ranges.conf;
# always put the following 2 lines after ip subnets:
real_ip_header X-Forwarded-For;
real_ip_header X-Real-IP;
real_ip_recursive on;
# Files generated by NPM
@ -84,6 +84,9 @@ http {
stream {
# Files generated by NPM
include /data/nginx/stream/*.conf;
# Custom
include /data/nginx/custom/stream[.]conf;
}
# Custom

View File

@ -45,21 +45,7 @@ footer: MIT Licensed | Copyright © 2016-present jc21.com
- [Docker Install documentation](https://docs.docker.com/install/)
- [Docker-Compose Install documentation](https://docs.docker.com/compose/install/)
2. Create a config file for example
```json
{
"database": {
"engine": "mysql",
"host": "db",
"name": "npm",
"user": "npm",
"password": "npm",
"port": 3306
}
}
```
3. Create a docker-compose.yml file similar to this:
2. Create a docker-compose.yml file similar to this:
```yml
version: '3'
@ -70,8 +56,13 @@ services:
- '80:80'
- '81:81'
- '443:443'
environment:
DB_MYSQL_HOST: "db"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: "npm"
DB_MYSQL_PASSWORD: "npm"
DB_MYSQL_NAME: "npm"
volumes:
- ./config.json:/app/config/production.json
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
db:
@ -85,13 +76,13 @@ services:
- ./data/mysql:/var/lib/mysql
```
4. Bring up your stack
3. Bring up your stack
```bash
docker-compose up -d
```
5. Log in to the Admin UI
4. Log in to the Admin UI
When your docker container is running, connect to it on port `81` for the admin interface.
Sometimes this can take a little bit because of the entropy of keys.

View File

@ -24,6 +24,7 @@ You can add your custom configuration snippet files at `/data/nginx/custom` as f
- `/data/nginx/custom/root.conf`: Included at the very end of nginx.conf
- `/data/nginx/custom/http.conf`: Included at the end of the main http block
- `/data/nginx/custom/stream.conf`: Included at the end of the main stream block
- `/data/nginx/custom/server_proxy.conf`: Included at the end of every proxy server block
- `/data/nginx/custom/server_redirect.conf`: Included at the end of every redirection server block
- `/data/nginx/custom/server_stream.conf`: Included at the end of every stream server block

View File

@ -1,50 +1,5 @@
# Full Setup Instructions
### Configuration File
**The configuration file needs to be provided by you!**
Don't worry, this is easy to do.
The app requires a configuration file to let it know what database you're using. By default, this file is called `config.json`
Here's an example configuration for `mysql` (or mariadb) that is compatible with the docker-compose example below:
```json
{
"database": {
"engine": "mysql",
"host": "db",
"name": "npm",
"user": "npm",
"password": "npm",
"port": 3306
}
}
```
Alternatively if you would like to use a Sqlite database file:
```json
{
"database": {
"engine": "knex-native",
"knex": {
"client": "sqlite3",
"connection": {
"filename": "/data/database.sqlite"
}
}
}
}
```
Once you've created your configuration file it's easy to mount it in the docker container.
**Note:** After the first run of the application, the config file will be altered to include generated encryption keys unique to your installation. These keys
affect the login and session management of the application. If these keys change for any reason, all users will be logged out.
### MySQL Database
If you opt for the MySQL configuration you will have to provide the database server yourself. You can also use MariaDB. Here are the minimum supported versions:
@ -61,7 +16,6 @@ When using a `mariadb` database, the NPM configuration file should still use the
:::
### Running the App
Via `docker-compose`:
@ -70,7 +24,7 @@ Via `docker-compose`:
version: "3"
services:
app:
image: jc21/nginx-proxy-manager:2
image: 'jc21/nginx-proxy-manager:latest'
restart: always
ports:
# Public HTTP Port:
@ -80,11 +34,18 @@ services:
# Admin Web Port:
- '81:81'
environment:
# These are the settings to access your db
DB_MYSQL_HOST: "db"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: "npm"
DB_MYSQL_PASSWORD: "npm"
DB_MYSQL_NAME: "npm"
# If you would rather use Sqlite uncomment this
# and remove all DB_MYSQL_* lines above
# DB_SQLITE_FILE: "/data/database.sqlite"
# Uncomment this if IPv6 is not enabled on your host
# DISABLE_IPV6: 'true'
volumes:
# Make sure this config.json file exists as per instructions above:
- ./config.json:/app/config/production.json
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
depends_on:
@ -101,14 +62,14 @@ services:
- ./data/mysql:/var/lib/mysql
```
_Please note, that `DB_MYSQL_*` environment variables will take precedent over `DB_SQLITE_*` variables. So if you keep the MySQL variables, you will not be able to use Sqlite._
Then:
```bash
docker-compose up -d
```
The config file (config.json) must be present in this directory.
### Running on Raspberry PI / ARM devices
The docker images support the following architectures:
@ -146,3 +107,49 @@ Password: changeme
```
Immediately after logging in with this default user you will be asked to modify your details and change your password.
### Configuration File
::: warning
This section is meant for advanced users
:::
If you would like more control over the database settings you can define a custom config JSON file.
Here's an example for `sqlite` configuration as it is generated from the environment variables:
```json
{
"database": {
"engine": "knex-native",
"knex": {
"client": "sqlite3",
"connection": {
"filename": "/data/database.sqlite"
}
}
}
}
```
You can modify the `knex` object with your custom configuration, but note that not all knex clients might be installed in the image.
Once you've created your configuration file you can mount it to `/app/config/production.json` inside you container using:
```
[...]
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
[...]
volumes:
- ./config.json:/app/config/production.json
[...]
[...]
```
**Note:** After the first run of the application, the config file will be altered to include generated encryption keys unique to your installation.
These keys affect the login and session management of the application. If these keys change for any reason, all users will be logged out.

View File

@ -5125,9 +5125,9 @@ inherits@2.0.3:
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
ini@^1.3.5, ini@~1.3.0:
version "1.3.5"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
version "1.3.8"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
internal-ip@^4.3.0:
version "4.3.0"

View File

@ -139,7 +139,11 @@ function FileUpload(path, fd) {
xhr.onreadystatechange = function () {
if (this.readyState === XMLHttpRequest.DONE) {
if (xhr.status !== 200 && xhr.status !== 201) {
reject(new Error('Upload failed: ' + xhr.status));
try {
reject(new Error('Upload failed: ' + JSON.parse(xhr.responseText).error.message));
} catch (err) {
reject(new Error('Upload failed: ' + xhr.status));
}
} else {
resolve(xhr.responseText);
}
@ -587,7 +591,8 @@ module.exports = {
* @param {Object} data
*/
create: function (data) {
const timeout = 180000 + (data.meta.propagation_seconds ? Number(data.meta.propagation_seconds) * 1000 : 0);
const timeout = 180000 + (data && data.meta && data.meta.propagation_seconds ? Number(data.meta.propagation_seconds) * 1000 : 0);
return fetch('post', 'nginx/certificates', data, {timeout});
},

View File

@ -16,6 +16,8 @@ module.exports = Mn.View.extend({
events: {
'click @ui.save': function (e) {
e.preventDefault();
this.ui.save.addClass('btn-loading');
this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
App.Api.Nginx.Certificates.delete(this.model.get('id'))
.then(() => {
@ -25,6 +27,7 @@ module.exports = Mn.View.extend({
.catch(err => {
alert(err.message);
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
this.ui.save.removeClass('btn-loading');
});
}
}

View File

@ -4,17 +4,14 @@
<button type="button" class="close cancel non-loader-content" aria-label="Close" data-dismiss="modal">&nbsp;</button>
</div>
<div class="modal-body">
<div class="alert alert-danger mb-0 rounded-0" id="le-error-info" role="alert"></div>
<div class="text-center loader-content">
<div class="loader mx-auto my-6"></div>
<p><%- i18n('ssl', 'obtaining-certificate-info') %></p>
<p><%- i18n('ssl', 'processing-info') %></p>
</div>
<form class="non-loader-content">
<div class="row">
<% if (provider === 'letsencrypt') { %>
<div class="col-sm-12 col-md-12">
<div class="alert alert-danger" id="le-error-info" role="alert"></div>
</div>
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label"><%- i18n('all-hosts', 'domain-names') %> <span class="form-required">*</span></label>
@ -132,6 +129,9 @@
</div>
<% } else if (provider === 'other') { %>
<!-- Other -->
<div class="col-sm-12 col-md-12">
<div class="text-blue mb-4"><i class="fe fe-alert-triangle"></i> <%= i18n('ssl', 'passphrase-protection-support-info') %></div>
</div>
<div class="col-sm-12 col-md-12">
<div class="form-group">
<label class="form-label"><%- i18n('str', 'name') %> <span class="form-required">*</span></label>

View File

@ -76,47 +76,44 @@ module.exports = Mn.View.extend({
return;
}
let view = this;
let data = this.ui.form.serializeJSON();
data.provider = this.model.get('provider');
let domain_err = false;
if (!data.meta.dns_challenge) {
data.domain_names.split(',').map(function (name) {
if (name.match(/\*/im)) {
domain_err = true;
}
});
}
if (domain_err) {
alert(i18n('ssl', 'no-wildcard-without-dns'));
return;
}
// Manipulate
if (typeof data.meta === 'undefined') data.meta = {};
data.meta.letsencrypt_agree = data.meta.letsencrypt_agree == 1;
data.meta.dns_challenge = data.meta.dns_challenge == 1;
if(!data.meta.dns_challenge){
data.meta.dns_provider = undefined;
data.meta.dns_provider_credentials = undefined;
data.meta.propagation_seconds = undefined;
} else {
if(data.meta.propagation_seconds === '') data.meta.propagation_seconds = undefined;
}
if (typeof data.domain_names === 'string' && data.domain_names) {
data.domain_names = data.domain_names.split(',');
}
let ssl_files = [];
// check files are attached
if (this.model.get('provider') === 'other' && !this.model.hasSslFiles()) {
if (data.provider === 'letsencrypt') {
if (typeof data.meta === 'undefined') data.meta = {};
let domain_err = false;
if (!data.meta.dns_challenge) {
data.domain_names.split(',').map(function (name) {
if (name.match(/\*/im)) {
domain_err = true;
}
});
}
if (domain_err) {
alert(i18n('ssl', 'no-wildcard-without-dns'));
return;
}
// Manipulate
data.meta.letsencrypt_agree = data.meta.letsencrypt_agree == 1;
data.meta.dns_challenge = data.meta.dns_challenge == 1;
if(!data.meta.dns_challenge){
data.meta.dns_provider = undefined;
data.meta.dns_provider_credentials = undefined;
data.meta.propagation_seconds = undefined;
} else {
if(data.meta.propagation_seconds === '') data.meta.propagation_seconds = undefined;
}
if (typeof data.domain_names === 'string' && data.domain_names) {
data.domain_names = data.domain_names.split(',');
}
} else if (data.provider === 'other' && !this.model.hasSslFiles()) {
// check files are attached
if (!this.ui.other_certificate[0].files.length || !this.ui.other_certificate[0].files[0].size) {
alert('Certificate file is not attached');
return;
@ -153,14 +150,14 @@ module.exports = Mn.View.extend({
// compile file data
let form_data = new FormData();
if (view.model.get('provider') && ssl_files.length) {
if (data.provider === 'other' && ssl_files.length) {
ssl_files.map(function (file) {
form_data.append(file.name, file.file);
});
}
new Promise(resolve => {
if (view.model.get('provider') === 'other') {
if (data.provider === 'other') {
resolve(App.Api.Nginx.Certificates.validate(form_data));
} else {
resolve();
@ -170,13 +167,13 @@ module.exports = Mn.View.extend({
return App.Api.Nginx.Certificates.create(data);
})
.then(result => {
view.model.set(result);
this.model.set(result);
// Now upload the certs if we need to
if (view.model.get('provider') === 'other') {
return App.Api.Nginx.Certificates.upload(view.model.get('id'), form_data)
if (data.provider === 'other') {
return App.Api.Nginx.Certificates.upload(this.model.get('id'), form_data)
.then(result => {
view.model.set('meta', _.assign({}, view.model.get('meta'), result));
this.model.set('meta', _.assign({}, this.model.get('meta'), result));
});
}
})
@ -187,7 +184,7 @@ module.exports = Mn.View.extend({
})
.catch(err => {
let more_info = '';
if(err.code === 500 && err.debug){
if (err.code === 500 && err.debug) {
try{
more_info = JSON.parse(err.debug).debug.stack.join("\n");
} catch(e) {}

View File

@ -109,10 +109,11 @@
"please-choose": "Please Choose...",
"credentials-file-content": "Credentials File Content",
"credentials-file-content-info": "This plugin requires a configuration file containing an API token or other credentials to your provider",
"stored-as-plaintext-info": "This data will be stored as plaintext in the database!",
"stored-as-plaintext-info": "This data will be stored as plaintext in the database and in a file!",
"propagation-seconds": "Propagation Seconds",
"propagation-seconds-info": "Leave empty to use the plugins default value. Number of seconds to wait for DNS propagation.",
"obtaining-certificate-info": "Obtaining certificate... This might take a few minutes."
"processing-info": "Processing... This might take a few minutes.",
"passphrase-protection-support-info": "Key files protected with a passphrase are not supported."
},
"proxy-hosts": {
"title": "Proxy Hosts",

View File

@ -10,9 +10,9 @@
* display_name: "Name displayed to the user",
* package_name: "Package name in PyPi repo",
* package_version: "Package version in PyPi repo",
* dependencies: "Additional dependencies, space separated (as you would pass it to pip install)",
* credentials: `Template of the credentials file`,
* full_plugin_name: "The full plugin name as used in the commandline with certbot, including prefixes, e.g. 'certbot-dns-njalla:dns-njalla'",
* credentials_file: Whether the plugin has a credentials file
* },
* ...
* }
@ -20,10 +20,21 @@
*/
module.exports = {
aliyun: {
display_name: 'Aliyun',
package_name: 'certbot-dns-aliyun',
package_version: '0.38.1',
dependencies: '',
credentials: `certbot_dns_aliyun:dns_aliyun_access_key = 12345678
certbot_dns_aliyun:dns_aliyun_access_key_secret = 1234567890abcdef1234567890abcdef`,
full_plugin_name: 'certbot-dns-aliyun:dns-aliyun',
},
//####################################################//
cloudflare: {
display_name: 'Cloudflare',
package_name: 'certbot-dns-cloudflare',
package_version: '1.8.0',
dependencies: 'cloudflare',
credentials: `# Cloudflare API token
dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567`,
full_plugin_name: 'dns-cloudflare',
@ -33,6 +44,7 @@ dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567`,
display_name: 'CloudXNS',
package_name: 'certbot-dns-cloudxns',
package_version: '1.8.0',
dependencies: '',
credentials: `dns_cloudxns_api_key = 1234567890abcdef1234567890abcdef
dns_cloudxns_secret_key = 1122334455667788`,
full_plugin_name: 'dns-cloudxns',
@ -42,6 +54,7 @@ dns_cloudxns_secret_key = 1122334455667788`,
display_name: 'Core Networks',
package_name: 'certbot-dns-corenetworks',
package_version: '0.1.4',
dependencies: '',
credentials: `certbot_dns_corenetworks:dns_corenetworks_username = asaHB12r
certbot_dns_corenetworks:dns_corenetworks_password = secure_password`,
full_plugin_name: 'certbot-dns-corenetworks:dns-corenetworks',
@ -51,6 +64,7 @@ certbot_dns_corenetworks:dns_corenetworks_password = secure_password`,
display_name: 'cPanel',
package_name: 'certbot-dns-cpanel',
package_version: '0.2.2',
dependencies: '',
credentials: `certbot_dns_cpanel:cpanel_url = https://cpanel.example.com:2083
certbot_dns_cpanel:cpanel_username = user
certbot_dns_cpanel:cpanel_password = hunter2`,
@ -61,6 +75,7 @@ certbot_dns_cpanel:cpanel_password = hunter2`,
display_name: 'DigitalOcean',
package_name: 'certbot-dns-digitalocean',
package_version: '1.8.0',
dependencies: '',
credentials: 'dns_digitalocean_token = 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff',
full_plugin_name: 'dns-digitalocean',
},
@ -69,6 +84,7 @@ certbot_dns_cpanel:cpanel_password = hunter2`,
display_name: 'DirectAdmin',
package_name: 'certbot-dns-directadmin',
package_version: '0.0.20',
dependencies: '',
credentials: `directadmin_url = https://my.directadminserver.com:2222
directadmin_username = username
directadmin_password = aSuperStrongPassword`,
@ -79,6 +95,7 @@ directadmin_password = aSuperStrongPassword`,
display_name: 'DNSimple',
package_name: 'certbot-dns-dnsimple',
package_version: '1.8.0',
dependencies: '',
credentials: 'dns_dnsimple_token = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw',
full_plugin_name: 'dns-dnsimple',
},
@ -87,6 +104,7 @@ directadmin_password = aSuperStrongPassword`,
display_name: 'DNS Made Easy',
package_name: 'certbot-dns-dnsmadeeasy',
package_version: '1.8.0',
dependencies: '',
credentials: `dns_dnsmadeeasy_api_key = 1c1a3c91-4770-4ce7-96f4-54c0eb0e457a
dns_dnsmadeeasy_secret_key = c9b5625f-9834-4ff8-baba-4ed5f32cae55`,
full_plugin_name: 'dns-dnsmadeeasy',
@ -96,18 +114,29 @@ dns_dnsmadeeasy_secret_key = c9b5625f-9834-4ff8-baba-4ed5f32cae55`,
display_name: 'DNSPod',
package_name: 'certbot-dns-dnspod',
package_version: '0.1.0',
dependencies: '',
credentials: `certbot_dns_dnspod:dns_dnspod_email = "DNSPOD-API-REQUIRES-A-VALID-EMAIL"
certbot_dns_dnspod:dns_dnspod_api_token = "DNSPOD-API-TOKEN"`,
full_plugin_name: 'certbot-dns-dnspod:dns-dnspod',
},
//####################################################//
gandi: {
display_name: 'Gandi Live DNS',
package_name: 'certbot_plugin_gandi',
package_version: '1.2.5',
dependencies: '',
credentials: 'certbot_plugin_gandi:dns_api_key = APIKEY',
full_plugin_name: 'certbot-plugin-gandi:dns',
},
//####################################################//
google: {
display_name: 'Google',
package_name: 'certbot-dns-google',
package_version: '1.8.0',
dependencies: '',
credentials: `{
"type": "service_account",
...
"type": "service_account",
...
}`,
full_plugin_name: 'dns-google',
},
@ -116,6 +145,7 @@ certbot_dns_dnspod:dns_dnspod_api_token = "DNSPOD-API-TOKEN"`,
display_name: 'Hetzner',
package_name: 'certbot-dns-hetzner',
package_version: '1.0.4',
dependencies: '',
credentials: 'certbot_dns_hetzner:dns_hetzner_api_token = 0123456789abcdef0123456789abcdef',
full_plugin_name: 'certbot-dns-hetzner:dns-hetzner',
},
@ -124,6 +154,7 @@ certbot_dns_dnspod:dns_dnspod_api_token = "DNSPOD-API-TOKEN"`,
display_name: 'INWX',
package_name: 'certbot-dns-inwx',
package_version: '2.1.2',
dependencies: '',
credentials: `certbot_dns_inwx:dns_inwx_url = https://api.domrobot.com/xmlrpc/
certbot_dns_inwx:dns_inwx_username = your_username
certbot_dns_inwx:dns_inwx_password = your_password
@ -135,6 +166,7 @@ certbot_dns_inwx:dns_inwx_shared_secret = your_shared_secret optional`,
display_name: 'ISPConfig',
package_name: 'certbot-dns-ispconfig',
package_version: '0.2.0',
dependencies: '',
credentials: `certbot_dns_ispconfig:dns_ispconfig_username = myremoteuser
certbot_dns_ispconfig:dns_ispconfig_password = verysecureremoteuserpassword
certbot_dns_ispconfig:dns_ispconfig_endpoint = https://localhost:8080`,
@ -145,6 +177,7 @@ certbot_dns_ispconfig:dns_ispconfig_endpoint = https://localhost:8080`,
display_name: 'Isset',
package_name: 'certbot-dns-isset',
package_version: '0.0.3',
dependencies: '',
credentials: `certbot_dns_isset:dns_isset_endpoint="https://customer.isset.net/api"
certbot_dns_isset:dns_isset_token="<token>"`,
full_plugin_name: 'certbot-dns-isset:dns-isset',
@ -154,6 +187,7 @@ certbot_dns_isset:dns_isset_token="<token>"`,
display_name: 'Linode',
package_name: 'certbot-dns-linode',
package_version: '1.8.0',
dependencies: '',
credentials: `dns_linode_key = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ64
dns_linode_version = [<blank>|3|4]`,
full_plugin_name: 'dns-linode',
@ -163,6 +197,7 @@ dns_linode_version = [<blank>|3|4]`,
display_name: 'LuaDNS',
package_name: 'certbot-dns-luadns',
package_version: '1.8.0',
dependencies: '',
credentials: `dns_luadns_email = user@example.com
dns_luadns_token = 0123456789abcdef0123456789abcdef`,
full_plugin_name: 'dns-luadns',
@ -172,6 +207,7 @@ dns_luadns_token = 0123456789abcdef0123456789abcdef`,
display_name: 'netcup',
package_name: 'certbot-dns-netcup',
package_version: '1.0.0',
dependencies: '',
credentials: `dns_netcup_customer_id = 123456
dns_netcup_api_key = 0123456789abcdef0123456789abcdef01234567
dns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123`,
@ -181,7 +217,8 @@ dns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123`,
njalla: {
display_name: 'Njalla',
package_name: 'certbot-dns-njalla',
package_version: '0.0.4',
package_version: '1.0.0',
dependencies: '',
credentials: 'certbot_dns_njalla:dns_njalla_token = 0123456789abcdef0123456789abcdef01234567',
full_plugin_name: 'certbot-dns-njalla:dns-njalla',
},
@ -190,6 +227,7 @@ dns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123`,
display_name: 'NS1',
package_name: 'certbot-dns-nsone',
package_version: '1.8.0',
dependencies: '',
credentials: 'dns_nsone_api_key = MDAwMDAwMDAwMDAwMDAw',
full_plugin_name: 'dns-nsone',
},
@ -198,6 +236,7 @@ dns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123`,
display_name: 'OVH',
package_name: 'certbot-dns-ovh',
package_version: '1.8.0',
dependencies: '',
credentials: `dns_ovh_endpoint = ovh-eu
dns_ovh_application_key = MDAwMDAwMDAwMDAw
dns_ovh_application_secret = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
@ -209,6 +248,7 @@ dns_ovh_consumer_key = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw`,
display_name: 'PowerDNS',
package_name: 'certbot-dns-powerdns',
package_version: '0.2.0',
dependencies: '',
credentials: `certbot_dns_powerdns:dns_powerdns_api_url = https://api.mypowerdns.example.org
certbot_dns_powerdns:dns_powerdns_api_key = AbCbASsd!@34`,
full_plugin_name: 'certbot-dns-powerdns:dns-powerdns',
@ -218,6 +258,7 @@ certbot_dns_powerdns:dns_powerdns_api_key = AbCbASsd!@34`,
display_name: 'RFC 2136',
package_name: 'certbot-dns-rfc2136',
package_version: '1.8.0',
dependencies: '',
credentials: `# Target DNS server
dns_rfc2136_server = 192.0.2.1
# Target DNS port
@ -235,6 +276,7 @@ dns_rfc2136_algorithm = HMAC-SHA512`,
display_name: 'Route 53 (Amazon)',
package_name: 'certbot-dns-route53',
package_version: '1.8.0',
dependencies: '',
credentials: `[default]
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`,
@ -245,6 +287,7 @@ aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`,
display_name: 'Vultr',
package_name: 'certbot-dns-vultr',
package_version: '1.0.3',
dependencies: '',
credentials: 'certbot_dns_vultr:dns_vultr_key = YOUR_VULTR_API_KEY',
full_plugin_name: 'certbot-dns-vultr:dns-vultr',
},

1
test/.dockerignore Normal file
View File

@ -0,0 +1 @@
node_modules

View File

@ -1,6 +1,11 @@
FROM cypress/included:4.12.1
FROM cypress/included:5.6.0
COPY --chown=1000 ./test /test
COPY --chown=1000 ./ /test
# mkcert
ENV MKCERT=1.4.2
RUN wget -O /usr/bin/mkcert "https://github.com/FiloSottile/mkcert/releases/download/v${MKCERT}/mkcert-v${MKCERT}-linux-amd64" \
&& chmod +x /usr/bin/mkcert
WORKDIR /test
RUN yarn install

View File

@ -7,7 +7,7 @@
"@jc21/cypress-swagger-validation": "^0.0.9",
"@jc21/restler": "^3.4.0",
"chalk": "^4.1.0",
"cypress": "^4.12.1",
"cypress": "^5.6.0",
"cypress-multi-reporters": "^1.4.0",
"cypress-plugin-retries": "^1.5.2",
"eslint": "^7.6.0",

View File

@ -1293,9 +1293,9 @@ inherits@2, inherits@^2.0.3, inherits@~2.0.3:
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
ini@^1.3.5:
version "1.3.5"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
version "1.3.8"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
is-arguments@^1.0.4:
version "1.0.4"