# Rust

> A compiled Rust binary serving its own HTTP — Axum, Actix Web, Rocket or a server of your own

A compiled Rust binary serving its own HTTP — Axum, Actix Web, Rocket or a server of your own. Replaces PHP-FPM and nginx rather than joining them: it is the web server as well as the application. In front of it is the platform's proxy, which terminates TLS, routes the hostname and compresses responses.

Your build steps run in the official Rust image, slim, on Debian trixie, with pkg-config, cmake and the OpenSSL, PostgreSQL and MySQL client headers, so the crates that link against them build. The binary runs in a slim Debian image with no Rust in it, about a tenth of the size, carrying the libraries those crates link against: the container runs as `vallic` with the release at `/var/www/html/current` (`WEB_ROOT`), read-only, and the release's own `bin/` on `PATH`. Deploy steps, cron jobs, workers and `vallic ssh` have the binary and no `cargo`: run what you built — `bin/server migrate` — rather than `cargo run`. A crate that links any other system library needs it in the image: open a ticket naming the library, and we add it ([Support](support.md)).

## A Rust project

`vallic.yaml` at the root of the repository:

```yaml
version: 1
type: rust

runtime:
  rust: '1.99'

build:
  steps:
    - name: Build
      run: cargo install --locked --path . --root .

port: 8080

health:
  path: /healthz
  timeout: 10
```

`cargo install --root .` puts the binary in `bin/`, and the image starts `bin/server`, so a package named `server` needs no `start`; name it anything else and write `start: bin/<name>`. Listen on `0.0.0.0` and on the port in `PORT`, which is `8080` unless `port` says otherwise.

**Nothing under `cache`.** Cargo's registry and its build directory are kept between builds for you, outside the checkout, so a build whose dependencies did not change compiles your own crate and nothing else. `target` listed as a cache would be copied into every release. A build directory that has grown past 4 GB is emptied, and that one build compiles everything again; cargo runs one compile job for each gigabyte a build may use, so a small machine builds slowly rather than running out of memory half-way.

**The version is the one under `runtime`.** A `rust-toolchain.toml` is not obeyed — a build does not download another toolchain — and `--locked` builds what `Cargo.lock` says, so commit it.

Uploads and anything else written at runtime go under `/mnt/files` (`VALLIC_PUBLIC_DIR`, `VALLIC_PRIVATE_DIR`), which outlive the release; the release itself is read-only. Environment variables are set on the environment in the console, and `RUST_LOG` and `RUST_BACKTRACE` on the service as well (see [Service settings](service-settings.md)).

## Versions

| Version | Status |
| --- | --- |
| `1.99` | Supported, and the default |
| `1.98` | Supported |

Pin the version, not the build: name `1.99` and the platform matches it to the
current build, so a security rebuild reaches you without anybody editing a
repository.

## What you can change

In [`vallic.yaml`](configuration.md) — what each one does is on [Service settings](service-settings.md):

```yaml
services:
  - rust:
      version: '1.99'
      environment:
        RUST_LOG: …
        RUST_BACKTRACE: …
```

Anything not on this list refuses the deploy, naming the variable — rather
than being accepted and quietly ignored.
