Skip to content

Commit 35d7a3a

Browse files
authored
Merge pull request #3847 from NginxProxyManager/develop
v2.11.3
2 parents 12d77e3 + 63d06da commit 35d7a3a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1454
-1213
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,7 @@
33
._*
44
.vscode
55
certbot-help.txt
6+
test/node_modules
7+
*/node_modules
8+
docker/dev/dnsrouter-config.json.tmp
9+
docker/dev/resolv.conf

.version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.11.2
1+
2.11.3

Jenkinsfile

+53-70
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,8 @@ pipeline {
1818
BUILD_VERSION = getVersion()
1919
MAJOR_VERSION = '2'
2020
BRANCH_LOWER = "${BRANCH_NAME.toLowerCase().replaceAll('\\\\', '-').replaceAll('/', '-').replaceAll('\\.', '-')}"
21-
COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}"
22-
COMPOSE_FILE = 'docker/docker-compose.ci.yml'
21+
BUILDX_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}"
2322
COMPOSE_INTERACTIVE_NO_CLI = 1
24-
BUILDX_NAME = "${COMPOSE_PROJECT_NAME}"
2523
}
2624
stages {
2725
stage('Environment') {
@@ -94,75 +92,61 @@ pipeline {
9492
}
9593
}
9694
}
97-
stage('Cypress') {
98-
steps {
99-
// Creating will also create the network prior to
100-
// using it in parallel stages below and mitigating
101-
// a race condition.
102-
sh 'docker-compose build cypress-sqlite'
103-
sh 'docker-compose build cypress-mysql'
104-
sh 'docker-compose create cypress-sqlite'
105-
sh 'docker-compose create cypress-mysql'
106-
}
95+
}
96+
}
97+
stage('Test Sqlite') {
98+
environment {
99+
COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}_sqlite"
100+
COMPOSE_FILE = 'docker/docker-compose.ci.yml:docker/docker-compose.ci.sqlite.yml'
101+
}
102+
when {
103+
not {
104+
equals expected: 'UNSTABLE', actual: currentBuild.result
105+
}
106+
}
107+
steps {
108+
sh 'rm -rf ./test/results/junit/*'
109+
sh './scripts/ci/fulltest-cypress'
110+
}
111+
post {
112+
always {
113+
// Dumps to analyze later
114+
sh 'mkdir -p debug/sqlite'
115+
sh 'docker logs $(docker-compose ps --all -q fullstack) > debug/sqlite/docker_fullstack.log 2>&1'
116+
sh 'docker logs $(docker-compose ps --all -q stepca) > debug/sqlite/docker_stepca.log 2>&1'
117+
sh 'docker logs $(docker-compose ps --all -q pdns) > debug/sqlite/docker_pdns.log 2>&1'
118+
sh 'docker logs $(docker-compose ps --all -q pdns-db) > debug/sqlite/docker_pdns-db.log 2>&1'
119+
sh 'docker logs $(docker-compose ps --all -q dnsrouter) > debug/sqlite/docker_dnsrouter.log 2>&1'
120+
junit 'test/results/junit/*'
121+
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
107122
}
108123
}
109124
}
110-
stage('Integration Tests') {
111-
parallel {
112-
stage('Sqlite') {
113-
steps {
114-
// Bring up a stack
115-
sh 'docker-compose up -d fullstack-sqlite'
116-
sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-sqlite) 120'
117-
// Stop and Start it, as this will test it's ability to restart with existing data
118-
sh 'docker-compose stop fullstack-sqlite'
119-
sh 'docker-compose start fullstack-sqlite'
120-
sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-sqlite) 120'
121-
122-
// Run tests
123-
sh 'rm -rf test/results-sqlite'
124-
sh 'docker-compose up cypress-sqlite'
125-
// Get results
126-
sh 'docker cp -L "$(docker-compose ps --all -q cypress-sqlite):/test/results" test/results-sqlite'
127-
}
128-
post {
129-
always {
130-
// Dumps to analyze later
131-
sh 'mkdir -p debug/sqlite'
132-
sh 'docker-compose logs fullstack-sqlite > debug/sqlite/docker_fullstack_sqlite.log'
133-
// Cypress videos and screenshot artifacts
134-
dir(path: 'test/results-sqlite') {
135-
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
136-
}
137-
junit 'test/results-sqlite/junit/*'
138-
}
139-
}
125+
stage('Test Mysql') {
126+
environment {
127+
COMPOSE_PROJECT_NAME = "npm_${BRANCH_LOWER}_${BUILD_NUMBER}_mysql"
128+
COMPOSE_FILE = 'docker/docker-compose.ci.yml:docker/docker-compose.ci.mysql.yml'
129+
}
130+
when {
131+
not {
132+
equals expected: 'UNSTABLE', actual: currentBuild.result
140133
}
141-
stage('Mysql') {
142-
steps {
143-
// Bring up a stack
144-
sh 'docker-compose up -d fullstack-mysql'
145-
sh './scripts/wait-healthy $(docker-compose ps --all -q fullstack-mysql) 120'
146-
147-
// Run tests
148-
sh 'rm -rf test/results-mysql'
149-
sh 'docker-compose up cypress-mysql'
150-
// Get results
151-
sh 'docker cp -L "$(docker-compose ps --all -q cypress-mysql):/test/results" test/results-mysql'
152-
}
153-
post {
154-
always {
155-
// Dumps to analyze later
156-
sh 'mkdir -p debug/mysql'
157-
sh 'docker-compose logs fullstack-mysql > debug/mysql/docker_fullstack_mysql.log'
158-
sh 'docker-compose logs db > debug/mysql/docker_db.log'
159-
// Cypress videos and screenshot artifacts
160-
dir(path: 'test/results-mysql') {
161-
archiveArtifacts allowEmptyArchive: true, artifacts: '**/*', excludes: '**/*.xml'
162-
}
163-
junit 'test/results-mysql/junit/*'
164-
}
165-
}
134+
}
135+
steps {
136+
sh 'rm -rf ./test/results/junit/*'
137+
sh './scripts/ci/fulltest-cypress'
138+
}
139+
post {
140+
always {
141+
// Dumps to analyze later
142+
sh 'mkdir -p debug/mysql'
143+
sh 'docker logs $(docker-compose ps --all -q fullstack) > debug/mysql/docker_fullstack.log 2>&1'
144+
sh 'docker logs $(docker-compose ps --all -q stepca) > debug/mysql/docker_stepca.log 2>&1'
145+
sh 'docker logs $(docker-compose ps --all -q pdns) > debug/mysql/docker_pdns.log 2>&1'
146+
sh 'docker logs $(docker-compose ps --all -q pdns-db) > debug/mysql/docker_pdns-db.log 2>&1'
147+
sh 'docker logs $(docker-compose ps --all -q dnsrouter) > debug/mysql/docker_dnsrouter.log 2>&1'
148+
junit 'test/results/junit/*'
149+
sh 'docker-compose down --remove-orphans --volumes -t 30 || true'
166150
}
167151
}
168152
}
@@ -214,9 +198,8 @@ pipeline {
214198
}
215199
post {
216200
always {
217-
sh 'docker-compose down --remove-orphans --volumes -t 30'
218201
sh 'echo Reverting ownership'
219-
sh 'docker run --rm -v $(pwd):/data jc21/ci-tools chown -R $(id -u):$(id -g) /data'
202+
sh 'docker run --rm -v "$(pwd):/data" jc21/ci-tools chown -R "$(id -u):$(id -g)" /data'
220203
}
221204
success {
222205
juxtapose event: 'success'

README.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<p align="center">
22
<img src="https://nginxproxymanager.com/github.png">
33
<br><br>
4-
<img src="https://img.shields.io/badge/version-2.11.2-green.svg?style=for-the-badge">
4+
<img src="https://img.shields.io/badge/version-2.11.3-green.svg?style=for-the-badge">
55
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
66
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge">
77
</a>
@@ -56,7 +56,6 @@ I won't go in to too much detail here but here are the basics for someone new to
5656
2. Create a docker-compose.yml file similar to this:
5757

5858
```yml
59-
version: '3.8'
6059
services:
6160
app:
6261
image: 'docker.io/jc21/nginx-proxy-manager:latest'

backend/internal/certificate.js

+5-8
Original file line numberDiff line numberDiff line change
@@ -861,9 +861,8 @@ const internalCertificate = {
861861
logger.info(`Requesting Let'sEncrypt certificates via ${dnsPlugin.name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
862862

863863
const credentialsLocation = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
864-
// Escape single quotes and backslashes
865-
const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll('\'', '\\\'').replaceAll('\\', '\\\\');
866-
const credentialsCmd = 'mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
864+
fs.mkdirSync('/etc/letsencrypt/credentials', { recursive: true });
865+
fs.writeFileSync(credentialsLocation, certificate.meta.dns_provider_credentials, {mode: 0o600});
867866

868867
// Whether the plugin has a --<name>-credentials argument
869868
const hasConfigArg = certificate.meta.dns_provider !== 'route53';
@@ -898,17 +897,15 @@ const internalCertificate = {
898897
mainCmd = mainCmd + ' --dns-duckdns-no-txt-restore';
899898
}
900899

901-
logger.info('Command:', `${credentialsCmd} && && ${mainCmd}`);
900+
logger.info('Command:', mainCmd);
902901

903902
try {
904-
await utils.exec(credentialsCmd);
905903
const result = await utils.exec(mainCmd);
906904
logger.info(result);
907905
return result;
908906
} catch (err) {
909-
// Don't fail if file does not exist
910-
const delete_credentialsCmd = `rm -f '${credentialsLocation}' || true`;
911-
await utils.exec(delete_credentialsCmd);
907+
// Don't fail if file does not exist, so no need for action in the callback
908+
fs.unlink(credentialsLocation, () => {});
912909
throw err;
913910
}
914911
},

backend/lib/config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ const generateKeys = () => {
9393
try {
9494
fs.writeFileSync(keysFile, JSON.stringify(keys, null, 2));
9595
} catch (err) {
96-
logger.error('Could not write JWT key pair to config file: ' + keysFile + ': ' . err.message);
96+
logger.error('Could not write JWT key pair to config file: ' + keysFile + ': ' + err.message);
9797
process.exit(1);
9898
}
9999
logger.info('Wrote JWT key pair to config file: ' + keysFile);

backend/setup.js

+6-3
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,14 @@ const setupDefaultUser = () => {
2121
.then((row) => {
2222
if (!row.count) {
2323
// Create a new user and set password
24-
logger.info('Creating a new user: [email protected] with password: changeme');
24+
let email = process.env.INITIAL_ADMIN_EMAIL || '[email protected]';
25+
let password = process.env.INITIAL_ADMIN_PASSWORD || 'changeme';
26+
27+
logger.info('Creating a new user: ' + email + ' with password: ' + password);
2528

2629
let data = {
2730
is_deleted: 0,
28-
31+
email: email,
2932
name: 'Administrator',
3033
nickname: 'Admin',
3134
avatar: '',
@@ -41,7 +44,7 @@ const setupDefaultUser = () => {
4144
.insert({
4245
user_id: user.id,
4346
type: 'password',
44-
secret: 'changeme',
47+
secret: password,
4548
meta: {},
4649
})
4750
.then(() => {

backend/templates/_location.conf

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
location {{ path }} {
2+
{{ advanced_config }}
3+
24
proxy_set_header Host $host;
35
proxy_set_header X-Forwarded-Scheme $scheme;
46
proxy_set_header X-Forwarded-Proto $scheme;
@@ -17,8 +19,5 @@
1719
proxy_set_header Connection $http_connection;
1820
proxy_http_version 1.1;
1921
{% endif %}
20-
21-
22-
{{ advanced_config }}
2322
}
2423

backend/yarn.lock

+11-11
Original file line numberDiff line numberDiff line change
@@ -448,11 +448,11 @@ brace-expansion@^1.1.7:
448448
concat-map "0.0.1"
449449

450450
braces@~3.0.2:
451-
version "3.0.2"
452-
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
453-
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
451+
version "3.0.3"
452+
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
453+
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
454454
dependencies:
455-
fill-range "^7.0.1"
455+
fill-range "^7.1.1"
456456

457457
buffer-crc32@^0.2.1, buffer-crc32@^0.2.13:
458458
version "0.2.13"
@@ -1206,10 +1206,10 @@ file-entry-cache@^6.0.1:
12061206
dependencies:
12071207
flat-cache "^3.0.4"
12081208

1209-
fill-range@^7.0.1:
1210-
version "7.0.1"
1211-
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
1212-
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
1209+
fill-range@^7.1.1:
1210+
version "7.1.1"
1211+
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
1212+
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
12131213
dependencies:
12141214
to-regex-range "^5.0.1"
12151215

@@ -1402,9 +1402,9 @@ glob-parent@^6.0.2:
14021402
is-glob "^4.0.3"
14031403

14041404
glob-parent@~5.1.0:
1405-
version "5.1.1"
1406-
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
1407-
integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
1405+
version "5.1.2"
1406+
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
1407+
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
14081408
dependencies:
14091409
is-glob "^4.0.1"
14101410

docker/dev/dnsrouter-config.json

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"log": {
3+
"format": "nice",
4+
"level": "debug"
5+
},
6+
"servers": [
7+
{
8+
"host": "0.0.0.0",
9+
"port": 53,
10+
"upstreams": [
11+
{
12+
"regex": "website[0-9]+.example\\.com",
13+
"upstream": "127.0.0.11"
14+
},
15+
{
16+
"regex": ".*\\.example\\.com",
17+
"upstream": "1.1.1.1"
18+
},
19+
{
20+
"regex": "local",
21+
"nxdomain": true
22+
}
23+
],
24+
"internal": null,
25+
"default_upstream": "127.0.0.11"
26+
}
27+
]
28+
}

docker/dev/letsencrypt.ini

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
text = True
2+
non-interactive = True
3+
webroot-path = /data/letsencrypt-acme-challenge
4+
key-type = ecdsa
5+
elliptic-curve = secp384r1
6+
preferred-chain = ISRG Root X1
7+
server =

0 commit comments

Comments
 (0)