Commit graph

201 commits

Author SHA1 Message Date
Alexis Loskoutoff
82529d6402 Require certificates:create permission to validate certificates 2026-10-13 18:34:20 +02:00
Jamie Curnow
2afd723cd8 Fix access list rules and SSL missing from re-rendered host configs
Some paths rendered host configs without fully loading the relations
the templates depend on, silently dropping access rules (and SSL):

- Enabling a proxy host loaded the access list without its clients or
  auth items, so the host came back with no access restrictions.
- Requesting a Let's Encrypt certificate re-rendered every host sharing
  its domains from bare rows, dropping access rules and SSL.

generateConfig now loads any referenced certificate or access list that
isn't fully loaded, so no caller can render a partial config. The two
callers above also fetch the relations themselves, and a warning is
logged when a host's access list is missing or has no rules.

Adds integration tests covering access lists across disable/enable.

Fixes #5919, #4286, #5710

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 22:13:31 +10:00
Amit Yadav
a54b73f153 fix: omit certificate_key from certificate API responses
The private key of custom certificates was returned in meta by GET /api/nginx/certificates and GET /api/nginx/certificates/{id}. Add meta.certificate_key to omissions(), the same way meta.dns_provider_credentials is hidden. The key stays in the database and is still written to /data/custom_ssl on upload.
2026-09-25 20:35:32 +05:30
Jamie Curnow
2cfd3395cf Adds integration tests for per path access lists, fixes ipv6 jsv,
and enforces host-wide access list when location access list is not set
2026-09-24 12:21:49 +10:00
Dimas Rakha Wisnu
633b653f79
Merge branch 'develop' into develop 2026-09-23 18:53:06 +07:00
jc21
c53f52ab51
Merge pull request #5878 from carlosalbertorg/feat/log-viewer
feat: Add a Logs viewer to the admin UI
2026-09-23 20:23:26 +10:00
carlosalbertorg
9445038b36 fix: Use forwarding_host instead of the renamed forward_ip column
The stream table's forward_ip column was renamed to forwarding_host
back in migration 20210423103500_stream_domain.js, so the stream log
source labels were always showing "undefined" for the forwarding
target. Spotted by @jc21 in review.
2026-09-23 07:00:19 -03:00
jc21
b1e0473a19
Merge pull request #5741 from addielaruee/fix/stream-ipv6-forward-host-brackets
fix(stream): bracket IPv6 forward host for valid nginx upstream
2026-09-23 14:29:27 +10:00
jc21
da12ee5b0c
Merge pull request #5814 from shawnhank/fix/dns-credentials-lifetime
Remove DNS provider credentials from disk after certbot runs
2026-09-23 14:08:29 +10:00
carlosalbertorg
4282d6c6e9 feat: Add a Logs viewer to the admin UI
Nginx Proxy Manager had no way to inspect application or nginx logs
from the web UI - admins had to shell into the container or read
`docker logs`. This adds an admin-only Logs page that can tail:

- the backend application log, now also mirrored to
  /data/logs/backend.log (in addition to stdout) and rotated by the
  logrotate timer that already runs every 2 days
- the Let's Encrypt/certbot log, which certbot already writes to
  /data/logs/letsencrypt.log via its existing --logs-dir flag
- per-host nginx access/error logs (proxy, redirection, 404 and
  stream hosts), with the file path always resolved server-side from
  a validated host_type enum + numeric host_id, never from client
  input

Reads use a reverse chunked scan (64KB chunks, capped at 5MB scanned
per request) instead of loading whole files into memory, and the
frontend polls every 5s only while the tab is focused and "Live" is
on, so this stays cheap on both CPU and memory. No new runtime
dependencies were added on either side.

Purely additive: two new admin-only endpoints
(GET /api/logs/sources, GET /api/logs/tail), no existing behaviour
changed.
2026-09-22 13:11:38 -03:00
José M. Requena Plens
e4585ac688
Stamp the password change from the app clock, not the database one
Your CI caught this: the check passed on SQLite and never fired on the
stack where the database container runs on a different timezone from the
app, so a stale token stayed valid. The comparison was between a token's
`iat`, which is UTC seconds from Node, and `auth.modified_on`, which the
driver hands back interpreted in the app's timezone. With the app on
Australia/Brisbane and the database on UTC, that column comes back ten
hours in the past and the token always looks newer than the change.

Record the moment in `auth.meta.password_changed_at` instead, written by
`setPassword` with the same `Date.now()` clock that mints `iat`. Same
unit on both sides, one clock, and no timestamp parsing: the Date and
local-string branch is gone, and so is the whole-second flooring that
Postgres microseconds made necessary.

Rows written before this have no marker and revoke nothing until their
next password change, which is the safe direction to be wrong in.
2026-09-06 20:15:12 +02:00
Shawn Hank
918728fcac Remove DNS provider credentials from disk after certbot runs
The credentials file written for a DNS-01 challenge was only cleaned up when
certbot failed - the unlink sat in a catch block. On success the file stayed in
/etc/letsencrypt/credentials for the entire life of the certificate, holding a
live DNS provider API token in plaintext.

The file cannot simply be deleted at issuance, because certbot records its path
in the renewal config and reads it back on every `certbot renew`. So the renew
path now writes the file itself immediately before invoking certbot, and both
paths remove it in a finally block.

Net effect: the credentials exist on disk for the duration of a certbot run
rather than permanently. The value still lives in the certificates table, which
is unavoidable - it has to come from somewhere to be written at all.

renewLetsEncryptSslWithDnsChallenge reads the row directly from the model
because renew() sources its certificate from internalCertificate.get(), which
strips meta.dns_provider_credentials via omissions().
2026-08-28 17:40:21 -06:00
vzagorovskiy
a570c0e503 Keep the failed nginx config as a .conf.err file
When `nginx -t` fails, configure() is meant to move the broken config to
<id>.conf.err so the failure can be inspected. renameConfigAsError()
unlinked the source file before renaming it, so the rename always failed
and the config was simply deleted. The deleteConfig() call after it then
removed any .err file left over from an earlier failure.

- unlink the destination .err file instead of the source
- return the rename promise so the delete does not race it
- pass delete_err_file = false so the new .err file survives
- drop the stale 4th argument in the success path, which silently made
  delete_err_file false and left old .err files behind
2026-08-28 11:47:02 +03:00
vgoer
08b4bbdbd4 fix: Changes not taking effect 2026-08-26 07:39:31 +00:00
Jamie Curnow
4e2b052b50 Updated backend packages 2026-08-22 23:10:26 +10:00
Dimas R. Wisnu
35ad8227d7 fix: resolve biome lint errors
- Use optional chaining for nullable checks
- Replace template literals with string literals for plain SQL
- Add node: protocol to fs/promises import in setup.js
2026-08-07 17:01:20 +07:00
Dimas R. Wisnu
4a0f212289 feat: per-path access lists, host logs modal, PostgreSQL support
- Per-path access lists: assign different access lists to individual
  locations on the same proxy host
- Host logs modal: view access/error logs from proxy host dropdown
- PostgreSQL JSON containment query (@>) for location regeneration
- Locale keys: action.logs, column.error
2026-08-07 16:40:32 +07:00
addielarue
9aa7fd5722
fix(stream): bracket IPv6 forward host for valid nginx upstream
A Stream Host with an IPv6 address as the Forward Host was accepted and
saved but never activated. The generated stream config rendered
`proxy_pass {{ forwarding_host }}:{{ forwarding_port }}` as e.g.
`fe80::528:3c87:e7bb:ab08:25`, which nginx rejects with
"invalid port in upstream" because an IPv6 literal must be wrapped in
square brackets before the port is appended (`[fe80::...]:25`).

Normalize the stream forward host in generateConfig (alongside the existing
per-host-type data massaging) using net.isIPv6(), so IPv6 hosts render as
`[address]:port` while IPv4 addresses and hostnames are emitted unchanged.
The mutation is applied to the deep-copied render object, so persisted and
audit data are unaffected.

Fixes #5740
2026-07-25 22:55:58 +10:00
Jamie Curnow
f53bf88f4d Update cypress docker version, generate custom certs each time 2026-05-19 08:04:49 +10:00
Jamie Curnow
ee1f7ba551 Fall back to error code 500 when not set in error object 2026-05-18 16:55:41 +10:00
Jamie Curnow
586dfd36a9 Fix openssl3 formatting of subject cn 2026-05-18 16:12:02 +10:00
Jamie Curnow
2bf9e9b213 Support different cert info output in new version of debian 2026-05-18 15:52:52 +10:00
Jamie Curnow
84886383a7 Fix certificates getting null domain names whgen no cn exists 2026-05-18 15:21:55 +10:00
jc21
d099b00463
Merge pull request #5421 from edklesel/access-list-clients-ordered-insert
Access list clients ordered insert
2026-05-14 11:39:32 +10:00
jc21
13cfa340de
Merge pull request #5508 from Zoey2936/fix-5441
Fix bug that allowed any authenticated user to modify their own roles field through the PUT
2026-05-14 10:23:31 +10:00
Jamie Curnow
7d58c579fa Fix backend linting 2026-05-13 13:40:06 +10:00
Jamie Curnow
18b3404f46 Update all packages and fix related problems 2026-05-13 13:27:59 +10:00
Zoey
1ad78af5a0
fix #5441 2026-04-26 14:14:30 +02:00
Edward Klesel
1635e512c7 Change access list client insert to synchronous to ensure order preserved 2026-03-21 21:49:28 +00:00
Jamie Curnow
eb67b3bfb6 Regenerate configs improvements
- Fix certificates
- Adds dry run
- code cleanup
2026-03-03 08:44:42 +10:00
Tech-no-1
40f363bd4f Fix uploading of custom certificates 2026-02-17 02:58:18 +01:00
7heMech
1d14f72ba5 Add guardrail for disable 2fa 2026-02-14 06:28:59 +00:00
Jamie Curnow
13fbc53591 Fix bug when adding invalid custom certs 2026-02-10 14:54:33 +10:00
Jamie Curnow
d19f5c1960 Fix upgrade problem with otplib existing secrets 2026-02-05 13:12:54 +10:00
Jamie Curnow
c88de65d3a Fix #5274 2fa backup codes not validating properly 2026-02-05 10:51:15 +10:00
Jamie Curnow
f90066822f Fix v13 otplib upgrades 2026-02-04 07:47:16 +10:00
Jamie Curnow
462c134751 2fa work slight refactor
- use existing access mechanisms for validation
- adds swagger/schema and validation of incoming payload
2026-01-14 11:45:12 +10:00
jc21
582681e3ff
Merge pull request #5080 from bzuro/develop
Change visibility to permission_visibility in report.js
2026-01-13 14:52:45 +10:00
jc21
b30f8e47e2
Merge pull request #5109 from piotrfx/develop
Add TOTP-based two-factor authentication
2026-01-13 14:30:48 +10:00
kk.cheng
471b62c7fe Add option to select RSA or ECDSA key type when creating certificates 2026-01-07 19:13:12 +08:00
piotrfx
427afa55b4 Add TOTP-based two-factor authentication
- Add 2FA setup, enable, disable, and backup code management
- Integrate 2FA challenge flow into login process
- Add frontend modal for 2FA configuration
- Support backup codes for account recovery
2025-12-28 11:58:30 +01:00
bzuro
da519e72ba
Change visibility to permission_visibility in report.js
fix for issue #2014
when even administrator with all_items visibility got 0 proxy hosts in dashboard.
2025-12-14 00:35:22 +01:00
Jamie Curnow
cf7306e766
Tweaks to showing new version available
- Added frontend translation for english
- Moved frontend api logic to hook and backend api space
- Added swagger schema for the new api endpoint
- Moved backend logic to its own internal file
- Added user agent header to github api check
- Added cypress integration test for version check api
- Added a memory cache item from github check to avoid hitting it too
  much
2025-11-13 11:20:31 +10:00
Jamie Curnow
8aeb2fa661
Fix #4692, #4856 - stick with auto for scheme in db, change it to $scheme when rendering 2025-11-11 14:46:25 +10:00
Jamie Curnow
4cb85f6480
Fix #4833 supports the usual proxy env vars for outgoing admin related requests 2025-11-05 15:16:42 +10:00
Jamie Curnow
8c37348b65
Properly wrap debug calls 2025-11-04 13:43:52 +10:00
Jamie Curnow
89abb9d559
Fix bugs from feedback 2025-10-29 08:48:29 +10:00
Jamie Curnow
3b9beaeae5
Various tweaks and backend improvements 2025-10-28 11:38:26 +10:00
Jamie Curnow
ca3c9aa39a
Show cert expiry date in yellow when < 30 days 2025-10-27 19:34:25 +10:00
Jamie Curnow
7b5c70ed35
Fix cert renewal backend bug after refactor 2025-10-27 18:04:58 +10:00