Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 32 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
# Brachyura

A TLS terminating, load balancing reverse proxy, which I am using as a Rust learning project. **An experimental work in progress project.**
A TLS terminating, load balancing reverse proxy, built as a Rust learning project. Functional and well tested, but not intended for production use.

I utilize Nginx as part of my home lab providing reverse proxy functionality as well as TLS termination. The idea of this project is to replace Nginx with a light weight Rust based reverse proxy. Configurable via a yaml config file.
I use Nginx in my home lab for reverse proxying and TLS termination. The goal of this project is to replace it with a lightweight Rust based alternative, built on [axum](https://github.com/tokio-rs/axum), [hyper](https://github.com/hyperium/hyper) and [tokio](https://github.com/tokio-rs/tokio), and configured via a single YAML file.

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
![ci-status](https://github.com/wjhoward/brachyura/actions/workflows/main.yml/badge.svg)
[![dependency status](https://deps.rs/repo/github/wjhoward/brachyura/status.svg)](https://deps.rs/repo/github/wjhoward/brachyura)

## Features

* TLS termination (connection between client and proxy is encrypted)
* Host header based routing to backends
* Round robin load balancing across multiple backends
* Prometheus metrics endpoint
* Graceful shutdown with a configurable connection drain timeout
* Sets X-Forwarded-For on proxied requests
* HTTP/1.1 and HTTP/2 support from clients

## Quick Start
The repo contains a local [docker compose](https://github.com/docker/compose) based environment with example backend services, [Prometheus](https://github.com/prometheus/prometheus
Expand Down Expand Up @@ -35,14 +46,18 @@ Configured in `config.yaml`
The key and cert paths are also defined in the yaml file. Only the connection between the client and proxy is encrypted.

### Timeout config
There is an optional global timeout config value in milliseconds (see the example config file) which applies to all connections from the proxy to backends. Defaults to 60 seconds if not configured.
There is an optional global `timeout_ms` value in milliseconds (see the example config file) which applies to all connections from the proxy to backends. Defaults to 60 seconds if not configured.

### Drain timeout config
On shutdown (SIGINT or SIGTERM) the proxy stops accepting new connections and waits for in flight requests to complete before exiting. The optional `drain_timeout_secs` value sets how long to wait before forcibly closing remaining connections. Defaults to 10 seconds if not configured.

### Proxy backend config

The proxy uses the host header to decide where to send the request, and this is configured in the yaml config file under "backends". The host header needs to match the name value, then the request is proxied to the location. For example:

backends:
- name: "origin.home"
backend_type: "single"
location: "127.0.0.1:10000"

A request with the host header `origin.home` would be proxied to `127.0.0.1:10000`
Expand All @@ -61,11 +76,24 @@ Multiple backends can be defined for a given host header, where requests to thes

---

## Internal endpoints

The proxy exposes two internal endpoints which are served directly rather than proxied to a backend. They are gated behind the `x-no-proxy` header (the same header the proxy sets on forwarded requests to prevent loops):

* `GET /status` returns a plain text message confirming the proxy is running
* `GET /metrics` returns Prometheus formatted metrics

Example:

curl -H "x-no-proxy: true" https://127.0.0.1:4000/status --insecure

---

## Testing

### Tests

Unit and integration tests can be run via `cargo test -- --test-threads=1`, single thread mode is required for the integration tests.
Unit and integration tests can be run via `cargo test`.

## Running

Expand Down
5 changes: 4 additions & 1 deletion config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ tls:
key_path: "tests/self-signed-cert/test.key"
cert_path: "tests/self-signed-cert/test.crt"

timeout: 1000
timeout_ms: 1000

backends:
- name: "prometheus.home"
backend_type: "single"
location: "127.0.0.1:9090"
- name: "grafana.home"
backend_type: "single"
location: "127.0.0.1:3000"
- name: "backend.home"
backend_type: "single"
location: "127.0.0.1:10000"
- name: "test-lb.home"
backend_type: "loadbalanced"
Expand Down
Binary file modified local_run.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading