diff --git a/CHANGELOG.md b/CHANGELOG.md index 01ee3bb..6494fb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,14 @@ Release history focused on **features, settings, default behavior, compatibility ## 0.34.5 — Administration UX improvements (source candidate) +- **Linux deployment/package filesystem access:** packaged and manually generated + systemd services now use `ProtectHome=read-only` rather than `true` so a + Web Server can read `/home` and other external document roots using Unix + groups/ACLs without per-host systemd overrides. `ProtectSystem=strict`, + the dedicated service account, private state/log paths and certificate + ownership/symlink validation remain in place. New DEB/RPM units require a + packaging rebuild; no installed service is changed by this source archive. + - **Web Server → Delivery:** separated static-file delivery, dynamic compression/codecs and precompressed `.br`/`.gz` sidecar controls into individually labelled settings groups. Existing options, defaults and configuration keys remain unchanged. - **Web Server → PHP-FPM:** grouped profile and endpoint selection, request behavior, timeouts/capacity, and FastCGI/php.ini overrides. Disabled inputs, selectors and textareas now share a clear inactive appearance when PHP is off or controlled by a shared profile. - **Streams → Backends:** split backend routing/capacity from health checks. Probe timing and UDP payload fields appear only when a health-check mode is selected; hidden controls retain their values and cannot block form validation. diff --git a/README.md b/README.md index e29623b..a57abc9 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,12 @@ For Debian 13+ source installation, manual compilation, managed updates or Docke Typical managed Linux defaults: HTTP on `:80`, HTTPS on `:443`, local administration at `http://127.0.0.1:9090`, private data in `/var/lib/rustproxy`. The initial public certificate is self-signed. **There is no default administrator password.** Initialize administration locally and assign trusted certificates before public use. +Updated Linux service templates allow **read-only** access to static website +roots under `/home`, `/var/www` and `/srv` using Unix groups or ACLs without +per-directory systemd overrides. The service still runs unprivileged with +`ProtectSystem=strict`; external certificate paths have stricter trust/owner +checks. See [Linux filesystem access](docs/INSTALL.md#linux-debrpm-read-only-access-to-external-paths). + ## First configuration 1. Install and start the service, then initialize the administrator using the local CLI. diff --git a/SHA256SUMS b/SHA256SUMS index a800e8a..6b162e2 100644 --- a/SHA256SUMS +++ b/SHA256SUMS @@ -2,16 +2,16 @@ 4140a2956264b44f259e6a37fc00ba02097bbe68b09296e04d3d243c1287129b .env.example 9e6356475bf587091bab72246ec9e325b498f7e48a6220e9a18baa50d0a385a6 .gitignore c85d98468358b1b6acfae1025db0de42858f4b80418a5e8d6072e9c059f684d2 AGENTS.md -0370b6470b855ad901c74a8afe1461987ba64fc020f5c71f441f41d5431b334c CHANGELOG.md +5f4a1d637a3450ccfb503dbe46d5a07bbfb752e882ec8c49849a5f9f8a5752c2 CHANGELOG.md 32a94804157a1bdf05335f2eb9fb1fa3c3507511997ca3aef51235884a1300ec Cargo.lock f716baecb16304e87bc0627a0d70c5a4a3d1a7e8847987f5a60f1ae1b77f4008 Cargo.toml 25c7f3c8162cbf5cc156439774118a81dae9fdc52b611ec7e40c230fc99a772c Dockerfile -b2435a90dd36e4a531b23711794bae7fee3c877edf84ee78064e199ac87fccbd README.md +82d522543c72fc26a15366e6d4ea708d3c8ca99ef47d5ed7019750c49b0add9f README.md ae6d14ada6fde7d0b8514840b821678418cf5b1816c18434e3b7fb2ae27a0b21 ROADMAP.md da8311e3db945290666324a2f24bf4521b365272d7ac3f862ded1be993eea646 UPDATE_CHECK.toml f645f218dd062bf6cb54a8ee634290562cad364a4cccf09f16e3c8303582af8c build.rs -99ac985e49fc0bf7ddfb0b157c241261ecb69f24f92e5dcc99e4f72d58ce6cea deploy/README.md -4fdba6349bbec3b8bc18411287b80b065aff59b52fe87ded1d9bdf7dcd79e593 deploy/rustproxy.service +2c6a0a5cb088399e2cc912073069eb334ec6615eee31734d2f0c161f1415fb6a deploy/README.md +13d514de5042a230cacf8c10abe1ef183c94ac799a89b8e2c111152ac7c69b48 deploy/rustproxy.service c111f5b20484707b80efb7dd9176acbaa27b63ac78db497261ac234821e1fade dev.sh 8a1ad36b0c7bda1fc6fe235c5a17becde8644600c1242b0d958d9eb57c2d6f62 docker-agent/README.md e9f18b358a740f1fe16e369ed16ee37581b8ce4c94ddeb34a1a37b89a49b5a06 docker-agent/certificate.go @@ -28,18 +28,17 @@ e52b31d0abf65ae3034f6cb367cca113633014ce8d1d799ad4dd5624d2c7b8bb docker-agent/n 634790f35ff4627df2a78cec2ed371f6e9ec9df00afb386075595fc7f3ed72eb docker-agent/rustproxy-docker-agent.service 5220d669171ec3ad65f50e0bc8de5178dadaa4904def8e1a4f61002aa9e9a55b docker-agent/server.go 30214fb5082c9de0ef90e1f4271825b5bf4c9898dd396ef797daf0a7abb37834 docs/ACCESS.md -64dacde6ce787302b6586f780eae7ef3e30bf81f8072c0b38020ec7a10dc3db0 docs/ACME_PROVIDERS.md +30542f4c60dc2738ea6b7f8214c7d3dc493c470d632e302681225f208b2fea79 docs/ACME_PROVIDERS.md 9268ab7fe86683dacd64bafbd9e0edc8956ce9b9ef6277cc6ada61c3fcb84746 docs/API.md 2362ab34020d4e0dcd70e280e9539ef7764b63212856ee08a3a55906c48f6421 docs/API_ACCESS.md 728b15b9825f547f34c4121219784798dd046fbbdd72ece8906d0cd77e8efc64 docs/BACKUP.md 0305f4e464cae51d50ed6a171571515505aab3bc3aacdcfaa632f252460cd4a8 docs/CACHE.md c81c6ee84e6af6507926144f8caf1e94daf497a8a0159449a3808088a11ea045 docs/CONFIGURATION.md 80bcc666736b10f6202386d0342e8d6feeba858d77aea310bf3ec6de01c2bfb3 docs/CONTAINER.md -ddaebc028e42f85652bf0c1fa0d88eb30346e543c66ebba64f22c0e54cd87678 docs/CSS_AUDIT.md dc670d912a6a946160c2f8528c9bb710ec38ebe406dcb7dcaf18fb2653f667b6 docs/CUSTOM_LOCATIONS.md 9fb2d0bcac70d1883dd16557622851a1f0527b3d3569a4b5177f5e6dedd3c74d docs/DASHBOARD.md 8a97377f04a12c28ca219accd921e439e67130fed0d87b51495c0e15a626cbc0 docs/DOCKER_DISCOVERY.md -dbae1a739874ac7b61e276c1ad6fd7c3465acc95afa4db3751224c8426ad6569 docs/INSTALL.md +f1baabe34e8a1b204d7c78e2f558c019c156b03adfa6ddecb931b4b8a5501f78 docs/INSTALL.md 37001cbf8ed248ca05ec40f12dd9876d33f6e0c97dcb21eb2e6f53c3d97a60bb docs/INTEGRATIONS.md 8c5007550ebae8408cbb72a75b2af9894578a1b9acda6bd34bc5f533916ddf72 docs/LOGS.md 888cdc8c56e10b8a7615012e192e085bf2899d0ec9b3ddfb5731e7de6ab5bcde docs/MIGRATION.md @@ -52,7 +51,7 @@ bbef60ff1771da9f48af812987766e1e479408873ae2f079b13f1d5c62ecc6ff docs/STREAMS.m 5bedc7d8b9fcaa80cacea225b1f6750101a7ac1b34eb9ce58310ec60329e380d docs/TRANSPORT.md 8542c4a5c9d5dfe474459099546ae590b4c4d3f363f0bba9721c6107643c2d3a docs/TROUBLESHOOTING.md 2fb3da550ff021456fdd5efb869869288cce1f027dafe72be07903fad6a6d1fe docs/VHOSTS.md -a47b394fbe87b312c89a59b17a58310595ebdaa1f55cfa603bd33e28653ed90f docs/WEB_SERVER.md +05efc113d33be361bac25c90064b1865cf2f574dabd0eaa73bdddda229b2946e docs/WEB_SERVER.md 5502e8ce44276213803b66c58e3a4d804a1354f5ed5d83f47ee805e8c44ab088 examples/acl-headers.json 2431dd88a2d9ad2cf3cd4b8fcdfa602563ab1013c612d8917fddbe7febfb2dc3 examples/cache-dashboard.json e31ac05a99615e4ea6c4c9a8b2e090968583fe3959f838a600b5740cb170f8c5 examples/config.json @@ -101,7 +100,7 @@ bd313cacfc1b450a90368b30ae39ab48b877c8bed3c2db8bbd4e4a1f40865c9e scripts/README f550ffab868c5241ff5d43d9ae569e19f6842b324b80ecefdc7034642125ed9b scripts/audit_css_usage.py 31953ddf3fda1c9b47fb5de7f85b91a23782b4ccc9555b8423a965659a0a8786 scripts/build/swagger_assets.py e4d15aa6aa864d04b9b30aca33826b833632af02ca643f8b23e219a5ea1298dd scripts/deploy/deploy.py -4853dbb3385ede933dcf66431eaca3bcfdd091c0f265dd8b34609505d29f0b58 scripts/deploy/deploy_core.py +618603239b000bbe4af36a6a6ee268758af632c761fc53fc6b7f44a4a818bdf1 scripts/deploy/deploy_core.py 8c7da13e95bcddd2bd1b4f1b22ade1c5ac1ecf54448601daa8416905d4239751 scripts/deploy/deploy_runtime.py a641bd35400c56f3b68b0a92e97b602d06090f03972ca8f01fa744e90dd97403 scripts/deploy/upgrade.py 2cc658faaa610b21b48942c59b955525539ad4503fd60f2a49c7e626a22faaff scripts/migration/migrate_npm.py @@ -208,7 +207,7 @@ e6c4d91d1542d0a5b47bb8736f9539d43a6713df5a473b635519d5b7eac2eb9c src/admin/web/ 0a5fff35555153f59d4346933030a67b6e1a8768cee7a47cfa2fcf1a2c564f63 src/admin/web/favicon.svg 7cbdef9192a9dee1f8eac42b85f52b3190f7f6efae50004aa7ad116a910e4036 src/admin/web/file-logs.js b14e7b3578322f309627f6fe965cc16abcf85da3437c9070be6caecae1908743 src/admin/web/host404.js -289ba997f960b4bb9321c32521c9064bf11f093b2f563b94112f86132cf9a225 src/admin/web/index.html +a57546ff4b1443e0dc66396edf22f94d851045f3794812aae6f8d01a09f18bba src/admin/web/index.html 7915a06cebb3dfa2c51833c326586920691ba4431b1f984429b039333f9c2a93 src/admin/web/integrations.js 7a12f020fc587205694978ab41b660e9a80487d413fbf6e34fc525eabc58308f src/admin/web/login-keys.json cbd41678eadd994dc5252628ee8ef9551fa9f7d8694ca5abd206240d9a96ad30 src/admin/web/login.html @@ -218,13 +217,12 @@ c2e5f554810b8e34fb47361fb90a01073a2e332ee26d82e030956fad3ec1f83e src/admin/web/ a8afc6e70950bc70b98725eb049d73cff35dc3a3ee659229a15a8e08d3eb4f12 src/admin/web/partials/overview-metrics.html 3928afce2ed6d5f2d3e29475dd29e4c3bd3c6df180ad5119beaff0c7a58e3b3b src/admin/web/prometheus-token.js 90d9a0836662135b79fb6f183c4f3eff60f8a64392d6c5795ccf1d8ef6862263 src/admin/web/redirects.js -b52db71e9efac0ea0a14fe3c332a6debf28cf762765327be007bf44849704db4 src/admin/web/settings.js +be9b78bee4ef0026608191d36a2aed831f93c1baaa5bc73da86bf09bc217ce76 src/admin/web/settings.js 8eadbada619b15087783dcfa0e889a81f88e78034d084c5ab616f7912b835940 src/admin/web/status_200.html -02dc0b1d86046c5f6515e8ca7f4891dd8373a436e479dc575cedaf2f8ef0c80b src/admin/web/streams.js -7776fa7c002a079f781748097538c6983031623fff714d0ad58c55a196e29c22 src/admin/web/style.css +6feb1996b1caa9d19e0dc56eae7ca5b48b7e7cdf0a93bb2e4b527fb8f13a2fe5 src/admin/web/streams.js +13013666b75a3d3d56d25d7f0536067f8b814583087324cfd2b2d62c0ccd7e98 src/admin/web/style.css d290c048450655b3eeae7c6ec54a82d645d1965513694ab29fdf7eef796a1abd src/admin/web/traffic-panel.js dfb4ded2fefb90fc1e2d33370cdef10b040a85cb43235ea9dbc1d73bef823a79 src/admin/web/transform-panel.js -2e323f3fbcd60d606bbeae88dfd024e243727b069c82d9017cfa47acd130bcb0 src/admin/web/unused.css ad2a127f83145792d5c658b9e9a3fae42e26bd5ec5339599feed34711133720e src/admin/web/vhosts/core.js 4f87802573f2e5abebcade4928ab460b0de78b991a96a391485cb36336d61812 src/admin/web/vhosts/editor.js 8338ce13b5e3e3f421437631124cb691aeb5b9e17409d256b4b9bcac457b3c59 src/admin/web/vhosts/health.js @@ -445,7 +443,7 @@ d9123c623e2a97d09e41edaa29993b4b2c8cba39a3abdf2b48a205aa9a9c2939 src/system_sta 1d7a6e0df1ca4d4acfbc1d059e60d80c9ccf31fa7d130091df44bff9f8ad4d31 src/tls/certificates.rs 436575144aa352498a4696f12c2258bef3a898f3f50e6fbc6d67c3b93afa099f src/tls/external_paths.rs 627c973870f6da0b18a90f84d3e92ed3f9fbdd5587490e4424dd77baaab3674c src/tls/server_config.rs -7de4781a04ba6ccfbdbd3b8a30939bf6cd6eda4e7d6a07f05302c61c79f5703c src/tls/tests.rs +5816e5e5b870a29d3f96d9e409fb2b667c1b2f4f599fd2b0ee25b522166df49e src/tls/tests.rs 2af2164ecdf2b7fd9eef7c6e358dec053dfac9aedaa501dbb75df742d18638b2 src/tls/tests/acme.rs 93b359e9defd62506729bc90e56c96783e2f14dd477dd67f337ca83149da7168 src/tls/tests/external_paths.rs 3292498e7122bb9fbee49d29e51e37cbb337c51af62ce367a06f6b01f6c0491b src/tls/types.rs diff --git a/deploy/README.md b/deploy/README.md index 9279bdb..d34984b 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -23,10 +23,13 @@ addresses, limits or a service-account convention. Never point it at a user-owne source directory containing writable executables or real public web content. After starting through your service manager, run account/certificate CLI operations -as the same service account with `--data-dir /var/lib/rustproxy`. The example -uses `ProtectHome=true`, so certificate files intended for runtime use must be in -the data directory, not in a home directory. Use an SSH tunnel to access the local -admin port remotely. This reference unit keeps administration on `127.0.0.1:9090`; public HTTP/HTTPS +as the same service account with `--data-dir /var/lib/rustproxy`. The reference +uses `ProtectHome=read-only`, so site roots in `/home` and trusted external +certificates can be read according to Unix permissions, groups and ACLs, +without overriding the systemd sandbox. The reference binds administration +to `0.0.0.0:9090`; restrict this to loopback before running on an untrusted +network, or use administration HTTPS and strict network controls. Use an SSH +tunnel to access a loopback-only admin port remotely. Public HTTP/HTTPS listeners remain explicit. For direct remote administration, enable Administration HTTPS and persist a non-loopback bind from the panel rather than exposing the plain-HTTP bootstrap listener. For a systemd drop-in, reset `ExecStart` before replacing it. Example preserving the loopback-safe admin: @@ -36,7 +39,6 @@ systemd drop-in, reset `ExecStart` before replacing it. Example preserving the l ExecStart= ExecStart=/opt/rustproxy/current/rust-proxy --data-dir /var/lib/rustproxy --admin-listen 127.0.0.1:9090 serve --proxy-listen 0.0.0.0:80 --tls-listen 0.0.0.0:443 ReadWritePaths=/var/log/rustproxy -ReadOnlyPaths=-/etc/letsencrypt -/etc/ssl ``` Saving HTTP/TLS or TCP/UDP stream listener changes in the UI does not restart this service. Restart explicitly @@ -73,7 +75,11 @@ sudo getfacl /etc/rustproxy /etc/rustproxy/config.json **Security:** the shown `0.0.0.0:9090` requires administration HTTPS and network access controls before remote exposure; use loopback administration otherwise. The complete export, privilege commands, validation and rollback guidance live in [Installation](../docs/INSTALL.md#optional-systemd-json-configuration). -External certificate files under `/etc/letsencrypt` or `/etc/ssl` remain read-only under the systemd sandbox. `ReadOnlyPaths=` does not grant Unix permissions; use narrow POSIX ACLs for the `rustproxy` user. For traversal of a protected root, for example: +External certificate files under `/etc/letsencrypt`, `/etc/ssl` or another +trusted root/service-owned directory remain read-only under the systemd +sandbox. No path-specific `ReadOnlyPaths=` allowlist is necessary; +`ReadOnlyPaths=` does not grant Unix permissions anyway. Use narrow POSIX ACLs +for the `rustproxy` user. For traversal of a protected root, for example: ```bash setfacl -m u:rustproxy:--x /etc/ssl/ @@ -81,3 +87,7 @@ setfacl -m u:rustproxy:--x /etc/ssl/ Grant `r--` only on the certificate/key files RustProxy actually needs; never grant write access to the service identity. If Certbot or another renewer recreates a key as `0600`, reapply the named file ACL to the newly resolved target in the renewal hook before calling the RustProxy reload API. +External certificate parent directories and PEM files must be owned by root +or the service account and meet the application's safe-file checks; arbitrary +user-owned `/home` trees work as Web Server roots, but not as PEM ancestry. +See [Installation: external paths](../docs/INSTALL.md#linux-debrpm-read-only-access-to-external-paths). diff --git a/deploy/rustproxy.service b/deploy/rustproxy.service index c371ccd..f39c9c1 100644 --- a/deploy/rustproxy.service +++ b/deploy/rustproxy.service @@ -30,8 +30,9 @@ ProtectSystem=strict LogsDirectory=rustproxy LogsDirectoryMode=0770 ReadWritePaths=/var/lib/rustproxy /var/log/rustproxy -/etc/rustproxy -ReadOnlyPaths=-/etc/letsencrypt -/etc/ssl -ProtectHome=true +# Read-only document roots/certificates may live in /home, /var/www or /srv; +# service-account Unix group/ACL permissions still apply. +ProtectHome=read-only ProtectKernelTunables=true ProtectKernelModules=true ProtectKernelLogs=true diff --git a/docs/ACME_PROVIDERS.md b/docs/ACME_PROVIDERS.md index ffc35c0..f49634d 100644 --- a/docs/ACME_PROVIDERS.md +++ b/docs/ACME_PROVIDERS.md @@ -2,6 +2,15 @@ Certificates are managed under **Certificates**. You can import a PEM pair, reference accessible external certificate files or request a managed ACME certificate. Issuing a certificate does **not** automatically assign it to a Vhost; choose the certificate in the intended frontend/Vhost afterwards. +On Linux, the updated DEB/RPM service allows **read-only** access to +external certificate paths according to the `rustproxy` user's Unix group/ +ACL permissions, including paths inside `/home`. A separate safety rule still +requires the actual PEM files and real parent directories to be owned by root +or `rustproxy`; user-owned `/home/alice` is therefore unsuitable as a PEM +ancestor even though it can host a Web Server document root. See +[Installation: external paths](INSTALL.md#linux-debrpm-read-only-access-to-external-paths) +for scoped ACLs and Certbot renewal handling. + ## Supported certificate methods | Mode | Requirements | diff --git a/docs/INSTALL.md b/docs/INSTALL.md index ac4a03a..1c52517 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -87,6 +87,78 @@ Then visit `http://127.0.0.1:9090` on your workstation. For a directly reachable - Listener bindings supplied explicitly via service arguments/systemd are locked against panel changes. Network bind, administration TLS and some monitoring changes take effect after a restart. - Ports below 1024 need the appropriate OS privileges/capability; use the installed service model rather than running the whole application as root. +## Linux DEB/RPM: read-only access to external paths + +New Linux packages (package-builder filesystem-access policy, revision 5) and +the maintained manual service template use `ProtectHome=read-only` rather than +`ProtectHome=true`. This makes document roots under `/home`, `/var/www` and +`/srv` readable if the service account has **ordinary Unix group or ACL +permissions**. `ProtectSystem=strict` remains enabled: the service cannot +modify these files merely because a group or ACL permits it. No systemd +drop-in or extra `ReadOnlyPaths=` entry is needed to **read** site content or +an external certificate. This also applies when paths are stored in the panel. + +The service runs as the unprivileged `rustproxy` user. To use a dedicated web +group, give that group directory traversal and file read permissions on the +site, then add RustProxy to it: + +```bash +sudo usermod -aG web-readers rustproxy # use an existing narrow site group +sudo systemctl restart rustproxy # renew the service process's group list +``` + +Alternatively, to expose only `/home/alice/public_html` (install `acl` to get +`setfacl`), grant traversal of the private home and read/traversal of the site: + +```bash +sudo setfacl -m u:rustproxy:--x /home/alice +sudo setfacl -R -m u:rustproxy:r-X /home/alice/public_html +sudo -u rustproxy test -r /home/alice/public_html/index.html && echo readable +sudo systemctl restart rustproxy +``` + +Use appropriate **default ACLs** or group ownership on directories where the +deployment process creates new files. Never expose the entire home directory +or use world-writable permissions to work around access errors. The +`sudo -u` check tests Unix permissions on the host, not the effective systemd +mount namespace. + +External PEM files have **additional application security checks**. The +certificate/key and every real ancestor directory must be owned by root or +the RustProxy service user, and ancestors cannot be group/world-writable; +private keys cannot be world-readable. For Certbot files at +`/etc/letsencrypt/live/example.com`, for example: + +```bash +sudo setfacl -m u:rustproxy:--x /etc/letsencrypt /etc/letsencrypt/live \ + /etc/letsencrypt/live/example.com /etc/letsencrypt/archive \ + /etc/letsencrypt/archive/example.com +sudo setfacl -m u:rustproxy:r-- "$(readlink -f /etc/letsencrypt/live/example.com/fullchain.pem)" +sudo setfacl -m u:rustproxy:r-- "$(readlink -f /etc/letsencrypt/live/example.com/privkey.pem)" +sudo systemctl reload rustproxy +``` + +Apply the file ACL again when a renewal replaces the symlink's target, then +reload. Arbitrary user-owned parent directories (for example `/home/alice`) +are suitable for static websites but **not** for external keys under the +current trusted-path validation. Use root-owned certificate storage instead. +Keep all key access narrow and read-only. + +To diagnose unresolved errors, run `systemctl cat rustproxy` and +`systemctl show rustproxy -p ProtectHome -p ProtectSystem -p User -p Group`, +check parent permissions with `namei -l /path/to/file`, and examine +`journalctl -u rustproxy`. A legacy whole-unit file in +`/etc/systemd/system/rustproxy.service` takes precedence over the packaged +unit and is **not** automatically removed by an upgrade. On SELinux/AppArmor +hosts, additional mandatory access-control policy may be required; POSIX ACLs +cannot bypass it. See [Web Server](WEB_SERVER.md) and +[Certificates](ACME_PROVIDERS.md). + +**Write access is intentionally different.** An app that needs to upload or +modify files under an arbitrary document root needs a separately planned +writable location/policy; group membership alone does not bypass the read-only +systemd mount. Keep mutable data isolated from served files. + ## Optional systemd JSON configuration This is **optional**. Without `--config`, RustProxy keeps its active configuration in `/var/lib/rustproxy/config.sqlite3` (SQLite). With `--config`, panel/API saves and history restores write `/etc/rustproxy/config.json` atomically; SQLite still contains history, administrator state and audit entries. In **Settings → Manual config** you can see which mode and path are active. diff --git a/docs/WEB_SERVER.md b/docs/WEB_SERVER.md index ad8de50..da8083a 100644 --- a/docs/WEB_SERVER.md +++ b/docs/WEB_SERVER.md @@ -13,6 +13,14 @@ The built-in Web Server serves local files and, optionally, passes PHP scripts t A Web Service can be shared across several Vhosts. A Vhost may also use ordinary Reverse Proxy as its default and a Web Service for `/assets` or another custom location. Web Server and HTTP reverse proxy use the normal frontend TLS, access, logging and eligible cache pipeline. +**Linux DEB/RPM paths:** With the updated package unit, `/home/user/public_html`, +`/var/www/site` and `/srv/site` are readable using an appropriately scoped +service-user group or POSIX ACL; no `systemctl edit` or +`ReadOnlyPaths=` exception is needed. The filesystem remains read-only to the +service outside its private state/log/config paths. Grant execute/traversal +on each parent directory and read permission on served files; see +[Installation: external paths](INSTALL.md#linux-debrpm-read-only-access-to-external-paths). + ## File serving options | Feature | Behavior / caution | @@ -58,7 +66,7 @@ Vhosts can intercept selected application error bodies in **Pages** and return a A Web Service's dashboard shows request rate, status/error counts, response-header timing, delivered bytes and PHP permit usage (when PHP is configured). These are application observations, not proof of external PHP worker count or final compressed network bytes. -- **403 / unexpected block:** inspect document-root permissions, symlink policy, hardening and inherited ACLs. +- **403 / unexpected block:** inspect document-root permissions (including parent traversal), symlink policy, hardening, inherited ACLs and any SELinux/AppArmor denial; verify the active systemd unit is the updated one. - **404 / unwanted SPA rewrite:** check actual files, index list, `try_files`, location matching and rewrite order. - **Wrong Content-Type/download:** check MIME override and attachment extensions. - **PHP script downloaded instead of executed:** check PHP enablement, script extension and FPM endpoint. diff --git a/scripts/deploy/deploy_core.py b/scripts/deploy/deploy_core.py index 14e89b8..ec96fb9 100755 --- a/scripts/deploy/deploy_core.py +++ b/scripts/deploy/deploy_core.py @@ -399,9 +399,8 @@ PrivateDevices=true ProtectSystem=strict LogsDirectory=rustproxy LogsDirectoryMode=0770 -ReadWritePaths={data} /var/log/rustproxy -ReadOnlyPaths=-/etc/letsencrypt -/etc/ssl -ProtectHome=true +ReadWritePaths={data} /var/log/rustproxy -/etc/rustproxy +ProtectHome=read-only ProtectKernelTunables=true ProtectKernelModules=true ProtectKernelLogs=true