Compare commits
103 Commits
v2.9.6
...
ssl-passth
Author | SHA1 | Date | |
---|---|---|---|
70163a66fb | |||
6e82161987 | |||
f650137c84 | |||
02d3093d88 | |||
ab026e5e18 | |||
725ba83606 | |||
281906c0b5 | |||
8ed121f43d | |||
81a9cab2b3 | |||
8d98a417c5 | |||
6fa81b179b | |||
9e169fbb42 | |||
27f84f880a | |||
5a2548c89d | |||
5b1f0cead1 | |||
0d9c941b4e | |||
8865aa9c8c | |||
6d8c4218f1 | |||
c134a43337 | |||
780759dc27 | |||
85128f08f3 | |||
d2f8c1e5f1 | |||
9c88b9c1e9 | |||
13fd2ce4e2 | |||
9979f516d6 | |||
39a5cd2d6e | |||
784516283f | |||
ce503232c3 | |||
f2edf9130f | |||
413ab50fc4 | |||
c1880bd3ff | |||
0f0a672275 | |||
babc5b7a38 | |||
b96c996a45 | |||
fb8f2c2f9a | |||
6794937391 | |||
f022e84979 | |||
fd5ac952cc | |||
07f60e5c77 | |||
628b8a7e1f | |||
30a442807d | |||
1626c8edd1 | |||
ca6561bf6c | |||
273a81471d | |||
8b07a67133 | |||
32089ea272 | |||
658acd147c | |||
ca3370a6ac | |||
c4e2557de2 | |||
6f2b4fdf86 | |||
f302ff71c9 | |||
fee87a44d6 | |||
8944609b63 | |||
be87c45f27 | |||
1b1807c79a | |||
a8f4699816 | |||
ac3df6dd77 | |||
5c67908460 | |||
7b67ef3015 | |||
e5a3b5ee2f | |||
5e9ff4d2bf | |||
daa71764b6 | |||
6a6c2ef192 | |||
320315956d | |||
4f10d129c2 | |||
62eb3fcd85 | |||
ab40e4e2cf | |||
0bb9450642 | |||
a6e15532b9 | |||
9a89a8a77e | |||
fe3675dc7a | |||
5c9acc2bff | |||
c94e937a50 | |||
3e4e10e644 | |||
ba7bb57ca2 | |||
14c125150a | |||
053701a702 | |||
3fc3e43042 | |||
b0dc68d7d4 | |||
e895baaeb4 | |||
c47f6fdb21 | |||
9e188e441a | |||
f6efcdf9f9 | |||
b1ceda3af4 | |||
cd3a0684d0 | |||
f25e54c6cb | |||
66f86cf497 | |||
d260edc547 | |||
ba1e6fa984 | |||
6b59f36213 | |||
1894960762 | |||
83c5c55f32 | |||
fb8c0b9a48 | |||
d34691152c | |||
cea80b482e | |||
c460a8fa5c | |||
5f852437fe | |||
6c1ae77a2a | |||
a56d976947 | |||
346b9b4b79 | |||
a5b8087dc5 | |||
7aa078e025 | |||
389fd158ad |
53
README.md
53
README.md
@ -1,7 +1,7 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://nginxproxymanager.com/github.png">
|
<img src="https://nginxproxymanager.com/github.png">
|
||||||
<br><br>
|
<br><br>
|
||||||
<img src="https://img.shields.io/badge/version-2.9.6-green.svg?style=for-the-badge">
|
<img src="https://img.shields.io/badge/version-2.9.9-green.svg?style=for-the-badge">
|
||||||
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
|
<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">
|
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge">
|
||||||
</a>
|
</a>
|
||||||
@ -17,7 +17,6 @@
|
|||||||
<a href="https://reddit.com/r/nginxproxymanager">
|
<a href="https://reddit.com/r/nginxproxymanager">
|
||||||
<img alt="Reddit" src="https://img.shields.io/reddit/subreddit-subscribers/nginxproxymanager?label=Reddit%20Community&style=for-the-badge">
|
<img alt="Reddit" src="https://img.shields.io/reddit/subreddit-subscribers/nginxproxymanager?label=Reddit%20Community&style=for-the-badge">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
This project comes as a pre-built docker image that enables you to easily forward to your websites
|
This project comes as a pre-built docker image that enables you to easily forward to your websites
|
||||||
@ -458,6 +457,56 @@ Special thanks to the following contributors:
|
|||||||
<br /><sub><b>Fuechslein</b></sub>
|
<br /><sub><b>Fuechslein</b></sub>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/nightah">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/3339418?v=4" width="80" alt=""/>
|
||||||
|
<br /><sub><b>Amir Zarrinkafsh</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/gabbe">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/156397?v=4" width="80" alt=""/>
|
||||||
|
<br /><sub><b>gabbe</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/bmbvenom">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/20530371?v=4" width="80" alt=""/>
|
||||||
|
<br /><sub><b>bmbvenom</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/FMeinicke">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/42121639?v=4" width="80" alt=""/>
|
||||||
|
<br /><sub><b>Florian Meinicke</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/ssrahul96">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/15570570?v=4" width="80" alt=""/>
|
||||||
|
<br /><sub><b>Rahul Somasundaram</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/BjoernAkAManf">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/833043?v=4" width="80" alt=""/>
|
||||||
|
<br /><sub><b>Björn Heinrichs</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/realJoshByrnes">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/204185?v=4" width="80" alt=""/>
|
||||||
|
<br /><sub><b>Josh Byrnes</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="https://github.com/bergi9">
|
||||||
|
<img src="https://avatars.githubusercontent.com/u/5556750?v=4" width="80" alt=""/>
|
||||||
|
<br /><sub><b>bergi9</b></sub>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<!-- markdownlint-enable -->
|
<!-- markdownlint-enable -->
|
||||||
|
@ -74,12 +74,10 @@ app.use(function (err, req, res, next) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Not every error is worth logging - but this is good for now until it gets annoying.
|
// Not every error is worth logging - but this is good for now until it gets annoying.
|
||||||
if (typeof err.stack !== 'undefined' && err.stack) {
|
if (process.env.NODE_ENV === 'development' || process.env.DEBUG) {
|
||||||
if (process.env.NODE_ENV === 'development') {
|
log.debug(err);
|
||||||
log.debug(err.stack);
|
} else if (typeof err.stack !== 'undefined' && err.stack && (typeof err.public == 'undefined' || !err.public)) {
|
||||||
} else if (typeof err.public == 'undefined' || !err.public) {
|
log.warn(err.message);
|
||||||
log.warn(err.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
|
@ -118,7 +118,6 @@ const internalAccessList = {
|
|||||||
// Sanity check that something crazy hasn't happened
|
// Sanity check that something crazy hasn't happened
|
||||||
throw new error.InternalValidationError('Access List could not be updated, IDs do not match: ' + row.id + ' !== ' + data.id);
|
throw new error.InternalValidationError('Access List could not be updated, IDs do not match: ' + row.id + ' !== ' + data.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// patch name if specified
|
// patch name if specified
|
||||||
@ -205,6 +204,7 @@ const internalAccessList = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.then(internalNginx.reload)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
|
@ -13,6 +13,8 @@ const internalHost = require('./host');
|
|||||||
const letsencryptStaging = process.env.NODE_ENV !== 'production';
|
const letsencryptStaging = process.env.NODE_ENV !== 'production';
|
||||||
const letsencryptConfig = '/etc/letsencrypt.ini';
|
const letsencryptConfig = '/etc/letsencrypt.ini';
|
||||||
const certbotCommand = 'certbot';
|
const certbotCommand = 'certbot';
|
||||||
|
const archiver = require('archiver');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
function omissions() {
|
function omissions() {
|
||||||
return ['is_deleted'];
|
return ['is_deleted'];
|
||||||
@ -335,6 +337,71 @@ const internalCertificate = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Number} data.id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
download: (access, data) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
access.can('certificates:get', data)
|
||||||
|
.then(() => {
|
||||||
|
return internalCertificate.get(access, data);
|
||||||
|
})
|
||||||
|
.then((certificate) => {
|
||||||
|
if (certificate.provider === 'letsencrypt') {
|
||||||
|
const zipDirectory = '/etc/letsencrypt/live/npm-' + data.id;
|
||||||
|
|
||||||
|
if (!fs.existsSync(zipDirectory)) {
|
||||||
|
throw new error.ItemNotFoundError('Certificate ' + certificate.nice_name + ' does not exists');
|
||||||
|
}
|
||||||
|
|
||||||
|
let certFiles = fs.readdirSync(zipDirectory)
|
||||||
|
.filter((fn) => fn.endsWith('.pem'))
|
||||||
|
.map((fn) => fs.realpathSync(path.join(zipDirectory, fn)));
|
||||||
|
const downloadName = 'npm-' + data.id + '-' + `${Date.now()}.zip`;
|
||||||
|
const opName = '/tmp/' + downloadName;
|
||||||
|
internalCertificate.zipFiles(certFiles, opName)
|
||||||
|
.then(() => {
|
||||||
|
logger.debug('zip completed : ', opName);
|
||||||
|
const resp = {
|
||||||
|
fileName: opName
|
||||||
|
};
|
||||||
|
resolve(resp);
|
||||||
|
}).catch((err) => reject(err));
|
||||||
|
} else {
|
||||||
|
throw new error.ValidationError('Only Let\'sEncrypt certificates can be downloaded');
|
||||||
|
}
|
||||||
|
}).catch((err) => reject(err));
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {String} source
|
||||||
|
* @param {String} out
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
zipFiles(source, out) {
|
||||||
|
const archive = archiver('zip', { zlib: { level: 9 } });
|
||||||
|
const stream = fs.createWriteStream(out);
|
||||||
|
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
source
|
||||||
|
.map((fl) => {
|
||||||
|
let fileName = path.basename(fl);
|
||||||
|
logger.debug(fl, 'added to certificate zip');
|
||||||
|
archive.file(fl, { name: fileName });
|
||||||
|
});
|
||||||
|
archive
|
||||||
|
.on('error', (err) => reject(err))
|
||||||
|
.pipe(stream);
|
||||||
|
|
||||||
|
stream.on('close', () => resolve());
|
||||||
|
archive.finalize();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
@ -758,6 +825,7 @@ const internalCertificate = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Request a certificate using the http challenge
|
||||||
* @param {Object} certificate the certificate row
|
* @param {Object} certificate the certificate row
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
@ -768,6 +836,7 @@ const internalCertificate = {
|
|||||||
'--config "' + letsencryptConfig + '" ' +
|
'--config "' + letsencryptConfig + '" ' +
|
||||||
'--cert-name "npm-' + certificate.id + '" ' +
|
'--cert-name "npm-' + certificate.id + '" ' +
|
||||||
'--agree-tos ' +
|
'--agree-tos ' +
|
||||||
|
'--authenticator webroot ' +
|
||||||
'--email "' + certificate.meta.letsencrypt_email + '" ' +
|
'--email "' + certificate.meta.letsencrypt_email + '" ' +
|
||||||
'--preferred-challenges "dns,http" ' +
|
'--preferred-challenges "dns,http" ' +
|
||||||
'--domains "' + certificate.domain_names.join(',') + '" ' +
|
'--domains "' + certificate.domain_names.join(',') + '" ' +
|
||||||
@ -800,7 +869,7 @@ const internalCertificate = {
|
|||||||
|
|
||||||
const credentialsLocation = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
|
const credentialsLocation = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
|
||||||
const credentialsCmd = 'mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
|
const credentialsCmd = 'mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
|
||||||
const prepareCmd = 'pip install ' + dns_plugin.package_name + '==' + dns_plugin.package_version + ' ' + dns_plugin.dependencies;
|
const prepareCmd = 'pip install ' + dns_plugin.package_name + (dns_plugin.version_requirement || '') + ' ' + dns_plugin.dependencies;
|
||||||
|
|
||||||
// Whether the plugin has a --<name>-credentials argument
|
// Whether the plugin has a --<name>-credentials argument
|
||||||
const hasConfigArg = certificate.meta.dns_provider !== 'route53';
|
const hasConfigArg = certificate.meta.dns_provider !== 'route53';
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const proxyHostModel = require('../models/proxy_host');
|
const proxyHostModel = require('../models/proxy_host');
|
||||||
const redirectionHostModel = require('../models/redirection_host');
|
const redirectionHostModel = require('../models/redirection_host');
|
||||||
const deadHostModel = require('../models/dead_host');
|
const deadHostModel = require('../models/dead_host');
|
||||||
|
const sslPassthroughHostModel = require('../models/ssl_passthrough_host');
|
||||||
|
|
||||||
const internalHost = {
|
const internalHost = {
|
||||||
|
|
||||||
@ -81,6 +82,9 @@ const internalHost = {
|
|||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0),
|
.where('is_deleted', 0),
|
||||||
deadHostModel
|
deadHostModel
|
||||||
|
.query()
|
||||||
|
.where('is_deleted', 0),
|
||||||
|
sslPassthroughHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
];
|
];
|
||||||
@ -112,6 +116,12 @@ const internalHost = {
|
|||||||
response_object.total_count += response_object.dead_hosts.length;
|
response_object.total_count += response_object.dead_hosts.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (promises_results[3]) {
|
||||||
|
// SSL Passthrough Hosts
|
||||||
|
response_object.ssl_passthrough_hosts = internalHost._getHostsWithDomains(promises_results[3], domain_names);
|
||||||
|
response_object.total_count += response_object.ssl_passthrough_hosts.length;
|
||||||
|
}
|
||||||
|
|
||||||
return response_object;
|
return response_object;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -137,7 +147,11 @@ const internalHost = {
|
|||||||
deadHostModel
|
deadHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.andWhere('domain_names', 'like', '%' + hostname + '%')
|
.andWhere('domain_names', 'like', '%' + hostname + '%'),
|
||||||
|
sslPassthroughHostModel
|
||||||
|
.query()
|
||||||
|
.where('is_deleted', 0)
|
||||||
|
.andWhere('domain_name', '=', hostname),
|
||||||
];
|
];
|
||||||
|
|
||||||
return Promise.all(promises)
|
return Promise.all(promises)
|
||||||
@ -165,6 +179,13 @@ const internalHost = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (promises_results[3]) {
|
||||||
|
// SSL Passthrough Hosts
|
||||||
|
if (internalHost._checkHostnameRecordsTaken(hostname, promises_results[3], ignore_type === 'ssl_passthrough' && ignore_id ? ignore_id : 0)) {
|
||||||
|
is_taken = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hostname: hostname,
|
hostname: hostname,
|
||||||
is_taken: is_taken
|
is_taken: is_taken
|
||||||
@ -185,14 +206,21 @@ const internalHost = {
|
|||||||
|
|
||||||
if (existing_rows && existing_rows.length) {
|
if (existing_rows && existing_rows.length) {
|
||||||
existing_rows.map(function (existing_row) {
|
existing_rows.map(function (existing_row) {
|
||||||
existing_row.domain_names.map(function (existing_hostname) {
|
|
||||||
|
function checkHostname(existing_hostname) {
|
||||||
// Does this domain match?
|
// Does this domain match?
|
||||||
if (existing_hostname.toLowerCase() === hostname.toLowerCase()) {
|
if (existing_hostname.toLowerCase() === hostname.toLowerCase()) {
|
||||||
if (!ignore_id || ignore_id !== existing_row.id) {
|
if (!ignore_id || ignore_id !== existing_row.id) {
|
||||||
is_taken = true;
|
is_taken = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (existing_row.domain_names) {
|
||||||
|
existing_row.domain_names.map(checkHostname);
|
||||||
|
} else if (existing_row.domain_name) {
|
||||||
|
checkHostname(existing_row.domain_name);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const logger = require('../logger').nginx;
|
const logger = require('../logger').nginx;
|
||||||
const utils = require('../lib/utils');
|
const utils = require('../lib/utils');
|
||||||
const error = require('../lib/error');
|
const error = require('../lib/error');
|
||||||
const { Liquid } = require('liquidjs');
|
const { Liquid } = require('liquidjs');
|
||||||
const debug_mode = process.env.NODE_ENV !== 'production' || !!process.env.DEBUG;
|
const passthroughHostModel = require('../models/ssl_passthrough_host');
|
||||||
|
const debug_mode = process.env.NODE_ENV !== 'production' || !!process.env.DEBUG;
|
||||||
|
|
||||||
const internalNginx = {
|
const internalNginx = {
|
||||||
|
|
||||||
@ -23,7 +24,8 @@ const internalNginx = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
configure: (model, host_type, host) => {
|
configure: (model, host_type, host) => {
|
||||||
let combined_meta = {};
|
let combined_meta = {};
|
||||||
|
const sslPassthroughEnabled = internalNginx.sslPassthroughEnabled();
|
||||||
|
|
||||||
return internalNginx.test()
|
return internalNginx.test()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@ -32,7 +34,25 @@ const internalNginx = {
|
|||||||
return internalNginx.deleteConfig(host_type, host); // Don't throw errors, as the file may not exist at all
|
return internalNginx.deleteConfig(host_type, host); // Don't throw errors, as the file may not exist at all
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalNginx.generateConfig(host_type, host);
|
if (host_type === 'ssl_passthrough_host' && !sslPassthroughEnabled){
|
||||||
|
// ssl passthrough is disabled
|
||||||
|
const meta = {
|
||||||
|
nginx_online: false,
|
||||||
|
nginx_err: 'SSL passthrough is not enabled in environment'
|
||||||
|
};
|
||||||
|
|
||||||
|
return passthroughHostModel
|
||||||
|
.query()
|
||||||
|
.where('is_deleted', 0)
|
||||||
|
.andWhere('enabled', 1)
|
||||||
|
.patch({
|
||||||
|
meta
|
||||||
|
}).then(() => {
|
||||||
|
return internalNginx.deleteConfig('ssl_passthrough_host', host, false);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return internalNginx.generateConfig(host_type, host);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Test nginx again and update meta with result
|
// Test nginx again and update meta with result
|
||||||
@ -44,12 +64,27 @@ const internalNginx = {
|
|||||||
nginx_err: null
|
nginx_err: null
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (host_type === 'ssl_passthrough_host'){
|
||||||
|
// If passthrough is disabled we have already marked the hosts as offline
|
||||||
|
if (sslPassthroughEnabled) {
|
||||||
|
return passthroughHostModel
|
||||||
|
.query()
|
||||||
|
.where('is_deleted', 0)
|
||||||
|
.andWhere('enabled', 1)
|
||||||
|
.patch({
|
||||||
|
meta: combined_meta
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
return model
|
return model
|
||||||
.query()
|
.query()
|
||||||
.where('id', host.id)
|
.where('id', host.id)
|
||||||
.patch({
|
.patch({
|
||||||
meta: combined_meta
|
meta: combined_meta
|
||||||
});
|
});
|
||||||
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
// Remove the error_log line because it's a docker-ism false positive that doesn't need to be reported.
|
// Remove the error_log line because it's a docker-ism false positive that doesn't need to be reported.
|
||||||
@ -74,6 +109,18 @@ const internalNginx = {
|
|||||||
nginx_err: valid_lines.join('\n')
|
nginx_err: valid_lines.join('\n')
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (host_type === 'ssl_passthrough_host'){
|
||||||
|
return passthroughHostModel
|
||||||
|
.query()
|
||||||
|
.where('is_deleted', 0)
|
||||||
|
.andWhere('enabled', 1)
|
||||||
|
.patch({
|
||||||
|
meta: combined_meta
|
||||||
|
}).then(() => {
|
||||||
|
return internalNginx.deleteConfig('ssl_passthrough_host', host, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return model
|
return model
|
||||||
.query()
|
.query()
|
||||||
.where('id', host.id)
|
.where('id', host.id)
|
||||||
@ -125,6 +172,8 @@ const internalNginx = {
|
|||||||
|
|
||||||
if (host_type === 'default') {
|
if (host_type === 'default') {
|
||||||
return '/data/nginx/default_host/site.conf';
|
return '/data/nginx/default_host/site.conf';
|
||||||
|
} else if (host_type === 'ssl_passthrough_host') {
|
||||||
|
return '/data/nginx/ssl_passthrough_host/hosts.conf';
|
||||||
}
|
}
|
||||||
|
|
||||||
return '/data/nginx/' + host_type + '/' + host_id + '.conf';
|
return '/data/nginx/' + host_type + '/' + host_id + '.conf';
|
||||||
@ -186,7 +235,7 @@ const internalNginx = {
|
|||||||
* @param {Object} host
|
* @param {Object} host
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
generateConfig: (host_type, host) => {
|
generateConfig: async (host_type, host) => {
|
||||||
host_type = host_type.replace(new RegExp('-', 'g'), '_');
|
host_type = host_type.replace(new RegExp('-', 'g'), '_');
|
||||||
|
|
||||||
if (debug_mode) {
|
if (debug_mode) {
|
||||||
@ -199,72 +248,87 @@ const internalNginx = {
|
|||||||
root: __dirname + '/../templates/'
|
root: __dirname + '/../templates/'
|
||||||
});
|
});
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
let template = null;
|
||||||
let template = null;
|
let filename = internalNginx.getConfigName(host_type, host.id);
|
||||||
let filename = internalNginx.getConfigName(host_type, host.id);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
template = fs.readFileSync(__dirname + '/../templates/' + host_type + '.conf', {encoding: 'utf8'});
|
template = fs.readFileSync(__dirname + '/../templates/' + host_type + '.conf', {encoding: 'utf8'});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(new error.ConfigurationError(err.message));
|
throw new error.ConfigurationError(err.message);
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let locationsPromise;
|
let locationsPromise;
|
||||||
let origLocations;
|
let origLocations;
|
||||||
|
|
||||||
// Manipulate the data a bit before sending it to the template
|
|
||||||
if (host_type !== 'default') {
|
|
||||||
host.use_default_location = true;
|
|
||||||
if (typeof host.advanced_config !== 'undefined' && host.advanced_config) {
|
|
||||||
host.use_default_location = !internalNginx.advancedConfigHasDefaultLocation(host.advanced_config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (host.locations) {
|
|
||||||
//logger.info ('host.locations = ' + JSON.stringify(host.locations, null, 2));
|
|
||||||
origLocations = [].concat(host.locations);
|
|
||||||
locationsPromise = internalNginx.renderLocations(host).then((renderedLocations) => {
|
|
||||||
host.locations = renderedLocations;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Allow someone who is using / custom location path to use it, and skip the default / location
|
|
||||||
_.map(host.locations, (location) => {
|
|
||||||
if (location.path === '/') {
|
|
||||||
host.use_default_location = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
// Manipulate the data a bit before sending it to the template
|
||||||
|
if (host_type === 'ssl_passthrough_host') {
|
||||||
|
if (internalNginx.sslPassthroughEnabled()){
|
||||||
|
const allHosts = await passthroughHostModel
|
||||||
|
.query()
|
||||||
|
.where('is_deleted', 0)
|
||||||
|
.groupBy('id')
|
||||||
|
.omit(['is_deleted']);
|
||||||
|
host = {
|
||||||
|
all_passthrough_hosts: allHosts.map((host) => {
|
||||||
|
// Replace dots in domain
|
||||||
|
host.forwarding_host = internalNginx.addIpv6Brackets(host.forwarding_host);
|
||||||
|
return host;
|
||||||
|
}),
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
locationsPromise = Promise.resolve();
|
internalNginx.deleteConfig(host_type, host, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (host_type !== 'default') {
|
||||||
|
host.use_default_location = true;
|
||||||
|
if (typeof host.advanced_config !== 'undefined' && host.advanced_config) {
|
||||||
|
host.use_default_location = !internalNginx.advancedConfigHasDefaultLocation(host.advanced_config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Set the IPv6 setting for the host
|
if (host.locations) {
|
||||||
host.ipv6 = internalNginx.ipv6Enabled();
|
//logger.info ('host.locations = ' + JSON.stringify(host.locations, null, 2));
|
||||||
|
origLocations = [].concat(host.locations);
|
||||||
locationsPromise.then(() => {
|
locationsPromise = internalNginx.renderLocations(host).then((renderedLocations) => {
|
||||||
renderEngine
|
host.locations = renderedLocations;
|
||||||
.parseAndRender(template, host)
|
|
||||||
.then((config_text) => {
|
|
||||||
fs.writeFileSync(filename, config_text, {encoding: 'utf8'});
|
|
||||||
|
|
||||||
if (debug_mode) {
|
|
||||||
logger.success('Wrote config:', filename, config_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore locations array
|
|
||||||
host.locations = origLocations;
|
|
||||||
|
|
||||||
resolve(true);
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
if (debug_mode) {
|
|
||||||
logger.warn('Could not write ' + filename + ':', err.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
reject(new error.ConfigurationError(err.message));
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Allow someone who is using / custom location path to use it, and skip the default / location
|
||||||
|
_.map(host.locations, (location) => {
|
||||||
|
if (location.path === '/') {
|
||||||
|
host.use_default_location = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
locationsPromise = Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the IPv6 setting for the host
|
||||||
|
host.ipv6 = internalNginx.ipv6Enabled();
|
||||||
|
|
||||||
|
return locationsPromise.then(() => {
|
||||||
|
renderEngine
|
||||||
|
.parseAndRender(template, host)
|
||||||
|
.then((config_text) => {
|
||||||
|
fs.writeFileSync(filename, config_text, {encoding: 'utf8'});
|
||||||
|
|
||||||
|
if (debug_mode) {
|
||||||
|
logger.success('Wrote config:', filename, config_text);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore locations array
|
||||||
|
host.locations = origLocations;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
if (debug_mode) {
|
||||||
|
logger.warn('Could not write ' + filename + ':', err.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new error.ConfigurationError(err.message);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -429,6 +493,33 @@ const internalNginx = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
sslPassthroughEnabled: function () {
|
||||||
|
if (typeof process.env.ENABLE_SSL_PASSTHROUGH !== 'undefined') {
|
||||||
|
const enabled = process.env.ENABLE_SSL_PASSTHROUGH.toLowerCase();
|
||||||
|
return (enabled === 'on' || enabled === 'true' || enabled === '1' || enabled === 'yes');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to add brackets to an IP if it is IPv6
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
addIpv6Brackets: function (ip) {
|
||||||
|
// Only run check if ipv6 is enabled
|
||||||
|
if (internalNginx.ipv6Enabled()) {
|
||||||
|
const ipv6Regex = /^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$/gi;
|
||||||
|
if (ipv6Regex.test(ip)){
|
||||||
|
return `[${ip}]`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ip;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
365
backend/internal/ssl-passthrough-host.js
Normal file
365
backend/internal/ssl-passthrough-host.js
Normal file
@ -0,0 +1,365 @@
|
|||||||
|
const _ = require('lodash');
|
||||||
|
const error = require('../lib/error');
|
||||||
|
const passthroughHostModel = require('../models/ssl_passthrough_host');
|
||||||
|
const internalHost = require('./host');
|
||||||
|
const internalNginx = require('./nginx');
|
||||||
|
const internalAuditLog = require('./audit-log');
|
||||||
|
|
||||||
|
function omissions () {
|
||||||
|
return ['is_deleted'];
|
||||||
|
}
|
||||||
|
|
||||||
|
const internalPassthroughHost = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
create: (access, data) => {
|
||||||
|
return access.can('ssl_passthrough_hosts:create', data)
|
||||||
|
.then(() => {
|
||||||
|
// Get the domain name and check it against existing records
|
||||||
|
return internalHost.isHostnameTaken(data.domain_name)
|
||||||
|
.then((result) => {
|
||||||
|
if (result.is_taken) {
|
||||||
|
throw new error.ValidationError(result.hostname + ' is already in use');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).then((/*access_data*/) => {
|
||||||
|
data.owner_user_id = access.token.getUserId(1);
|
||||||
|
|
||||||
|
if (typeof data.meta === 'undefined') {
|
||||||
|
data.meta = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return passthroughHostModel
|
||||||
|
.query()
|
||||||
|
.omit(omissions())
|
||||||
|
.insertAndFetch(data);
|
||||||
|
})
|
||||||
|
.then((row) => {
|
||||||
|
// Configure nginx
|
||||||
|
return internalNginx.configure(passthroughHostModel, 'ssl_passthrough_host', {})
|
||||||
|
.then(() => {
|
||||||
|
return internalPassthroughHost.get(access, {id: row.id, expand: ['owner']});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then((row) => {
|
||||||
|
// Add to audit log
|
||||||
|
return internalAuditLog.add(access, {
|
||||||
|
action: 'created',
|
||||||
|
object_type: 'ssl-passthrough-host',
|
||||||
|
object_id: row.id,
|
||||||
|
meta: data
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return row;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Number} data.id
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
update: (access, data) => {
|
||||||
|
return access.can('ssl_passthrough_hosts:update', data.id)
|
||||||
|
.then((/*access_data*/) => {
|
||||||
|
// Get the domain name and check it against existing records
|
||||||
|
if (typeof data.domain_name !== 'undefined') {
|
||||||
|
return internalHost.isHostnameTaken(data.domain_name, 'ssl_passthrough', data.id)
|
||||||
|
.then((result) => {
|
||||||
|
if (result.is_taken) {
|
||||||
|
throw new error.ValidationError(result.hostname + ' is already in use');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}).then((/*access_data*/) => {
|
||||||
|
return internalPassthroughHost.get(access, {id: data.id});
|
||||||
|
})
|
||||||
|
.then((row) => {
|
||||||
|
if (row.id !== data.id) {
|
||||||
|
// Sanity check that something crazy hasn't happened
|
||||||
|
throw new error.InternalValidationError('SSL Passthrough Host could not be updated, IDs do not match: ' + row.id + ' !== ' + data.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return passthroughHostModel
|
||||||
|
.query()
|
||||||
|
.omit(omissions())
|
||||||
|
.patchAndFetchById(row.id, data)
|
||||||
|
.then(() => {
|
||||||
|
return internalNginx.configure(passthroughHostModel, 'ssl_passthrough_host', {})
|
||||||
|
.then(() => {
|
||||||
|
return internalPassthroughHost.get(access, {id: row.id, expand: ['owner']});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then((saved_row) => {
|
||||||
|
// Add to audit log
|
||||||
|
return internalAuditLog.add(access, {
|
||||||
|
action: 'updated',
|
||||||
|
object_type: 'ssl-passthrough-host',
|
||||||
|
object_id: row.id,
|
||||||
|
meta: data
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return _.omit(saved_row, omissions());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Number} data.id
|
||||||
|
* @param {Array} [data.expand]
|
||||||
|
* @param {Array} [data.omit]
|
||||||
|
* @return {Promise}
|
||||||
|
*/
|
||||||
|
get: (access, data) => {
|
||||||
|
if (typeof data === 'undefined') {
|
||||||
|
data = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return access.can('ssl_passthrough_hosts:get', data.id)
|
||||||
|
.then((access_data) => {
|
||||||
|
let query = passthroughHostModel
|
||||||
|
.query()
|
||||||
|
.where('is_deleted', 0)
|
||||||
|
.andWhere('id', data.id)
|
||||||
|
.allowEager('[owner]')
|
||||||
|
.first();
|
||||||
|
|
||||||
|
if (access_data.permission_visibility !== 'all') {
|
||||||
|
query.andWhere('owner_user_id', access.token.getUserId(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom omissions
|
||||||
|
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
||||||
|
query.omit(data.omit);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
||||||
|
query.eager('[' + data.expand.join(', ') + ']');
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
})
|
||||||
|
.then((row) => {
|
||||||
|
if (row) {
|
||||||
|
return _.omit(row, omissions());
|
||||||
|
} else {
|
||||||
|
throw new error.ItemNotFoundError(data.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Number} data.id
|
||||||
|
* @param {String} [data.reason]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
delete: (access, data) => {
|
||||||
|
return access.can('ssl_passthrough_hosts:delete', data.id)
|
||||||
|
.then(() => {
|
||||||
|
return internalPassthroughHost.get(access, {id: data.id});
|
||||||
|
})
|
||||||
|
.then((row) => {
|
||||||
|
if (!row) {
|
||||||
|
throw new error.ItemNotFoundError(data.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return passthroughHostModel
|
||||||
|
.query()
|
||||||
|
.where('id', row.id)
|
||||||
|
.patch({
|
||||||
|
is_deleted: 1
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Update Nginx Config
|
||||||
|
return internalNginx.configure(passthroughHostModel, 'ssl_passthrough_host', {})
|
||||||
|
.then(() => {
|
||||||
|
return internalNginx.reload();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Add to audit log
|
||||||
|
return internalAuditLog.add(access, {
|
||||||
|
action: 'deleted',
|
||||||
|
object_type: 'ssl-passthrough-host',
|
||||||
|
object_id: row.id,
|
||||||
|
meta: _.omit(row, omissions())
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Number} data.id
|
||||||
|
* @param {String} [data.reason]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
enable: (access, data) => {
|
||||||
|
return access.can('ssl_passthrough_hosts:update', data.id)
|
||||||
|
.then(() => {
|
||||||
|
return internalPassthroughHost.get(access, {
|
||||||
|
id: data.id,
|
||||||
|
expand: ['owner']
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then((row) => {
|
||||||
|
if (!row) {
|
||||||
|
throw new error.ItemNotFoundError(data.id);
|
||||||
|
} else if (row.enabled) {
|
||||||
|
throw new error.ValidationError('Host is already enabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
row.enabled = 1;
|
||||||
|
|
||||||
|
return passthroughHostModel
|
||||||
|
.query()
|
||||||
|
.where('id', row.id)
|
||||||
|
.patch({
|
||||||
|
enabled: 1
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Configure nginx
|
||||||
|
return internalNginx.configure(passthroughHostModel, 'ssl_passthrough_host', {});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Add to audit log
|
||||||
|
return internalAuditLog.add(access, {
|
||||||
|
action: 'enabled',
|
||||||
|
object_type: 'ssl-passthrough-host',
|
||||||
|
object_id: row.id,
|
||||||
|
meta: _.omit(row, omissions())
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Number} data.id
|
||||||
|
* @param {String} [data.reason]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
disable: (access, data) => {
|
||||||
|
return access.can('ssl_passthrough_hosts:update', data.id)
|
||||||
|
.then(() => {
|
||||||
|
return internalPassthroughHost.get(access, {id: data.id});
|
||||||
|
})
|
||||||
|
.then((row) => {
|
||||||
|
if (!row) {
|
||||||
|
throw new error.ItemNotFoundError(data.id);
|
||||||
|
} else if (!row.enabled) {
|
||||||
|
throw new error.ValidationError('Host is already disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
row.enabled = 0;
|
||||||
|
|
||||||
|
return passthroughHostModel
|
||||||
|
.query()
|
||||||
|
.where('id', row.id)
|
||||||
|
.patch({
|
||||||
|
enabled: 0
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Update Nginx Config
|
||||||
|
return internalNginx.configure(passthroughHostModel, 'ssl_passthrough_host', {})
|
||||||
|
.then(() => {
|
||||||
|
return internalNginx.reload();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
// Add to audit log
|
||||||
|
return internalAuditLog.add(access, {
|
||||||
|
action: 'disabled',
|
||||||
|
object_type: 'ssl-passthrough-host',
|
||||||
|
object_id: row.id,
|
||||||
|
meta: _.omit(row, omissions())
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All SSL Passthrough Hosts
|
||||||
|
*
|
||||||
|
* @param {Access} access
|
||||||
|
* @param {Array} [expand]
|
||||||
|
* @param {String} [search_query]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getAll: (access, expand, search_query) => {
|
||||||
|
return access.can('ssl_passthrough_hosts:list')
|
||||||
|
.then((access_data) => {
|
||||||
|
let query = passthroughHostModel
|
||||||
|
.query()
|
||||||
|
.where('is_deleted', 0)
|
||||||
|
.groupBy('id')
|
||||||
|
.omit(['is_deleted'])
|
||||||
|
.allowEager('[owner]')
|
||||||
|
.orderBy('domain_name', 'ASC');
|
||||||
|
|
||||||
|
if (access_data.permission_visibility !== 'all') {
|
||||||
|
query.andWhere('owner_user_id', access.token.getUserId(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Query is used for searching
|
||||||
|
if (typeof search_query === 'string') {
|
||||||
|
query.where(function () {
|
||||||
|
this.where('domain_name', 'like', '%' + search_query + '%');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof expand !== 'undefined' && expand !== null) {
|
||||||
|
query.eager('[' + expand.join(', ') + ']');
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report use
|
||||||
|
*
|
||||||
|
* @param {Number} user_id
|
||||||
|
* @param {String} visibility
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getCount: (user_id, visibility) => {
|
||||||
|
let query = passthroughHostModel
|
||||||
|
.query()
|
||||||
|
.count('id as count')
|
||||||
|
.where('is_deleted', 0);
|
||||||
|
|
||||||
|
if (visibility !== 'all') {
|
||||||
|
query.andWhere('owner_user_id', user_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.first()
|
||||||
|
.then((row) => {
|
||||||
|
return parseInt(row.count, 10);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = internalPassthroughHost;
|
@ -62,14 +62,15 @@ const internalUser = {
|
|||||||
return userPermissionModel
|
return userPermissionModel
|
||||||
.query()
|
.query()
|
||||||
.insert({
|
.insert({
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
visibility: is_admin ? 'all' : 'user',
|
visibility: is_admin ? 'all' : 'user',
|
||||||
proxy_hosts: 'manage',
|
proxy_hosts: 'manage',
|
||||||
redirection_hosts: 'manage',
|
redirection_hosts: 'manage',
|
||||||
dead_hosts: 'manage',
|
dead_hosts: 'manage',
|
||||||
streams: 'manage',
|
ssl_passthrough_hosts: 'manage',
|
||||||
access_lists: 'manage',
|
streams: 'manage',
|
||||||
certificates: 'manage'
|
access_lists: 'manage',
|
||||||
|
certificates: 'manage'
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalUser.get(access, {id: user.id, expand: ['permissions']});
|
return internalUser.get(access, {id: user.id, expand: ['permissions']});
|
||||||
|
23
backend/lib/access/ssl_passthrough_hosts-create.json
Normal file
23
backend/lib/access/ssl_passthrough_hosts-create.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "roles#/definitions/admin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": ["permission_ssl_passthrough_hosts", "roles"],
|
||||||
|
"properties": {
|
||||||
|
"permission_ssl_passthrough_hosts": {
|
||||||
|
"$ref": "perms#/definitions/manage"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["user"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
23
backend/lib/access/ssl_passthrough_hosts-delete.json
Normal file
23
backend/lib/access/ssl_passthrough_hosts-delete.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "roles#/definitions/admin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": ["permission_ssl_passthrough_hosts", "roles"],
|
||||||
|
"properties": {
|
||||||
|
"permission_ssl_passthrough_hosts": {
|
||||||
|
"$ref": "perms#/definitions/manage"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["user"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
23
backend/lib/access/ssl_passthrough_hosts-get.json
Normal file
23
backend/lib/access/ssl_passthrough_hosts-get.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "roles#/definitions/admin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": ["permission_ssl_passthrough_hosts", "roles"],
|
||||||
|
"properties": {
|
||||||
|
"permission_ssl_passthrough_hosts": {
|
||||||
|
"$ref": "perms#/definitions/view"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["user"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
23
backend/lib/access/ssl_passthrough_hosts-list.json
Normal file
23
backend/lib/access/ssl_passthrough_hosts-list.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "roles#/definitions/admin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": ["permission_ssl_passthrough_hosts", "roles"],
|
||||||
|
"properties": {
|
||||||
|
"permission_ssl_passthrough_hosts": {
|
||||||
|
"$ref": "perms#/definitions/view"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["user"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
23
backend/lib/access/ssl_passthrough_hosts-update.json
Normal file
23
backend/lib/access/ssl_passthrough_hosts-update.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "roles#/definitions/admin"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"required": ["permission_ssl_passthrough_hosts", "roles"],
|
||||||
|
"properties": {
|
||||||
|
"permission_ssl_passthrough_hosts": {
|
||||||
|
"$ref": "perms#/definitions/manage"
|
||||||
|
},
|
||||||
|
"roles": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["user"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
40
backend/migrations/20210423103500_stream_domain.js
Normal file
40
backend/migrations/20210423103500_stream_domain.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
const migrate_name = 'stream_domain';
|
||||||
|
const logger = require('../logger').migrate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate
|
||||||
|
*
|
||||||
|
* @see http://knexjs.org/#Schema
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.up = function (knex/*, Promise*/) {
|
||||||
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
|
return knex.schema.table('stream', (table) => {
|
||||||
|
table.renameColumn('forward_ip', 'forwarding_host');
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
logger.info('[' + migrate_name + '] stream Table altered');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo Migrate
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.down = function (knex/*, Promise*/) {
|
||||||
|
logger.info('[' + migrate_name + '] Migrating Down...');
|
||||||
|
|
||||||
|
return knex.schema.table('stream', (table) => {
|
||||||
|
table.renameColumn('forwarding_host', 'forward_ip');
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
logger.info('[' + migrate_name + '] stream Table altered');
|
||||||
|
});
|
||||||
|
};
|
85
backend/migrations/20211010141200_ssl_passthrough_host.js
Normal file
85
backend/migrations/20211010141200_ssl_passthrough_host.js
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
const migrate_name = 'ssl_passthrough_host';
|
||||||
|
const logger = require('../logger').migrate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate
|
||||||
|
*
|
||||||
|
* @see http://knexjs.org/#Schema
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.up = async function (knex/*, Promise*/) {
|
||||||
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
|
await knex.schema.createTable('ssl_passthrough_host', (table) => {
|
||||||
|
table.increments().primary();
|
||||||
|
table.dateTime('created_on').notNull();
|
||||||
|
table.dateTime('modified_on').notNull();
|
||||||
|
table.integer('owner_user_id').notNull().unsigned();
|
||||||
|
table.integer('is_deleted').notNull().unsigned().defaultTo(0);
|
||||||
|
table.string('domain_name').notNull();
|
||||||
|
table.string('forwarding_host').notNull();
|
||||||
|
table.integer('forwarding_port').notNull().unsigned();
|
||||||
|
table.integer('enabled').notNull().unsigned().defaultTo(1);
|
||||||
|
table.json('meta').notNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
logger.info('[' + migrate_name + '] Table created');
|
||||||
|
|
||||||
|
// Remove unique constraint so name can be used for new table
|
||||||
|
await knex.schema.alterTable('user_permission', (table) => {
|
||||||
|
table.dropUnique('user_id');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.renameTable('user_permission', 'user_permission_old');
|
||||||
|
|
||||||
|
// We need to recreate the table since sqlite does not support altering columns
|
||||||
|
await knex.schema.createTable('user_permission', (table) => {
|
||||||
|
table.increments().primary();
|
||||||
|
table.dateTime('created_on').notNull();
|
||||||
|
table.dateTime('modified_on').notNull();
|
||||||
|
table.integer('user_id').notNull().unsigned();
|
||||||
|
table.string('visibility').notNull();
|
||||||
|
table.string('proxy_hosts').notNull();
|
||||||
|
table.string('redirection_hosts').notNull();
|
||||||
|
table.string('dead_hosts').notNull();
|
||||||
|
table.string('streams').notNull();
|
||||||
|
table.string('ssl_passthrough_hosts').notNull();
|
||||||
|
table.string('access_lists').notNull();
|
||||||
|
table.string('certificates').notNull();
|
||||||
|
table.unique('user_id');
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex('user_permission_old').select('*', 'streams as ssl_passthrough_hosts').then((data) => {
|
||||||
|
if (data.length) {
|
||||||
|
return knex('user_permission').insert(data);
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex.schema.dropTableIfExists('user_permission_old');
|
||||||
|
|
||||||
|
logger.info('[' + migrate_name + '] permissions updated');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo Migrate
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.down = function (knex/*, Promise*/) {
|
||||||
|
logger.info('[' + migrate_name + '] Migrating Down...');
|
||||||
|
|
||||||
|
return knex.schema.dropTable('stream').then(() => {
|
||||||
|
return knex.schema.table('user_permission', (table) => {
|
||||||
|
table.dropColumn('ssl_passthrough_hosts');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
logger.info('[' + migrate_name + '] Table altered and permissions updated');
|
||||||
|
});
|
||||||
|
};
|
56
backend/models/ssl_passthrough_host.js
Normal file
56
backend/models/ssl_passthrough_host.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
// Objection Docs:
|
||||||
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
|
const db = require('../db');
|
||||||
|
const Model = require('objection').Model;
|
||||||
|
const User = require('./user');
|
||||||
|
const now = require('./now_helper');
|
||||||
|
|
||||||
|
Model.knex(db);
|
||||||
|
|
||||||
|
class SslPassthrougHost extends Model {
|
||||||
|
$beforeInsert () {
|
||||||
|
this.created_on = now();
|
||||||
|
this.modified_on = now();
|
||||||
|
|
||||||
|
// Default for meta
|
||||||
|
if (typeof this.meta === 'undefined') {
|
||||||
|
this.meta = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$beforeUpdate () {
|
||||||
|
this.modified_on = now();
|
||||||
|
}
|
||||||
|
|
||||||
|
static get name () {
|
||||||
|
return 'SslPassthrougHost';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get tableName () {
|
||||||
|
return 'ssl_passthrough_host';
|
||||||
|
}
|
||||||
|
|
||||||
|
static get jsonAttributes () {
|
||||||
|
return ['meta'];
|
||||||
|
}
|
||||||
|
|
||||||
|
static get relationMappings () {
|
||||||
|
return {
|
||||||
|
owner: {
|
||||||
|
relation: Model.HasOneRelation,
|
||||||
|
modelClass: User,
|
||||||
|
join: {
|
||||||
|
from: 'ssl_passthrough_host.owner_user_id',
|
||||||
|
to: 'user.id'
|
||||||
|
},
|
||||||
|
modify: function (qb) {
|
||||||
|
qb.where('user.is_deleted', 0);
|
||||||
|
qb.omit(['id', 'created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = SslPassthrougHost;
|
@ -5,6 +5,7 @@
|
|||||||
"main": "js/index.js",
|
"main": "js/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^6.12.0",
|
"ajv": "^6.12.0",
|
||||||
|
"archiver": "^5.3.0",
|
||||||
"batchflow": "^0.4.0",
|
"batchflow": "^0.4.0",
|
||||||
"bcrypt": "^5.0.0",
|
"bcrypt": "^5.0.0",
|
||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
@ -24,7 +25,7 @@
|
|||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
"node-rsa": "^1.0.8",
|
"node-rsa": "^1.0.8",
|
||||||
"nodemon": "^2.0.2",
|
"nodemon": "^2.0.2",
|
||||||
"objection": "^2.1.3",
|
"objection": "^2.2.16",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"pg": "^7.12.1",
|
"pg": "^7.12.1",
|
||||||
"restler": "^3.4.0",
|
"restler": "^3.4.0",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const pjson = require('../../package.json');
|
const pjson = require('../../package.json');
|
||||||
const error = require('../../lib/error');
|
const error = require('../../lib/error');
|
||||||
|
const internalNginx = require('../../internal/nginx');
|
||||||
|
|
||||||
let router = express.Router({
|
let router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
@ -34,10 +35,18 @@ router.use('/settings', require('./settings'));
|
|||||||
router.use('/nginx/proxy-hosts', require('./nginx/proxy_hosts'));
|
router.use('/nginx/proxy-hosts', require('./nginx/proxy_hosts'));
|
||||||
router.use('/nginx/redirection-hosts', require('./nginx/redirection_hosts'));
|
router.use('/nginx/redirection-hosts', require('./nginx/redirection_hosts'));
|
||||||
router.use('/nginx/dead-hosts', require('./nginx/dead_hosts'));
|
router.use('/nginx/dead-hosts', require('./nginx/dead_hosts'));
|
||||||
|
router.use('/nginx/ssl-passthrough-hosts', require('./nginx/ssl_passthrough_hosts'));
|
||||||
router.use('/nginx/streams', require('./nginx/streams'));
|
router.use('/nginx/streams', require('./nginx/streams'));
|
||||||
router.use('/nginx/access-lists', require('./nginx/access_lists'));
|
router.use('/nginx/access-lists', require('./nginx/access_lists'));
|
||||||
router.use('/nginx/certificates', require('./nginx/certificates'));
|
router.use('/nginx/certificates', require('./nginx/certificates'));
|
||||||
|
|
||||||
|
router.get('/ssl-passthrough-enabled', (req, res/*, next*/) => {
|
||||||
|
res.status(200).send({
|
||||||
|
status: 'OK',
|
||||||
|
ssl_passthrough_enabled: internalNginx.sslPassthroughEnabled()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API 404 for all other routes
|
* API 404 for all other routes
|
||||||
*
|
*
|
||||||
|
@ -209,6 +209,35 @@ router
|
|||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download LE Certs
|
||||||
|
*
|
||||||
|
* /api/nginx/certificates/123/download
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:certificate_id/download')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/nginx/certificates/123/download
|
||||||
|
*
|
||||||
|
* Renew certificate
|
||||||
|
*/
|
||||||
|
.get((req, res, next) => {
|
||||||
|
internalCertificate.download(res.locals.access, {
|
||||||
|
id: parseInt(req.params.certificate_id, 10)
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
res.status(200)
|
||||||
|
.download(result.fileName);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate Certs before saving
|
* Validate Certs before saving
|
||||||
*
|
*
|
||||||
|
196
backend/routes/api/nginx/ssl_passthrough_hosts.js
Normal file
196
backend/routes/api/nginx/ssl_passthrough_hosts.js
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
const express = require('express');
|
||||||
|
const validator = require('../../../lib/validator');
|
||||||
|
const jwtdecode = require('../../../lib/express/jwt-decode');
|
||||||
|
const internalSslPassthrough = require('../../../internal/ssl-passthrough-host');
|
||||||
|
const apiValidator = require('../../../lib/validator/api');
|
||||||
|
|
||||||
|
let router = express.Router({
|
||||||
|
caseSensitive: true,
|
||||||
|
strict: true,
|
||||||
|
mergeParams: true
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* /api/nginx/ssl-passthrough-hosts
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/nginx/ssl-passthrough-hosts
|
||||||
|
*
|
||||||
|
* Retrieve all ssl passthrough hosts
|
||||||
|
*/
|
||||||
|
.get((req, res, next) => {
|
||||||
|
validator({
|
||||||
|
additionalProperties: false,
|
||||||
|
properties: {
|
||||||
|
expand: {
|
||||||
|
$ref: 'definitions#/definitions/expand'
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
$ref: 'definitions#/definitions/query'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null),
|
||||||
|
query: (typeof req.query.query === 'string' ? req.query.query : null)
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
return internalSslPassthrough.getAll(res.locals.access, data.expand, data.query);
|
||||||
|
})
|
||||||
|
.then((rows) => {
|
||||||
|
res.status(200)
|
||||||
|
.send(rows);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/nginx/ssl-passthrough-hosts
|
||||||
|
*
|
||||||
|
* Create a new ssl passthrough host
|
||||||
|
*/
|
||||||
|
.post((req, res, next) => {
|
||||||
|
apiValidator({$ref: 'endpoints/ssl-passthrough-hosts#/links/1/schema'}, req.body)
|
||||||
|
.then((payload) => {
|
||||||
|
return internalSslPassthrough.create(res.locals.access, payload);
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
res.status(201)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specific ssl passthrough host
|
||||||
|
*
|
||||||
|
* /api/nginx/ssl-passthrough-hosts/123
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:host_id')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/nginx/ssl-passthrough-hosts/123
|
||||||
|
*
|
||||||
|
* Retrieve a specific ssl passthrough host
|
||||||
|
*/
|
||||||
|
.get((req, res, next) => {
|
||||||
|
validator({
|
||||||
|
required: ['host_id'],
|
||||||
|
additionalProperties: false,
|
||||||
|
properties: {
|
||||||
|
host_id: {
|
||||||
|
$ref: 'definitions#/definitions/id'
|
||||||
|
},
|
||||||
|
expand: {
|
||||||
|
$ref: 'definitions#/definitions/expand'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
host_id: req.params.host_id,
|
||||||
|
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null)
|
||||||
|
})
|
||||||
|
.then((data) => {
|
||||||
|
return internalSslPassthrough.get(res.locals.access, {
|
||||||
|
id: parseInt(data.host_id, 10),
|
||||||
|
expand: data.expand
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then((row) => {
|
||||||
|
res.status(200)
|
||||||
|
.send(row);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PUT /api/nginx/ssl-passthrough-hosts/123
|
||||||
|
*
|
||||||
|
* Update an existing ssl passthrough host
|
||||||
|
*/
|
||||||
|
.put((req, res, next) => {
|
||||||
|
apiValidator({$ref: 'endpoints/ssl-passthrough-hosts#/links/2/schema'}, req.body)
|
||||||
|
.then((payload) => {
|
||||||
|
payload.id = parseInt(req.params.host_id, 10);
|
||||||
|
return internalSslPassthrough.update(res.locals.access, payload);
|
||||||
|
})
|
||||||
|
.then((result) => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DELETE /api/nginx/ssl-passthrough-hosts/123
|
||||||
|
*
|
||||||
|
* Delete an ssl passthrough host
|
||||||
|
*/
|
||||||
|
.delete((req, res, next) => {
|
||||||
|
internalSslPassthrough.delete(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
||||||
|
.then((result) => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable ssl passthrough host
|
||||||
|
*
|
||||||
|
* /api/nginx/ssl-passthrough-hosts/123/enable
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:host_id/enable')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/nginx/ssl-passthrough-hosts/123/enable
|
||||||
|
*/
|
||||||
|
.post((req, res, next) => {
|
||||||
|
internalSslPassthrough.enable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
||||||
|
.then((result) => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable ssl passthrough host
|
||||||
|
*
|
||||||
|
* /api/nginx/ssl-passthrough-hosts/123/disable
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/:host_id/disable')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* POST /api/nginx/ssl-passthrough-hosts/123/disable
|
||||||
|
*/
|
||||||
|
.post((req, res, next) => {
|
||||||
|
internalSslPassthrough.disable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
||||||
|
.then((result) => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
@ -153,7 +153,7 @@
|
|||||||
"example": "john@example.com",
|
"example": "john@example.com",
|
||||||
"format": "email",
|
"format": "email",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 8,
|
"minLength": 6,
|
||||||
"maxLength": 100
|
"maxLength": 100
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
|
208
backend/schema/endpoints/ssl-passthrough-hosts.json
Normal file
208
backend/schema/endpoints/ssl-passthrough-hosts.json
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"$id": "endpoints/ssl-passthrough-hosts",
|
||||||
|
"title": "SSL Passthrough Hosts",
|
||||||
|
"description": "Endpoints relating to SSL Passthrough Hosts",
|
||||||
|
"stability": "stable",
|
||||||
|
"type": "object",
|
||||||
|
"definitions": {
|
||||||
|
"id": {
|
||||||
|
"$ref": "../definitions.json#/definitions/id"
|
||||||
|
},
|
||||||
|
"created_on": {
|
||||||
|
"$ref": "../definitions.json#/definitions/created_on"
|
||||||
|
},
|
||||||
|
"modified_on": {
|
||||||
|
"$ref": "../definitions.json#/definitions/modified_on"
|
||||||
|
},
|
||||||
|
"domain_name": {
|
||||||
|
"$ref": "../definitions.json#/definitions/domain_name"
|
||||||
|
},
|
||||||
|
"forwarding_host": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "../definitions.json#/definitions/domain_name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"format": "ipv4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"format": "ipv6"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"forwarding_port": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 1,
|
||||||
|
"maximum": 65535
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"$ref": "../definitions.json#/definitions/enabled"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"$ref": "#/definitions/id"
|
||||||
|
},
|
||||||
|
"created_on": {
|
||||||
|
"$ref": "#/definitions/created_on"
|
||||||
|
},
|
||||||
|
"modified_on": {
|
||||||
|
"$ref": "#/definitions/modified_on"
|
||||||
|
},
|
||||||
|
"domain_name": {
|
||||||
|
"$ref": "#/definitions/domain_name"
|
||||||
|
},
|
||||||
|
"forwarding_host": {
|
||||||
|
"$ref": "#/definitions/forwarding_host"
|
||||||
|
},
|
||||||
|
"forwarding_port": {
|
||||||
|
"$ref": "#/definitions/forwarding_port"
|
||||||
|
},
|
||||||
|
"enabled": {
|
||||||
|
"$ref": "#/definitions/enabled"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"$ref": "#/definitions/meta"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"title": "List",
|
||||||
|
"description": "Returns a list of SSL Passthrough Hosts",
|
||||||
|
"href": "/nginx/ssl-passthrough-hosts",
|
||||||
|
"access": "private",
|
||||||
|
"method": "GET",
|
||||||
|
"rel": "self",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Create",
|
||||||
|
"description": "Creates a new SSL Passthrough Host",
|
||||||
|
"href": "/nginx/ssl-passthrough-hosts",
|
||||||
|
"access": "private",
|
||||||
|
"method": "POST",
|
||||||
|
"rel": "create",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"required": [
|
||||||
|
"domain_name",
|
||||||
|
"forwarding_host",
|
||||||
|
"forwarding_port"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"domain_name": {
|
||||||
|
"$ref": "#/definitions/domain_name"
|
||||||
|
},
|
||||||
|
"forwarding_host": {
|
||||||
|
"$ref": "#/definitions/forwarding_host"
|
||||||
|
},
|
||||||
|
"forwarding_port": {
|
||||||
|
"$ref": "#/definitions/forwarding_port"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"$ref": "#/definitions/meta"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"properties": {
|
||||||
|
"$ref": "#/properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Update",
|
||||||
|
"description": "Updates a existing SSL Passthrough Host",
|
||||||
|
"href": "/nginx/ssl-passthrough-hosts/{definitions.identity.example}",
|
||||||
|
"access": "private",
|
||||||
|
"method": "PUT",
|
||||||
|
"rel": "update",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"domain_name": {
|
||||||
|
"$ref": "#/definitions/domain_name"
|
||||||
|
},
|
||||||
|
"forwarding_host": {
|
||||||
|
"$ref": "#/definitions/forwarding_host"
|
||||||
|
},
|
||||||
|
"forwarding_port": {
|
||||||
|
"$ref": "#/definitions/forwarding_port"
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"$ref": "#/definitions/meta"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"properties": {
|
||||||
|
"$ref": "#/properties"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Delete",
|
||||||
|
"description": "Deletes a existing SSL Passthrough Host",
|
||||||
|
"href": "/nginx/ssl-passthrough-hosts/{definitions.identity.example}",
|
||||||
|
"access": "private",
|
||||||
|
"method": "DELETE",
|
||||||
|
"rel": "delete",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Enable",
|
||||||
|
"description": "Enables a existing SSL Passthrough Host",
|
||||||
|
"href": "/nginx/ssl-passthrough-hosts/{definitions.identity.example}/enable",
|
||||||
|
"access": "private",
|
||||||
|
"method": "POST",
|
||||||
|
"rel": "update",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Disable",
|
||||||
|
"description": "Disables a existing SSL Passthrough Host",
|
||||||
|
"href": "/nginx/ssl-passthrough-hosts/{definitions.identity.example}/disable",
|
||||||
|
"access": "private",
|
||||||
|
"method": "POST",
|
||||||
|
"rel": "update",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
},
|
||||||
|
"targetSchema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -20,9 +20,20 @@
|
|||||||
"minimum": 1,
|
"minimum": 1,
|
||||||
"maximum": 65535
|
"maximum": 65535
|
||||||
},
|
},
|
||||||
"forward_ip": {
|
"forwarding_host": {
|
||||||
"type": "string",
|
"anyOf": [
|
||||||
"format": "ipv4"
|
{
|
||||||
|
"$ref": "../definitions.json#/definitions/domain_name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"format": "ipv4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"format": "ipv6"
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"forwarding_port": {
|
"forwarding_port": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
@ -55,8 +66,8 @@
|
|||||||
"incoming_port": {
|
"incoming_port": {
|
||||||
"$ref": "#/definitions/incoming_port"
|
"$ref": "#/definitions/incoming_port"
|
||||||
},
|
},
|
||||||
"forward_ip": {
|
"forwarding_host": {
|
||||||
"$ref": "#/definitions/forward_ip"
|
"$ref": "#/definitions/forwarding_host"
|
||||||
},
|
},
|
||||||
"forwarding_port": {
|
"forwarding_port": {
|
||||||
"$ref": "#/definitions/forwarding_port"
|
"$ref": "#/definitions/forwarding_port"
|
||||||
@ -107,15 +118,15 @@
|
|||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
"required": [
|
"required": [
|
||||||
"incoming_port",
|
"incoming_port",
|
||||||
"forward_ip",
|
"forwarding_host",
|
||||||
"forwarding_port"
|
"forwarding_port"
|
||||||
],
|
],
|
||||||
"properties": {
|
"properties": {
|
||||||
"incoming_port": {
|
"incoming_port": {
|
||||||
"$ref": "#/definitions/incoming_port"
|
"$ref": "#/definitions/incoming_port"
|
||||||
},
|
},
|
||||||
"forward_ip": {
|
"forwarding_host": {
|
||||||
"$ref": "#/definitions/forward_ip"
|
"$ref": "#/definitions/forwarding_host"
|
||||||
},
|
},
|
||||||
"forwarding_port": {
|
"forwarding_port": {
|
||||||
"$ref": "#/definitions/forwarding_port"
|
"$ref": "#/definitions/forwarding_port"
|
||||||
@ -154,8 +165,8 @@
|
|||||||
"incoming_port": {
|
"incoming_port": {
|
||||||
"$ref": "#/definitions/incoming_port"
|
"$ref": "#/definitions/incoming_port"
|
||||||
},
|
},
|
||||||
"forward_ip": {
|
"forwarding_host": {
|
||||||
"$ref": "#/definitions/forward_ip"
|
"$ref": "#/definitions/forwarding_host"
|
||||||
},
|
},
|
||||||
"forwarding_port": {
|
"forwarding_port": {
|
||||||
"$ref": "#/definitions/forwarding_port"
|
"$ref": "#/definitions/forwarding_port"
|
||||||
|
@ -26,6 +26,9 @@
|
|||||||
"dead-hosts": {
|
"dead-hosts": {
|
||||||
"$ref": "endpoints/dead-hosts.json"
|
"$ref": "endpoints/dead-hosts.json"
|
||||||
},
|
},
|
||||||
|
"ssl-passthrough-hosts": {
|
||||||
|
"$ref": "endpoints/ssl-passthrough-hosts.json"
|
||||||
|
},
|
||||||
"streams": {
|
"streams": {
|
||||||
"$ref": "endpoints/streams.json"
|
"$ref": "endpoints/streams.json"
|
||||||
},
|
},
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const NodeRSA = require('node-rsa');
|
const NodeRSA = require('node-rsa');
|
||||||
const config = require('config');
|
const config = require('config');
|
||||||
const logger = require('./logger').setup;
|
const logger = require('./logger').setup;
|
||||||
const certificateModel = require('./models/certificate');
|
const certificateModel = require('./models/certificate');
|
||||||
const userModel = require('./models/user');
|
const userModel = require('./models/user');
|
||||||
const userPermissionModel = require('./models/user_permission');
|
const userPermissionModel = require('./models/user_permission');
|
||||||
const utils = require('./lib/utils');
|
const utils = require('./lib/utils');
|
||||||
const authModel = require('./models/auth');
|
const authModel = require('./models/auth');
|
||||||
const settingModel = require('./models/setting');
|
const settingModel = require('./models/setting');
|
||||||
const dns_plugins = require('./global/certbot-dns-plugins');
|
const passthroughHostModel = require('./models/ssl_passthrough_host');
|
||||||
const debug_mode = process.env.NODE_ENV !== 'production' || !!process.env.DEBUG;
|
const dns_plugins = require('./global/certbot-dns-plugins');
|
||||||
|
const internalNginx = require('./internal/nginx');
|
||||||
|
const debug_mode = process.env.NODE_ENV !== 'production' || !!process.env.DEBUG;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new JWT RSA Keypair if not alread set on the config
|
* Creates a new JWT RSA Keypair if not alread set on the config
|
||||||
@ -105,14 +107,15 @@ const setupDefaultUser = () => {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return userPermissionModel.query().insert({
|
return userPermissionModel.query().insert({
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
visibility: 'all',
|
visibility: 'all',
|
||||||
proxy_hosts: 'manage',
|
proxy_hosts: 'manage',
|
||||||
redirection_hosts: 'manage',
|
redirection_hosts: 'manage',
|
||||||
dead_hosts: 'manage',
|
dead_hosts: 'manage',
|
||||||
streams: 'manage',
|
ssl_passthrough_hosts: 'manage',
|
||||||
access_lists: 'manage',
|
streams: 'manage',
|
||||||
certificates: 'manage',
|
access_lists: 'manage',
|
||||||
|
certificates: 'manage',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@ -175,7 +178,7 @@ const setupCertbotPlugins = () => {
|
|||||||
certificates.map(function (certificate) {
|
certificates.map(function (certificate) {
|
||||||
if (certificate.meta && certificate.meta.dns_challenge === true) {
|
if (certificate.meta && certificate.meta.dns_challenge === true) {
|
||||||
const dns_plugin = dns_plugins[certificate.meta.dns_provider];
|
const dns_plugin = dns_plugins[certificate.meta.dns_provider];
|
||||||
const packages_to_install = `${dns_plugin.package_name}==${dns_plugin.package_version} ${dns_plugin.dependencies}`;
|
const packages_to_install = `${dns_plugin.package_name}${dns_plugin.version_requirement || ''} ${dns_plugin.dependencies}`;
|
||||||
|
|
||||||
if (plugins.indexOf(packages_to_install) === -1) plugins.push(packages_to_install);
|
if (plugins.indexOf(packages_to_install) === -1) plugins.push(packages_to_install);
|
||||||
|
|
||||||
@ -222,10 +225,19 @@ const setupLogrotation = () => {
|
|||||||
return runLogrotate();
|
return runLogrotate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes sure the ssl passthrough option is reflected in the nginx config
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
const setupSslPassthrough = () => {
|
||||||
|
return internalNginx.configure(passthroughHostModel, 'ssl_passthrough_host', {});
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
return setupJwt()
|
return setupJwt()
|
||||||
.then(setupDefaultUser)
|
.then(setupDefaultUser)
|
||||||
.then(setupDefaultSettings)
|
.then(setupDefaultSettings)
|
||||||
.then(setupCertbotPlugins)
|
.then(setupCertbotPlugins)
|
||||||
.then(setupLogrotation);
|
.then(setupLogrotation)
|
||||||
|
.then(setupSslPassthrough);
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
{% if certificate -%}
|
{% if certificate -%}
|
||||||
listen 443 ssl{% if http2_support %} http2{% endif %};
|
listen 443 ssl{% if http2_support %} http2{% endif %};
|
||||||
{% if ipv6 -%}
|
{% if ipv6 -%}
|
||||||
listen [::]:443;
|
listen [::]:443 ssl{% if http2_support %} http2{% endif %};
|
||||||
{% else -%}
|
{% else -%}
|
||||||
#listen [::]:443;
|
#listen [::]:443;
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
location {{ path }} {
|
location {{ path }} {
|
||||||
|
set $upstream {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}{{ forward_path }};
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Forwarded-Scheme $scheme;
|
proxy_set_header X-Forwarded-Scheme $scheme;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
proxy_set_header X-Forwarded-For $remote_addr;
|
proxy_set_header X-Forwarded-For $remote_addr;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_pass {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}{{ forward_path }};
|
proxy_pass $upstream;
|
||||||
|
|
||||||
{% if access_list_id > 0 %}
|
{% if access_list_id > 0 %}
|
||||||
{% if access_list.items.length > 0 %}
|
{% if access_list.items.length > 0 %}
|
||||||
|
@ -16,6 +16,8 @@ server {
|
|||||||
error_log /data/logs/default-host_error.log warn;
|
error_log /data/logs/default-host_error.log warn;
|
||||||
{% include "_exploits.conf" %}
|
{% include "_exploits.conf" %}
|
||||||
|
|
||||||
|
include conf.d/include/letsencrypt-acme-challenge.conf;
|
||||||
|
|
||||||
{%- if value == "404" %}
|
{%- if value == "404" %}
|
||||||
location / {
|
location / {
|
||||||
return 404;
|
return 404;
|
||||||
|
41
backend/templates/ssl_passthrough_host.conf
Normal file
41
backend/templates/ssl_passthrough_host.conf
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
# ------------------------------------------------------------
|
||||||
|
# SSL Passthrough hosts
|
||||||
|
# ------------------------------------------------------------
|
||||||
|
|
||||||
|
map $ssl_preread_server_name $name {
|
||||||
|
{% for host in all_passthrough_hosts %}
|
||||||
|
{% if host.enabled %}
|
||||||
|
{{ host.domain_name }} ssl_passthrough_{{ host.domain_name }};
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
default https_default_backend;
|
||||||
|
}
|
||||||
|
|
||||||
|
{% for host in all_passthrough_hosts %}
|
||||||
|
{% if host.enabled %}
|
||||||
|
upstream ssl_passthrough_{{ host.domain_name }} {
|
||||||
|
server {{host.forwarding_host}}:{{host.forwarding_port}};
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
upstream https_default_backend {
|
||||||
|
server 127.0.0.1:443;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 444;
|
||||||
|
{% if ipv6 -%}
|
||||||
|
listen [::]:444;
|
||||||
|
{% else -%}
|
||||||
|
#listen [::]:444;
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
proxy_pass $name;
|
||||||
|
ssl_preread on;
|
||||||
|
|
||||||
|
error_log /data/logs/ssl-passthrough-hosts_error.log warn;
|
||||||
|
|
||||||
|
# Custom
|
||||||
|
include /data/nginx/custom/server_ssl_passthrough[.]conf;
|
||||||
|
}
|
@ -12,7 +12,7 @@ server {
|
|||||||
#listen [::]:{{ incoming_port }};
|
#listen [::]:{{ incoming_port }};
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
proxy_pass {{ forward_ip }}:{{ forwarding_port }};
|
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
|
||||||
|
|
||||||
# Custom
|
# Custom
|
||||||
include /data/nginx/custom/server_stream[.]conf;
|
include /data/nginx/custom/server_stream[.]conf;
|
||||||
@ -27,7 +27,7 @@ server {
|
|||||||
{% else -%}
|
{% else -%}
|
||||||
#listen [::]:{{ incoming_port }} udp;
|
#listen [::]:{{ incoming_port }} udp;
|
||||||
{% endif %}
|
{% endif %}
|
||||||
proxy_pass {{ forward_ip }}:{{ forwarding_port }};
|
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
|
||||||
|
|
||||||
# Custom
|
# Custom
|
||||||
include /data/nginx/custom/server_stream[.]conf;
|
include /data/nginx/custom/server_stream[.]conf;
|
||||||
|
@ -77,10 +77,10 @@ acorn@^7.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c"
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c"
|
||||||
integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==
|
integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==
|
||||||
|
|
||||||
ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0:
|
ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.12.6:
|
||||||
version "6.12.3"
|
version "6.12.6"
|
||||||
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706"
|
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
|
||||||
integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==
|
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
|
||||||
dependencies:
|
dependencies:
|
||||||
fast-deep-equal "^3.1.1"
|
fast-deep-equal "^3.1.1"
|
||||||
fast-json-stable-stringify "^2.0.0"
|
fast-json-stable-stringify "^2.0.0"
|
||||||
@ -154,6 +154,35 @@ aproba@^1.0.3:
|
|||||||
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
|
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
|
||||||
integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
|
integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
|
||||||
|
|
||||||
|
archiver-utils@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2"
|
||||||
|
integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==
|
||||||
|
dependencies:
|
||||||
|
glob "^7.1.4"
|
||||||
|
graceful-fs "^4.2.0"
|
||||||
|
lazystream "^1.0.0"
|
||||||
|
lodash.defaults "^4.2.0"
|
||||||
|
lodash.difference "^4.5.0"
|
||||||
|
lodash.flatten "^4.4.0"
|
||||||
|
lodash.isplainobject "^4.0.6"
|
||||||
|
lodash.union "^4.6.0"
|
||||||
|
normalize-path "^3.0.0"
|
||||||
|
readable-stream "^2.0.0"
|
||||||
|
|
||||||
|
archiver@^5.3.0:
|
||||||
|
version "5.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.3.0.tgz#dd3e097624481741df626267564f7dd8640a45ba"
|
||||||
|
integrity sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==
|
||||||
|
dependencies:
|
||||||
|
archiver-utils "^2.1.0"
|
||||||
|
async "^3.2.0"
|
||||||
|
buffer-crc32 "^0.2.1"
|
||||||
|
readable-stream "^3.6.0"
|
||||||
|
readdir-glob "^1.0.0"
|
||||||
|
tar-stream "^2.2.0"
|
||||||
|
zip-stream "^4.1.0"
|
||||||
|
|
||||||
are-we-there-yet@~1.1.2:
|
are-we-there-yet@~1.1.2:
|
||||||
version "1.1.5"
|
version "1.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
|
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
|
||||||
@ -221,6 +250,11 @@ astral-regex@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
|
resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9"
|
||||||
integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
|
integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==
|
||||||
|
|
||||||
|
async@^3.2.0:
|
||||||
|
version "3.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/async/-/async-3.2.1.tgz#d3274ec66d107a47476a4c49136aacdb00665fc8"
|
||||||
|
integrity sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg==
|
||||||
|
|
||||||
atob@^2.1.2:
|
atob@^2.1.2:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
|
||||||
@ -231,6 +265,11 @@ balanced-match@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||||
|
|
||||||
|
base64-js@^1.3.1:
|
||||||
|
version "1.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||||
|
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||||
|
|
||||||
base@^0.11.1:
|
base@^0.11.1:
|
||||||
version "0.11.2"
|
version "0.11.2"
|
||||||
resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
|
resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
|
||||||
@ -267,6 +306,15 @@ binary-extensions@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9"
|
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9"
|
||||||
integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==
|
integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==
|
||||||
|
|
||||||
|
bl@^4.0.3:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
|
||||||
|
integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
|
||||||
|
dependencies:
|
||||||
|
buffer "^5.5.0"
|
||||||
|
inherits "^2.0.4"
|
||||||
|
readable-stream "^3.4.0"
|
||||||
|
|
||||||
blueimp-md5@^2.16.0:
|
blueimp-md5@^2.16.0:
|
||||||
version "2.17.0"
|
version "2.17.0"
|
||||||
resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.17.0.tgz#f4fcac088b115f7b4045f19f5da59e9d01b1bb96"
|
resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.17.0.tgz#f4fcac088b115f7b4045f19f5da59e9d01b1bb96"
|
||||||
@ -333,6 +381,11 @@ braces@~3.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fill-range "^7.0.1"
|
fill-range "^7.0.1"
|
||||||
|
|
||||||
|
buffer-crc32@^0.2.1, buffer-crc32@^0.2.13:
|
||||||
|
version "0.2.13"
|
||||||
|
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
||||||
|
integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=
|
||||||
|
|
||||||
buffer-equal-constant-time@1.0.1:
|
buffer-equal-constant-time@1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
|
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
|
||||||
@ -343,6 +396,14 @@ buffer-writer@2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04"
|
resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04"
|
||||||
integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==
|
integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==
|
||||||
|
|
||||||
|
buffer@^5.5.0:
|
||||||
|
version "5.7.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
|
||||||
|
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
|
||||||
|
dependencies:
|
||||||
|
base64-js "^1.3.1"
|
||||||
|
ieee754 "^1.1.13"
|
||||||
|
|
||||||
busboy@^0.3.1:
|
busboy@^0.3.1:
|
||||||
version "0.3.1"
|
version "0.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b"
|
resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.3.1.tgz#170899274c5bf38aae27d5c62b71268cd585fd1b"
|
||||||
@ -457,7 +518,7 @@ chokidar@^3.2.2:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.1.2"
|
fsevents "~2.1.2"
|
||||||
|
|
||||||
chownr@^1.1.1:
|
chownr@^1.1.4:
|
||||||
version "1.1.4"
|
version "1.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
||||||
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
|
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
|
||||||
@ -562,6 +623,16 @@ component-emitter@^1.2.1:
|
|||||||
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
|
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
|
||||||
integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
|
integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==
|
||||||
|
|
||||||
|
compress-commons@^4.1.0:
|
||||||
|
version "4.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-4.1.1.tgz#df2a09a7ed17447642bad10a85cc9a19e5c42a7d"
|
||||||
|
integrity sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==
|
||||||
|
dependencies:
|
||||||
|
buffer-crc32 "^0.2.13"
|
||||||
|
crc32-stream "^4.0.2"
|
||||||
|
normalize-path "^3.0.0"
|
||||||
|
readable-stream "^3.6.0"
|
||||||
|
|
||||||
compressible@~2.0.16:
|
compressible@~2.0.16:
|
||||||
version "2.0.18"
|
version "2.0.18"
|
||||||
resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
|
resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
|
||||||
@ -643,6 +714,22 @@ core-util-is@~1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
|
||||||
|
|
||||||
|
crc-32@^1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208"
|
||||||
|
integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==
|
||||||
|
dependencies:
|
||||||
|
exit-on-epipe "~1.0.1"
|
||||||
|
printj "~1.1.0"
|
||||||
|
|
||||||
|
crc32-stream@^4.0.2:
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-4.0.2.tgz#c922ad22b38395abe9d3870f02fa8134ed709007"
|
||||||
|
integrity sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==
|
||||||
|
dependencies:
|
||||||
|
crc-32 "^1.2.0"
|
||||||
|
readable-stream "^3.4.0"
|
||||||
|
|
||||||
cross-spawn@^6.0.5:
|
cross-spawn@^6.0.5:
|
||||||
version "6.0.5"
|
version "6.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
|
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
|
||||||
@ -831,7 +918,7 @@ encodeurl@~1.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||||
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
|
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
|
||||||
|
|
||||||
end-of-stream@^1.1.0:
|
end-of-stream@^1.1.0, end-of-stream@^1.4.1:
|
||||||
version "1.4.4"
|
version "1.4.4"
|
||||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
||||||
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
|
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
|
||||||
@ -981,6 +1068,11 @@ etag@~1.8.1:
|
|||||||
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
|
||||||
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
|
integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=
|
||||||
|
|
||||||
|
exit-on-epipe@~1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692"
|
||||||
|
integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==
|
||||||
|
|
||||||
expand-brackets@^2.1.4:
|
expand-brackets@^2.1.4:
|
||||||
version "2.1.4"
|
version "2.1.4"
|
||||||
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
|
resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622"
|
||||||
@ -1237,7 +1329,12 @@ fresh@0.5.2:
|
|||||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||||
integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
|
integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
|
||||||
|
|
||||||
fs-minipass@^1.2.5:
|
fs-constants@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
|
||||||
|
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
|
||||||
|
|
||||||
|
fs-minipass@^1.2.7:
|
||||||
version "1.2.7"
|
version "1.2.7"
|
||||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
|
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
|
||||||
integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==
|
integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==
|
||||||
@ -1321,6 +1418,18 @@ glob@^7.1.3:
|
|||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
path-is-absolute "^1.0.0"
|
path-is-absolute "^1.0.0"
|
||||||
|
|
||||||
|
glob@^7.1.4:
|
||||||
|
version "7.1.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
|
||||||
|
integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
|
||||||
|
dependencies:
|
||||||
|
fs.realpath "^1.0.0"
|
||||||
|
inflight "^1.0.4"
|
||||||
|
inherits "2"
|
||||||
|
minimatch "^3.0.4"
|
||||||
|
once "^1.3.0"
|
||||||
|
path-is-absolute "^1.0.0"
|
||||||
|
|
||||||
global-dirs@^2.0.1:
|
global-dirs@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.0.1.tgz#acdf3bb6685bcd55cb35e8a052266569e9469201"
|
resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.0.1.tgz#acdf3bb6685bcd55cb35e8a052266569e9469201"
|
||||||
@ -1377,6 +1486,11 @@ graceful-fs@^4.1.15, graceful-fs@^4.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
|
||||||
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
|
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==
|
||||||
|
|
||||||
|
graceful-fs@^4.2.0:
|
||||||
|
version "4.2.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a"
|
||||||
|
integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==
|
||||||
|
|
||||||
gravatar@^1.8.0:
|
gravatar@^1.8.0:
|
||||||
version "1.8.1"
|
version "1.8.1"
|
||||||
resolved "https://registry.yarnpkg.com/gravatar/-/gravatar-1.8.1.tgz#743bbdf3185c3433172e00e0e6ff5f6b30c58997"
|
resolved "https://registry.yarnpkg.com/gravatar/-/gravatar-1.8.1.tgz#743bbdf3185c3433172e00e0e6ff5f6b30c58997"
|
||||||
@ -1494,6 +1608,11 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer ">= 2.1.2 < 3"
|
safer-buffer ">= 2.1.2 < 3"
|
||||||
|
|
||||||
|
ieee754@^1.1.13:
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||||
|
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||||
|
|
||||||
ignore-by-default@^1.0.1:
|
ignore-by-default@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
|
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
|
||||||
@ -1537,7 +1656,7 @@ inflight@^1.0.4:
|
|||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
inherits@2, inherits@2.0.4, inherits@~2.0.3, inherits@~2.0.4:
|
inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3, inherits@~2.0.4:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
@ -1937,6 +2056,13 @@ latest-version@^5.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
package-json "^6.3.0"
|
package-json "^6.3.0"
|
||||||
|
|
||||||
|
lazystream@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4"
|
||||||
|
integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=
|
||||||
|
dependencies:
|
||||||
|
readable-stream "^2.0.5"
|
||||||
|
|
||||||
levn@^0.3.0, levn@~0.3.0:
|
levn@^0.3.0, levn@~0.3.0:
|
||||||
version "0.3.0"
|
version "0.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
|
resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
|
||||||
@ -1989,6 +2115,21 @@ locate-path@^5.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
p-locate "^4.1.0"
|
p-locate "^4.1.0"
|
||||||
|
|
||||||
|
lodash.defaults@^4.2.0:
|
||||||
|
version "4.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c"
|
||||||
|
integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=
|
||||||
|
|
||||||
|
lodash.difference@^4.5.0:
|
||||||
|
version "4.5.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c"
|
||||||
|
integrity sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=
|
||||||
|
|
||||||
|
lodash.flatten@^4.4.0:
|
||||||
|
version "4.4.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
|
||||||
|
integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=
|
||||||
|
|
||||||
lodash.includes@^4.3.0:
|
lodash.includes@^4.3.0:
|
||||||
version "4.3.0"
|
version "4.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
|
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
|
||||||
@ -2024,6 +2165,11 @@ lodash.once@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
|
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
|
||||||
integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
|
integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
|
||||||
|
|
||||||
|
lodash.union@^4.6.0:
|
||||||
|
version "4.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88"
|
||||||
|
integrity sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=
|
||||||
|
|
||||||
lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21:
|
lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21:
|
||||||
version "4.17.21"
|
version "4.17.21"
|
||||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||||
@ -2143,7 +2289,7 @@ minimist@^1.2.0, minimist@^1.2.5:
|
|||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||||
|
|
||||||
minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
|
minipass@^2.6.0, minipass@^2.9.0:
|
||||||
version "2.9.0"
|
version "2.9.0"
|
||||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
|
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
|
||||||
integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
|
integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
|
||||||
@ -2151,7 +2297,7 @@ minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
|
|||||||
safe-buffer "^5.1.2"
|
safe-buffer "^5.1.2"
|
||||||
yallist "^3.0.0"
|
yallist "^3.0.0"
|
||||||
|
|
||||||
minizlib@^1.2.1:
|
minizlib@^1.3.3:
|
||||||
version "1.3.3"
|
version "1.3.3"
|
||||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
|
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
|
||||||
integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==
|
integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==
|
||||||
@ -2166,7 +2312,7 @@ mixin-deep@^1.2.0:
|
|||||||
for-in "^1.0.2"
|
for-in "^1.0.2"
|
||||||
is-extendable "^1.0.1"
|
is-extendable "^1.0.1"
|
||||||
|
|
||||||
mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3:
|
mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5:
|
||||||
version "0.5.5"
|
version "0.5.5"
|
||||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
|
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
|
||||||
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
|
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
|
||||||
@ -2340,9 +2486,9 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
|
|||||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||||
|
|
||||||
normalize-url@^4.1.0:
|
normalize-url@^4.1.0:
|
||||||
version "4.5.0"
|
version "4.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129"
|
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a"
|
||||||
integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==
|
integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==
|
||||||
|
|
||||||
npm-bundled@^1.0.1:
|
npm-bundled@^1.0.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
@ -2426,12 +2572,12 @@ object.pick@^1.2.0, object.pick@^1.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
isobject "^3.0.1"
|
isobject "^3.0.1"
|
||||||
|
|
||||||
objection@^2.1.3:
|
objection@^2.2.16:
|
||||||
version "2.2.2"
|
version "2.2.16"
|
||||||
resolved "https://registry.yarnpkg.com/objection/-/objection-2.2.2.tgz#1a3c9010270e3677940d2bc91aeaeb3c0f103800"
|
resolved "https://registry.yarnpkg.com/objection/-/objection-2.2.16.tgz#552ec6d625a7f80d6e204fc63732cbd3fc56f31c"
|
||||||
integrity sha512-+1Ap7u9NQRochzDW5/BggUlKi94JfZGTJwQJuNXo8DwmAb8czEirvxcWBcX91/MmQq0BQUJjM4RPSiZhnkkWQw==
|
integrity sha512-sq8erZdxW5ruPUK6tVvwDxyO16U49XAn/BmOm2zaNhNA2phOPCe2/7+R70nDEF1SFrgJOrwDu/PtoxybuJxnjQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv "^6.12.0"
|
ajv "^6.12.6"
|
||||||
db-errors "^0.2.3"
|
db-errors "^0.2.3"
|
||||||
|
|
||||||
on-finished@~2.3.0:
|
on-finished@~2.3.0:
|
||||||
@ -2608,9 +2754,9 @@ path-key@^2.0.1:
|
|||||||
integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
|
integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=
|
||||||
|
|
||||||
path-parse@^1.0.6:
|
path-parse@^1.0.6:
|
||||||
version "1.0.6"
|
version "1.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
|
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||||
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
|
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||||
|
|
||||||
path-root-regex@^0.1.0:
|
path-root-regex@^0.1.0:
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
@ -2754,6 +2900,11 @@ prettier@^2.0.4:
|
|||||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4"
|
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4"
|
||||||
integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==
|
integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==
|
||||||
|
|
||||||
|
printj@~1.1.0:
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222"
|
||||||
|
integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==
|
||||||
|
|
||||||
process-nextick-args@~2.0.0:
|
process-nextick-args@~2.0.0:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||||
@ -2842,7 +2993,7 @@ rc@^1.2.7, rc@^1.2.8:
|
|||||||
minimist "^1.2.0"
|
minimist "^1.2.0"
|
||||||
strip-json-comments "~2.0.1"
|
strip-json-comments "~2.0.1"
|
||||||
|
|
||||||
readable-stream@2.3.7, readable-stream@^2.0.6:
|
readable-stream@2.3.7, readable-stream@^2.0.0, readable-stream@^2.0.5, readable-stream@^2.0.6:
|
||||||
version "2.3.7"
|
version "2.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||||
@ -2855,6 +3006,22 @@ readable-stream@2.3.7, readable-stream@^2.0.6:
|
|||||||
string_decoder "~1.1.1"
|
string_decoder "~1.1.1"
|
||||||
util-deprecate "~1.0.1"
|
util-deprecate "~1.0.1"
|
||||||
|
|
||||||
|
readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
|
||||||
|
version "3.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||||
|
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
||||||
|
dependencies:
|
||||||
|
inherits "^2.0.3"
|
||||||
|
string_decoder "^1.1.1"
|
||||||
|
util-deprecate "^1.0.1"
|
||||||
|
|
||||||
|
readdir-glob@^1.0.0:
|
||||||
|
version "1.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.1.1.tgz#f0e10bb7bf7bfa7e0add8baffdc54c3f7dbee6c4"
|
||||||
|
integrity sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==
|
||||||
|
dependencies:
|
||||||
|
minimatch "^3.0.4"
|
||||||
|
|
||||||
readdirp@~3.4.0:
|
readdirp@~3.4.0:
|
||||||
version "3.4.0"
|
version "3.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada"
|
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada"
|
||||||
@ -3002,7 +3169,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||||
|
|
||||||
safe-buffer@^5.0.1, safe-buffer@^5.1.2:
|
safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0:
|
||||||
version "5.2.1"
|
version "5.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||||
@ -3271,6 +3438,13 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0:
|
|||||||
is-fullwidth-code-point "^3.0.0"
|
is-fullwidth-code-point "^3.0.0"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
|
string_decoder@^1.1.1:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
|
||||||
|
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
||||||
|
dependencies:
|
||||||
|
safe-buffer "~5.2.0"
|
||||||
|
|
||||||
string_decoder@~1.1.1:
|
string_decoder@~1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
|
||||||
@ -3350,18 +3524,29 @@ table@^5.2.3:
|
|||||||
slice-ansi "^2.1.0"
|
slice-ansi "^2.1.0"
|
||||||
string-width "^3.0.0"
|
string-width "^3.0.0"
|
||||||
|
|
||||||
tar@^4, tar@^4.4.2:
|
tar-stream@^2.2.0:
|
||||||
version "4.4.13"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
|
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
|
||||||
integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==
|
integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
chownr "^1.1.1"
|
bl "^4.0.3"
|
||||||
fs-minipass "^1.2.5"
|
end-of-stream "^1.4.1"
|
||||||
minipass "^2.8.6"
|
fs-constants "^1.0.0"
|
||||||
minizlib "^1.2.1"
|
inherits "^2.0.3"
|
||||||
mkdirp "^0.5.0"
|
readable-stream "^3.1.1"
|
||||||
safe-buffer "^5.1.2"
|
|
||||||
yallist "^3.0.3"
|
tar@^4, tar@^4.4.2:
|
||||||
|
version "4.4.19"
|
||||||
|
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3"
|
||||||
|
integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==
|
||||||
|
dependencies:
|
||||||
|
chownr "^1.1.4"
|
||||||
|
fs-minipass "^1.2.7"
|
||||||
|
minipass "^2.9.0"
|
||||||
|
minizlib "^1.3.3"
|
||||||
|
mkdirp "^0.5.5"
|
||||||
|
safe-buffer "^5.2.1"
|
||||||
|
yallist "^3.1.1"
|
||||||
|
|
||||||
tarn@^2.0.0:
|
tarn@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
@ -3587,7 +3772,7 @@ use@^3.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
|
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
|
||||||
integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
|
integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
|
||||||
|
|
||||||
util-deprecate@~1.0.1:
|
util-deprecate@^1.0.1, util-deprecate@~1.0.1:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||||
@ -3721,7 +3906,7 @@ y18n@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4"
|
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4"
|
||||||
integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==
|
integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==
|
||||||
|
|
||||||
yallist@^3.0.0, yallist@^3.0.3:
|
yallist@^3.0.0, yallist@^3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
||||||
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
||||||
@ -3755,3 +3940,12 @@ yargs@^15.4.1:
|
|||||||
which-module "^2.0.0"
|
which-module "^2.0.0"
|
||||||
y18n "^4.0.0"
|
y18n "^4.0.0"
|
||||||
yargs-parser "^18.1.2"
|
yargs-parser "^18.1.2"
|
||||||
|
|
||||||
|
zip-stream@^4.1.0:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.1.0.tgz#51dd326571544e36aa3f756430b313576dc8fc79"
|
||||||
|
integrity sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==
|
||||||
|
dependencies:
|
||||||
|
archiver-utils "^2.1.0"
|
||||||
|
compress-commons "^4.1.0"
|
||||||
|
readable-stream "^3.6.0"
|
||||||
|
14
docker/.dive-ci
Normal file
14
docker/.dive-ci
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
rules:
|
||||||
|
# If the efficiency is measured below X%, mark as failed.
|
||||||
|
# Expressed as a ratio between 0-1.
|
||||||
|
lowestEfficiency: 0.99
|
||||||
|
|
||||||
|
# If the amount of wasted space is at least X or larger than X, mark as failed.
|
||||||
|
# Expressed in B, KB, MB, and GB.
|
||||||
|
highestWastedBytes: 15MB
|
||||||
|
|
||||||
|
# If the amount of wasted space makes up for X% or more of the image, mark as failed.
|
||||||
|
# Note: the base image layer is NOT included in the total image size.
|
||||||
|
# Expressed as a ratio between 0-1; fails if the threshold is met or crossed.
|
||||||
|
highestUserWastedPercent: 0.02
|
||||||
|
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
# This file assumes that the frontend has been built using ./scripts/frontend-build
|
# This file assumes that the frontend has been built using ./scripts/frontend-build
|
||||||
|
|
||||||
FROM jc21/nginx-full:node
|
FROM nginxproxymanager/nginx-full:node
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
ARG BUILD_VERSION
|
ARG BUILD_VERSION
|
||||||
@ -48,7 +48,6 @@ RUN chmod 644 /etc/logrotate.d/nginx-proxy-manager
|
|||||||
|
|
||||||
VOLUME [ "/data", "/etc/letsencrypt" ]
|
VOLUME [ "/data", "/etc/letsencrypt" ]
|
||||||
ENTRYPOINT [ "/init" ]
|
ENTRYPOINT [ "/init" ]
|
||||||
HEALTHCHECK --interval=5s --timeout=3s CMD /bin/check-health
|
|
||||||
|
|
||||||
LABEL org.label-schema.schema-version="1.0" \
|
LABEL org.label-schema.schema-version="1.0" \
|
||||||
org.label-schema.license="MIT" \
|
org.label-schema.license="MIT" \
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM jc21/nginx-full:node
|
FROM nginxproxymanager/nginx-full:node
|
||||||
LABEL maintainer="Jamie Curnow <jc@jc21.com>"
|
LABEL maintainer="Jamie Curnow <jc@jc21.com>"
|
||||||
|
|
||||||
ENV S6_LOGGING=0 \
|
ENV S6_LOGGING=0 \
|
||||||
@ -26,4 +26,4 @@ RUN curl -L -o /tmp/s6-overlay-amd64.tar.gz "https://github.com/just-containers/
|
|||||||
|
|
||||||
EXPOSE 80 81 443
|
EXPOSE 80 81 443
|
||||||
ENTRYPOINT [ "/init" ]
|
ENTRYPOINT [ "/init" ]
|
||||||
HEALTHCHECK --interval=5s --timeout=3s CMD /bin/check-health
|
|
||||||
|
@ -20,6 +20,10 @@ services:
|
|||||||
- 443
|
- 443
|
||||||
depends_on:
|
depends_on:
|
||||||
- db
|
- db
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "/bin/check-health"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 3s
|
||||||
|
|
||||||
fullstack-sqlite:
|
fullstack-sqlite:
|
||||||
image: ${IMAGE}:ci-${BUILD_NUMBER}
|
image: ${IMAGE}:ci-${BUILD_NUMBER}
|
||||||
@ -33,6 +37,10 @@ services:
|
|||||||
- 81
|
- 81
|
||||||
- 80
|
- 80
|
||||||
- 443
|
- 443
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "/bin/check-health"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 3s
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: jc21/mariadb-aria
|
image: jc21/mariadb-aria
|
||||||
|
@ -10,7 +10,8 @@ services:
|
|||||||
ports:
|
ports:
|
||||||
- 3080:80
|
- 3080:80
|
||||||
- 3081:81
|
- 3081:81
|
||||||
- 3443:443
|
- 3443:443 # Ususally you would only have this one
|
||||||
|
- 3444:444 # This is to test ssl passthrough
|
||||||
networks:
|
networks:
|
||||||
- nginx_proxy_manager
|
- nginx_proxy_manager
|
||||||
environment:
|
environment:
|
||||||
@ -22,6 +23,7 @@ services:
|
|||||||
DB_MYSQL_USER: "npm"
|
DB_MYSQL_USER: "npm"
|
||||||
DB_MYSQL_PASSWORD: "npm"
|
DB_MYSQL_PASSWORD: "npm"
|
||||||
DB_MYSQL_NAME: "npm"
|
DB_MYSQL_NAME: "npm"
|
||||||
|
# ENABLE_SSL_PASSTHROUGH: "true"
|
||||||
# DB_SQLITE_FILE: "/data/database.sqlite"
|
# DB_SQLITE_FILE: "/data/database.sqlite"
|
||||||
# DISABLE_IPV6: "true"
|
# DISABLE_IPV6: "true"
|
||||||
volumes:
|
volumes:
|
||||||
@ -39,6 +41,8 @@ services:
|
|||||||
container_name: npm_db
|
container_name: npm_db
|
||||||
networks:
|
networks:
|
||||||
- nginx_proxy_manager
|
- nginx_proxy_manager
|
||||||
|
ports:
|
||||||
|
- 33306:3306
|
||||||
environment:
|
environment:
|
||||||
MYSQL_ROOT_PASSWORD: "npm"
|
MYSQL_ROOT_PASSWORD: "npm"
|
||||||
MYSQL_DATABASE: "npm"
|
MYSQL_DATABASE: "npm"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
text = True
|
text = True
|
||||||
non-interactive = True
|
non-interactive = True
|
||||||
authenticator = webroot
|
|
||||||
webroot-path = /data/letsencrypt-acme-challenge
|
webroot-path = /data/letsencrypt-acme-challenge
|
||||||
|
key-type = ecdsa
|
||||||
|
elliptic-curve = secp384r1
|
||||||
|
@ -9,9 +9,10 @@ server {
|
|||||||
|
|
||||||
server_name localhost-nginx-proxy-manager;
|
server_name localhost-nginx-proxy-manager;
|
||||||
access_log /data/logs/fallback_access.log standard;
|
access_log /data/logs/fallback_access.log standard;
|
||||||
error_log /dev/null crit;
|
error_log /data/logs/fallback_error.log warn;
|
||||||
include conf.d/include/assets.conf;
|
include conf.d/include/assets.conf;
|
||||||
include conf.d/include/block-exploits.conf;
|
include conf.d/include/block-exploits.conf;
|
||||||
|
include conf.d/include/letsencrypt-acme-challenge.conf;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
index index.html;
|
index index.html;
|
||||||
|
@ -85,6 +85,7 @@ http {
|
|||||||
|
|
||||||
stream {
|
stream {
|
||||||
# Files generated by NPM
|
# Files generated by NPM
|
||||||
|
include /data/nginx/ssl_passthrough_host/hosts[.]conf;
|
||||||
include /data/nginx/stream/*.conf;
|
include /data/nginx/stream/*.conf;
|
||||||
|
|
||||||
# Custom
|
# Custom
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
if [ "$DEVELOPMENT" == "true" ]; then
|
if [ "$DEVELOPMENT" == "true" ]; then
|
||||||
cd /app/frontend || exit 1
|
cd /app/frontend || exit 1
|
||||||
|
# If yarn install fails: add --verbose --network-concurrency 1
|
||||||
yarn install
|
yarn install
|
||||||
yarn watch
|
yarn watch
|
||||||
else
|
else
|
||||||
|
@ -6,6 +6,7 @@ cd /app || echo
|
|||||||
|
|
||||||
if [ "$DEVELOPMENT" == "true" ]; then
|
if [ "$DEVELOPMENT" == "true" ]; then
|
||||||
cd /app || exit 1
|
cd /app || exit 1
|
||||||
|
# If yarn install fails: add --verbose --network-concurrency 1
|
||||||
yarn install
|
yarn install
|
||||||
node --max_old_space_size=250 --abort_on_uncaught_exception node_modules/nodemon/bin/nodemon.js
|
node --max_old_space_size=250 --abort_on_uncaught_exception node_modules/nodemon/bin/nodemon.js
|
||||||
else
|
else
|
||||||
|
@ -12,6 +12,7 @@ mkdir -p /tmp/nginx/body \
|
|||||||
/data/nginx/default_www \
|
/data/nginx/default_www \
|
||||||
/data/nginx/proxy_host \
|
/data/nginx/proxy_host \
|
||||||
/data/nginx/redirection_host \
|
/data/nginx/redirection_host \
|
||||||
|
/data/nginx/ssl_passthrough_host \
|
||||||
/data/nginx/stream \
|
/data/nginx/stream \
|
||||||
/data/nginx/dead_host \
|
/data/nginx/dead_host \
|
||||||
/data/nginx/temp \
|
/data/nginx/temp \
|
||||||
@ -36,7 +37,7 @@ then
|
|||||||
-days 3650 \
|
-days 3650 \
|
||||||
-nodes \
|
-nodes \
|
||||||
-x509 \
|
-x509 \
|
||||||
-subj '/O=Nginx Proxy Manager/OU=Dummy Certificate/CN=localhost' \
|
-subj '/O=localhost/OU=localhost/CN=localhost' \
|
||||||
-keyout /data/nginx/dummykey.pem \
|
-keyout /data/nginx/dummykey.pem \
|
||||||
-out /data/nginx/dummycert.pem
|
-out /data/nginx/dummycert.pem
|
||||||
echo "Complete"
|
echo "Complete"
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
# Advanced Configuration
|
# Advanced Configuration
|
||||||
|
|
||||||
## Best Practice: Use a docker network
|
## Best Practice: Use a Docker network
|
||||||
|
|
||||||
For those who have a few of their upstream services running in docker on the same docker
|
For those who have a few of their upstream services running in Docker on the same Docker
|
||||||
host as NPM, here's a trick to secure things a bit better. By creating a custom docker network,
|
host as NPM, here's a trick to secure things a bit better. By creating a custom Docker network,
|
||||||
you don't need to publish ports for your upstream services to all of the docker host's interfaces.
|
you don't need to publish ports for your upstream services to all of the Docker host's interfaces.
|
||||||
|
|
||||||
Create a network, ie "scoobydoo":
|
Create a network, ie "scoobydoo":
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ docker network create scoobydoo
|
|||||||
```
|
```
|
||||||
|
|
||||||
Then add the following to the `docker-compose.yml` file for both NPM and any other
|
Then add the following to the `docker-compose.yml` file for both NPM and any other
|
||||||
services running on this docker host:
|
services running on this Docker host:
|
||||||
|
|
||||||
```yml
|
```yml
|
||||||
networks:
|
networks:
|
||||||
@ -44,10 +44,22 @@ networks:
|
|||||||
|
|
||||||
Now in the NPM UI you can create a proxy host with `portainer` as the hostname,
|
Now in the NPM UI you can create a proxy host with `portainer` as the hostname,
|
||||||
and port `9000` as the port. Even though this port isn't listed in the docker-compose
|
and port `9000` as the port. Even though this port isn't listed in the docker-compose
|
||||||
file, it's "exposed" by the portainer docker image for you and not available on
|
file, it's "exposed" by the Portainer Docker image for you and not available on
|
||||||
the docker host outside of this docker network. The service name is used as the
|
the Docker host outside of this Docker network. The service name is used as the
|
||||||
hostname, so make sure your service names are unique when using the same network.
|
hostname, so make sure your service names are unique when using the same network.
|
||||||
|
|
||||||
|
## Docker Healthcheck
|
||||||
|
|
||||||
|
The `Dockerfile` that builds this project does not include a `HEALTHCHECK` but you can opt in to this
|
||||||
|
feature by adding the following to the service in your `docker-compose.yml` file:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "/bin/check-health"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 3s
|
||||||
|
```
|
||||||
|
|
||||||
## Docker Secrets
|
## Docker Secrets
|
||||||
|
|
||||||
This image supports the use of Docker secrets to import from file and keep sensitive usernames or passwords from being passed or preserved in plaintext.
|
This image supports the use of Docker secrets to import from file and keep sensitive usernames or passwords from being passed or preserved in plaintext.
|
||||||
@ -116,7 +128,7 @@ services:
|
|||||||
|
|
||||||
## Disabling IPv6
|
## Disabling IPv6
|
||||||
|
|
||||||
On some docker hosts IPv6 may not be enabled. In these cases, the following message may be seen in the log:
|
On some Docker hosts IPv6 may not be enabled. In these cases, the following message may be seen in the log:
|
||||||
|
|
||||||
> Address family not supported by protocol
|
> Address family not supported by protocol
|
||||||
|
|
||||||
@ -160,3 +172,28 @@ value by specifying it as a Docker environment variable. The default if not spec
|
|||||||
X_FRAME_OPTIONS: "sameorigin"
|
X_FRAME_OPTIONS: "sameorigin"
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## SSL Passthrough
|
||||||
|
|
||||||
|
SSL Passthrough will allow you to proxy a server without [SSL termination](https://en.wikipedia.org/wiki/TLS_termination_proxy). This means the SSL encryption of the server will be passed right through the proxy, retaining the original certificate.
|
||||||
|
|
||||||
|
Because of the SSL encryption the proxy does not know anything about the traffic and it just relies on an SSL feature called [Server Name Indication](https://en.wikipedia.org/wiki/Server_Name_Indication) to know where to send this network packet. This also means if the client does not provide this additional information, accessing the site through the proxy won't be possible. But most modern browsers include this information a HTTPS requests.
|
||||||
|
|
||||||
|
Due to nginx constraints using SSL Passthrough comes with **a performance penalty for other hosts**, since all hosts (including normal proxy hosts) now have to pass through this additional step and basically being proxied twice. If you want to retain the upstream SSL certificate but do not need your service to be available on port 443, it is recommended to use a stream host instead.
|
||||||
|
|
||||||
|
To enable SSL Passthrough on your npm instance you need to do two things: add the environment variable `ENABLE_SSL_PASSTHROUGH` with the value `"true"`, and expose port 444 instead of 443 to the outside as port 443.
|
||||||
|
|
||||||
|
```yml
|
||||||
|
version: '3'
|
||||||
|
services:
|
||||||
|
app:
|
||||||
|
...
|
||||||
|
ports:
|
||||||
|
- '80:80'
|
||||||
|
- '81:81'
|
||||||
|
- '443:444' # Expose internal port 444 instead of 443 as SSL port
|
||||||
|
environment:
|
||||||
|
...
|
||||||
|
ENABLE_SSL_PASSTHROUGH: "true" # Enable SSL Passthrough
|
||||||
|
...
|
||||||
|
```
|
@ -443,7 +443,7 @@
|
|||||||
"normalize-url": "^5.1.0",
|
"normalize-url": "^5.1.0",
|
||||||
"npm-run-path": "^4.0.1",
|
"npm-run-path": "^4.0.1",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"nth-check": "^1.0.2",
|
"nth-check": "^2.0.1",
|
||||||
"num2fraction": "^1.2.2",
|
"num2fraction": "^1.2.2",
|
||||||
"number-is-nan": "^2.0.0",
|
"number-is-nan": "^2.0.0",
|
||||||
"oauth-sign": "^0.9.0",
|
"oauth-sign": "^0.9.0",
|
||||||
@ -612,7 +612,7 @@
|
|||||||
"serve-index": "^1.9.1",
|
"serve-index": "^1.9.1",
|
||||||
"serve-static": "^1.14.1",
|
"serve-static": "^1.14.1",
|
||||||
"set-blocking": "^2.0.0",
|
"set-blocking": "^2.0.0",
|
||||||
"set-value": "^3.0.2",
|
"set-value": "^4.0.1",
|
||||||
"setimmediate": "^1.0.5",
|
"setimmediate": "^1.0.5",
|
||||||
"setprototypeof": "^1.2.0",
|
"setprototypeof": "^1.2.0",
|
||||||
"sha.js": "^2.4.11",
|
"sha.js": "^2.4.11",
|
||||||
|
@ -1624,9 +1624,9 @@ ansi-regex@^4.1.0:
|
|||||||
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
|
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
|
||||||
|
|
||||||
ansi-regex@^5.0.0:
|
ansi-regex@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
||||||
integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
|
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
|
||||||
|
|
||||||
ansi-styles@^2.2.1:
|
ansi-styles@^2.2.1:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
@ -2560,7 +2560,7 @@ cli-boxes@^2.2.0:
|
|||||||
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d"
|
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d"
|
||||||
integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==
|
integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==
|
||||||
|
|
||||||
clipboard@^2.0.0, clipboard@^2.0.6:
|
clipboard@^2.0.6:
|
||||||
version "2.0.6"
|
version "2.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.6.tgz#52921296eec0fdf77ead1749421b21c968647376"
|
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.6.tgz#52921296eec0fdf77ead1749421b21c968647376"
|
||||||
integrity sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==
|
integrity sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==
|
||||||
@ -6405,10 +6405,10 @@ minipass@^3.0.0, minipass@^3.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
yallist "^4.0.0"
|
yallist "^4.0.0"
|
||||||
|
|
||||||
minizlib@^2.1.0:
|
minizlib@^2.1.1:
|
||||||
version "2.1.0"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.0.tgz#fd52c645301ef09a63a2c209697c294c6ce02cf3"
|
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
|
||||||
integrity sha512-EzTZN/fjSvifSX0SlqUERCN39o6T40AMarPbv0MrarSFtIITCBh7bi+dU8nxGFHuqs9jdIAeoYoKuQAAASsPPA==
|
integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
|
||||||
dependencies:
|
dependencies:
|
||||||
minipass "^3.0.0"
|
minipass "^3.0.0"
|
||||||
yallist "^4.0.0"
|
yallist "^4.0.0"
|
||||||
@ -6726,6 +6726,13 @@ nth-check@^1.0.2, nth-check@~1.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
boolbase "~1.0.0"
|
boolbase "~1.0.0"
|
||||||
|
|
||||||
|
nth-check@^2.0.1:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2"
|
||||||
|
integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==
|
||||||
|
dependencies:
|
||||||
|
boolbase "^1.0.0"
|
||||||
|
|
||||||
num2fraction@^1.2.2:
|
num2fraction@^1.2.2:
|
||||||
version "1.2.2"
|
version "1.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
|
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
|
||||||
@ -7173,9 +7180,9 @@ path-key@^3.0.0, path-key@^3.1.0, path-key@^3.1.1:
|
|||||||
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
|
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
|
||||||
|
|
||||||
path-parse@^1.0.6:
|
path-parse@^1.0.6:
|
||||||
version "1.0.6"
|
version "1.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
|
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||||
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
|
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||||
|
|
||||||
path-to-regexp@0.1.7:
|
path-to-regexp@0.1.7:
|
||||||
version "0.1.7"
|
version "0.1.7"
|
||||||
@ -7699,11 +7706,9 @@ pretty-time@^1.1.0:
|
|||||||
integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==
|
integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==
|
||||||
|
|
||||||
prismjs@^1.13.0, prismjs@^1.20.0:
|
prismjs@^1.13.0, prismjs@^1.20.0:
|
||||||
version "1.23.0"
|
version "1.25.0"
|
||||||
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.23.0.tgz#d3b3967f7d72440690497652a9d40ff046067f33"
|
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.25.0.tgz#6f822df1bdad965734b310b315a23315cf999756"
|
||||||
integrity sha512-c29LVsqOaLbBHuIbsTxaKENh1N2EQBOHaWv7gkHN4dgRbxSREqDnDbtFJYdpPauS4YCplMSNCABQ6Eeor69bAA==
|
integrity sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==
|
||||||
optionalDependencies:
|
|
||||||
clipboard "^2.0.0"
|
|
||||||
|
|
||||||
private@^0.1.8:
|
private@^0.1.8:
|
||||||
version "0.1.8"
|
version "0.1.8"
|
||||||
@ -8438,13 +8443,20 @@ set-value@^2.0.0, set-value@^2.0.1:
|
|||||||
is-plain-object "^2.0.3"
|
is-plain-object "^2.0.3"
|
||||||
split-string "^3.0.1"
|
split-string "^3.0.1"
|
||||||
|
|
||||||
set-value@^3.0.0, set-value@^3.0.2:
|
set-value@^3.0.0:
|
||||||
version "3.0.2"
|
version "3.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/set-value/-/set-value-3.0.2.tgz#74e8ecd023c33d0f77199d415409a40f21e61b90"
|
resolved "https://registry.yarnpkg.com/set-value/-/set-value-3.0.2.tgz#74e8ecd023c33d0f77199d415409a40f21e61b90"
|
||||||
integrity sha512-npjkVoz+ank0zjlV9F47Fdbjfj/PfXyVhZvGALWsyIYU/qrMzpi6avjKW3/7KeSU2Df3I46BrN1xOI1+6vW0hA==
|
integrity sha512-npjkVoz+ank0zjlV9F47Fdbjfj/PfXyVhZvGALWsyIYU/qrMzpi6avjKW3/7KeSU2Df3I46BrN1xOI1+6vW0hA==
|
||||||
dependencies:
|
dependencies:
|
||||||
is-plain-object "^2.0.4"
|
is-plain-object "^2.0.4"
|
||||||
|
|
||||||
|
set-value@^4.0.1:
|
||||||
|
version "4.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/set-value/-/set-value-4.0.1.tgz#bc23522ade2d52314ec3b5d6fb140f5cd3a88acf"
|
||||||
|
integrity sha512-ayATicCYPVnlNpFmjq2/VmVwhoCQA9+13j8qWp044fmFE3IFphosPtRM+0CJ5xoIx5Uy52fCcwg3XeH2pHbbPQ==
|
||||||
|
dependencies:
|
||||||
|
is-plain-object "^2.0.4"
|
||||||
|
|
||||||
setimmediate@^1.0.4, setimmediate@^1.0.5:
|
setimmediate@^1.0.4, setimmediate@^1.0.5:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
|
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
|
||||||
@ -9156,14 +9168,14 @@ tapable@^1.0.0, tapable@^1.1.3:
|
|||||||
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
|
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
|
||||||
|
|
||||||
tar@^6.0.2:
|
tar@^6.0.2:
|
||||||
version "6.0.2"
|
version "6.1.11"
|
||||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.2.tgz#5df17813468a6264ff14f766886c622b84ae2f39"
|
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
|
||||||
integrity sha512-Glo3jkRtPcvpDlAs/0+hozav78yoXKFr+c4wgw62NNMO3oo4AaJdCo21Uu7lcwr55h39W2XD1LMERc64wtbItg==
|
integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
|
||||||
dependencies:
|
dependencies:
|
||||||
chownr "^2.0.0"
|
chownr "^2.0.0"
|
||||||
fs-minipass "^2.0.0"
|
fs-minipass "^2.0.0"
|
||||||
minipass "^3.0.0"
|
minipass "^3.0.0"
|
||||||
minizlib "^2.1.0"
|
minizlib "^2.1.1"
|
||||||
mkdirp "^1.0.3"
|
mkdirp "^1.0.3"
|
||||||
yallist "^4.0.0"
|
yallist "^4.0.0"
|
||||||
|
|
||||||
@ -9652,9 +9664,9 @@ url-parse-lax@^3.0.0:
|
|||||||
prepend-http "^2.0.0"
|
prepend-http "^2.0.0"
|
||||||
|
|
||||||
url-parse@^1.4.3, url-parse@^1.4.7:
|
url-parse@^1.4.3, url-parse@^1.4.7:
|
||||||
version "1.5.0"
|
version "1.5.2"
|
||||||
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.0.tgz#90aba6c902aeb2d80eac17b91131c27665d5d828"
|
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.2.tgz#a4eff6fd5ff9fe6ab98ac1f79641819d13247cda"
|
||||||
integrity sha512-9iT6N4s93SMfzunOyDPe4vo4nLcSu1yq0IQK1gURmjm8tQNlM6loiuCRrKG1hHGXfB2EWd6H4cGi7tGdaygMFw==
|
integrity sha512-6bTUPERy1muxxYClbzoRo5qtQuyoGEbzbQvi0SW4/8U8UyVkAQhWFBlnigqJkRm4su4x1zDQfNbEzWkt+vchcg==
|
||||||
dependencies:
|
dependencies:
|
||||||
querystringify "^2.1.1"
|
querystringify "^2.1.1"
|
||||||
requires-port "^1.0.0"
|
requires-port "^1.0.0"
|
||||||
|
@ -152,6 +152,51 @@ function FileUpload(path, fd) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//ref : https://codepen.io/chrisdpratt/pen/RKxJNo
|
||||||
|
function DownloadFile(verb, path, filename) {
|
||||||
|
return new Promise(function (resolve, reject) {
|
||||||
|
let api_url = '/api/';
|
||||||
|
let url = api_url + path;
|
||||||
|
let token = Tokens.getTopToken();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: url,
|
||||||
|
type: verb,
|
||||||
|
crossDomain: true,
|
||||||
|
xhrFields: {
|
||||||
|
withCredentials: true,
|
||||||
|
responseType: 'blob'
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeSend: function (xhr) {
|
||||||
|
xhr.setRequestHeader('Authorization', 'Bearer ' + (token ? token.t : null));
|
||||||
|
},
|
||||||
|
|
||||||
|
success: function (data) {
|
||||||
|
var a = document.createElement('a');
|
||||||
|
var url = window.URL.createObjectURL(data);
|
||||||
|
a.href = url;
|
||||||
|
a.download = filename;
|
||||||
|
document.body.append(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
},
|
||||||
|
|
||||||
|
error: function (xhr, status, error_thrown) {
|
||||||
|
let code = 400;
|
||||||
|
|
||||||
|
if (typeof xhr.responseJSON !== 'undefined' && typeof xhr.responseJSON.error !== 'undefined' && typeof xhr.responseJSON.error.message !== 'undefined') {
|
||||||
|
error_thrown = xhr.responseJSON.error.message;
|
||||||
|
code = xhr.responseJSON.error.code || 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
reject(new ApiError(error_thrown, xhr.responseText, code));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
status: function () {
|
status: function () {
|
||||||
return fetch('get', '');
|
return fetch('get', '');
|
||||||
@ -470,6 +515,76 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
SslPassthroughHosts: {
|
||||||
|
/**
|
||||||
|
* @param {Array} [expand]
|
||||||
|
* @param {String} [query]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getFeatureEnabled: function () {
|
||||||
|
return fetch('get', 'ssl-passthrough-enabled');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Array} [expand]
|
||||||
|
* @param {String} [query]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
getAll: function (expand, query) {
|
||||||
|
return getAllObjects('nginx/ssl-passthrough-hosts', expand, query);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} data
|
||||||
|
*/
|
||||||
|
create: function (data) {
|
||||||
|
return fetch('post', 'nginx/ssl-passthrough-hosts', data);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} data
|
||||||
|
* @param {Number} data.id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
update: function (data) {
|
||||||
|
let id = data.id;
|
||||||
|
delete data.id;
|
||||||
|
return fetch('put', 'nginx/ssl-passthrough-hosts/' + id, data);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
delete: function (id) {
|
||||||
|
return fetch('delete', 'nginx/ssl-passthrough-hosts/' + id);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
get: function (id) {
|
||||||
|
return fetch('get', 'nginx/ssl-passthrough-hosts/' + id);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
enable: function (id) {
|
||||||
|
return fetch('post', 'nginx/ssl-passthrough-hosts/' + id + '/enable');
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
disable: function (id) {
|
||||||
|
return fetch('post', 'nginx/ssl-passthrough-hosts/' + id + '/disable');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
DeadHosts: {
|
DeadHosts: {
|
||||||
/**
|
/**
|
||||||
* @param {Array} [expand]
|
* @param {Array} [expand]
|
||||||
@ -638,6 +753,14 @@ module.exports = {
|
|||||||
*/
|
*/
|
||||||
renew: function (id, timeout = 180000) {
|
renew: function (id, timeout = 180000) {
|
||||||
return fetch('post', 'nginx/certificates/' + id + '/renew', undefined, {timeout});
|
return fetch('post', 'nginx/certificates/' + id + '/renew', undefined, {timeout});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
download: function (id) {
|
||||||
|
return DownloadFile('get', "nginx/certificates/" + id + "/download", "certificate.zip")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -221,6 +221,46 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nginx SSL Passthrough Hosts
|
||||||
|
*/
|
||||||
|
showNginxSslPassthrough: function () {
|
||||||
|
if (Cache.User.isAdmin() || Cache.User.canView('ssl_passthrough_hosts')) {
|
||||||
|
let controller = this;
|
||||||
|
|
||||||
|
require(['./main', './nginx/ssl-passthrough/main'], (App, View) => {
|
||||||
|
controller.navigate('/nginx/ssl-passthrough');
|
||||||
|
App.UI.showAppContent(new View());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SSL Passthrough Hosts Form
|
||||||
|
*
|
||||||
|
* @param [model]
|
||||||
|
*/
|
||||||
|
showNginxSslPassthroughForm: function (model) {
|
||||||
|
if (Cache.User.isAdmin() || Cache.User.canManage('ssl_passthrough_hosts')) {
|
||||||
|
require(['./main', './nginx/ssl-passthrough/form'], function (App, View) {
|
||||||
|
App.UI.showModalDialog(new View({model: model}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SSL Passthrough Hosts Delete Confirm
|
||||||
|
*
|
||||||
|
* @param model
|
||||||
|
*/
|
||||||
|
showNginxSslPassthroughDeleteConfirm: function (model) {
|
||||||
|
if (Cache.User.isAdmin() || Cache.User.canManage('ssl_passthrough_hosts')) {
|
||||||
|
require(['./main', './nginx/ssl-passthrough/delete'], function (App, View) {
|
||||||
|
App.UI.showModalDialog(new View({model: model}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Nginx Dead Hosts
|
* Nginx Dead Hosts
|
||||||
*/
|
*/
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
<span class="dropdown-header"><%- i18n('audit-log', 'certificate') %> #<%- id %></span>
|
<span class="dropdown-header"><%- i18n('audit-log', 'certificate') %> #<%- id %></span>
|
||||||
<% if (provider === 'letsencrypt') { %>
|
<% if (provider === 'letsencrypt') { %>
|
||||||
<a href="#" class="renew dropdown-item"><i class="dropdown-icon fe fe-refresh-cw"></i> <%- i18n('certificates', 'force-renew') %></a>
|
<a href="#" class="renew dropdown-item"><i class="dropdown-icon fe fe-refresh-cw"></i> <%- i18n('certificates', 'force-renew') %></a>
|
||||||
|
<a href="#" class="download dropdown-item"><i class="dropdown-icon fe fe-download"></i> <%- i18n('certificates', 'download') %></a>
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
<% } %>
|
<% } %>
|
||||||
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
||||||
|
@ -11,7 +11,8 @@ module.exports = Mn.View.extend({
|
|||||||
ui: {
|
ui: {
|
||||||
host_link: '.host-link',
|
host_link: '.host-link',
|
||||||
renew: 'a.renew',
|
renew: 'a.renew',
|
||||||
delete: 'a.delete'
|
delete: 'a.delete',
|
||||||
|
download: 'a.download'
|
||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
@ -29,6 +30,11 @@ module.exports = Mn.View.extend({
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
let win = window.open($(e.currentTarget).attr('rel'), '_blank');
|
let win = window.open($(e.currentTarget).attr('rel'), '_blank');
|
||||||
win.focus();
|
win.focus();
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.download': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
App.Api.Nginx.Certificates.download(this.model.get('id'))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
19
frontend/js/app/nginx/ssl-passthrough/delete.ejs
Normal file
19
frontend/js/app/nginx/ssl-passthrough/delete.ejs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title"><%- i18n('ssl-passthrough-hosts', 'delete') %></h5>
|
||||||
|
<button type="button" class="close cancel" aria-label="Close" data-dismiss="modal"> </button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12 col-md-12">
|
||||||
|
<%= i18n('ssl-passthrough-hosts', 'delete-confirm') %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary cancel" data-dismiss="modal"><%- i18n('str', 'cancel') %></button>
|
||||||
|
<button type="button" class="btn btn-danger save"><%- i18n('str', 'sure') %></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
32
frontend/js/app/nginx/ssl-passthrough/delete.js
Normal file
32
frontend/js/app/nginx/ssl-passthrough/delete.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const App = require('../../main');
|
||||||
|
const template = require('./delete.ejs');
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
template: template,
|
||||||
|
className: 'modal-dialog',
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
form: 'form',
|
||||||
|
buttons: '.modal-footer button',
|
||||||
|
cancel: 'button.cancel',
|
||||||
|
save: 'button.save'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
|
||||||
|
'click @ui.save': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
App.Api.Nginx.SslPassthroughHosts.delete(this.model.get('id'))
|
||||||
|
.then(() => {
|
||||||
|
App.Controller.showNginxSslPassthrough();
|
||||||
|
App.UI.closeModal();
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
alert(err.message);
|
||||||
|
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
34
frontend/js/app/nginx/ssl-passthrough/form.ejs
Normal file
34
frontend/js/app/nginx/ssl-passthrough/form.ejs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title"><%- i18n('ssl-passthrough-hosts', 'form-title', {id: id}) %></h5>
|
||||||
|
<button type="button" class="close cancel" aria-label="Close" data-dismiss="modal"> </button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<form>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12 col-md-12">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label"><%- i18n('all-hosts', 'domain-name') %> <span class="form-required">*</span></label>
|
||||||
|
<input type="text" name="domain_name" class="form-control" id="input-domain" placeholder="example.com" value="<%- domain_name %>" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-8 col-md-8">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label"><%- i18n('ssl-passthrough-hosts', 'forwarding-host') %><span class="form-required">*</span></label>
|
||||||
|
<input type="text" name="forwarding_host" class="form-control text-monospace" placeholder="example.com or 10.0.0.1 or 2001:db8:3333:4444:5555:6666:7777:8888" value="<%- forwarding_host %>" autocomplete="off" maxlength="255" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-4 col-md-4">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label"><%- i18n('ssl-passthrough-hosts', 'forwarding-port') %> <span class="form-required">*</span></label>
|
||||||
|
<input name="forwarding_port" type="number" class="form-control text-monospace" placeholder="eg: 443" value="<%- forwarding_port %>" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary cancel" data-dismiss="modal"><%- i18n('str', 'cancel') %></button>
|
||||||
|
<button type="button" class="btn btn-teal save"><%- i18n('str', 'save') %></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
74
frontend/js/app/nginx/ssl-passthrough/form.js
Normal file
74
frontend/js/app/nginx/ssl-passthrough/form.js
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const App = require('../../main');
|
||||||
|
const SslPassthroughModel = require('../../../models/ssl-passthrough-host');
|
||||||
|
const template = require('./form.ejs');
|
||||||
|
|
||||||
|
require('jquery-serializejson');
|
||||||
|
require('jquery-mask-plugin');
|
||||||
|
require('selectize');
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
template: template,
|
||||||
|
className: 'modal-dialog',
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
form: 'form',
|
||||||
|
forwarding_host: 'input[name="forwarding_host"]',
|
||||||
|
buttons: '.modal-footer button',
|
||||||
|
cancel: 'button.cancel',
|
||||||
|
save: 'button.save'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'change @ui.switches': function () {
|
||||||
|
this.ui.type_error.hide();
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.save': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (!this.ui.form[0].checkValidity()) {
|
||||||
|
$('<input type="submit">').hide().appendTo(this.ui.form).click().remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let view = this;
|
||||||
|
let data = this.ui.form.serializeJSON();
|
||||||
|
|
||||||
|
// Manipulate
|
||||||
|
data.forwarding_port = parseInt(data.forwarding_port, 10);
|
||||||
|
|
||||||
|
let method = App.Api.Nginx.SslPassthroughHosts.create;
|
||||||
|
let is_new = true;
|
||||||
|
|
||||||
|
if (this.model.get('id')) {
|
||||||
|
// edit
|
||||||
|
is_new = false;
|
||||||
|
method = App.Api.Nginx.SslPassthroughHosts.update;
|
||||||
|
data.id = this.model.get('id');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ui.buttons.prop('disabled', true).addClass('btn-disabled');
|
||||||
|
method(data)
|
||||||
|
.then(result => {
|
||||||
|
view.model.set(result);
|
||||||
|
|
||||||
|
App.UI.closeModal(function () {
|
||||||
|
if (is_new) {
|
||||||
|
App.Controller.showNginxSslPassthrough();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
alert(err.message);
|
||||||
|
this.ui.buttons.prop('disabled', false).removeClass('btn-disabled');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function (options) {
|
||||||
|
if (typeof options.model === 'undefined' || !options.model) {
|
||||||
|
this.model = new SslPassthroughModel.Model();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
43
frontend/js/app/nginx/ssl-passthrough/list/item.ejs
Normal file
43
frontend/js/app/nginx/ssl-passthrough/list/item.ejs
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<td class="text-center">
|
||||||
|
<div class="avatar d-block" style="background-image: url(<%- owner.avatar || '/images/default-avatar.jpg' %>)" title="Owned by <%- owner.name %>">
|
||||||
|
<span class="avatar-status <%- owner.is_disabled ? 'bg-red' : 'bg-green' %>"></span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="text-monospace">
|
||||||
|
<%- domain_name %>
|
||||||
|
</div>
|
||||||
|
<div class="small text-muted">
|
||||||
|
<%- i18n('str', 'created-on', {date: formatDbDate(created_on, 'Do MMMM YYYY')}) %>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="text-monospace"><%- forwarding_host %>:<%- forwarding_port %></div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<%
|
||||||
|
var o = isOnline();
|
||||||
|
if (!enabled) { %>
|
||||||
|
<span class="status-icon bg-warning"></span> <%- i18n('str', 'disabled') %>
|
||||||
|
<% } else if (o === true) { %>
|
||||||
|
<span class="status-icon bg-success"></span> <%- i18n('str', 'online') %>
|
||||||
|
<% } else if (o === false) { %>
|
||||||
|
<span title="<%- getOfflineError() %>"><span class="status-icon bg-danger"></span> <%- i18n('str', 'offline') %></span>
|
||||||
|
<% } else { %>
|
||||||
|
<span class="status-icon bg-warning"></span> <%- i18n('str', 'unknown') %>
|
||||||
|
<% } %>
|
||||||
|
</td>
|
||||||
|
<% if (canManage) { %>
|
||||||
|
<td class="text-right">
|
||||||
|
<div class="item-action dropdown">
|
||||||
|
<a href="#" data-toggle="dropdown" class="icon"><i class="fe fe-more-vertical"></i></a>
|
||||||
|
<div class="dropdown-menu dropdown-menu-right">
|
||||||
|
<span class="dropdown-header"><%- i18n('audit-log', 'ssl-passthrough-host') %> #<%- id %></span>
|
||||||
|
<a href="#" class="edit dropdown-item"><i class="dropdown-icon fe fe-edit"></i> <%- i18n('str', 'edit') %></a>
|
||||||
|
<a href="#" class="able dropdown-item"><i class="dropdown-icon fe fe-power"></i> <%- i18n('str', enabled ? 'disable' : 'enable') %></a>
|
||||||
|
<div class="dropdown-divider"></div>
|
||||||
|
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<% } %>
|
54
frontend/js/app/nginx/ssl-passthrough/list/item.js
Normal file
54
frontend/js/app/nginx/ssl-passthrough/list/item.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const App = require('../../../main');
|
||||||
|
const template = require('./item.ejs');
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
template: template,
|
||||||
|
tagName: 'tr',
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
able: 'a.able',
|
||||||
|
edit: 'a.edit',
|
||||||
|
delete: 'a.delete'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'click @ui.able': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let id = this.model.get('id');
|
||||||
|
App.Api.Nginx.SslPassthroughHosts[this.model.get('enabled') ? 'disable' : 'enable'](id)
|
||||||
|
.then(() => {
|
||||||
|
return App.Api.Nginx.SslPassthroughHosts.get(id)
|
||||||
|
.then(row => {
|
||||||
|
this.model.set(row);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.edit': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
App.Controller.showNginxSslPassthroughForm(this.model);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.delete': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
App.Controller.showNginxSslPassthroughDeleteConfirm(this.model);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
templateContext: {
|
||||||
|
canManage: App.Cache.User.canManage('ssl_passthrough_hosts'),
|
||||||
|
|
||||||
|
isOnline: function () {
|
||||||
|
return typeof this.meta.nginx_online === 'undefined' ? null : this.meta.nginx_online;
|
||||||
|
},
|
||||||
|
|
||||||
|
getOfflineError: function () {
|
||||||
|
return this.meta.nginx_err || '';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function () {
|
||||||
|
this.listenTo(this.model, 'change', this.render);
|
||||||
|
}
|
||||||
|
});
|
12
frontend/js/app/nginx/ssl-passthrough/list/main.ejs
Normal file
12
frontend/js/app/nginx/ssl-passthrough/list/main.ejs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<thead>
|
||||||
|
<th width="30"> </th>
|
||||||
|
<th><%- i18n('all-hosts', 'domain-name') %></th>
|
||||||
|
<th><%- i18n('str', 'destination') %></th>
|
||||||
|
<th><%- i18n('str', 'status') %></th>
|
||||||
|
<% if (canManage) { %>
|
||||||
|
<th> </th>
|
||||||
|
<% } %>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<!-- items -->
|
||||||
|
</tbody>
|
32
frontend/js/app/nginx/ssl-passthrough/list/main.js
Normal file
32
frontend/js/app/nginx/ssl-passthrough/list/main.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const App = require('../../../main');
|
||||||
|
const ItemView = require('./item');
|
||||||
|
const template = require('./main.ejs');
|
||||||
|
|
||||||
|
const TableBody = Mn.CollectionView.extend({
|
||||||
|
tagName: 'tbody',
|
||||||
|
childView: ItemView
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
tagName: 'table',
|
||||||
|
className: 'table table-hover table-outline table-vcenter card-table',
|
||||||
|
template: template,
|
||||||
|
|
||||||
|
regions: {
|
||||||
|
body: {
|
||||||
|
el: 'tbody',
|
||||||
|
replaceElement: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
templateContext: {
|
||||||
|
canManage: App.Cache.User.canManage('ssl_passthrough_hosts')
|
||||||
|
},
|
||||||
|
|
||||||
|
onRender: function () {
|
||||||
|
this.showChildView('body', new TableBody({
|
||||||
|
collection: this.collection
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
23
frontend/js/app/nginx/ssl-passthrough/main.ejs
Normal file
23
frontend/js/app/nginx/ssl-passthrough/main.ejs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<div class="card">
|
||||||
|
<div class="card-status bg-dark"></div>
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title"><%- i18n('ssl-passthrough-hosts', 'title') %></h3>
|
||||||
|
<div class="card-options">
|
||||||
|
<a href="#" class="btn btn-outline-secondary btn-sm ml-2 help"><i class="fe fe-help-circle"></i></a>
|
||||||
|
<% if (showAddButton) { %>
|
||||||
|
<a href="#" class="btn btn-outline-dark btn-sm ml-2 add-item"><%- i18n('ssl-passthrough-hosts', 'add') %></a>
|
||||||
|
<% } %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body no-padding min-100">
|
||||||
|
<div id="ssl-passthrough-disabled-info" class="alert alert-danger rounded-0 mb-0">
|
||||||
|
<%= i18n('ssl-passthrough-hosts', 'is-disabled-warning', {url: 'https://nginxproxymanager.com/advanced-config/#ssl-passthrough'}) %>
|
||||||
|
</div>
|
||||||
|
<div class="dimmer active">
|
||||||
|
<div class="loader"></div>
|
||||||
|
<div class="dimmer-content list-region">
|
||||||
|
<!-- List Region -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
91
frontend/js/app/nginx/ssl-passthrough/main.js
Normal file
91
frontend/js/app/nginx/ssl-passthrough/main.js
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const App = require('../../main');
|
||||||
|
const SslPassthroughModel = require('../../../models/ssl-passthrough-host');
|
||||||
|
const ListView = require('./list/main');
|
||||||
|
const ErrorView = require('../../error/main');
|
||||||
|
const EmptyView = require('../../empty/main');
|
||||||
|
const template = require('./main.ejs');
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
id: 'nginx-ssl-passthrough',
|
||||||
|
template: template,
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
list_region: '.list-region',
|
||||||
|
add: '.add-item',
|
||||||
|
help: '.help',
|
||||||
|
dimmer: '.dimmer',
|
||||||
|
disabled_info: '#ssl-passthrough-disabled-info'
|
||||||
|
},
|
||||||
|
|
||||||
|
regions: {
|
||||||
|
list_region: '@ui.list_region'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'click @ui.add': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
App.Controller.showNginxSslPassthroughForm();
|
||||||
|
},
|
||||||
|
|
||||||
|
'click @ui.help': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
App.Controller.showHelp(App.i18n('ssl-passthrough-hosts', 'help-title'), App.i18n('ssl-passthrough-hosts', 'help-content'));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
templateContext: {
|
||||||
|
showAddButton: App.Cache.User.canManage('ssl_passthrough_hosts')
|
||||||
|
},
|
||||||
|
|
||||||
|
onRender: function () {
|
||||||
|
let view = this;
|
||||||
|
view.ui.disabled_info.hide();
|
||||||
|
|
||||||
|
App.Api.Nginx.SslPassthroughHosts.getFeatureEnabled().then((response) => {
|
||||||
|
if (response.ssl_passthrough_enabled === false) {
|
||||||
|
view.ui.disabled_info.show();
|
||||||
|
} else {
|
||||||
|
view.ui.disabled_info.hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
App.Api.Nginx.SslPassthroughHosts.getAll(['owner'])
|
||||||
|
.then(response => {
|
||||||
|
if (!view.isDestroyed()) {
|
||||||
|
if (response && response.length) {
|
||||||
|
view.showChildView('list_region', new ListView({
|
||||||
|
collection: new SslPassthroughModel.Collection(response)
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
let manage = App.Cache.User.canManage('ssl_passthrough_hosts');
|
||||||
|
|
||||||
|
view.showChildView('list_region', new EmptyView({
|
||||||
|
title: App.i18n('ssl-passthrough-hosts', 'empty'),
|
||||||
|
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
||||||
|
link: manage ? App.i18n('ssl-passthrough-hosts', 'add') : null,
|
||||||
|
btn_color: 'dark',
|
||||||
|
permission: 'ssl-passthrough-hosts',
|
||||||
|
action: function () {
|
||||||
|
App.Controller.showNginxSslPassthroughForm();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
view.showChildView('list_region', new ErrorView({
|
||||||
|
code: err.code,
|
||||||
|
message: err.message,
|
||||||
|
retry: function () {
|
||||||
|
App.Controller.showNginxSslPassthrough();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
view.ui.dimmer.removeClass('active');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
@ -14,8 +14,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-sm-8 col-md-8">
|
<div class="col-sm-8 col-md-8">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label"><%- i18n('streams', 'forward-ip') %><span class="form-required">*</span></label>
|
<label class="form-label"><%- i18n('streams', 'forwarding-host') %><span class="form-required">*</span></label>
|
||||||
<input type="text" name="forward_ip" class="form-control text-monospace" placeholder="000.000.000.000" value="<%- forward_ip %>" autocomplete="off" maxlength="15" required>
|
<input type="text" name="forwarding_host" class="form-control text-monospace" placeholder="example.com or 10.0.0.1 or 2001:db8:3333:4444:5555:6666:7777:8888" value="<%- forwarding_host %>" autocomplete="off" maxlength="255" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4 col-md-4">
|
<div class="col-sm-4 col-md-4">
|
||||||
|
@ -13,7 +13,7 @@ module.exports = Mn.View.extend({
|
|||||||
|
|
||||||
ui: {
|
ui: {
|
||||||
form: 'form',
|
form: 'form',
|
||||||
forward_ip: 'input[name="forward_ip"]',
|
forwarding_host: 'input[name="forwarding_host"]',
|
||||||
type_error: '.forward-type-error',
|
type_error: '.forward-type-error',
|
||||||
buttons: '.modal-footer button',
|
buttons: '.modal-footer button',
|
||||||
switches: '.custom-switch-input',
|
switches: '.custom-switch-input',
|
||||||
@ -76,13 +76,6 @@ module.exports = Mn.View.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onRender: function () {
|
|
||||||
this.ui.forward_ip.mask('099.099.099.099', {
|
|
||||||
clearIfNotMatch: true,
|
|
||||||
placeholder: '000.000.000.000'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
initialize: function (options) {
|
initialize: function (options) {
|
||||||
if (typeof options.model === 'undefined' || !options.model) {
|
if (typeof options.model === 'undefined' || !options.model) {
|
||||||
this.model = new StreamModel.Model();
|
this.model = new StreamModel.Model();
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="text-monospace"><%- forward_ip %>:<%- forwarding_port %></div>
|
<div class="text-monospace"><%- forwarding_host %>:<%- forwarding_port %></div>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<div>
|
<div>
|
||||||
|
@ -4,16 +4,17 @@ const Controller = require('./controller');
|
|||||||
module.exports = AppRouter.default.extend({
|
module.exports = AppRouter.default.extend({
|
||||||
controller: Controller,
|
controller: Controller,
|
||||||
appRoutes: {
|
appRoutes: {
|
||||||
users: 'showUsers',
|
users: 'showUsers',
|
||||||
logout: 'logout',
|
logout: 'logout',
|
||||||
'nginx/proxy': 'showNginxProxy',
|
'nginx/proxy': 'showNginxProxy',
|
||||||
'nginx/redirection': 'showNginxRedirection',
|
'nginx/redirection': 'showNginxRedirection',
|
||||||
'nginx/404': 'showNginxDead',
|
'nginx/404': 'showNginxDead',
|
||||||
'nginx/stream': 'showNginxStream',
|
'nginx/ssl-passthrough': 'showNginxSslPassthrough',
|
||||||
'nginx/access': 'showNginxAccess',
|
'nginx/stream': 'showNginxStream',
|
||||||
'nginx/certificates': 'showNginxCertificates',
|
'nginx/access': 'showNginxAccess',
|
||||||
'audit-log': 'showAuditLog',
|
'nginx/certificates': 'showNginxCertificates',
|
||||||
'settings': 'showSettings',
|
'audit-log': 'showAuditLog',
|
||||||
'*default': 'showDashboard'
|
'settings': 'showSettings',
|
||||||
|
'*default': 'showDashboard'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
|
<button class="navbar-toggler d-lg-none mr-2" type="button" data-toggle="collapse" data-target="#menu">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
<a class="navbar-brand" href="/">
|
<a class="navbar-brand" href="/">
|
||||||
<img src="/images/favicons/favicon-32x32.png" border="0"> <%- i18n('main', 'app') %>
|
<img src="/images/favicons/favicon-32x32.png" border="0"> <%- i18n('main', 'app') %>
|
||||||
</a>
|
</a>
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
<div class="page-main">
|
<div class="page-main">
|
||||||
<div class="header" id="header">
|
<div class="navbar-light">
|
||||||
<!-- Header View -->
|
<div class="header" id="header">
|
||||||
</div>
|
<!-- Header View -->
|
||||||
<div id="menu">
|
</div>
|
||||||
<!-- Menu View -->
|
<div id="menu">
|
||||||
|
<!-- Menu View -->
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="my-3 my-md-5">
|
<div class="my-3 my-md-5">
|
||||||
<div id="app-content" class="container">
|
<div id="app-content" class="container">
|
||||||
|
@ -20,6 +20,10 @@
|
|||||||
<a href="/nginx/stream" class="dropdown-item "><%- i18n('streams', 'title') %></a>
|
<a href="/nginx/stream" class="dropdown-item "><%- i18n('streams', 'title') %></a>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
|
<% if (canShow('ssl_passthrough_hosts')) { %>
|
||||||
|
<a href="/nginx/ssl-passthrough" class="dropdown-item "><%- i18n('ssl-passthrough-hosts', 'title') %></a>
|
||||||
|
<% } %>
|
||||||
|
|
||||||
<% if (canShow('dead_hosts')) { %>
|
<% if (canShow('dead_hosts')) { %>
|
||||||
<a href="/nginx/404" class="dropdown-item "><%- i18n('dead-hosts', 'title') %></a>
|
<a href="/nginx/404" class="dropdown-item "><%- i18n('dead-hosts', 'title') %></a>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
@ -31,9 +31,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%
|
<%
|
||||||
var list = ['proxy-hosts', 'redirection-hosts', 'dead-hosts', 'streams', 'access-lists', 'certificates'];
|
var list = ['proxy-hosts', 'redirection-hosts', 'dead-hosts', 'streams', 'ssl-passthrough-hosts', 'access-lists', 'certificates'];
|
||||||
list.map(function(item) {
|
list.map(function(item) {
|
||||||
var perm = item.replace('-', '_');
|
var perm = item.replace(/-/g, '_');
|
||||||
%>
|
%>
|
||||||
<div class="col-sm-12 col-md-12">
|
<div class="col-sm-12 col-md-12">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -29,12 +29,13 @@ module.exports = Mn.View.extend({
|
|||||||
if (view.model.isAdmin()) {
|
if (view.model.isAdmin()) {
|
||||||
// Force some attributes for admin
|
// Force some attributes for admin
|
||||||
data = _.assign({}, data, {
|
data = _.assign({}, data, {
|
||||||
access_lists: 'manage',
|
access_lists: 'manage',
|
||||||
dead_hosts: 'manage',
|
dead_hosts: 'manage',
|
||||||
proxy_hosts: 'manage',
|
proxy_hosts: 'manage',
|
||||||
redirection_hosts: 'manage',
|
redirection_hosts: 'manage',
|
||||||
streams: 'manage',
|
ssl_passthrough_hosts: 'manage',
|
||||||
certificates: 'manage'
|
streams: 'manage',
|
||||||
|
certificates: 'manage'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +72,7 @@
|
|||||||
"enable-ssl": "Enable SSL",
|
"enable-ssl": "Enable SSL",
|
||||||
"force-ssl": "Force SSL",
|
"force-ssl": "Force SSL",
|
||||||
"http2-support": "HTTP/2 Support",
|
"http2-support": "HTTP/2 Support",
|
||||||
|
"domain-name": "Domain Name",
|
||||||
"domain-names": "Domain Names",
|
"domain-names": "Domain Names",
|
||||||
"cert-provider": "Certificate Provider",
|
"cert-provider": "Certificate Provider",
|
||||||
"block-exploits": "Block Common Exploits",
|
"block-exploits": "Block Common Exploits",
|
||||||
@ -115,6 +116,19 @@
|
|||||||
"processing-info": "Processing... 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."
|
"passphrase-protection-support-info": "Key files protected with a passphrase are not supported."
|
||||||
},
|
},
|
||||||
|
"ssl-passthrough-hosts": {
|
||||||
|
"title": "SSL Passthrough Hosts",
|
||||||
|
"empty": "There are no SSL Passthrough Hosts",
|
||||||
|
"add": "Add SSL Passthrough Hosts",
|
||||||
|
"form-title": "{id, select, undefined{New} other{Edit}} SSL Passthrough Host",
|
||||||
|
"forwarding-host": "Forward Host",
|
||||||
|
"forwarding-port": "Forward Port",
|
||||||
|
"delete": "Delete SSL Passthrough Host",
|
||||||
|
"delete-confirm": "Are you sure you want to delete this SSL Passthrough Host?",
|
||||||
|
"is-disabled-warning": "SSL Passthrough Hosts are not enabled in the environment. Please see <a href=\"{url}\" target=\"_blank\">the docs</a> for more information.",
|
||||||
|
"help-title": "What is an SSL Passthrough Host?",
|
||||||
|
"help-content": "An SSL Passthrough Host will allow you to proxy a server without SSL termination. This means the SSL encryption of the server will be passed right through the proxy, retaining the upstream certificate.\n Because of the SSL encryption the proxy does not know anything about the traffic, and it just relies on an SSL feature called Server Name Indication to know where to send this packet. This also means if the client does not provide this additional information, accessing the site through the proxy won't be possible. But most modern browsers include this information in HTTP requests.\n\nDue to nginx constraints using SSL Passthrough comes with a performance penalty for other hosts, since all hosts (including normal proxy hosts) now have to pass through this additional step and basically being proxied twice. If you want to retain the upstream SSL certificate but do not need your service to be available on port 443, it is recommended to use a stream host instead."
|
||||||
|
},
|
||||||
"proxy-hosts": {
|
"proxy-hosts": {
|
||||||
"title": "Proxy Hosts",
|
"title": "Proxy Hosts",
|
||||||
"empty": "There are no Proxy Hosts",
|
"empty": "There are no Proxy Hosts",
|
||||||
@ -130,7 +144,7 @@
|
|||||||
"access-list": "Access List",
|
"access-list": "Access List",
|
||||||
"allow-websocket-upgrade": "Websockets Support",
|
"allow-websocket-upgrade": "Websockets Support",
|
||||||
"ignore-invalid-upstream-ssl": "Ignore Invalid SSL",
|
"ignore-invalid-upstream-ssl": "Ignore Invalid SSL",
|
||||||
"custom-forward-host-help": "Use 1.1.1.1/path for sub-folder forwarding"
|
"custom-forward-host-help": "Add a path for sub-folder forwarding.\nExample: 203.0.113.25/path"
|
||||||
},
|
},
|
||||||
"redirection-hosts": {
|
"redirection-hosts": {
|
||||||
"title": "Redirection Hosts",
|
"title": "Redirection Hosts",
|
||||||
@ -162,7 +176,7 @@
|
|||||||
"add": "Add Stream",
|
"add": "Add Stream",
|
||||||
"form-title": "{id, select, undefined{New} other{Edit}} Stream",
|
"form-title": "{id, select, undefined{New} other{Edit}} Stream",
|
||||||
"incoming-port": "Incoming Port",
|
"incoming-port": "Incoming Port",
|
||||||
"forward-ip": "Forward IP",
|
"forwarding-host": "Forward Host",
|
||||||
"forwarding-port": "Forward Port",
|
"forwarding-port": "Forward Port",
|
||||||
"tcp-forwarding": "TCP Forwarding",
|
"tcp-forwarding": "TCP Forwarding",
|
||||||
"udp-forwarding": "UDP Forwarding",
|
"udp-forwarding": "UDP Forwarding",
|
||||||
@ -188,6 +202,7 @@
|
|||||||
"other-certificate-key": "Certificate Key",
|
"other-certificate-key": "Certificate Key",
|
||||||
"other-intermediate-certificate": "Intermediate Certificate",
|
"other-intermediate-certificate": "Intermediate Certificate",
|
||||||
"force-renew": "Renew Now",
|
"force-renew": "Renew Now",
|
||||||
|
"download": "Download",
|
||||||
"renew-title": "Renew Let'sEncrypt Certificate"
|
"renew-title": "Renew Let'sEncrypt Certificate"
|
||||||
},
|
},
|
||||||
"access-lists": {
|
"access-lists": {
|
||||||
@ -247,6 +262,7 @@
|
|||||||
"proxy-host": "Proxy Host",
|
"proxy-host": "Proxy Host",
|
||||||
"redirection-host": "Redirection Host",
|
"redirection-host": "Redirection Host",
|
||||||
"dead-host": "404 Host",
|
"dead-host": "404 Host",
|
||||||
|
"ssl-passthrough-host": "SSL Passthrough Host",
|
||||||
"stream": "Stream",
|
"stream": "Stream",
|
||||||
"user": "User",
|
"user": "User",
|
||||||
"certificate": "Certificate",
|
"certificate": "Certificate",
|
||||||
|
27
frontend/js/models/ssl-passthrough-host.js
Normal file
27
frontend/js/models/ssl-passthrough-host.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
const Backbone = require('backbone');
|
||||||
|
|
||||||
|
const model = Backbone.Model.extend({
|
||||||
|
idAttribute: 'id',
|
||||||
|
|
||||||
|
defaults: function () {
|
||||||
|
return {
|
||||||
|
id: undefined,
|
||||||
|
created_on: null,
|
||||||
|
modified_on: null,
|
||||||
|
domain_name: null,
|
||||||
|
forwarding_host: null,
|
||||||
|
forwarding_port: null,
|
||||||
|
enabled: true,
|
||||||
|
meta: {},
|
||||||
|
// The following are expansions:
|
||||||
|
owner: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
Model: model,
|
||||||
|
Collection: Backbone.Collection.extend({
|
||||||
|
model: model
|
||||||
|
})
|
||||||
|
};
|
@ -9,7 +9,7 @@ const model = Backbone.Model.extend({
|
|||||||
created_on: null,
|
created_on: null,
|
||||||
modified_on: null,
|
modified_on: null,
|
||||||
incoming_port: null,
|
incoming_port: null,
|
||||||
forward_ip: null,
|
forwarding_host: null,
|
||||||
forwarding_port: null,
|
forwarding_port: null,
|
||||||
tcp_forwarding: true,
|
tcp_forwarding: true,
|
||||||
udp_forwarding: false,
|
udp_forwarding: false,
|
||||||
|
@ -28,10 +28,10 @@
|
|||||||
"messageformat-loader": "^0.8.1",
|
"messageformat-loader": "^0.8.1",
|
||||||
"mini-css-extract-plugin": "^0.9.0",
|
"mini-css-extract-plugin": "^0.9.0",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
"node-sass": "^4.13.1",
|
"node-sass": "^6.0.1",
|
||||||
"nodemon": "^2.0.2",
|
"nodemon": "^2.0.2",
|
||||||
"numeral": "^2.0.6",
|
"numeral": "^2.0.6",
|
||||||
"sass-loader": "^8.0.2",
|
"sass-loader": "10.2.0",
|
||||||
"style-loader": "^1.1.3",
|
"style-loader": "^1.1.3",
|
||||||
"tabler-ui": "git+https://github.com/tabler/tabler.git#00f78ad823311bc3ad974ac3e5b0126198f0a813",
|
"tabler-ui": "git+https://github.com/tabler/tabler.git#00f78ad823311bc3ad974ac3e5b0126198f0a813",
|
||||||
"underscore": "^1.12.1",
|
"underscore": "^1.12.1",
|
||||||
|
@ -12,6 +12,15 @@ a:hover {
|
|||||||
color: darken($primary-color, 10%);
|
color: darken($primary-color, 10%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.alert-danger a {
|
||||||
|
color: #6b1110;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: darken(#6b1110, 10%);
|
||||||
|
}
|
||||||
|
|
||||||
.dropdown-header {
|
.dropdown-header {
|
||||||
padding-left: 1rem;
|
padding-left: 1rem;
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -9,7 +9,7 @@
|
|||||||
* cloudflare: {
|
* cloudflare: {
|
||||||
* display_name: "Name displayed to the user",
|
* display_name: "Name displayed to the user",
|
||||||
* package_name: "Package name in PyPi repo",
|
* package_name: "Package name in PyPi repo",
|
||||||
* package_version: "Package version in PyPi repo",
|
* version_requirement: "Optional package version requirements (e.g. ==1.3 or >=1.2,<2.0, see https://www.python.org/dev/peps/pep-0440/#version-specifiers)",
|
||||||
* dependencies: "Additional dependencies, space separated (as you would pass it to pip install)",
|
* dependencies: "Additional dependencies, space separated (as you would pass it to pip install)",
|
||||||
* credentials: `Template of the credentials file`,
|
* 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'",
|
* full_plugin_name: "The full plugin name as used in the commandline with certbot, including prefixes, e.g. 'certbot-dns-njalla:dns-njalla'",
|
||||||
@ -22,30 +22,30 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
//####################################################//
|
//####################################################//
|
||||||
acmedns: {
|
acmedns: {
|
||||||
display_name: 'ACME-DNS',
|
display_name: 'ACME-DNS',
|
||||||
package_name: 'certbot-dns-acmedns',
|
package_name: 'certbot-dns-acmedns',
|
||||||
package_version: '0.1.0',
|
version_requirement: '~=0.1.0',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `certbot_dns_acmedns:dns_acmedns_api_url = http://acmedns-server/
|
credentials: `certbot_dns_acmedns:dns_acmedns_api_url = http://acmedns-server/
|
||||||
certbot_dns_acmedns:dns_acmedns_registration_file = /data/acme-registration.json`,
|
certbot_dns_acmedns:dns_acmedns_registration_file = /data/acme-registration.json`,
|
||||||
full_plugin_name: 'certbot-dns-acmedns:dns-acmedns',
|
full_plugin_name: 'certbot-dns-acmedns:dns-acmedns',
|
||||||
},
|
},
|
||||||
aliyun: {
|
aliyun: {
|
||||||
display_name: 'Aliyun',
|
display_name: 'Aliyun',
|
||||||
package_name: 'certbot-dns-aliyun',
|
package_name: 'certbot-dns-aliyun',
|
||||||
package_version: '0.38.1',
|
version_requirement: '~=0.38.1',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `certbot_dns_aliyun:dns_aliyun_access_key = 12345678
|
credentials: `certbot_dns_aliyun:dns_aliyun_access_key = 12345678
|
||||||
certbot_dns_aliyun:dns_aliyun_access_key_secret = 1234567890abcdef1234567890abcdef`,
|
certbot_dns_aliyun:dns_aliyun_access_key_secret = 1234567890abcdef1234567890abcdef`,
|
||||||
full_plugin_name: 'certbot-dns-aliyun:dns-aliyun',
|
full_plugin_name: 'certbot-dns-aliyun:dns-aliyun',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
azure: {
|
azure: {
|
||||||
display_name: 'Azure',
|
display_name: 'Azure',
|
||||||
package_name: 'certbot-dns-azure',
|
package_name: 'certbot-dns-azure',
|
||||||
package_version: '1.2.0',
|
version_requirement: '~=1.2.0',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `# This plugin supported API authentication using either Service Principals or utilizing a Managed Identity assigned to the virtual machine.
|
credentials: `# This plugin supported API authentication using either Service Principals or utilizing a Managed Identity assigned to the virtual machine.
|
||||||
# Regardless which authentication method used, the identity will need the “DNS Zone Contributor” role assigned to it.
|
# Regardless which authentication method used, the identity will need the “DNS Zone Contributor” role assigned to it.
|
||||||
# As multiple Azure DNS Zones in multiple resource groups can exist, the config file needs a mapping of zone to resource group ID. Multiple zones -> ID mappings can be listed by using the key dns_azure_zoneX where X is a unique number. At least 1 zone mapping is required.
|
# As multiple Azure DNS Zones in multiple resource groups can exist, the config file needs a mapping of zone to resource group ID. Multiple zones -> ID mappings can be listed by using the key dns_azure_zoneX where X is a unique number. At least 1 zone mapping is required.
|
||||||
|
|
||||||
@ -67,165 +67,175 @@ dns_azure_zone2 = example.org:/subscriptions/99800903-fb14-4992-9aff-12eaf274462
|
|||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
cloudflare: {
|
cloudflare: {
|
||||||
display_name: 'Cloudflare',
|
display_name: 'Cloudflare',
|
||||||
package_name: 'certbot-dns-cloudflare',
|
package_name: 'certbot-dns-cloudflare',
|
||||||
package_version: '1.8.0',
|
// version_requirement: '', // Official plugin, no version requirement
|
||||||
dependencies: 'cloudflare',
|
dependencies: 'cloudflare',
|
||||||
credentials: `# Cloudflare API token
|
credentials: `# Cloudflare API token
|
||||||
dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567`,
|
dns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567`,
|
||||||
full_plugin_name: 'dns-cloudflare',
|
full_plugin_name: 'dns-cloudflare',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
cloudns: {
|
cloudns: {
|
||||||
display_name: 'ClouDNS',
|
display_name: 'ClouDNS',
|
||||||
package_name: 'certbot-dns-cloudns',
|
package_name: 'certbot-dns-cloudns',
|
||||||
package_version: '0.4.0',
|
version_requirement: '~=0.4.0',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `# Target user ID (see https://www.cloudns.net/api-settings/)
|
credentials: `# Target user ID (see https://www.cloudns.net/api-settings/)
|
||||||
dns_cloudns_auth_id=1234
|
dns_cloudns_auth_id=1234
|
||||||
# Alternatively, one of the following two options can be set:
|
# Alternatively, one of the following two options can be set:
|
||||||
# dns_cloudns_sub_auth_id=1234
|
# dns_cloudns_sub_auth_id=1234
|
||||||
# dns_cloudns_sub_auth_user=foobar
|
# dns_cloudns_sub_auth_user=foobar
|
||||||
|
|
||||||
# API password
|
# API password
|
||||||
dns_cloudns_auth_password=password1`,
|
dns_cloudns_auth_password=password1`,
|
||||||
full_plugin_name: 'dns-cloudns',
|
full_plugin_name: 'dns-cloudns',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
cloudxns: {
|
cloudxns: {
|
||||||
display_name: 'CloudXNS',
|
display_name: 'CloudXNS',
|
||||||
package_name: 'certbot-dns-cloudxns',
|
package_name: 'certbot-dns-cloudxns',
|
||||||
package_version: '1.8.0',
|
// version_requirement: '', // Official plugin, no version requirement
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `dns_cloudxns_api_key = 1234567890abcdef1234567890abcdef
|
credentials: `dns_cloudxns_api_key = 1234567890abcdef1234567890abcdef
|
||||||
dns_cloudxns_secret_key = 1122334455667788`,
|
dns_cloudxns_secret_key = 1122334455667788`,
|
||||||
full_plugin_name: 'dns-cloudxns',
|
full_plugin_name: 'dns-cloudxns',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
corenetworks: {
|
corenetworks: {
|
||||||
display_name: 'Core Networks',
|
display_name: 'Core Networks',
|
||||||
package_name: 'certbot-dns-corenetworks',
|
package_name: 'certbot-dns-corenetworks',
|
||||||
package_version: '0.1.4',
|
version_requirement: '~=0.1.4',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `certbot_dns_corenetworks:dns_corenetworks_username = asaHB12r
|
credentials: `certbot_dns_corenetworks:dns_corenetworks_username = asaHB12r
|
||||||
certbot_dns_corenetworks:dns_corenetworks_password = secure_password`,
|
certbot_dns_corenetworks:dns_corenetworks_password = secure_password`,
|
||||||
full_plugin_name: 'certbot-dns-corenetworks:dns-corenetworks',
|
full_plugin_name: 'certbot-dns-corenetworks:dns-corenetworks',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
cpanel: {
|
cpanel: {
|
||||||
display_name: 'cPanel',
|
display_name: 'cPanel',
|
||||||
package_name: 'certbot-dns-cpanel',
|
package_name: 'certbot-dns-cpanel',
|
||||||
package_version: '0.2.2',
|
version_requirement: '~=0.2.2',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `certbot_dns_cpanel:cpanel_url = https://cpanel.example.com:2083
|
credentials: `certbot_dns_cpanel:cpanel_url = https://cpanel.example.com:2083
|
||||||
certbot_dns_cpanel:cpanel_username = user
|
certbot_dns_cpanel:cpanel_username = user
|
||||||
certbot_dns_cpanel:cpanel_password = hunter2`,
|
certbot_dns_cpanel:cpanel_password = hunter2`,
|
||||||
full_plugin_name: 'certbot-dns-cpanel:cpanel',
|
full_plugin_name: 'certbot-dns-cpanel:cpanel',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
|
desec: {
|
||||||
|
display_name: 'deSEC',
|
||||||
|
package_name: 'certbot-dns-desec',
|
||||||
|
version_requirement: '~=0.3.0',
|
||||||
|
dependencies: '',
|
||||||
|
credentials: `certbot_dns_desec:dns_desec_token = YOUR_DESEC_API_TOKEN
|
||||||
|
certbot_dns_desec:dns_desec_endpoint = https://desec.io/api/v1/`,
|
||||||
|
full_plugin_name: 'certbot-dns-desec:dns-desec',
|
||||||
|
},
|
||||||
|
//####################################################//
|
||||||
duckdns: {
|
duckdns: {
|
||||||
display_name: 'DuckDNS',
|
display_name: 'DuckDNS',
|
||||||
package_name: 'certbot-dns-duckdns',
|
package_name: 'certbot-dns-duckdns',
|
||||||
package_version: '0.6',
|
version_requirement: '~=0.6',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: 'dns_duckdns_token=your-duckdns-token',
|
credentials: 'dns_duckdns_token=your-duckdns-token',
|
||||||
full_plugin_name: 'dns-duckdns',
|
full_plugin_name: 'dns-duckdns',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
digitalocean: {
|
digitalocean: {
|
||||||
display_name: 'DigitalOcean',
|
display_name: 'DigitalOcean',
|
||||||
package_name: 'certbot-dns-digitalocean',
|
package_name: 'certbot-dns-digitalocean',
|
||||||
package_version: '1.8.0',
|
// version_requirement: '', // Official plugin, no version requirement
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: 'dns_digitalocean_token = 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff',
|
credentials: 'dns_digitalocean_token = 0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff',
|
||||||
full_plugin_name: 'dns-digitalocean',
|
full_plugin_name: 'dns-digitalocean',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
directadmin: {
|
directadmin: {
|
||||||
display_name: 'DirectAdmin',
|
display_name: 'DirectAdmin',
|
||||||
package_name: 'certbot-dns-directadmin',
|
package_name: 'certbot-dns-directadmin',
|
||||||
package_version: '0.0.20',
|
version_requirement: '~=0.0.23',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `directadmin_url = https://my.directadminserver.com:2222
|
credentials: `directadmin_url = https://my.directadminserver.com:2222
|
||||||
directadmin_username = username
|
directadmin_username = username
|
||||||
directadmin_password = aSuperStrongPassword`,
|
directadmin_password = aSuperStrongPassword`,
|
||||||
full_plugin_name: 'certbot-dns-directadmin:directadmin',
|
full_plugin_name: 'directadmin',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
dnsimple: {
|
dnsimple: {
|
||||||
display_name: 'DNSimple',
|
display_name: 'DNSimple',
|
||||||
package_name: 'certbot-dns-dnsimple',
|
package_name: 'certbot-dns-dnsimple',
|
||||||
package_version: '1.8.0',
|
// version_requirement: '', // Official plugin, no version requirement
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: 'dns_dnsimple_token = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw',
|
credentials: 'dns_dnsimple_token = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw',
|
||||||
full_plugin_name: 'dns-dnsimple',
|
full_plugin_name: 'dns-dnsimple',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
dnsmadeeasy: {
|
dnsmadeeasy: {
|
||||||
display_name: 'DNS Made Easy',
|
display_name: 'DNS Made Easy',
|
||||||
package_name: 'certbot-dns-dnsmadeeasy',
|
package_name: 'certbot-dns-dnsmadeeasy',
|
||||||
package_version: '1.8.0',
|
// version_requirement: '', // Official plugin, no version requirement
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `dns_dnsmadeeasy_api_key = 1c1a3c91-4770-4ce7-96f4-54c0eb0e457a
|
credentials: `dns_dnsmadeeasy_api_key = 1c1a3c91-4770-4ce7-96f4-54c0eb0e457a
|
||||||
dns_dnsmadeeasy_secret_key = c9b5625f-9834-4ff8-baba-4ed5f32cae55`,
|
dns_dnsmadeeasy_secret_key = c9b5625f-9834-4ff8-baba-4ed5f32cae55`,
|
||||||
full_plugin_name: 'dns-dnsmadeeasy',
|
full_plugin_name: 'dns-dnsmadeeasy',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
dnspod: {
|
dnspod: {
|
||||||
display_name: 'DNSPod',
|
display_name: 'DNSPod',
|
||||||
package_name: 'certbot-dns-dnspod',
|
package_name: 'certbot-dns-dnspod',
|
||||||
package_version: '0.1.0',
|
version_requirement: '~=0.1.0',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `certbot_dns_dnspod:dns_dnspod_email = "DNSPOD-API-REQUIRES-A-VALID-EMAIL"
|
credentials: `certbot_dns_dnspod:dns_dnspod_email = "DNSPOD-API-REQUIRES-A-VALID-EMAIL"
|
||||||
certbot_dns_dnspod:dns_dnspod_api_token = "DNSPOD-API-TOKEN"`,
|
certbot_dns_dnspod:dns_dnspod_api_token = "DNSPOD-API-TOKEN"`,
|
||||||
full_plugin_name: 'certbot-dns-dnspod:dns-dnspod',
|
full_plugin_name: 'certbot-dns-dnspod:dns-dnspod',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
dynu: {
|
dynu: {
|
||||||
display_name: 'Dynu',
|
display_name: 'Dynu',
|
||||||
package_name: 'certbot-dns-dynu',
|
package_name: 'certbot-dns-dynu',
|
||||||
package_version: '0.0.1',
|
version_requirement: '~=0.0.1',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: 'certbot_dns_dynu:dns_dynu_auth_token = YOUR_DYNU_AUTH_TOKEN',
|
credentials: 'certbot_dns_dynu:dns_dynu_auth_token = YOUR_DYNU_AUTH_TOKEN',
|
||||||
full_plugin_name: 'certbot-dns-dynu:dns-dynu',
|
full_plugin_name: 'certbot-dns-dynu:dns-dynu',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
eurodns: {
|
eurodns: {
|
||||||
display_name: 'EuroDNS',
|
display_name: 'EuroDNS',
|
||||||
package_name: 'certbot-dns-eurodns',
|
package_name: 'certbot-dns-eurodns',
|
||||||
package_version: '0.0.4',
|
version_requirement: '~=0.0.4',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `dns_eurodns_applicationId = myuser
|
credentials: `dns_eurodns_applicationId = myuser
|
||||||
dns_eurodns_apiKey = mysecretpassword
|
dns_eurodns_apiKey = mysecretpassword
|
||||||
dns_eurodns_endpoint = https://rest-api.eurodns.com/user-api-gateway/proxy`,
|
dns_eurodns_endpoint = https://rest-api.eurodns.com/user-api-gateway/proxy`,
|
||||||
full_plugin_name: 'certbot-dns-eurodns:dns-eurodns',
|
full_plugin_name: 'certbot-dns-eurodns:dns-eurodns',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
gandi: {
|
gandi: {
|
||||||
display_name: 'Gandi Live DNS',
|
display_name: 'Gandi Live DNS',
|
||||||
package_name: 'certbot_plugin_gandi',
|
package_name: 'certbot_plugin_gandi',
|
||||||
package_version: '1.2.5',
|
version_requirement: '~=1.2.5',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: 'certbot_plugin_gandi:dns_api_key = APIKEY',
|
credentials: 'certbot_plugin_gandi:dns_api_key = APIKEY',
|
||||||
full_plugin_name: 'certbot-plugin-gandi:dns',
|
full_plugin_name: 'certbot-plugin-gandi:dns',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
godaddy: {
|
godaddy: {
|
||||||
display_name: 'GoDaddy',
|
display_name: 'GoDaddy',
|
||||||
package_name: 'certbot-dns-godaddy',
|
package_name: 'certbot-dns-godaddy',
|
||||||
package_version: '0.2.0',
|
version_requirement: '~=0.2.0',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `dns_godaddy_secret = 0123456789abcdef0123456789abcdef01234567
|
credentials: `dns_godaddy_secret = 0123456789abcdef0123456789abcdef01234567
|
||||||
dns_godaddy_key = abcdef0123456789abcdef01234567abcdef0123`,
|
dns_godaddy_key = abcdef0123456789abcdef01234567abcdef0123`,
|
||||||
full_plugin_name: 'dns-godaddy',
|
full_plugin_name: 'dns-godaddy',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
google: {
|
google: {
|
||||||
display_name: 'Google',
|
display_name: 'Google',
|
||||||
package_name: 'certbot-dns-google',
|
package_name: 'certbot-dns-google',
|
||||||
package_version: '1.8.0',
|
// version_requirement: '', // Official plugin, no version requirement
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `{
|
credentials: `{
|
||||||
"type": "service_account",
|
"type": "service_account",
|
||||||
...
|
...
|
||||||
}`,
|
}`,
|
||||||
@ -233,29 +243,29 @@ dns_godaddy_key = abcdef0123456789abcdef01234567abcdef0123`,
|
|||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
hetzner: {
|
hetzner: {
|
||||||
display_name: 'Hetzner',
|
display_name: 'Hetzner',
|
||||||
package_name: 'certbot-dns-hetzner',
|
package_name: 'certbot-dns-hetzner',
|
||||||
package_version: '1.0.4',
|
version_requirement: '~=1.0.4',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: 'certbot_dns_hetzner:dns_hetzner_api_token = 0123456789abcdef0123456789abcdef',
|
credentials: 'certbot_dns_hetzner:dns_hetzner_api_token = 0123456789abcdef0123456789abcdef',
|
||||||
full_plugin_name: 'certbot-dns-hetzner:dns-hetzner',
|
full_plugin_name: 'certbot-dns-hetzner:dns-hetzner',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
infomaniak: {
|
infomaniak: {
|
||||||
display_name: 'Infomaniak',
|
display_name: 'Infomaniak',
|
||||||
package_name: 'certbot-dns-infomaniak',
|
package_name: 'certbot-dns-infomaniak',
|
||||||
package_version: '0.1.12',
|
version_requirement: '~=0.1.12',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: 'certbot_dns_infomaniak:dns_infomaniak_token = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
|
credentials: 'certbot_dns_infomaniak:dns_infomaniak_token = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
|
||||||
full_plugin_name: 'certbot-dns-infomaniak:dns-infomaniak',
|
full_plugin_name: 'certbot-dns-infomaniak:dns-infomaniak',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
inwx: {
|
inwx: {
|
||||||
display_name: 'INWX',
|
display_name: 'INWX',
|
||||||
package_name: 'certbot-dns-inwx',
|
package_name: 'certbot-dns-inwx',
|
||||||
package_version: '2.1.2',
|
version_requirement: '~=2.1.2',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `certbot_dns_inwx:dns_inwx_url = https://api.domrobot.com/xmlrpc/
|
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_username = your_username
|
||||||
certbot_dns_inwx:dns_inwx_password = your_password
|
certbot_dns_inwx:dns_inwx_password = your_password
|
||||||
certbot_dns_inwx:dns_inwx_shared_secret = your_shared_secret optional`,
|
certbot_dns_inwx:dns_inwx_shared_secret = your_shared_secret optional`,
|
||||||
@ -263,102 +273,126 @@ certbot_dns_inwx:dns_inwx_shared_secret = your_shared_secret optional`,
|
|||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
ionos: {
|
ionos: {
|
||||||
display_name: 'IONOS',
|
display_name: 'IONOS',
|
||||||
package_name: 'certbot-dns-ionos',
|
package_name: 'certbot-dns-ionos',
|
||||||
package_version: '0.0.7',
|
version_requirement: '~=0.0.7',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `certbot_dns_ionos:dns_ionos_prefix = myapikeyprefix
|
credentials: `certbot_dns_ionos:dns_ionos_prefix = myapikeyprefix
|
||||||
certbot_dns_ionos:dns_ionos_secret = verysecureapikeysecret
|
certbot_dns_ionos:dns_ionos_secret = verysecureapikeysecret
|
||||||
certbot_dns_ionos:dns_ionos_endpoint = https://api.hosting.ionos.com`,
|
certbot_dns_ionos:dns_ionos_endpoint = https://api.hosting.ionos.com`,
|
||||||
full_plugin_name: 'certbot-dns-ionos:dns-ionos',
|
full_plugin_name: 'certbot-dns-ionos:dns-ionos',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
ispconfig: {
|
ispconfig: {
|
||||||
display_name: 'ISPConfig',
|
display_name: 'ISPConfig',
|
||||||
package_name: 'certbot-dns-ispconfig',
|
package_name: 'certbot-dns-ispconfig',
|
||||||
package_version: '0.2.0',
|
version_requirement: '~=0.2.0',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `certbot_dns_ispconfig:dns_ispconfig_username = myremoteuser
|
credentials: `certbot_dns_ispconfig:dns_ispconfig_username = myremoteuser
|
||||||
certbot_dns_ispconfig:dns_ispconfig_password = verysecureremoteuserpassword
|
certbot_dns_ispconfig:dns_ispconfig_password = verysecureremoteuserpassword
|
||||||
certbot_dns_ispconfig:dns_ispconfig_endpoint = https://localhost:8080`,
|
certbot_dns_ispconfig:dns_ispconfig_endpoint = https://localhost:8080`,
|
||||||
full_plugin_name: 'certbot-dns-ispconfig:dns-ispconfig',
|
full_plugin_name: 'certbot-dns-ispconfig:dns-ispconfig',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
isset: {
|
isset: {
|
||||||
display_name: 'Isset',
|
display_name: 'Isset',
|
||||||
package_name: 'certbot-dns-isset',
|
package_name: 'certbot-dns-isset',
|
||||||
package_version: '0.0.3',
|
version_requirement: '~=0.0.3',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `certbot_dns_isset:dns_isset_endpoint="https://customer.isset.net/api"
|
credentials: `certbot_dns_isset:dns_isset_endpoint="https://customer.isset.net/api"
|
||||||
certbot_dns_isset:dns_isset_token="<token>"`,
|
certbot_dns_isset:dns_isset_token="<token>"`,
|
||||||
full_plugin_name: 'certbot-dns-isset:dns-isset',
|
full_plugin_name: 'certbot-dns-isset:dns-isset',
|
||||||
},
|
},
|
||||||
joker: {
|
joker: {
|
||||||
display_name: 'Joker',
|
display_name: 'Joker',
|
||||||
package_name: 'certbot-dns-joker',
|
package_name: 'certbot-dns-joker',
|
||||||
package_version: '1.1.0',
|
version_requirement: '~=1.1.0',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `certbot_dns_joker:dns_joker_username = <Dynamic DNS Authentication Username>
|
credentials: `certbot_dns_joker:dns_joker_username = <Dynamic DNS Authentication Username>
|
||||||
certbot_dns_joker:dns_joker_password = <Dynamic DNS Authentication Password>
|
certbot_dns_joker:dns_joker_password = <Dynamic DNS Authentication Password>
|
||||||
certbot_dns_joker:dns_joker_domain = <Dynamic DNS Domain>`,
|
certbot_dns_joker:dns_joker_domain = <Dynamic DNS Domain>`,
|
||||||
full_plugin_name: 'certbot-dns-joker:dns-joker',
|
full_plugin_name: 'certbot-dns-joker:dns-joker',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
linode: {
|
linode: {
|
||||||
display_name: 'Linode',
|
display_name: 'Linode',
|
||||||
package_name: 'certbot-dns-linode',
|
package_name: 'certbot-dns-linode',
|
||||||
package_version: '1.8.0',
|
// version_requirement: '', // Official plugin, no version requirement
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `dns_linode_key = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ64
|
credentials: `dns_linode_key = 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ64
|
||||||
dns_linode_version = [<blank>|3|4]`,
|
dns_linode_version = [<blank>|3|4]`,
|
||||||
full_plugin_name: 'dns-linode',
|
full_plugin_name: 'dns-linode',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
|
loopia: {
|
||||||
|
display_name: 'Loopia',
|
||||||
|
package_name: 'certbot-dns-loopia',
|
||||||
|
version_requirement: '~=1.0.0',
|
||||||
|
dependencies: '',
|
||||||
|
credentials: `dns_loopia_user = user@loopiaapi
|
||||||
|
dns_loopia_password = abcdef0123456789abcdef01234567abcdef0123`,
|
||||||
|
full_plugin_name: 'dns-loopia',
|
||||||
|
},
|
||||||
|
//####################################################//
|
||||||
luadns: {
|
luadns: {
|
||||||
display_name: 'LuaDNS',
|
display_name: 'LuaDNS',
|
||||||
package_name: 'certbot-dns-luadns',
|
package_name: 'certbot-dns-luadns',
|
||||||
package_version: '1.8.0',
|
// version_requirement: '', // Official plugin, no version requirement
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `dns_luadns_email = user@example.com
|
credentials: `dns_luadns_email = user@example.com
|
||||||
dns_luadns_token = 0123456789abcdef0123456789abcdef`,
|
dns_luadns_token = 0123456789abcdef0123456789abcdef`,
|
||||||
full_plugin_name: 'dns-luadns',
|
full_plugin_name: 'dns-luadns',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
netcup: {
|
netcup: {
|
||||||
display_name: 'netcup',
|
display_name: 'netcup',
|
||||||
package_name: 'certbot-dns-netcup',
|
package_name: 'certbot-dns-netcup',
|
||||||
package_version: '1.0.0',
|
version_requirement: '~=1.0.0',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `certbot_dns_netcup:dns_netcup_customer_id = 123456
|
credentials: `certbot_dns_netcup:dns_netcup_customer_id = 123456
|
||||||
certbot_dns_netcup:dns_netcup_api_key = 0123456789abcdef0123456789abcdef01234567
|
certbot_dns_netcup:dns_netcup_api_key = 0123456789abcdef0123456789abcdef01234567
|
||||||
certbot_dns_netcup:dns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123`,
|
certbot_dns_netcup:dns_netcup_api_password = abcdef0123456789abcdef01234567abcdef0123`,
|
||||||
full_plugin_name: 'certbot-dns-netcup:dns-netcup',
|
full_plugin_name: 'certbot-dns-netcup:dns-netcup',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
njalla: {
|
njalla: {
|
||||||
display_name: 'Njalla',
|
display_name: 'Njalla',
|
||||||
package_name: 'certbot-dns-njalla',
|
package_name: 'certbot-dns-njalla',
|
||||||
package_version: '1.0.0',
|
version_requirement: '~=1.0.0',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: 'certbot_dns_njalla:dns_njalla_token = 0123456789abcdef0123456789abcdef01234567',
|
credentials: 'certbot_dns_njalla:dns_njalla_token = 0123456789abcdef0123456789abcdef01234567',
|
||||||
full_plugin_name: 'certbot-dns-njalla:dns-njalla',
|
full_plugin_name: 'certbot-dns-njalla:dns-njalla',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
nsone: {
|
nsone: {
|
||||||
display_name: 'NS1',
|
display_name: 'NS1',
|
||||||
package_name: 'certbot-dns-nsone',
|
package_name: 'certbot-dns-nsone',
|
||||||
package_version: '1.8.0',
|
// version_requirement: '', // Official plugin, no version requirement
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: 'dns_nsone_api_key = MDAwMDAwMDAwMDAwMDAw',
|
credentials: 'dns_nsone_api_key = MDAwMDAwMDAwMDAwMDAw',
|
||||||
full_plugin_name: 'dns-nsone',
|
full_plugin_name: 'dns-nsone',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
|
oci: {
|
||||||
|
display_name: 'Oracle Cloud Infrastructure DNS',
|
||||||
|
package_name: 'certbot-dns-oci',
|
||||||
|
package_version: '0.3.6',
|
||||||
|
dependencies: 'oci',
|
||||||
|
credentials: `[DEFAULT]
|
||||||
|
user = ocid1.user.oc1...
|
||||||
|
fingerprint = xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
|
||||||
|
tenancy = ocid1.tenancy.oc1...
|
||||||
|
region = us-ashburn-1
|
||||||
|
key_file = ~/.oci/oci_api_key.pem`,
|
||||||
|
full_plugin_name: 'dns-oci',
|
||||||
|
},
|
||||||
|
//####################################################//
|
||||||
ovh: {
|
ovh: {
|
||||||
display_name: 'OVH',
|
display_name: 'OVH',
|
||||||
package_name: 'certbot-dns-ovh',
|
package_name: 'certbot-dns-ovh',
|
||||||
package_version: '1.8.0',
|
// version_requirement: '', // Official plugin, no version requirement
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `dns_ovh_endpoint = ovh-eu
|
credentials: `dns_ovh_endpoint = ovh-eu
|
||||||
dns_ovh_application_key = MDAwMDAwMDAwMDAw
|
dns_ovh_application_key = MDAwMDAwMDAwMDAw
|
||||||
dns_ovh_application_secret = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
|
dns_ovh_application_secret = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw
|
||||||
dns_ovh_consumer_key = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw`,
|
dns_ovh_consumer_key = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw`,
|
||||||
@ -366,41 +400,41 @@ dns_ovh_consumer_key = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw`,
|
|||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
porkbun: {
|
porkbun: {
|
||||||
display_name: 'Porkbun',
|
display_name: 'Porkbun',
|
||||||
package_name: 'certbot-dns-porkbun',
|
package_name: 'certbot-dns-porkbun',
|
||||||
package_version: '0.2',
|
version_requirement: '~=0.2',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `dns_porkbun_key=your-porkbun-api-key
|
credentials: `dns_porkbun_key=your-porkbun-api-key
|
||||||
dns_porkbun_secret=your-porkbun-api-secret`,
|
dns_porkbun_secret=your-porkbun-api-secret`,
|
||||||
full_plugin_name: 'dns-porkbun',
|
full_plugin_name: 'dns-porkbun',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
powerdns: {
|
powerdns: {
|
||||||
display_name: 'PowerDNS',
|
display_name: 'PowerDNS',
|
||||||
package_name: 'certbot-dns-powerdns',
|
package_name: 'certbot-dns-powerdns',
|
||||||
package_version: '0.2.0',
|
version_requirement: '~=0.2.0',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `certbot_dns_powerdns:dns_powerdns_api_url = https://api.mypowerdns.example.org
|
credentials: `certbot_dns_powerdns:dns_powerdns_api_url = https://api.mypowerdns.example.org
|
||||||
certbot_dns_powerdns:dns_powerdns_api_key = AbCbASsd!@34`,
|
certbot_dns_powerdns:dns_powerdns_api_key = AbCbASsd!@34`,
|
||||||
full_plugin_name: 'certbot-dns-powerdns:dns-powerdns',
|
full_plugin_name: 'certbot-dns-powerdns:dns-powerdns',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
regru: {
|
regru: {
|
||||||
display_name: 'reg.ru',
|
display_name: 'reg.ru',
|
||||||
package_name: 'certbot-regru',
|
package_name: 'certbot-regru',
|
||||||
package_version: '1.0.2',
|
version_requirement: '~=1.0.2',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `certbot_regru:dns_username=username
|
credentials: `certbot_regru:dns_username=username
|
||||||
certbot_regru:dns_password=password`,
|
certbot_regru:dns_password=password`,
|
||||||
full_plugin_name: 'certbot-regru:dns',
|
full_plugin_name: 'certbot-regru:dns',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
rfc2136: {
|
rfc2136: {
|
||||||
display_name: 'RFC 2136',
|
display_name: 'RFC 2136',
|
||||||
package_name: 'certbot-dns-rfc2136',
|
package_name: 'certbot-dns-rfc2136',
|
||||||
package_version: '1.8.0',
|
// version_requirement: '', // Official plugin, no version requirement
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `# Target DNS server
|
credentials: `# Target DNS server
|
||||||
dns_rfc2136_server = 192.0.2.1
|
dns_rfc2136_server = 192.0.2.1
|
||||||
# Target DNS port
|
# Target DNS port
|
||||||
dns_rfc2136_port = 53
|
dns_rfc2136_port = 53
|
||||||
@ -414,32 +448,32 @@ dns_rfc2136_algorithm = HMAC-SHA512`,
|
|||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
route53: {
|
route53: {
|
||||||
display_name: 'Route 53 (Amazon)',
|
display_name: 'Route 53 (Amazon)',
|
||||||
package_name: 'certbot-dns-route53',
|
package_name: 'certbot-dns-route53',
|
||||||
package_version: '1.8.0',
|
// version_requirement: '', // Official plugin, no version requirement
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `[default]
|
credentials: `[default]
|
||||||
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
|
aws_access_key_id=AKIAIOSFODNN7EXAMPLE
|
||||||
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`,
|
aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`,
|
||||||
full_plugin_name: 'dns-route53',
|
full_plugin_name: 'dns-route53',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
transip: {
|
transip: {
|
||||||
display_name: 'TransIP',
|
display_name: 'TransIP',
|
||||||
package_name: 'certbot-dns-transip',
|
package_name: 'certbot-dns-transip',
|
||||||
package_version: '0.3.3',
|
version_requirement: '~=0.3.3',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: `certbot_dns_transip:dns_transip_username = my_username
|
credentials: `certbot_dns_transip:dns_transip_username = my_username
|
||||||
certbot_dns_transip:dns_transip_key_file = /etc/letsencrypt/transip-rsa.key`,
|
certbot_dns_transip:dns_transip_key_file = /etc/letsencrypt/transip-rsa.key`,
|
||||||
full_plugin_name: 'certbot-dns-transip:dns-transip',
|
full_plugin_name: 'certbot-dns-transip:dns-transip',
|
||||||
},
|
},
|
||||||
//####################################################//
|
//####################################################//
|
||||||
vultr: {
|
vultr: {
|
||||||
display_name: 'Vultr',
|
display_name: 'Vultr',
|
||||||
package_name: 'certbot-dns-vultr',
|
package_name: 'certbot-dns-vultr',
|
||||||
package_version: '1.0.3',
|
version_requirement: '~=1.0.3',
|
||||||
dependencies: '',
|
dependencies: '',
|
||||||
credentials: 'certbot_dns_vultr:dns_vultr_key = YOUR_VULTR_API_KEY',
|
credentials: 'certbot_dns_vultr:dns_vultr_key = YOUR_VULTR_API_KEY',
|
||||||
full_plugin_name: 'certbot-dns-vultr:dns-vultr',
|
full_plugin_name: 'certbot-dns-vultr:dns-vultr',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user