Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
b687548
Merge pull request 'Fork syncthing' (#1) from GitHub/nginx-proxy-mana…
SBado Feb 23, 2022
ecb2752
PROXY Protocol support implementation
SBado Feb 23, 2022
9eabfb9
Merge branch 'NginxProxyManager:develop' into develop
SBado Jun 10, 2022
6c5f198
Merge branch 'develop' into develop
SBado Oct 13, 2022
54864f4
Merge branch 'NginxProxyManager:develop' into develop
SBado Mar 21, 2023
cc6d249
Merge branch 'NginxProxyManager:develop' into develop
SBado May 11, 2023
1eb6a57
Merge branch 'NginxProxyManager:develop' into develop
SBado Sep 1, 2023
fe8f853
Merge branch 'develop' of ssh://github.com/NginxProxyManager/nginx-pr…
adrum Apr 5, 2025
5e73361
bump build
adrum Apr 29, 2025
cf4965c
Update proxy_host.js
Iaotle Jul 1, 2025
db2f4d4
Merge pull request #1 from NikeLaosClericus/patch-1
NikeLaosClericus Jul 16, 2025
1e080c2
enable standard ports when proxy protocol is enabled
adrum Jul 25, 2025
5d14b74
always enable real ip proxy protocol if enabled
adrum Jul 25, 2025
473dbc7
Merge remote-tracking branch 'adrum/develop' into proxy-protocol
reversefold Apr 24, 2026
aa8ac9b
Fix migration script
reversefold Apr 24, 2026
c9c9b0b
Sorted lang files
reversefold Apr 24, 2026
24bdb5d
Fix comments
reversefold Apr 24, 2026
5ec08cf
Fill out missing schema
reversefold Apr 24, 2026
49bb743
Add PROXY protocol ports
reversefold Apr 24, 2026
d9990df
conditionally require and disable the load balancer ip
reversefold Apr 24, 2026
6618f15
Fix lint errors
reversefold Apr 24, 2026
857a35e
Implement down migration and standardize on double quotes
reversefold Apr 25, 2026
5965a6c
Add support for PROXY protocol for Streams
reversefold Apr 25, 2026
57c2fa3
Fix streams tests
reversefold Apr 26, 2026
b81951b
Remove the expects....?
reversefold Apr 26, 2026
cb9d5cf
Add missing parameter to tests, not sure why ProxyHosts test is worki…
reversefold Apr 26, 2026
7317102
This is a regex, it should be a pattern
reversefold Apr 29, 2026
548f3bd
Perhaps the problem is the onChange
reversefold Apr 29, 2026
e727961
Revert "Perhaps the problem is the onChange"
reversefold Apr 29, 2026
1a5f39a
Put back the expects
reversefold Apr 29, 2026
efca9a8
Let's also add a check to ProxyHosts tests to see if it passes
reversefold Apr 29, 2026
a9e5729
Aha! The magic boolean list didn't have enable_proxy_protocol
reversefold Apr 29, 2026
4b58ca6
Fix the name of the property here
reversefold Apr 29, 2026
dcff928
Fix migration variable names
reversefold May 17, 2026
85502c0
Rename this migration that was inherited from the four-year-old branc…
reversefold May 17, 2026
affc800
Remove trailing commas from JSON
reversefold May 17, 2026
fbeb4a5
Remove comment
reversefold May 17, 2026
db73747
Add "or enable_proxy_protocol == true" to make these checks the same…
reversefold May 17, 2026
f5adcf9
load_balancer_ip is actually required
reversefold May 17, 2026
ae28cac
Remove commented code
reversefold May 17, 2026
f9c59d9
Add docs for PROXY protocol listeners
reversefold May 17, 2026
bdcc1c3
Add a test for creating a steram with PROXY protocol enabled
reversefold May 17, 2026
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: 2 additions & 0 deletions backend/internal/nginx.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ const internalNginx = {
{ caching_enabled: host.caching_enabled },
{ block_exploits: host.block_exploits },
{ allow_websocket_upgrade: host.allow_websocket_upgrade },
{ enable_proxy_protocol: host.enable_proxy_protocol },
{ load_balancer_ip: host.load_balancer_ip },
{ http2_support: host.http2_support },
{ hsts_enabled: host.hsts_enabled },
{ hsts_subdomains: host.hsts_subdomains },
Expand Down
41 changes: 41 additions & 0 deletions backend/migrations/20260425014441_proxy_protocol.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const migrate_name = "proxy_protocol";
import { migrate as logger } from "../logger.js";

/**
* Migrate
*
* @see http://knexjs.org/#Schema
*
* @param {Object} knex
* @returns {Promise}
*/
const up = (knex) => {
logger.info(`[${migrate_name}] Migrating Up...`);

return knex.schema.table("proxy_host", (table) => {
table.integer("enable_proxy_protocol").notNull().unsigned().defaultTo(0);
table.string("load_balancer_ip").notNull().defaultTo("");
}).then(() => {
logger.info(`[${migrate_name}] proxy_host Table altered`);
});
};

/**
* Undo Migrate
*
* @param {Object} knex
* @returns {Promise}
*/
const down = (knex) => {
logger.info(`[${migrate_name}] Migrating Down...`);

return knex.schema.table("proxy_host", (table) => {
table.dropColumn("enable_proxy_protocol");
table.dropColumn("load_balancer_ip");
})
.then(() => {
logger.info(`[${migrate_name}] proxy_host Table altered`);
});
};

export { up, down };
40 changes: 40 additions & 0 deletions backend/migrations/20260425014442_proxy_protocol_stream.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const migrate_name = "proxy_protocol_stream";
import { migrate as logger } from "../logger.js";

/**
* Migrate
*
* @see http://knexjs.org/#Schema
*
* @param {Object} knex
* @returns {Promise}
*/
const up = (knex) => {
logger.info(`[${migrate_name}] Migrating Up...`);

return knex.schema.table("stream", (table) => {
table.integer("enable_proxy_protocol").notNull().unsigned().defaultTo(0);
}).then(() => {
logger.info(`[${migrate_name}] stream Table altered`);
});

};

/**
* Undo Migrate
*
* @param {Object} knex
* @returns {Promise}
*/
const down = (knex) => {
logger.info(`[${migrate_name}] Migrating Down...`);

return knex.schema.table("stream", (table) => {
table.dropColumn("enable_proxy_protocol");
})
.then(() => {
logger.info(`[${migrate_name}] stream Table altered`);
});
};

export { up, down };
1 change: 1 addition & 0 deletions backend/models/proxy_host.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const boolFields = [
"hsts_enabled",
"hsts_subdomains",
"trust_forwarded_proto",
"enable_proxy_protocol",
];

class ProxyHost extends Model {
Expand Down
8 changes: 7 additions & 1 deletion backend/models/stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ import User from "./user.js";

Model.knex(db());

const boolFields = ["is_deleted", "enabled", "tcp_forwarding", "udp_forwarding"];
const boolFields = [
"is_deleted",
"enabled",
"tcp_forwarding",
"udp_forwarding",
"enable_proxy_protocol"
];

class Stream extends Model {
$beforeInsert() {
Expand Down
14 changes: 14 additions & 0 deletions backend/schema/components/proxy-host-object.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"advanced_config",
"meta",
"allow_websocket_upgrade",
"enable_proxy_protocol",
"load_balancer_ip",
"http2_support",
"forward_scheme",
"enabled",
Expand Down Expand Up @@ -84,6 +86,18 @@
"type": "boolean",
"example": true
},
"enable_proxy_protocol": {
"description": "Enable PROXY Protocol support",
"example": true,
"type": "boolean"
},
"load_balancer_ip": {
"description": "Load balancer or TCP proxy IP / CIDR range",
"type": "string",
"minLength": 0,
"maxLength": 255,
"example": "10.0.9.3"
},
"http2_support": {
"$ref": "../common.json#/properties/http2_support"
},
Expand Down
10 changes: 8 additions & 2 deletions backend/schema/components/stream-object.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"tcp_forwarding",
"udp_forwarding",
"enabled",
"meta"
"meta",
"enable_proxy_protocol"
],
"additionalProperties": false,
"properties": {
Expand Down Expand Up @@ -44,7 +45,7 @@
},
{
"type": "string",
"format": "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$"
"pattern": "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$"
},
{
"type": "string",
Expand All @@ -70,6 +71,11 @@
"enabled": {
"$ref": "../common.json#/properties/enabled"
},
"enable_proxy_protocol": {
"description": "Enable PROXY Protocol support",
"type": "boolean",
"example": false
},
"certificate_id": {
"$ref": "../common.json#/properties/certificate_id"
},
Expand Down
2 changes: 2 additions & 0 deletions backend/schema/paths/nginx/proxy-hosts/get.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
"nginx_err": null
},
"allow_websocket_upgrade": false,
"enable_proxy_protocol": false,
"load_balancer_ip": "",
"http2_support": false,
"forward_scheme": "http",
"enabled": true,
Expand Down
2 changes: 2 additions & 0 deletions backend/schema/paths/nginx/proxy-hosts/hostID/get.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
"nginx_err": null
},
"allow_websocket_upgrade": false,
"enable_proxy_protocol": false,
"load_balancer_ip": "",
"http2_support": false,
"forward_scheme": "http",
"enabled": true,
Expand Down
8 changes: 8 additions & 0 deletions backend/schema/paths/nginx/proxy-hosts/hostID/put.json
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@
"allow_websocket_upgrade": {
"$ref": "../../../../components/proxy-host-object.json#/properties/allow_websocket_upgrade"
},
"enable_proxy_protocol": {
"$ref": "../../../../components/proxy-host-object.json#/properties/enable_proxy_protocol"
},
"load_balancer_ip": {
"$ref": "../../../../components/proxy-host-object.json#/properties/load_balancer_ip"
},
"access_list_id": {
"$ref": "../../../../components/proxy-host-object.json#/properties/access_list_id"
},
Expand Down Expand Up @@ -119,6 +125,8 @@
"nginx_err": null
},
"allow_websocket_upgrade": false,
"enable_proxy_protocol": false,
"load_balancer_ip": "",
"http2_support": false,
"forward_scheme": "http",
"enabled": true,
Expand Down
8 changes: 8 additions & 0 deletions backend/schema/paths/nginx/proxy-hosts/post.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@
"allow_websocket_upgrade": {
"$ref": "../../../components/proxy-host-object.json#/properties/allow_websocket_upgrade"
},
"enable_proxy_protocol": {
"$ref": "../../../components/proxy-host-object.json#/properties/enable_proxy_protocol"
},
"load_balancer_ip": {
"$ref": "../../../components/proxy-host-object.json#/properties/load_balancer_ip"
},
"access_list_id": {
"$ref": "../../../components/proxy-host-object.json#/properties/access_list_id"
},
Expand Down Expand Up @@ -116,6 +122,8 @@
"advanced_config": "",
"meta": {},
"allow_websocket_upgrade": false,
"enable_proxy_protocol": false,
"load_balancer_ip": "",
"http2_support": false,
"forward_scheme": "http",
"enabled": true,
Expand Down
1 change: 1 addition & 0 deletions backend/schema/paths/nginx/streams/get.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"nginx_err": null
},
"enabled": true,
"enable_proxy_protocol": false,
"certificate_id": 0
}
]
Expand Down
5 changes: 5 additions & 0 deletions backend/schema/paths/nginx/streams/post.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
"certificate_id": {
"$ref": "../../../components/stream-object.json#/properties/certificate_id"
},
"enable_proxy_protocol": {
"$ref": "../../../components/stream-object.json#/properties/enable_proxy_protocol"
},
"meta": {
"$ref": "../../../components/stream-object.json#/properties/meta"
},
Expand All @@ -56,6 +59,7 @@
"tcp_forwarding": true,
"udp_forwarding": false,
"certificate_id": 0,
"enable_proxy_protocol": false,
"meta": {}
}
}
Expand Down Expand Up @@ -83,6 +87,7 @@
"nginx_err": null
},
"enabled": true,
"enable_proxy_protocol": false,
"owner": {
"id": 1,
"created_on": "2024-10-09T02:33:16.000Z",
Expand Down
1 change: 1 addition & 0 deletions backend/schema/paths/nginx/streams/streamID/get.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"nginx_err": null
},
"enabled": true,
"enable_proxy_protocol": false,
"certificate_id": 0
}
}
Expand Down
4 changes: 4 additions & 0 deletions backend/schema/paths/nginx/streams/streamID/put.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@
"certificate_id": {
"$ref": "../../../../components/stream-object.json#/properties/certificate_id"
},
"enable_proxy_protocol": {
"$ref": "../../../../components/stream-object.json#/properties/enable_proxy_protocol"
},
"meta": {
"$ref": "../../../../components/stream-object.json#/properties/meta"
}
Expand Down Expand Up @@ -78,6 +81,7 @@
"nginx_err": null
},
"enabled": true,
"enable_proxy_protocol": false,
"owner": {
"id": 1,
"created_on": "2024-10-09T02:33:16.000Z",
Expand Down
20 changes: 19 additions & 1 deletion backend/templates/_listen.conf
Original file line number Diff line number Diff line change
@@ -1,20 +1,38 @@
{% if enable_proxy_protocol == 1 or enable_proxy_protocol == true%}
listen 88 proxy_protocol;
listen 80;
{% if ipv6 -%}
listen [::]:88 proxy_protocol;
listen [::]:80;
{% endif %}
{% else -%}
listen 80;
{% if ipv6 -%}
listen [::]:80;
{% else -%}
#listen [::]:80;
{% endif %}
{% endif %}
{% if certificate -%}
{% if enable_proxy_protocol == 1 or enable_proxy_protocol == true%}
listen 444 ssl proxy_protocol;
listen 443 ssl;
{% if ipv6 -%}
listen [::]:444 ssl proxy_protocol;
listen [::]:443 ssl;
{% endif %}
{% else -%}
listen 443 ssl;
{% if ipv6 -%}
listen [::]:443 ssl;
{% else -%}
#listen [::]:443;
{% endif %}
{% endif %}
{% endif %}
server_name {{ domain_names | join: " " }};
{% if http2_support == 1 or http2_support == true %}
http2 on;
{% else -%}
http2 off;
{% endif %}
{% endif %}
4 changes: 4 additions & 0 deletions backend/templates/_proxy_protocol.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{% if enable_proxy_protocol == 1 or enable_proxy_protocol == true %}
set_real_ip_from {{ load_balancer_ip }};
real_ip_header proxy_protocol;
{% endif %}
1 change: 1 addition & 0 deletions backend/templates/proxy_host.conf
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ server {
{% include "_exploits.conf" %}
{% include "_hsts.conf" %}
{% include "_forced_ssl.conf" %}
{% include "_proxy_protocol.conf" %}

{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
proxy_set_header Upgrade $http_upgrade;
Expand Down
4 changes: 2 additions & 2 deletions backend/templates/stream.conf
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
{% if enabled %}
{% if tcp_forwarding == 1 or tcp_forwarding == true -%}
server {
listen {{ incoming_port }} {%- if certificate %} ssl {%- endif %};
{% unless ipv6 -%} # {%- endunless -%} listen [::]:{{ incoming_port }} {%- if certificate %} ssl {%- endif %};
listen {{ incoming_port }} {%- if certificate %} ssl {%- endif %} {%- if enable_proxy_protocol == 1 or enable_proxy_protocol == true %} proxy_protocol {%- endif %};
{% unless ipv6 -%} # {%- endunless -%} listen [::]:{{ incoming_port }} {%- if certificate %} ssl {%- endif %} {%- if enable_proxy_protocol == 1 or enable_proxy_protocol == true %} proxy_protocol {%- endif %};

{%- include "_certificates_stream.conf" %}

Expand Down
2 changes: 2 additions & 0 deletions docker/docker-compose.dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ services:
ports:
- 3080:80
- 3081:81
- 3088:88
- 3443:443
- 3444:444
networks:
nginx_proxy_manager:
aliases:
Expand Down
13 changes: 13 additions & 0 deletions docs/src/advanced-config/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,3 +248,16 @@ On startup, we generate a resolvers directive for Nginx unless this is defined:

In this configuration, all DNS queries performed by Nginx will fall to the `/etc/hosts` file
and then the `/etc/resolv.conf`.

## Using PROXY protocol

If you are using PROXY protocol support for any proxy host or stream you will need to expose ports `88` and `444` for HTTP and HTTPS listeners with PROXY protocol support.
```yml
ports:
# Public HTTP Port with PROXY protocol:
- '88:88'
# Public HTTPS Port with PROXY protocol:
- '444:444'
```

NPM will still listen on ports `80` and `443` for proxy hosts and streams where the PROXY protocol option has not been enabled.
Loading