Files
RustProxy/deploy/README.md
T
2026-10-19 14:05:13 +02:00

5.9 KiB

Example Linux service

rustproxy.service is an operator-reviewed deployment example, not an installed or tested service. With RustProxy 0.34.2, the example includes ExecReload so systemctl reload rustproxy uses the authenticated CLI soft reload. If using RUST_PROXY_CONFIG, configure it in the service EnvironmentFile so both ExecStart and ExecReload share the same file source. It runs the compiled executable as a dedicated rustproxy account, uses the public administration profile shown below and grants only the capability needed for low-port binding. It does not run the proxy as root or grant Docker socket access.

Before installation, run the real Rust acceptance suite, build a release executable, create the unprivileged account/group through your normal system administration process and install the executable at /opt/rustproxy/rust-proxy. The service manager creates /var/lib/rustproxy as private writable state; the actual private data directory is /var/lib/rustproxy. LogsDirectory=rustproxy provisions /var/log/rustproxy for the JSONL access-log sink while the rest of the filesystem remains protected by ProtectSystem=strict. The service enables 80/443 startup defaults, does not start a demo backend and uses a self-signed fallback certificate until trusted certificates are imported. Firewall, DNS and trust configuration are separate operator responsibilities.

Existing SQLite listener overrides take precedence over these startup defaults. Review Settings before moving an old database into this service. Public addresses are deliberately explicit in the example. Customize the unit for other paths, addresses, limits or a service-account convention. Never point it at a user-owned 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 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:

[Service]
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 only after checking permission, free ports and certificate readiness. A bad saved bind can prevent startup; preserve a pre-change database backup and consult docs/MIGRATION.md for recovery. Verify the unit on the target system with systemd-analyze verify and exercise actual non-root binding before accepting a production deployment. This packaging environment did not run systemd or bind privileged ports through this unit.

Optional JSON backing file (--config)

Use sudo systemctl edit rustproxy to override the startup command, not to edit the packaged unit directly. For the /usr/bin installation requested below (switch to /opt/rustproxy/current/rust-proxy on the managed deployment), configure:

[Service]
ExecStart=
ExecStart=/usr/bin/rust-proxy --data-dir /var/lib/rustproxy --admin-listen 0.0.0.0:9090 serve --proxy-listen 0.0.0.0:80 --tls-listen 0.0.0.0:443 --allow-remote-admin --config /etc/rustproxy/config.json
ReadWritePaths=/etc/rustproxy

Only activate after exporting a complete, valid JSON config. The directory and initial file may remain root:root, restricted to 0700 and 0600; use:

sudo chown root:root /etc/rustproxy /etc/rustproxy/config.json
sudo chmod 0700 /etc/rustproxy
sudo chmod 0600 /etc/rustproxy/config.json
sudo setfacl -m u:rustproxy:rwx /etc/rustproxy
sudo setfacl -m u:rustproxy:rw- /etc/rustproxy/config.json
sudo getfacl /etc/rustproxy /etc/rustproxy/config.json

Atomic panel saves replace the file: the service needs directory traversal/create/rename permission (rwx), not just file write. New config files are written 0600, normally owned by rustproxy; do not assume named file ACLs survive replacement. ProtectSystem=strict additionally requires ReadWritePaths=/etc/rustproxy in the unit; ACLs do not override the systemd sandbox. Keep the original private data directory and SQLite state. Check the active source in Settings → Manual config, inspect the unit with systemctl cat rustproxy, then systemctl restart rustproxy and verify a save. An external JSON edit needs systemctl reload rustproxy; there is no automatic file watching.

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.

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:

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.