Skip to content

[pull] develop from NginxProxyManager:develop #33

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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.12.4
2.12.5
2 changes: 1 addition & 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.12.4-green.svg?style=for-the-badge">
<img src="https://img.shields.io/badge/version-2.12.5-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
17 changes: 12 additions & 5 deletions backend/lib/certbot.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const certbot = {
/**
* @param {array} pluginKeys
*/
installPlugins: async function (pluginKeys) {
installPlugins: async (pluginKeys) => {
let hasErrors = false;

return new Promise((resolve, reject) => {
Expand All @@ -21,7 +21,7 @@ const certbot = {
}

batchflow(pluginKeys).sequential()
.each((i, pluginKey, next) => {
.each((_i, pluginKey, next) => {
certbot.installPlugin(pluginKey)
.then(() => {
next();
Expand Down Expand Up @@ -51,7 +51,7 @@ const certbot = {
* @param {string} pluginKey
* @returns {Object}
*/
installPlugin: async function (pluginKey) {
installPlugin: async (pluginKey) => {
if (typeof dnsPlugins[pluginKey] === 'undefined') {
// throw Error(`Certbot plugin ${pluginKey} not found`);
throw new error.ItemNotFoundError(pluginKey);
Expand All @@ -63,8 +63,15 @@ const certbot = {
plugin.version = plugin.version.replace(/{{certbot-version}}/g, CERTBOT_VERSION_REPLACEMENT);
plugin.dependencies = plugin.dependencies.replace(/{{certbot-version}}/g, CERTBOT_VERSION_REPLACEMENT);

const cmd = '. /opt/certbot/bin/activate && pip install --no-cache-dir ' + plugin.dependencies + ' ' + plugin.package_name + plugin.version + ' ' + ' && deactivate';
return utils.exec(cmd)
// SETUPTOOLS_USE_DISTUTILS is required for certbot plugins to install correctly
// in new versions of Python
let env = Object.assign({}, process.env, {SETUPTOOLS_USE_DISTUTILS: 'stdlib'});
if (typeof plugin.env === 'object') {
env = Object.assign(env, plugin.env);
}

const cmd = `. /opt/certbot/bin/activate && pip install --no-cache-dir ${plugin.dependencies} ${plugin.package_name}${plugin.version} && deactivate`;
return utils.exec(cmd, {env})
.then((result) => {
logger.complete(`Installed ${pluginKey}`);
return result;
Expand Down
18 changes: 9 additions & 9 deletions backend/lib/utils.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
const _ = require('lodash');
const exec = require('child_process').exec;
const execFile = require('child_process').execFile;
const exec = require('node:child_process').exec;
const execFile = require('node:child_process').execFile;
const { Liquid } = require('liquidjs');
const logger = require('../logger').global;
const error = require('./error');

module.exports = {

exec: async function(cmd, options = {}) {
exec: async (cmd, options = {}) => {
logger.debug('CMD:', cmd);

const { stdout, stderr } = await new Promise((resolve, reject) => {
Expand All @@ -31,11 +31,11 @@ module.exports = {
* @param {Array} args
* @returns {Promise}
*/
execFile: function (cmd, args) {
execFile: (cmd, args) => {
// logger.debug('CMD: ' + cmd + ' ' + (args ? args.join(' ') : ''));

return new Promise((resolve, reject) => {
execFile(cmd, args, function (err, stdout, /*stderr*/) {
execFile(cmd, args, (err, stdout, /*stderr*/) => {
if (err && typeof err === 'object') {
reject(err);
} else {
Expand All @@ -51,7 +51,7 @@ module.exports = {
* @param {Array} omissions
* @returns {Function}
*/
omitRow: function (omissions) {
omitRow: (omissions) => {
/**
* @param {Object} row
* @returns {Object}
Expand All @@ -67,7 +67,7 @@ module.exports = {
* @param {Array} omissions
* @returns {Function}
*/
omitRows: function (omissions) {
omitRows: (omissions) => {
/**
* @param {Array} rows
* @returns {Object}
Expand All @@ -83,9 +83,9 @@ module.exports = {
/**
* @returns {Object} Liquid render engine
*/
getRenderEngine: function () {
getRenderEngine: () => {
const renderEngine = new Liquid({
root: __dirname + '/../templates/'
root: `${__dirname}/../templates/`
});

/**
Expand Down
5 changes: 4 additions & 1 deletion docker/rootfs/etc/s6-overlay/s6-rc.d/prepare/30-ownership.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ CERT_INIT_FLAG="/opt/certbot/.ownership_initialized"

if [ ! -f "$CERT_INIT_FLAG" ]; then
# Prevents errors when installing python certbot plugins when non-root
chown "$PUID:$PGID" /opt/certbot /opt/certbot/bin
if [ "$SKIP_CERTBOT_OWNERSHIP" != "true" ]; then
log_info 'Changing ownership of /opt/certbot directories ...'
chown "$PUID:$PGID" /opt/certbot /opt/certbot/bin
fi

# Handle all site-packages directories efficiently
find /opt/certbot/lib -type d -name "site-packages" | while read -r SITE_PACKAGES_DIR; do
Expand Down
6 changes: 3 additions & 3 deletions test/cypress/e2e/api/Certificates.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ describe('Certificates endpoints', () => {
});
});

it('Validate custom certificate', function() {
it('Validate custom certificate', () => {
cy.task('backendApiPostFiles', {
token: token,
path: '/api/nginx/certificates/validate',
Expand All @@ -25,7 +25,7 @@ describe('Certificates endpoints', () => {
});
});

it('Custom certificate lifecycle', function() {
it('Custom certificate lifecycle', () => {
// Create custom cert
cy.task('backendApiPost', {
token: token,
Expand Down Expand Up @@ -73,7 +73,7 @@ describe('Certificates endpoints', () => {
});
});

it('Request Certificate - CVE-2024-46256/CVE-2024-46257', function() {
it('Request Certificate - CVE-2024-46256/CVE-2024-46257', () => {
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/certificates',
Expand Down
2 changes: 1 addition & 1 deletion test/cypress/e2e/api/Dashboard.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('Dashboard endpoints', () => {
});
});

it('Should be able to get host counts', function() {
it('Should be able to get host counts', () => {
cy.task('backendApiGet', {
token: token,
path: '/api/reports/hosts'
Expand Down
4 changes: 2 additions & 2 deletions test/cypress/e2e/api/FullCertProvision.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('Full Certificate Provisions', () => {
});
});

it('Should be able to create new http certificate', function() {
it('Should be able to create new http certificate', () => {
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/certificates',
Expand All @@ -32,7 +32,7 @@ describe('Full Certificate Provisions', () => {
});
});

it('Should be able to create new DNS certificate with Powerdns', function() {
it('Should be able to create new DNS certificate with Powerdns', () => {
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/certificates',
Expand Down
6 changes: 3 additions & 3 deletions test/cypress/e2e/api/Health.cy.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/// <reference types="cypress" />

describe('Basic API checks', () => {
it('Should return a valid health payload', function () {
it('Should return a valid health payload', () => {
cy.task('backendApiGet', {
path: '/api/',
}).then((data) => {
Expand All @@ -10,9 +10,9 @@ describe('Basic API checks', () => {
});
});

it('Should return a valid schema payload', function () {
it('Should return a valid schema payload', () => {
cy.task('backendApiGet', {
path: '/api/schema?ts=' + Date.now(),
path: `/api/schema?ts=${Date.now()}`,
}).then((data) => {
expect(data.openapi).to.be.equal('3.1.0');
});
Expand Down
6 changes: 3 additions & 3 deletions test/cypress/e2e/api/Ldap.cy.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/// <reference types="cypress" />

describe('LDAP with Authentik', () => {
let token;
let _token;
if (Cypress.env('skipStackCheck') === 'true' || Cypress.env('stack') === 'postgres') {

before(() => {
cy.getToken().then((tok) => {
token = tok;
_token = tok;

// cy.task('backendApiPut', {
// token: token,
Expand Down Expand Up @@ -45,7 +45,7 @@ describe('LDAP with Authentik', () => {
});
});

it.skip('Should log in with LDAP', function() {
it.skip('Should log in with LDAP', () => {
// cy.task('backendApiPost', {
// token: token,
// path: '/api/auth',
Expand Down
6 changes: 3 additions & 3 deletions test/cypress/e2e/api/OAuth.cy.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/// <reference types="cypress" />

describe('OAuth with Authentik', () => {
let token;
let _token;
if (Cypress.env('skipStackCheck') === 'true' || Cypress.env('stack') === 'postgres') {

before(() => {
cy.getToken().then((tok) => {
token = tok;
_token = tok;

// cy.task('backendApiPut', {
// token: token,
Expand Down Expand Up @@ -47,7 +47,7 @@ describe('OAuth with Authentik', () => {
});
});

it.skip('Should log in with OAuth', function() {
it.skip('Should log in with OAuth', () => {
// cy.task('backendApiGet', {
// path: '/oauth/login?redirect_base=' + encodeURI(Cypress.config('baseUrl')),
// }).then((data) => {
Expand Down
2 changes: 1 addition & 1 deletion test/cypress/e2e/api/ProxyHosts.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('Proxy Hosts endpoints', () => {
});
});

it('Should be able to create a http host', function() {
it('Should be able to create a http host', () => {
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/proxy-hosts',
Expand Down
14 changes: 7 additions & 7 deletions test/cypress/e2e/api/Settings.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('Settings endpoints', () => {
});
});

it('Get all settings', function() {
it('Get all settings', () => {
cy.task('backendApiGet', {
token: token,
path: '/api/settings',
Expand All @@ -19,7 +19,7 @@ describe('Settings endpoints', () => {
});
});

it('Get default-site setting', function() {
it('Get default-site setting', () => {
cy.task('backendApiGet', {
token: token,
path: '/api/settings/default-site',
Expand All @@ -30,7 +30,7 @@ describe('Settings endpoints', () => {
});
});

it('Default Site congratulations', function() {
it('Default Site congratulations', () => {
cy.task('backendApiPut', {
token: token,
path: '/api/settings/default-site',
Expand All @@ -46,7 +46,7 @@ describe('Settings endpoints', () => {
});
});

it('Default Site 404', function() {
it('Default Site 404', () => {
cy.task('backendApiPut', {
token: token,
path: '/api/settings/default-site',
Expand All @@ -62,7 +62,7 @@ describe('Settings endpoints', () => {
});
});

it('Default Site 444', function() {
it('Default Site 444', () => {
cy.task('backendApiPut', {
token: token,
path: '/api/settings/default-site',
Expand All @@ -78,7 +78,7 @@ describe('Settings endpoints', () => {
});
});

it('Default Site redirect', function() {
it('Default Site redirect', () => {
cy.task('backendApiPut', {
token: token,
path: '/api/settings/default-site',
Expand All @@ -100,7 +100,7 @@ describe('Settings endpoints', () => {
});
});

it('Default Site html', function() {
it('Default Site html', () => {
cy.task('backendApiPut', {
token: token,
path: '/api/settings/default-site',
Expand Down
12 changes: 6 additions & 6 deletions test/cypress/e2e/api/Streams.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('Streams', () => {
cy.exec('rm -f /test/results/testssl.json');
});

it('Should be able to create TCP Stream', function() {
it('Should be able to create TCP Stream', () => {
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/streams',
Expand Down Expand Up @@ -65,7 +65,7 @@ describe('Streams', () => {
});
});

it('Should be able to create UDP Stream', function() {
it('Should be able to create UDP Stream', () => {
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/streams',
Expand All @@ -92,7 +92,7 @@ describe('Streams', () => {
});
});

it('Should be able to create TCP/UDP Stream', function() {
it('Should be able to create TCP/UDP Stream', () => {
cy.task('backendApiPost', {
token: token,
path: '/api/nginx/streams',
Expand Down Expand Up @@ -124,7 +124,7 @@ describe('Streams', () => {
});
});

it('Should be able to create SSL TCP Stream', function() {
it('Should be able to create SSL TCP Stream', () => {
let certID = 0;

// Create custom cert
Expand Down Expand Up @@ -184,7 +184,7 @@ describe('Streams', () => {
cy.exec('/testssl/testssl.sh --quiet --add-ca="$(/bin/mkcert -CAROOT)/rootCA.pem" --jsonfile=/test/results/testssl.json website1.example.com:1503', {
timeout: 120000, // 2 minutes
}).then((result) => {
cy.task('log', '[testssl.sh] ' + result.stdout);
cy.task('log', `[testssl.sh] ${result.stdout}`);

const allowedSeverities = ["INFO", "OK", "LOW", "MEDIUM"];
const ignoredIDs = [
Expand All @@ -210,7 +210,7 @@ describe('Streams', () => {
});
});

it('Should be able to List Streams', function() {
it('Should be able to List Streams', () => {
cy.task('backendApiGet', {
token: token,
path: '/api/nginx/streams?expand=owner,certificate',
Expand Down
Loading