16 KiB
Installation, updates and first start
Use maintained packages whenever possible. For custom installations, use the scripts included with this source version; do not combine parts of different releases.
Supported entry points
| Installation | Recommended starting point |
|---|---|
| Linux DEB/RPM (RustProxy server) | https://rustproxy.linuxiarz.pl/ |
| Docker host discovery agent (independent DEB/RPM) | sudo apt install rustproxy-docker-agent or sudo dnf install rustproxy-docker-agent; see Docker discovery |
| OPNsense plugin | https://rustproxy-opn.linuxiarz.pl/ |
| Debian 13+ source bootstrap | install-debian13.sh from the project repository |
| Manual Linux/systemd install | Compile the application; use install.sh and update.sh |
| OCI container | Included Dockerfile; see Container |
Package/plugin instructions and maintenance policies are maintained separately from the source archive. The optional Docker agent is packaged independently of RustProxy's main service for Linux amd64/x86_64 only, not FreeBSD pkg. On a Docker host, the agent can also be installed manually from docker-agent/install.sh; the installer and packages preserve existing tokens and TLS keys. See Docker discovery and agent operations.
Debian 13+ source bootstrap
Review the remote script before execution. On a managed installation, auto selects install or update from /opt/rustproxy/install.json.
# Initial install or existing managed update
wget -qO- https://git.linuxiarz.pl/gru/RustProxy/raw/branch/master/install-debian13.sh | bash
# Explicit managed update
wget -qO- https://git.linuxiarz.pl/gru/RustProxy/raw/branch/master/install-debian13.sh | bash -s -- update
The script installs dependencies, builds with cargo build --release --locked as an unprivileged build user, then uses the local deployment scripts. Run it only on Debian 13+ and with access to its required repositories. Installing from a moving master branch does not pin a specific audited release; use a reviewed commit when reproducibility matters.
Build from the source
The current Cargo.toml declares Rust 1.99 minimum, with a stable toolchain in rust-toolchain.toml. Use Cargo, a C compiler/linker, Bash and Python 3 (Python 3.11+ is advisable for project checks). Run as a normal build user:
bash dev.sh doctor
bash dev.sh check
bash dev.sh test
bash dev.sh release
dev.sh release builds the application; it is not equivalent to a successful production rollout. Cargo dependencies and Swagger assets must be available to the build environment. An example systemd unit is in deploy/.
For a first Linux/systemd installation:
bash install.sh --plan --binary target/release/rust-proxy
sudo bash install.sh --binary target/release/rust-proxy
Use --plan to inspect changes first. The installer refuses existing unmanaged/nonempty state rather than overwriting it. Common options include --prefix, --data-dir, --http, --https, --no-https, --admin, --allow-remote-admin and --no-start (see install.sh --help).
Defaults and administrator setup
For the standard managed Linux installation:
| Item | Default |
|---|---|
| HTTP frontend | 0.0.0.0:80 |
| HTTPS frontend | 0.0.0.0:443 with an initially self-signed certificate |
| Administration | 127.0.0.1:9090, HTTP on loopback |
| Installation | /opt/rustproxy/current/ |
| Private data | /var/lib/rustproxy |
| Service account | rustproxy |
The first installation has no predefined administrator and no application Vhosts. Obtain the one-time setup token locally:
sudo -u rustproxy /opt/rustproxy/current/rust-proxy \
--data-dir /var/lib/rustproxy admin setup-token
Use the setup page, or initialize the account interactively using admin init. To access loopback administration from another machine, tunnel over SSH:
ssh -L 9090:127.0.0.1:9090 operator@server
Then visit http://127.0.0.1:9090 on your workstation. For a directly reachable administration listener, configure Settings → Administration → HTTPS and a suitable certificate, restrict the network, save and restart. Do not publish unauthenticated or plain-HTTP administration over the Internet. Public frontend HTTPS and administration HTTPS are separate.
Listeners and networking
- Assign a trusted public certificate to the relevant hosts before exposing them.
- Configure DNS to reach the intended public listener; check IPv4/IPv6 and firewall rules.
- HTTP/3 needs UDP on the HTTPS port as well as TCP for normal HTTPS.
- 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.
In 0.34.10, the panel generates Linux permission commands from the actual
paths you enter: below the two external certificate/key fields, and directly
below a Web Server's document root. The commands target the standard
rustproxy account and resolve symlink targets when run. Review them and run
them as an administrator on the server; the panel never executes them.
Install your distribution's acl package for setfacl. If you use a different
service identity, set Service user under Options and help to that account before
copying. This field changes only the commands, not the process identity.
No command can replace
the certificate trusted-owner checks or bypass systemd/SELinux/AppArmor
restrictions.
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:
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:
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:
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.
After granting certificate read access, return to the form and use Read names from certificate. The editor reads the public certificate's DNS SAN entries into the legacy SNI field; this does not read the private key or save the certificate. Manual name edits are preserved by background reads. See Certificates.
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 and
Certificates.
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.
-
First export your existing, validated full configuration (do not start with
{}on an established host). On the running instance with administration reachable at127.0.0.1:9090, use a privileged shell withset -o pipefail:sudo install -d -o root -g root -m 0700 /etc/rustproxy sudo install -o root -g root -m 0600 /dev/null /etc/rustproxy/config.json sudo -u rustproxy /usr/bin/rust-proxy --data-dir /var/lib/rustproxy \ --admin-listen 127.0.0.1:9090 config get | sudo tee /etc/rustproxy/config.json >/dev/nullIf the installed binary is at
/opt/rustproxy/current/rust-proxy, use that path in both commands and the override. The export requires an existing initialized administrator. You may instead use Settings → Manual config → Export JSON, then install that file securely withsudo install -o root -g root -m 0600 exported.json /etc/rustproxy/config.json. -
Keep the directory and initial file owned by
root, allow only the RustProxy service identity through named POSIX ACLs (install theaclpackage first, e.g.sudo apt-get install aclon Debian, to obtainsetfacl/getfacl). The directory needsrwxfor atomic create/rename; the original JSON needsrwfor startup and backup tools.rootretains ownership until the first atomic panel save, after which the new0600file is normally owned byrustproxy: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 sudo -u rustproxy test -r /etc/rustproxy/config.json sudo -u rustproxy test -w /etc/rustproxyNever make
/etc/rustproxyworld-writable. RustProxy checks that--configis an existing absolute regular non-symlink file. The parent directory must be on a filesystem that supports atomic rename. Restoring a file as root may require reapplying its named ACL; atomic saves generate a new owner-only0600file. -
Edit the systemd drop-in with
sudo systemctl edit rustproxyand add the following example (the binary path must match your installation):[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/rustproxyReadWritePaths=is needed when the unit hasProtectSystem=strict; it does not grant Unix file permissions, hence the ACLs above. An existingExecReloadcan remain; it reloads through the local control API. Keep the existing unit's sandboxing, state/log writable paths, network capabilities and runtime user. Do not expose the example's0.0.0.0:9090admin listener over plaintext on an untrusted network: enable administration HTTPS and strict network controls first, or use the safer127.0.0.1:9090binding without--allow-remote-admin. -
Verify and restart during a maintenance window:
sudo systemctl daemon-reload sudo systemctl cat rustproxy sudo systemd-analyze verify rustproxy.service sudo systemctl restart rustproxy sudo systemctl status rustproxy sudo journalctl -u rustproxy -n 60 --no-pagerConfirm in Settings → Manual config that the source is JSON file and the path is
/etc/rustproxy/config.json. Save a harmless edit and confirm that the file is rewritten and readable byrustproxy; check that a revision appears in SQLite. To import a deliberate external file edit without restarting, runsudo systemctl reload rustproxy(if the unit hasExecReload) orrust-proxy --data-dir /var/lib/rustproxy --admin-listen 127.0.0.1:9090 config reload. The file is not watched automatically. An incompatible external edit must fail validation rather than silently overwrite the live configuration.
For the alternate environment-variable method, set RUST_PROXY_CONFIG=/etc/rustproxy/config.json in the service's protected EnvironmentFile. Do not set both unrelated config paths. See Configuration and the deployment example.
Managed update
Test the new build first. Then execute:
bash update.sh --plan --binary target/release/rust-proxy
sudo bash update.sh --binary target/release/rust-proxy
Managed updates preserve the saved configuration, create a private backup, switch releases and attempt rollback on failed startup/health checks. They interrupt traffic and are not a substitute for a separate off-host backup. Keep your backup password and test a restore on a separate installation. Source-tree/unmanaged migrations require the dedicated stopped upgrade path: see Migration.
ACME prerequisites
The managed certificate service can create a private Python/Certbot environment in the data directory; a usable system Certbot may be used as fallback. DNS-01 providers need credentials and appropriate permissions. HTTP-01 needs incoming public TCP 80. On systems without an available Python/Certbot runtime, PEM import and external certificate references can still be used. See Certificates.
After installation
Verify systemctl status rustproxy and journalctl -u rustproxy (managed systemd), the panel login, frontend certificates, first Vhost, real backend response, access policies, optional QUIC, current logs and a full backup/restore test. For error diagnosis, consult Troubleshooting.
Release verification: RustProxy 0.34.2 is a source package; complete a Rust 1.99+ build and target-platform HTTP/systemd/security acceptance tests before Internet-facing production use.