Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
01660b5
Fixed now_helper for sqlite: it should also returns the time.
jlesage Aug 6, 2020
d686565
Merge pull request #544 from jlesage/sqlite-now-helper-fix
jc21 Aug 6, 2020
7034613
Bump prismjs from 1.20.0 to 1.21.0 in /docs
dependabot[bot] Aug 8, 2020
5d65166
Ignore local subnets for real IP determination
jc21 Aug 11, 2020
f539e81
Removed the hardcoded `--webroot` certbot argument to better support …
jlesage Aug 14, 2020
83fad8b
Removed usage of `FROM_UNIXTIME` mysql-specific function.
jlesage Aug 14, 2020
f78a4c6
Bump bcrypt from 4.0.1 to 5.0.0 in /backend
dependabot[bot] Aug 20, 2020
6694a42
Merge pull request #560 from jlesage/remove-from-unixtime
jc21 Aug 21, 2020
251aac7
Add CloudFlare DNS plugin to certbot
jipjan Aug 21, 2020
2d7576c
add cloudflare dns also to dev docker file
jipjan Aug 23, 2020
b9a9584
add cloudflare dns option to letsencrypt via manual certificate
jipjan Aug 23, 2020
ff17702
request via cloudflare dns working
jipjan Aug 23, 2020
077cf75
wildcard support
jipjan Aug 23, 2020
cff6c4d
- prevent wildcard generation when not using Cloudflare dns
jipjan Aug 23, 2020
c5aa2b9
add cloudflare renew and make revoke working for both by deleting unn…
jipjan Aug 23, 2020
1b611e6
Merge commit 'c5aa2b9f771cbd4c78c239ed0791aeb8d9e4d2e4' into features…
jipjan Aug 23, 2020
ab67481
fix eslint errors
jipjan Aug 23, 2020
e8596c1
cloudflare DNS also possible while adding proxy, redirection and 404
jipjan Aug 24, 2020
a561605
show in ssl certificates list that CloudFlare is used
jipjan Aug 24, 2020
e5034a3
Merge pull request #570 from jc21/dependabot/npm_and_yarn/backend/bcr…
jc21 Aug 24, 2020
bf8beb5
Merge pull request #559 from jlesage/remove-webroot-certbot-arg
jc21 Aug 24, 2020
4bafc7f
Merge pull request #546 from jc21/dependabot/npm_and_yarn/docs/prismj…
jc21 Aug 25, 2020
87f61b8
Merge pull request #572 from jipjan/features/dns-cloudflare
jc21 Sep 3, 2020
2c5eac9
Merge branch 'master' of github.com:jc21/nginx-proxy-manager into dev…
jc21 Sep 3, 2020
a6b9bd7
Version bump and contributors
jc21 Sep 3, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.4.0
2.5.0
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<p align="center">
<img src="https://nginxproxymanager.com/github.png">
<br><br>
<img src="https://img.shields.io/badge/version-2.4.0-green.svg?style=for-the-badge">
<img src="https://img.shields.io/badge/version-2.5.0-green.svg?style=for-the-badge">
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge">
</a>
Expand Down Expand Up @@ -173,6 +173,18 @@ Special thanks to the following contributors:
<br /><sub><b>vrenjith</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/duhruh">
<img src="https://avatars2.githubusercontent.com/u/1133969?s=460&u=c0691e6131ec6d516416c1c6fcedb5034f877bbe&v=4" width="80px;" alt=""/>
<br /><sub><b>David Rivera</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/jipjan">
<img src="https://avatars2.githubusercontent.com/u/1384618?s=460&v=4" width="80px;" alt=""/>
<br /><sub><b>Jaap-Jan de Wit</b></sub>
</a>
</td>
</tr>
</table>
<!-- markdownlint-enable -->
Expand Down
150 changes: 115 additions & 35 deletions backend/internal/certificate.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const internalCertificate = {
.where('id', certificate.id)
.andWhere('provider', 'letsencrypt')
.patch({
expires_on: certificateModel.raw('FROM_UNIXTIME(' + cert_info.dates.to + ')')
expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss')
});
})
.catch((err) => {
Expand Down Expand Up @@ -141,36 +141,60 @@ const internalCertificate = {
});
})
.then((in_use_result) => {
// 3. Generate the LE config
return internalNginx.generateLetsEncryptRequestConfig(certificate)
.then(internalNginx.reload)
.then(() => {
// Is CloudFlare, no config needed, so skip 3 and 5.
if (data.meta.cloudflare_use) {
return internalNginx.reload().then(() => {
// 4. Request cert
return internalCertificate.requestLetsEncryptSsl(certificate);
})
.then(() => {
// 5. Remove LE config
return internalNginx.deleteLetsEncryptRequestConfig(certificate);
})
.then(internalNginx.reload)
.then(() => {
// 6. Re-instate previously disabled hosts
return internalCertificate.enableInUseHosts(in_use_result);
})
.then(() => {
return certificate;
return internalCertificate.requestLetsEncryptCloudFlareDnsSsl(certificate, data.meta.cloudflare_token);
})
.catch((err) => {
// In the event of failure, revert things and throw err back
return internalNginx.deleteLetsEncryptRequestConfig(certificate)
.then(() => {
return internalCertificate.enableInUseHosts(in_use_result);
})
.then(internalNginx.reload)
.then(() => {
throw err;
});
});
.then(internalNginx.reload)
.then(() => {
// 6. Re-instate previously disabled hosts
return internalCertificate.enableInUseHosts(in_use_result);
})
.then(() => {
return certificate;
})
.catch((err) => {
// In the event of failure, revert things and throw err back
return internalCertificate.enableInUseHosts(in_use_result)
.then(internalNginx.reload)
.then(() => {
throw err;
});
});
} else {
// 3. Generate the LE config
return internalNginx.generateLetsEncryptRequestConfig(certificate)
.then(internalNginx.reload)
.then(() => {
// 4. Request cert
return internalCertificate.requestLetsEncryptSsl(certificate);
})
.then(() => {
// 5. Remove LE config
return internalNginx.deleteLetsEncryptRequestConfig(certificate);
})
.then(internalNginx.reload)
.then(() => {
// 6. Re-instate previously disabled hosts
return internalCertificate.enableInUseHosts(in_use_result);
})
.then(() => {
return certificate;
})
.catch((err) => {
// In the event of failure, revert things and throw err back
return internalNginx.deleteLetsEncryptRequestConfig(certificate)
.then(() => {
return internalCertificate.enableInUseHosts(in_use_result);
})
.then(internalNginx.reload)
.then(() => {
throw err;
});
});
}
})
.then(() => {
// At this point, the letsencrypt cert should exist on disk.
Expand All @@ -180,7 +204,7 @@ const internalCertificate = {
return certificateModel
.query()
.patchAndFetchById(certificate.id, {
expires_on: certificateModel.raw('FROM_UNIXTIME(' + cert_info.dates.to + ')')
expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss')
})
.then((saved_row) => {
// Add cert data for audit log
Expand Down Expand Up @@ -558,7 +582,7 @@ const internalCertificate = {
// TODO: This uses a mysql only raw function that won't translate to postgres
return internalCertificate.update(access, {
id: data.id,
expires_on: certificateModel.raw('FROM_UNIXTIME(' + validations.certificate.dates.to + ')'),
expires_on: moment(validations.certificate.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss'),
domain_names: [validations.certificate.cn],
meta: _.clone(row.meta) // Prevent the update method from changing this value that we'll use later
})
Expand Down Expand Up @@ -733,7 +757,6 @@ const internalCertificate = {
'--agree-tos ' +
'--email "' + certificate.meta.letsencrypt_email + '" ' +
'--preferred-challenges "dns,http" ' +
'--webroot ' +
'--domains "' + certificate.domain_names.join(',') + '" ' +
(le_staging ? '--staging' : '');

Expand All @@ -748,6 +771,39 @@ const internalCertificate = {
});
},

/**
* @param {Object} certificate the certificate row
* @param {String} apiToken the cloudflare api token
* @returns {Promise}
*/
requestLetsEncryptCloudFlareDnsSsl: (certificate, apiToken) => {
logger.info('Requesting Let\'sEncrypt certificates via Cloudflare DNS for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));

let tokenLoc = '~/cloudflare-token';
let storeKey = 'echo "dns_cloudflare_api_token = ' + apiToken + '" > ' + tokenLoc;

let cmd =
storeKey + ' && ' +
certbot_command + ' certonly --non-interactive ' +
'--cert-name "npm-' + certificate.id + '" ' +
'--agree-tos ' +
'--email "' + certificate.meta.letsencrypt_email + '" ' +
'--domains "' + certificate.domain_names.join(',') + '" ' +
'--dns-cloudflare --dns-cloudflare-credentials ' + tokenLoc +
(le_staging ? ' --staging' : '')
+ ' && rm ' + tokenLoc;

if (debug_mode) {
logger.info('Command:', cmd);
}

return utils.exec(cmd).then((result) => {
logger.info(result);
return result;
});
},


/**
* @param {Access} access
* @param {Object} data
Expand All @@ -761,15 +817,17 @@ const internalCertificate = {
})
.then((certificate) => {
if (certificate.provider === 'letsencrypt') {
return internalCertificate.renewLetsEncryptSsl(certificate)
let renewMethod = certificate.meta.cloudflare_use ? internalCertificate.renewLetsEncryptCloudFlareSsl : internalCertificate.renewLetsEncryptSsl;

return renewMethod(certificate)
.then(() => {
return internalCertificate.getCertificateInfoFromFile('/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem');
})
.then((cert_info) => {
return certificateModel
.query()
.patchAndFetchById(certificate.id, {
expires_on: certificateModel.raw('FROM_UNIXTIME(' + cert_info.dates.to + ')')
expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss')
});
})
.then((updated_certificate) => {
Expand Down Expand Up @@ -815,6 +873,29 @@ const internalCertificate = {
});
},

/**
* @param {Object} certificate the certificate row
* @returns {Promise}
*/
renewLetsEncryptCloudFlareSsl: (certificate) => {
logger.info('Renewing Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));

let cmd = certbot_command + ' renew --non-interactive ' +
'--cert-name "npm-' + certificate.id + '" ' +
'--disable-hook-validation ' +
(le_staging ? '--staging' : '');

if (debug_mode) {
logger.info('Command:', cmd);
}

return utils.exec(cmd)
.then((result) => {
logger.info(result);
return result;
});
},

/**
* @param {Object} certificate the certificate row
* @param {Boolean} [throw_errors]
Expand All @@ -824,7 +905,6 @@ const internalCertificate = {
logger.info('Revoking Let\'sEncrypt certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));

let cmd = certbot_command + ' revoke --non-interactive ' +
'--config "' + le_config + '" ' +
'--cert-path "/etc/letsencrypt/live/npm-' + certificate.id + '/fullchain.pem" ' +
'--delete-after-revoke ' +
(le_staging ? '--staging' : '');
Expand Down
2 changes: 1 addition & 1 deletion backend/models/now_helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Model.knex(db);

module.exports = function () {
if (config.database.knex && config.database.knex.client === 'sqlite3') {
return Model.raw('date(\'now\')');
return Model.raw('datetime(\'now\',\'localtime\')');
} else {
return Model.raw('NOW()');
}
Expand Down
2 changes: 1 addition & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"dependencies": {
"ajv": "^6.12.0",
"batchflow": "^0.4.0",
"bcrypt": "^4.0.1",
"bcrypt": "^5.0.0",
"body-parser": "^1.19.0",
"compression": "^1.7.4",
"config": "^3.3.1",
Expand Down
6 changes: 6 additions & 0 deletions backend/schema/endpoints/certificates.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@
},
"letsencrypt_agree": {
"type": "boolean"
},
"cloudflare_use": {
"type": "boolean"
},
"cloudflare_token": {
"type": "string"
}
}
}
Expand Down
36 changes: 18 additions & 18 deletions backend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -249,13 +249,13 @@ batchflow@^0.4.0:
resolved "https://registry.yarnpkg.com/batchflow/-/batchflow-0.4.0.tgz#7d419df79b6b7587b06f9ea34f96ccef6f74e5b5"
integrity sha1-fUGd95trdYewb56jT5bM72905bU=

bcrypt@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-4.0.1.tgz#06e21e749a061020e4ff1283c1faa93187ac57fe"
integrity sha512-hSIZHkUxIDS5zA2o00Kf2O5RfVbQ888n54xQoF/eIaquU4uaLxK8vhhBdktd0B3n2MjkcAWzv4mnhogykBKOUQ==
bcrypt@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/bcrypt/-/bcrypt-5.0.0.tgz#051407c7cd5ffbfb773d541ca3760ea0754e37e2"
integrity sha512-jB0yCBl4W/kVHM2whjfyqnxTmOHkCX4kHEa5nYKSoGeYe8YrjTYTc87/6bwt1g8cmV0QrbhKriETg9jWtcREhg==
dependencies:
node-addon-api "^2.0.0"
node-pre-gyp "0.14.0"
node-addon-api "^3.0.0"
node-pre-gyp "0.15.0"

[email protected]:
version "9.0.0"
Expand Down Expand Up @@ -2166,7 +2166,7 @@ mixin-deep@^1.2.0:
for-in "^1.0.2"
is-extendable "^1.0.1"

mkdirp@^0.5.0, mkdirp@^0.5.1:
mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3:
version "0.5.5"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==
Expand Down Expand Up @@ -2235,7 +2235,7 @@ natural-compare@^1.4.0:
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=

needle@^2.2.1:
needle@^2.2.1, needle@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/needle/-/needle-2.5.0.tgz#e6fc4b3cc6c25caed7554bd613a5cf0bac8c31c0"
integrity sha512-o/qITSDR0JCyCKEQ1/1bnUXMmznxabbwi/Y4WwJElf+evwJNFNwIDMCCt5IigFVxgeGBJESLohGtIS9gEzo1fA==
Expand All @@ -2254,19 +2254,19 @@ nice-try@^1.0.4:
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==

node-addon-api@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32"
integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==
node-addon-api@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.0.0.tgz#812446a1001a54f71663bed188314bba07e09247"
integrity sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg==

node-pre-gyp@0.14.0:
version "0.14.0"
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83"
integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==
node-pre-gyp@0.15.0:
version "0.15.0"
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz#c2fc383276b74c7ffa842925241553e8b40f1087"
integrity sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA==
dependencies:
detect-libc "^1.0.2"
mkdirp "^0.5.1"
needle "^2.2.1"
mkdirp "^0.5.3"
needle "^2.5.0"
nopt "^4.0.1"
npm-packlist "^1.1.6"
npmlog "^4.0.2"
Expand Down
3 changes: 2 additions & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ ENV NODE_ENV=production

RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
&& apk update \
&& apk add python2 certbot jq \
&& apk add python2 py-pip certbot jq \
&& pip install certbot-dns-cloudflare \
&& rm -rf /var/cache/apk/*

ENV NPM_BUILD_VERSION="${BUILD_VERSION}" NPM_BUILD_COMMIT="${BUILD_COMMIT}" NPM_BUILD_DATE="${BUILD_DATE}"
Expand Down
3 changes: 2 additions & 1 deletion docker/dev/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ ENV S6_FIX_ATTRS_HIDDEN=1

RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
&& apk update \
&& apk add python2 certbot jq \
&& apk add python2 py-pip certbot jq \
&& pip install certbot-dns-cloudflare \
&& rm -rf /var/cache/apk/*

# Task
Expand Down
9 changes: 6 additions & 3 deletions docker/rootfs/etc/nginx/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ http {
tcp_nodelay on;
client_body_temp_path /tmp/nginx/body 1 2;
keepalive_timeout 90s;
proxy_connect_timeout 90s;
proxy_send_timeout 90s;
proxy_read_timeout 90s;
proxy_connect_timeout 90s;
proxy_send_timeout 90s;
proxy_read_timeout 90s;
ssl_prefer_server_ciphers on;
gzip on;
proxy_ignore_client_abort off;
Expand Down Expand Up @@ -60,6 +60,9 @@ http {
# Real IP Determination
# Docker subnet:
set_real_ip_from 172.0.0.0/8;
# Local subnets:
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 192.0.0.0/8;
# NPM generated CDN ip ranges:
include conf.d/include/ip_ranges.conf;
# always put the following 2 lines after ip subnets:
Expand Down
Loading