Merge branch 'NginxProxyManager:develop' into develop-crowdsec

This commit is contained in:
Brian Munro 2024-01-15 06:34:14 +02:00 committed by GitHub
commit a108a5d316
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 5815 additions and 12080 deletions

View File

@ -1 +1 @@
2.10.4 2.11.0

252
Jenkinsfile vendored
View File

@ -17,13 +17,11 @@ pipeline {
IMAGE = 'nginx-proxy-manager' IMAGE = 'nginx-proxy-manager'
BUILD_VERSION = getVersion() BUILD_VERSION = getVersion()
MAJOR_VERSION = '2' 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_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}"
COMPOSE_FILE = 'docker/docker-compose.ci.yml' COMPOSE_FILE = 'docker/docker-compose.ci.yml'
COMPOSE_INTERACTIVE_NO_CLI = 1 COMPOSE_INTERACTIVE_NO_CLI = 1
BUILDX_NAME = "${COMPOSE_PROJECT_NAME}" BUILDX_NAME = "${COMPOSE_PROJECT_NAME}"
DOCS_BUCKET = 'jc21-npm-site'
DOCS_CDN = 'EN1G6DEWZUTDT'
} }
stages { stages {
stage('Environment') { stage('Environment') {
@ -62,103 +60,114 @@ pipeline {
} }
} }
} }
stage('Build and Test') { stage('Builds') {
steps { parallel {
script { stage('Project') {
// Frontend and Backend steps {
def shStatusCode = sh(label: 'Checking and Building', returnStatus: true, script: ''' script {
set -e // Frontend and Backend
./scripts/ci/frontend-build > ${WORKSPACE}/tmp-sh-build 2>&1 def shStatusCode = sh(label: 'Checking and Building', returnStatus: true, script: '''
./scripts/ci/test-and-build > ${WORKSPACE}/tmp-sh-build 2>&1 set -e
''') ./scripts/ci/frontend-build > ${WORKSPACE}/tmp-sh-build 2>&1
shOutput = readFile "${env.WORKSPACE}/tmp-sh-build" ./scripts/ci/test-and-build > ${WORKSPACE}/tmp-sh-build 2>&1
if (shStatusCode != 0) { ''')
error "${shOutput}" shOutput = readFile "${env.WORKSPACE}/tmp-sh-build"
if (shStatusCode != 0) {
error "${shOutput}"
}
}
}
post {
always {
sh 'rm -f ${WORKSPACE}/tmp-sh-build'
}
failure {
npmGithubPrComment("CI Error:\n\n```\n${shOutput}\n```", true)
}
}
}
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'
} }
} }
} }
post {
always {
sh 'rm -f ${WORKSPACE}/tmp-sh-build'
}
failure {
npmGithubPrComment("CI Error:\n\n```\n${shOutput}\n```", true)
}
}
} }
stage('Integration Tests Sqlite') { stage('Integration Tests') {
steps { parallel {
// Bring up a stack stage('Sqlite') {
sh 'docker-compose up -d fullstack-sqlite' steps {
sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-sqlite) 120' // Bring up a stack
// Stop and Start it, as this will test it's ability to restart with existing data sh 'docker-compose up -d fullstack-sqlite'
sh 'docker-compose stop fullstack-sqlite' sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-sqlite) 120'
sh 'docker-compose start fullstack-sqlite' // Stop and Start it, as this will test it's ability to restart with existing data
sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-sqlite) 120' sh 'docker-compose stop fullstack-sqlite'
sh 'docker-compose start fullstack-sqlite'
sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-sqlite) 120'
// Run tests // Run tests
sh 'rm -rf test/results' sh 'rm -rf test/results-sqlite'
sh 'docker-compose up cypress-sqlite' sh 'docker-compose up cypress-sqlite'
// Get results // 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'
// Cypress videos and screenshot artifacts
dir(path: 'test/results') {
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
} }
junit 'test/results/junit/*' post {
} always {
} // Dumps to analyze later
} sh 'mkdir -p debug/sqlite'
stage('Integration Tests Mysql') { sh 'docker-compose logs fullstack-sqlite > debug/sqlite/docker_fullstack_sqlite.log'
steps { // Cypress videos and screenshot artifacts
// Bring up a stack dir(path: 'test/results-sqlite') {
sh 'docker-compose up -d fullstack-mysql' archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-mysql) 120' }
junit 'test/results-sqlite/junit/*'
// Run tests }
sh 'rm -rf test/results'
sh 'docker-compose up cypress-mysql'
// Get results
sh 'docker cp -L "$(docker-compose ps --all -q cypress-mysql):/test/results" test/'
}
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'
// Cypress videos and screenshot artifacts
dir(path: 'test/results') {
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
} }
junit 'test/results/junit/*'
}
}
}
stage('Docs') {
when {
not {
equals expected: 'UNSTABLE', actual: currentBuild.result
}
}
steps {
dir(path: 'docs') {
sh 'yarn install'
sh 'yarn build'
} }
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'
dir(path: 'docs/.vuepress/dist') { // Run tests
sh 'tar -czf ../../docs.tgz *' sh 'rm -rf test/results-mysql'
sh 'docker-compose up cypress-mysql'
// Get results
sh 'docker cp -L "$(docker-compose ps --all -q cypress-mysql):/test/results" test/results-mysql'
}
post {
always {
// Dumps to analyze later
sh 'mkdir -p debug/mysql'
sh 'docker-compose logs fullstack-mysql > debug/mysql/docker_fullstack_mysql.log'
sh 'docker-compose logs db > debug/mysql/docker_db.log'
// Cypress videos and screenshot artifacts
dir(path: 'test/results-mysql') {
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
}
junit 'test/results-mysql/junit/*'
}
}
} }
archiveArtifacts(artifacts: 'docs/docs.tgz', allowEmptyArchive: false)
} }
} }
stage('MultiArch Build') { stage('MultiArch Build') {
@ -174,31 +183,48 @@ pipeline {
} }
} }
} }
stage('Docs Deploy') { stage('Docs / Comment') {
when { parallel {
allOf { stage('Master Docs') {
branch 'master' when {
not { allOf {
equals expected: 'UNSTABLE', actual: currentBuild.result branch 'master'
not {
equals expected: 'UNSTABLE', actual: currentBuild.result
}
}
}
steps {
npmDocsReleaseMaster()
} }
} }
} stage('Develop Docs') {
steps { when {
npmDocsRelease("$DOCS_BUCKET", "$DOCS_CDN") allOf {
} branch 'develop'
} not {
stage('PR Comment') { equals expected: 'UNSTABLE', actual: currentBuild.result
when { }
allOf { }
changeRequest() }
not { steps {
equals expected: 'UNSTABLE', actual: currentBuild.result npmDocsReleaseDevelop()
} }
} }
} stage('PR Comment') {
steps { when {
script { allOf {
npmGithubPrComment("Docker Image for build ${BUILD_NUMBER} is available on [DockerHub](https://cloud.docker.com/repository/docker/jc21/${IMAGE}) as `jc21/${IMAGE}:github-${BRANCH_LOWER}`\n\n**Note:** ensure you backup your NPM instance before testing this PR image! Especially if this PR contains database changes.", true) changeRequest()
not {
equals expected: 'UNSTABLE', actual: currentBuild.result
}
}
}
steps {
script {
npmGithubPrComment("Docker Image for build ${BUILD_NUMBER} is available on [DockerHub](https://cloud.docker.com/repository/docker/jc21/${IMAGE}) as `jc21/${IMAGE}:github-${BRANCH_LOWER}`\n\n**Note:** ensure you backup your NPM instance before testing this PR image! Especially if this PR contains database changes.", true)
}
}
} }
} }
} }
@ -214,12 +240,12 @@ pipeline {
sh 'figlet "SUCCESS"' sh 'figlet "SUCCESS"'
} }
failure { failure {
archiveArtifacts(artifacts: 'debug/**.*', allowEmptyArchive: true) archiveArtifacts(artifacts: 'debug/**/*.*', allowEmptyArchive: true)
juxtapose event: 'failure' juxtapose event: 'failure'
sh 'figlet "FAILURE"' sh 'figlet "FAILURE"'
} }
unstable { unstable {
archiveArtifacts(artifacts: 'debug/**.*', allowEmptyArchive: true) archiveArtifacts(artifacts: 'debug/**/*.*', allowEmptyArchive: true)
juxtapose event: 'unstable' juxtapose event: 'unstable'
sh 'figlet "UNSTABLE"' sh 'figlet "UNSTABLE"'
} }

View File

@ -1,7 +1,7 @@
<p align="center"> <p align="center">
<img src="https://nginxproxymanager.com/github.png"> <img src="https://nginxproxymanager.com/github.png">
<br><br> <br><br>
<img src="https://img.shields.io/badge/version-2.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"> <a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge"> <img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge">
</a> </a>
@ -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. 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). 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) 1. [Found a bug?](https://github.com/NginxProxyManager/nginx-proxy-manager/issues)
2. [Discussions](https://github.com/NginxProxyManager/nginx-proxy-manager/discussions) 2. [Discussions](https://github.com/NginxProxyManager/nginx-proxy-manager/discussions)
3. [Development Gitter](https://gitter.im/nginx-proxy-manager/community) 3. [Reddit](https://reddit.com/r/nginxproxymanager)
4. [Reddit](https://reddit.com/r/nginxproxymanager)

View File

@ -8,6 +8,7 @@ const config = require('../lib/config');
const error = require('../lib/error'); const error = require('../lib/error');
const utils = require('../lib/utils'); const utils = require('../lib/utils');
const certificateModel = require('../models/certificate'); const certificateModel = require('../models/certificate');
const tokenModel = require('../models/token');
const dnsPlugins = require('../global/certbot-dns-plugins'); const dnsPlugins = require('../global/certbot-dns-plugins');
const internalAuditLog = require('./audit-log'); const internalAuditLog = require('./audit-log');
const internalNginx = require('./nginx'); const internalNginx = require('./nginx');
@ -26,10 +27,11 @@ function omissions() {
const internalCertificate = { const internalCertificate = {
allowedSslFiles: ['certificate', 'certificate_key', 'intermediate_certificate'], allowedSslFiles: ['certificate', 'certificate_key', 'intermediate_certificate'],
intervalTimeout: 1000 * 60 * 60, // 1 hour intervalTimeout: 1000 * 60 * 60, // 1 hour
interval: null, interval: null,
intervalProcessing: false, intervalProcessing: false,
renewBeforeExpirationBy: [30, 'days'],
initTimer: () => { initTimer: () => {
logger.info('Let\'s Encrypt Renewal Timer initialized'); logger.info('Let\'s Encrypt Renewal Timer initialized');
@ -44,62 +46,51 @@ const internalCertificate = {
processExpiringHosts: () => { processExpiringHosts: () => {
if (!internalCertificate.intervalProcessing) { if (!internalCertificate.intervalProcessing) {
internalCertificate.intervalProcessing = true; 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 ' + const expirationThreshold = moment().add(internalCertificate.renewBeforeExpirationBy[0], internalCertificate.renewBeforeExpirationBy[1]).format('YYYY-MM-DD HH:mm:ss');
'--config "' + letsencryptConfig + '" ' +
'--work-dir "/tmp/letsencrypt-lib" ' +
'--logs-dir "/tmp/letsencrypt-log" ' +
'--preferred-challenges "dns,http" ' +
'--disable-hook-validation ' +
(letsencryptStaging ? '--staging' : '');
return utils.exec(cmd) // Fetch all the letsencrypt certs from the db that will expire within the configured threshold
.then((result) => { certificateModel
if (result) { .query()
logger.info('Renew Result: ' + result); .where('is_deleted', 0)
.andWhere('provider', 'letsencrypt')
.andWhere('expires_on', '<', expirationThreshold)
.then((certificates) => {
if (!certificates || !certificates.length) {
return null;
} }
return internalNginx.reload() /**
.then(() => { * Renews must be run sequentially or we'll get an error 'Another
logger.info('Renew Complete'); * instance of Certbot is already running.'
return result; */
}); let sequence = Promise.resolve();
})
.then(() => { certificates.forEach(function (certificate) {
// Now go and fetch all the letsencrypt certs from the db and query the files and update expiry times sequence = sequence.then(() =>
return certificateModel internalCertificate
.query() .renew(
.where('is_deleted', 0) {
.andWhere('provider', 'letsencrypt') can: () =>
.then((certificates) => { Promise.resolve({
if (certificates && certificates.length) { permission_visibility: 'all',
let promises = []; }),
token: new tokenModel(),
certificates.map(function (certificate) { },
promises.push( { id: certificate.id },
internalCertificate.getCertificateInfoFromFile('/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem') )
.then((cert_info) => { .catch((err) => {
return certificateModel // Don't want to stop the train here, just log the error
.query() logger.error(err.message);
.where('id', certificate.id) }),
.andWhere('provider', 'letsencrypt') );
.patch({ });
expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss')
}); return sequence;
})
.catch((err) => {
// Don't want to stop the train here, just log the error
logger.error(err.message);
})
);
});
return Promise.all(promises);
}
});
}) })
.then(() => { .then(() => {
logger.info('Completed SSL cert renew process');
internalCertificate.intervalProcessing = false; internalCertificate.intervalProcessing = false;
}) })
.catch((err) => { .catch((err) => {
@ -908,6 +899,10 @@ const internalCertificate = {
mainCmd = 'AWS_CONFIG_FILE=\'' + credentialsLocation + '\' ' + mainCmd; 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}`); logger.info('Command:', `${credentialsCmd} && ${prepareCmd} && ${mainCmd}`);
return utils.exec(credentialsCmd) 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(', ')}`); 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 + '" ' + '--config "' + letsencryptConfig + '" ' +
'--work-dir "/tmp/letsencrypt-lib" ' + '--work-dir "/tmp/letsencrypt-lib" ' +
'--logs-dir "/tmp/letsencrypt-log" ' + '--logs-dir "/tmp/letsencrypt-log" ' +
@ -1046,6 +1041,8 @@ const internalCertificate = {
const mainCmd = certbotCommand + ' revoke ' + const mainCmd = certbotCommand + ' revoke ' +
'--config "' + letsencryptConfig + '" ' + '--config "' + letsencryptConfig + '" ' +
'--work-dir "/tmp/letsencrypt-lib" ' +
'--logs-dir "/tmp/letsencrypt-log" ' +
'--cert-path "/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' + '--cert-path "/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' +
'--delete-after-revoke ' + '--delete-after-revoke ' +
(letsencryptStaging ? '--staging' : ''); (letsencryptStaging ? '--staging' : '');
@ -1163,6 +1160,7 @@ const internalCertificate = {
const options = { const options = {
method: 'POST', method: 'POST',
headers: { headers: {
'User-Agent': 'Mozilla/5.0',
'Content-Type': 'application/x-www-form-urlencoded', 'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(formBody) 'Content-Length': Buffer.byteLength(formBody)
} }
@ -1175,12 +1173,22 @@ const internalCertificate = {
res.on('data', (chunk) => responseBody = responseBody + chunk); res.on('data', (chunk) => responseBody = responseBody + chunk);
res.on('end', function () { res.on('end', function () {
const parsedBody = JSON.parse(responseBody + ''); try {
if (res.statusCode !== 200) { const parsedBody = JSON.parse(responseBody + '');
logger.warn(`Failed to test HTTP challenge for domain ${domain}`, res); if (res.statusCode !== 200) {
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(undefined);
} }
resolve(parsedBody);
}); });
}); });
@ -1194,6 +1202,9 @@ const internalCertificate = {
if (!result) { if (!result) {
// Some error occurred while trying to get the data // Some error occurred while trying to get the data
return 'failed'; 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') { } else if (`${result.responsecode}` === '200' && result.htmlresponse === 'Success') {
// Server exists and has responded with the correct data // Server exists and has responded with the correct data
return 'ok'; return 'ok';

View File

@ -225,7 +225,7 @@ const internalProxyHost = {
.query() .query()
.where('is_deleted', 0) .where('is_deleted', 0)
.andWhere('id', data.id) .andWhere('id', data.id)
.allowGraph('[owner,access_list,access_list.[clients,items],certificate]') .allowGraph('[owner,access_list.[clients,items],certificate]')
.first(); .first();
if (access_data.permission_visibility !== 'all') { if (access_data.permission_visibility !== 'all') {

View File

@ -172,7 +172,7 @@
"description": "Domain Names separated by a comma", "description": "Domain Names separated by a comma",
"example": "*.jc21.com,blog.jc21.com", "example": "*.jc21.com,blog.jc21.com",
"type": "array", "type": "array",
"maxItems": 15, "maxItems": 30,
"uniqueItems": true, "uniqueItems": true,
"items": { "items": {
"type": "string", "type": "string",

View File

@ -2,7 +2,7 @@
{% if ssl_forced == 1 or ssl_forced == true %} {% if ssl_forced == 1 or ssl_forced == true %}
{% if hsts_enabled == 1 or hsts_enabled == true %} {% if hsts_enabled == 1 or hsts_enabled == true %}
# HSTS (ngx_http_headers_module is required) (63072000 seconds = 2 years) # 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 %} {% endif %}
{% endif %} {% endif %}

View File

@ -0,0 +1,3 @@
map $scheme $hsts_header {
https "max-age=63072000;{% if hsts_subdomains == 1 or hsts_subdomains == true -%} includeSubDomains;{% endif %} preload";
}

View File

@ -5,9 +5,9 @@
#listen [::]:80; #listen [::]:80;
{% endif %} {% endif %}
{% if certificate -%} {% 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 -%} {% if ipv6 -%}
listen [::]:443 ssl{% if http2_support %} http2{% endif %}; listen [::]:443 ssl{% if http2_support == 1 or http2_support == true %} http2{% endif %};
{% else -%} {% else -%}
#listen [::]:443; #listen [::]:443;
{% endif %} {% endif %}

View File

@ -1,3 +1,5 @@
{% include "_hsts_map.conf" %}
location {{ path }} { location {{ path }} {
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Forwarded-Scheme $scheme; proxy_set_header X-Forwarded-Scheme $scheme;

View File

@ -1,6 +1,9 @@
{% include "_header_comment.conf" %} {% include "_header_comment.conf" %}
{% if enabled %} {% if enabled %}
{% include "_hsts_map.conf" %}
server { server {
{% include "_listen.conf" %} {% include "_listen.conf" %}
{% include "_certificates.conf" %} {% include "_certificates.conf" %}

View File

@ -1,6 +1,9 @@
{% include "_header_comment.conf" %} {% include "_header_comment.conf" %}
{% if enabled %} {% if enabled %}
{% include "_hsts_map.conf" %}
server { server {
set $forward_scheme {{ forward_scheme }}; set $forward_scheme {{ forward_scheme }};
set $server "{{ forward_host }}"; set $server "{{ forward_host }}";

View File

@ -1,6 +1,9 @@
{% include "_header_comment.conf" %} {% include "_header_comment.conf" %}
{% if enabled %} {% if enabled %}
{% include "_hsts_map.conf" %}
server { server {
{% include "_listen.conf" %} {% include "_listen.conf" %}
{% include "_certificates.conf" %} {% include "_certificates.conf" %}

View File

@ -3,7 +3,7 @@
# This file assumes that the frontend has been built using ./scripts/frontend-build # This file assumes that the frontend has been built using ./scripts/frontend-build
FROM jc21/nginx-full:certbot-node FROM nginxproxymanager/nginx-full:certbot-node
ARG TARGETPLATFORM ARG TARGETPLATFORM
ARG BUILD_VERSION ARG BUILD_VERSION
@ -20,7 +20,8 @@ ENV SUPPRESS_NO_CONFIG_WARNING=1 \
NODE_ENV=production \ NODE_ENV=production \
NPM_BUILD_VERSION="${BUILD_VERSION}" \ NPM_BUILD_VERSION="${BUILD_VERSION}" \
NPM_BUILD_COMMIT="${BUILD_COMMIT}" \ 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 \ RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
&& apt-get update \ && apt-get update \
@ -47,11 +48,9 @@ COPY docker/rootfs /
# Remove frontend service not required for prod, dev nginx config as well # 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 \ 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 \ && chmod 644 /etc/logrotate.d/nginx-proxy-manager
&& pip uninstall --yes setuptools \
&& pip install --no-cache-dir "setuptools==58.0.0"
VOLUME [ "/data", "/etc/letsencrypt" ] VOLUME [ "/data" ]
ENTRYPOINT [ "/init" ] ENTRYPOINT [ "/init" ]
LABEL org.label-schema.schema-version="1.0" \ LABEL org.label-schema.schema-version="1.0" \

View File

@ -1,4 +1,4 @@
FROM jc21/nginx-full:certbot-node FROM nginxproxymanager/nginx-full:certbot-node
LABEL maintainer="Jamie Curnow <jc@jc21.com>" LABEL maintainer="Jamie Curnow <jc@jc21.com>"
# See: https://github.com/just-containers/s6-overlay/blob/master/README.md # 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_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
S6_FIX_ATTRS_HIDDEN=1 \ S6_FIX_ATTRS_HIDDEN=1 \
S6_KILL_FINISH_MAXTIME=10000 \ 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 \ RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
&& apt-get update \ && apt-get update \

View File

@ -14,7 +14,8 @@ services:
DB_MYSQL_PASSWORD: 'npm' DB_MYSQL_PASSWORD: 'npm'
DB_MYSQL_NAME: 'npm' DB_MYSQL_NAME: 'npm'
volumes: volumes:
- npm_data:/data - npm_data_mysql:/data
- npm_le_mysql:/etc/letsencrypt
expose: expose:
- 81 - 81
- 80 - 80
@ -22,7 +23,7 @@ services:
depends_on: depends_on:
- db - db
healthcheck: healthcheck:
test: ["CMD", "/bin/check-health"] test: ["CMD", "/usr/bin/check-health"]
interval: 10s interval: 10s
timeout: 3s timeout: 3s
@ -37,13 +38,14 @@ services:
PGID: 1000 PGID: 1000
DISABLE_IPV6: 'true' DISABLE_IPV6: 'true'
volumes: volumes:
- npm_data:/data - npm_data_sqlite:/data
- npm_le_sqlite:/etc/letsencrypt
expose: expose:
- 81 - 81
- 80 - 80
- 443 - 443
healthcheck: healthcheck:
test: ["CMD", "/bin/check-health"] test: ["CMD", "/usr/bin/check-health"]
interval: 10s interval: 10s
timeout: 3s timeout: 3s
@ -55,7 +57,7 @@ services:
MYSQL_USER: 'npm' MYSQL_USER: 'npm'
MYSQL_PASSWORD: 'npm' MYSQL_PASSWORD: 'npm'
volumes: volumes:
- db_data:/var/lib/mysql - mysql_data:/var/lib/mysql
cypress-mysql: cypress-mysql:
image: "${IMAGE}-cypress:ci-${BUILD_NUMBER}" image: "${IMAGE}-cypress:ci-${BUILD_NUMBER}"
@ -65,7 +67,7 @@ services:
environment: environment:
CYPRESS_baseUrl: 'http://fullstack-mysql:81' CYPRESS_baseUrl: 'http://fullstack-mysql:81'
volumes: volumes:
- cypress-logs:/results - cypress_logs_mysql:/results
command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json} command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json}
cypress-sqlite: cypress-sqlite:
@ -76,10 +78,14 @@ services:
environment: environment:
CYPRESS_baseUrl: "http://fullstack-sqlite:81" CYPRESS_baseUrl: "http://fullstack-sqlite:81"
volumes: volumes:
- cypress-logs:/results - cypress_logs_sqlite:/results
command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json} command: cypress run --browser chrome --config-file=${CYPRESS_CONFIG:-cypress/config/ci.json}
volumes: volumes:
cypress-logs: cypress_logs_mysql:
npm_data: cypress_logs_sqlite:
db_data: npm_data_mysql:
npm_data_sqlite:
npm_le_sqlite:
npm_le_mysql:
mysql_data:

View File

@ -1,5 +1,6 @@
/data/logs/*_access.log /data/logs/*/access.log { /data/logs/*_access.log /data/logs/*/access.log {
create 0644 root root su npm npm
create 0644
weekly weekly
rotate 4 rotate 4
missingok missingok
@ -12,7 +13,8 @@
} }
/data/logs/*_error.log /data/logs/*/error.log { /data/logs/*_error.log /data/logs/*/error.log {
create 0644 root root su npm npm
create 0644
weekly weekly
rotate 10 rotate 10
missingok missingok

View File

@ -1,3 +1,10 @@
set $test "";
if ($scheme = "http") { 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; return 301 https://$host$request_uri;
} }

View File

@ -3,7 +3,7 @@
set -e set -e
. /bin/common.sh . /usr/bin/common.sh
cd /app || exit 1 cd /app || exit 1

View File

@ -6,7 +6,7 @@ set -e
# This service is DEVELOPMENT only. # This service is DEVELOPMENT only.
if [ "$DEVELOPMENT" = 'true' ]; then if [ "$DEVELOPMENT" = 'true' ]; then
. /bin/common.sh . /usr/bin/common.sh
cd /app/frontend || exit 1 cd /app/frontend || exit 1
HOME=$NPMHOME HOME=$NPMHOME
export HOME export HOME

View File

@ -3,7 +3,7 @@
set -e set -e
. /bin/common.sh . /usr/bin/common.sh
log_info 'Starting nginx ...' log_info 'Starting nginx ...'
exec s6-setuidgid "$PUID:$PGID" nginx exec s6-setuidgid "$PUID:$PGID" nginx

View File

@ -3,7 +3,7 @@
set -e set -e
. /bin/common.sh . /usr/bin/common.sh
if [ "$(id -u)" != "0" ]; then 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." 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."

View File

@ -24,4 +24,4 @@ chown -R "$PUID:$PGID" /etc/nginx/nginx.conf
chown -R "$PUID:$PGID" /etc/nginx/conf.d chown -R "$PUID:$PGID" /etc/nginx/conf.d
# Prevents errors when installing python certbot plugins when non-root # 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

View File

@ -12,6 +12,10 @@ export CYAN BLUE YELLOW RED RESET
PUID=${PUID:-0} PUID=${PUID:-0}
PGID=${PGID:-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 NPMUSER=npm
NPMGROUP=npm NPMGROUP=npm
NPMHOME=/tmp/npmuserhome NPMHOME=/tmp/npmuserhome

10
docs/.gitignore vendored
View File

@ -1,3 +1,13 @@
.vuepress/dist .vuepress/dist
node_modules node_modules
ts ts
.temp
.cache
.yarn/*
!.yarn/releases
!.yarn/plugins
!.yarn/sdks
!.yarn/versions
*.gz
*.tgz

View File

@ -1,82 +1,120 @@
module.exports = { import { defineUserConfig } from 'vuepress';
locales: { import { defaultTheme } from 'vuepress'
"/": { import { googleAnalyticsPlugin } from '@vuepress/plugin-google-analytics';
lang: "en-US", import { searchPlugin } from '@vuepress/plugin-search'
title: "Nginx Proxy Manager", import { sitemapPlugin } from 'vuepress-plugin-sitemap2';
description: "Expose your services easily and securely" import zoomingPlugin from 'vuepress-plugin-zooming';
}
}, export default defineUserConfig({
head: [ locales: {
["link", { rel: "icon", href: "/icon.png" }], "/": {
["meta", { name: "description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt" }], lang: "en-US",
["meta", { property: "og:title", content: "Nginx Proxy Manager" }], title: "Nginx Proxy Manager",
["meta", { property: "og:description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt"}], description: "Expose your services easily and securely",
["meta", { property: "og:type", content: "website" }], },
["meta", { property: "og:url", content: "https://nginxproxymanager.com/" }], },
["meta", { property: "og:image", content: "https://nginxproxymanager.com/icon.png" }], head: [
["meta", { name: "twitter:card", content: "summary"}], ["link", { rel: "icon", href: "/icon.png" }],
["meta", { name: "twitter:title", content: "Nginx Proxy Manager"}], ["meta", { name: "description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt" }],
["meta", { name: "twitter:description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt"}], ["meta", { property: "og:title", content: "Nginx Proxy Manager" }],
["meta", { name: "twitter:image", content: "https://nginxproxymanager.com/icon.png"}], ["meta", { property: "og:description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt"}],
["meta", { name: "twitter:alt", content: "Nginx Proxy Manager"}], ["meta", { property: "og:type", content: "website" }],
], ["meta", { property: "og:url", content: "https://nginxproxymanager.com/" }],
themeConfig: { ["meta", { property: "og:image", content: "https://nginxproxymanager.com/icon.png" }],
logo: "/icon.png", ["meta", { name: "twitter:card", content: "summary"}],
// the GitHub repo path ["meta", { name: "twitter:title", content: "Nginx Proxy Manager"}],
repo: "jc21/nginx-proxy-manager", ["meta", { name: "twitter:description", content: "Docker container and built in Web Application for managing Nginx proxy hosts with a simple, powerful interface, providing free SSL support via Let's Encrypt"}],
// the label linking to the repo ["meta", { name: "twitter:image", content: "https://nginxproxymanager.com/icon.png"}],
repoLabel: "GitHub", ["meta", { name: "twitter:alt", content: "Nginx Proxy Manager"}],
// if your docs are not at the root of the repo: ],
docsDir: "docs", theme: defaultTheme({
// defaults to false, set to true to enable logo: '/icon.png',
editLinks: true, repo: "jc21/nginx-proxy-manager",
locales: { docsRepo: 'https://github.com/jc21/nginx-proxy-manager',
"/": { docsBranch: 'develop',
// text for the language dropdown docsDir: 'docs',
selectText: "Languages", editLinkPattern: ':repo/edit/:branch/:path',
// label for this locale in the language dropdown locales: {
label: "English", '/': {
// Custom text for edit link. Defaults to "Edit this page" label: 'English',
editLinkText: "Edit this page on GitHub", selectLanguageText: 'Languages',
// Custom navbar values selectLanguageName: 'English',
nav: [{ text: "Setup", link: "/setup/" }], editLinkText: 'Edit this page on GitHub',
// Custom sidebar values navbar: [
sidebar: [ { text: 'Setup', link: '/setup/' }
"/", ],
["/guide/", "Guide"], sidebar: {
["/screenshots/", "Screenshots"], '/': [
["/setup/", "Setup Instructions"], {
["/advanced-config/", "Advanced Configuration"], text: 'Home',
["/upgrading/", "Upgrading"], link: '/'
["/faq/", "Frequently Asked Questions"], },
["/third-party/", "Third Party"] {
] text: 'Guide',
} link: '/guide/',
} collapsible: true,
}, },
plugins: [ {
[ text: 'Screenshots',
"@vuepress/google-analytics", link: '/screenshots/',
{ collapsible: true,
ga: "UA-99675467-4" },
} {
], text: 'Setup Instructions',
[ link: '/setup/',
"sitemap", collapsible: true,
{ },
hostname: "https://nginxproxymanager.com" {
} text: 'Advanced Configuration',
], link: '/advanced-config/',
[ collapsible: true,
'vuepress-plugin-zooming', },
{ {
selector: '.zooming', text: 'Upgrading',
delay: 1000, link: '/upgrading/',
options: { collapsible: true,
bgColor: 'black', },
zIndex: 10000, {
}, text: 'Frequently Asked Questions',
}, link: '/faq/',
], collapsible: true,
] },
}; {
text: 'Third Party',
link: '/third-party/',
collapsible: true,
},
],
},
}
}
}),
markdown: {
code: {
lineNumbers: false,
},
},
plugins: [
googleAnalyticsPlugin({
id: 'UA-99675467-4'
}),
sitemapPlugin({
hostname: "https://nginxproxymanager.com",
}),
zoomingPlugin({
selector: '.zooming',
delay: 1000,
options: {
bgColor: 'black',
zIndex: 10000,
},
}),
searchPlugin({
locales: {
'/': {
placeholder: 'Search',
},
},
}),
],
});

View 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;
}

View File

@ -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;

View File

@ -1,4 +0,0 @@
$accentColor = #f15833
$textColor = #663015
$borderColor = #eaecef
$codeBgColor = #282c34

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
View File

@ -0,0 +1,3 @@
nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-4.0.2.cjs

View File

@ -1,8 +1,10 @@
--- ---
home: true home: true
heroImage: /logo.png heroImage: /logo.png
actionText: Get Started → actions:
actionLink: /guide/ - text: Get Started
link: /guide/
type: primary
footer: MIT Licensed | Copyright © 2016-present jc21.com footer: MIT Licensed | Copyright © 2016-present jc21.com
--- ---

View File

@ -76,7 +76,7 @@ feature by adding the following to the service in your `docker-compose.yml` file
```yml ```yml
healthcheck: healthcheck:
test: ["CMD", "/bin/check-health"] test: ["CMD", "/usr/bin/check-health"]
interval: 10s interval: 10s
timeout: 3s timeout: 3s
``` ```
@ -138,6 +138,7 @@ services:
MYSQL_USER: "npm" MYSQL_USER: "npm"
# MYSQL_PASSWORD: "npm" # use secret instead # MYSQL_PASSWORD: "npm" # use secret instead
MYSQL_PASSWORD__FILE: /run/secrets/MYSQL_PWD MYSQL_PASSWORD__FILE: /run/secrets/MYSQL_PWD
MARIADB_AUTO_UPGRADE: '1'
volumes: volumes:
- ./mysql:/var/lib/mysql - ./mysql:/var/lib/mysql
secrets: secrets:
@ -193,3 +194,17 @@ value by specifying it as a Docker environment variable. The default if not spec
X_FRAME_OPTIONS: "sameorigin" 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).

View File

@ -3,775 +3,21 @@
"version": "1.0.0", "version": "1.0.0",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"dependencies": { "devDependencies": {
"@vuepress/plugin-google-analytics": "^1.5.3", "vuepress": "^2.0.0-rc.0"
"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": {},
"scripts": { "scripts": {
"dev": "vuepress dev", "dev": "vuepress dev",
"build": "vuepress build" "build": "vuepress build"
}, },
"author": "", "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"
}
} }

View File

@ -86,6 +86,7 @@ services:
MYSQL_DATABASE: 'npm' MYSQL_DATABASE: 'npm'
MYSQL_USER: 'npm' MYSQL_USER: 'npm'
MYSQL_PASSWORD: 'npm' MYSQL_PASSWORD: 'npm'
MARIADB_AUTO_UPGRADE: '1'
volumes: volumes:
- ./mysql:/var/lib/mysql - ./mysql:/var/lib/mysql
``` ```

View File

@ -7,7 +7,7 @@ Known integrations:
- [HomeAssistant Hass.io plugin](https://github.com/hassio-addons/addon-nginx-proxy-manager) - [HomeAssistant Hass.io plugin](https://github.com/hassio-addons/addon-nginx-proxy-manager)
- [UnRaid / Synology](https://github.com/jlesage/docker-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) - [nginxproxymanagerGraf](https://github.com/ma-karai/nginxproxymanagerGraf)

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,7 @@
<meta name="mobile-web-app-capable" content="yes"> <meta name="mobile-web-app-capable" content="yes">
<meta name="HandheldFriendly" content="True"> <meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320"> <meta name="MobileOptimized" content="320">
<meta name="robots" content="noindex">
<title><%- title %></title> <title><%- title %></title>
<link rel="apple-touch-icon" sizes="180x180" href="/images/favicons/apple-touch-icon.png"> <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"> <link rel="icon" type="image/png" sizes="32x32" href="/images/favicons/favicon-32x32.png">

View File

@ -265,7 +265,7 @@ module.exports = Mn.View.extend({
this.ui.domain_names.selectize({ this.ui.domain_names.selectize({
delimiter: ',', delimiter: ',',
persist: false, persist: false,
maxOptions: 15, maxOptions: 30,
create: function (input) { create: function (input) {
return { return {
value: input, value: input,

View File

@ -233,7 +233,7 @@ module.exports = Mn.View.extend({
this.ui.domain_names.selectize({ this.ui.domain_names.selectize({
delimiter: ',', delimiter: ',',
persist: false, persist: false,
maxOptions: 15, maxOptions: 30,
create: function (input) { create: function (input) {
return { return {
value: input, value: input,

View File

@ -271,7 +271,7 @@ module.exports = Mn.View.extend({
this.ui.domain_names.selectize({ this.ui.domain_names.selectize({
delimiter: ',', delimiter: ',',
persist: false, persist: false,
maxOptions: 15, maxOptions: 30,
create: function (input) { create: function (input) {
return { return {
value: input, value: input,

View File

@ -45,7 +45,7 @@
<div class="col-sm-4 col-md-4"> <div class="col-sm-4 col-md-4">
<div class="form-group"> <div class="form-group">
<label class="form-label"><%- i18n('proxy-hosts', 'forward-port') %> <span class="form-required">*</span></label> <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> </div>
</div> </div>

View File

@ -235,7 +235,7 @@ module.exports = Mn.View.extend({
this.ui.domain_names.selectize({ this.ui.domain_names.selectize({
delimiter: ',', delimiter: ',',
persist: false, persist: false,
maxOptions: 15, maxOptions: 30,
create: function (input) { create: function (input) {
return { return {
value: input, value: input,

View File

@ -9,7 +9,7 @@
<div class="col-sm-12 col-md-12"> <div class="col-sm-12 col-md-12">
<div class="form-group"> <div class="form-group">
<label class="form-label"><%- i18n('streams', 'incoming-port') %> <span class="form-required">*</span></label> <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> </div>
<div class="col-sm-8 col-md-8"> <div class="col-sm-8 col-md-8">
@ -21,7 +21,7 @@
<div class="col-sm-4 col-md-4"> <div class="col-sm-4 col-md-4">
<div class="form-group"> <div class="form-group">
<label class="form-label"><%- i18n('streams', 'forwarding-port') %> <span class="form-required">*</span></label> <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> </div>
<div class="col-sm-6 col-md-6"> <div class="col-sm-6 col-md-6">

View File

@ -8,7 +8,7 @@
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-12"> <div class="col-sm-12 col-md-12">
<div class="form-group"> <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"> <div class="custom-controls-stacked">
<label class="custom-control custom-radio"> <label class="custom-control custom-radio">
<input class="custom-control-input" name="value" value="congratulations" type="radio" required <%- value === 'congratulations' ? 'checked' : '' %>> <input class="custom-control-input" name="value" value="congratulations" type="radio" required <%- value === 'congratulations' ? 'checked' : '' %>>

View File

@ -1,7 +1,7 @@
<td> <td>
<div><%- name %></div> <div><%- i18n('settings', 'default-site') %></div>
<div class="small text-muted"> <div class="small text-muted">
<%- description %> <%- i18n('settings', 'default-site-description') %>
</div> </div>
</td> </td>
<td> <td>

View File

@ -60,7 +60,7 @@
}, },
"footer": { "footer": {
"fork-me": "Fork me on Github", "fork-me": "Fork me on Github",
"copy": "&copy; 2023 <a href=\"{url}\" target=\"_blank\">jc21.com</a>.", "copy": "&copy; 2024 <a href=\"{url}\" target=\"_blank\">jc21.com</a>.",
"theme": "Theme by <a href=\"{url}\" target=\"_blank\">Tabler</a>" "theme": "Theme by <a href=\"{url}\" target=\"_blank\">Tabler</a>"
}, },
"dashboard": { "dashboard": {
@ -285,6 +285,7 @@
"settings": { "settings": {
"title": "Settings", "title": "Settings",
"default-site": "Default Site", "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-congratulations": "Congratulations Page",
"default-site-404": "404 Page", "default-site-404": "404 Page",
"default-site-444": "No Response (444)", "default-site-444": "No Response (444)",

View File

@ -27,10 +27,10 @@
"messageformat-loader": "^0.8.1", "messageformat-loader": "^0.8.1",
"mini-css-extract-plugin": "^0.9.0", "mini-css-extract-plugin": "^0.9.0",
"moment": "^2.29.4", "moment": "^2.29.4",
"node-sass": "^6.0.1", "node-sass": "^9.0.0",
"nodemon": "^2.0.2", "nodemon": "^2.0.2",
"numeral": "^2.0.6", "numeral": "^2.0.6",
"sass-loader": "10.2.0", "sass-loader": "^10.0.0",
"style-loader": "^1.1.3", "style-loader": "^1.1.3",
"tabler-ui": "git+https://github.com/tabler/tabler.git#00f78ad823311bc3ad974ac3e5b0126198f0a813", "tabler-ui": "git+https://github.com/tabler/tabler.git#00f78ad823311bc3ad974ac3e5b0126198f0a813",
"underscore": "^1.12.1", "underscore": "^1.12.1",

File diff suppressed because it is too large Load Diff

View File

@ -254,13 +254,10 @@ dns_eurodns_endpoint = https://rest-api.eurodns.com/user-api-gateway/proxy`,
gandi: { gandi: {
display_name: 'Gandi Live DNS', display_name: 'Gandi Live DNS',
package_name: 'certbot_plugin_gandi', package_name: 'certbot_plugin_gandi',
version_requirement: '~=1.3.2', version_requirement: '~=1.5.0',
dependencies: '', dependencies: '',
credentials: `# live dns v5 api key credentials: `# Gandi personal access token
dns_gandi_api_key=APIKEY dns_gandi_token=PERSONAL_ACCESS_TOKEN`,
# optional organization id, remove it if not used
dns_gandi_sharing_id=SHARINGID`,
full_plugin_name: 'dns-gandi', full_plugin_name: 'dns-gandi',
}, },
//####################################################// //####################################################//
@ -296,6 +293,16 @@ dns_google_domains_zone = "example.com"`,
full_plugin_name: 'dns-google-domains', 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: { hetzner: {
display_name: 'Hetzner', display_name: 'Hetzner',
package_name: 'certbot-dns-hetzner', package_name: 'certbot-dns-hetzner',
@ -472,6 +479,17 @@ dns_ovh_consumer_key = MDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAw`,
full_plugin_name: 'dns-ovh', 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: { porkbun: {
display_name: 'Porkbun', display_name: 'Porkbun',
package_name: 'certbot-dns-porkbun', package_name: 'certbot-dns-porkbun',
@ -538,9 +556,20 @@ aws_secret_access_key=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY`,
dependencies: '', dependencies: '',
credentials: `dns_strato_username = user credentials: `dns_strato_username = user
dns_strato_password = pass 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 # uncomment if domain name contains special characters
# insert domain display name as seen on your account page here # 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', full_plugin_name: 'dns-strato',
}, },
//####################################################// //####################################################//
@ -557,7 +586,7 @@ dns_transip_key_file = /etc/letsencrypt/transip-rsa.key`,
tencentcloud: { tencentcloud: {
display_name: 'Tencent Cloud', display_name: 'Tencent Cloud',
package_name: 'certbot-dns-tencentcloud', package_name: 'certbot-dns-tencentcloud',
version_requirement: '~=2.0.0', version_requirement: '~=2.0.2',
dependencies: '', dependencies: '',
credentials: `dns_tencentcloud_secret_id = TENCENT_CLOUD_SECRET_ID credentials: `dns_tencentcloud_secret_id = TENCENT_CLOUD_SECRET_ID
dns_tencentcloud_secret_key = TENCENT_CLOUD_SECRET_KEY`, dns_tencentcloud_secret_key = TENCENT_CLOUD_SECRET_KEY`,
@ -567,7 +596,7 @@ dns_tencentcloud_secret_key = TENCENT_CLOUD_SECRET_KEY`,
vultr: { vultr: {
display_name: 'Vultr', display_name: 'Vultr',
package_name: 'certbot-dns-vultr', package_name: 'certbot-dns-vultr',
version_requirement: '~=1.0.3', version_requirement: '~=1.1.0',
dependencies: '', dependencies: '',
credentials: 'dns_vultr_key = YOUR_VULTR_API_KEY', credentials: 'dns_vultr_key = YOUR_VULTR_API_KEY',
full_plugin_name: 'dns-vultr', full_plugin_name: 'dns-vultr',

View File

@ -3,14 +3,22 @@
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
. "$DIR/../.common.sh" . "$DIR/../.common.sh"
DOCKER_IMAGE=jc21/nginx-full:certbot-node DOCKER_IMAGE=nginxproxymanager/nginx-full:certbot-node
# Ensure docker exists # Ensure docker exists
if hash docker 2>/dev/null; then if hash docker 2>/dev/null; then
docker pull "${DOCKER_IMAGE}" docker pull "${DOCKER_IMAGE}"
cd "${DIR}/../.." cd "${DIR}/../.."
echo -e "${BLUE} ${CYAN}Building Frontend ...${RESET}" 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}" echo -e "${BLUE} ${GREEN}Building Frontend Complete${RESET}"
else else
echo -e "${RED} docker command is not available${RESET}" echo -e "${RED} docker command is not available${RESET}"

View File

@ -1,23 +1,31 @@
#!/bin/bash -e #!/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}" docker pull "${DOCKER_IMAGE}"
# Test # Test
echo -e "${BLUE} ${CYAN}Testing backend ...${RESET}"
docker run --rm \ docker run --rm \
-v "$(pwd)/backend:/app" \ -v "$(pwd)/backend:/app" \
-v "$(pwd)/global:/app/global" \ -v "$(pwd)/global:/app/global" \
-w /app \ -w /app \
"${DOCKER_IMAGE}" \ "${DOCKER_IMAGE}" \
sh -c 'yarn install && yarn eslint . && rm -rf node_modules' sh -c 'yarn install && yarn eslint . && rm -rf node_modules'
echo -e "${BLUE} ${GREEN}Testing Complete${RESET}"
# Build # 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}" \ -t "${IMAGE}:ci-${BUILD_NUMBER}" \
-f docker/Dockerfile \ -f docker/Dockerfile \
--progress=plain \
--build-arg TARGETPLATFORM=linux/amd64 \ --build-arg TARGETPLATFORM=linux/amd64 \
--build-arg BUILDPLATFORM=linux/amd64 \ --build-arg BUILDPLATFORM=linux/amd64 \
--build-arg BUILD_VERSION="${BUILD_VERSION}" \ --build-arg BUILD_VERSION="${BUILD_VERSION}" \
--build-arg BUILD_COMMIT="${BUILD_COMMIT}" \ --build-arg BUILD_COMMIT="${BUILD_COMMIT}" \
--build-arg BUILD_DATE="$(date '+%Y-%m-%d %T %Z')" \ --build-arg BUILD_DATE="$(date '+%Y-%m-%d %T %Z')" \
. .
echo -e "${BLUE} ${GREEN}Building Complete${RESET}"

View File

@ -7,7 +7,7 @@ DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if hash docker 2>/dev/null; then if hash docker 2>/dev/null; then
cd "${DIR}/.." cd "${DIR}/.."
echo -e "${BLUE} ${CYAN}Building Docs ...${RESET}" 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}" echo -e "${BLUE} ${GREEN}Building Docs Complete${RESET}"
else else
echo -e "${RED} docker command is not available${RESET}" echo -e "${RED} docker command is not available${RESET}"