mirror of
				https://github.com/NginxProxyManager/nginx-proxy-manager.git
				synced 2025-11-04 09:25:15 +00:00 
			
		
		
		
	Merge branch 'NginxProxyManager:develop' into develop-crowdsec
This commit is contained in:
		
							
								
								
									
										108
									
								
								Jenkinsfile
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										108
									
								
								Jenkinsfile
									
									
									
									
										vendored
									
									
								
							@@ -17,13 +17,11 @@ pipeline {
 | 
			
		||||
		IMAGE                      = 'nginx-proxy-manager'
 | 
			
		||||
		BUILD_VERSION              = getVersion()
 | 
			
		||||
		MAJOR_VERSION              = '2'
 | 
			
		||||
		BRANCH_LOWER               = "${BRANCH_NAME.toLowerCase().replaceAll('/', '-')}"
 | 
			
		||||
		BRANCH_LOWER               = "${BRANCH_NAME.toLowerCase().replaceAll('\\\\', '-').replaceAll('/', '-').replaceAll('\\.', '-')}"
 | 
			
		||||
		COMPOSE_PROJECT_NAME       = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}"
 | 
			
		||||
		COMPOSE_FILE               = 'docker/docker-compose.ci.yml'
 | 
			
		||||
		COMPOSE_INTERACTIVE_NO_CLI = 1
 | 
			
		||||
		BUILDX_NAME                = "${COMPOSE_PROJECT_NAME}"
 | 
			
		||||
		DOCS_BUCKET                = 'jc21-npm-site'
 | 
			
		||||
		DOCS_CDN                   = 'EN1G6DEWZUTDT'
 | 
			
		||||
	}
 | 
			
		||||
	stages {
 | 
			
		||||
		stage('Environment') {
 | 
			
		||||
@@ -62,7 +60,9 @@ pipeline {
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		stage('Build and Test') {
 | 
			
		||||
		stage('Builds') {
 | 
			
		||||
			parallel {
 | 
			
		||||
				stage('Project') {
 | 
			
		||||
					steps {
 | 
			
		||||
						script {
 | 
			
		||||
							// Frontend and Backend
 | 
			
		||||
@@ -86,7 +86,34 @@ pipeline {
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
		stage('Integration Tests Sqlite') {
 | 
			
		||||
				stage('Docs') {
 | 
			
		||||
					steps {
 | 
			
		||||
						dir(path: 'docs') {
 | 
			
		||||
							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') {
 | 
			
		||||
					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'
 | 
			
		||||
@@ -97,68 +124,50 @@ pipeline {
 | 
			
		||||
						sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-sqlite) 120'
 | 
			
		||||
 | 
			
		||||
						// Run tests
 | 
			
		||||
				sh 'rm -rf test/results'
 | 
			
		||||
						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/'
 | 
			
		||||
						sh 'docker cp -L "$(docker-compose ps --all -q cypress-sqlite):/test/results" test/results-sqlite'
 | 
			
		||||
					}
 | 
			
		||||
					post {
 | 
			
		||||
						always {
 | 
			
		||||
							// Dumps to analyze later
 | 
			
		||||
					sh 'mkdir -p debug'
 | 
			
		||||
					sh 'docker-compose logs fullstack-sqlite > debug/docker_fullstack_sqlite.log'
 | 
			
		||||
					sh 'docker-compose logs db > debug/docker_db.log'
 | 
			
		||||
							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') {
 | 
			
		||||
							dir(path: 'test/results-sqlite') {
 | 
			
		||||
								archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
 | 
			
		||||
							}
 | 
			
		||||
					junit 'test/results/junit/*'
 | 
			
		||||
							junit 'test/results-sqlite/junit/*'
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
		stage('Integration Tests Mysql') {
 | 
			
		||||
				stage('Mysql') {
 | 
			
		||||
					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'
 | 
			
		||||
						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/'
 | 
			
		||||
						sh 'docker cp -L "$(docker-compose ps --all -q cypress-mysql):/test/results" test/results-mysql'
 | 
			
		||||
					}
 | 
			
		||||
					post {
 | 
			
		||||
						always {
 | 
			
		||||
							// Dumps to analyze later
 | 
			
		||||
					sh 'mkdir -p debug'
 | 
			
		||||
					sh 'docker-compose logs fullstack-mysql > debug/docker_fullstack_mysql.log'
 | 
			
		||||
					sh 'docker-compose logs db > debug/docker_db.log'
 | 
			
		||||
							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') {
 | 
			
		||||
							dir(path: 'test/results-mysql') {
 | 
			
		||||
								archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
 | 
			
		||||
							}
 | 
			
		||||
					junit 'test/results/junit/*'
 | 
			
		||||
							junit 'test/results-mysql/junit/*'
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
		stage('Docs') {
 | 
			
		||||
			when {
 | 
			
		||||
				not {
 | 
			
		||||
					equals expected: 'UNSTABLE', actual: currentBuild.result
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			steps {
 | 
			
		||||
				dir(path: 'docs') {
 | 
			
		||||
					sh 'yarn install'
 | 
			
		||||
					sh 'yarn build'
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				dir(path: 'docs/.vuepress/dist') {
 | 
			
		||||
					sh 'tar -czf ../../docs.tgz *'
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				archiveArtifacts(artifacts: 'docs/docs.tgz', allowEmptyArchive: false)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		stage('MultiArch Build') {
 | 
			
		||||
@@ -174,7 +183,9 @@ pipeline {
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		stage('Docs Deploy') {
 | 
			
		||||
		stage('Docs / Comment') {
 | 
			
		||||
			parallel {
 | 
			
		||||
				stage('Master Docs') {
 | 
			
		||||
					when {
 | 
			
		||||
						allOf {
 | 
			
		||||
							branch 'master'
 | 
			
		||||
@@ -184,7 +195,20 @@ pipeline {
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					steps {
 | 
			
		||||
				npmDocsRelease("$DOCS_BUCKET", "$DOCS_CDN")
 | 
			
		||||
						npmDocsReleaseMaster()
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				stage('Develop Docs') {
 | 
			
		||||
					when {
 | 
			
		||||
						allOf {
 | 
			
		||||
							branch 'develop'
 | 
			
		||||
							not {
 | 
			
		||||
								equals expected: 'UNSTABLE', actual: currentBuild.result
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					steps {
 | 
			
		||||
						npmDocsReleaseDevelop()
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				stage('PR Comment') {
 | 
			
		||||
@@ -203,6 +227,8 @@ pipeline {
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	post {
 | 
			
		||||
		always {
 | 
			
		||||
			sh 'docker-compose down --remove-orphans --volumes -t 30'
 | 
			
		||||
@@ -214,12 +240,12 @@ pipeline {
 | 
			
		||||
			sh 'figlet "SUCCESS"'
 | 
			
		||||
		}
 | 
			
		||||
		failure {
 | 
			
		||||
			archiveArtifacts(artifacts: 'debug/**.*', allowEmptyArchive: true)
 | 
			
		||||
			archiveArtifacts(artifacts: 'debug/**/*.*', allowEmptyArchive: true)
 | 
			
		||||
			juxtapose event: 'failure'
 | 
			
		||||
			sh 'figlet "FAILURE"'
 | 
			
		||||
		}
 | 
			
		||||
		unstable {
 | 
			
		||||
			archiveArtifacts(artifacts: 'debug/**.*', allowEmptyArchive: true)
 | 
			
		||||
			archiveArtifacts(artifacts: 'debug/**/*.*', allowEmptyArchive: true)
 | 
			
		||||
			juxtapose event: 'unstable'
 | 
			
		||||
			sh 'figlet "UNSTABLE"'
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								README.md
									
									
									
									
									
								
							@@ -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.10.4-green.svg?style=for-the-badge">
 | 
			
		||||
	<img src="https://img.shields.io/badge/version-2.11.0-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>
 | 
			
		||||
@@ -98,7 +98,18 @@ Password: changeme
 | 
			
		||||
Immediately after logging in with this default user you will be asked to modify your details and change your password.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Contributors
 | 
			
		||||
## 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).
 | 
			
		||||
 | 
			
		||||
@@ -107,5 +118,4 @@ Special thanks to [all of our contributors](https://github.com/NginxProxyManager
 | 
			
		||||
 | 
			
		||||
1. [Found a bug?](https://github.com/NginxProxyManager/nginx-proxy-manager/issues)
 | 
			
		||||
2. [Discussions](https://github.com/NginxProxyManager/nginx-proxy-manager/discussions)
 | 
			
		||||
3. [Development Gitter](https://gitter.im/nginx-proxy-manager/community)
 | 
			
		||||
4. [Reddit](https://reddit.com/r/nginxproxymanager)
 | 
			
		||||
3. [Reddit](https://reddit.com/r/nginxproxymanager)
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ const config           = require('../lib/config');
 | 
			
		||||
const error            = require('../lib/error');
 | 
			
		||||
const utils            = require('../lib/utils');
 | 
			
		||||
const certificateModel = require('../models/certificate');
 | 
			
		||||
const tokenModel       = require('../models/token');
 | 
			
		||||
const dnsPlugins       = require('../global/certbot-dns-plugins');
 | 
			
		||||
const internalAuditLog = require('./audit-log');
 | 
			
		||||
const internalNginx    = require('./nginx');
 | 
			
		||||
@@ -30,6 +31,7 @@ const internalCertificate = {
 | 
			
		||||
	intervalTimeout:         1000 * 60 * 60, // 1 hour
 | 
			
		||||
	interval:                null,
 | 
			
		||||
	intervalProcessing:      false,
 | 
			
		||||
	renewBeforeExpirationBy: [30, 'days'],
 | 
			
		||||
 | 
			
		||||
	initTimer: () => {
 | 
			
		||||
		logger.info('Let\'s Encrypt Renewal Timer initialized');
 | 
			
		||||
@@ -44,62 +46,51 @@ const internalCertificate = {
 | 
			
		||||
	processExpiringHosts: () => {
 | 
			
		||||
		if (!internalCertificate.intervalProcessing) {
 | 
			
		||||
			internalCertificate.intervalProcessing = true;
 | 
			
		||||
			logger.info('Renewing SSL certs close to expiry...');
 | 
			
		||||
			logger.info('Renewing SSL certs expiring within ' + internalCertificate.renewBeforeExpirationBy[0] + ' ' + internalCertificate.renewBeforeExpirationBy[1] + ' ...');
 | 
			
		||||
 | 
			
		||||
			const cmd = certbotCommand + ' renew --non-interactive --quiet ' +
 | 
			
		||||
				'--config "' + letsencryptConfig + '" ' +
 | 
			
		||||
				'--work-dir "/tmp/letsencrypt-lib" ' +
 | 
			
		||||
				'--logs-dir "/tmp/letsencrypt-log" ' +
 | 
			
		||||
				'--preferred-challenges "dns,http" ' +
 | 
			
		||||
				'--disable-hook-validation ' +
 | 
			
		||||
				(letsencryptStaging ? '--staging' : '');
 | 
			
		||||
			const expirationThreshold = moment().add(internalCertificate.renewBeforeExpirationBy[0], internalCertificate.renewBeforeExpirationBy[1]).format('YYYY-MM-DD HH:mm:ss');
 | 
			
		||||
 | 
			
		||||
			return utils.exec(cmd)
 | 
			
		||||
				.then((result) => {
 | 
			
		||||
					if (result) {
 | 
			
		||||
						logger.info('Renew Result: ' + result);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					return internalNginx.reload()
 | 
			
		||||
						.then(() => {
 | 
			
		||||
							logger.info('Renew Complete');
 | 
			
		||||
							return result;
 | 
			
		||||
						});
 | 
			
		||||
				})
 | 
			
		||||
				.then(() => {
 | 
			
		||||
					// Now go and fetch all the letsencrypt certs from the db and query the files and update expiry times
 | 
			
		||||
					return certificateModel
 | 
			
		||||
			// Fetch all the letsencrypt certs from the db that will expire within the configured threshold
 | 
			
		||||
			certificateModel
 | 
			
		||||
				.query()
 | 
			
		||||
				.where('is_deleted', 0)
 | 
			
		||||
				.andWhere('provider', 'letsencrypt')
 | 
			
		||||
				.andWhere('expires_on', '<', expirationThreshold)
 | 
			
		||||
				.then((certificates) => {
 | 
			
		||||
							if (certificates && certificates.length) {
 | 
			
		||||
								let promises = [];
 | 
			
		||||
					if (!certificates || !certificates.length) {
 | 
			
		||||
						return null;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
								certificates.map(function (certificate) {
 | 
			
		||||
									promises.push(
 | 
			
		||||
										internalCertificate.getCertificateInfoFromFile('/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem')
 | 
			
		||||
											.then((cert_info) => {
 | 
			
		||||
												return certificateModel
 | 
			
		||||
													.query()
 | 
			
		||||
													.where('id', certificate.id)
 | 
			
		||||
													.andWhere('provider', 'letsencrypt')
 | 
			
		||||
													.patch({
 | 
			
		||||
														expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss')
 | 
			
		||||
													});
 | 
			
		||||
											})
 | 
			
		||||
					/**
 | 
			
		||||
					 * Renews must be run sequentially or we'll get an error 'Another
 | 
			
		||||
					 * instance of Certbot is already running.'
 | 
			
		||||
					 */
 | 
			
		||||
					let sequence = Promise.resolve();
 | 
			
		||||
 | 
			
		||||
					certificates.forEach(function (certificate) {
 | 
			
		||||
						sequence = sequence.then(() =>
 | 
			
		||||
							internalCertificate
 | 
			
		||||
								.renew(
 | 
			
		||||
									{
 | 
			
		||||
										can: () =>
 | 
			
		||||
											Promise.resolve({
 | 
			
		||||
												permission_visibility: 'all',
 | 
			
		||||
											}),
 | 
			
		||||
										token: new tokenModel(),
 | 
			
		||||
									},
 | 
			
		||||
									{ id: certificate.id },
 | 
			
		||||
								)
 | 
			
		||||
								.catch((err) => {
 | 
			
		||||
									// Don't want to stop the train here, just log the error
 | 
			
		||||
									logger.error(err.message);
 | 
			
		||||
											})
 | 
			
		||||
								}),
 | 
			
		||||
						);
 | 
			
		||||
					});
 | 
			
		||||
 | 
			
		||||
								return Promise.all(promises);
 | 
			
		||||
							}
 | 
			
		||||
						});
 | 
			
		||||
					return sequence;
 | 
			
		||||
				})
 | 
			
		||||
				.then(() => {
 | 
			
		||||
					logger.info('Completed SSL cert renew process');
 | 
			
		||||
					internalCertificate.intervalProcessing = false;
 | 
			
		||||
				})
 | 
			
		||||
				.catch((err) => {
 | 
			
		||||
@@ -908,6 +899,10 @@ const internalCertificate = {
 | 
			
		||||
			mainCmd = 'AWS_CONFIG_FILE=\'' + credentialsLocation + '\' ' + mainCmd;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (certificate.meta.dns_provider === 'duckdns') {
 | 
			
		||||
			mainCmd = mainCmd + ' --dns-duckdns-no-txt-restore';
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		logger.info('Command:', `${credentialsCmd} && ${prepareCmd} && ${mainCmd}`);
 | 
			
		||||
 | 
			
		||||
		return utils.exec(credentialsCmd)
 | 
			
		||||
@@ -1012,7 +1007,7 @@ const internalCertificate = {
 | 
			
		||||
 | 
			
		||||
		logger.info(`Renewing Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
 | 
			
		||||
 | 
			
		||||
		let mainCmd = certbotCommand + ' renew ' +
 | 
			
		||||
		let mainCmd = certbotCommand + ' renew --force-renewal ' +
 | 
			
		||||
			'--config "' + letsencryptConfig + '" ' +
 | 
			
		||||
			'--work-dir "/tmp/letsencrypt-lib" ' +
 | 
			
		||||
			'--logs-dir "/tmp/letsencrypt-log" ' +
 | 
			
		||||
@@ -1046,6 +1041,8 @@ const internalCertificate = {
 | 
			
		||||
 | 
			
		||||
		const mainCmd = certbotCommand + ' revoke ' +
 | 
			
		||||
			'--config "' + letsencryptConfig + '" ' +
 | 
			
		||||
			'--work-dir "/tmp/letsencrypt-lib" ' +
 | 
			
		||||
			'--logs-dir "/tmp/letsencrypt-log" ' +
 | 
			
		||||
			'--cert-path "/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' +
 | 
			
		||||
			'--delete-after-revoke ' +
 | 
			
		||||
			(letsencryptStaging ? '--staging' : '');
 | 
			
		||||
@@ -1163,6 +1160,7 @@ const internalCertificate = {
 | 
			
		||||
			const options  = {
 | 
			
		||||
				method:  'POST',
 | 
			
		||||
				headers: {
 | 
			
		||||
					'User-Agent':     'Mozilla/5.0',
 | 
			
		||||
					'Content-Type':   'application/x-www-form-urlencoded',
 | 
			
		||||
					'Content-Length': Buffer.byteLength(formBody)
 | 
			
		||||
				}
 | 
			
		||||
@@ -1175,12 +1173,22 @@ const internalCertificate = {
 | 
			
		||||
 | 
			
		||||
					res.on('data', (chunk) => responseBody = responseBody + chunk);
 | 
			
		||||
					res.on('end', function () {
 | 
			
		||||
						try {
 | 
			
		||||
							const parsedBody = JSON.parse(responseBody + '');
 | 
			
		||||
							if (res.statusCode !== 200) {
 | 
			
		||||
							logger.warn(`Failed to test HTTP challenge for domain ${domain}`, res);
 | 
			
		||||
								logger.warn(`Failed to test HTTP challenge for domain ${domain} because HTTP status code ${res.statusCode} was returned: ${parsedBody.message}`);
 | 
			
		||||
								resolve(undefined);
 | 
			
		||||
							} else {
 | 
			
		||||
								resolve(parsedBody);
 | 
			
		||||
							}
 | 
			
		||||
						} catch (err) {
 | 
			
		||||
							if (res.statusCode !== 200) {
 | 
			
		||||
								logger.warn(`Failed to test HTTP challenge for domain ${domain} because HTTP status code ${res.statusCode} was returned`);
 | 
			
		||||
							} else {
 | 
			
		||||
								logger.warn(`Failed to test HTTP challenge for domain ${domain} because response failed to be parsed: ${err.message}`);
 | 
			
		||||
							}
 | 
			
		||||
							resolve(undefined);
 | 
			
		||||
						}
 | 
			
		||||
						resolve(parsedBody);
 | 
			
		||||
					});
 | 
			
		||||
				});
 | 
			
		||||
 | 
			
		||||
@@ -1194,6 +1202,9 @@ const internalCertificate = {
 | 
			
		||||
			if (!result) {
 | 
			
		||||
				// Some error occurred while trying to get the data
 | 
			
		||||
				return 'failed';
 | 
			
		||||
			} else if (result.error) {
 | 
			
		||||
				logger.info(`HTTP challenge test failed for domain ${domain} because error was returned: ${result.error.msg}`);
 | 
			
		||||
				return `other:${result.error.msg}`;
 | 
			
		||||
			} else if (`${result.responsecode}` === '200' && result.htmlresponse === 'Success') {
 | 
			
		||||
				// Server exists and has responded with the correct data
 | 
			
		||||
				return 'ok';
 | 
			
		||||
 
 | 
			
		||||
@@ -225,7 +225,7 @@ const internalProxyHost = {
 | 
			
		||||
					.query()
 | 
			
		||||
					.where('is_deleted', 0)
 | 
			
		||||
					.andWhere('id', data.id)
 | 
			
		||||
					.allowGraph('[owner,access_list,access_list.[clients,items],certificate]')
 | 
			
		||||
					.allowGraph('[owner,access_list.[clients,items],certificate]')
 | 
			
		||||
					.first();
 | 
			
		||||
 | 
			
		||||
				if (access_data.permission_visibility !== 'all') {
 | 
			
		||||
 
 | 
			
		||||
@@ -172,7 +172,7 @@
 | 
			
		||||
      "description": "Domain Names separated by a comma",
 | 
			
		||||
      "example": "*.jc21.com,blog.jc21.com",
 | 
			
		||||
      "type": "array",
 | 
			
		||||
      "maxItems": 15,
 | 
			
		||||
      "maxItems": 30,
 | 
			
		||||
      "uniqueItems": true,
 | 
			
		||||
      "items": {
 | 
			
		||||
        "type": "string",
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
{% if ssl_forced == 1 or ssl_forced == true %}
 | 
			
		||||
{% if hsts_enabled == 1 or hsts_enabled == true %}
 | 
			
		||||
  # HSTS (ngx_http_headers_module is required) (63072000 seconds = 2 years)
 | 
			
		||||
  add_header Strict-Transport-Security "max-age=63072000;{% if hsts_subdomains == 1 or hsts_subdomains == true -%} includeSubDomains;{% endif %} preload" always;
 | 
			
		||||
  add_header Strict-Transport-Security $hsts_header always;
 | 
			
		||||
{% endif %}
 | 
			
		||||
{% endif %}
 | 
			
		||||
{% endif %}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								backend/templates/_hsts_map.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								backend/templates/_hsts_map.conf
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
map $scheme $hsts_header {
 | 
			
		||||
    https   "max-age=63072000;{% if hsts_subdomains == 1 or hsts_subdomains == true -%} includeSubDomains;{% endif %} preload";
 | 
			
		||||
}
 | 
			
		||||
@@ -5,9 +5,9 @@
 | 
			
		||||
  #listen [::]:80;
 | 
			
		||||
{% endif %}
 | 
			
		||||
{% if certificate -%}
 | 
			
		||||
  listen 443 ssl{% if http2_support %} http2{% endif %};
 | 
			
		||||
  listen 443 ssl{% if http2_support == 1 or http2_support == true %} http2{% endif %};
 | 
			
		||||
{% if ipv6 -%}
 | 
			
		||||
  listen [::]:443 ssl{% if http2_support %} http2{% endif %};
 | 
			
		||||
  listen [::]:443 ssl{% if http2_support == 1 or http2_support == true %} http2{% endif %};
 | 
			
		||||
{% else -%}
 | 
			
		||||
  #listen [::]:443;
 | 
			
		||||
{% endif %}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
  {% include "_hsts_map.conf" %}
 | 
			
		||||
 | 
			
		||||
  location {{ path }} {
 | 
			
		||||
    proxy_set_header Host $host;
 | 
			
		||||
    proxy_set_header X-Forwarded-Scheme $scheme;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,9 @@
 | 
			
		||||
{% include "_header_comment.conf" %}
 | 
			
		||||
 | 
			
		||||
{% if enabled %}
 | 
			
		||||
 | 
			
		||||
{% include "_hsts_map.conf" %}
 | 
			
		||||
 | 
			
		||||
server {
 | 
			
		||||
{% include "_listen.conf" %}
 | 
			
		||||
{% include "_certificates.conf" %}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,9 @@
 | 
			
		||||
{% include "_header_comment.conf" %}
 | 
			
		||||
 | 
			
		||||
{% if enabled %}
 | 
			
		||||
 | 
			
		||||
{% include "_hsts_map.conf" %}
 | 
			
		||||
 | 
			
		||||
server {
 | 
			
		||||
  set $forward_scheme {{ forward_scheme }};
 | 
			
		||||
  set $server         "{{ forward_host }}";
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,9 @@
 | 
			
		||||
{% include "_header_comment.conf" %}
 | 
			
		||||
 | 
			
		||||
{% if enabled %}
 | 
			
		||||
 | 
			
		||||
{% include "_hsts_map.conf" %}
 | 
			
		||||
 | 
			
		||||
server {
 | 
			
		||||
{% include "_listen.conf" %}
 | 
			
		||||
{% include "_certificates.conf" %}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
 | 
			
		||||
# This file assumes that the frontend has been built using ./scripts/frontend-build
 | 
			
		||||
 | 
			
		||||
FROM jc21/nginx-full:certbot-node
 | 
			
		||||
FROM nginxproxymanager/nginx-full:certbot-node
 | 
			
		||||
 | 
			
		||||
ARG TARGETPLATFORM
 | 
			
		||||
ARG BUILD_VERSION
 | 
			
		||||
@@ -20,7 +20,8 @@ ENV SUPPRESS_NO_CONFIG_WARNING=1 \
 | 
			
		||||
	NODE_ENV=production \
 | 
			
		||||
	NPM_BUILD_VERSION="${BUILD_VERSION}" \
 | 
			
		||||
	NPM_BUILD_COMMIT="${BUILD_COMMIT}" \
 | 
			
		||||
	NPM_BUILD_DATE="${BUILD_DATE}"
 | 
			
		||||
	NPM_BUILD_DATE="${BUILD_DATE}" \
 | 
			
		||||
	NODE_OPTIONS="--openssl-legacy-provider"
 | 
			
		||||
 | 
			
		||||
RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
 | 
			
		||||
	&& apt-get update \
 | 
			
		||||
@@ -47,11 +48,9 @@ COPY docker/rootfs /
 | 
			
		||||
 | 
			
		||||
# Remove frontend service not required for prod, dev nginx config as well
 | 
			
		||||
RUN rm -rf /etc/s6-overlay/s6-rc.d/user/contents.d/frontend /etc/nginx/conf.d/dev.conf \
 | 
			
		||||
	&& chmod 644 /etc/logrotate.d/nginx-proxy-manager \
 | 
			
		||||
	&& pip uninstall --yes setuptools \
 | 
			
		||||
	&& pip install --no-cache-dir "setuptools==58.0.0"
 | 
			
		||||
	&& chmod 644 /etc/logrotate.d/nginx-proxy-manager
 | 
			
		||||
 | 
			
		||||
VOLUME [ "/data", "/etc/letsencrypt" ]
 | 
			
		||||
VOLUME [ "/data" ]
 | 
			
		||||
ENTRYPOINT [ "/init" ]
 | 
			
		||||
 | 
			
		||||
LABEL org.label-schema.schema-version="1.0" \
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
FROM jc21/nginx-full:certbot-node
 | 
			
		||||
FROM nginxproxymanager/nginx-full:certbot-node
 | 
			
		||||
LABEL maintainer="Jamie Curnow <jc@jc21.com>"
 | 
			
		||||
 | 
			
		||||
# See: https://github.com/just-containers/s6-overlay/blob/master/README.md
 | 
			
		||||
@@ -7,7 +7,8 @@ ENV SUPPRESS_NO_CONFIG_WARNING=1 \
 | 
			
		||||
	S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
 | 
			
		||||
	S6_FIX_ATTRS_HIDDEN=1 \
 | 
			
		||||
	S6_KILL_FINISH_MAXTIME=10000 \
 | 
			
		||||
	S6_VERBOSITY=2
 | 
			
		||||
	S6_VERBOSITY=2 \
 | 
			
		||||
	NODE_OPTIONS="--openssl-legacy-provider"
 | 
			
		||||
 | 
			
		||||
RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
 | 
			
		||||
	&& apt-get update \
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,8 @@ services:
 | 
			
		||||
      DB_MYSQL_PASSWORD: 'npm'
 | 
			
		||||
      DB_MYSQL_NAME: 'npm'
 | 
			
		||||
    volumes:
 | 
			
		||||
      - npm_data:/data
 | 
			
		||||
      - npm_data_mysql:/data
 | 
			
		||||
      - npm_le_mysql:/etc/letsencrypt
 | 
			
		||||
    expose:
 | 
			
		||||
      - 81
 | 
			
		||||
      - 80
 | 
			
		||||
@@ -22,7 +23,7 @@ services:
 | 
			
		||||
    depends_on:
 | 
			
		||||
      - db
 | 
			
		||||
    healthcheck:
 | 
			
		||||
      test: ["CMD", "/bin/check-health"]
 | 
			
		||||
      test: ["CMD", "/usr/bin/check-health"]
 | 
			
		||||
      interval: 10s
 | 
			
		||||
      timeout: 3s
 | 
			
		||||
 | 
			
		||||
@@ -37,13 +38,14 @@ services:
 | 
			
		||||
      PGID: 1000
 | 
			
		||||
      DISABLE_IPV6: 'true'
 | 
			
		||||
    volumes:
 | 
			
		||||
      - npm_data:/data
 | 
			
		||||
      - npm_data_sqlite:/data
 | 
			
		||||
      - npm_le_sqlite:/etc/letsencrypt
 | 
			
		||||
    expose:
 | 
			
		||||
      - 81
 | 
			
		||||
      - 80
 | 
			
		||||
      - 443
 | 
			
		||||
    healthcheck:
 | 
			
		||||
      test: ["CMD", "/bin/check-health"]
 | 
			
		||||
      test: ["CMD", "/usr/bin/check-health"]
 | 
			
		||||
      interval: 10s
 | 
			
		||||
      timeout: 3s
 | 
			
		||||
 | 
			
		||||
@@ -55,7 +57,7 @@ services:
 | 
			
		||||
      MYSQL_USER: 'npm'
 | 
			
		||||
      MYSQL_PASSWORD: 'npm'
 | 
			
		||||
    volumes:
 | 
			
		||||
      - db_data:/var/lib/mysql
 | 
			
		||||
      - mysql_data:/var/lib/mysql
 | 
			
		||||
 | 
			
		||||
  cypress-mysql:
 | 
			
		||||
    image: "${IMAGE}-cypress:ci-${BUILD_NUMBER}"
 | 
			
		||||
@@ -65,7 +67,7 @@ services:
 | 
			
		||||
    environment:
 | 
			
		||||
      CYPRESS_baseUrl: 'http://fullstack-mysql:81'
 | 
			
		||||
    volumes:
 | 
			
		||||
      - cypress-logs:/results
 | 
			
		||||
      - cypress_logs_mysql:/results
 | 
			
		||||
    command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json}
 | 
			
		||||
 | 
			
		||||
  cypress-sqlite:
 | 
			
		||||
@@ -76,10 +78,14 @@ services:
 | 
			
		||||
    environment:
 | 
			
		||||
      CYPRESS_baseUrl: "http://fullstack-sqlite:81"
 | 
			
		||||
    volumes:
 | 
			
		||||
      - cypress-logs:/results
 | 
			
		||||
      - cypress_logs_sqlite:/results
 | 
			
		||||
    command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json}
 | 
			
		||||
 | 
			
		||||
volumes:
 | 
			
		||||
  cypress-logs:
 | 
			
		||||
  npm_data:
 | 
			
		||||
  db_data:
 | 
			
		||||
  cypress_logs_mysql:
 | 
			
		||||
  cypress_logs_sqlite:
 | 
			
		||||
  npm_data_mysql:
 | 
			
		||||
  npm_data_sqlite:
 | 
			
		||||
  npm_le_sqlite:
 | 
			
		||||
  npm_le_mysql:
 | 
			
		||||
  mysql_data:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
/data/logs/*_access.log /data/logs/*/access.log {
 | 
			
		||||
    create 0644 root root
 | 
			
		||||
    su npm npm
 | 
			
		||||
    create 0644
 | 
			
		||||
    weekly
 | 
			
		||||
    rotate 4
 | 
			
		||||
    missingok
 | 
			
		||||
@@ -12,7 +13,8 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/data/logs/*_error.log /data/logs/*/error.log {
 | 
			
		||||
    create 0644 root root
 | 
			
		||||
    su npm npm
 | 
			
		||||
    create 0644
 | 
			
		||||
    weekly
 | 
			
		||||
    rotate 10
 | 
			
		||||
    missingok
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,10 @@
 | 
			
		||||
set $test "";
 | 
			
		||||
if ($scheme = "http") {
 | 
			
		||||
	set $test "H";
 | 
			
		||||
}
 | 
			
		||||
if ($request_uri = /.well-known/acme-challenge/test-challenge) {
 | 
			
		||||
	set $test "${test}T";
 | 
			
		||||
}
 | 
			
		||||
if ($test = H) {
 | 
			
		||||
	return 301 https://$host$request_uri;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
. /bin/common.sh
 | 
			
		||||
. /usr/bin/common.sh
 | 
			
		||||
 | 
			
		||||
cd /app || exit 1
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,7 +6,7 @@ set -e
 | 
			
		||||
# This service is DEVELOPMENT only.
 | 
			
		||||
 | 
			
		||||
if [ "$DEVELOPMENT" = 'true' ]; then
 | 
			
		||||
	. /bin/common.sh
 | 
			
		||||
	. /usr/bin/common.sh
 | 
			
		||||
	cd /app/frontend || exit 1
 | 
			
		||||
	HOME=$NPMHOME
 | 
			
		||||
	export HOME
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
. /bin/common.sh
 | 
			
		||||
. /usr/bin/common.sh
 | 
			
		||||
 | 
			
		||||
log_info 'Starting nginx ...'
 | 
			
		||||
exec s6-setuidgid "$PUID:$PGID" nginx
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
 | 
			
		||||
set -e
 | 
			
		||||
 | 
			
		||||
. /bin/common.sh
 | 
			
		||||
. /usr/bin/common.sh
 | 
			
		||||
 | 
			
		||||
if [ "$(id -u)" != "0" ]; then
 | 
			
		||||
	log_fatal "This docker container must be run as root, do not specify a user.\nYou can specify PUID and PGID env vars to run processes as that user and group after initialization."
 | 
			
		||||
 
 | 
			
		||||
@@ -24,4 +24,4 @@ chown -R "$PUID:$PGID" /etc/nginx/nginx.conf
 | 
			
		||||
chown -R "$PUID:$PGID" /etc/nginx/conf.d
 | 
			
		||||
 | 
			
		||||
# Prevents errors when installing python certbot plugins when non-root
 | 
			
		||||
chown -R "$PUID:$PGID" /opt/certbot
 | 
			
		||||
chown -R "$PUID:$PGID" /opt/certbot/lib/python*/site-packages
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,10 @@ export CYAN BLUE YELLOW RED RESET
 | 
			
		||||
PUID=${PUID:-0}
 | 
			
		||||
PGID=${PGID:-0}
 | 
			
		||||
 | 
			
		||||
# If changing the username and group name below,
 | 
			
		||||
# ensure all references to this user is also changed.
 | 
			
		||||
# See docker/rootfs/etc/logrotate.d/nginx-proxy-manager
 | 
			
		||||
# and docker/rootfs/etc/nginx/nginx.conf
 | 
			
		||||
NPMUSER=npm
 | 
			
		||||
NPMGROUP=npm
 | 
			
		||||
NPMHOME=/tmp/npmuserhome
 | 
			
		||||
							
								
								
									
										10
									
								
								docs/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								docs/.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,13 @@
 | 
			
		||||
.vuepress/dist
 | 
			
		||||
node_modules
 | 
			
		||||
ts
 | 
			
		||||
.temp
 | 
			
		||||
.cache
 | 
			
		||||
 | 
			
		||||
.yarn/*
 | 
			
		||||
!.yarn/releases
 | 
			
		||||
!.yarn/plugins
 | 
			
		||||
!.yarn/sdks
 | 
			
		||||
!.yarn/versions
 | 
			
		||||
*.gz
 | 
			
		||||
*.tgz
 | 
			
		||||
@@ -1,10 +1,17 @@
 | 
			
		||||
module.exports = {
 | 
			
		||||
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"
 | 
			
		||||
		}
 | 
			
		||||
      description: "Expose your services easily and securely",
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  head: [
 | 
			
		||||
    ["link", { rel: "icon", href: "/icon.png" }],
 | 
			
		||||
@@ -20,63 +27,94 @@ module.exports = {
 | 
			
		||||
    ["meta", { name: "twitter:image", content: "https://nginxproxymanager.com/icon.png"}],
 | 
			
		||||
    ["meta", { name: "twitter:alt", content: "Nginx Proxy Manager"}],
 | 
			
		||||
  ],
 | 
			
		||||
	themeConfig: {
 | 
			
		||||
		logo: "/icon.png",
 | 
			
		||||
		// the GitHub repo path
 | 
			
		||||
  theme: defaultTheme({
 | 
			
		||||
    logo: '/icon.png',
 | 
			
		||||
    repo: "jc21/nginx-proxy-manager",
 | 
			
		||||
		// the label linking to the repo
 | 
			
		||||
		repoLabel: "GitHub",
 | 
			
		||||
		// if your docs are not at the root of the repo:
 | 
			
		||||
		docsDir: "docs",
 | 
			
		||||
		// defaults to false, set to true to enable
 | 
			
		||||
		editLinks: true,
 | 
			
		||||
    docsRepo: 'https://github.com/jc21/nginx-proxy-manager',
 | 
			
		||||
    docsBranch: 'develop',
 | 
			
		||||
    docsDir: 'docs',
 | 
			
		||||
    editLinkPattern: ':repo/edit/:branch/:path',
 | 
			
		||||
    locales: {
 | 
			
		||||
			"/": {
 | 
			
		||||
				// text for the language dropdown
 | 
			
		||||
				selectText: "Languages",
 | 
			
		||||
				// label for this locale in the language dropdown
 | 
			
		||||
				label: "English",
 | 
			
		||||
				// Custom text for edit link. Defaults to "Edit this page"
 | 
			
		||||
				editLinkText: "Edit this page on GitHub",
 | 
			
		||||
				// Custom navbar values
 | 
			
		||||
				nav: [{ text: "Setup", link: "/setup/" }],
 | 
			
		||||
				// Custom sidebar values
 | 
			
		||||
				sidebar: [
 | 
			
		||||
					"/",
 | 
			
		||||
					["/guide/", "Guide"],
 | 
			
		||||
					["/screenshots/", "Screenshots"],
 | 
			
		||||
					["/setup/", "Setup Instructions"],
 | 
			
		||||
					["/advanced-config/", "Advanced Configuration"],
 | 
			
		||||
					["/upgrading/", "Upgrading"],
 | 
			
		||||
					["/faq/", "Frequently Asked Questions"],
 | 
			
		||||
					["/third-party/", "Third Party"]
 | 
			
		||||
				]
 | 
			
		||||
      '/': {
 | 
			
		||||
        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: [
 | 
			
		||||
		[
 | 
			
		||||
			"@vuepress/google-analytics",
 | 
			
		||||
			{
 | 
			
		||||
				ga: "UA-99675467-4"
 | 
			
		||||
			}
 | 
			
		||||
		],
 | 
			
		||||
		[
 | 
			
		||||
			"sitemap",
 | 
			
		||||
			{
 | 
			
		||||
				hostname: "https://nginxproxymanager.com"
 | 
			
		||||
			}
 | 
			
		||||
		],
 | 
			
		||||
		[
 | 
			
		||||
			'vuepress-plugin-zooming',
 | 
			
		||||
			{
 | 
			
		||||
    googleAnalyticsPlugin({
 | 
			
		||||
      id: 'UA-99675467-4'
 | 
			
		||||
    }),
 | 
			
		||||
    sitemapPlugin({
 | 
			
		||||
      hostname: "https://nginxproxymanager.com",
 | 
			
		||||
    }),
 | 
			
		||||
    zoomingPlugin({
 | 
			
		||||
      selector: '.zooming',
 | 
			
		||||
      delay: 1000,
 | 
			
		||||
      options: {
 | 
			
		||||
        bgColor: 'black',
 | 
			
		||||
        zIndex: 10000,
 | 
			
		||||
      },
 | 
			
		||||
    }),
 | 
			
		||||
    searchPlugin({
 | 
			
		||||
      locales: {
 | 
			
		||||
        '/': {
 | 
			
		||||
          placeholder: 'Search',
 | 
			
		||||
        },
 | 
			
		||||
      },
 | 
			
		||||
    }),
 | 
			
		||||
  ],
 | 
			
		||||
	]
 | 
			
		||||
};
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										258
									
								
								docs/.vuepress/styles/index.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								docs/.vuepress/styles/index.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,258 @@
 | 
			
		||||
: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;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,23 +0,0 @@
 | 
			
		||||
.home .hero img
 | 
			
		||||
  max-width: 500px !important
 | 
			
		||||
  min-width: 300px
 | 
			
		||||
  width: 100%
 | 
			
		||||
 | 
			
		||||
.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;
 | 
			
		||||
@@ -1,4 +0,0 @@
 | 
			
		||||
$accentColor = #f15833
 | 
			
		||||
$textColor = #663015
 | 
			
		||||
$borderColor = #eaecef
 | 
			
		||||
$codeBgColor = #282c34
 | 
			
		||||
							
								
								
									
										893
									
								
								docs/.yarn/releases/yarn-4.0.2.cjs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										893
									
								
								docs/.yarn/releases/yarn-4.0.2.cjs
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										3
									
								
								docs/.yarnrc.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								docs/.yarnrc.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
nodeLinker: node-modules
 | 
			
		||||
 | 
			
		||||
yarnPath: .yarn/releases/yarn-4.0.2.cjs
 | 
			
		||||
@@ -1,8 +1,10 @@
 | 
			
		||||
---
 | 
			
		||||
home: true
 | 
			
		||||
heroImage: /logo.png
 | 
			
		||||
actionText: Get Started →
 | 
			
		||||
actionLink: /guide/
 | 
			
		||||
actions:
 | 
			
		||||
  - text: Get Started
 | 
			
		||||
    link: /guide/
 | 
			
		||||
    type: primary
 | 
			
		||||
footer: MIT Licensed | Copyright © 2016-present jc21.com
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -76,7 +76,7 @@ feature by adding the following to the service in your `docker-compose.yml` file
 | 
			
		||||
 | 
			
		||||
```yml
 | 
			
		||||
healthcheck:
 | 
			
		||||
  test: ["CMD", "/bin/check-health"]
 | 
			
		||||
  test: ["CMD", "/usr/bin/check-health"]
 | 
			
		||||
  interval: 10s
 | 
			
		||||
  timeout: 3s
 | 
			
		||||
```
 | 
			
		||||
@@ -138,6 +138,7 @@ services:
 | 
			
		||||
      MYSQL_USER: "npm"
 | 
			
		||||
      # MYSQL_PASSWORD: "npm"  # use secret instead
 | 
			
		||||
      MYSQL_PASSWORD__FILE: /run/secrets/MYSQL_PWD
 | 
			
		||||
      MARIADB_AUTO_UPGRADE: '1'
 | 
			
		||||
    volumes:
 | 
			
		||||
      - ./mysql:/var/lib/mysql
 | 
			
		||||
    secrets:
 | 
			
		||||
@@ -193,3 +194,17 @@ value by specifying it as a Docker environment variable. The default if not spec
 | 
			
		||||
    X_FRAME_OPTIONS: "sameorigin"
 | 
			
		||||
  ...
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Customising logrotate settings
 | 
			
		||||
 | 
			
		||||
By default, NPM rotates the access- and error logs weekly and keeps 4 and 10 log files respectively.
 | 
			
		||||
Depending on the usage, this can lead to large log files, especially access logs.
 | 
			
		||||
You can customise the logrotate configuration through a mount (if your custom config is `logrotate.custom`):
 | 
			
		||||
 | 
			
		||||
```yml
 | 
			
		||||
  volumes:
 | 
			
		||||
    ...
 | 
			
		||||
    - ./logrotate.custom:/etc/logrotate.d/nginx-proxy-manager
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
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).
 | 
			
		||||
 
 | 
			
		||||
@@ -3,775 +3,21 @@
 | 
			
		||||
  "version": "1.0.0",
 | 
			
		||||
  "description": "",
 | 
			
		||||
  "main": "index.js",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "@vuepress/plugin-google-analytics": "^1.5.3",
 | 
			
		||||
    "abbrev": "^1.1.1",
 | 
			
		||||
    "accepts": "^1.3.7",
 | 
			
		||||
    "acorn": "^7.4.0",
 | 
			
		||||
    "agentkeepalive": "^4.1.3",
 | 
			
		||||
    "ajv": "^6.12.3",
 | 
			
		||||
    "ajv-errors": "^1.0.1",
 | 
			
		||||
    "ajv-keywords": "^3.5.2",
 | 
			
		||||
    "algoliasearch": "^4.3.1",
 | 
			
		||||
    "alphanum-sort": "^1.0.2",
 | 
			
		||||
    "ansi-colors": "^4.1.1",
 | 
			
		||||
    "ansi-escapes": "^4.3.1",
 | 
			
		||||
    "ansi-html": "^0.0.8",
 | 
			
		||||
    "ansi-regex": "^5.0.0",
 | 
			
		||||
    "ansi-styles": "^4.2.1",
 | 
			
		||||
    "anymatch": "^3.1.1",
 | 
			
		||||
    "aproba": "^2.0.0",
 | 
			
		||||
    "argparse": "^1.0.10",
 | 
			
		||||
    "arr-diff": "^4.0.0",
 | 
			
		||||
    "arr-flatten": "^1.1.0",
 | 
			
		||||
    "arr-union": "^3.1.0",
 | 
			
		||||
    "array-flatten": "^3.0.0",
 | 
			
		||||
    "array-union": "^2.1.0",
 | 
			
		||||
    "array-uniq": "^2.1.0",
 | 
			
		||||
    "array-unique": "^0.3.2",
 | 
			
		||||
    "asn1": "^0.2.4",
 | 
			
		||||
    "asn1.js": "^5.4.1",
 | 
			
		||||
    "assert": "^2.0.0",
 | 
			
		||||
    "assert-plus": "^1.0.0",
 | 
			
		||||
    "assign-symbols": "^2.0.2",
 | 
			
		||||
    "async": "^3.2.0",
 | 
			
		||||
    "async-each": "^1.0.3",
 | 
			
		||||
    "async-limiter": "^2.0.0",
 | 
			
		||||
    "asynckit": "^0.4.0",
 | 
			
		||||
    "atob": "^2.1.2",
 | 
			
		||||
    "autocomplete.js": "^0.37.1",
 | 
			
		||||
    "autoprefixer": "^9.8.6",
 | 
			
		||||
    "aws-sign2": "^0.7.0",
 | 
			
		||||
    "aws4": "^1.10.0",
 | 
			
		||||
    "babel-loader": "^8.1.0",
 | 
			
		||||
    "babel-plugin-dynamic-import-node": "^2.3.3",
 | 
			
		||||
    "babel-plugin-module-resolver": "^4.0.0",
 | 
			
		||||
    "balanced-match": "^1.0.0",
 | 
			
		||||
    "base": "^3.0.0",
 | 
			
		||||
    "base64-js": "^1.3.1",
 | 
			
		||||
    "batch": "^0.6.1",
 | 
			
		||||
    "bcrypt-pbkdf": "^1.0.2",
 | 
			
		||||
    "big.js": "^5.2.2",
 | 
			
		||||
    "binary-extensions": "^2.1.0",
 | 
			
		||||
    "bluebird": "^3.7.2",
 | 
			
		||||
    "bn.js": "^5.1.2",
 | 
			
		||||
    "body-parser": "^1.19.0",
 | 
			
		||||
    "bonjour": "^3.5.0",
 | 
			
		||||
    "boolbase": "^1.0.0",
 | 
			
		||||
    "brace-expansion": "^1.1.11",
 | 
			
		||||
    "braces": "^3.0.2",
 | 
			
		||||
    "brorand": "^1.1.0",
 | 
			
		||||
    "browserify-aes": "^1.2.0",
 | 
			
		||||
    "browserify-cipher": "^1.0.1",
 | 
			
		||||
    "browserify-des": "^1.0.2",
 | 
			
		||||
    "browserify-rsa": "^4.0.1",
 | 
			
		||||
    "browserify-sign": "^4.2.1",
 | 
			
		||||
    "browserify-zlib": "^0.2.0",
 | 
			
		||||
    "browserslist": "^4.13.0",
 | 
			
		||||
    "buffer": "^5.6.0",
 | 
			
		||||
    "buffer-from": "^1.1.1",
 | 
			
		||||
    "buffer-indexof": "^1.1.1",
 | 
			
		||||
    "buffer-json": "^2.0.0",
 | 
			
		||||
    "buffer-xor": "^2.0.2",
 | 
			
		||||
    "builtin-status-codes": "^3.0.0",
 | 
			
		||||
    "bytes": "^3.1.0",
 | 
			
		||||
    "cac": "^6.6.1",
 | 
			
		||||
    "cacache": "^15.0.5",
 | 
			
		||||
    "cache-base": "^4.0.0",
 | 
			
		||||
    "cache-loader": "^4.1.0",
 | 
			
		||||
    "call-me-maybe": "^1.0.1",
 | 
			
		||||
    "caller-callsite": "^4.1.0",
 | 
			
		||||
    "caller-path": "^3.0.0",
 | 
			
		||||
    "callsites": "^3.1.0",
 | 
			
		||||
    "camel-case": "^4.1.1",
 | 
			
		||||
    "camelcase": "^6.0.0",
 | 
			
		||||
    "caniuse-api": "^3.0.0",
 | 
			
		||||
    "caniuse-lite": "^1.0.30001111",
 | 
			
		||||
    "caseless": "^0.12.0",
 | 
			
		||||
    "chalk": "^4.1.0",
 | 
			
		||||
    "chokidar": "^3.4.1",
 | 
			
		||||
    "chownr": "^2.0.0",
 | 
			
		||||
    "chrome-trace-event": "^1.0.2",
 | 
			
		||||
    "ci-info": "^2.0.0",
 | 
			
		||||
    "cipher-base": "^1.0.4",
 | 
			
		||||
    "class-utils": "^0.3.6",
 | 
			
		||||
    "clean-css": "^4.2.3",
 | 
			
		||||
    "clipboard": "^2.0.6",
 | 
			
		||||
    "cliui": "^6.0.0",
 | 
			
		||||
    "coa": "^2.0.2",
 | 
			
		||||
    "code-point-at": "^1.1.0",
 | 
			
		||||
    "collection-visit": "^1.0.0",
 | 
			
		||||
    "color": "^3.1.2",
 | 
			
		||||
    "color-convert": "^2.0.1",
 | 
			
		||||
    "color-name": "^1.1.4",
 | 
			
		||||
    "color-string": "^1.5.3",
 | 
			
		||||
    "combined-stream": "^1.0.8",
 | 
			
		||||
    "commander": "^6.0.0",
 | 
			
		||||
    "commondir": "^1.0.1",
 | 
			
		||||
    "component-emitter": "^1.3.0",
 | 
			
		||||
    "compressible": "^2.0.18",
 | 
			
		||||
    "compression": "^1.7.4",
 | 
			
		||||
    "concat-map": "^0.0.1",
 | 
			
		||||
    "concat-stream": "^2.0.0",
 | 
			
		||||
    "connect-history-api-fallback": "^1.6.0",
 | 
			
		||||
    "consola": "^2.15.0",
 | 
			
		||||
    "console-browserify": "^1.2.0",
 | 
			
		||||
    "consolidate": "^0.15.1",
 | 
			
		||||
    "constants-browserify": "^1.0.0",
 | 
			
		||||
    "content-disposition": "^0.5.3",
 | 
			
		||||
    "content-type": "^1.0.4",
 | 
			
		||||
    "convert-source-map": "^1.7.0",
 | 
			
		||||
    "cookie": "^0.4.1",
 | 
			
		||||
    "cookie-signature": "^1.1.0",
 | 
			
		||||
    "copy-concurrently": "^1.0.5",
 | 
			
		||||
    "copy-descriptor": "^0.1.1",
 | 
			
		||||
    "copy-webpack-plugin": "^6.0.3",
 | 
			
		||||
    "core-js": "^3.6.5",
 | 
			
		||||
    "core-util-is": "^1.0.2",
 | 
			
		||||
    "cosmiconfig": "^7.0.0",
 | 
			
		||||
    "create-ecdh": "^4.0.4",
 | 
			
		||||
    "create-hash": "^1.2.0",
 | 
			
		||||
    "create-hmac": "^1.1.7",
 | 
			
		||||
    "cross-spawn": "^7.0.3",
 | 
			
		||||
    "crypto-browserify": "^3.12.0",
 | 
			
		||||
    "css": "^3.0.0",
 | 
			
		||||
    "css-color-names": "^1.0.1",
 | 
			
		||||
    "css-declaration-sorter": "^5.1.2",
 | 
			
		||||
    "css-loader": "^4.2.0",
 | 
			
		||||
    "css-parse": "^2.0.0",
 | 
			
		||||
    "css-select": "^2.1.0",
 | 
			
		||||
    "css-select-base-adapter": "^0.1.1",
 | 
			
		||||
    "css-tree": "^1.0.0-alpha.39",
 | 
			
		||||
    "css-unit-converter": "^1.1.2",
 | 
			
		||||
    "css-what": "^5.0.1",
 | 
			
		||||
    "cssesc": "^3.0.0",
 | 
			
		||||
    "cssnano": "^4.1.10",
 | 
			
		||||
    "cssnano-preset-default": "^4.0.7",
 | 
			
		||||
    "cssnano-util-get-arguments": "^4.0.0",
 | 
			
		||||
    "cssnano-util-get-match": "^4.0.0",
 | 
			
		||||
    "cssnano-util-raw-cache": "^4.0.1",
 | 
			
		||||
    "cssnano-util-same-parent": "^4.0.1",
 | 
			
		||||
    "csso": "^4.0.3",
 | 
			
		||||
    "cyclist": "^1.0.1",
 | 
			
		||||
    "dashdash": "^1.14.1",
 | 
			
		||||
    "de-indent": "^1.0.2",
 | 
			
		||||
    "debug": "^4.1.1",
 | 
			
		||||
    "decamelize": "^4.0.0",
 | 
			
		||||
    "decode-uri-component": "^0.2.0",
 | 
			
		||||
    "deep-equal": "^2.0.3",
 | 
			
		||||
    "deepmerge": "^4.2.2",
 | 
			
		||||
    "default-gateway": "^6.0.1",
 | 
			
		||||
    "define-properties": "^1.1.3",
 | 
			
		||||
    "define-property": "^2.0.2",
 | 
			
		||||
    "del": "^5.1.0",
 | 
			
		||||
    "delayed-stream": "^1.0.0",
 | 
			
		||||
    "delegate": "^3.2.0",
 | 
			
		||||
    "depd": "^2.0.0",
 | 
			
		||||
    "des.js": "^1.0.1",
 | 
			
		||||
    "destroy": "^1.0.4",
 | 
			
		||||
    "detect-node": "^2.0.4",
 | 
			
		||||
    "diacritics": "^1.3.0",
 | 
			
		||||
    "diffie-hellman": "^5.0.3",
 | 
			
		||||
    "dir-glob": "^3.0.1",
 | 
			
		||||
    "dns-equal": "^1.0.0",
 | 
			
		||||
    "dns-packet": "^5.2.1",
 | 
			
		||||
    "dns-txt": "^2.0.2",
 | 
			
		||||
    "docsearch.js": "^2.6.3",
 | 
			
		||||
    "dom-converter": "^0.2.0",
 | 
			
		||||
    "dom-serializer": "^1.0.1",
 | 
			
		||||
    "dom-walk": "^0.1.2",
 | 
			
		||||
    "domain-browser": "^4.16.0",
 | 
			
		||||
    "domelementtype": "^2.0.1",
 | 
			
		||||
    "domhandler": "^3.0.0",
 | 
			
		||||
    "domutils": "^2.1.0",
 | 
			
		||||
    "dot-prop": "^5.2.0",
 | 
			
		||||
    "duplexify": "^4.1.1",
 | 
			
		||||
    "ecc-jsbn": "^0.2.0",
 | 
			
		||||
    "ee-first": "^1.1.1",
 | 
			
		||||
    "electron-to-chromium": "^1.3.522",
 | 
			
		||||
    "elliptic": "^6.5.3",
 | 
			
		||||
    "emoji-regex": "^9.0.0",
 | 
			
		||||
    "emojis-list": "^3.0.0",
 | 
			
		||||
    "encodeurl": "^1.0.2",
 | 
			
		||||
    "end-of-stream": "^1.4.4",
 | 
			
		||||
    "enhanced-resolve": "^4.3.0",
 | 
			
		||||
    "entities": "^2.0.3",
 | 
			
		||||
    "envify": "^4.1.0",
 | 
			
		||||
    "envinfo": "^7.7.2",
 | 
			
		||||
    "errno": "^0.1.7",
 | 
			
		||||
    "error-ex": "^1.3.2",
 | 
			
		||||
    "es-abstract": "^1.17.6",
 | 
			
		||||
    "es-to-primitive": "^1.2.1",
 | 
			
		||||
    "es6-promise": "^4.2.8",
 | 
			
		||||
    "escape-html": "^1.0.3",
 | 
			
		||||
    "escape-string-regexp": "^4.0.0",
 | 
			
		||||
    "eslint-scope": "^5.1.0",
 | 
			
		||||
    "esprima": "^4.0.1",
 | 
			
		||||
    "esrecurse": "^4.2.1",
 | 
			
		||||
    "estraverse": "^5.2.0",
 | 
			
		||||
    "esutils": "^2.0.3",
 | 
			
		||||
    "etag": "^1.8.1",
 | 
			
		||||
    "eventemitter3": "^4.0.4",
 | 
			
		||||
    "events": "^3.2.0",
 | 
			
		||||
    "eventsource": "^2.0.2",
 | 
			
		||||
    "evp_bytestokey": "^1.0.3",
 | 
			
		||||
    "execa": "^4.0.3",
 | 
			
		||||
    "expand-brackets": "^4.0.0",
 | 
			
		||||
    "express": "^4.17.1",
 | 
			
		||||
    "extend": "^3.0.2",
 | 
			
		||||
    "extend-shallow": "^3.0.2",
 | 
			
		||||
    "extglob": "^3.0.0",
 | 
			
		||||
    "extsprintf": "^1.4.0",
 | 
			
		||||
    "fast-deep-equal": "^3.1.3",
 | 
			
		||||
    "fast-glob": "^3.2.4",
 | 
			
		||||
    "fast-json-stable-stringify": "^2.1.0",
 | 
			
		||||
    "faye-websocket": "^0.11.3",
 | 
			
		||||
    "figgy-pudding": "^3.5.2",
 | 
			
		||||
    "figures": "^3.2.0",
 | 
			
		||||
    "file-loader": "^6.0.0",
 | 
			
		||||
    "fill-range": "^7.0.1",
 | 
			
		||||
    "finalhandler": "^1.1.2",
 | 
			
		||||
    "find-babel-config": "^1.2.0",
 | 
			
		||||
    "find-cache-dir": "^3.3.1",
 | 
			
		||||
    "find-up": "^4.1.0",
 | 
			
		||||
    "flush-write-stream": "^2.0.0",
 | 
			
		||||
    "follow-redirects": "^1.12.1",
 | 
			
		||||
    "for-in": "^1.0.2",
 | 
			
		||||
    "foreach": "^2.0.5",
 | 
			
		||||
    "forever-agent": "^0.6.1",
 | 
			
		||||
    "form-data": "^3.0.0",
 | 
			
		||||
    "forwarded": "^0.1.2",
 | 
			
		||||
    "fragment-cache": "^0.2.1",
 | 
			
		||||
    "fresh": "^0.5.2",
 | 
			
		||||
    "from2": "^2.3.0",
 | 
			
		||||
    "fs-extra": "^9.0.1",
 | 
			
		||||
    "fs-write-stream-atomic": "^1.0.10",
 | 
			
		||||
    "fs.realpath": "^1.0.0",
 | 
			
		||||
    "function-bind": "^1.1.1",
 | 
			
		||||
    "gensync": "^1.0.0-beta.1",
 | 
			
		||||
    "get-caller-file": "^2.0.5",
 | 
			
		||||
    "get-stream": "^5.1.0",
 | 
			
		||||
    "get-value": "^3.0.1",
 | 
			
		||||
    "getpass": "^0.1.7",
 | 
			
		||||
    "glob": "^7.1.6",
 | 
			
		||||
    "glob-parent": "^5.1.1",
 | 
			
		||||
    "glob-to-regexp": "^0.4.1",
 | 
			
		||||
    "global": "^4.4.0",
 | 
			
		||||
    "globals": "^13.1.0",
 | 
			
		||||
    "globby": "^11.0.1",
 | 
			
		||||
    "good-listener": "^1.2.2",
 | 
			
		||||
    "graceful-fs": "^4.2.4",
 | 
			
		||||
    "gray-matter": "^4.0.2",
 | 
			
		||||
    "handle-thing": "^2.0.1",
 | 
			
		||||
    "har-schema": "^2.0.0",
 | 
			
		||||
    "har-validator": "^5.1.5",
 | 
			
		||||
    "has": "^1.0.3",
 | 
			
		||||
    "has-ansi": "^4.0.0",
 | 
			
		||||
    "has-flag": "^4.0.0",
 | 
			
		||||
    "has-symbols": "^1.0.1",
 | 
			
		||||
    "has-value": "^2.0.2",
 | 
			
		||||
    "has-values": "^2.0.1",
 | 
			
		||||
    "hash-base": "^3.1.0",
 | 
			
		||||
    "hash-sum": "^2.0.0",
 | 
			
		||||
    "hash.js": "^1.1.7",
 | 
			
		||||
    "he": "^1.2.0",
 | 
			
		||||
    "hex-color-regex": "^1.1.0",
 | 
			
		||||
    "hmac-drbg": "^1.0.1",
 | 
			
		||||
    "hogan.js": "^3.0.2",
 | 
			
		||||
    "hpack.js": "^2.1.6",
 | 
			
		||||
    "hsl-regex": "^1.0.0",
 | 
			
		||||
    "hsla-regex": "^1.0.0",
 | 
			
		||||
    "html-comment-regex": "^1.1.2",
 | 
			
		||||
    "html-entities": "^1.3.1",
 | 
			
		||||
    "html-minifier": "^4.0.0",
 | 
			
		||||
    "html-tags": "^3.1.0",
 | 
			
		||||
    "htmlparser2": "^4.1.0",
 | 
			
		||||
    "http-deceiver": "^1.2.7",
 | 
			
		||||
    "http-errors": "^1.8.0",
 | 
			
		||||
    "http-parser-js": "^0.5.2",
 | 
			
		||||
    "http-proxy": "^1.18.1",
 | 
			
		||||
    "http-proxy-middleware": "^1.0.5",
 | 
			
		||||
    "http-signature": "^1.3.4",
 | 
			
		||||
    "https-browserify": "^1.0.0",
 | 
			
		||||
    "iconv-lite": "^0.6.2",
 | 
			
		||||
    "icss-replace-symbols": "^1.1.0",
 | 
			
		||||
    "icss-utils": "^4.1.1",
 | 
			
		||||
    "ieee754": "^1.1.13",
 | 
			
		||||
    "iferr": "^1.0.2",
 | 
			
		||||
    "ignore": "^5.1.8",
 | 
			
		||||
    "immediate": "^3.3.0",
 | 
			
		||||
    "import-cwd": "^3.0.0",
 | 
			
		||||
    "import-fresh": "^3.2.1",
 | 
			
		||||
    "import-from": "^3.0.0",
 | 
			
		||||
    "import-local": "^3.0.2",
 | 
			
		||||
    "imurmurhash": "^0.1.4",
 | 
			
		||||
    "indexes-of": "^1.0.1",
 | 
			
		||||
    "infer-owner": "^1.0.4",
 | 
			
		||||
    "inflight": "^1.0.6",
 | 
			
		||||
    "inherits": "^2.0.4",
 | 
			
		||||
    "internal-ip": "^6.1.0",
 | 
			
		||||
    "invariant": "^2.2.4",
 | 
			
		||||
    "invert-kv": "^3.0.1",
 | 
			
		||||
    "ip": "^1.1.5",
 | 
			
		||||
    "ip-regex": "^4.1.0",
 | 
			
		||||
    "ipaddr.js": "^1.9.1",
 | 
			
		||||
    "is-absolute-url": "^3.0.3",
 | 
			
		||||
    "is-accessor-descriptor": "^3.0.1",
 | 
			
		||||
    "is-arguments": "^1.0.4",
 | 
			
		||||
    "is-arrayish": "^0.3.2",
 | 
			
		||||
    "is-binary-path": "^2.1.0",
 | 
			
		||||
    "is-buffer": "^2.0.4",
 | 
			
		||||
    "is-callable": "^1.2.0",
 | 
			
		||||
    "is-color-stop": "^1.1.0",
 | 
			
		||||
    "is-data-descriptor": "^2.0.0",
 | 
			
		||||
    "is-date-object": "^1.0.2",
 | 
			
		||||
    "is-descriptor": "^3.0.0",
 | 
			
		||||
    "is-directory": "^0.3.1",
 | 
			
		||||
    "is-extendable": "^1.0.1",
 | 
			
		||||
    "is-extglob": "^2.1.1",
 | 
			
		||||
    "is-fullwidth-code-point": "^3.0.0",
 | 
			
		||||
    "is-glob": "^4.0.1",
 | 
			
		||||
    "is-number": "^7.0.0",
 | 
			
		||||
    "is-obj": "^2.0.0",
 | 
			
		||||
    "is-path-cwd": "^2.2.0",
 | 
			
		||||
    "is-path-in-cwd": "^3.0.0",
 | 
			
		||||
    "is-path-inside": "^3.0.2",
 | 
			
		||||
    "is-plain-obj": "^2.1.0",
 | 
			
		||||
    "is-plain-object": "^4.1.1",
 | 
			
		||||
    "is-regex": "^1.1.1",
 | 
			
		||||
    "is-resolvable": "^1.1.0",
 | 
			
		||||
    "is-stream": "^2.0.0",
 | 
			
		||||
    "is-svg": "^4.2.1",
 | 
			
		||||
    "is-symbol": "^1.0.3",
 | 
			
		||||
    "is-typedarray": "^1.0.0",
 | 
			
		||||
    "is-windows": "^1.0.2",
 | 
			
		||||
    "is-wsl": "^2.2.0",
 | 
			
		||||
    "isarray": "^2.0.5",
 | 
			
		||||
    "isexe": "^2.0.0",
 | 
			
		||||
    "isobject": "^4.0.0",
 | 
			
		||||
    "isstream": "^0.1.2",
 | 
			
		||||
    "javascript-stringify": "^2.0.1",
 | 
			
		||||
    "js-levenshtein": "^1.1.6",
 | 
			
		||||
    "js-tokens": "^6.0.0",
 | 
			
		||||
    "js-yaml": "^3.14.0",
 | 
			
		||||
    "jsbn": "^1.1.0",
 | 
			
		||||
    "jsesc": "^3.0.1",
 | 
			
		||||
    "json-parse-better-errors": "^1.0.2",
 | 
			
		||||
    "json-schema": "^0.4.0",
 | 
			
		||||
    "json-schema-traverse": "^0.4.1",
 | 
			
		||||
    "json-stringify-safe": "^5.0.1",
 | 
			
		||||
    "json3": "^3.3.3",
 | 
			
		||||
    "json5": "^2.1.3",
 | 
			
		||||
    "jsonfile": "^6.0.1",
 | 
			
		||||
    "jsprim": "^2.0.0",
 | 
			
		||||
    "killable": "^1.0.1",
 | 
			
		||||
    "kind-of": "^6.0.3",
 | 
			
		||||
    "last-call-webpack-plugin": "^3.0.0",
 | 
			
		||||
    "lcid": "^3.1.1",
 | 
			
		||||
    "linkify-it": "^3.0.2",
 | 
			
		||||
    "load-script": "^1.0.0",
 | 
			
		||||
    "loader-runner": "^4.0.0",
 | 
			
		||||
    "loader-utils": "^2.0.0",
 | 
			
		||||
    "locate-path": "^5.0.0",
 | 
			
		||||
    "lodash": "^4.17.19",
 | 
			
		||||
    "lodash._reinterpolate": "^3.0.0",
 | 
			
		||||
    "lodash.chunk": "^4.2.0",
 | 
			
		||||
    "lodash.clonedeep": "^4.5.0",
 | 
			
		||||
    "lodash.debounce": "^4.0.8",
 | 
			
		||||
    "lodash.kebabcase": "^4.1.1",
 | 
			
		||||
    "lodash.memoize": "^4.1.2",
 | 
			
		||||
    "lodash.padstart": "^4.6.1",
 | 
			
		||||
    "lodash.sortby": "^4.7.0",
 | 
			
		||||
    "lodash.template": "^4.5.0",
 | 
			
		||||
    "lodash.templatesettings": "^4.2.0",
 | 
			
		||||
    "lodash.uniq": "^4.5.0",
 | 
			
		||||
    "loglevel": "^1.6.8",
 | 
			
		||||
    "loose-envify": "^1.4.0",
 | 
			
		||||
    "lower-case": "^2.0.1",
 | 
			
		||||
    "lru-cache": "^6.0.0",
 | 
			
		||||
    "make-dir": "^3.1.0",
 | 
			
		||||
    "mamacro": "^0.0.7",
 | 
			
		||||
    "map-age-cleaner": "^0.1.3",
 | 
			
		||||
    "map-cache": "^0.2.2",
 | 
			
		||||
    "map-visit": "^1.0.0",
 | 
			
		||||
    "markdown-it": "^12.3.2",
 | 
			
		||||
    "markdown-it-anchor": "^5.3.0",
 | 
			
		||||
    "markdown-it-chain": "^1.3.0",
 | 
			
		||||
    "markdown-it-container": "^3.0.0",
 | 
			
		||||
    "markdown-it-emoji": "^1.4.0",
 | 
			
		||||
    "markdown-it-table-of-contents": "^0.4.4",
 | 
			
		||||
    "md5.js": "^1.3.5",
 | 
			
		||||
    "mdn-data": "^2.0.11",
 | 
			
		||||
    "mdurl": "^1.0.1",
 | 
			
		||||
    "media-typer": "^1.1.0",
 | 
			
		||||
    "mem": "^6.1.0",
 | 
			
		||||
    "memory-fs": "^0.5.0",
 | 
			
		||||
    "merge-descriptors": "^1.0.1",
 | 
			
		||||
    "merge-source-map": "^1.1.0",
 | 
			
		||||
    "merge2": "^1.4.1",
 | 
			
		||||
    "methods": "^1.1.2",
 | 
			
		||||
    "micromatch": "^4.0.2",
 | 
			
		||||
    "miller-rabin": "^4.0.1",
 | 
			
		||||
    "mime": "^2.4.6",
 | 
			
		||||
    "mime-db": "^1.44.0",
 | 
			
		||||
    "mime-types": "^2.1.27",
 | 
			
		||||
    "mimic-fn": "^3.1.0",
 | 
			
		||||
    "min-document": "^2.19.0",
 | 
			
		||||
    "mini-css-extract-plugin": "^0.9.0",
 | 
			
		||||
    "minimalistic-assert": "^1.0.1",
 | 
			
		||||
    "minimalistic-crypto-utils": "^1.0.1",
 | 
			
		||||
    "minimatch": "^3.0.4",
 | 
			
		||||
    "minimist": "^1.2.5",
 | 
			
		||||
    "mississippi": "^4.0.0",
 | 
			
		||||
    "mixin-deep": "^2.0.1",
 | 
			
		||||
    "mkdirp": "^1.0.4",
 | 
			
		||||
    "move-concurrently": "^1.0.1",
 | 
			
		||||
    "ms": "^2.1.2",
 | 
			
		||||
    "multicast-dns": "^7.2.2",
 | 
			
		||||
    "multicast-dns-service-types": "^1.1.0",
 | 
			
		||||
    "nanomatch": "^1.2.13",
 | 
			
		||||
    "negotiator": "^0.6.2",
 | 
			
		||||
    "neo-async": "^2.6.2",
 | 
			
		||||
    "nice-try": "^2.0.1",
 | 
			
		||||
    "no-case": "^3.0.3",
 | 
			
		||||
    "node-forge": "^1.0.0",
 | 
			
		||||
    "node-libs-browser": "^2.2.1",
 | 
			
		||||
    "node-releases": "^1.1.60",
 | 
			
		||||
    "nopt": "^4.0.3",
 | 
			
		||||
    "normalize-path": "^3.0.0",
 | 
			
		||||
    "normalize-range": "^0.1.2",
 | 
			
		||||
    "normalize-url": "^5.1.0",
 | 
			
		||||
    "npm-run-path": "^4.0.1",
 | 
			
		||||
    "nprogress": "^0.2.0",
 | 
			
		||||
    "nth-check": "^2.0.1",
 | 
			
		||||
    "num2fraction": "^1.2.2",
 | 
			
		||||
    "number-is-nan": "^2.0.0",
 | 
			
		||||
    "oauth-sign": "^0.9.0",
 | 
			
		||||
    "object-assign": "^4.1.1",
 | 
			
		||||
    "object-copy": "^1.0.0",
 | 
			
		||||
    "object-inspect": "^1.8.0",
 | 
			
		||||
    "object-is": "^1.1.2",
 | 
			
		||||
    "object-keys": "^1.1.1",
 | 
			
		||||
    "object-visit": "^1.0.1",
 | 
			
		||||
    "object.assign": "^4.1.0",
 | 
			
		||||
    "object.getownpropertydescriptors": "^2.1.0",
 | 
			
		||||
    "object.pick": "^1.3.0",
 | 
			
		||||
    "object.values": "^1.1.1",
 | 
			
		||||
    "obuf": "^1.1.2",
 | 
			
		||||
    "on-finished": "^2.3.0",
 | 
			
		||||
    "on-headers": "^1.0.2",
 | 
			
		||||
    "once": "^1.4.0",
 | 
			
		||||
    "opencollective-postinstall": "^2.0.3",
 | 
			
		||||
    "opn": "^6.0.0",
 | 
			
		||||
    "optimize-css-assets-webpack-plugin": "^5.0.3",
 | 
			
		||||
    "original": "^1.0.2",
 | 
			
		||||
    "os-browserify": "^0.3.0",
 | 
			
		||||
    "os-locale": "^5.0.0",
 | 
			
		||||
    "p-defer": "^3.0.0",
 | 
			
		||||
    "p-finally": "^2.0.1",
 | 
			
		||||
    "p-is-promise": "^3.0.0",
 | 
			
		||||
    "p-limit": "^3.0.2",
 | 
			
		||||
    "p-locate": "^4.1.0",
 | 
			
		||||
    "p-map": "^4.0.0",
 | 
			
		||||
    "p-retry": "^4.2.0",
 | 
			
		||||
    "p-try": "^2.2.0",
 | 
			
		||||
    "pako": "^1.0.11",
 | 
			
		||||
    "parallel-transform": "^1.2.0",
 | 
			
		||||
    "param-case": "^3.0.3",
 | 
			
		||||
    "parse-asn1": "^5.1.5",
 | 
			
		||||
    "parse-json": "^5.0.1",
 | 
			
		||||
    "parseurl": "^1.3.3",
 | 
			
		||||
    "pascalcase": "^1.0.0",
 | 
			
		||||
    "path-browserify": "^1.0.1",
 | 
			
		||||
    "path-dirname": "^1.0.2",
 | 
			
		||||
    "path-exists": "^4.0.0",
 | 
			
		||||
    "path-is-absolute": "^2.0.0",
 | 
			
		||||
    "path-is-inside": "^1.0.2",
 | 
			
		||||
    "path-key": "^3.1.1",
 | 
			
		||||
    "path-parse": "^1.0.6",
 | 
			
		||||
    "path-to-regexp": "^6.1.0",
 | 
			
		||||
    "path-type": "^4.0.0",
 | 
			
		||||
    "pbkdf2": "^3.1.1",
 | 
			
		||||
    "performance-now": "^2.1.0",
 | 
			
		||||
    "pify": "^5.0.0",
 | 
			
		||||
    "pinkie": "^2.0.4",
 | 
			
		||||
    "pinkie-promise": "^2.0.1",
 | 
			
		||||
    "pkg-dir": "^4.2.0",
 | 
			
		||||
    "pkg-up": "^3.1.0",
 | 
			
		||||
    "portfinder": "^1.0.28",
 | 
			
		||||
    "posix-character-classes": "^1.0.0",
 | 
			
		||||
    "postcss": "^8.2.10",
 | 
			
		||||
    "postcss-calc": "^7.0.2",
 | 
			
		||||
    "postcss-colormin": "^4.0.3",
 | 
			
		||||
    "postcss-convert-values": "^4.0.1",
 | 
			
		||||
    "postcss-discard-comments": "^4.0.2",
 | 
			
		||||
    "postcss-discard-duplicates": "^4.0.2",
 | 
			
		||||
    "postcss-discard-empty": "^4.0.1",
 | 
			
		||||
    "postcss-discard-overridden": "^4.0.1",
 | 
			
		||||
    "postcss-load-config": "^2.1.0",
 | 
			
		||||
    "postcss-loader": "^3.0.0",
 | 
			
		||||
    "postcss-merge-longhand": "^4.0.11",
 | 
			
		||||
    "postcss-merge-rules": "^4.0.3",
 | 
			
		||||
    "postcss-minify-font-values": "^4.0.2",
 | 
			
		||||
    "postcss-minify-gradients": "^4.0.2",
 | 
			
		||||
    "postcss-minify-params": "^4.0.2",
 | 
			
		||||
    "postcss-minify-selectors": "^4.0.2",
 | 
			
		||||
    "postcss-modules-extract-imports": "^2.0.0",
 | 
			
		||||
    "postcss-modules-local-by-default": "^3.0.3",
 | 
			
		||||
    "postcss-modules-scope": "^2.2.0",
 | 
			
		||||
    "postcss-modules-values": "^3.0.0",
 | 
			
		||||
    "postcss-normalize-charset": "^4.0.1",
 | 
			
		||||
    "postcss-normalize-display-values": "^4.0.2",
 | 
			
		||||
    "postcss-normalize-positions": "^4.0.2",
 | 
			
		||||
    "postcss-normalize-repeat-style": "^4.0.2",
 | 
			
		||||
    "postcss-normalize-string": "^4.0.2",
 | 
			
		||||
    "postcss-normalize-timing-functions": "^4.0.2",
 | 
			
		||||
    "postcss-normalize-unicode": "^4.0.1",
 | 
			
		||||
    "postcss-normalize-url": "^4.0.1",
 | 
			
		||||
    "postcss-normalize-whitespace": "^4.0.2",
 | 
			
		||||
    "postcss-ordered-values": "^4.1.2",
 | 
			
		||||
    "postcss-reduce-initial": "^4.0.3",
 | 
			
		||||
    "postcss-reduce-transforms": "^4.0.2",
 | 
			
		||||
    "postcss-safe-parser": "^4.0.2",
 | 
			
		||||
    "postcss-selector-parser": "^6.0.2",
 | 
			
		||||
    "postcss-svgo": "^4.0.2",
 | 
			
		||||
    "postcss-unique-selectors": "^4.0.1",
 | 
			
		||||
    "postcss-value-parser": "^4.1.0",
 | 
			
		||||
    "prepend-http": "^3.0.1",
 | 
			
		||||
    "prettier": "^2.0.5",
 | 
			
		||||
    "pretty-error": "^2.1.1",
 | 
			
		||||
    "pretty-time": "^1.1.0",
 | 
			
		||||
    "prismjs": "^1.20.0",
 | 
			
		||||
    "private": "^0.1.8",
 | 
			
		||||
    "process": "^0.11.10",
 | 
			
		||||
    "process-nextick-args": "^2.0.1",
 | 
			
		||||
    "promise-inflight": "^1.0.1",
 | 
			
		||||
    "proxy-addr": "^2.0.6",
 | 
			
		||||
    "prr": "^1.0.1",
 | 
			
		||||
    "pseudomap": "^1.0.2",
 | 
			
		||||
    "psl": "^1.8.0",
 | 
			
		||||
    "public-encrypt": "^4.0.3",
 | 
			
		||||
    "pump": "^3.0.0",
 | 
			
		||||
    "pumpify": "^2.0.1",
 | 
			
		||||
    "punycode": "^2.1.1",
 | 
			
		||||
    "q": "^1.5.1",
 | 
			
		||||
    "qs": "^6.9.4",
 | 
			
		||||
    "query-string": "^6.13.1",
 | 
			
		||||
    "querystring": "^0.2.0",
 | 
			
		||||
    "querystring-es3": "^0.2.1",
 | 
			
		||||
    "querystringify": "^2.1.1",
 | 
			
		||||
    "randombytes": "^2.1.0",
 | 
			
		||||
    "randomfill": "^1.0.4",
 | 
			
		||||
    "range-parser": "^1.2.1",
 | 
			
		||||
    "raw-body": "^2.4.1",
 | 
			
		||||
    "readable-stream": "^3.6.0",
 | 
			
		||||
    "readdirp": "^3.4.0",
 | 
			
		||||
    "reduce": "^1.0.2",
 | 
			
		||||
    "regenerate": "^1.4.1",
 | 
			
		||||
    "regenerate-unicode-properties": "^8.2.0",
 | 
			
		||||
    "regenerator-runtime": "^0.13.7",
 | 
			
		||||
    "regenerator-transform": "^0.14.5",
 | 
			
		||||
    "regex-not": "^1.0.2",
 | 
			
		||||
    "regexp.prototype.flags": "^1.3.0",
 | 
			
		||||
    "regexpu-core": "^4.7.0",
 | 
			
		||||
    "regjsgen": "^0.5.2",
 | 
			
		||||
    "regjsparser": "^0.6.4",
 | 
			
		||||
    "relateurl": "^0.2.7",
 | 
			
		||||
    "remove-trailing-separator": "^1.1.0",
 | 
			
		||||
    "renderkid": "^2.0.3",
 | 
			
		||||
    "repeat-element": "^1.1.3",
 | 
			
		||||
    "repeat-string": "^1.6.1",
 | 
			
		||||
    "request": "^2.88.2",
 | 
			
		||||
    "require-directory": "^2.1.1",
 | 
			
		||||
    "require-main-filename": "^2.0.0",
 | 
			
		||||
    "requires-port": "^1.0.0",
 | 
			
		||||
    "reselect": "^4.0.0",
 | 
			
		||||
    "resolve": "^1.17.0",
 | 
			
		||||
    "resolve-cwd": "^3.0.0",
 | 
			
		||||
    "resolve-from": "^5.0.0",
 | 
			
		||||
    "resolve-url": "^0.2.1",
 | 
			
		||||
    "ret": "^0.3.1",
 | 
			
		||||
    "retry": "^0.12.0",
 | 
			
		||||
    "rgb-regex": "^1.0.1",
 | 
			
		||||
    "rgba-regex": "^1.0.0",
 | 
			
		||||
    "rimraf": "^3.0.2",
 | 
			
		||||
    "ripemd160": "^2.0.2",
 | 
			
		||||
    "run-queue": "^2.0.1",
 | 
			
		||||
    "safe-buffer": "^5.2.1",
 | 
			
		||||
    "safe-regex": "^2.1.1",
 | 
			
		||||
    "safer-buffer": "^2.1.2",
 | 
			
		||||
    "sax": "^1.2.4",
 | 
			
		||||
    "schema-utils": "^2.7.0",
 | 
			
		||||
    "section-matter": "^1.0.0",
 | 
			
		||||
    "select": "^1.1.2",
 | 
			
		||||
    "select-hose": "^2.0.0",
 | 
			
		||||
    "selfsigned": "^1.10.7",
 | 
			
		||||
    "semver": "^7.3.2",
 | 
			
		||||
    "send": "^0.17.1",
 | 
			
		||||
    "serialize-javascript": "^4.0.0",
 | 
			
		||||
    "serve-index": "^1.9.1",
 | 
			
		||||
    "serve-static": "^1.14.1",
 | 
			
		||||
    "set-blocking": "^2.0.0",
 | 
			
		||||
    "set-value": "^4.0.1",
 | 
			
		||||
    "setimmediate": "^1.0.5",
 | 
			
		||||
    "setprototypeof": "^1.2.0",
 | 
			
		||||
    "sha.js": "^2.4.11",
 | 
			
		||||
    "shebang-command": "^2.0.0",
 | 
			
		||||
    "shebang-regex": "^3.0.0",
 | 
			
		||||
    "signal-exit": "^3.0.3",
 | 
			
		||||
    "simple-swizzle": "^0.2.2",
 | 
			
		||||
    "sitemap": "^6.2.0",
 | 
			
		||||
    "slash": "^3.0.0",
 | 
			
		||||
    "smoothscroll-polyfill": "^0.4.4",
 | 
			
		||||
    "snapdragon": "^0.12.0",
 | 
			
		||||
    "snapdragon-node": "^3.0.0",
 | 
			
		||||
    "snapdragon-util": "^5.0.1",
 | 
			
		||||
    "sockjs": "^0.3.21",
 | 
			
		||||
    "sockjs-client": "^1.5.0",
 | 
			
		||||
    "sort-keys": "^4.0.0",
 | 
			
		||||
    "source-list-map": "^2.0.1",
 | 
			
		||||
    "source-map": "^0.7.3",
 | 
			
		||||
    "source-map-resolve": "^0.6.0",
 | 
			
		||||
    "source-map-support": "^0.5.19",
 | 
			
		||||
    "source-map-url": "^0.4.0",
 | 
			
		||||
    "spdy": "^4.0.2",
 | 
			
		||||
    "spdy-transport": "^3.0.0",
 | 
			
		||||
    "split-string": "^6.1.0",
 | 
			
		||||
    "sprintf-js": "^1.1.2",
 | 
			
		||||
    "sshpk": "^1.16.1",
 | 
			
		||||
    "ssri": "^8.0.0",
 | 
			
		||||
    "stable": "^0.1.8",
 | 
			
		||||
    "stack-utils": "^2.0.2",
 | 
			
		||||
    "static-extend": "^0.1.2",
 | 
			
		||||
    "statuses": "^2.0.0",
 | 
			
		||||
    "std-env": "^2.2.1",
 | 
			
		||||
    "stream-browserify": "^3.0.0",
 | 
			
		||||
    "stream-each": "^1.2.3",
 | 
			
		||||
    "stream-http": "^3.1.1",
 | 
			
		||||
    "stream-shift": "^1.0.1",
 | 
			
		||||
    "strict-uri-encode": "^2.0.0",
 | 
			
		||||
    "string-width": "^4.2.0",
 | 
			
		||||
    "string.prototype.trimleft": "^2.1.2",
 | 
			
		||||
    "string.prototype.trimright": "^2.1.2",
 | 
			
		||||
    "string_decoder": "^1.3.0",
 | 
			
		||||
    "strip-ansi": "^6.0.0",
 | 
			
		||||
    "strip-bom-string": "^1.0.0",
 | 
			
		||||
    "strip-eof": "^2.0.0",
 | 
			
		||||
    "stylehacks": "^4.0.3",
 | 
			
		||||
    "stylus": "^0.54.8",
 | 
			
		||||
    "stylus-loader": "^3.0.2",
 | 
			
		||||
    "supports-color": "^7.1.0",
 | 
			
		||||
    "svg-tags": "^1.0.0",
 | 
			
		||||
    "svgo": "^1.3.2",
 | 
			
		||||
    "tapable": "^1.1.3",
 | 
			
		||||
    "terser": "^5.0.0",
 | 
			
		||||
    "terser-webpack-plugin": "^4.0.0",
 | 
			
		||||
    "text-table": "^0.2.0",
 | 
			
		||||
    "through": "^2.3.8",
 | 
			
		||||
    "through2": "^4.0.2",
 | 
			
		||||
    "thunky": "^1.1.0",
 | 
			
		||||
    "timers-browserify": "^2.0.11",
 | 
			
		||||
    "timsort": "^0.3.0",
 | 
			
		||||
    "tiny-emitter": "^2.1.0",
 | 
			
		||||
    "to-arraybuffer": "^1.0.1",
 | 
			
		||||
    "to-factory": "^1.0.0",
 | 
			
		||||
    "to-fast-properties": "^3.0.1",
 | 
			
		||||
    "to-object-path": "^0.3.0",
 | 
			
		||||
    "to-regex": "^3.0.2",
 | 
			
		||||
    "to-regex-range": "^5.0.1",
 | 
			
		||||
    "toidentifier": "^1.0.0",
 | 
			
		||||
    "toml": "^3.0.0",
 | 
			
		||||
    "toposort": "^2.0.2",
 | 
			
		||||
    "tough-cookie": "^4.0.0",
 | 
			
		||||
    "tr46": "^2.0.2",
 | 
			
		||||
    "tslib": "^2.0.0",
 | 
			
		||||
    "tty-browserify": "^0.0.1",
 | 
			
		||||
    "tunnel-agent": "^0.6.0",
 | 
			
		||||
    "tweetnacl": "^1.0.3",
 | 
			
		||||
    "type-fest": "^0.16.0",
 | 
			
		||||
    "type-is": "^1.6.18",
 | 
			
		||||
    "typedarray": "^0.0.6",
 | 
			
		||||
    "uc.micro": "^1.0.6",
 | 
			
		||||
    "uglify-js": "^3.10.1",
 | 
			
		||||
    "unicode-canonical-property-names-ecmascript": "^1.0.4",
 | 
			
		||||
    "unicode-match-property-ecmascript": "^1.0.4",
 | 
			
		||||
    "unicode-match-property-value-ecmascript": "^1.2.0",
 | 
			
		||||
    "unicode-property-aliases-ecmascript": "^1.1.0",
 | 
			
		||||
    "union-value": "^2.0.1",
 | 
			
		||||
    "uniq": "^1.0.1",
 | 
			
		||||
    "uniqs": "^2.0.0",
 | 
			
		||||
    "unique-filename": "^1.1.1",
 | 
			
		||||
    "unique-slug": "^2.0.2",
 | 
			
		||||
    "universalify": "^2.0.0",
 | 
			
		||||
    "unpipe": "^1.0.0",
 | 
			
		||||
    "unquote": "^1.1.1",
 | 
			
		||||
    "unset-value": "^1.0.0",
 | 
			
		||||
    "upath": "^1.2.0",
 | 
			
		||||
    "upper-case": "^2.0.1",
 | 
			
		||||
    "uri-js": "^4.2.2",
 | 
			
		||||
    "urix": "^0.1.0",
 | 
			
		||||
    "url": "^0.11.0",
 | 
			
		||||
    "url-loader": "^4.1.0",
 | 
			
		||||
    "url-parse": "^1.4.7",
 | 
			
		||||
    "use": "^3.1.1",
 | 
			
		||||
    "util": "^0.12.3",
 | 
			
		||||
    "util-deprecate": "^1.0.2",
 | 
			
		||||
    "util.promisify": "^1.0.1",
 | 
			
		||||
    "utila": "^0.4.0",
 | 
			
		||||
    "utils-merge": "^1.0.1",
 | 
			
		||||
    "uuid": "^8.3.0",
 | 
			
		||||
    "vary": "^1.1.2",
 | 
			
		||||
    "vendors": "^1.0.4",
 | 
			
		||||
    "verror": "^1.10.0",
 | 
			
		||||
    "vm-browserify": "^1.1.2",
 | 
			
		||||
    "vue": "^2.6.11",
 | 
			
		||||
    "vue-hot-reload-api": "^2.3.4",
 | 
			
		||||
    "vue-loader": "^15.9.3",
 | 
			
		||||
    "vue-router": "^3.4.0",
 | 
			
		||||
    "vue-server-renderer": "^2.6.11",
 | 
			
		||||
    "vue-style-loader": "^4.1.2",
 | 
			
		||||
    "vue-template-compiler": "^2.6.11",
 | 
			
		||||
    "vue-template-es2015-compiler": "^1.9.1",
 | 
			
		||||
    "vuepress": "^1.5.3",
 | 
			
		||||
    "vuepress-html-webpack-plugin": "^3.2.0",
 | 
			
		||||
    "vuepress-plugin-container": "^2.1.4",
 | 
			
		||||
    "vuepress-plugin-sitemap": "^2.3.1",
 | 
			
		||||
    "vuepress-plugin-smooth-scroll": "^0.0.9",
 | 
			
		||||
    "vuepress-plugin-zooming": "^1.1.7",
 | 
			
		||||
    "watchpack": "^1.7.4",
 | 
			
		||||
    "wbuf": "^1.7.3",
 | 
			
		||||
    "webidl-conversions": "^6.1.0",
 | 
			
		||||
    "webpack": "^4.44.1",
 | 
			
		||||
    "webpack-chain": "^6.5.1",
 | 
			
		||||
    "webpack-dev-middleware": "^3.7.2",
 | 
			
		||||
    "webpack-dev-server": "^3.11.0",
 | 
			
		||||
    "webpack-log": "^3.0.1",
 | 
			
		||||
    "webpack-merge": "^5.1.1",
 | 
			
		||||
    "webpack-sources": "^1.4.3",
 | 
			
		||||
    "webpackbar": "^4.0.0",
 | 
			
		||||
    "websocket-driver": "^0.7.4",
 | 
			
		||||
    "websocket-extensions": "^0.1.4",
 | 
			
		||||
    "whatwg-url": "^8.1.0",
 | 
			
		||||
    "when": "^3.7.8",
 | 
			
		||||
    "which": "^2.0.2",
 | 
			
		||||
    "which-module": "^2.0.0",
 | 
			
		||||
    "worker-farm": "^1.7.0",
 | 
			
		||||
    "wrap-ansi": "^7.0.0",
 | 
			
		||||
    "wrappy": "^1.0.2",
 | 
			
		||||
    "ws": "^7.3.1",
 | 
			
		||||
    "xmlbuilder": "^15.1.1",
 | 
			
		||||
    "xtend": "^4.0.2",
 | 
			
		||||
    "y18n": "^4.0.0",
 | 
			
		||||
    "yallist": "^4.0.0",
 | 
			
		||||
    "yargs": "^15.4.1",
 | 
			
		||||
    "yargs-parser": "^18.1.3",
 | 
			
		||||
    "zepto": "^1.2.0"
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "vuepress": "^2.0.0-rc.0"
 | 
			
		||||
  },
 | 
			
		||||
  "devDependencies": {},
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "dev": "vuepress dev",
 | 
			
		||||
    "build": "vuepress build"
 | 
			
		||||
  },
 | 
			
		||||
  "author": "",
 | 
			
		||||
  "license": "ISC"
 | 
			
		||||
  "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"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -86,6 +86,7 @@ services:
 | 
			
		||||
      MYSQL_DATABASE: 'npm'
 | 
			
		||||
      MYSQL_USER: 'npm'
 | 
			
		||||
      MYSQL_PASSWORD: 'npm'
 | 
			
		||||
      MARIADB_AUTO_UPGRADE: '1'
 | 
			
		||||
    volumes:
 | 
			
		||||
      - ./mysql:/var/lib/mysql
 | 
			
		||||
```
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								docs/third-party/README.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								docs/third-party/README.md
									
									
									
									
										vendored
									
									
								
							@@ -7,7 +7,7 @@ Known integrations:
 | 
			
		||||
 | 
			
		||||
- [HomeAssistant Hass.io plugin](https://github.com/hassio-addons/addon-nginx-proxy-manager)
 | 
			
		||||
- [UnRaid / Synology](https://github.com/jlesage/docker-nginx-proxy-manager)
 | 
			
		||||
- [Proxmox Scripts](https://github.com/ej52/proxmox-scripts/tree/main/lxc/nginx-proxy-manager)
 | 
			
		||||
- [Proxmox Scripts](https://github.com/ej52/proxmox-scripts/tree/main/apps/nginx-proxy-manager)
 | 
			
		||||
- [nginxproxymanagerGraf](https://github.com/ma-karai/nginxproxymanagerGraf)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13851
									
								
								docs/yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										13851
									
								
								docs/yarn.lock
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -10,6 +10,7 @@
 | 
			
		||||
		<meta name="mobile-web-app-capable" content="yes">
 | 
			
		||||
		<meta name="HandheldFriendly" content="True">
 | 
			
		||||
		<meta name="MobileOptimized" content="320">
 | 
			
		||||
		<meta name="robots" content="noindex">
 | 
			
		||||
		<title><%- title %></title>
 | 
			
		||||
		<link rel="apple-touch-icon" sizes="180x180" href="/images/favicons/apple-touch-icon.png">
 | 
			
		||||
		<link rel="icon" type="image/png" sizes="32x32" href="/images/favicons/favicon-32x32.png">
 | 
			
		||||
 
 | 
			
		||||
@@ -265,7 +265,7 @@ module.exports = Mn.View.extend({
 | 
			
		||||
        this.ui.domain_names.selectize({
 | 
			
		||||
            delimiter:    ',',
 | 
			
		||||
            persist:      false,
 | 
			
		||||
            maxOptions:   15,
 | 
			
		||||
            maxOptions:   30,
 | 
			
		||||
            create:       function (input) {
 | 
			
		||||
                return {
 | 
			
		||||
                    value: input,
 | 
			
		||||
 
 | 
			
		||||
@@ -233,7 +233,7 @@ module.exports = Mn.View.extend({
 | 
			
		||||
        this.ui.domain_names.selectize({
 | 
			
		||||
            delimiter:    ',',
 | 
			
		||||
            persist:      false,
 | 
			
		||||
            maxOptions:   15,
 | 
			
		||||
            maxOptions:   30,
 | 
			
		||||
            create:       function (input) {
 | 
			
		||||
                return {
 | 
			
		||||
                    value: input,
 | 
			
		||||
 
 | 
			
		||||
@@ -271,7 +271,7 @@ module.exports = Mn.View.extend({
 | 
			
		||||
        this.ui.domain_names.selectize({
 | 
			
		||||
            delimiter:    ',',
 | 
			
		||||
            persist:      false,
 | 
			
		||||
            maxOptions:   15,
 | 
			
		||||
            maxOptions:   30,
 | 
			
		||||
            create:       function (input) {
 | 
			
		||||
                return {
 | 
			
		||||
                    value: input,
 | 
			
		||||
 
 | 
			
		||||
@@ -45,7 +45,7 @@
 | 
			
		||||
            <div class="col-sm-4 col-md-4">
 | 
			
		||||
                <div class="form-group">
 | 
			
		||||
                    <label class="form-label"><%- i18n('proxy-hosts', 'forward-port') %> <span class="form-required">*</span></label>
 | 
			
		||||
                    <input name="forward_port" type="number" class="form-control text-monospace model" placeholder="80" value="<%- forward_port %>" required>
 | 
			
		||||
                    <input name="forward_port" type="number" class="form-control text-monospace model" placeholder="80" min="1" max="65535" value="<%- forward_port %>" required>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -235,7 +235,7 @@ module.exports = Mn.View.extend({
 | 
			
		||||
        this.ui.domain_names.selectize({
 | 
			
		||||
            delimiter:    ',',
 | 
			
		||||
            persist:      false,
 | 
			
		||||
            maxOptions:   15,
 | 
			
		||||
            maxOptions:   30,
 | 
			
		||||
            create:       function (input) {
 | 
			
		||||
                return {
 | 
			
		||||
                    value: input,
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,7 @@
 | 
			
		||||
                <div class="col-sm-12 col-md-12">
 | 
			
		||||
                    <div class="form-group">
 | 
			
		||||
                        <label class="form-label"><%- i18n('streams', 'incoming-port') %> <span class="form-required">*</span></label>
 | 
			
		||||
                        <input name="incoming_port" type="number" class="form-control text-monospace" placeholder="eg: 8080" value="<%- incoming_port %>" required>
 | 
			
		||||
                        <input name="incoming_port" type="number" class="form-control text-monospace" placeholder="eg: 8080" min="1" max="65535" value="<%- incoming_port %>" required>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="col-sm-8 col-md-8">
 | 
			
		||||
@@ -21,7 +21,7 @@
 | 
			
		||||
                <div class="col-sm-4 col-md-4">
 | 
			
		||||
                    <div class="form-group">
 | 
			
		||||
                        <label class="form-label"><%- i18n('streams', 'forwarding-port') %> <span class="form-required">*</span></label>
 | 
			
		||||
                        <input name="forwarding_port" type="number" class="form-control text-monospace" placeholder="eg: 80" value="<%- forwarding_port %>" required>
 | 
			
		||||
                        <input name="forwarding_port" type="number" class="form-control text-monospace" placeholder="eg: 80" min="1" max="65535" value="<%- forwarding_port %>" required>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="col-sm-6 col-md-6">
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@
 | 
			
		||||
            <div class="row">
 | 
			
		||||
                <div class="col-sm-12 col-md-12">
 | 
			
		||||
                    <div class="form-group">
 | 
			
		||||
                        <div class="form-label"><%- description %></div>
 | 
			
		||||
                        <div class="form-label"><%- i18n('settings', 'default-site-description') %></div>
 | 
			
		||||
                        <div class="custom-controls-stacked">
 | 
			
		||||
                            <label class="custom-control custom-radio">
 | 
			
		||||
                                <input class="custom-control-input" name="value" value="congratulations" type="radio" required <%- value === 'congratulations' ? 'checked' : '' %>>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
<td>
 | 
			
		||||
    <div><%- name %></div>
 | 
			
		||||
    <div><%- i18n('settings', 'default-site') %></div>
 | 
			
		||||
    <div class="small text-muted">
 | 
			
		||||
        <%- description %>
 | 
			
		||||
        <%- i18n('settings', 'default-site-description') %>
 | 
			
		||||
    </div>
 | 
			
		||||
</td>
 | 
			
		||||
<td>
 | 
			
		||||
 
 | 
			
		||||
@@ -60,7 +60,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "footer": {
 | 
			
		||||
      "fork-me": "Fork me on Github",
 | 
			
		||||
      "copy": "© 2023 <a href=\"{url}\" target=\"_blank\">jc21.com</a>.",
 | 
			
		||||
      "copy": "© 2024 <a href=\"{url}\" target=\"_blank\">jc21.com</a>.",
 | 
			
		||||
      "theme": "Theme by <a href=\"{url}\" target=\"_blank\">Tabler</a>"
 | 
			
		||||
    },
 | 
			
		||||
    "dashboard": {
 | 
			
		||||
@@ -285,6 +285,7 @@
 | 
			
		||||
    "settings": {
 | 
			
		||||
      "title": "Settings",
 | 
			
		||||
      "default-site": "Default Site",
 | 
			
		||||
      "default-site-description": "What to show when Nginx is hit with an unknown Host",
 | 
			
		||||
      "default-site-congratulations": "Congratulations Page",
 | 
			
		||||
      "default-site-404": "404 Page",
 | 
			
		||||
      "default-site-444": "No Response (444)",
 | 
			
		||||
 
 | 
			
		||||
@@ -27,10 +27,10 @@
 | 
			
		||||
    "messageformat-loader": "^0.8.1",
 | 
			
		||||
    "mini-css-extract-plugin": "^0.9.0",
 | 
			
		||||
    "moment": "^2.29.4",
 | 
			
		||||
    "node-sass": "^6.0.1",
 | 
			
		||||
    "node-sass": "^9.0.0",
 | 
			
		||||
    "nodemon": "^2.0.2",
 | 
			
		||||
    "numeral": "^2.0.6",
 | 
			
		||||
    "sass-loader": "10.2.0",
 | 
			
		||||
    "sass-loader": "^10.0.0",
 | 
			
		||||
    "style-loader": "^1.1.3",
 | 
			
		||||
    "tabler-ui": "git+https://github.com/tabler/tabler.git#00f78ad823311bc3ad974ac3e5b0126198f0a813",
 | 
			
		||||
    "underscore": "^1.12.1",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1254
									
								
								frontend/yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										1254
									
								
								frontend/yarn.lock
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -254,13 +254,10 @@ dns_eurodns_endpoint = https://rest-api.eurodns.com/user-api-gateway/proxy`,
 | 
			
		||||
	gandi: {
 | 
			
		||||
		display_name:        'Gandi Live DNS',
 | 
			
		||||
		package_name:        'certbot_plugin_gandi',
 | 
			
		||||
		version_requirement: '~=1.3.2',
 | 
			
		||||
		version_requirement: '~=1.5.0',
 | 
			
		||||
		dependencies:        '',
 | 
			
		||||
		credentials:         `# live dns v5 api key
 | 
			
		||||
dns_gandi_api_key=APIKEY
 | 
			
		||||
 | 
			
		||||
# optional organization id, remove it if not used
 | 
			
		||||
dns_gandi_sharing_id=SHARINGID`,
 | 
			
		||||
		credentials:         `# Gandi personal access token
 | 
			
		||||
dns_gandi_token=PERSONAL_ACCESS_TOKEN`,
 | 
			
		||||
		full_plugin_name: 'dns-gandi',
 | 
			
		||||
	},
 | 
			
		||||
	//####################################################//
 | 
			
		||||
@@ -296,6 +293,16 @@ dns_google_domains_zone = "example.com"`,
 | 
			
		||||
		full_plugin_name: 'dns-google-domains',
 | 
			
		||||
	},
 | 
			
		||||
	//####################################################//
 | 
			
		||||
	he: {
 | 
			
		||||
		display_name:        'Hurricane Electric',
 | 
			
		||||
		package_name:        'certbot-dns-he',
 | 
			
		||||
		version_requirement: '~=1.0.0',
 | 
			
		||||
		dependencies:        '',
 | 
			
		||||
		credentials:         `dns_he_user = Me
 | 
			
		||||
dns_he_pass = my HE password`,
 | 
			
		||||
		full_plugin_name: 'dns-he',
 | 
			
		||||
	},
 | 
			
		||||
	//####################################################//
 | 
			
		||||
	hetzner: {
 | 
			
		||||
		display_name:        'Hetzner',
 | 
			
		||||
		package_name:        'certbot-dns-hetzner',
 | 
			
		||||
@@ -472,6 +479,17 @@ dns_ovh_consumer_key = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw`,
 | 
			
		||||
		full_plugin_name: 'dns-ovh',
 | 
			
		||||
	},
 | 
			
		||||
	//####################################################//
 | 
			
		||||
	plesk: {
 | 
			
		||||
		display_name:        'Plesk',
 | 
			
		||||
		package_name:        'certbot-dns-plesk',
 | 
			
		||||
		version_requirement: '~=0.3.0',
 | 
			
		||||
		dependencies:        '',
 | 
			
		||||
		credentials:         `dns_plesk_username = your-username
 | 
			
		||||
dns_plesk_password = secret
 | 
			
		||||
dns_plesk_api_url = https://plesk-api-host:8443`,
 | 
			
		||||
		full_plugin_name: 'dns-plesk',
 | 
			
		||||
	},
 | 
			
		||||
	//####################################################//
 | 
			
		||||
	porkbun: {
 | 
			
		||||
		display_name:        'Porkbun',
 | 
			
		||||
		package_name:        'certbot-dns-porkbun',
 | 
			
		||||
@@ -538,9 +556,20 @@ aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`,
 | 
			
		||||
		dependencies:        '',
 | 
			
		||||
		credentials:         `dns_strato_username = user
 | 
			
		||||
dns_strato_password = pass
 | 
			
		||||
# uncomment if youre using two factor authentication:
 | 
			
		||||
# dns_strato_totp_devicename = 2fa_device
 | 
			
		||||
# dns_strato_totp_secret = 2fa_secret
 | 
			
		||||
#
 | 
			
		||||
# uncomment if domain name contains special characters
 | 
			
		||||
# insert domain display name as seen on your account page here
 | 
			
		||||
# dns_strato_domain_display_name = my-punicode-url.de`,
 | 
			
		||||
# dns_strato_domain_display_name = my-punicode-url.de
 | 
			
		||||
#
 | 
			
		||||
# if youre not using strato.de or another special endpoint you can customise it below
 | 
			
		||||
# you will probably only need to adjust the host, but you can also change the complete endpoint url
 | 
			
		||||
# dns_strato_custom_api_scheme = https
 | 
			
		||||
# dns_strato_custom_api_host = www.strato.de
 | 
			
		||||
# dns_strato_custom_api_port = 443
 | 
			
		||||
# dns_strato_custom_api_path = "/apps/CustomerService"`,
 | 
			
		||||
		full_plugin_name: 'dns-strato',
 | 
			
		||||
	},
 | 
			
		||||
	//####################################################//
 | 
			
		||||
@@ -557,7 +586,7 @@ dns_transip_key_file = /etc/letsencrypt/transip-rsa.key`,
 | 
			
		||||
	tencentcloud: {
 | 
			
		||||
		display_name:        'Tencent Cloud',
 | 
			
		||||
		package_name:        'certbot-dns-tencentcloud',
 | 
			
		||||
		version_requirement: '~=2.0.0',
 | 
			
		||||
		version_requirement: '~=2.0.2',
 | 
			
		||||
		dependencies:        '',
 | 
			
		||||
		credentials:         `dns_tencentcloud_secret_id  = TENCENT_CLOUD_SECRET_ID
 | 
			
		||||
dns_tencentcloud_secret_key = TENCENT_CLOUD_SECRET_KEY`,
 | 
			
		||||
@@ -567,7 +596,7 @@ dns_tencentcloud_secret_key = TENCENT_CLOUD_SECRET_KEY`,
 | 
			
		||||
	vultr: {
 | 
			
		||||
		display_name:        'Vultr',
 | 
			
		||||
		package_name:        'certbot-dns-vultr',
 | 
			
		||||
		version_requirement: '~=1.0.3',
 | 
			
		||||
		version_requirement: '~=1.1.0',
 | 
			
		||||
		dependencies:        '',
 | 
			
		||||
		credentials:         'dns_vultr_key = YOUR_VULTR_API_KEY',
 | 
			
		||||
		full_plugin_name:    'dns-vultr',
 | 
			
		||||
 
 | 
			
		||||
@@ -3,14 +3,22 @@
 | 
			
		||||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
 | 
			
		||||
. "$DIR/../.common.sh"
 | 
			
		||||
 | 
			
		||||
DOCKER_IMAGE=jc21/nginx-full:certbot-node
 | 
			
		||||
DOCKER_IMAGE=nginxproxymanager/nginx-full:certbot-node
 | 
			
		||||
 | 
			
		||||
# Ensure docker exists
 | 
			
		||||
if hash docker 2>/dev/null; then
 | 
			
		||||
	docker pull "${DOCKER_IMAGE}"
 | 
			
		||||
	cd "${DIR}/../.."
 | 
			
		||||
	echo -e "${BLUE}❯ ${CYAN}Building Frontend ...${RESET}"
 | 
			
		||||
	docker run --rm -e CI=true -v "$(pwd)/frontend:/app/frontend" -v "$(pwd)/global:/app/global" -w /app/frontend "$DOCKER_IMAGE" sh -c "yarn install && yarn build && yarn build && chown -R $(id -u):$(id -g) /app/frontend"
 | 
			
		||||
 | 
			
		||||
	docker run --rm \
 | 
			
		||||
		-e CI=true \
 | 
			
		||||
		-e NODE_OPTIONS=--openssl-legacy-provider \
 | 
			
		||||
		-v "$(pwd)/frontend:/app/frontend" \
 | 
			
		||||
		-v "$(pwd)/global:/app/global" \
 | 
			
		||||
		-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}"
 | 
			
		||||
else
 | 
			
		||||
	echo -e "${RED}❯ docker command is not available${RESET}"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,23 +1,31 @@
 | 
			
		||||
#!/bin/bash -e
 | 
			
		||||
 | 
			
		||||
DOCKER_IMAGE=jc21/nginx-full:certbot-node
 | 
			
		||||
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
 | 
			
		||||
. "$DIR/../.common.sh"
 | 
			
		||||
 | 
			
		||||
DOCKER_IMAGE=nginxproxymanager/nginx-full:certbot-node
 | 
			
		||||
docker pull "${DOCKER_IMAGE}"
 | 
			
		||||
 | 
			
		||||
# Test
 | 
			
		||||
echo -e "${BLUE}❯ ${CYAN}Testing backend ...${RESET}"
 | 
			
		||||
docker run --rm \
 | 
			
		||||
	-v "$(pwd)/backend:/app" \
 | 
			
		||||
	-v "$(pwd)/global:/app/global" \
 | 
			
		||||
	-w /app \
 | 
			
		||||
	"${DOCKER_IMAGE}" \
 | 
			
		||||
	sh -c 'yarn install && yarn eslint . && rm -rf node_modules'
 | 
			
		||||
echo -e "${BLUE}❯ ${GREEN}Testing Complete${RESET}"
 | 
			
		||||
 | 
			
		||||
# Build
 | 
			
		||||
docker build --pull --no-cache --squash --compress \
 | 
			
		||||
echo -e "${BLUE}❯ ${CYAN}Building ...${RESET}"
 | 
			
		||||
docker build --pull --no-cache --compress \
 | 
			
		||||
	-t "${IMAGE}:ci-${BUILD_NUMBER}" \
 | 
			
		||||
	-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_DATE="$(date '+%Y-%m-%d %T %Z')" \
 | 
			
		||||
	.
 | 
			
		||||
echo -e "${BLUE}❯ ${GREEN}Building Complete${RESET}"
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
 | 
			
		||||
if hash docker 2>/dev/null; then
 | 
			
		||||
	cd "${DIR}/.."
 | 
			
		||||
	echo -e "${BLUE}❯ ${CYAN}Building Docs ...${RESET}"
 | 
			
		||||
	docker run --rm -e CI=true -v "$(pwd)/docs:/app/docs" -w /app/docs node:alpine sh -c "yarn install && yarn build && chown -R $(id -u):$(id -g) /app/docs"
 | 
			
		||||
	docker run --rm -e CI=true -v "$(pwd)/docs:/app/docs" -w /app/docs node:alpine sh -c "yarn set version berry && yarn install && yarn build && chown -R $(id -u):$(id -g) /app/docs"
 | 
			
		||||
	echo -e "${BLUE}❯ ${GREEN}Building Docs Complete${RESET}"
 | 
			
		||||
else
 | 
			
		||||
	echo -e "${RED}❯ docker command is not available${RESET}"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user