Skip to content

Commit 081380c

Browse files
authored
Merge pull request NginxProxyManager#1716 from jc21/develop
v2.9.14
2 parents 84bc33d + 7e451bc commit 081380c

File tree

13 files changed

+131
-85
lines changed

13 files changed

+131
-85
lines changed

.version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.9.13
1+
2.9.14

Jenkinsfile

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ pipeline {
6262
stage('Backend') {
6363
steps {
6464
echo 'Checking Syntax ...'
65+
sh 'docker pull node:latest'
6566
// See: https://github.com/yarnpkg/yarn/issues/3254
6667
sh '''docker run --rm \\
6768
-v "$(pwd)/backend:/app" \\

README.md

+27-7
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.9.13-green.svg?style=for-the-badge">
4+
<img src="https://img.shields.io/badge/version-2.9.14-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>
@@ -110,9 +110,9 @@ Special thanks to the following contributors:
110110
<table>
111111
<tr>
112112
<td align="center">
113-
<a href="https://github.com/Subv">
114-
<img src="https://avatars1.githubusercontent.com/u/357072?s=460&u=d8adcdc91d749ae53e177973ed9b6bb6c4c894a3&v=4" width="80" alt=""/>
115-
<br /><sub><b>Sebastian Valle</b></sub>
113+
<a href="https://github.com/chaptergy">
114+
<img src="https://avatars2.githubusercontent.com/u/26956711?s=460&u=7d9adebabb6b4e7af7cb05d98d751087a372304b&v=4" width="80" alt=""/>
115+
<br /><sub><b>chaptergy</b></sub>
116116
</a>
117117
</td>
118118
<td align="center">
@@ -242,9 +242,9 @@ Special thanks to the following contributors:
242242
</tr>
243243
<tr>
244244
<td align="center">
245-
<a href="https://github.com/chaptergy">
246-
<img src="https://avatars2.githubusercontent.com/u/26956711?s=460&u=7d9adebabb6b4e7af7cb05d98d751087a372304b&v=4" width="80" alt=""/>
247-
<br /><sub><b>chaptergy</b></sub>
245+
<a href="https://github.com/Subv">
246+
<img src="https://avatars1.githubusercontent.com/u/357072?s=460&u=d8adcdc91d749ae53e177973ed9b6bb6c4c894a3&v=4" width="80" alt=""/>
247+
<br /><sub><b>Sebastian Valle</b></sub>
248248
</a>
249249
</td>
250250
<td align="center">
@@ -491,6 +491,26 @@ Special thanks to the following contributors:
491491
<br /><sub><b>bergi9</b></sub>
492492
</a>
493493
</td>
494+
<td align="center">
495+
<a href="https://github.com/luoweihua7">
496+
<img src="https://avatars.githubusercontent.com/u/3157520?v=4" width="80" alt=""/>
497+
<br /><sub><b>luoweihua7</b></sub>
498+
</a>
499+
</td>
500+
<td align="center">
501+
<a href="https://github.com/TobiasKneidl">
502+
<img src="https://avatars.githubusercontent.com/u/26301707?v=4" width="80" alt=""/>
503+
<br /><sub><b>Tobias Kneidl</b></sub>
504+
</a>
505+
</td>
506+
</tr>
507+
<tr>
508+
<td align="center">
509+
<a href="https://github.com/piuswalter">
510+
<img src="https://avatars.githubusercontent.com/u/64539242?v=4" width="80" alt=""/>
511+
<br /><sub><b>Pius Walter</b></sub>
512+
</a>
513+
</td>
494514
</tr>
495515
</table>
496516
<!-- markdownlint-enable -->

backend/internal/certificate.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ const internalCertificate = {
171171
// 3. Generate the LE config
172172
return internalNginx.generateLetsEncryptRequestConfig(certificate)
173173
.then(internalNginx.reload)
174+
.then(async() => await new Promise((r) => setTimeout(r, 5000)))
174175
.then(() => {
175176
// 4. Request cert
176177
return internalCertificate.requestLetsEncryptSsl(certificate);
@@ -870,8 +871,10 @@ const internalCertificate = {
870871
logger.info(`Requesting Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
871872

872873
const credentialsLocation = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
873-
const credentialsCmd = 'mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
874-
const prepareCmd = 'pip install ' + dns_plugin.package_name + (dns_plugin.version_requirement || '') + ' ' + dns_plugin.dependencies;
874+
// Escape single quotes and backslashes
875+
const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll('\'', '\\\'').replaceAll('\\', '\\\\');
876+
const credentialsCmd = 'mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
877+
const prepareCmd = 'pip install ' + dns_plugin.package_name + (dns_plugin.version_requirement || '') + ' ' + dns_plugin.dependencies;
875878

876879
// Whether the plugin has a --<name>-credentials argument
877880
const hasConfigArg = certificate.meta.dns_provider !== 'route53';

backend/internal/ip_ranges.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ const CLOUDFRONT_URL = 'https://ip-ranges.amazonaws.com/ip-ranges.json';
99
const CLOUDFARE_V4_URL = 'https://www.cloudflare.com/ips-v4';
1010
const CLOUDFARE_V6_URL = 'https://www.cloudflare.com/ips-v6';
1111

12+
const regIpV4 = /^(\d+\.?){4}\/\d+/;
13+
const regIpV6 = /^(([\da-fA-F]+)?:)+\/\d+/;
14+
1215
const internalIpRanges = {
1316

1417
interval_timeout: 1000 * 60 * 60 * 6, // 6 hours
@@ -74,14 +77,14 @@ const internalIpRanges = {
7477
return internalIpRanges.fetchUrl(CLOUDFARE_V4_URL);
7578
})
7679
.then((cloudfare_data) => {
77-
let items = cloudfare_data.split('\n');
80+
let items = cloudfare_data.split('\n').filter((line) => regIpV4.test(line));
7881
ip_ranges = [... ip_ranges, ... items];
7982
})
8083
.then(() => {
8184
return internalIpRanges.fetchUrl(CLOUDFARE_V6_URL);
8285
})
8386
.then((cloudfare_data) => {
84-
let items = cloudfare_data.split('\n');
87+
let items = cloudfare_data.split('\n').filter((line) => regIpV6.test(line));
8588
ip_ranges = [... ip_ranges, ... items];
8689
})
8790
.then(() => {

backend/setup.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ const setupCertbotPlugins = () => {
181181

182182
// Make sure credentials file exists
183183
const credentials_loc = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
184-
const credentials_cmd = '[ -f \'' + credentials_loc + '\' ] || { mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'; }';
184+
// Escape single quotes and backslashes
185+
const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll('\'', '\\\'').replaceAll('\\', '\\\\');
186+
const credentials_cmd = '[ -f \'' + credentials_loc + '\' ] || { mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'; }';
185187
promises.push(utils.exec(credentials_cmd));
186188
}
187189
});

backend/templates/default.conf

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
server {
88
listen 80 default;
99
{% if ipv6 -%}
10-
listen [::]:80;
10+
listen [::]:80 default;
1111
{% else -%}
12-
#listen [::]:80;
12+
#listen [::]:80 default;
1313
{% endif %}
1414
server_name default-host.localhost;
1515
access_log /data/logs/default-host_access.log combined;

docker/rootfs/etc/nginx/conf.d/default.conf

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ server {
3030
set $port "443";
3131

3232
server_name localhost;
33-
access_log /data/logs/fallback-access.log standard;
33+
access_log /data/logs/fallback_access.log standard;
3434
error_log /dev/null crit;
3535
ssl_certificate /data/nginx/dummycert.pem;
3636
ssl_certificate_key /data/nginx/dummykey.pem;

docker/rootfs/etc/nginx/conf.d/include/proxy.conf

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ add_header X-Served-By $host;
22
proxy_set_header Host $host;
33
proxy_set_header X-Forwarded-Scheme $scheme;
44
proxy_set_header X-Forwarded-Proto $scheme;
5+
proxy_set_header X-Forwarded-Host $host;
6+
proxy_set_header X-Forwarded-Port $port;
57
proxy_set_header X-Forwarded-For $remote_addr;
68
proxy_set_header X-Real-IP $remote_addr;
79
proxy_pass $forward_scheme://$server:$port$request_uri;

docker/rootfs/etc/services.d/nginx/run

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ chown root /tmp/nginx
2424

2525
# Dynamically generate resolvers file, if resolver is IPv6, enclose in `[]`
2626
# thanks @tfmm
27-
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" > /etc/nginx/conf.d/include/resolvers.conf
27+
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" { sub(/%.*$/,"",$2); print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" > /etc/nginx/conf.d/include/resolvers.conf
2828

2929
# Generate dummy self-signed certificate.
3030
if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]

docs/faq/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,6 @@ Your best bet is to ask the [Reddit community for support](https://www.reddit.co
2121

2222
Gitter is best left for anyone contributing to the project to ask for help about internals, code reviews etc.
2323

24+
## When adding username and password access control to a proxy host, I can no longer login into the app.
25+
26+
Having an Access Control List (ACL) with username and password requires the browser to always send this username and password in the `Authorization` header on each request. If your proxied app also requires authentication (like Nginx Proxy Manager itself), most likely the app will also use the `Authorization` header to transmit this information, as this is the standardized header meant for this kind of information. However having multiples of the same headers is not allowed in the [internet standard](https://www.rfc-editor.org/rfc/rfc7230#section-3.2.2) and almost all apps do not support multiple values in the `Authorization` header. Hence one of the two logins will be broken. This can only be fixed by either removing one of the logins or by changing the app to use other non-standard headers for authorization.

frontend/js/app/nginx/certificates/form.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,11 @@ module.exports = Mn.View.extend({
278278
this.ui.credentials_file_content.hide();
279279
this.ui.loader_content.hide();
280280
this.ui.le_error_info.hide();
281-
const domainNames = this.ui.domain_names[0].value.split(',');
282-
if (!domainNames || domainNames.length === 0 || (domainNames.length === 1 && domainNames[0] === "")) {
283-
this.ui.test_domains_button.prop('disabled', true);
281+
if (this.ui.domain_names[0]) {
282+
const domainNames = this.ui.domain_names[0].value.split(',');
283+
if (!domainNames || domainNames.length === 0 || (domainNames.length === 1 && domainNames[0] === "")) {
284+
this.ui.test_domains_button.prop('disabled', true);
285+
}
284286
}
285287
},
286288

0 commit comments

Comments
 (0)