Files
nginx-proxy-manager/frontend/src/api/backend/models.ts
jerry-yuan 187d21a0d5 feat: add trust_forwarded_proto option for SSL redirect handling in reverse proxy scenarios
When Nginx is behind another proxy server (like CloudFlare or AWS ALB), the force-SSL
feature can cause redirect loops because Nginx sees the connection as plain HTTP
while SSL is already handled upstream. This adds a new boolean option to trust
the X-Forwarded-Proto header from upstream proxies.

Changes:
- Add `trust_forwarded_proto` column to proxy_host table (migration)
- Update model and API schema to support the new boolean field
- Modify force-ssl Nginx template to check X-Forwarded-Proto/X-Forwarded-Scheme
- Add map directives in nginx.conf to validate and sanitize forwarded headers
- Add advanced option toggle in frontend UI with i18n support (EN/ZH)
- Set proxy headers from validated map variables instead of $scheme

This allows administrators to control SSL redirect behavior when Nginx is deployed
behind a TLS-terminating proxy.
2026-01-31 13:11:47 +00:00

211 lines
4.0 KiB
TypeScript

export interface AppVersion {
major: number;
minor: number;
revision: number;
}
export interface UserPermissions {
id?: number;
createdOn?: string;
modifiedOn?: string;
userId?: number;
visibility: string;
proxyHosts: string;
redirectionHosts: string;
deadHosts: string;
streams: string;
accessLists: string;
certificates: string;
}
export interface User {
id: number;
createdOn: string;
modifiedOn: string;
isDisabled: boolean;
email: string;
name: string;
nickname: string;
avatar: string;
roles: string[];
permissions?: UserPermissions;
}
export interface AuditLog {
id: number;
createdOn: string;
modifiedOn: string;
userId: number;
objectType: string;
objectId: number;
action: string;
meta: Record<string, any>;
// Expansions:
user?: User;
}
export interface AccessList {
id?: number;
createdOn?: string;
modifiedOn?: string;
ownerUserId: number;
name: string;
meta: Record<string, any>;
satisfyAny: boolean;
passAuth: boolean;
proxyHostCount?: number;
// Expansions:
owner?: User;
items?: AccessListItem[];
clients?: AccessListClient[];
}
export interface AccessListItem {
id?: number;
createdOn?: string;
modifiedOn?: string;
accessListId?: number;
username: string;
password: string;
meta?: Record<string, any>;
hint?: string;
}
export type AccessListClient = {
id?: number;
createdOn?: string;
modifiedOn?: string;
accessListId?: number;
address: string;
directive: "allow" | "deny";
meta?: Record<string, any>;
};
export interface Certificate {
id: number;
createdOn: string;
modifiedOn: string;
ownerUserId: number;
provider: string;
niceName: string;
domainNames: string[];
expiresOn: string;
meta: Record<string, any>;
owner?: User;
proxyHosts?: ProxyHost[];
deadHosts?: DeadHost[];
redirectionHosts?: RedirectionHost[];
}
export interface ProxyLocation {
path: string;
advancedConfig: string;
forwardScheme: string;
forwardHost: string;
forwardPort: number;
}
export interface ProxyHost {
id: number;
createdOn: string;
modifiedOn: string;
ownerUserId: number;
domainNames: string[];
forwardScheme: string;
forwardHost: string;
forwardPort: number;
accessListId: number;
certificateId: number;
sslForced: boolean;
cachingEnabled: boolean;
blockExploits: boolean;
advancedConfig: string;
meta: Record<string, any>;
allowWebsocketUpgrade: boolean;
http2Support: boolean;
enabled: boolean;
locations?: ProxyLocation[];
hstsEnabled: boolean;
hstsSubdomains: boolean;
trustForwardedProto: boolean;
// Expansions:
owner?: User;
accessList?: AccessList;
certificate?: Certificate;
}
export interface DeadHost {
id: number;
createdOn: string;
modifiedOn: string;
ownerUserId: number;
domainNames: string[];
certificateId: number;
sslForced: boolean;
advancedConfig: string;
meta: Record<string, any>;
http2Support: boolean;
enabled: boolean;
hstsEnabled: boolean;
hstsSubdomains: boolean;
// Expansions:
owner?: User;
certificate?: Certificate;
}
export interface RedirectionHost {
id: number;
createdOn: string;
modifiedOn: string;
ownerUserId: number;
domainNames: string[];
forwardDomainName: string;
preservePath: boolean;
certificateId: number;
sslForced: boolean;
blockExploits: boolean;
advancedConfig: string;
meta: Record<string, any>;
http2Support: boolean;
forwardScheme: string;
forwardHttpCode: number;
enabled: boolean;
hstsEnabled: boolean;
hstsSubdomains: boolean;
// Expansions:
owner?: User;
certificate?: Certificate;
}
export interface Stream {
id: number;
createdOn: string;
modifiedOn: string;
ownerUserId: number;
incomingPort: number;
forwardingHost: string;
forwardingPort: number;
tcpForwarding: boolean;
udpForwarding: boolean;
meta: Record<string, any>;
enabled: boolean;
certificateId: number;
// Expansions:
owner?: User;
certificate?: Certificate;
}
export interface Setting {
id: string;
name?: string;
description?: string;
value: string;
meta?: Record<string, any>;
}
export interface DNSProvider {
id: string;
name: string;
credentials: string;
}