Compare commits
85 Commits
671817d640
...
openidc
Author | SHA1 | Date | |
---|---|---|---|
fdb22e467b | |||
694d8a0f21 | |||
63d06da8a8 | |||
b5a0d74654 | |||
99cce7e2b0 | |||
120d50e5c0 | |||
5454fd61b3 | |||
b33012705b | |||
e948b60194 | |||
7913c9a07d | |||
d1c23b6286 | |||
c7e2946dbf | |||
8936402229 | |||
001c77e686 | |||
5578e825b1 | |||
c93656a7a1 | |||
50aeae234f | |||
a5c06c1a34 | |||
51414ced3a | |||
5e35e538af | |||
13fec42d1f | |||
b4560d7dde | |||
6f9eed8a61 | |||
d66e4e03e6 | |||
1d19c29bb0 | |||
e20a11de4a | |||
d3a654b546 | |||
bed387ebd4 | |||
6ac9a82279 | |||
ef23e796ec | |||
3754a569ba | |||
b383f46656 | |||
3ce477d350 | |||
516b4d991c | |||
12d77e3ab6 | |||
8d80af3a26 | |||
1f45e6a5e9 | |||
dcb9628c36 | |||
029b184398 | |||
2422587530 | |||
4ee940d3dc | |||
47dddc548b | |||
256a667e2c | |||
79cd0c5294 | |||
09a03edfd7 | |||
35f0fe745d | |||
f1e433714e | |||
035eaed0a4 | |||
4b100a384d | |||
c5c5fa0a5a | |||
280bac8b43 | |||
02aefa50cd | |||
4d91cfc397 | |||
79a453f2fe | |||
c62c09569d | |||
09bcf4010c | |||
6aeade6c98 | |||
8655b7d2db | |||
2d929dffa8 | |||
52eaa042d8 | |||
b35aa50b88 | |||
c575a706b5 | |||
587b97c2d3 | |||
317003beda | |||
5a761236c5 | |||
b135527347 | |||
abca9cc89c | |||
6721923601 | |||
a88f77c1a5 | |||
a5b21d0306 | |||
8eab8d71f2 | |||
d06572bb5f | |||
c55e47aacf | |||
aec30207da | |||
a91dcb144d | |||
e7f7be2a2b | |||
076d89b5b5 | |||
8539930f89 | |||
87d9babbd3 | |||
9f2d3a1737 | |||
daf399163c | |||
cdf702e545 | |||
5811345050 | |||
53792a5cf7 | |||
8e10b7da37 |
4
.gitignore
vendored
@ -3,3 +3,7 @@
|
||||
._*
|
||||
.vscode
|
||||
certbot-help.txt
|
||||
test/node_modules
|
||||
*/node_modules
|
||||
docker/dev/dnsrouter-config.json.tmp
|
||||
docker/dev/resolv.conf
|
||||
|
124
Jenkinsfile
vendored
@ -18,10 +18,8 @@ pipeline {
|
||||
BUILD_VERSION = getVersion()
|
||||
MAJOR_VERSION = '2'
|
||||
BRANCH_LOWER = "${BRANCH_NAME.toLowerCase().replaceAll('\\\\', '-').replaceAll('/', '-').replaceAll('\\.', '-')}"
|
||||
COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}"
|
||||
COMPOSE_FILE = 'docker/docker-compose.ci.yml'
|
||||
BUILDX_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}"
|
||||
COMPOSE_INTERACTIVE_NO_CLI = 1
|
||||
BUILDX_NAME = "${COMPOSE_PROJECT_NAME}"
|
||||
}
|
||||
stages {
|
||||
stage('Environment') {
|
||||
@ -92,81 +90,63 @@ pipeline {
|
||||
sh 'yarn install'
|
||||
sh 'yarn build'
|
||||
}
|
||||
dir(path: 'docs/.vuepress/dist') {
|
||||
sh 'tar -czf ../../docs.tgz *'
|
||||
}
|
||||
archiveArtifacts(artifacts: 'docs/docs.tgz', allowEmptyArchive: false)
|
||||
}
|
||||
}
|
||||
stage('Cypress') {
|
||||
}
|
||||
}
|
||||
stage('Test Sqlite') {
|
||||
environment {
|
||||
COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}_sqlite"
|
||||
COMPOSE_FILE = 'docker/docker-compose.ci.yml:docker/docker-compose.ci.sqlite.yml'
|
||||
}
|
||||
when {
|
||||
not {
|
||||
equals expected: 'UNSTABLE', actual: currentBuild.result
|
||||
}
|
||||
}
|
||||
steps {
|
||||
// Creating will also create the network prior to
|
||||
// using it in parallel stages below and mitigating
|
||||
// a race condition.
|
||||
sh 'docker-compose build cypress-sqlite'
|
||||
sh 'docker-compose build cypress-mysql'
|
||||
sh 'docker-compose create cypress-sqlite'
|
||||
sh 'docker-compose create cypress-mysql'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Integration Tests') {
|
||||
parallel {
|
||||
stage('Sqlite') {
|
||||
steps {
|
||||
// Bring up a stack
|
||||
sh 'docker-compose up -d fullstack-sqlite'
|
||||
sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-sqlite) 120'
|
||||
// Stop and Start it, as this will test it's ability to restart with existing data
|
||||
sh 'docker-compose stop fullstack-sqlite'
|
||||
sh 'docker-compose start fullstack-sqlite'
|
||||
sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-sqlite) 120'
|
||||
|
||||
// Run tests
|
||||
sh 'rm -rf test/results-sqlite'
|
||||
sh 'docker-compose up cypress-sqlite'
|
||||
// Get results
|
||||
sh 'docker cp -L "$(docker-compose ps --all -q cypress-sqlite):/test/results" test/results-sqlite'
|
||||
sh 'rm -rf ./test/results/junit/*'
|
||||
sh './scripts/ci/fulltest-cypress'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
// Dumps to analyze later
|
||||
sh 'mkdir -p debug/sqlite'
|
||||
sh 'docker-compose logs fullstack-sqlite > debug/sqlite/docker_fullstack_sqlite.log'
|
||||
// Cypress videos and screenshot artifacts
|
||||
dir(path: 'test/results-sqlite') {
|
||||
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
|
||||
}
|
||||
junit 'test/results-sqlite/junit/*'
|
||||
sh 'docker logs $(docker-compose ps --all -q fullstack) > debug/sqlite/docker_fullstack.log 2>&1'
|
||||
sh 'docker logs $(docker-compose ps --all -q stepca) > debug/sqlite/docker_stepca.log 2>&1'
|
||||
sh 'docker logs $(docker-compose ps --all -q pdns) > debug/sqlite/docker_pdns.log 2>&1'
|
||||
sh 'docker logs $(docker-compose ps --all -q pdns-db) > debug/sqlite/docker_pdns-db.log 2>&1'
|
||||
sh 'docker logs $(docker-compose ps --all -q dnsrouter) > debug/sqlite/docker_dnsrouter.log 2>&1'
|
||||
junit 'test/results/junit/*'
|
||||
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('Mysql') {
|
||||
stage('Test Mysql') {
|
||||
environment {
|
||||
COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}_mysql"
|
||||
COMPOSE_FILE = 'docker/docker-compose.ci.yml:docker/docker-compose.ci.mysql.yml'
|
||||
}
|
||||
when {
|
||||
not {
|
||||
equals expected: 'UNSTABLE', actual: currentBuild.result
|
||||
}
|
||||
}
|
||||
steps {
|
||||
// Bring up a stack
|
||||
sh 'docker-compose up -d fullstack-mysql'
|
||||
sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-mysql) 120'
|
||||
|
||||
// Run tests
|
||||
sh 'rm -rf test/results-mysql'
|
||||
sh 'docker-compose up cypress-mysql'
|
||||
// Get results
|
||||
sh 'docker cp -L "$(docker-compose ps --all -q cypress-mysql):/test/results" test/results-mysql'
|
||||
sh 'rm -rf ./test/results/junit/*'
|
||||
sh './scripts/ci/fulltest-cypress'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
// Dumps to analyze later
|
||||
sh 'mkdir -p debug/mysql'
|
||||
sh 'docker-compose logs fullstack-mysql > debug/mysql/docker_fullstack_mysql.log'
|
||||
sh 'docker-compose logs db > debug/mysql/docker_db.log'
|
||||
// Cypress videos and screenshot artifacts
|
||||
dir(path: 'test/results-mysql') {
|
||||
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
|
||||
}
|
||||
junit 'test/results-mysql/junit/*'
|
||||
}
|
||||
}
|
||||
sh 'docker logs $(docker-compose ps --all -q fullstack) > debug/mysql/docker_fullstack.log 2>&1'
|
||||
sh 'docker logs $(docker-compose ps --all -q stepca) > debug/mysql/docker_stepca.log 2>&1'
|
||||
sh 'docker logs $(docker-compose ps --all -q pdns) > debug/mysql/docker_pdns.log 2>&1'
|
||||
sh 'docker logs $(docker-compose ps --all -q pdns-db) > debug/mysql/docker_pdns-db.log 2>&1'
|
||||
sh 'docker logs $(docker-compose ps --all -q dnsrouter) > debug/mysql/docker_dnsrouter.log 2>&1'
|
||||
junit 'test/results/junit/*'
|
||||
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -185,30 +165,17 @@ pipeline {
|
||||
}
|
||||
stage('Docs / Comment') {
|
||||
parallel {
|
||||
stage('Master Docs') {
|
||||
stage('Docs Job') {
|
||||
when {
|
||||
allOf {
|
||||
branch 'master'
|
||||
branch pattern: "^(develop|master)\$", comparator: "REGEXP"
|
||||
not {
|
||||
equals expected: 'UNSTABLE', actual: currentBuild.result
|
||||
}
|
||||
}
|
||||
}
|
||||
steps {
|
||||
npmDocsReleaseMaster()
|
||||
}
|
||||
}
|
||||
stage('Develop Docs') {
|
||||
when {
|
||||
allOf {
|
||||
branch 'develop'
|
||||
not {
|
||||
equals expected: 'UNSTABLE', actual: currentBuild.result
|
||||
}
|
||||
}
|
||||
}
|
||||
steps {
|
||||
npmDocsReleaseDevelop()
|
||||
build wait: false, job: 'nginx-proxy-manager-docs', parameters: [string(name: 'docs_branch', value: "$BRANCH_NAME")]
|
||||
}
|
||||
}
|
||||
stage('PR Comment') {
|
||||
@ -231,9 +198,8 @@ pipeline {
|
||||
}
|
||||
post {
|
||||
always {
|
||||
sh 'docker-compose down --remove-orphans --volumes -t 30'
|
||||
sh 'echo Reverting ownership'
|
||||
sh 'docker run --rm -v $(pwd):/data jc21/ci-tools chown -R $(id -u):$(id -g) /data'
|
||||
sh 'docker run --rm -v "$(pwd):/data" jc21/ci-tools chown -R "$(id -u):$(id -g)" /data'
|
||||
}
|
||||
success {
|
||||
juxtapose event: 'success'
|
||||
|
@ -1,7 +1,7 @@
|
||||
<p align="center">
|
||||
<img src="https://nginxproxymanager.com/github.png">
|
||||
<br><br>
|
||||
<img src="https://img.shields.io/badge/version-2.11.1-green.svg?style=for-the-badge">
|
||||
<img src="https://img.shields.io/badge/version-2.11.3-green.svg?style=for-the-badge">
|
||||
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
|
||||
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge">
|
||||
</a>
|
||||
@ -56,7 +56,6 @@ I won't go in to too much detail here but here are the basics for someone new to
|
||||
2. Create a docker-compose.yml file similar to this:
|
||||
|
||||
```yml
|
||||
version: '3.8'
|
||||
services:
|
||||
app:
|
||||
image: 'docker.io/jc21/nginx-proxy-manager:latest'
|
||||
@ -102,11 +101,6 @@ Immediately after logging in with this default user you will be asked to modify
|
||||
|
||||
All are welcome to create pull requests for this project, against the `develop` branch. Official releases are created from the `master` branch.
|
||||
|
||||
Run the following commands to test locally:
|
||||
|
||||
- `cd backend && npm i && node_modules/eslint/bin/eslint.js .`
|
||||
- `cd test && npm i && npm run cypress`
|
||||
|
||||
CI is used in this project. All PR's must pass before being considered. After passing,
|
||||
docker builds for PR's are available on dockerhub for manual verifications.
|
||||
|
||||
|
@ -90,8 +90,6 @@
|
||||
"nginx_err": "Command failed: /usr/sbin/nginx -t -g \"error_log off;\"\nnginx: [emerg] unknown directive \"sdfsdfsdf\" in /data/nginx/proxy_host/1.conf:37\nnginx: configuration file /etc/nginx/nginx.conf test failed\n"
|
||||
},
|
||||
"allow_websocket_upgrade": 0,
|
||||
"enable_proxy_protocol": 0,
|
||||
"load_balancer_ip": "",
|
||||
"http2_support": 0,
|
||||
"forward_scheme": "http",
|
||||
"enabled": 1,
|
||||
@ -212,8 +210,6 @@
|
||||
"dns_challenge": false
|
||||
},
|
||||
"allow_websocket_upgrade": 0,
|
||||
"enable_proxy_protocol": 0,
|
||||
"load_balancer_ip": "",
|
||||
"http2_support": 0,
|
||||
"forward_scheme": "http",
|
||||
"enabled": 1,
|
||||
@ -1124,8 +1120,6 @@
|
||||
"advanced_config",
|
||||
"meta",
|
||||
"allow_websocket_upgrade",
|
||||
"enable_proxy_protocol",
|
||||
"load_balancer_ip",
|
||||
"http2_support",
|
||||
"forward_scheme",
|
||||
"enabled",
|
||||
@ -1199,12 +1193,6 @@
|
||||
"allow_websocket_upgrade": {
|
||||
"type": "integer"
|
||||
},
|
||||
"enable_proxy_protocol": {
|
||||
"type": "integer"
|
||||
},
|
||||
"load_balancer_ip": {
|
||||
"type": "string"
|
||||
},
|
||||
"http2_support": {
|
||||
"type": "integer"
|
||||
},
|
||||
|
@ -861,9 +861,8 @@ const internalCertificate = {
|
||||
logger.info(`Requesting Let'sEncrypt certificates via ${dnsPlugin.name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
|
||||
|
||||
const credentialsLocation = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
|
||||
// Escape single quotes and backslashes
|
||||
const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll('\'', '\\\'').replaceAll('\\', '\\\\');
|
||||
const credentialsCmd = 'mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
|
||||
fs.mkdirSync('/etc/letsencrypt/credentials', { recursive: true });
|
||||
fs.writeFileSync(credentialsLocation, certificate.meta.dns_provider_credentials, {mode: 0o600});
|
||||
|
||||
// Whether the plugin has a --<name>-credentials argument
|
||||
const hasConfigArg = certificate.meta.dns_provider !== 'route53';
|
||||
@ -898,17 +897,15 @@ const internalCertificate = {
|
||||
mainCmd = mainCmd + ' --dns-duckdns-no-txt-restore';
|
||||
}
|
||||
|
||||
logger.info('Command:', `${credentialsCmd} && && ${mainCmd}`);
|
||||
logger.info('Command:', mainCmd);
|
||||
|
||||
try {
|
||||
await utils.exec(credentialsCmd);
|
||||
const result = await utils.exec(mainCmd);
|
||||
logger.info(result);
|
||||
return result;
|
||||
} catch (err) {
|
||||
// Don't fail if file does not exist
|
||||
const delete_credentialsCmd = `rm -f '${credentialsLocation}' || true`;
|
||||
await utils.exec(delete_credentialsCmd);
|
||||
// Don't fail if file does not exist, so no need for action in the callback
|
||||
fs.unlink(credentialsLocation, () => {});
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
|
@ -155,7 +155,6 @@ const internalNginx = {
|
||||
let locationCopy = Object.assign({}, {access_list_id: host.access_list_id}, {certificate_id: host.certificate_id},
|
||||
{ssl_forced: host.ssl_forced}, {caching_enabled: host.caching_enabled}, {block_exploits: host.block_exploits},
|
||||
{allow_websocket_upgrade: host.allow_websocket_upgrade}, {http2_support: host.http2_support},
|
||||
{enable_proxy_protocol: host.enable_proxy_protocol}, {load_balancer_ip: host.load_balancer_ip},
|
||||
{hsts_enabled: host.hsts_enabled}, {hsts_subdomains: host.hsts_subdomains}, {access_list: host.access_list},
|
||||
{certificate: host.certificate}, host.locations[i]);
|
||||
|
||||
|
@ -93,7 +93,7 @@ const generateKeys = () => {
|
||||
try {
|
||||
fs.writeFileSync(keysFile, JSON.stringify(keys, null, 2));
|
||||
} catch (err) {
|
||||
logger.error('Could not write JWT key pair to config file: ' + keysFile + ': ' . err.message);
|
||||
logger.error('Could not write JWT key pair to config file: ' + keysFile + ': ' + err.message);
|
||||
process.exit(1);
|
||||
}
|
||||
logger.info('Wrote JWT key pair to config file: ' + keysFile);
|
||||
|
48
backend/migrations/20200522113248_openid_connect.js
Normal file
@ -0,0 +1,48 @@
|
||||
const migrate_name = 'openid_connect';
|
||||
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('proxy_host', function (proxy_host) {
|
||||
proxy_host.integer('openidc_enabled').notNull().unsigned().defaultTo(0);
|
||||
proxy_host.text('openidc_redirect_uri').notNull().defaultTo('');
|
||||
proxy_host.text('openidc_discovery').notNull().defaultTo('');
|
||||
proxy_host.text('openidc_auth_method').notNull().defaultTo('');
|
||||
proxy_host.text('openidc_client_id').notNull().defaultTo('');
|
||||
proxy_host.text('openidc_client_secret').notNull().defaultTo('');
|
||||
})
|
||||
.then(() => {
|
||||
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Undo Migrate
|
||||
*
|
||||
* @param {Object} knex
|
||||
* @param {Promise} Promise
|
||||
* @returns {Promise}
|
||||
*/
|
||||
exports.down = function (knex/*, Promise*/) {
|
||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
||||
proxy_host.dropColumn('openidc_enabled');
|
||||
proxy_host.dropColumn('openidc_redirect_uri');
|
||||
proxy_host.dropColumn('openidc_discovery');
|
||||
proxy_host.dropColumn('openidc_auth_method');
|
||||
proxy_host.dropColumn('openidc_client_id');
|
||||
proxy_host.dropColumn('openidc_client_secret');
|
||||
})
|
||||
.then(() => {
|
||||
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
||||
});
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
const migrate_name = 'proxy_protocol';
|
||||
const migrate_name = 'openid_allowed_users';
|
||||
const logger = require('../logger').migrate;
|
||||
|
||||
/**
|
||||
@ -14,13 +14,12 @@ exports.up = function (knex/*, Promise*/) {
|
||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||
|
||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
||||
proxy_host.integer('enable_proxy_protocol').notNull().unsigned().defaultTo(0);
|
||||
proxy_host.string('load_balancer_ip').notNull().defaultTo('');
|
||||
proxy_host.integer('openidc_restrict_users_enabled').notNull().unsigned().defaultTo(0);
|
||||
proxy_host.json('openidc_allowed_users').notNull().defaultTo([]);
|
||||
})
|
||||
.then(() => {
|
||||
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@ -32,10 +31,10 @@ exports.up = function (knex/*, Promise*/) {
|
||||
*/
|
||||
exports.down = function (knex/*, Promise*/) {
|
||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
||||
proxy_host.dropColumn('enable_proxy_protocol');
|
||||
proxy_host.dropColumn('load_balancer_ip');
|
||||
proxy_host.dropColumn('openidc_restrict_users_enabled');
|
||||
proxy_host.dropColumn('openidc_allowed_users');
|
||||
})
|
||||
.then(function () {
|
||||
.then(() => {
|
||||
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
||||
});
|
||||
};
|
@ -1,41 +0,0 @@
|
||||
const migrate_name = 'proxy_protocol_streams';
|
||||
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', function (stream) {
|
||||
stream.integer('enable_proxy_protocol').notNull().unsigned().defaultTo(0);
|
||||
stream.string('load_balancer_ip').notNull().defaultTo('');
|
||||
})
|
||||
.then(() => {
|
||||
logger.info('[' + migrate_name + '] stream Table altered');
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Undo Migrate
|
||||
*
|
||||
* @param {Object} knex
|
||||
* @param {Promise} Promise
|
||||
* @returns {Promise}
|
||||
*/
|
||||
exports.down = function (knex/*, Promise*/) {
|
||||
return knex.schema.table('stream', function (stream) {
|
||||
stream.dropColumn('enable_proxy_protocol');
|
||||
stream.dropColumn('load_balancer_ip');
|
||||
})
|
||||
.then(function () {
|
||||
logger.info('[' + migrate_name + '] stream Table altered');
|
||||
});
|
||||
};
|
@ -20,12 +20,23 @@ class ProxyHost extends Model {
|
||||
this.domain_names = [];
|
||||
}
|
||||
|
||||
// Default for openidc_allowed_users
|
||||
if (typeof this.openidc_allowed_users === 'undefined') {
|
||||
this.openidc_allowed_users = [];
|
||||
}
|
||||
|
||||
// Default for meta
|
||||
if (typeof this.meta === 'undefined') {
|
||||
this.meta = {};
|
||||
}
|
||||
|
||||
// Openidc defaults
|
||||
if (typeof this.openidc_auth_method === 'undefined') {
|
||||
this.openidc_auth_method = 'client_secret_post';
|
||||
}
|
||||
|
||||
this.domain_names.sort();
|
||||
this.openidc_allowed_users.sort();
|
||||
}
|
||||
|
||||
$beforeUpdate () {
|
||||
@ -35,6 +46,11 @@ class ProxyHost extends Model {
|
||||
if (typeof this.domain_names !== 'undefined') {
|
||||
this.domain_names.sort();
|
||||
}
|
||||
|
||||
// Sort openidc_allowed_users
|
||||
if (typeof this.openidc_allowed_users !== 'undefined') {
|
||||
this.openidc_allowed_users.sort();
|
||||
}
|
||||
}
|
||||
|
||||
static get name () {
|
||||
@ -46,7 +62,7 @@ class ProxyHost extends Model {
|
||||
}
|
||||
|
||||
static get jsonAttributes () {
|
||||
return ['domain_names', 'meta', 'locations'];
|
||||
return ['domain_names', 'meta', 'locations', 'openidc_allowed_users'];
|
||||
}
|
||||
|
||||
static get relationMappings () {
|
||||
|
@ -10,7 +10,7 @@
|
||||
"bcrypt": "^5.0.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"compression": "^1.7.4",
|
||||
"express": "^4.17.3",
|
||||
"express": "^4.19.2",
|
||||
"express-fileupload": "^1.1.9",
|
||||
"gravatar": "^1.8.0",
|
||||
"json-schema-ref-parser": "^8.0.0",
|
||||
|
@ -235,6 +235,43 @@
|
||||
"description": "Should we cache assets",
|
||||
"example": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"openidc_enabled": {
|
||||
"description": "Is OpenID Connect authentication enabled",
|
||||
"example": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"openidc_redirect_uri": {
|
||||
"type": "string"
|
||||
},
|
||||
"openidc_discovery": {
|
||||
"type": "string"
|
||||
},
|
||||
"openidc_auth_method": {
|
||||
"type": "string",
|
||||
"pattern": "^(client_secret_basic|client_secret_post)$"
|
||||
},
|
||||
"openidc_client_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"openidc_client_secret": {
|
||||
"type": "string"
|
||||
},
|
||||
"openidc_restrict_users_enabled": {
|
||||
"description": "Only allow a specific set of OpenID Connect emails to access the resource",
|
||||
"example": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"openidc_allowed_users": {
|
||||
"type": "array",
|
||||
"minItems": 0,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"description": "Email Address",
|
||||
"example": "john@example.com",
|
||||
"format": "email",
|
||||
"minLength": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,22 +58,36 @@
|
||||
"example": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"enable_proxy_protocol": {
|
||||
"description": "Enable PROXY Protocol support",
|
||||
"example": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"load_balancer_ip": {
|
||||
"type": "string",
|
||||
"minLength": 0,
|
||||
"maxLength": 255
|
||||
},
|
||||
"access_list_id": {
|
||||
"$ref": "../definitions.json#/definitions/access_list_id"
|
||||
},
|
||||
"advanced_config": {
|
||||
"type": "string"
|
||||
},
|
||||
"openidc_enabled": {
|
||||
"$ref": "../definitions.json#/definitions/openidc_enabled"
|
||||
},
|
||||
"openidc_redirect_uri": {
|
||||
"$ref": "../definitions.json#/definitions/openidc_redirect_uri"
|
||||
},
|
||||
"openidc_discovery": {
|
||||
"$ref": "../definitions.json#/definitions/openidc_discovery"
|
||||
},
|
||||
"openidc_auth_method": {
|
||||
"$ref": "../definitions.json#/definitions/openidc_auth_method"
|
||||
},
|
||||
"openidc_client_id": {
|
||||
"$ref": "../definitions.json#/definitions/openidc_client_id"
|
||||
},
|
||||
"openidc_client_secret": {
|
||||
"$ref": "../definitions.json#/definitions/openidc_client_secret"
|
||||
},
|
||||
"openidc_restrict_users_enabled": {
|
||||
"$ref": "../definitions.json#/definitions/openidc_restrict_users_enabled"
|
||||
},
|
||||
"openidc_allowed_users": {
|
||||
"$ref": "../definitions.json#/definitions/openidc_allowed_users"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "../definitions.json#/definitions/enabled"
|
||||
},
|
||||
@ -165,18 +179,36 @@
|
||||
"allow_websocket_upgrade": {
|
||||
"$ref": "#/definitions/allow_websocket_upgrade"
|
||||
},
|
||||
"enable_proxy_protocol": {
|
||||
"$ref": "#/definitions/enable_proxy_protocol"
|
||||
},
|
||||
"load_balancer_ip": {
|
||||
"$ref": "#/definitions/load_balancer_ip"
|
||||
},
|
||||
"access_list_id": {
|
||||
"$ref": "#/definitions/access_list_id"
|
||||
},
|
||||
"advanced_config": {
|
||||
"$ref": "#/definitions/advanced_config"
|
||||
},
|
||||
"openidc_enabled": {
|
||||
"$ref": "#/definitions/openidc_enabled"
|
||||
},
|
||||
"openidc_redirect_uri": {
|
||||
"$ref": "#/definitions/openidc_redirect_uri"
|
||||
},
|
||||
"openidc_discovery": {
|
||||
"$ref": "#/definitions/openidc_discovery"
|
||||
},
|
||||
"openidc_auth_method": {
|
||||
"$ref": "#/definitions/openidc_auth_method"
|
||||
},
|
||||
"openidc_client_id": {
|
||||
"$ref": "#/definitions/openidc_client_id"
|
||||
},
|
||||
"openidc_client_secret": {
|
||||
"$ref": "#/definitions/openidc_client_secret"
|
||||
},
|
||||
"openidc_restrict_users_enabled": {
|
||||
"$ref": "#/definitions/openidc_restrict_users_enabled"
|
||||
},
|
||||
"openidc_allowed_users": {
|
||||
"$ref": "#/definitions/openidc_allowed_users"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "#/definitions/enabled"
|
||||
},
|
||||
@ -261,18 +293,36 @@
|
||||
"allow_websocket_upgrade": {
|
||||
"$ref": "#/definitions/allow_websocket_upgrade"
|
||||
},
|
||||
"enable_proxy_protocol": {
|
||||
"$ref": "#/definitions/enable_proxy_protocol"
|
||||
},
|
||||
"load_balancer_ip": {
|
||||
"$ref": "#/definitions/load_balancer_ip"
|
||||
},
|
||||
"access_list_id": {
|
||||
"$ref": "#/definitions/access_list_id"
|
||||
},
|
||||
"advanced_config": {
|
||||
"$ref": "#/definitions/advanced_config"
|
||||
},
|
||||
"openidc_enabled": {
|
||||
"$ref": "#/definitions/openidc_enabled"
|
||||
},
|
||||
"openidc_redirect_uri": {
|
||||
"$ref": "#/definitions/openidc_redirect_uri"
|
||||
},
|
||||
"openidc_discovery": {
|
||||
"$ref": "#/definitions/openidc_discovery"
|
||||
},
|
||||
"openidc_auth_method": {
|
||||
"$ref": "#/definitions/openidc_auth_method"
|
||||
},
|
||||
"openidc_client_id": {
|
||||
"$ref": "#/definitions/openidc_client_id"
|
||||
},
|
||||
"openidc_client_secret": {
|
||||
"$ref": "#/definitions/openidc_client_secret"
|
||||
},
|
||||
"openidc_restrict_users_enabled": {
|
||||
"$ref": "#/definitions/openidc_restrict_users_enabled"
|
||||
},
|
||||
"openidc_allowed_users": {
|
||||
"$ref": "#/definitions/openidc_allowed_users"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "#/definitions/enabled"
|
||||
},
|
||||
@ -340,18 +390,36 @@
|
||||
"allow_websocket_upgrade": {
|
||||
"$ref": "#/definitions/allow_websocket_upgrade"
|
||||
},
|
||||
"enable_proxy_protocol": {
|
||||
"$ref": "#/definitions/enable_proxy_protocol"
|
||||
},
|
||||
"load_balancer_ip": {
|
||||
"$ref": "#/definitions/load_balancer_ip"
|
||||
},
|
||||
"access_list_id": {
|
||||
"$ref": "#/definitions/access_list_id"
|
||||
},
|
||||
"advanced_config": {
|
||||
"$ref": "#/definitions/advanced_config"
|
||||
},
|
||||
"openidc_enabled": {
|
||||
"$ref": "#/definitions/openidc_enabled"
|
||||
},
|
||||
"openidc_redirect_uri": {
|
||||
"$ref": "#/definitions/openidc_redirect_uri"
|
||||
},
|
||||
"openidc_discovery": {
|
||||
"$ref": "#/definitions/openidc_discovery"
|
||||
},
|
||||
"openidc_auth_method": {
|
||||
"$ref": "#/definitions/openidc_auth_method"
|
||||
},
|
||||
"openidc_client_id": {
|
||||
"$ref": "#/definitions/openidc_client_id"
|
||||
},
|
||||
"openidc_client_secret": {
|
||||
"$ref": "#/definitions/openidc_client_secret"
|
||||
},
|
||||
"openidc_restrict_users_enabled": {
|
||||
"$ref": "#/definitions/openidc_restrict_users_enabled"
|
||||
},
|
||||
"openidc_allowed_users": {
|
||||
"$ref": "#/definitions/openidc_allowed_users"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "#/definitions/enabled"
|
||||
},
|
||||
|
@ -46,16 +46,6 @@
|
||||
"udp_forwarding": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"enable_proxy_protocol": {
|
||||
"description": "Enable PROXY Protocol support",
|
||||
"example": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"load_balancer_ip": {
|
||||
"type": "string",
|
||||
"minLength": 0,
|
||||
"maxLength": 255
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "../definitions.json#/definitions/enabled"
|
||||
},
|
||||
@ -88,12 +78,6 @@
|
||||
"udp_forwarding": {
|
||||
"$ref": "#/definitions/udp_forwarding"
|
||||
},
|
||||
"enable_proxy_protocol": {
|
||||
"$ref": "#/definitions/enable_proxy_protocol"
|
||||
},
|
||||
"load_balancer_ip": {
|
||||
"$ref": "#/definitions/load_balancer_ip"
|
||||
},
|
||||
"enabled": {
|
||||
"$ref": "#/definitions/enabled"
|
||||
},
|
||||
@ -153,12 +137,6 @@
|
||||
"udp_forwarding": {
|
||||
"$ref": "#/definitions/udp_forwarding"
|
||||
},
|
||||
"enable_proxy_protocol": {
|
||||
"$ref": "#/definitions/enable_proxy_protocol"
|
||||
},
|
||||
"load_balancer_ip": {
|
||||
"$ref": "#/definitions/load_balancer_ip"
|
||||
},
|
||||
"meta": {
|
||||
"$ref": "#/definitions/meta"
|
||||
}
|
||||
@ -199,12 +177,6 @@
|
||||
"udp_forwarding": {
|
||||
"$ref": "#/definitions/udp_forwarding"
|
||||
},
|
||||
"enable_proxy_protocol": {
|
||||
"$ref": "#/definitions/enable_proxy_protocol"
|
||||
},
|
||||
"load_balancer_ip": {
|
||||
"$ref": "#/definitions/load_balancer_ip"
|
||||
},
|
||||
"meta": {
|
||||
"$ref": "#/definitions/meta"
|
||||
}
|
||||
|
@ -21,11 +21,14 @@ const setupDefaultUser = () => {
|
||||
.then((row) => {
|
||||
if (!row.count) {
|
||||
// Create a new user and set password
|
||||
logger.info('Creating a new user: admin@example.com with password: changeme');
|
||||
let email = process.env.INITIAL_ADMIN_EMAIL || 'admin@example.com';
|
||||
let password = process.env.INITIAL_ADMIN_PASSWORD || 'changeme';
|
||||
|
||||
logger.info('Creating a new user: ' + email + ' with password: ' + password);
|
||||
|
||||
let data = {
|
||||
is_deleted: 0,
|
||||
email: 'admin@example.com',
|
||||
email: email,
|
||||
name: 'Administrator',
|
||||
nickname: 'Admin',
|
||||
avatar: '',
|
||||
@ -41,7 +44,7 @@ const setupDefaultUser = () => {
|
||||
.insert({
|
||||
user_id: user.id,
|
||||
type: 'password',
|
||||
secret: 'changeme',
|
||||
secret: password,
|
||||
meta: {},
|
||||
})
|
||||
.then(() => {
|
||||
|
@ -1,24 +1,15 @@
|
||||
{% if enable_proxy_protocol == 1 or enable_proxy_protocol == true -%}
|
||||
{% assign port_number_http = "88" -%}
|
||||
{% assign port_number_https = "444" -%}
|
||||
{% assign listen_extra_args = "proxy_protocol" -%}
|
||||
listen 80;
|
||||
{% if ipv6 -%}
|
||||
listen [::]:80;
|
||||
{% else -%}
|
||||
{% assign port_number_http = "80" -%}
|
||||
{% assign port_number_https = "443" -%}
|
||||
{% assign listen_extra_args = "" -%}
|
||||
{% endif -%}
|
||||
|
||||
listen {{ port_number_http }} {{ listen_extra_args }};
|
||||
{% if ipv6 -%}
|
||||
listen [::]:{{ port_number_http }} {{ listen_extra_args }};
|
||||
{% endif -%}
|
||||
|
||||
#listen [::]:80;
|
||||
{% endif %}
|
||||
{% if certificate -%}
|
||||
{% capture listen_extra_args_https %}ssl{% if http2_support %} http2{% endif %} {{ listen_extra_args }}{% endcapture -%}
|
||||
listen {{ port_number_https }} {{ listen_extra_args_https }};
|
||||
listen 443 ssl{% if http2_support == 1 or http2_support == true %} http2{% endif %};
|
||||
{% if ipv6 -%}
|
||||
listen [::]:{{ port_number_https }} {{ listen_extra_args_https }};
|
||||
{% endif -%}
|
||||
{% endif -%}
|
||||
|
||||
listen [::]:443 ssl{% if http2_support == 1 or http2_support == true %} http2{% endif %};
|
||||
{% else -%}
|
||||
#listen [::]:443;
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
server_name {{ domain_names | join: " " }};
|
||||
|
@ -1,4 +1,6 @@
|
||||
location {{ path }} {
|
||||
{{ advanced_config }}
|
||||
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-Scheme $scheme;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
@ -17,8 +19,5 @@
|
||||
proxy_set_header Connection $http_connection;
|
||||
proxy_http_version 1.1;
|
||||
{% endif %}
|
||||
|
||||
|
||||
{{ advanced_config }}
|
||||
}
|
||||
|
||||
|
47
backend/templates/_openid_connect.conf
Normal file
@ -0,0 +1,47 @@
|
||||
{% if openidc_enabled == 1 or openidc_enabled == true -%}
|
||||
access_by_lua_block {
|
||||
local openidc = require("resty.openidc")
|
||||
local opts = {
|
||||
redirect_uri = "{{- openidc_redirect_uri -}}",
|
||||
discovery = "{{- openidc_discovery -}}",
|
||||
token_endpoint_auth_method = "{{- openidc_auth_method -}}",
|
||||
client_id = "{{- openidc_client_id -}}",
|
||||
client_secret = "{{- openidc_client_secret -}}",
|
||||
scope = "openid email profile"
|
||||
}
|
||||
|
||||
local res, err = openidc.authenticate(opts)
|
||||
|
||||
if err then
|
||||
ngx.status = 500
|
||||
ngx.say(err)
|
||||
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
|
||||
end
|
||||
|
||||
{% if openidc_restrict_users_enabled == 1 or openidc_restrict_users_enabled == true -%}
|
||||
local function contains(table, val)
|
||||
for i=1,#table do
|
||||
if table[i] == val then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local allowed_users = {
|
||||
{% for user in openidc_allowed_users %}
|
||||
"{{ user }}",
|
||||
{% endfor %}
|
||||
}
|
||||
|
||||
if not contains(allowed_users, res.id_token.email) then
|
||||
ngx.exit(ngx.HTTP_FORBIDDEN)
|
||||
end
|
||||
{% endif -%}
|
||||
|
||||
|
||||
ngx.req.set_header("X-OIDC-SUB", res.id_token.sub)
|
||||
ngx.req.set_header("X-OIDC-EMAIL", res.id_token.email)
|
||||
ngx.req.set_header("X-OIDC-NAME", res.id_token.name)
|
||||
}
|
||||
{% endif %}
|
@ -1,6 +0,0 @@
|
||||
{% if enable_proxy_protocol == 1 or enable_proxy_protocol == true %}
|
||||
{% if load_balancer_ip != '' %}
|
||||
set_real_ip_from {{ load_balancer_ip }};
|
||||
real_ip_header proxy_protocol;
|
||||
{% endif %}
|
||||
{% endif %}
|
@ -15,7 +15,6 @@ server {
|
||||
{% include "_exploits.conf" %}
|
||||
{% include "_hsts.conf" %}
|
||||
{% include "_forced_ssl.conf" %}
|
||||
{% include "_proxy_protocol.conf" %}
|
||||
|
||||
{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
@ -34,8 +33,30 @@ proxy_http_version 1.1;
|
||||
|
||||
location / {
|
||||
|
||||
{% include "_access.conf" %}
|
||||
{% include "_hsts.conf" %}
|
||||
{% if access_list_id > 0 %}
|
||||
{% if access_list.items.length > 0 %}
|
||||
# Authorization
|
||||
auth_basic "Authorization required";
|
||||
auth_basic_user_file /data/access/{{ access_list_id }};
|
||||
|
||||
{{ access_list.passauth }}
|
||||
{% endif %}
|
||||
|
||||
# Access Rules
|
||||
{% for client in access_list.clients %}
|
||||
{{- client.rule -}};
|
||||
{% endfor %}deny all;
|
||||
|
||||
# Access checks must...
|
||||
{% if access_list.satisfy %}
|
||||
{{ access_list.satisfy }};
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% include "_openid_connect.conf" %}
|
||||
{% include "_access.conf" %}
|
||||
{% include "_hsts.conf" %}
|
||||
|
||||
{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
|
@ -1,38 +1,31 @@
|
||||
# ------------------------------------------------------------
|
||||
# {{ incoming_port }} TCP: {{ tcp_forwarding }} UDP: {{ udp_forwarding }}
|
||||
# ------------------------------------------------------------
|
||||
{% if enable_proxy_protocol == 1 or enable_proxy_protocol == true -%}
|
||||
{% capture listen_extra_args %}proxy_protocol{% endcapture -%}
|
||||
{% endif -%}
|
||||
|
||||
{% if enabled %}
|
||||
{% if tcp_forwarding == 1 or tcp_forwarding == true -%}
|
||||
server {
|
||||
listen {{ incoming_port }} {{ listen_extra_args }};
|
||||
listen {{ incoming_port }};
|
||||
{% if ipv6 -%}
|
||||
listen [::]:{{ incoming_port }} {{ listen_extra_args }};
|
||||
listen [::]:{{ incoming_port }};
|
||||
{% else -%}
|
||||
#listen [::]:{{ incoming_port }} {{ listen_extra_args }};
|
||||
#listen [::]:{{ incoming_port }};
|
||||
{% endif %}
|
||||
|
||||
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
|
||||
|
||||
{% include '_proxy_protocol.conf' %}
|
||||
|
||||
# Custom
|
||||
include /data/nginx/custom/server_stream[.]conf;
|
||||
include /data/nginx/custom/server_stream_tcp[.]conf;
|
||||
}
|
||||
{% endif %}
|
||||
{% if udp_forwarding == 1 or udp_forwarding == true %}
|
||||
{% # Proxy Protocol is not supported for UDP %}
|
||||
{% assign listen_extra_args = "" %}
|
||||
server {
|
||||
listen {{ incoming_port }} udp {{ listen_extra_args }};
|
||||
listen {{ incoming_port }} udp;
|
||||
{% if ipv6 -%}
|
||||
listen [::]:{{ incoming_port }} udp {{ listen_extra_args }};
|
||||
listen [::]:{{ incoming_port }} udp;
|
||||
{% else -%}
|
||||
#listen [::]:{{ incoming_port }} udp {{ listen_extra_args }};
|
||||
#listen [::]:{{ incoming_port }} udp;
|
||||
{% endif %}
|
||||
proxy_pass {{ forwarding_host }}:{{ forwarding_port }};
|
||||
|
||||
|
@ -407,21 +407,23 @@ blueimp-md5@^2.16.0:
|
||||
resolved "https://registry.yarnpkg.com/blueimp-md5/-/blueimp-md5-2.17.0.tgz#f4fcac088b115f7b4045f19f5da59e9d01b1bb96"
|
||||
integrity sha512-x5PKJHY5rHQYaADj6NwPUR2QRCUVSggPzrUKkeENpj871o9l9IefJbO2jkT5UvYykeOK9dx0VmkIo6dZ+vThYw==
|
||||
|
||||
body-parser@1.19.2, body-parser@^1.19.0:
|
||||
version "1.19.2"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e"
|
||||
integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==
|
||||
body-parser@1.20.2, body-parser@^1.19.0:
|
||||
version "1.20.2"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd"
|
||||
integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
content-type "~1.0.4"
|
||||
content-type "~1.0.5"
|
||||
debug "2.6.9"
|
||||
depd "~1.1.2"
|
||||
http-errors "1.8.1"
|
||||
depd "2.0.0"
|
||||
destroy "1.2.0"
|
||||
http-errors "2.0.0"
|
||||
iconv-lite "0.4.24"
|
||||
on-finished "~2.3.0"
|
||||
qs "6.9.7"
|
||||
raw-body "2.4.3"
|
||||
on-finished "2.4.1"
|
||||
qs "6.11.0"
|
||||
raw-body "2.5.2"
|
||||
type-is "~1.6.18"
|
||||
unpipe "1.0.0"
|
||||
|
||||
boxen@^4.2.0:
|
||||
version "4.2.0"
|
||||
@ -446,11 +448,11 @@ brace-expansion@^1.1.7:
|
||||
concat-map "0.0.1"
|
||||
|
||||
braces@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
|
||||
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
|
||||
dependencies:
|
||||
fill-range "^7.0.1"
|
||||
fill-range "^7.1.1"
|
||||
|
||||
buffer-crc32@^0.2.1, buffer-crc32@^0.2.13:
|
||||
version "0.2.13"
|
||||
@ -524,6 +526,17 @@ cacheable-request@^6.0.0:
|
||||
normalize-url "^4.1.0"
|
||||
responselike "^1.0.2"
|
||||
|
||||
call-bind@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9"
|
||||
integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==
|
||||
dependencies:
|
||||
es-define-property "^1.0.0"
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
get-intrinsic "^1.2.4"
|
||||
set-function-length "^1.2.1"
|
||||
|
||||
call-me-maybe@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
|
||||
@ -728,20 +741,20 @@ content-disposition@0.5.4:
|
||||
dependencies:
|
||||
safe-buffer "5.2.1"
|
||||
|
||||
content-type@~1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||
integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
|
||||
content-type@~1.0.4, content-type@~1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
|
||||
integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
|
||||
|
||||
cookie-signature@1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
|
||||
integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw=
|
||||
|
||||
cookie@0.4.2:
|
||||
version "0.4.2"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432"
|
||||
integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
|
||||
cookie@0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051"
|
||||
integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==
|
||||
|
||||
core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
@ -831,25 +844,29 @@ defer-to-connect@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
|
||||
integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
|
||||
|
||||
define-data-property@^1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
|
||||
integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==
|
||||
dependencies:
|
||||
es-define-property "^1.0.0"
|
||||
es-errors "^1.3.0"
|
||||
gopd "^1.0.1"
|
||||
|
||||
delegates@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
|
||||
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
|
||||
|
||||
depd@^2.0.0:
|
||||
depd@2.0.0, depd@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
|
||||
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
|
||||
|
||||
depd@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
||||
integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=
|
||||
|
||||
destroy@~1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
|
||||
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
|
||||
destroy@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
|
||||
integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
|
||||
|
||||
detect-libc@^1.0.2:
|
||||
version "1.0.3"
|
||||
@ -950,6 +967,18 @@ error-ex@^1.3.1:
|
||||
dependencies:
|
||||
is-arrayish "^0.2.1"
|
||||
|
||||
es-define-property@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845"
|
||||
integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==
|
||||
dependencies:
|
||||
get-intrinsic "^1.2.4"
|
||||
|
||||
es-errors@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
|
||||
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
|
||||
|
||||
escalade@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
@ -1104,38 +1133,39 @@ express-fileupload@^1.1.9:
|
||||
dependencies:
|
||||
busboy "^0.3.1"
|
||||
|
||||
express@^4.17.3:
|
||||
version "4.17.3"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1"
|
||||
integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==
|
||||
express@^4.19.2:
|
||||
version "4.19.2"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465"
|
||||
integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==
|
||||
dependencies:
|
||||
accepts "~1.3.8"
|
||||
array-flatten "1.1.1"
|
||||
body-parser "1.19.2"
|
||||
body-parser "1.20.2"
|
||||
content-disposition "0.5.4"
|
||||
content-type "~1.0.4"
|
||||
cookie "0.4.2"
|
||||
cookie "0.6.0"
|
||||
cookie-signature "1.0.6"
|
||||
debug "2.6.9"
|
||||
depd "~1.1.2"
|
||||
depd "2.0.0"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
finalhandler "~1.1.2"
|
||||
finalhandler "1.2.0"
|
||||
fresh "0.5.2"
|
||||
http-errors "2.0.0"
|
||||
merge-descriptors "1.0.1"
|
||||
methods "~1.1.2"
|
||||
on-finished "~2.3.0"
|
||||
on-finished "2.4.1"
|
||||
parseurl "~1.3.3"
|
||||
path-to-regexp "0.1.7"
|
||||
proxy-addr "~2.0.7"
|
||||
qs "6.9.7"
|
||||
qs "6.11.0"
|
||||
range-parser "~1.2.1"
|
||||
safe-buffer "5.2.1"
|
||||
send "0.17.2"
|
||||
serve-static "1.14.2"
|
||||
send "0.18.0"
|
||||
serve-static "1.15.0"
|
||||
setprototypeof "1.2.0"
|
||||
statuses "~1.5.0"
|
||||
statuses "2.0.1"
|
||||
type-is "~1.6.18"
|
||||
utils-merge "1.0.1"
|
||||
vary "~1.1.2"
|
||||
@ -1176,24 +1206,24 @@ file-entry-cache@^6.0.1:
|
||||
dependencies:
|
||||
flat-cache "^3.0.4"
|
||||
|
||||
fill-range@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
||||
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
|
||||
fill-range@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
|
||||
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
|
||||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
finalhandler@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d"
|
||||
integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==
|
||||
finalhandler@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32"
|
||||
integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
on-finished "~2.3.0"
|
||||
on-finished "2.4.1"
|
||||
parseurl "~1.3.3"
|
||||
statuses "~1.5.0"
|
||||
statuses "2.0.1"
|
||||
unpipe "~1.0.0"
|
||||
|
||||
find-up@^2.0.0:
|
||||
@ -1276,6 +1306,11 @@ function-bind@^1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||
|
||||
function-bind@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
|
||||
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
|
||||
|
||||
gauge@^3.0.0:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/gauge/-/gauge-3.0.2.tgz#03bf4441c044383908bcfa0656ad91803259b395"
|
||||
@ -1324,6 +1359,17 @@ get-caller-file@^2.0.1:
|
||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||
|
||||
get-intrinsic@^1.1.3, get-intrinsic@^1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
|
||||
integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
has-proto "^1.0.1"
|
||||
has-symbols "^1.0.3"
|
||||
hasown "^2.0.0"
|
||||
|
||||
get-package-type@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a"
|
||||
@ -1356,9 +1402,9 @@ glob-parent@^6.0.2:
|
||||
is-glob "^4.0.3"
|
||||
|
||||
glob-parent@~5.1.0:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
|
||||
integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
|
||||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
@ -1400,6 +1446,13 @@ globals@^13.19.0:
|
||||
dependencies:
|
||||
type-fest "^0.20.2"
|
||||
|
||||
gopd@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
|
||||
integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
|
||||
dependencies:
|
||||
get-intrinsic "^1.1.3"
|
||||
|
||||
got@^9.6.0:
|
||||
version "9.6.0"
|
||||
resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85"
|
||||
@ -1457,6 +1510,23 @@ has-flag@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||
|
||||
has-property-descriptors@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854"
|
||||
integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==
|
||||
dependencies:
|
||||
es-define-property "^1.0.0"
|
||||
|
||||
has-proto@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd"
|
||||
integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==
|
||||
|
||||
has-symbols@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
|
||||
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
|
||||
|
||||
has-unicode@^2.0.0, has-unicode@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
|
||||
@ -1474,20 +1544,27 @@ has@^1.0.3:
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
hasown@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
|
||||
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
|
||||
dependencies:
|
||||
function-bind "^1.1.2"
|
||||
|
||||
http-cache-semantics@^4.0.0, http-cache-semantics@^4.1.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"
|
||||
integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==
|
||||
|
||||
http-errors@1.8.1:
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c"
|
||||
integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==
|
||||
http-errors@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
|
||||
integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
|
||||
dependencies:
|
||||
depd "~1.1.2"
|
||||
depd "2.0.0"
|
||||
inherits "2.0.4"
|
||||
setprototypeof "1.2.0"
|
||||
statuses ">= 1.5.0 < 2"
|
||||
statuses "2.0.1"
|
||||
toidentifier "1.0.1"
|
||||
|
||||
http-proxy-agent@^4.0.1:
|
||||
@ -1615,9 +1692,9 @@ interpret@^2.2.0:
|
||||
integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==
|
||||
|
||||
ip@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da"
|
||||
integrity sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
|
||||
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
|
||||
|
||||
ipaddr.js@1.9.1:
|
||||
version "1.9.1"
|
||||
@ -2365,6 +2442,11 @@ object-assign@^4.1.0, object-assign@^4.1.1:
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||
|
||||
object-inspect@^1.13.1:
|
||||
version "1.13.1"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2"
|
||||
integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==
|
||||
|
||||
objection@3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/objection/-/objection-3.0.1.tgz#f67dc698187d10524e5d1b5d37a54e5bba49a42a"
|
||||
@ -2373,10 +2455,10 @@ objection@3.0.1:
|
||||
ajv "^8.6.2"
|
||||
db-errors "^0.2.3"
|
||||
|
||||
on-finished@~2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947"
|
||||
integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=
|
||||
on-finished@2.4.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
|
||||
integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
|
||||
dependencies:
|
||||
ee-first "1.1.1"
|
||||
|
||||
@ -2653,10 +2735,12 @@ pupa@^2.0.1:
|
||||
dependencies:
|
||||
escape-goat "^2.0.0"
|
||||
|
||||
qs@6.9.7:
|
||||
version "6.9.7"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe"
|
||||
integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==
|
||||
qs@6.11.0:
|
||||
version "6.11.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
|
||||
integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
|
||||
dependencies:
|
||||
side-channel "^1.0.4"
|
||||
|
||||
querystring@0.2.0:
|
||||
version "0.2.0"
|
||||
@ -2673,13 +2757,13 @@ range-parser@~1.2.1:
|
||||
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
||||
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
|
||||
|
||||
raw-body@2.4.3:
|
||||
version "2.4.3"
|
||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c"
|
||||
integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==
|
||||
raw-body@2.5.2:
|
||||
version "2.5.2"
|
||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a"
|
||||
integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
http-errors "1.8.1"
|
||||
http-errors "2.0.0"
|
||||
iconv-lite "0.4.24"
|
||||
unpipe "1.0.0"
|
||||
|
||||
@ -2866,40 +2950,52 @@ semver@^7.3.5, semver@^7.3.8:
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
send@0.17.2:
|
||||
version "0.17.2"
|
||||
resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820"
|
||||
integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==
|
||||
send@0.18.0:
|
||||
version "0.18.0"
|
||||
resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
|
||||
integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
depd "~1.1.2"
|
||||
destroy "~1.0.4"
|
||||
depd "2.0.0"
|
||||
destroy "1.2.0"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
fresh "0.5.2"
|
||||
http-errors "1.8.1"
|
||||
http-errors "2.0.0"
|
||||
mime "1.6.0"
|
||||
ms "2.1.3"
|
||||
on-finished "~2.3.0"
|
||||
on-finished "2.4.1"
|
||||
range-parser "~1.2.1"
|
||||
statuses "~1.5.0"
|
||||
statuses "2.0.1"
|
||||
|
||||
serve-static@1.14.2:
|
||||
version "1.14.2"
|
||||
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa"
|
||||
integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==
|
||||
serve-static@1.15.0:
|
||||
version "1.15.0"
|
||||
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
|
||||
integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
|
||||
dependencies:
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
parseurl "~1.3.3"
|
||||
send "0.17.2"
|
||||
send "0.18.0"
|
||||
|
||||
set-blocking@^2.0.0, set-blocking@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
|
||||
|
||||
set-function-length@^1.2.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
|
||||
integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==
|
||||
dependencies:
|
||||
define-data-property "^1.1.4"
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
get-intrinsic "^1.2.4"
|
||||
gopd "^1.0.1"
|
||||
has-property-descriptors "^1.0.2"
|
||||
|
||||
setprototypeof@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
|
||||
@ -2917,6 +3013,16 @@ shebang-regex@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
|
||||
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
||||
|
||||
side-channel@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2"
|
||||
integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==
|
||||
dependencies:
|
||||
call-bind "^1.0.7"
|
||||
es-errors "^1.3.0"
|
||||
get-intrinsic "^1.2.4"
|
||||
object-inspect "^1.13.1"
|
||||
|
||||
signal-exit@^3.0.0, signal-exit@^3.0.2:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
|
||||
@ -2986,10 +3092,10 @@ ssri@^8.0.0, ssri@^8.0.1:
|
||||
dependencies:
|
||||
minipass "^3.1.1"
|
||||
|
||||
"statuses@>= 1.5.0 < 2", statuses@~1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
|
||||
integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
|
||||
statuses@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
|
||||
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
|
||||
|
||||
streamsearch@0.1.2:
|
||||
version "0.1.2"
|
||||
|
@ -33,7 +33,7 @@ RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
|
||||
COPY docker/scripts/install-s6 /tmp/install-s6
|
||||
RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6
|
||||
|
||||
EXPOSE 80 81 88 443 444
|
||||
EXPOSE 80 81 443
|
||||
|
||||
COPY backend /app
|
||||
COPY frontend/dist /app/frontend
|
||||
|
@ -29,5 +29,5 @@ RUN chmod 644 /etc/logrotate.d/nginx-proxy-manager
|
||||
COPY scripts/install-s6 /tmp/install-s6
|
||||
RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6
|
||||
|
||||
EXPOSE 80 81 88 443 444
|
||||
EXPOSE 80 81 443
|
||||
ENTRYPOINT [ "/init" ]
|
||||
|
28
docker/dev/dnsrouter-config.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"log": {
|
||||
"format": "nice",
|
||||
"level": "debug"
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"host": "0.0.0.0",
|
||||
"port": 53,
|
||||
"upstreams": [
|
||||
{
|
||||
"regex": "website[0-9]+.example\\.com",
|
||||
"upstream": "127.0.0.11"
|
||||
},
|
||||
{
|
||||
"regex": ".*\\.example\\.com",
|
||||
"upstream": "1.1.1.1"
|
||||
},
|
||||
{
|
||||
"regex": "local",
|
||||
"nxdomain": true
|
||||
}
|
||||
],
|
||||
"internal": null,
|
||||
"default_upstream": "127.0.0.11"
|
||||
}
|
||||
]
|
||||
}
|
7
docker/dev/letsencrypt.ini
Normal file
@ -0,0 +1,7 @@
|
||||
text = True
|
||||
non-interactive = True
|
||||
webroot-path = /data/letsencrypt-acme-challenge
|
||||
key-type = ecdsa
|
||||
elliptic-curve = secp384r1
|
||||
preferred-chain = ISRG Root X1
|
||||
server =
|
255
docker/dev/pdns-db.sql
Normal file
@ -0,0 +1,255 @@
|
||||
/*
|
||||
|
||||
How this was generated:
|
||||
1. bring up an empty pdns stack
|
||||
2. use api to create a zone ...
|
||||
|
||||
curl -X POST \
|
||||
'http://npm.dev:8081/api/v1/servers/localhost/zones' \
|
||||
--header 'X-API-Key: npm' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw '{
|
||||
"name": "example.com.",
|
||||
"kind": "Native",
|
||||
"masters": [],
|
||||
"nameservers": [
|
||||
"ns1.pdns.",
|
||||
"ns2.pdns."
|
||||
]
|
||||
}'
|
||||
|
||||
3. Dump sql:
|
||||
|
||||
docker exec -ti npm.pdns.db mysqldump -u pdns -p pdns
|
||||
|
||||
*/
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!40101 SET NAMES utf8mb4 */;
|
||||
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
--
|
||||
-- Table structure for table `comments`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `comments`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `comments` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`domain_id` int(11) NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`type` varchar(10) NOT NULL,
|
||||
`modified_at` int(11) NOT NULL,
|
||||
`account` varchar(40) CHARACTER SET utf8mb3 DEFAULT NULL,
|
||||
`comment` text CHARACTER SET utf8mb3 NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `comments_name_type_idx` (`name`,`type`),
|
||||
KEY `comments_order_idx` (`domain_id`,`modified_at`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `comments`
|
||||
--
|
||||
|
||||
LOCK TABLES `comments` WRITE;
|
||||
/*!40000 ALTER TABLE `comments` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `comments` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `cryptokeys`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `cryptokeys`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `cryptokeys` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`domain_id` int(11) NOT NULL,
|
||||
`flags` int(11) NOT NULL,
|
||||
`active` tinyint(1) DEFAULT NULL,
|
||||
`published` tinyint(1) DEFAULT 1,
|
||||
`content` text DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `domainidindex` (`domain_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `cryptokeys`
|
||||
--
|
||||
|
||||
LOCK TABLES `cryptokeys` WRITE;
|
||||
/*!40000 ALTER TABLE `cryptokeys` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `cryptokeys` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `domainmetadata`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `domainmetadata`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `domainmetadata` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`domain_id` int(11) NOT NULL,
|
||||
`kind` varchar(32) DEFAULT NULL,
|
||||
`content` text DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `domainmetadata_idx` (`domain_id`,`kind`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `domainmetadata`
|
||||
--
|
||||
|
||||
LOCK TABLES `domainmetadata` WRITE;
|
||||
/*!40000 ALTER TABLE `domainmetadata` DISABLE KEYS */;
|
||||
INSERT INTO `domainmetadata` VALUES
|
||||
(1,1,'SOA-EDIT-API','DEFAULT');
|
||||
/*!40000 ALTER TABLE `domainmetadata` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `domains`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `domains`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `domains` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`master` varchar(128) DEFAULT NULL,
|
||||
`last_check` int(11) DEFAULT NULL,
|
||||
`type` varchar(8) NOT NULL,
|
||||
`notified_serial` int(10) unsigned DEFAULT NULL,
|
||||
`account` varchar(40) CHARACTER SET utf8mb3 DEFAULT NULL,
|
||||
`options` varchar(64000) DEFAULT NULL,
|
||||
`catalog` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `name_index` (`name`),
|
||||
KEY `catalog_idx` (`catalog`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `domains`
|
||||
--
|
||||
|
||||
LOCK TABLES `domains` WRITE;
|
||||
/*!40000 ALTER TABLE `domains` DISABLE KEYS */;
|
||||
INSERT INTO `domains` VALUES
|
||||
(1,'example.com','',NULL,'NATIVE',NULL,'',NULL,NULL);
|
||||
/*!40000 ALTER TABLE `domains` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `records`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `records`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `records` (
|
||||
`id` bigint(20) NOT NULL AUTO_INCREMENT,
|
||||
`domain_id` int(11) DEFAULT NULL,
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
`type` varchar(10) DEFAULT NULL,
|
||||
`content` varchar(64000) DEFAULT NULL,
|
||||
`ttl` int(11) DEFAULT NULL,
|
||||
`prio` int(11) DEFAULT NULL,
|
||||
`disabled` tinyint(1) DEFAULT 0,
|
||||
`ordername` varchar(255) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL,
|
||||
`auth` tinyint(1) DEFAULT 1,
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `nametype_index` (`name`,`type`),
|
||||
KEY `domain_id` (`domain_id`),
|
||||
KEY `ordername` (`ordername`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `records`
|
||||
--
|
||||
|
||||
LOCK TABLES `records` WRITE;
|
||||
/*!40000 ALTER TABLE `records` DISABLE KEYS */;
|
||||
INSERT INTO `records` VALUES
|
||||
(1,1,'example.com','NS','ns1.pdns',1500,0,0,NULL,1),
|
||||
(2,1,'example.com','NS','ns2.pdns',1500,0,0,NULL,1),
|
||||
(3,1,'example.com','SOA','a.misconfigured.dns.server.invalid hostmaster.example.com 2023030501 10800 3600 604800 3600',1500,0,0,NULL,1);
|
||||
/*!40000 ALTER TABLE `records` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `supermasters`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `supermasters`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `supermasters` (
|
||||
`ip` varchar(64) NOT NULL,
|
||||
`nameserver` varchar(255) NOT NULL,
|
||||
`account` varchar(40) CHARACTER SET utf8mb3 NOT NULL,
|
||||
PRIMARY KEY (`ip`,`nameserver`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `supermasters`
|
||||
--
|
||||
|
||||
LOCK TABLES `supermasters` WRITE;
|
||||
/*!40000 ALTER TABLE `supermasters` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `supermasters` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Table structure for table `tsigkeys`
|
||||
--
|
||||
|
||||
DROP TABLE IF EXISTS `tsigkeys`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `tsigkeys` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) DEFAULT NULL,
|
||||
`algorithm` varchar(50) DEFAULT NULL,
|
||||
`secret` varchar(255) DEFAULT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `namealgoindex` (`name`,`algorithm`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Dumping data for table `tsigkeys`
|
||||
--
|
||||
|
||||
LOCK TABLES `tsigkeys` WRITE;
|
||||
/*!40000 ALTER TABLE `tsigkeys` DISABLE KEYS */;
|
||||
/*!40000 ALTER TABLE `tsigkeys` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
12
docker/dev/pebble-config.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"pebble": {
|
||||
"listenAddress": "0.0.0.0:443",
|
||||
"managementListenAddress": "0.0.0.0:15000",
|
||||
"certificate": "test/certs/localhost/cert.pem",
|
||||
"privateKey": "test/certs/localhost/key.pem",
|
||||
"httpPort": 80,
|
||||
"tlsPort": 443,
|
||||
"ocspResponderURL": "",
|
||||
"externalAccountBindingRequired": false
|
||||
}
|
||||
}
|
27
docker/docker-compose.ci.mysql.yml
Normal file
@ -0,0 +1,27 @@
|
||||
# WARNING: This is a CI docker-compose file used for building and testing of the entire app, it should not be used for production.
|
||||
services:
|
||||
|
||||
fullstack:
|
||||
environment:
|
||||
DB_MYSQL_HOST: 'db-mysql'
|
||||
DB_MYSQL_PORT: '3306'
|
||||
DB_MYSQL_USER: 'npm'
|
||||
DB_MYSQL_PASSWORD: 'npmpass'
|
||||
DB_MYSQL_NAME: 'npm'
|
||||
depends_on:
|
||||
- db-mysql
|
||||
|
||||
db-mysql:
|
||||
image: jc21/mariadb-aria
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: 'npm'
|
||||
MYSQL_DATABASE: 'npm'
|
||||
MYSQL_USER: 'npm'
|
||||
MYSQL_PASSWORD: 'npmpass'
|
||||
volumes:
|
||||
- mysql_vol:/var/lib/mysql
|
||||
networks:
|
||||
- fulltest
|
||||
|
||||
volumes:
|
||||
mysql_vol:
|
9
docker/docker-compose.ci.sqlite.yml
Normal file
@ -0,0 +1,9 @@
|
||||
# WARNING: This is a CI docker-compose file used for building and testing of the entire app, it should not be used for production.
|
||||
services:
|
||||
|
||||
fullstack:
|
||||
environment:
|
||||
DB_SQLITE_FILE: '/data/mydb.sqlite'
|
||||
PUID: 1000
|
||||
PGID: 1000
|
||||
DISABLE_IPV6: 'true'
|
@ -1,95 +1,110 @@
|
||||
# WARNING: This is a CI docker-compose file used for building and testing of the entire app, it should not be used for production.
|
||||
version: '3.8'
|
||||
# WARNING: This is a CI docker-compose file used for building
|
||||
# and testing of the entire app, it should not be used for production.
|
||||
# This is a base compose file, it should be extended with a
|
||||
# docker-compose.ci.*.yml file
|
||||
services:
|
||||
|
||||
fullstack-mysql:
|
||||
image: "${IMAGE}:ci-${BUILD_NUMBER}"
|
||||
fullstack:
|
||||
image: "${IMAGE}:${BRANCH_LOWER}-ci-${BUILD_NUMBER}"
|
||||
environment:
|
||||
DEBUG: 'true'
|
||||
LE_STAGING: 'true'
|
||||
FORCE_COLOR: 1
|
||||
DB_MYSQL_HOST: 'db'
|
||||
DB_MYSQL_PORT: '3306'
|
||||
DB_MYSQL_USER: 'npm'
|
||||
DB_MYSQL_PASSWORD: 'npm'
|
||||
DB_MYSQL_NAME: 'npm'
|
||||
volumes:
|
||||
- npm_data_mysql:/data
|
||||
- npm_le_mysql:/etc/letsencrypt
|
||||
expose:
|
||||
- 81
|
||||
- 80
|
||||
- 88
|
||||
- 443
|
||||
- 444
|
||||
- 'npm_data_ci:/data'
|
||||
- 'npm_le_ci:/etc/letsencrypt'
|
||||
- './dev/letsencrypt.ini:/etc/letsencrypt.ini:ro'
|
||||
- './dev/resolv.conf:/etc/resolv.conf:ro'
|
||||
- '/etc/localtime:/etc/localtime:ro'
|
||||
healthcheck:
|
||||
test: ["CMD", "/usr/bin/check-health"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
networks:
|
||||
fulltest:
|
||||
aliases:
|
||||
- website1.example.com
|
||||
- website2.example.com
|
||||
- website3.example.com
|
||||
|
||||
stepca:
|
||||
image: jc21/testca
|
||||
volumes:
|
||||
- './dev/resolv.conf:/etc/resolv.conf:ro'
|
||||
- '/etc/localtime:/etc/localtime:ro'
|
||||
networks:
|
||||
fulltest:
|
||||
aliases:
|
||||
- ca.internal
|
||||
|
||||
pdns:
|
||||
image: pschiffe/pdns-mysql
|
||||
volumes:
|
||||
- '/etc/localtime:/etc/localtime:ro'
|
||||
environment:
|
||||
PDNS_master: 'yes'
|
||||
PDNS_api: 'yes'
|
||||
PDNS_api_key: 'npm'
|
||||
PDNS_webserver: 'yes'
|
||||
PDNS_webserver_address: '0.0.0.0'
|
||||
PDNS_webserver_password: 'npm'
|
||||
PDNS_webserver-allow-from: '127.0.0.0/8,192.0.0.0/8,10.0.0.0/8,172.0.0.0/8'
|
||||
PDNS_version_string: 'anonymous'
|
||||
PDNS_default_ttl: 1500
|
||||
PDNS_allow_axfr_ips: '127.0.0.0/8,192.0.0.0/8,10.0.0.0/8,172.0.0.0/8'
|
||||
PDNS_gmysql_host: pdns-db
|
||||
PDNS_gmysql_port: 3306
|
||||
PDNS_gmysql_user: pdns
|
||||
PDNS_gmysql_password: pdns
|
||||
PDNS_gmysql_dbname: pdns
|
||||
depends_on:
|
||||
- db
|
||||
healthcheck:
|
||||
test: ["CMD", "/usr/bin/check-health"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
- pdns-db
|
||||
networks:
|
||||
fulltest:
|
||||
aliases:
|
||||
- ns1.pdns
|
||||
- ns2.pdns
|
||||
|
||||
fullstack-sqlite:
|
||||
image: "${IMAGE}:ci-${BUILD_NUMBER}"
|
||||
pdns-db:
|
||||
image: mariadb
|
||||
environment:
|
||||
DEBUG: 'true'
|
||||
LE_STAGING: 'true'
|
||||
FORCE_COLOR: 1
|
||||
DB_SQLITE_FILE: '/data/mydb.sqlite'
|
||||
PUID: 1000
|
||||
PGID: 1000
|
||||
DISABLE_IPV6: 'true'
|
||||
MYSQL_ROOT_PASSWORD: 'pdns'
|
||||
MYSQL_DATABASE: 'pdns'
|
||||
MYSQL_USER: 'pdns'
|
||||
MYSQL_PASSWORD: 'pdns'
|
||||
volumes:
|
||||
- npm_data_sqlite:/data
|
||||
- npm_le_sqlite:/etc/letsencrypt
|
||||
expose:
|
||||
- 81
|
||||
- 80
|
||||
- 88
|
||||
- 443
|
||||
- 444
|
||||
healthcheck:
|
||||
test: ["CMD", "/usr/bin/check-health"]
|
||||
interval: 10s
|
||||
timeout: 3s
|
||||
- 'pdns_mysql_vol:/var/lib/mysql'
|
||||
- '/etc/localtime:/etc/localtime:ro'
|
||||
- './dev/pdns-db.sql:/docker-entrypoint-initdb.d/01_init.sql:ro'
|
||||
networks:
|
||||
- fulltest
|
||||
|
||||
db:
|
||||
image: jc21/mariadb-aria
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: 'npm'
|
||||
MYSQL_DATABASE: 'npm'
|
||||
MYSQL_USER: 'npm'
|
||||
MYSQL_PASSWORD: 'npm'
|
||||
dnsrouter:
|
||||
image: jc21/dnsrouter
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
- ./dev/dnsrouter-config.json.tmp:/dnsrouter-config.json:ro
|
||||
networks:
|
||||
- fulltest
|
||||
|
||||
cypress-mysql:
|
||||
cypress:
|
||||
image: "${IMAGE}-cypress:ci-${BUILD_NUMBER}"
|
||||
build:
|
||||
context: ../test/
|
||||
dockerfile: cypress/Dockerfile
|
||||
context: ../
|
||||
dockerfile: test/cypress/Dockerfile
|
||||
environment:
|
||||
CYPRESS_baseUrl: 'http://fullstack-mysql:81'
|
||||
CYPRESS_baseUrl: 'http://fullstack:81'
|
||||
volumes:
|
||||
- cypress_logs_mysql:/results
|
||||
command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json}
|
||||
|
||||
cypress-sqlite:
|
||||
image: "${IMAGE}-cypress:ci-${BUILD_NUMBER}"
|
||||
build:
|
||||
context: ../test/
|
||||
dockerfile: cypress/Dockerfile
|
||||
environment:
|
||||
CYPRESS_baseUrl: "http://fullstack-sqlite:81"
|
||||
volumes:
|
||||
- cypress_logs_sqlite:/results
|
||||
command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json}
|
||||
- 'cypress_logs:/results'
|
||||
- './dev/resolv.conf:/etc/resolv.conf:ro'
|
||||
command: cypress run --browser chrome --config-file=cypress/config/ci.js
|
||||
networks:
|
||||
- fulltest
|
||||
|
||||
volumes:
|
||||
cypress_logs_mysql:
|
||||
cypress_logs_sqlite:
|
||||
npm_data_mysql:
|
||||
npm_data_sqlite:
|
||||
npm_le_sqlite:
|
||||
npm_le_mysql:
|
||||
mysql_data:
|
||||
cypress_logs:
|
||||
npm_data_ci:
|
||||
npm_le_ci:
|
||||
pdns_mysql_vol:
|
||||
|
||||
networks:
|
||||
fulltest:
|
||||
name: "npm-${BRANCH_LOWER}-ci-${BUILD_NUMBER}"
|
||||
|
@ -1,5 +1,4 @@
|
||||
# WARNING: This is a DEVELOPMENT docker-compose file, it should not be used for production.
|
||||
version: '3.8'
|
||||
services:
|
||||
|
||||
npm:
|
||||
@ -11,9 +10,7 @@ services:
|
||||
ports:
|
||||
- 3080:80
|
||||
- 3081:81
|
||||
- 3088:88
|
||||
- 3443:443
|
||||
- 3444:444
|
||||
networks:
|
||||
- nginx_proxy_manager
|
||||
environment:
|
||||
|
4
docker/rootfs/etc/nginx/conf.d/include/log.conf
Normal file
@ -0,0 +1,4 @@
|
||||
log_format proxy '[$time_local] $upstream_cache_status $upstream_status $status - $request_method $scheme $host "$request_uri" [Client $remote_addr] [Length $body_bytes_sent] [Gzip $gzip_ratio] [Sent-to $server] "$http_user_agent" "$http_referer"';
|
||||
log_format standard '[$time_local] $status - $request_method $scheme $host "$request_uri" [Client $remote_addr] [Length $body_bytes_sent] [Gzip $gzip_ratio] "$http_user_agent" "$http_referer"';
|
||||
|
||||
access_log /data/logs/fallback_access.log proxy;
|
@ -14,6 +14,9 @@ error_log /data/logs/fallback_error.log warn;
|
||||
# Includes files with directives to load dynamic modules.
|
||||
include /etc/nginx/modules/*.conf;
|
||||
|
||||
# Custom
|
||||
include /data/nginx/custom/root_top[.]conf;
|
||||
|
||||
events {
|
||||
include /data/nginx/custom/events[.]conf;
|
||||
}
|
||||
@ -43,11 +46,23 @@ http {
|
||||
proxy_cache_path /var/lib/nginx/cache/public levels=1:2 keys_zone=public-cache:30m max_size=192m;
|
||||
proxy_cache_path /var/lib/nginx/cache/private levels=1:2 keys_zone=private-cache:5m max_size=1024m;
|
||||
|
||||
lua_package_path '~/lua/?.lua;;';
|
||||
|
||||
lua_ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt;
|
||||
lua_ssl_verify_depth 5;
|
||||
|
||||
# cache for discovery metadata documents
|
||||
lua_shared_dict discovery 1m;
|
||||
# cache for JWKs
|
||||
lua_shared_dict jwks 1m;
|
||||
|
||||
log_format proxy '[$time_local] $upstream_cache_status $upstream_status $status - $request_method $scheme $host "$request_uri" [Client $remote_addr] [Length $body_bytes_sent] [Gzip $gzip_ratio] [Sent-to $server] "$http_user_agent" "$http_referer"';
|
||||
log_format standard '[$time_local] $status - $request_method $scheme $host "$request_uri" [Client $remote_addr] [Length $body_bytes_sent] [Gzip $gzip_ratio] "$http_user_agent" "$http_referer"';
|
||||
|
||||
access_log /data/logs/fallback_access.log proxy;
|
||||
|
||||
include /etc/nginx/conf.d/include/log.conf;
|
||||
|
||||
# Dynamically generated resolvers file
|
||||
include /etc/nginx/conf.d/include/resolvers.conf;
|
||||
|
||||
|
@ -25,4 +25,4 @@ chown -R "$PUID:$PGID" /etc/nginx/conf.d
|
||||
|
||||
# Prevents errors when installing python certbot plugins when non-root
|
||||
chown "$PUID:$PGID" /opt/certbot /opt/certbot/bin
|
||||
chown -R "$PUID:$PGID" /opt/certbot/lib/python*/site-packages
|
||||
find /opt/certbot/lib/python*/site-packages -not -user "$PUID" -execdir chown "$PUID:$PGID" {} \+
|
||||
|
3
docs/.gitignore
vendored
@ -1,8 +1,9 @@
|
||||
.vuepress/dist
|
||||
dist
|
||||
node_modules
|
||||
ts
|
||||
.temp
|
||||
.cache
|
||||
.vitepress/cache
|
||||
|
||||
.yarn/*
|
||||
!.yarn/releases
|
||||
|
61
docs/.vitepress/config.mts
Normal file
@ -0,0 +1,61 @@
|
||||
import { defineConfig, type DefaultTheme } from 'vitepress';
|
||||
|
||||
// https://vitepress.dev/reference/site-config
|
||||
export default defineConfig({
|
||||
title: "Nginx Proxy Manager",
|
||||
description: "Expose your services easily and securely",
|
||||
head: [
|
||||
["link", { rel: "icon", href: "/icon.png" }],
|
||||
["meta", { name: "description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt" }],
|
||||
["meta", { property: "og:title", content: "Nginx Proxy Manager" }],
|
||||
["meta", { property: "og:description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt"}],
|
||||
["meta", { property: "og:type", content: "website" }],
|
||||
["meta", { property: "og:url", content: "https://nginxproxymanager.com/" }],
|
||||
["meta", { property: "og:image", content: "https://nginxproxymanager.com/icon.png" }],
|
||||
["meta", { name: "twitter:card", content: "summary"}],
|
||||
["meta", { name: "twitter:title", content: "Nginx Proxy Manager"}],
|
||||
["meta", { name: "twitter:description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt"}],
|
||||
["meta", { name: "twitter:image", content: "https://nginxproxymanager.com/icon.png"}],
|
||||
["meta", { name: "twitter:alt", content: "Nginx Proxy Manager"}],
|
||||
// GA
|
||||
['script', { async: 'true', src: 'https://www.googletagmanager.com/gtag/js?id=G-TXT8F5WY5B'}],
|
||||
['script', {}, "window.dataLayer = window.dataLayer || [];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js', new Date());\ngtag('config', 'G-TXT8F5WY5B');"],
|
||||
],
|
||||
sitemap: {
|
||||
hostname: 'https://nginxproxymanager.com'
|
||||
},
|
||||
metaChunk: true,
|
||||
srcDir: './src',
|
||||
outDir: './dist',
|
||||
themeConfig: {
|
||||
// https://vitepress.dev/reference/default-theme-config
|
||||
logo: { src: '/logo.svg', width: 24, height: 24 },
|
||||
nav: [
|
||||
{ text: 'Setup', link: '/setup/' },
|
||||
],
|
||||
sidebar: [
|
||||
{
|
||||
items: [
|
||||
// { text: 'Home', link: '/' },
|
||||
{ text: 'Guide', link: '/guide/' },
|
||||
{ text: 'Screenshots', link: '/screenshots/' },
|
||||
{ text: 'Setup Instructions', link: '/setup/' },
|
||||
{ text: 'Advanced Configuration', link: '/advanced-config/' },
|
||||
{ text: 'Upgrading', link: '/upgrading/' },
|
||||
{ text: 'Frequently Asked Questions', link: '/faq/' },
|
||||
{ text: 'Third Party', link: '/third-party/' },
|
||||
]
|
||||
}
|
||||
],
|
||||
socialLinks: [
|
||||
{ icon: 'github', link: 'https://github.com/NginxProxyManager/nginx-proxy-manager' }
|
||||
],
|
||||
search: {
|
||||
provider: 'local'
|
||||
},
|
||||
footer: {
|
||||
message: 'Released under the MIT License.',
|
||||
copyright: 'Copyright © 2016-present jc21.com'
|
||||
}
|
||||
}
|
||||
});
|
27
docs/.vitepress/theme/custom.css
Normal file
@ -0,0 +1,27 @@
|
||||
:root {
|
||||
--vp-home-hero-name-color: transparent;
|
||||
--vp-home-hero-name-background: -webkit-linear-gradient(120deg, #f15833 30%, #FAA42F);
|
||||
|
||||
--vp-home-hero-image-background-image: linear-gradient(-45deg, #aaaaaa 50%, #777777 50%);
|
||||
--vp-home-hero-image-filter: blur(44px);
|
||||
|
||||
--vp-c-brand-1: #f15833;
|
||||
--vp-c-brand-2: #FAA42F;
|
||||
--vp-c-brand-3: #f15833;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
:root {
|
||||
--vp-home-hero-image-filter: blur(56px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 960px) {
|
||||
:root {
|
||||
--vp-home-hero-image-filter: blur(68px);
|
||||
}
|
||||
}
|
||||
|
||||
.inline-img img {
|
||||
display: inline;
|
||||
}
|
4
docs/.vitepress/theme/index.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import DefaultTheme from 'vitepress/theme'
|
||||
import './custom.css'
|
||||
|
||||
export default DefaultTheme
|
@ -1,120 +0,0 @@
|
||||
import { defineUserConfig } from 'vuepress';
|
||||
import { defaultTheme } from 'vuepress'
|
||||
import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics';
|
||||
import { searchPlugin } from '@vuepress/plugin-search'
|
||||
import { sitemapPlugin } from 'vuepress-plugin-sitemap2';
|
||||
import zoomingPlugin from 'vuepress-plugin-zooming';
|
||||
|
||||
export default defineUserConfig({
|
||||
locales: {
|
||||
"/": {
|
||||
lang: "en-US",
|
||||
title: "Nginx Proxy Manager",
|
||||
description: "Expose your services easily and securely",
|
||||
},
|
||||
},
|
||||
head: [
|
||||
["link", { rel: "icon", href: "/icon.png" }],
|
||||
["meta", { name: "description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt" }],
|
||||
["meta", { property: "og:title", content: "Nginx Proxy Manager" }],
|
||||
["meta", { property: "og:description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt"}],
|
||||
["meta", { property: "og:type", content: "website" }],
|
||||
["meta", { property: "og:url", content: "https://nginxproxymanager.com/" }],
|
||||
["meta", { property: "og:image", content: "https://nginxproxymanager.com/icon.png" }],
|
||||
["meta", { name: "twitter:card", content: "summary"}],
|
||||
["meta", { name: "twitter:title", content: "Nginx Proxy Manager"}],
|
||||
["meta", { name: "twitter:description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt"}],
|
||||
["meta", { name: "twitter:image", content: "https://nginxproxymanager.com/icon.png"}],
|
||||
["meta", { name: "twitter:alt", content: "Nginx Proxy Manager"}],
|
||||
],
|
||||
theme: defaultTheme({
|
||||
logo: '/icon.png',
|
||||
repo: "jc21/nginx-proxy-manager",
|
||||
docsRepo: 'https://github.com/jc21/nginx-proxy-manager',
|
||||
docsBranch: 'develop',
|
||||
docsDir: 'docs',
|
||||
editLinkPattern: ':repo/edit/:branch/:path',
|
||||
locales: {
|
||||
'/': {
|
||||
label: 'English',
|
||||
selectLanguageText: 'Languages',
|
||||
selectLanguageName: 'English',
|
||||
editLinkText: 'Edit this page on GitHub',
|
||||
navbar: [
|
||||
{ text: 'Setup', link: '/setup/' }
|
||||
],
|
||||
sidebar: {
|
||||
'/': [
|
||||
{
|
||||
text: 'Home',
|
||||
link: '/'
|
||||
},
|
||||
{
|
||||
text: 'Guide',
|
||||
link: '/guide/',
|
||||
collapsible: true,
|
||||
},
|
||||
{
|
||||
text: 'Screenshots',
|
||||
link: '/screenshots/',
|
||||
collapsible: true,
|
||||
},
|
||||
{
|
||||
text: 'Setup Instructions',
|
||||
link: '/setup/',
|
||||
collapsible: true,
|
||||
},
|
||||
{
|
||||
text: 'Advanced Configuration',
|
||||
link: '/advanced-config/',
|
||||
collapsible: true,
|
||||
},
|
||||
{
|
||||
text: 'Upgrading',
|
||||
link: '/upgrading/',
|
||||
collapsible: true,
|
||||
},
|
||||
{
|
||||
text: 'Frequently Asked Questions',
|
||||
link: '/faq/',
|
||||
collapsible: true,
|
||||
},
|
||||
{
|
||||
text: 'Third Party',
|
||||
link: '/third-party/',
|
||||
collapsible: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
}),
|
||||
markdown: {
|
||||
code: {
|
||||
lineNumbers: false,
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
googleAnalyticsPlugin({
|
||||
id: 'UA-99675467-4'
|
||||
}),
|
||||
sitemapPlugin({
|
||||
hostname: "https://nginxproxymanager.com",
|
||||
}),
|
||||
zoomingPlugin({
|
||||
selector: '.zooming',
|
||||
delay: 1000,
|
||||
options: {
|
||||
bgColor: 'black',
|
||||
zIndex: 10000,
|
||||
},
|
||||
}),
|
||||
searchPlugin({
|
||||
locales: {
|
||||
'/': {
|
||||
placeholder: 'Search',
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
Before Width: | Height: | Size: 57 KiB |
@ -1,258 +0,0 @@
|
||||
:root {
|
||||
// brand colors
|
||||
--c-brand: #f15833;
|
||||
--c-brand-light: #f15833;
|
||||
|
||||
// background colors
|
||||
--c-bg: #ffffff;
|
||||
--c-bg-light: #f3f4f5;
|
||||
--c-bg-lighter: #eeeeee;
|
||||
--c-bg-dark: #ebebec;
|
||||
--c-bg-darker: #e6e6e6;
|
||||
--c-bg-navbar: var(--c-bg);
|
||||
--c-bg-sidebar: var(--c-bg);
|
||||
--c-bg-arrow: #cccccc;
|
||||
|
||||
// text colors
|
||||
--c-text: #663015;
|
||||
--c-text-accent: var(--c-brand);
|
||||
--c-text-light: #863f1c;
|
||||
--c-text-lighter: #b65626;
|
||||
--c-text-lightest: #f15833;
|
||||
--c-text-quote: #999999;
|
||||
|
||||
// border colors
|
||||
--c-border: #eaecef;
|
||||
--c-border-dark: #dfe2e5;
|
||||
|
||||
// custom container colors
|
||||
--c-tip: #42b983;
|
||||
--c-tip-bg: var(--c-bg-light);
|
||||
--c-tip-title: var(--c-text);
|
||||
--c-tip-text: var(--c-text);
|
||||
--c-tip-text-accent: var(--c-text-accent);
|
||||
--c-warning: #ffc310;
|
||||
--c-warning-bg: #fffae3;
|
||||
--c-warning-bg-light: #fff3ba;
|
||||
--c-warning-bg-lighter: #fff0b0;
|
||||
--c-warning-border-dark: #f7dc91;
|
||||
--c-warning-details-bg: #fff5ca;
|
||||
--c-warning-title: #f1b300;
|
||||
--c-warning-text: #746000;
|
||||
--c-warning-text-accent: #edb100;
|
||||
--c-warning-text-light: #c1971c;
|
||||
--c-warning-text-quote: #ccab49;
|
||||
--c-danger: #f11e37;
|
||||
--c-danger-bg: #ffe0e0;
|
||||
--c-danger-bg-light: #ffcfde;
|
||||
--c-danger-bg-lighter: #ffc9c9;
|
||||
--c-danger-border-dark: #f1abab;
|
||||
--c-danger-details-bg: #ffd4d4;
|
||||
--c-danger-title: #ed1e2c;
|
||||
--c-danger-text: #660000;
|
||||
--c-danger-text-accent: #bd1a1a;
|
||||
--c-danger-text-light: #b5474d;
|
||||
--c-danger-text-quote: #c15b5b;
|
||||
--c-details-bg: #eeeeee;
|
||||
|
||||
// badge component colors
|
||||
--c-badge-tip: var(--c-tip);
|
||||
--c-badge-warning: #ecc808;
|
||||
--c-badge-warning-text: var(--c-bg);
|
||||
--c-badge-danger: #dc2626;
|
||||
--c-badge-danger-text: var(--c-bg);
|
||||
|
||||
// transition vars
|
||||
--t-color: 0.3s ease;
|
||||
--t-transform: 0.3s ease;
|
||||
|
||||
// code blocks vars
|
||||
--code-bg-color: #282c34;
|
||||
--code-hl-bg-color: rgba(0, 0, 0, 0.66);
|
||||
--code-ln-color: #9e9e9e;
|
||||
--code-ln-wrapper-width: 3.5rem;
|
||||
|
||||
// font vars
|
||||
--font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
|
||||
Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
|
||||
--font-family-code: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
|
||||
// layout vars
|
||||
--navbar-height: 3.6rem;
|
||||
--navbar-padding-v: 0.7rem;
|
||||
--navbar-padding-h: 1.5rem;
|
||||
--sidebar-width: 20rem;
|
||||
--sidebar-width-mobile: calc(var(--sidebar-width) * 0.82);
|
||||
--content-width: 740px;
|
||||
--homepage-width: 960px;
|
||||
}
|
||||
|
||||
html.dark {
|
||||
// brand colors
|
||||
--c-brand: #f15833;
|
||||
--c-brand-light: #f15833;
|
||||
|
||||
// background colors
|
||||
--c-bg: #22272e;
|
||||
--c-bg-light: #2b313a;
|
||||
--c-bg-lighter: #262c34;
|
||||
--c-bg-dark: #343b44;
|
||||
--c-bg-darker: #37404c;
|
||||
|
||||
// text colors
|
||||
--c-text: #adbac7;
|
||||
--c-text-light: #96a7b7;
|
||||
--c-text-lighter: #8b9eb0;
|
||||
--c-text-lightest: #8094a8;
|
||||
|
||||
// border colors
|
||||
--c-border: #3e4c5a;
|
||||
--c-border-dark: #34404c;
|
||||
|
||||
// custom container colors
|
||||
--c-tip: #318a62;
|
||||
--c-warning: #e0ad15;
|
||||
--c-warning-bg: #2d2f2d;
|
||||
--c-warning-bg-light: #423e2a;
|
||||
--c-warning-bg-lighter: #44442f;
|
||||
--c-warning-border-dark: #957c35;
|
||||
--c-warning-details-bg: #39392d;
|
||||
--c-warning-title: #fdca31;
|
||||
--c-warning-text: #d8d96d;
|
||||
--c-warning-text-accent: #ffbf00;
|
||||
--c-warning-text-light: #ddb84b;
|
||||
--c-warning-text-quote: #ccab49;
|
||||
--c-danger: #fc1e38;
|
||||
--c-danger-bg: #39232c;
|
||||
--c-danger-bg-light: #4b2b35;
|
||||
--c-danger-bg-lighter: #553040;
|
||||
--c-danger-border-dark: #a25151;
|
||||
--c-danger-details-bg: #482936;
|
||||
--c-danger-title: #fc2d3b;
|
||||
--c-danger-text: #ea9ca0;
|
||||
--c-danger-text-accent: #fd3636;
|
||||
--c-danger-text-light: #d9777c;
|
||||
--c-danger-text-quote: #d56b6b;
|
||||
--c-details-bg: #323843;
|
||||
|
||||
// badge component colors
|
||||
--c-badge-warning: var(--c-warning);
|
||||
--c-badge-warning-text: #3c2e05;
|
||||
--c-badge-danger: var(--c-danger);
|
||||
--c-badge-danger-text: #401416;
|
||||
|
||||
// code blocks vars
|
||||
--code-hl-bg-color: #363b46;
|
||||
}
|
||||
|
||||
|
||||
// plugin-back-to-top
|
||||
.back-to-top {
|
||||
--back-to-top-color: var(--c-brand);
|
||||
--back-to-top-color-hover: var(--c-brand-light);
|
||||
}
|
||||
|
||||
// plugin-docsearch
|
||||
.DocSearch {
|
||||
--docsearch-primary-color: var(--c-brand);
|
||||
--docsearch-text-color: var(--c-text);
|
||||
--docsearch-highlight-color: var(--c-brand);
|
||||
--docsearch-muted-color: var(--c-text-quote);
|
||||
--docsearch-container-background: rgba(9, 10, 17, 0.8);
|
||||
--docsearch-modal-background: var(--c-bg-light);
|
||||
--docsearch-searchbox-background: var(--c-bg-lighter);
|
||||
--docsearch-searchbox-focus-background: var(--c-bg);
|
||||
--docsearch-searchbox-shadow: inset 0 0 0 2px var(--c-brand);
|
||||
--docsearch-hit-color: var(--c-text-light);
|
||||
--docsearch-hit-active-color: var(--c-bg);
|
||||
--docsearch-hit-background: var(--c-bg);
|
||||
--docsearch-hit-shadow: 0 1px 3px 0 var(--c-border-dark);
|
||||
--docsearch-footer-background: var(--c-bg);
|
||||
}
|
||||
|
||||
// dark plugin-docsearch
|
||||
html.dark .DocSearch {
|
||||
--docsearch-logo-color: var(--c-text);
|
||||
--docsearch-modal-shadow: inset 1px 1px 0 0 #2c2e40, 0 3px 8px 0 #000309;
|
||||
--docsearch-key-shadow: inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d,
|
||||
0 2px 2px 0 rgba(3, 4, 9, 0.3);
|
||||
--docsearch-key-gradient: linear-gradient(-225deg, #444950, #1c1e21);
|
||||
--docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, 0.5),
|
||||
0 -4px 8px 0 rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
// plugin-external-link-icon
|
||||
.external-link-icon {
|
||||
--external-link-icon-color: var(--c-text-quote);
|
||||
}
|
||||
|
||||
// plugin-medium-zoom
|
||||
.medium-zoom-overlay {
|
||||
--medium-zoom-bg-color: var(--c-bg);
|
||||
}
|
||||
|
||||
// plugin-nprogress
|
||||
#nprogress {
|
||||
--nprogress-color: var(--c-brand);
|
||||
}
|
||||
|
||||
// plugin-pwa-popup
|
||||
.pwa-popup {
|
||||
--pwa-popup-text-color: var(--c-text);
|
||||
--pwa-popup-bg-color: var(--c-bg);
|
||||
--pwa-popup-border-color: var(--c-brand);
|
||||
--pwa-popup-shadow: 0 4px 16px var(--c-brand);
|
||||
--pwa-popup-btn-text-color: var(--c-bg);
|
||||
--pwa-popup-btn-bg-color: var(--c-brand);
|
||||
--pwa-popup-btn-hover-bg-color: var(--c-brand-light);
|
||||
}
|
||||
|
||||
// plugin-search
|
||||
.search-box {
|
||||
--search-bg-color: var(--c-bg);
|
||||
--search-accent-color: var(--c-brand);
|
||||
--search-text-color: var(--c-text);
|
||||
--search-border-color: var(--c-border);
|
||||
|
||||
--search-item-text-color: var(--c-text-lighter);
|
||||
--search-item-focus-bg-color: var(--c-bg-light);
|
||||
}
|
||||
|
||||
.home .hero img {
|
||||
max-width: 500px !important;
|
||||
height: 100%;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.center {
|
||||
margin: 0 auto;
|
||||
width: 80%
|
||||
}
|
||||
|
||||
#main-title {
|
||||
display: none
|
||||
}
|
||||
|
||||
.center {
|
||||
margin: 0 auto;
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
#main-title {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.hero {
|
||||
margin: 150px 25px 70px;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Nerd Font';
|
||||
src: url("/nerd-font.woff2") format("woff2");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: 'Nerd Font', source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
}
|
893
docs/.yarn/releases/yarn-4.0.2.cjs
vendored
@ -1,3 +0,0 @@
|
||||
nodeLinker: node-modules
|
||||
|
||||
yarnPath: .yarn/releases/yarn-4.0.2.cjs
|
@ -1,41 +0,0 @@
|
||||
---
|
||||
home: true
|
||||
heroImage: /logo.png
|
||||
actions:
|
||||
- text: Get Started
|
||||
link: /guide/
|
||||
type: primary
|
||||
footer: MIT Licensed | Copyright © 2016-present jc21.com
|
||||
---
|
||||
|
||||
<div class="features">
|
||||
<div class="feature">
|
||||
<h2>Get Connected</h2>
|
||||
<p>
|
||||
Expose web services on your network ·
|
||||
Free SSL with Let's Encrypt ·
|
||||
Designed with security in mind ·
|
||||
Perfect for home networks
|
||||
</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<h2>Proxy Hosts</h2>
|
||||
<p>Expose your private network Web services and get connected anywhere.</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<h2>Beautiful UI</h2>
|
||||
<p>Based on Tabler, the interface is a pleasure to use. Configuring a server has never been so fun.</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<h2>Free SSL</h2>
|
||||
<p>Built in Let’s Encrypt support allows you to secure your Web services at no cost to you. The certificates even renew themselves!</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<h2>Docker FTW</h2>
|
||||
<p>Built as a Docker Image, Nginx Proxy Manager only requires a database.</p>
|
||||
</div>
|
||||
<div class="feature">
|
||||
<h2>Multiple Users</h2>
|
||||
<p>Configure other users to either view or manage their own hosts. Full access permissions are available.</p>
|
||||
</div>
|
||||
</div>
|
@ -1 +0,0 @@
|
||||
../../README.md
|
@ -1,23 +1,11 @@
|
||||
{
|
||||
"name": "docs",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"devDependencies": {
|
||||
"vuepress": "^2.0.0-rc.0"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vuepress dev",
|
||||
"build": "vuepress build"
|
||||
"dev": "vitepress dev --host",
|
||||
"build": "vitepress build",
|
||||
"preview": "vitepress preview"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"packageManager": "yarn@4.0.2",
|
||||
"dependencies": {
|
||||
"@vuepress/plugin-google-analytics": "2.0.0-rc.0",
|
||||
"@vuepress/plugin-search": "2.0.0-rc.0",
|
||||
"@vuepress/theme-default": "^2.0.0-rc.0",
|
||||
"vuepress-plugin-sitemap2": "^2.0.0-rc.5",
|
||||
"vuepress-plugin-zooming": "^1.1.8"
|
||||
}
|
||||
"devDependencies": {
|
||||
"vitepress": "^1.1.4"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
|
@ -1,12 +0,0 @@
|
||||
# Screenshots
|
||||
|
||||
<img class="no-medium-zoom zooming" src="/screenshots/login.png" alt="Login" title="Login" width="200"/>
|
||||
<img class="no-medium-zoom zooming" src="/screenshots/dashboard.png" alt="Dashboard" title="Dashboard" width="200"/>
|
||||
<img class="no-medium-zoom zooming" src="/screenshots/proxy-hosts.png" alt="Proxy Hosts" title="Proxy Hosts" width="200"/>
|
||||
<img class="no-medium-zoom zooming" src="/screenshots/proxy-hosts-add.png" alt="Add Proxy Host" title="Add Proxy Host" width="200"/>
|
||||
<img class="no-medium-zoom zooming" src="/screenshots/redirection-hosts.png" alt="Redirection Hosts" title="Redirection Hosts" width="200"/>
|
||||
<img class="no-medium-zoom zooming" src="/screenshots/dead-hosts.png" alt="404 Hosts" title="404 Hosts" width="200"/>
|
||||
<img class="no-medium-zoom zooming" src="/screenshots/permissions.png" alt="User Permissions" title="User Permissions" width="200"/>
|
||||
<img class="no-medium-zoom zooming" src="/screenshots/certificates.png" alt="Certificates" title="Certificates" width="200"/>
|
||||
<img class="no-medium-zoom zooming" src="/screenshots/audit-log.png" alt="Audit Log" title="Audit Log" width="200"/>
|
||||
<img class="no-medium-zoom zooming" src="/screenshots/custom-settings.png" alt="Custom Settings" title="Custom Settings" width="200"/>
|
@ -1,3 +1,7 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Advanced Configuration
|
||||
|
||||
## Running processes as a user/group
|
||||
@ -169,6 +173,7 @@ NPM has the ability to include different custom configuration snippets in differ
|
||||
|
||||
You can add your custom configuration snippet files at `/data/nginx/custom` as follow:
|
||||
|
||||
- `/data/nginx/custom/root_top.conf`: Included at the top of nginx.conf
|
||||
- `/data/nginx/custom/root.conf`: Included at the very end of nginx.conf
|
||||
- `/data/nginx/custom/http_top.conf`: Included at the top of the main http block
|
||||
- `/data/nginx/custom/http.conf`: Included at the end of the main http block
|
||||
@ -195,6 +200,28 @@ value by specifying it as a Docker environment variable. The default if not spec
|
||||
...
|
||||
```
|
||||
|
||||
## OpenID Connect SSO
|
||||
|
||||
You can secure any of your proxy hosts with OpenID Connect authentication, providing SSO support from an identity provider like Azure AD or KeyCloak. OpenID Connect support is provided through the [`lua-resty-openidc`](https://github.com/zmartzone/lua-resty-openidc) library of [`OpenResty`](https://github.com/openresty/openresty).
|
||||
|
||||
You will need a few things to get started with OpenID Connect:
|
||||
|
||||
- A registered application with your identity provider, they will provide you with a `Client ID` and a `Client Secret`. Public OpenID Connect applications (without a client secret) are not yet supported.
|
||||
|
||||
- A redirect URL to send the users to after they login with the identity provider, this can be any unused URL under the proxy host, like `https://<proxy host url>/private/callback`, the server will take care of capturing that URL and redirecting you to the proxy host root. You will need to add this URL to the list of allowed redirect URLs for the application you registered with your identity provider.
|
||||
|
||||
- The well-known discovery endpoint of the identity provider you want to use, this is an URL usually with the form `https://<provider URL>/.well-known/openid-configuration`.
|
||||
|
||||
After you have all this you can proceed to configure the proxy host with OpenID Connect authentication.
|
||||
|
||||
You can also add some rudimentary access control through a list of allowed emails in case your identity provider doesn't let you do that, if this option is enabled, any email not on that list will be denied access to the proxied host.
|
||||
|
||||
The proxy adds some headers based on the authentication result from the identity provider:
|
||||
|
||||
- `X-OIDC-SUB`: The subject identifier, according to the OpenID Coonect spec: `A locally unique and never reassigned identifier within the Issuer for the End-User`.
|
||||
- `X-OIDC-EMAIL`: The email of the user that logged in, as specified in the `id_token` returned from the identity provider. The same value that will be checked for the email whitelist.
|
||||
- `X-OIDC-NAME`: The user's name claim from the `id_token`, please note that not all id tokens necessarily contain this claim.
|
||||
|
||||
## Customising logrotate settings
|
||||
|
||||
By default, NPM rotates the access- and error logs weekly and keeps 4 and 10 log files respectively.
|
||||
@ -209,26 +236,11 @@ You can customise the logrotate configuration through a mount (if your custom co
|
||||
|
||||
For reference, the default configuration can be found [here](https://github.com/NginxProxyManager/nginx-proxy-manager/blob/develop/docker/rootfs/etc/logrotate.d/nginx-proxy-manager).
|
||||
|
||||
## Enabling PROXY protocol for Proxy Hosts
|
||||
## Enabling the geoip2 module
|
||||
|
||||
When running NPM behind a load balancer, you might want to use the [PROXY procotol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) to receive client information such as the source IP address (useful for banning IPs).
|
||||
To enable the geoip2 module, you can create the custom configuration file `/data/nginx/custom/root_top.conf` and include the following snippet:
|
||||
|
||||
When configuring the PROXY protocol for proxy hosts, NPM uses the ports 88 for http and 444 for https traffic to allow you to decide on a per host basis whether to use the PROSY protocol.
|
||||
|
||||
To enable the PROXY protocol for your hosts you need to perform the following steps:
|
||||
|
||||
1. Expose the ports `88` (and `444` is applicable) by adjusting your `docker-compose.yml`
|
||||
2. Edit your proxy hosts to enable the PROXY protocol
|
||||
3. Edit your upstream load balancer to redirect traffic to the port `88`/`444` and enable the PROXY protocol
|
||||
|
||||
## Enabling PROXY protocol for Streams
|
||||
|
||||
When running NPM behind a load balancer, you might want to use the [PROXY procotol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) to receive client information such as the source IP address (useful for banning IPs).
|
||||
|
||||
Keep in mind that the PROXY procotol cannot be enabled for udp endpoints.
|
||||
|
||||
To enable the PROXY protocol for streams:
|
||||
|
||||
1. Expose the desired port by adjusting you `docker-compose.yml`
|
||||
2. Edit the Stream to enable the PROXY protocol
|
||||
3. Edit your upstream load balancer to enable the PROXY protocol
|
||||
```
|
||||
load_module /usr/lib/nginx/modules/ngx_http_geoip2_module.so;
|
||||
load_module /usr/lib/nginx/modules/ngx_stream_geoip2_module.so;
|
||||
```
|
@ -1,26 +1,26 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# FAQ
|
||||
|
||||
## Do I have to use Docker?
|
||||
|
||||
Yes, that's how this project is packaged.
|
||||
|
||||
This makes it easier to support the project when I have control over the version of Nginx and NodeJS
|
||||
being used. In future this could change if the backend was no longer using NodeJS and it's long list
|
||||
of dependencies.
|
||||
|
||||
This makes it easier to support the project when we have control over the version of Nginx other packages
|
||||
use by the project.
|
||||
|
||||
## Can I run it on a Raspberry Pi?
|
||||
|
||||
Yes! The docker image is multi-arch and is built for a variety of architectures. If yours is
|
||||
[not listed](https://hub.docker.com/r/jc21/nginx-proxy-manager/tags) please open a
|
||||
[GitHub issue](https://github.com/jc21/nginx-proxy-manager/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=).
|
||||
[GitHub issue](https://github.com/NginxProxyManager/nginx-proxy-manager/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=).
|
||||
|
||||
## I can't get my service to proxy properly?
|
||||
|
||||
Your best bet is to ask the [Reddit community for support](https://www.reddit.com/r/nginxproxymanager/). There's safety in numbers.
|
||||
|
||||
Gitter is best left for anyone contributing to the project to ask for help about internals, code reviews etc.
|
||||
|
||||
## When adding username and password access control to a proxy host, I can no longer login into the app.
|
||||
|
||||
Having an Access Control List (ACL) with username and password requires the browser to always send this username and password in the `Authorization` header on each request. If your proxied app also requires authentication (like Nginx Proxy Manager itself), most likely the app will also use the `Authorization` header to transmit this information, as this is the standardized header meant for this kind of information. However having multiples of the same headers is not allowed in the [internet standard](https://www.rfc-editor.org/rfc/rfc7230#section-3.2.2) and almost all apps do not support multiple values in the `Authorization` header. Hence one of the two logins will be broken. This can only be fixed by either removing one of the logins or by changing the app to use other non-standard headers for authorization.
|
126
docs/src/guide/index.md
Normal file
@ -0,0 +1,126 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Guide
|
||||
|
||||
::: raw
|
||||
<p align="center">
|
||||
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager" style="display:inline;margin-right:5px;">
|
||||
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge" style="display:inline;">
|
||||
</a>
|
||||
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager" style="display:inline;margin-right:5px;">
|
||||
<img src="https://img.shields.io/docker/pulls/jc21/nginx-proxy-manager.svg?style=for-the-badge" style="display:inline;">
|
||||
</a>
|
||||
</p>
|
||||
:::
|
||||
|
||||
This project comes as a pre-built docker image that enables you to easily forward to your websites
|
||||
running at home or otherwise, including free SSL, without having to know too much about Nginx or Letsencrypt.
|
||||
|
||||
- [Quick Setup](#quick-setup)
|
||||
- [Full Setup](/setup/)
|
||||
- [Screenshots](/screenshots/)
|
||||
|
||||
## Project Goal
|
||||
|
||||
I created this project to fill a personal need to provide users with an easy way to accomplish reverse
|
||||
proxying hosts with SSL termination and it had to be so easy that a monkey could do it. This goal hasn't changed.
|
||||
While there might be advanced options they are optional and the project should be as simple as possible
|
||||
so that the barrier for entry here is low.
|
||||
|
||||
::: raw
|
||||
<a href="https://www.buymeacoffee.com/jc21" target="_blank"><img src="http://public.jc21.com/github/by-me-a-coffee.png" alt="Buy Me A Coffee" style="height: 51px !important;width: 217px !important;" ></a>
|
||||
:::
|
||||
|
||||
## Features
|
||||
|
||||
- Beautiful and Secure Admin Interface based on [Tabler](https://tabler.github.io/)
|
||||
- Easily create forwarding domains, redirections, streams and 404 hosts without knowing anything about Nginx
|
||||
- Free SSL using Let's Encrypt or provide your own custom SSL certificates
|
||||
- Access Lists and basic HTTP Authentication for your hosts
|
||||
- Advanced Nginx configuration available for super users
|
||||
- User management, permissions and audit log
|
||||
|
||||
|
||||
## Hosting your home network
|
||||
|
||||
I won't go in to too much detail here but here are the basics for someone new to this self-hosted world.
|
||||
|
||||
1. Your home router will have a Port Forwarding section somewhere. Log in and find it
|
||||
2. Add port forwarding for port 80 and 443 to the server hosting this project
|
||||
3. Configure your domain name details to point to your home, either with a static ip or a service like DuckDNS or [Amazon Route53](https://github.com/jc21/route53-ddns)
|
||||
4. Use the Nginx Proxy Manager as your gateway to forward to your other web based services
|
||||
|
||||
## Quick Setup
|
||||
|
||||
1. Install Docker and Docker-Compose
|
||||
|
||||
- [Docker Install documentation](https://docs.docker.com/get-docker/)
|
||||
- [Docker-Compose Install documentation](https://docs.docker.com/compose/install/)
|
||||
|
||||
2. Create a docker-compose.yml file similar to this:
|
||||
|
||||
```yml
|
||||
version: '3.8'
|
||||
services:
|
||||
app:
|
||||
image: 'jc21/nginx-proxy-manager:latest'
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- '80:80'
|
||||
- '81:81'
|
||||
- '443:443'
|
||||
volumes:
|
||||
- ./data:/data
|
||||
- ./letsencrypt:/etc/letsencrypt
|
||||
```
|
||||
|
||||
This is the bare minimum configuration required. See the [documentation](https://nginxproxymanager.com/setup/) for more.
|
||||
|
||||
3. Bring up your stack by running
|
||||
|
||||
```bash
|
||||
docker-compose up -d
|
||||
|
||||
# If using docker-compose-plugin
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
4. Log in to the Admin UI
|
||||
|
||||
When your docker container is running, connect to it on port `81` for the admin interface.
|
||||
Sometimes this can take a little bit because of the entropy of keys.
|
||||
|
||||
[http://127.0.0.1:81](http://127.0.0.1:81)
|
||||
|
||||
Default Admin User:
|
||||
```
|
||||
Email: admin@example.com
|
||||
Password: changeme
|
||||
```
|
||||
|
||||
Immediately after logging in with this default user you will be asked to modify your details and change your password.
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
All are welcome to create pull requests for this project, against the `develop` branch. Official releases are created from the `master` branch.
|
||||
|
||||
CI is used in this project. All PR's must pass before being considered. After passing,
|
||||
docker builds for PR's are available on dockerhub for manual verifications.
|
||||
|
||||
Documentation within the `develop` branch is available for preview at
|
||||
[https://develop.nginxproxymanager.com](https://develop.nginxproxymanager.com)
|
||||
|
||||
|
||||
### Contributors
|
||||
|
||||
Special thanks to [all of our contributors](https://github.com/NginxProxyManager/nginx-proxy-manager/graphs/contributors).
|
||||
|
||||
|
||||
## Getting Support
|
||||
|
||||
1. [Found a bug?](https://github.com/NginxProxyManager/nginx-proxy-manager/issues)
|
||||
2. [Discussions](https://github.com/NginxProxyManager/nginx-proxy-manager/discussions)
|
||||
3. [Reddit](https://reddit.com/r/nginxproxymanager)
|
32
docs/src/index.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
# https://vitepress.dev/reference/default-theme-home-page
|
||||
layout: home
|
||||
|
||||
hero:
|
||||
name: "Nginx Proxy Manager"
|
||||
tagline: Expose your services easily and securely
|
||||
image:
|
||||
src: /logo.svg
|
||||
alt: NPM Logo
|
||||
actions:
|
||||
- theme: brand
|
||||
text: Get Started
|
||||
link: /guide/
|
||||
- theme: alt
|
||||
text: GitHub
|
||||
link: https://github.com/NginxProxyManager/nginx-proxy-manager
|
||||
|
||||
features:
|
||||
- title: Get Connected
|
||||
details: Expose web services on your network · Free SSL with Let's Encrypt · Designed with security in mind · Perfect for home networks
|
||||
- title: Proxy Hosts
|
||||
details: Expose your private network Web services and get connected anywhere.
|
||||
- title: Beautiful UI
|
||||
details: Based on Tabler, the interface is a pleasure to use. Configuring a server has never been so fun.
|
||||
- title: Free SSL
|
||||
details: Built in Let’s Encrypt support allows you to secure your Web services at no cost to you. The certificates even renew themselves!
|
||||
- title: Docker FTW
|
||||
details: Built as a Docker Image, Nginx Proxy Manager only requires a database.
|
||||
- title: Multiple Users
|
||||
details: Configure other users to either view or manage their own hosts. Full access permissions are available.
|
||||
---
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 106 KiB After Width: | Height: | Size: 106 KiB |
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 178 KiB |
Before Width: | Height: | Size: 173 KiB After Width: | Height: | Size: 173 KiB |
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 141 KiB |
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 150 KiB |
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB |
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 151 KiB |
Before Width: | Height: | Size: 207 KiB After Width: | Height: | Size: 207 KiB |
Before Width: | Height: | Size: 181 KiB After Width: | Height: | Size: 181 KiB |
Before Width: | Height: | Size: 162 KiB After Width: | Height: | Size: 162 KiB |
20
docs/src/screenshots/index.md
Normal file
@ -0,0 +1,20 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Screenshots
|
||||
|
||||
::: raw
|
||||
<div class="inline-img">
|
||||
<a href="/screenshots/login.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/login.png" alt="Login" title="Login" width="200"/></a>
|
||||
<a href="/screenshots/dashboard.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/dashboard.png" alt="Dashboard" title="Dashboard" width="200"/></a>
|
||||
<a href="/screenshots/proxy-hosts.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/proxy-hosts.png" alt="Proxy Hosts" title="Proxy Hosts" width="200"/></a>
|
||||
<a href="/screenshots/proxy-hosts-add.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/proxy-hosts-add.png" alt="Add Proxy Host" title="Add Proxy Host" width="200"/></a>
|
||||
<a href="/screenshots/redirection-hosts.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/redirection-hosts.png" alt="Redirection Hosts" title="Redirection Hosts" width="200"/></a>
|
||||
<a href="/screenshots/dead-hosts.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/dead-hosts.png" alt="404 Hosts" title="404 Hosts" width="200"/></a>
|
||||
<a href="/screenshots/permissions.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/permissions.png" alt="User Permissions" title="User Permissions" width="200"/></a>
|
||||
<a href="/screenshots/certificates.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/certificates.png" alt="Certificates" title="Certificates" width="200"/></a>
|
||||
<a href="/screenshots/audit-log.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/audit-log.png" alt="Audit Log" title="Audit Log" width="200"/></a>
|
||||
<a href="/screenshots/custom-settings.png" target="_blank"><img class="no-medium-zoom zooming" src="/screenshots/custom-settings.png" alt="Custom Settings" title="Custom Settings" width="200"/></a>
|
||||
</div>
|
||||
:::
|
@ -1,3 +1,7 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Full Setup Instructions
|
||||
|
||||
## Running the App
|
||||
@ -61,8 +65,6 @@ services:
|
||||
- '80:80' # Public HTTP Port
|
||||
- '443:443' # Public HTTPS Port
|
||||
- '81:81' # Admin Web Port
|
||||
# - '88:88' # Public HTTP Port with proxy_protocol enabled
|
||||
# - '444:444' # Public HTTPS Port with proxy_protocol enabled
|
||||
# Add any other Stream port you want to expose
|
||||
# - '21:21' # FTP
|
||||
environment:
|
@ -1,3 +1,7 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Third Party
|
||||
|
||||
As this software gains popularity it's common to see it integrated with other platforms. Please be aware that unless specifically mentioned in the documentation of those
|
||||
@ -12,5 +16,4 @@ Known integrations:
|
||||
|
||||
|
||||
If you would like your integration of NPM listed, please open a
|
||||
[Github issue](https://github.com/jc21/nginx-proxy-manager/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=)
|
||||
|
||||
[Github issue](https://github.com/NginxProxyManager/nginx-proxy-manager/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=)
|
@ -1,8 +1,12 @@
|
||||
---
|
||||
outline: deep
|
||||
---
|
||||
|
||||
# Upgrading
|
||||
|
||||
```bash
|
||||
docker-compose pull
|
||||
docker-compose up -d
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
This project will automatically update any databases or other requirements so you don't have to follow
|
4120
docs/yarn.lock
@ -11,6 +11,7 @@
|
||||
<li role="presentation" class="nav-item"><a href="#locations" aria-controls="tab4" role="tab" data-toggle="tab" class="nav-link"><i class="fe fe-layers"></i> <%- i18n('all-hosts', 'locations') %></a></li>
|
||||
<li role="presentation" class="nav-item"><a href="#ssl-options" aria-controls="tab2" role="tab" data-toggle="tab" class="nav-link"><i class="fe fe-shield"></i> <%- i18n('str', 'ssl') %></a></li>
|
||||
<li role="presentation" class="nav-item"><a href="#advanced" aria-controls="tab3" role="tab" data-toggle="tab" class="nav-link"><i class="fe fe-settings"></i> <%- i18n('all-hosts', 'advanced') %></a></li>
|
||||
<li role="presentation" class="nav-item"><a href="#openidc" aria-controls="tab3" role="tab" data-toggle="tab" class="nav-link"><i class="fe fe-settings"></i><%- i18n('proxy-hosts', 'oidc') %></a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
|
||||
@ -72,7 +73,7 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-6">
|
||||
<div class="col-sm-12 col-md-12">
|
||||
<div class="form-group">
|
||||
<label class="custom-switch">
|
||||
<input type="checkbox" class="custom-switch-input" name="allow_websocket_upgrade" value="1"<%- allow_websocket_upgrade ? ' checked' : '' %>>
|
||||
@ -81,22 +82,6 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="custom-switch">
|
||||
<input type="checkbox" class="custom-switch-input" name="enable_proxy_protocol" value="1"<%- enable_proxy_protocol ? ' checked' : '' %>>
|
||||
<span class="custom-switch-indicator"></span>
|
||||
<span class="custom-switch-description"><%- i18n('proxy-hosts', 'enable-proxy-protocol') %><a href="https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/#introduction" target="_blank"><i class="fe fe-help-circle"></i></a></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-12">
|
||||
<div class="form-group">
|
||||
<label class="form-label"><%- i18n('proxy-hosts', 'load-balancer-ip') %> <a href="https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/#changing-the-load-balancers-ip-address-to-the-client-ip-address" target="_blank"><i class="fe fe-help-circle"></i></a></label>
|
||||
<input type="text" name="load_balancer_ip" class="form-control text-monospace" placeholder="" value="<%- load_balancer_ip %>" autocomplete="off" maxlength="255" <%- enable_proxy_protocol ? '' : ' disabled' %>>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-12">
|
||||
<div class="form-group">
|
||||
@ -287,6 +272,71 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- OpenID Connect -->
|
||||
<div role="tabpanel" class="tab-pane" id="openidc">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-12">
|
||||
<div class="form-group">
|
||||
<label class="custom-switch">
|
||||
<input type="checkbox" class="custom-switch-input" name="openidc_enabled" value="1"<%- openidc_enabled ? ' checked' : '' %>>
|
||||
<span class="custom-switch-indicator"></span>
|
||||
<span class="custom-switch-description"><%- i18n('proxy-hosts', 'oidc-enabled') %></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-12 openidc">
|
||||
<div class="form-group">
|
||||
<label class="form-label"><%- i18n('proxy-hosts', 'oidc-redirect-uri') %><span class="form-required">*</span></label>
|
||||
<input type="text" name="openidc_redirect_uri" class="form-control text-monospace" placeholder="" value="<%- openidc_redirect_uri %>" autocomplete="off" maxlength="255" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-12 openidc">
|
||||
<div class="form-group">
|
||||
<label class="form-label"><%- i18n('proxy-hosts', 'oidc-discovery-endpoint') %><span class="form-required">*</span></label>
|
||||
<input type="text" name="openidc_discovery" class="form-control text-monospace" placeholder="" value="<%- openidc_discovery %>" autocomplete="off" maxlength="255" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-12 openidc">
|
||||
<div class="form-group">
|
||||
<label class="form-label"><%- i18n('proxy-hosts', 'oidc-token-auth-method') %><span class="form-required">*</span></label>
|
||||
<select name="openidc_auth_method" class="form-control custom-select" placeholder="client_secret_post">
|
||||
<option value="client_secret_post" <%- openidc_auth_method === 'client_secret_post' ? 'selected' : '' %>>client_secret_post</option>
|
||||
<option value="client_secret_basic" <%- openidc_auth_method === 'client_secret_basic' ? 'selected' : '' %>>client_secret_basic</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-12 openidc">
|
||||
<div class="form-group">
|
||||
<label class="form-label"><%- i18n('proxy-hosts', 'oidc-client-id') %><span class="form-required">*</span></label>
|
||||
<input type="text" name="openidc_client_id" class="form-control text-monospace" placeholder="" value="<%- openidc_client_id %>" autocomplete="off" maxlength="255" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-12 openidc">
|
||||
<div class="form-group">
|
||||
<label class="form-label"><%- i18n('proxy-hosts', 'oidc-client-secret') %><span class="form-required">*</span></label>
|
||||
<input type="text" name="openidc_client_secret" class="form-control text-monospace" placeholder="" value="<%- openidc_client_secret %>" autocomplete="off" maxlength="255" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="openidc">
|
||||
<div class="col-sm-12 col-md-12">
|
||||
<div class="form-group">
|
||||
<label class="custom-switch">
|
||||
<input type="checkbox" class="custom-switch-input" name="openidc_restrict_users_enabled" value="1"<%- openidc_restrict_users_enabled ? ' checked' : '' %>>
|
||||
<span class="custom-switch-indicator"></span>
|
||||
<span class="custom-switch-description"><%- i18n('proxy-hosts', 'oidc-allow-only-emails') %></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-12 openidc_users">
|
||||
<div class="form-group">
|
||||
<label class="form-label"><%- i18n('proxy-hosts', 'oidc-allowed-emails') %><span class="form-required">*</span></label>
|
||||
<input type="text" name="openidc_allowed_users" class="form-control" id="openidc_allowed_users" value="<%- openidc_allowed_users.join(',') %>" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -43,9 +43,12 @@ module.exports = Mn.View.extend({
|
||||
dns_provider_credentials: 'textarea[name="meta[dns_provider_credentials]"]',
|
||||
propagation_seconds: 'input[name="meta[propagation_seconds]"]',
|
||||
forward_scheme: 'select[name="forward_scheme"]',
|
||||
enable_proxy_protocol: 'input[name="enable_proxy_protocol"]',
|
||||
load_balancer_ip: 'input[name="load_balancer_ip"]',
|
||||
letsencrypt: '.letsencrypt'
|
||||
letsencrypt: '.letsencrypt',
|
||||
openidc_enabled: 'input[name="openidc_enabled"]',
|
||||
openidc_restrict_users_enabled: 'input[name="openidc_restrict_users_enabled"]',
|
||||
openidc_allowed_users: 'input[name="openidc_allowed_users"]',
|
||||
openidc: '.openidc',
|
||||
openidc_users: '.openidc_users',
|
||||
},
|
||||
|
||||
regions: {
|
||||
@ -53,13 +56,6 @@ module.exports = Mn.View.extend({
|
||||
},
|
||||
|
||||
events: {
|
||||
'change @ui.enable_proxy_protocol': function () {
|
||||
let checked = this.ui.enable_proxy_protocol.prop('checked');
|
||||
this.ui.load_balancer_ip
|
||||
.prop('disabled', !checked)
|
||||
.parents('.form-group')
|
||||
.css('opacity', checked ? 1 : 0.5);
|
||||
},
|
||||
'change @ui.certificate_select': function () {
|
||||
let id = this.ui.certificate_select.val();
|
||||
if (id === 'new') {
|
||||
@ -138,6 +134,27 @@ module.exports = Mn.View.extend({
|
||||
}
|
||||
},
|
||||
|
||||
'change @ui.openidc_enabled': function () {
|
||||
let checked = this.ui.openidc_enabled.prop('checked');
|
||||
|
||||
if (checked) {
|
||||
this.ui.openidc.show().find('input').prop('disabled', false);
|
||||
} else {
|
||||
this.ui.openidc.hide().find('input').prop('disabled', true);
|
||||
}
|
||||
|
||||
this.ui.openidc_restrict_users_enabled.trigger('change');
|
||||
},
|
||||
|
||||
'change @ui.openidc_restrict_users_enabled': function () {
|
||||
let checked = this.ui.openidc_restrict_users_enabled.prop('checked');
|
||||
if (checked) {
|
||||
this.ui.openidc_users.show().find('input').prop('disabled', false);
|
||||
} else {
|
||||
this.ui.openidc_users.hide().find('input').prop('disabled', true);
|
||||
}
|
||||
},
|
||||
|
||||
'click @ui.add_location_btn': function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
@ -172,11 +189,18 @@ module.exports = Mn.View.extend({
|
||||
data.block_exploits = !!data.block_exploits;
|
||||
data.caching_enabled = !!data.caching_enabled;
|
||||
data.allow_websocket_upgrade = !!data.allow_websocket_upgrade;
|
||||
data.enable_proxy_protocol = !!data.enable_proxy_protocol;
|
||||
data.http2_support = !!data.http2_support;
|
||||
data.hsts_enabled = !!data.hsts_enabled;
|
||||
data.hsts_subdomains = !!data.hsts_subdomains;
|
||||
data.ssl_forced = !!data.ssl_forced;
|
||||
data.openidc_enabled = data.openidc_enabled === '1';
|
||||
data.openidc_restrict_users_enabled = data.openidc_restrict_users_enabled === '1';
|
||||
|
||||
if (data.openidc_restrict_users_enabled) {
|
||||
if (typeof data.openidc_allowed_users === 'string' && data.openidc_allowed_users) {
|
||||
data.openidc_allowed_users = data.openidc_allowed_users.split(',');
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof data.meta === 'undefined') data.meta = {};
|
||||
data.meta.letsencrypt_agree = data.meta.letsencrypt_agree == 1;
|
||||
@ -213,6 +237,12 @@ module.exports = Mn.View.extend({
|
||||
data.certificate_id = parseInt(data.certificate_id, 10);
|
||||
}
|
||||
|
||||
// OpenID Connect won't work with multiple domain names because the redirect URL has to point to a specific one
|
||||
if (data.openidc_enabled && data.domain_names.length > 1) {
|
||||
alert('Cannot use mutliple domain names when OpenID Connect is enabled');
|
||||
return;
|
||||
}
|
||||
|
||||
let method = App.Api.Nginx.ProxyHosts.create;
|
||||
let is_new = true;
|
||||
|
||||
@ -274,7 +304,6 @@ module.exports = Mn.View.extend({
|
||||
onRender: function () {
|
||||
let view = this;
|
||||
|
||||
this.ui.enable_proxy_protocol.trigger('change');
|
||||
this.ui.ssl_forced.trigger('change');
|
||||
this.ui.hsts_enabled.trigger('change');
|
||||
|
||||
@ -355,6 +384,23 @@ module.exports = Mn.View.extend({
|
||||
view.ui.certificate_select[0].selectize.setValue(view.model.get('certificate_id'));
|
||||
}
|
||||
});
|
||||
|
||||
// OpenID Connect
|
||||
this.ui.openidc_allowed_users.selectize({
|
||||
delimiter: ',',
|
||||
persist: false,
|
||||
maxOptions: 15,
|
||||
create: function (input) {
|
||||
return {
|
||||
value: input,
|
||||
text: input
|
||||
};
|
||||
}
|
||||
});
|
||||
this.ui.openidc.hide().find('input').prop('disabled', true);
|
||||
this.ui.openidc_users.hide().find('input').prop('disabled', true);
|
||||
this.ui.openidc_enabled.trigger('change');
|
||||
this.ui.openidc_restrict_users_enabled.trigger('change');
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
|
@ -42,22 +42,6 @@
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-6">
|
||||
<div class="form-group">
|
||||
<label class="custom-switch">
|
||||
<input type="checkbox" class="custom-switch-input" name="enable_proxy_protocol" value="1"<%- enable_proxy_protocol ? ' checked' : '' %>>
|
||||
<span class="custom-switch-indicator"></span>
|
||||
<span class="custom-switch-description"><%- i18n('streams', 'enable-proxy-protocol') %><a href="https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/#introduction" target="_blank"><i class="fe fe-help-circle"></i></a></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-12">
|
||||
<div class="form-group">
|
||||
<label class="form-label"><%- i18n('streams', 'load-balancer-ip') %><a href="https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/#changing-the-load-balancers-ip-address-to-the-client-ip-address" target="_blank"><i class="fe fe-help-circle"></i></a></label>
|
||||
<input type="text" name="load_balancer_ip" class="form-control text-monospace" placeholder="" value="<%- load_balancer_ip %>" autocomplete="off" maxlength="255" <%- enable_proxy_protocol ? '' : ' disabled' %>>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-12">
|
||||
<div class="forward-type-error invalid-feedback"><%- i18n('streams', 'forward-type-error') %></div>
|
||||
</div>
|
||||
|
@ -14,8 +14,6 @@ module.exports = Mn.View.extend({
|
||||
ui: {
|
||||
form: 'form',
|
||||
forwarding_host: 'input[name="forwarding_host"]',
|
||||
enable_proxy_protocol: 'input[name="enable_proxy_protocol"]',
|
||||
load_balancer_ip: 'input[name="load_balancer_ip"]',
|
||||
type_error: '.forward-type-error',
|
||||
buttons: '.modal-footer button',
|
||||
switches: '.custom-switch-input',
|
||||
@ -24,13 +22,6 @@ module.exports = Mn.View.extend({
|
||||
},
|
||||
|
||||
events: {
|
||||
'change @ui.enable_proxy_protocol': function () {
|
||||
let checked = this.ui.enable_proxy_protocol.prop('checked');
|
||||
this.ui.load_balancer_ip
|
||||
.prop('disabled', !checked)
|
||||
.parents('.form-group')
|
||||
.css('opacity', checked ? 1 : 0.5);
|
||||
},
|
||||
'change @ui.switches': function () {
|
||||
this.ui.type_error.hide();
|
||||
},
|
||||
@ -56,7 +47,6 @@ module.exports = Mn.View.extend({
|
||||
data.forwarding_port = parseInt(data.forwarding_port, 10);
|
||||
data.tcp_forwarding = !!data.tcp_forwarding;
|
||||
data.udp_forwarding = !!data.udp_forwarding;
|
||||
data.enable_proxy_protocol = !!data.enable_proxy_protocol;
|
||||
|
||||
let method = App.Api.Nginx.Streams.create;
|
||||
let is_new = true;
|
||||
@ -86,10 +76,6 @@ module.exports = Mn.View.extend({
|
||||
}
|
||||
},
|
||||
|
||||
onRender: function () {
|
||||
this.ui.enable_proxy_protocol.trigger('change');
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
if (typeof options.model === 'undefined' || !options.model) {
|
||||
this.model = new StreamModel.Model();
|
||||
|
@ -131,9 +131,17 @@
|
||||
"help-content": "A Proxy Host is the incoming endpoint for a web service that you want to forward.\nIt provides optional SSL termination for your service that might not have SSL support built in.\nProxy Hosts are the most common use for the Nginx Proxy Manager.",
|
||||
"access-list": "Access List",
|
||||
"allow-websocket-upgrade": "Websockets Support",
|
||||
"enable-proxy-protocol": "Enable Proxy Protocol",
|
||||
"load-balancer-ip": "Load balancer or TCP proxy IP / CIDR range",
|
||||
"ignore-invalid-upstream-ssl": "Ignore Invalid SSL",
|
||||
"custom-forward-host-help": "Use 1.1.1.1/path for sub-folder forwarding",
|
||||
"oidc": "OpenID Connect",
|
||||
"oidc-enabled": "Use OpenID Connect authentication",
|
||||
"oidc-redirect-uri": "Redirect URI",
|
||||
"oidc-discovery-endpoint": "Well-known discovery endpoint",
|
||||
"oidc-token-auth-method": "Token endpoint auth method",
|
||||
"oidc-client-id": "Client ID",
|
||||
"oidc-client-secret": "Client secret",
|
||||
"oidc-allow-only-emails": "Allow only these user emails",
|
||||
"oidc-allowed-emails": "Allowed email addresses",
|
||||
"custom-forward-host-help": "Add a path for sub-folder forwarding.\nExample: 203.0.113.25/path/",
|
||||
"search": "Search Host…"
|
||||
},
|
||||
@ -177,8 +185,6 @@
|
||||
"protocol": "Protocol",
|
||||
"tcp": "TCP",
|
||||
"udp": "UDP",
|
||||
"enable-proxy-protocol": "Enable Proxy Protocol",
|
||||
"load-balancer-ip": "Load balancer or TCP proxy IP / CIDR range",
|
||||
"delete": "Delete Stream",
|
||||
"delete-confirm": "Are you sure you want to delete this Stream?",
|
||||
"help-title": "What is a Stream?",
|
||||
|
@ -19,11 +19,17 @@ const model = Backbone.Model.extend({
|
||||
hsts_subdomains: false,
|
||||
caching_enabled: false,
|
||||
allow_websocket_upgrade: false,
|
||||
enable_proxy_protocol: false,
|
||||
load_balancer_ip: '',
|
||||
block_exploits: false,
|
||||
http2_support: false,
|
||||
advanced_config: '',
|
||||
openidc_enabled: false,
|
||||
openidc_redirect_uri: '',
|
||||
openidc_discovery: '',
|
||||
openidc_auth_method: 'client_secret_post',
|
||||
openidc_client_id: '',
|
||||
openidc_client_secret: '',
|
||||
openidc_restrict_users_enabled: false,
|
||||
openidc_allowed_users: [],
|
||||
enabled: true,
|
||||
meta: {},
|
||||
// The following are expansions:
|
||||
|
@ -13,8 +13,6 @@ const model = Backbone.Model.extend({
|
||||
forwarding_port: null,
|
||||
tcp_forwarding: true,
|
||||
udp_forwarding: false,
|
||||
enable_proxy_protocol: false,
|
||||
load_balancer_ip: "",
|
||||
enabled: true,
|
||||
meta: {},
|
||||
// The following are expansions:
|
||||
|
@ -6514,22 +6514,10 @@ tapable@^1.0.0, tapable@^1.1.3:
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
|
||||
integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
|
||||
|
||||
tar@^6.0.2:
|
||||
version "6.1.11"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
|
||||
integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
|
||||
dependencies:
|
||||
chownr "^2.0.0"
|
||||
fs-minipass "^2.0.0"
|
||||
minipass "^3.0.0"
|
||||
minizlib "^2.1.1"
|
||||
mkdirp "^1.0.3"
|
||||
yallist "^4.0.0"
|
||||
|
||||
tar@^6.1.11, tar@^6.1.2:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73"
|
||||
integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==
|
||||
tar@^6.0.2, tar@^6.1.11, tar@^6.1.2:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a"
|
||||
integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==
|
||||
dependencies:
|
||||
chownr "^2.0.0"
|
||||
fs-minipass "^2.0.0"
|
||||
|
@ -35,8 +35,8 @@
|
||||
"name": "Cloudflare",
|
||||
"package_name": "certbot-dns-cloudflare",
|
||||
"version": "=={{certbot-version}}",
|
||||
"dependencies": "cloudflare acme=={{certbot-version}}",
|
||||
"credentials": "# Cloudflare API token\ndns_cloudflare_api_token = 0123456789abcdef0123456789abcdef01234567",
|
||||
"dependencies": "cloudflare==2.19.* acme=={{certbot-version}}",
|
||||
"credentials": "# Cloudflare API token\ndns_cloudflare_api_token=0123456789abcdef0123456789abcdef01234567",
|
||||
"full_plugin_name": "dns-cloudflare"
|
||||
},
|
||||
"cloudns": {
|
||||
@ -90,7 +90,7 @@
|
||||
"duckdns": {
|
||||
"name": "DuckDNS",
|
||||
"package_name": "certbot-dns-duckdns",
|
||||
"version": "~=0.9",
|
||||
"version": "~=1.0",
|
||||
"dependencies": "",
|
||||
"credentials": "dns_duckdns_token=your-duckdns-token",
|
||||
"full_plugin_name": "dns-duckdns"
|
||||
@ -127,6 +127,14 @@
|
||||
"credentials": "dns_dnsmadeeasy_api_key = 1c1a3c91-4770-4ce7-96f4-54c0eb0e457a\ndns_dnsmadeeasy_secret_key = c9b5625f-9834-4ff8-baba-4ed5f32cae55",
|
||||
"full_plugin_name": "dns-dnsmadeeasy"
|
||||
},
|
||||
"dnsmulti": {
|
||||
"name": "DnsMulti",
|
||||
"package_name": "certbot-dns-multi",
|
||||
"version": "~=4.9",
|
||||
"dependencies": "",
|
||||
"credentials": "# See https://go-acme.github.io/lego/dns/#dns-providers for list of providers and their settings\n# Example provider configuration for DreamHost\n# dns_multi_provider = dreamhost\n# DREAMHOST_API_KEY = ABCDEFG1234",
|
||||
"full_plugin_name": "dns-multi"
|
||||
},
|
||||
"dnspod": {
|
||||
"name": "DNSPod",
|
||||
"package_name": "certbot-dns-dnspod",
|
||||
@ -194,7 +202,7 @@
|
||||
"godaddy": {
|
||||
"name": "GoDaddy",
|
||||
"package_name": "certbot-dns-godaddy",
|
||||
"version": "=={{certbot-version}}",
|
||||
"version": "==2.8.0",
|
||||
"dependencies": "",
|
||||
"credentials": "dns_godaddy_secret = 0123456789abcdef0123456789abcdef01234567\ndns_godaddy_key = abcdef0123456789abcdef01234567abcdef0123",
|
||||
"full_plugin_name": "dns-godaddy"
|
||||
@ -231,10 +239,18 @@
|
||||
"credentials": "dns_hetzner_api_token = 0123456789abcdef0123456789abcdef",
|
||||
"full_plugin_name": "dns-hetzner"
|
||||
},
|
||||
"hover": {
|
||||
"name": "Hover",
|
||||
"package_name": "certbot-dns-hover",
|
||||
"version": "~=1.2.1",
|
||||
"dependencies": "",
|
||||
"credentials": "dns_hover_hoverurl = https://www.hover.com\ndns_hover_username = hover-admin-username\ndns_hover_password = hover-admin-password\ndns_hover_totpsecret = 2fa-totp-secret",
|
||||
"full_plugin_name": "dns-hover"
|
||||
},
|
||||
"infomaniak": {
|
||||
"name": "Infomaniak",
|
||||
"package_name": "certbot-dns-infomaniak",
|
||||
"version": "~=0.1.12",
|
||||
"version": "~=0.2.2",
|
||||
"dependencies": "",
|
||||
"credentials": "dns_infomaniak_token = XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
|
||||
"full_plugin_name": "dns-infomaniak"
|
||||
@ -402,7 +418,7 @@
|
||||
"strato": {
|
||||
"name": "Strato",
|
||||
"package_name": "certbot-dns-strato",
|
||||
"version": "~=0.1.1",
|
||||
"version": "~=0.2.1",
|
||||
"dependencies": "",
|
||||
"credentials": "dns_strato_username = user\ndns_strato_password = pass\n# uncomment if youre using two factor authentication:\n# dns_strato_totp_devicename = 2fa_device\n# dns_strato_totp_secret = 2fa_secret\n#\n# uncomment if domain name contains special characters\n# insert domain display name as seen on your account page here\n# dns_strato_domain_display_name = my-punicode-url.de\n#\n# if youre not using strato.de or another special endpoint you can customise it below\n# you will probably only need to adjust the host, but you can also change the complete endpoint url\n# dns_strato_custom_api_scheme = https\n# dns_strato_custom_api_host = www.strato.de\n# dns_strato_custom_api_port = 443\n# dns_strato_custom_api_path = \"/apps/CustomerService\"",
|
||||
"full_plugin_name": "dns-strato"
|
||||
@ -418,7 +434,7 @@
|
||||
"transip": {
|
||||
"name": "TransIP",
|
||||
"package_name": "certbot-dns-transip",
|
||||
"version": "~=0.4.3",
|
||||
"version": "~=0.5.2",
|
||||
"dependencies": "",
|
||||
"credentials": "dns_transip_username = my_username\ndns_transip_key_file = /etc/letsencrypt/transip-rsa.key",
|
||||
"full_plugin_name": "dns-transip"
|
||||
@ -446,5 +462,13 @@
|
||||
"dependencies": "",
|
||||
"credentials": "dns_websupport_identifier = <api_key>\ndns_websupport_secret_key = <secret>",
|
||||
"full_plugin_name": "dns-websupport"
|
||||
},
|
||||
"wedos":{
|
||||
"name": "Wedos",
|
||||
"package_name": "certbot-dns-wedos",
|
||||
"version": "~=2.2",
|
||||
"dependencies": "",
|
||||
"credentials": "dns_wedos_user = <wedos_registration>\ndns_wedos_auth = <wapi_sha256_password>",
|
||||
"full_plugin_name": "dns-wedos"
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ if hash docker 2>/dev/null; then
|
||||
-e NODE_OPTIONS=--openssl-legacy-provider \
|
||||
-v "$(pwd)/frontend:/app/frontend" \
|
||||
-v "$(pwd)/global:/app/global" \
|
||||
-w /app/frontend "$DOCKER_IMAGE" \
|
||||
-w /app/frontend "${DOCKER_IMAGE}" \
|
||||
sh -c "yarn install && yarn build && yarn build && chown -R $(id -u):$(id -g) /app/frontend"
|
||||
|
||||
echo -e "${BLUE}❯ ${GREEN}Building Frontend Complete${RESET}"
|
||||
|
89
scripts/ci/fulltest-cypress
Executable file
@ -0,0 +1,89 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
STACK="${1:-sqlite}"
|
||||
|
||||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
# remember this is running in "ci" folder..
|
||||
|
||||
# Some defaults for running this script outside of CI
|
||||
export COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-npm_local_fulltest}"
|
||||
export IMAGE="${IMAGE:-nginx-proxy-manager}"
|
||||
export BRANCH_LOWER="${BRANCH_LOWER:-unknown}"
|
||||
export BUILD_NUMBER="${BUILD_NUMBER:-0000}"
|
||||
|
||||
if [ "${COMPOSE_FILE:-}" = "" ]; then
|
||||
export COMPOSE_FILE="docker/docker-compose.ci.yml:docker/docker-compose.ci.${STACK}.yml"
|
||||
fi
|
||||
|
||||
# Colors
|
||||
BLUE='\E[1;34m'
|
||||
RED='\E[1;31m'
|
||||
CYAN='\E[1;36m'
|
||||
GREEN='\E[1;32m'
|
||||
RESET='\E[0m'
|
||||
YELLOW='\E[1;33m'
|
||||
|
||||
export BLUE CYAN GREEN RESET YELLOW
|
||||
|
||||
echo -e "${BLUE}❯ ${CYAN}Starting fullstack cypress testing ...${RESET}"
|
||||
echo -e "${BLUE}❯ $(docker-compose config)${RESET}"
|
||||
|
||||
# $1: container_name
|
||||
get_container_ip () {
|
||||
local container_name=$1
|
||||
local container
|
||||
local ip
|
||||
container=$(docker-compose ps --all -q "${container_name}" | tail -n1)
|
||||
ip=$(docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' "$container")
|
||||
echo "$ip"
|
||||
}
|
||||
|
||||
# Bring up a stack, in steps so we can inject IPs everywhere
|
||||
docker-compose up -d pdns pdns-db
|
||||
PDNS_IP=$(get_container_ip "pdns")
|
||||
echo -e "${BLUE}❯ ${YELLOW}PDNS IP is ${PDNS_IP}${RESET}"
|
||||
|
||||
# adjust the dnsrouter config
|
||||
LOCAL_DNSROUTER_CONFIG="$DIR/../../docker/dev/dnsrouter-config.json"
|
||||
rm -rf "$LOCAL_DNSROUTER_CONFIG.tmp"
|
||||
# IMPORTANT: changes to dnsrouter-config.json will affect this line:
|
||||
jq --arg a "$PDNS_IP" '.servers[0].upstreams[1].upstream = $a' "$LOCAL_DNSROUTER_CONFIG" > "$LOCAL_DNSROUTER_CONFIG.tmp"
|
||||
|
||||
docker-compose up -d dnsrouter
|
||||
DNSROUTER_IP=$(get_container_ip "dnsrouter")
|
||||
echo -e "${BLUE}❯ ${YELLOW}DNS Router IP is ${DNSROUTER_IP}"
|
||||
|
||||
if [ "${DNSROUTER_IP:-}" = "" ]; then
|
||||
echo -e "${RED}❯ ERROR: DNS Router IP is not set${RESET}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# mount the resolver
|
||||
LOCAL_RESOLVE="$DIR/../../docker/dev/resolv.conf"
|
||||
rm -rf "${LOCAL_RESOLVE}"
|
||||
printf "nameserver %s\noptions ndots:0" "${DNSROUTER_IP}" > "${LOCAL_RESOLVE}"
|
||||
|
||||
# bring up all remaining containers, except cypress!
|
||||
docker-compose up -d --remove-orphans stepca
|
||||
docker-compose pull db-mysql || true # ok to fail
|
||||
docker-compose up -d --remove-orphans --pull=never fullstack
|
||||
|
||||
# wait for main container to be healthy
|
||||
bash "$DIR/../wait-healthy" "$(docker-compose ps --all -q fullstack)" 120
|
||||
|
||||
# Run tests
|
||||
rm -rf "$DIR/../../test/results"
|
||||
docker-compose up --build cypress
|
||||
|
||||
# Get results
|
||||
docker cp -L "$(docker-compose ps --all -q cypress):/test/results" "$DIR/../../test/"
|
||||
docker cp -L "$(docker-compose ps --all -q fullstack):/data/logs" "$DIR/../../test/results/"
|
||||
|
||||
if [ "$2" = "cleanup" ]; then
|
||||
echo -e "${BLUE}❯ ${CYAN}Cleaning up containers ...${RESET}"
|
||||
docker-compose down --remove-orphans --volumes -t 30
|
||||
fi
|
||||
|
||||
echo -e "${BLUE}❯ ${GREEN}Fullstack cypress testing complete${RESET}"
|
||||
|
@ -3,8 +3,8 @@
|
||||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
. "$DIR/../.common.sh"
|
||||
|
||||
DOCKER_IMAGE=nginxproxymanager/nginx-full:certbot-node
|
||||
docker pull "${DOCKER_IMAGE}"
|
||||
TESTING_IMAGE=nginxproxymanager/nginx-full:certbot-node
|
||||
docker pull "${TESTING_IMAGE}"
|
||||
|
||||
# Test
|
||||
echo -e "${BLUE}❯ ${CYAN}Testing backend ...${RESET}"
|
||||
@ -12,20 +12,20 @@ docker run --rm \
|
||||
-v "$(pwd)/backend:/app" \
|
||||
-v "$(pwd)/global:/app/global" \
|
||||
-w /app \
|
||||
"${DOCKER_IMAGE}" \
|
||||
"${TESTING_IMAGE}" \
|
||||
sh -c 'yarn install && yarn eslint . && rm -rf node_modules'
|
||||
echo -e "${BLUE}❯ ${GREEN}Testing Complete${RESET}"
|
||||
|
||||
# Build
|
||||
echo -e "${BLUE}❯ ${CYAN}Building ...${RESET}"
|
||||
docker build --pull --no-cache --compress \
|
||||
-t "${IMAGE}:ci-${BUILD_NUMBER}" \
|
||||
-t "${IMAGE:-nginx-proxy-manager}:${BRANCH_LOWER:-unknown}-ci-${BUILD_NUMBER:-0000}" \
|
||||
-f docker/Dockerfile \
|
||||
--progress=plain \
|
||||
--build-arg TARGETPLATFORM=linux/amd64 \
|
||||
--build-arg BUILDPLATFORM=linux/amd64 \
|
||||
--build-arg BUILD_VERSION="${BUILD_VERSION}" \
|
||||
--build-arg BUILD_COMMIT="${BUILD_COMMIT}" \
|
||||
--build-arg BUILD_VERSION="${BUILD_VERSION:-unknown}" \
|
||||
--build-arg BUILD_COMMIT="${BUILD_COMMIT:-unknown}" \
|
||||
--build-arg BUILD_DATE="$(date '+%Y-%m-%d %T %Z')" \
|
||||
.
|
||||
echo -e "${BLUE}❯ ${GREEN}Building Complete${RESET}"
|
||||
|
@ -23,9 +23,8 @@ until [ "${HEALTHY}" = "healthy" ]; do
|
||||
((LOOPCOUNT++))
|
||||
|
||||
if [ "$LOOPCOUNT" == "$LIMIT" ]; then
|
||||
echo ""
|
||||
echo ""
|
||||
echo -e "${BLUE}❯ ${RED}Timed out waiting for healthy${RESET}"
|
||||
docker logs --tail 50 "$SERVICE"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
@ -1 +0,0 @@
|
||||
node_modules
|
6
test/.gitignore
vendored
@ -1,4 +1,2 @@
|
||||
.vscode
|
||||
node_modules
|
||||
results
|
||||
cypress/videos
|
||||
results/*
|
||||
cypress/results/*
|
||||
|
@ -1,13 +1,12 @@
|
||||
FROM cypress/included:9.4.1
|
||||
FROM cypress/included:13.9.0
|
||||
|
||||
COPY --chown=1000 ./ /test
|
||||
COPY --chown=1000 ./test /test
|
||||
|
||||
# mkcert
|
||||
ENV MKCERT=1.4.2
|
||||
RUN wget -O /usr/bin/mkcert "https://github.com/FiloSottile/mkcert/releases/download/v${MKCERT}/mkcert-v${MKCERT}-linux-amd64" \
|
||||
&& chmod +x /usr/bin/mkcert
|
||||
# Disable Cypress CLI colors
|
||||
ENV FORCE_COLOR=0
|
||||
ENV NO_COLOR=1
|
||||
|
||||
WORKDIR /test
|
||||
RUN yarn install
|
||||
RUN yarn install && yarn cache clean
|
||||
ENTRYPOINT []
|
||||
CMD ["cypress", "run"]
|
||||
|
22
test/cypress/config/ci.js
Normal file
@ -0,0 +1,22 @@
|
||||
const { defineConfig } = require('cypress');
|
||||
|
||||
module.exports = defineConfig({
|
||||
requestTimeout: 30000,
|
||||
defaultCommandTimeout: 20000,
|
||||
reporter: 'cypress-multi-reporters',
|
||||
reporterOptions: {
|
||||
configFile: 'multi-reporter.json'
|
||||
},
|
||||
video: true,
|
||||
videosFolder: 'results/videos',
|
||||
screenshotsFolder: 'results/screenshots',
|
||||
e2e: {
|
||||
setupNodeEvents(on, config) {
|
||||
return require("../plugins/index.js")(on, config);
|
||||
},
|
||||
env: {
|
||||
swaggerBase: '{{baseUrl}}/api/schema',
|
||||
},
|
||||
baseUrl: 'http://localhost:1234',
|
||||
}
|
||||
});
|
@ -1,14 +0,0 @@
|
||||
{
|
||||
"requestTimeout": 30000,
|
||||
"defaultCommandTimeout": 20000,
|
||||
"reporter": "cypress-multi-reporters",
|
||||
"reporterOptions": {
|
||||
"configFile": "multi-reporter.json"
|
||||
},
|
||||
"videosFolder": "results/videos",
|
||||
"screenshotsFolder": "results/screenshots",
|
||||
"env": {
|
||||
"swaggerBase": "{{baseUrl}}/api/schema",
|
||||
"RETRIES": 4
|
||||
}
|
||||
}
|
22
test/cypress/config/dev.js
Normal file
@ -0,0 +1,22 @@
|
||||
const { defineConfig } = require('cypress');
|
||||
|
||||
module.exports = defineConfig({
|
||||
requestTimeout: 30000,
|
||||
defaultCommandTimeout: 20000,
|
||||
reporter: 'cypress-multi-reporters',
|
||||
reporterOptions: {
|
||||
configFile: 'multi-reporter.json'
|
||||
},
|
||||
video: false,
|
||||
videosFolder: 'results/videos',
|
||||
screenshotsFolder: 'results/screenshots',
|
||||
e2e: {
|
||||
setupNodeEvents(on, config) {
|
||||
return require("../plugins/index.js")(on, config);
|
||||
},
|
||||
env: {
|
||||
swaggerBase: '{{baseUrl}}/api/schema',
|
||||
},
|
||||
baseUrl: 'http://localhost:1234',
|
||||
}
|
||||
});
|
@ -1,14 +0,0 @@
|
||||
{
|
||||
"requestTimeout": 30000,
|
||||
"defaultCommandTimeout": 20000,
|
||||
"reporter": "cypress-multi-reporters",
|
||||
"reporterOptions": {
|
||||
"configFile": "multi-reporter.json"
|
||||
},
|
||||
"videos": false,
|
||||
"screenshotsFolder": "results/screenshots",
|
||||
"env": {
|
||||
"swaggerBase": "{{baseUrl}}/api/schema",
|
||||
"RETRIES": 0
|
||||
}
|
||||
}
|
@ -29,8 +29,6 @@ describe('Hosts endpoints', () => {
|
||||
block_exploits: false,
|
||||
caching_enabled: false,
|
||||
allow_websocket_upgrade: false,
|
||||
enable_proxy_protocol: false,
|
||||
load_balancer_ip: '',
|
||||
http2_support: false,
|
||||
hsts_enabled: false,
|
||||
hsts_subdomains: false,
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "Using fixtures to represent data",
|
||||
"email": "hello@cypress.io",
|
||||
"body": "Fixtures are a great way to mock data for responses to routes"
|
||||
}
|
@ -1,8 +1,12 @@
|
||||
const _ = require('lodash');
|
||||
const chalk = require('chalk');
|
||||
const _ = require("lodash");
|
||||
const chalk = require("chalk");
|
||||
|
||||
module.exports = function () {
|
||||
module.exports = function() {
|
||||
var arr = _.values(arguments);
|
||||
arr.unshift(chalk.blue.bold('[') + chalk.yellow.bold('Backend API') + chalk.blue.bold(']'));
|
||||
arr.unshift(
|
||||
chalk.blue.bold("[") +
|
||||
chalk.yellow.bold("Backend API") +
|
||||
chalk.blue.bold("]"),
|
||||
);
|
||||
console.log.apply(null, arr);
|
||||
};
|
||||
|