Skip to content
Merged

v2.13.5 #4956

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
a85b5f6
Bump version after rebase
fhennig42 Nov 4, 2025
990ba28
Update SiteFooter.tsx
sopex Nov 10, 2025
f1d7203
v2
sopex Nov 10, 2025
b434bba
remove hardcoded version number
sopex Nov 10, 2025
b6dbb68
Update SiteFooter.tsx
sopex Nov 10, 2025
ae5faa7
backend test
sopex Nov 11, 2025
dc03ad8
minimal changes
sopex Nov 11, 2025
87eef10
remove useCallback logic
sopex Nov 11, 2025
b043e70
add azure-mgmt-dns fix version as dependency
fhennig42 Nov 12, 2025
2d6252d
https.get
sopex Nov 12, 2025
15394c6
trigger Jenkins that failed due to internet connection problems
sopex Nov 12, 2025
17cc75f
Fix language and theme selectors on mobile and desktop
7heMech Nov 12, 2025
d783cc3
Remove unused styles
7heMech Nov 12, 2025
66fa08f
Add profile back to main app on mobile
7heMech Nov 12, 2025
6ce9567
Merge pull request #4816 from fhennig42/azure-dns
jc21 Nov 12, 2025
e86a34f
Close menu after navigation.
7heMech Nov 12, 2025
963125f
Space scandal retified (hopefully)
7heMech Nov 12, 2025
911476f
Delay before close for smooth feel.
7heMech Nov 12, 2025
b4fd242
remove 1
sopex Nov 12, 2025
f40fe56
Add new section with theme and locale pickers.
7heMech Nov 12, 2025
9be1381
Uhhh, I didn't like the Standard User lol
7heMech Nov 12, 2025
75c012b
Fix linter error
7heMech Nov 12, 2025
8838dab
Merge pull request #4906 from sopex/develop
jc21 Nov 13, 2025
dadd10f
Fixed my troubles with text wrap
7heMech Nov 13, 2025
1c442dc
True mobile layout with responsive table rows (sticky header)
7heMech Nov 13, 2025
cf7306e
Tweaks to showing new version available
jc21 Nov 13, 2025
7e875eb
Change docker ci expose format for docker 28 :/
jc21 Nov 13, 2025
8959190
Change docker ci expose format for docker 28 :/
jc21 Nov 13, 2025
e5aae1f
Fix openapi schema format
jc21 Nov 13, 2025
79a9653
Remove the compiled lang files, compile on dev server and when buildi…
jc21 Nov 13, 2025
47db5c9
Fixed typo: corrected 'role' to proper Polish declension 'rola'
Nov 13, 2025
d848ba9
Fixed typo: corrected 'role' to proper Polish declension 'rola' and '…
Nov 13, 2025
7f9b9df
Fix for dropdown menus being clipped by table-responsive containers.
7heMech Nov 13, 2025
824c895
Remove cn where not needed
7heMech Nov 13, 2025
9807e25
Remove unused import
7heMech Nov 13, 2025
9b2d60e
Update Russian locale
kraineff Nov 13, 2025
afd6134
Get rid of logo flicker and improve LCP
7heMech Nov 13, 2025
8c3c964
Fix page offset
7heMech Nov 13, 2025
960d4bf
Revert change which should have no effect on theory
7heMech Nov 13, 2025
45a8d50
Add IT Translation
archettitechnology Nov 13, 2025
4ca5cad
Add Italian language support to IntlProvider
archettitechnology Nov 13, 2025
8774cfe
Add Italian locale to check-locales
archettitechnology Nov 13, 2025
8d8463a
Add Italian language support to HelpDoc
archettitechnology Nov 13, 2025
fb53df8
Add Italian documentation for Access Lists
archettitechnology Nov 13, 2025
d0f7dc5
Add Italian HelpDoc for certificate options
archettitechnology Nov 13, 2025
c281fc5
Add Italian HelpDoc for 404 Host explanation
archettitechnology Nov 13, 2025
b23ceeb
Add Italian documentation for ProxyHost
archettitechnology Nov 13, 2025
5fc9feb
Update title of ProxyHost.md in Italian
archettitechnology Nov 13, 2025
bc341c1
Add RedirectionHosts.md with explanation in Italian
archettitechnology Nov 13, 2025
8ef65ca
Add Italian documentation for Streams feature
archettitechnology Nov 13, 2025
74cbfb2
Create indes.ts to export HelpDoc modules
archettitechnology Nov 13, 2025
0bcfe0b
Add Italian language support to lang-list.json
archettitechnology Nov 13, 2025
d7384c5
Fix #4933 when cert may not have domain names
jc21 Nov 13, 2025
118c479
Amend locale readme
jc21 Nov 13, 2025
0ec1a09
fix issues #4939
vsc55 Nov 13, 2025
2c630bb
Merge branch 'develop' into develop
jc21 Nov 14, 2025
5288fbd
Update index.ts
archettitechnology Nov 14, 2025
7536b1b
Merge branch 'develop' into develop
archettitechnology Nov 14, 2025
a4d54a0
Merge pull request #4932 from kraineff/develop
jc21 Nov 14, 2025
60f3ee0
Fix typo in file name from 'indes.ts' to 'index.ts'
archettitechnology Nov 14, 2025
66ebecd
Merge branch 'develop' into develop
archettitechnology Nov 14, 2025
9d8c4cc
Rename DeadHost.md to DeadHosts.md
archettitechnology Nov 14, 2025
6cae088
Rename ProxyHost.md to ProxyHosts.md
archettitechnology Nov 14, 2025
fdc0c29
Improve modals in dark mode via a dark backdrop and shadow.
7heMech Nov 14, 2025
2650648
Bump js-yaml from 4.1.0 to 4.1.1 in /backend
dependabot[bot] Nov 15, 2025
87ec9c4
Fix message for GitHub fork reference in zh.json
gjssss Nov 15, 2025
fce569c
Modify host.forward-port to avoid line breaks
vsc55 Nov 16, 2025
9b4c349
Update porkbun certbot plugin
jc21 Nov 16, 2025
81f2aa1
Add vietnamese
dominhhieu1405 Nov 17, 2025
890d06c
Update Slovak language label
dodog Nov 17, 2025
316b758
Tweaks to cypress suite
jc21 Nov 17, 2025
2d4b739
Merge pull request #4953 from dodog/develop
jc21 Nov 18, 2025
de7d3b0
Merge pull request #4950 from dominhhieu1405/develop
jc21 Nov 18, 2025
c7f999f
Merge pull request #4944 from gjssss/patch-1
jc21 Nov 18, 2025
32ab3fa
Merge pull request #4943 from NginxProxyManager/dependabot/npm_and_ya…
jc21 Nov 18, 2025
decdfec
Merge branch 'develop' into develop
jc21 Nov 18, 2025
a87f24c
Merge pull request #4940 from vsc55/issues_4939
jc21 Nov 18, 2025
d49ff6e
Merge pull request #4934 from zdzichu6969/develop
jc21 Nov 18, 2025
f1039ce
Merge pull request #4928 from 7heMech/develop
jc21 Nov 18, 2025
2c11c0c
Merge pull request #4937 from archettitechnology/develop
jc21 Nov 18, 2025
484ce8d
Add Dutch language
Jelcoo Nov 13, 2025
2c6d614
Add HelpDoc translations
Jelcoo Nov 13, 2025
c2177ab
Add language to frontend settings & correct some translations
Jelcoo Nov 13, 2025
cfa9836
Merge pull request #4955 from NginxProxyManager/lang-nl
jc21 Nov 18, 2025
dc89635
Fix up locales, optimised some functions
jc21 Nov 18, 2025
3231023
Bump version
jc21 Nov 18, 2025
89b8b74
Merge branch 'master' into develop
jc21 Nov 18, 2025
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.13.4
2.13.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.13.4-green.svg?style=for-the-badge">
<img src="https://img.shields.io/badge/version-2.13.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
6 changes: 3 additions & 3 deletions backend/certbot/dns-plugins.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
"azure": {
"name": "Azure",
"package_name": "certbot-dns-azure",
"version": "~=1.2.0",
"dependencies": "",
"version": "~=2.6.1",
"dependencies": "azure-mgmt-dns==8.2.0",
"credentials": "# This plugin supported API authentication using either Service Principals or utilizing a Managed Identity assigned to the virtual machine.\n# Regardless which authentication method used, the identity will need the “DNS Zone Contributor” role assigned to it.\n# As multiple Azure DNS Zones in multiple resource groups can exist, the config file needs a mapping of zone to resource group ID. Multiple zones -> ID mappings can be listed by using the key dns_azure_zoneX where X is a unique number. At least 1 zone mapping is required.\n\n# Using a service principal (option 1)\ndns_azure_sp_client_id = 912ce44a-0156-4669-ae22-c16a17d34ca5\ndns_azure_sp_client_secret = E-xqXU83Y-jzTI6xe9fs2YC~mck3ZzUih9\ndns_azure_tenant_id = ed1090f3-ab18-4b12-816c-599af8a88cf7\n\n# Using used assigned MSI (option 2)\n# dns_azure_msi_client_id = 912ce44a-0156-4669-ae22-c16a17d34ca5\n\n# Using system assigned MSI (option 3)\n# dns_azure_msi_system_assigned = true\n\n# Zones (at least one always required)\ndns_azure_zone1 = example.com:/subscriptions/c135abce-d87d-48df-936c-15596c6968a5/resourceGroups/dns1\ndns_azure_zone2 = example.org:/subscriptions/99800903-fb14-4992-9aff-12eaf2744622/resourceGroups/dns2",
"full_plugin_name": "dns-azure"
},
Expand Down Expand Up @@ -482,7 +482,7 @@
"porkbun": {
"name": "Porkbun",
"package_name": "certbot-dns-porkbun",
"version": "~=0.9",
"version": "~=0.11.0",
"dependencies": "",
"credentials": "dns_porkbun_key=your-porkbun-api-key\ndns_porkbun_secret=your-porkbun-api-secret",
"full_plugin_name": "dns-porkbun"
Expand Down
84 changes: 84 additions & 0 deletions backend/internal/remote-version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import https from "node:https";
import { ProxyAgent } from "proxy-agent";
import { debug, remoteVersion as logger } from "../logger.js";
import pjson from "../package.json" with { type: "json" };

const VERSION_URL = "https://api.github.com/repos/NginxProxyManager/nginx-proxy-manager/releases/latest";

const internalRemoteVersion = {
cache_timeout: 1000 * 60 * 15, // 15 minutes
last_result: null,
last_fetch_time: null,

/**
* Fetch the latest version info, using a cached result if within the cache timeout period.
* @return {Promise<{current: string, latest: string, update_available: boolean}>} Version info
*/
get: async () => {
if (
!internalRemoteVersion.last_result ||
!internalRemoteVersion.last_fetch_time ||
Date.now() - internalRemoteVersion.last_fetch_time > internalRemoteVersion.cache_timeout
) {
const raw = await internalRemoteVersion.fetchUrl(VERSION_URL);
const data = JSON.parse(raw);
internalRemoteVersion.last_result = data;
internalRemoteVersion.last_fetch_time = Date.now();
} else {
debug(logger, "Using cached remote version result");
}

const latestVersion = internalRemoteVersion.last_result.tag_name;
const version = pjson.version.split("-").shift().split(".");
const currentVersion = `v${version[0]}.${version[1]}.${version[2]}`;
return {
current: currentVersion,
latest: latestVersion,
update_available: internalRemoteVersion.compareVersions(currentVersion, latestVersion),
};
},

fetchUrl: (url) => {
const agent = new ProxyAgent();
const headers = {
"User-Agent": `NginxProxyManager v${pjson.version}`,
};

return new Promise((resolve, reject) => {
logger.info(`Fetching ${url}`);
return https
.get(url, { agent, headers }, (res) => {
res.setEncoding("utf8");
let raw_data = "";
res.on("data", (chunk) => {
raw_data += chunk;
});
res.on("end", () => {
resolve(raw_data);
});
})
.on("error", (err) => {
reject(err);
});
});
},

compareVersions: (current, latest) => {
const cleanCurrent = current.replace(/^v/, "");
const cleanLatest = latest.replace(/^v/, "");

const currentParts = cleanCurrent.split(".").map(Number);
const latestParts = cleanLatest.split(".").map(Number);

for (let i = 0; i < Math.max(currentParts.length, latestParts.length); i++) {
const curr = currentParts[i] || 0;
const lat = latestParts[i] || 0;

if (lat > curr) return true;
if (lat < curr) return false;
}
return false;
},
};

export default internalRemoteVersion;
3 changes: 2 additions & 1 deletion backend/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ const certbot = new signale.Signale({ scope: "Certbot ", ...opts });
const importer = new signale.Signale({ scope: "Importer ", ...opts });
const setup = new signale.Signale({ scope: "Setup ", ...opts });
const ipRanges = new signale.Signale({ scope: "IP Ranges", ...opts });
const remoteVersion = new signale.Signale({ scope: "Remote Version", ...opts });

const debug = (logger, ...args) => {
if (isDebugMode()) {
logger.debug(...args);
}
};

export { debug, global, migrate, express, access, nginx, ssl, certbot, importer, setup, ipRanges };
export { debug, global, migrate, express, access, nginx, ssl, certbot, importer, setup, ipRanges, remoteVersion };
2 changes: 2 additions & 0 deletions backend/routes/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import schemaRoutes from "./schema.js";
import settingsRoutes from "./settings.js";
import tokensRoutes from "./tokens.js";
import usersRoutes from "./users.js";
import versionRoutes from "./version.js";

const router = express.Router({
caseSensitive: true,
Expand Down Expand Up @@ -46,6 +47,7 @@ router.use("/users", usersRoutes);
router.use("/audit-log", auditLogRoutes);
router.use("/reports", reportsRoutes);
router.use("/settings", settingsRoutes);
router.use("/version", versionRoutes);
router.use("/nginx/proxy-hosts", proxyHostsRoutes);
router.use("/nginx/redirection-hosts", redirectionHostsRoutes);
router.use("/nginx/dead-hosts", deadHostsRoutes);
Expand Down
40 changes: 40 additions & 0 deletions backend/routes/version.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import express from "express";
import internalRemoteVersion from "../internal/remote-version.js";
import { debug, express as logger } from "../logger.js";

const router = express.Router({
caseSensitive: true,
strict: true,
mergeParams: true,
});

/**
* /api/version/check
*/
router
.route("/check")
.options((_, res) => {
res.sendStatus(204);
})

/**
* GET /api/version/check
*
* Check for available updates
*/
.get(async (req, res, _next) => {
try {
const data = await internalRemoteVersion.get();
res.status(200).send(data);
} catch (error) {
debug(logger, `${req.method.toUpperCase()} ${req.path}: ${error}`);
// Send 200 even though there's an error to avoid triggering update checks repeatedly
res.status(200).send({
current: null,
latest: null,
update_available: false,
});
}
});

export default router;
23 changes: 23 additions & 0 deletions backend/schema/components/check-version-object.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"type": "object",
"description": "Check Version object",
"additionalProperties": false,
"required": ["current", "latest", "update_available"],
"properties": {
"current": {
"type": ["string", "null"],
"description": "Current version string",
"example": "v2.10.1"
},
"latest": {
"type": ["string", "null"],
"description": "Latest version string",
"example": "v2.13.4"
},
"update_available": {
"type": "boolean",
"description": "Whether there's an update available",
"example": true
}
}
}
26 changes: 26 additions & 0 deletions backend/schema/paths/version/check/get.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"operationId": "checkVersion",
"summary": "Returns any new version data from github",
"tags": ["public"],
"responses": {
"200": {
"description": "200 response",
"content": {
"application/json": {
"examples": {
"default": {
"value": {
"current": "v2.12.0",
"latest": "v2.13.4",
"update_available": true
}
}
},
"schema": {
"$ref": "../../../components/check-version-object.json"
}
}
}
}
}
}
5 changes: 5 additions & 0 deletions backend/schema/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,11 @@
"$ref": "./paths/tokens/post.json"
}
},
"/version/check": {
"get": {
"$ref": "./paths/version/check/get.json"
}
},
"/users": {
"get": {
"$ref": "./paths/users/get.json"
Expand Down
6 changes: 3 additions & 3 deletions backend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1430,9 +1430,9 @@ isexe@^2.0.0:
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==

js-yaml@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
version "4.1.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b"
integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==
dependencies:
argparse "^2.0.1"

Expand Down
8 changes: 6 additions & 2 deletions docker/docker-compose.ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@ services:
interval: 10s
timeout: 3s
expose:
- "80-81/tcp"
- "80/tcp"
- "81/tcp"
- "443/tcp"
- "1500-1503/tcp"
- "1500/tcp"
- "1501/tcp"
- "1502/tcp"
- "1503/tcp"
networks:
fulltest:
aliases:
Expand Down
2 changes: 2 additions & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
src/locale/lang

# Logs
logs
*.log
Expand Down
8 changes: 6 additions & 2 deletions frontend/check-locales.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@

const allLocales = [
["en", "en-US"],
["es", "es-ES"],
["de", "de-DE"],
["es", "es-ES"],
["it", "it-IT"],
["ja", "ja-JP"],
["nl", "nl-NL"],
["pl", "pl-PL"],
["ru", "ru-RU"],
["sk", "sk-SK"],
["vi", "vi-VN"],
["zh", "zh-CN"],
["pl", "pl-PL"],
];

const ignoreUnused = [
Expand Down
1 change: 1 addition & 0 deletions frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Nginx Proxy Manager</title>
<meta name="description" content="In The Office Planner" />
<link rel="preload" href="/images/logo-no-text.svg" as="image" type="image/svg+xml" fetchPriority="high">
<link
rel="apple-touch-icon"
sizes="180x180"
Expand Down
21 changes: 21 additions & 0 deletions frontend/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@
--tblr-backdrop-opacity: 0.8 !important;
}

[data-bs-theme="dark"] .modal-content {
--tblr-modal-box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15) !important;
}

[data-bs-theme="dark"] .modal-backdrop {
--tblr-backdrop-bg: #000 !important;
--tblr-backdrop-opacity: 0.65 !important;
}

.domain-name {
font-family: monospace;
}
Expand Down Expand Up @@ -95,3 +104,15 @@ label.row {
border-radius: var(--tblr-border-radius) 0 0 var(--tblr-border-radius);
}
}

/* Fix for dropdown menus being clipped by table-responsive containers. */
.table-responsive .dropdown {
position: static;
}

/* Fix for Tabler scrollbar compensation */
@media (min-width: 992px) {
:host, :root {
margin-left: 0;
}
}
8 changes: 8 additions & 0 deletions frontend/src/api/backend/checkVersion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as api from "./base";
import type { VersionCheckResponse } from "./responseTypes";

export async function checkVersion(): Promise<VersionCheckResponse> {
return await api.get({
url: "/version/check",
});
}
1 change: 1 addition & 0 deletions frontend/src/api/backend/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./checkVersion";
export * from "./createAccessList";
export * from "./createCertificate";
export * from "./createDeadHost";
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/api/backend/responseTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,9 @@ export interface ValidatedCertificateResponse {
export interface LoginAsTokenResponse extends TokenResponse {
user: User;
}

export interface VersionCheckResponse {
current: string | null;
latest: string | null;
updateAvailable: boolean;
}
Loading
Loading