Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0.5.0 #66

Merged
merged 15 commits into from
Aug 2, 2023
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
126 changes: 75 additions & 51 deletions .github/workflows/docker_build_push.yml
Original file line number Diff line number Diff line change
@@ -1,103 +1,127 @@
name: Build and Publish Docker

on:
push:
branches:
- main
- develop
- "develop"
- "main"
pull_request:
types: [synchronize, opened]

env:
REGISTRY_IMAGE: jqtype/rpxy
GHCR: ghcr.io
GHCR_IMAGE_NAME: ${{ github.repository }}
DH_REGISTRY_NAME: jqtype/rpxy

jobs:
build_and_push:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- target: "default"
dockerfile: ./docker/Dockerfile
platforms: linux/amd64,linux/arm64

- target: "default-slim"
dockerfile: ./docker/Dockerfile-slim
build-contexts: |
messense/rust-musl-cross:amd64-musl=docker-image://messense/rust-musl-cross:x86_64-musl
messense/rust-musl-cross:arm64-musl=docker-image://messense/rust-musl-cross:aarch64-musl
platforms: linux/amd64,linux/arm64
tags-suffix: "-slim"
# Aliases must be used only for release builds
aliases: |
"slim"

- target: "s2n"
dockerfile: ./docker/Dockerfile
build-args: |
"CARGO_FEATURES=--no-default-features --features http3-s2n"
"ADDITIONAL_DEPS=pkg-config libssl-dev cmake libclang1 gcc g++"
platforms: linux/amd64,linux/arm64
tags-suffix: "-s2n"
# Aliases must be used only for release builds
aliases: |
"s2n"

steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: recursive

- name: GitHub Environment
run: echo "BRANCH=${GITHUB_REF##*/}" >> $GITHUB_ENV

- name: Docker meta
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY_IMAGE }}
images: ${{ env.GHCR }}/${{ env.GHCR_IMAGE_NAME }}

- name: Set up QEMU
uses: docker/setup-qemu-action@v2

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ${{ env.GHCR }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Release build and push
if: ${{ env.BRANCH == 'main' }}
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
${{ env.REGISTRY_IMAGE }}:latest
file: ./docker/Dockerfile
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
labels: ${{ steps.meta.outputs.labels }}

- name: Release build and push slim
if: ${{ env.BRANCH == 'main' }}
- name: Nightly build test on amd64 for pull requests
if: ${{ github.event_name == 'pull_request' }}
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: |
${{ env.REGISTRY_IMAGE }}:slim, ${{ env.REGISTRY_IMAGE }}:latest-slim
build-contexts: |
messense/rust-musl-cross:amd64-musl=docker-image://messense/rust-musl-cross:x86_64-musl
messense/rust-musl-cross:arm64-musl=docker-image://messense/rust-musl-cross:aarch64-musl
file: ./docker/Dockerfile.slim
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
build-args: ${{ matrix.build-args }}
push: false
build-contexts: ${{ matrix.build-contexts }}
file: ${{ matrix.dockerfile }}
cache-from: type=gha,scope=rpxy-nightly-${{ matrix.target }}
cache-to: type=gha,mode=max,scope=rpxy-nightly-${{ matrix.target }}
platforms: linux/amd64
labels: ${{ steps.meta.outputs.labels }}

- name: Nightly build and push
if: ${{ env.BRANCH == 'develop' }}
- name: Nightly build and push from develop branch
if: ${{ (github.ref_name == 'develop') && (github.event_name == 'push') }}
uses: docker/build-push-action@v4
with:
context: .
build-args: ${{ matrix.build-args }}
push: true
tags: |
${{ env.REGISTRY_IMAGE }}:nightly
file: ./docker/Dockerfile
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
${{ env.GHCR }}/${{ env.GHCR_IMAGE_NAME }}:nightly${{ matrix.tags-suffix }}
${{ env.DH_REGISTRY_NAME }}:nightly${{ matrix.tags-suffix }}
build-contexts: ${{ matrix.build-contexts }}
file: ${{ matrix.dockerfile }}
cache-from: type=gha,scope=rpxy-nightly-${{ matrix.target }}
cache-to: type=gha,mode=max,scope=rpxy-nightly-${{ matrix.target }}
platforms: ${{ matrix.platforms }}
labels: ${{ steps.meta.outputs.labels }}

- name: Nightly build and push slim
if: ${{ env.BRANCH == 'develop' }}
- name: Release build and push from main branch
if: ${{ (github.ref_name == 'main') && (github.event_name == 'push') }}
uses: docker/build-push-action@v4
with:
context: .
build-args: ${{ matrix.build-args }}
push: true
tags: |
${{ env.REGISTRY_IMAGE }}:nightly-slim
build-contexts: |
messense/rust-musl-cross:amd64-musl=docker-image://messense/rust-musl-cross:x86_64-musl
messense/rust-musl-cross:arm64-musl=docker-image://messense/rust-musl-cross:aarch64-musl
file: ./docker/Dockerfile.slim
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64
${{ env.GHCR }}/${{ env.GHCR_IMAGE_NAME }}:latest${{ matrix.tags-suffix }}
${{ env.DH_REGISTRY_NAME }}:latest${{ matrix.tags-suffix }}
${{ env.GHCR }}/${{ env.GHCR_IMAGE_NAME }}:${{ matrix.aliases }}
${{ env.DH_REGISTRY_NAME }}:${{ matrix.aliases }}
build-contexts: ${{ matrix.build-contexts }}
file: ${{ matrix.dockerfile }}
cache-from: type=gha,scope=rpxy-latest-${{ matrix.target }}
cache-to: type=gha,mode=max,scope=rpxy-latest-${{ matrix.target }}
platforms: ${{ matrix.platforms }}
labels: ${{ steps.meta.outputs.labels }}
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
[submodule "quinn"]
path = quinn
url = [email protected]:junkurihara/quinn.git
[submodule "s2n-quic"]
path = s2n-quic
url = [email protected]:junkurihara/s2n-quic.git
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
# CHANGELOG

## 0.4.0 (unreleased)
## 0.6.0 (unreleased)

## 0.5.0

### Improvement

- Feat: `s2n-quic` with `s2n-quic-h3` is supported as QUIC and HTTP/3 library in addition to `quinn` with `h3-quinn`, related to #57.
- Feat: Publish dockerfile for `rpxy` with `s2n-quic` on both `amd64` and `arm64`.
- Feat: Start to publish docker images on `ghcr.io`
- Refactor: logs of minor improvements

## 0.4.0

### Improvement

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[workspace]

members = ["rpxy-bin", "rpxy-lib"]
exclude = ["quinn", "h3-quinn", "h3"]
exclude = ["quinn", "h3-quinn", "h3", "s2n-quic"]

[profile.release]
codegen-units = 1
Expand Down
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

`rpxy` [ahr-pik-see] is an implementation of simple and lightweight reverse-proxy with some additional features. The implementation is based on [`hyper`](https://github.com/hyperium/hyper), [`rustls`](https://github.com/rustls/rustls) and [`tokio`](https://github.com/tokio-rs/tokio), i.e., written in pure Rust. Our `rpxy` routes multiple host names to appropriate backend application servers while serving TLS connections.

As default, `rpxy` provides the *TLS connection sanitization* by correctly binding a certificate used to establish a secure channel with the backend application. Specifically, it always keeps the consistency between the given SNI (server name indication) in `ClientHello` of the underlying TLS and the domain name given by the overlaid HTTP HOST header (or URL in Request line) [^1]. Additionally, as a somewhat unstable feature, our `rpxy` can handle the brand-new HTTP/3 connection thanks to [`quinn`](https://github.com/quinn-rs/quinn) and [`hyperium/h3`](https://github.com/hyperium/h3).
As default, `rpxy` provides the *TLS connection sanitization* by correctly binding a certificate used to establish a secure channel with the backend application. Specifically, it always keeps the consistency between the given SNI (server name indication) in `ClientHello` of the underlying TLS and the domain name given by the overlaid HTTP HOST header (or URL in Request line) [^1]. Additionally, as a somewhat unstable feature, our `rpxy` can handle the brand-new HTTP/3 connection thanks to [`quinn`](https://github.com/quinn-rs/quinn), [`s2n-quic`](https://github.com/aws/s2n-quic) and [`hyperium/h3`](https://github.com/hyperium/h3).[^h3lib]

[^h3lib]: HTTP/3 libraries are mutually exclusive. You need to explicitly specify `s2n-quic` with `--no-default-features` flag. Also note that if you build `rpxy` with `s2n-quic`, then it requires `openssl` just for building the package.

This project is still *work-in-progress*. But it is already working in some production environments and serves a number of domain names. Furthermore it *significantly outperforms* NGINX and Caddy, e.g., *1.5x faster than NGINX*, in the setting of a very simple HTTP reverse-proxy scenario (See [`bench`](./bench/) directory).

Expand All @@ -27,11 +29,14 @@ You can build an executable binary yourself by checking out this Git repository.
% git clone https://github.com/junkurihara/rust-rpxy
% cd rust-rpxy

# Update submodule hyperium/h3
# Update submodules
% git submodule update --init

# Build
# Build (default: QUIC and HTTP/3 is enabled using `quinn`)
% cargo build --release

# If you want to use `s2n-quic`, build as follows. You may need several additional dependencies.
% cargo build --no-default-features --features http3-s2n --release
```

Then you have an executive binary `rust-rpxy/target/release/rpxy`.
Expand Down Expand Up @@ -231,7 +236,9 @@ Since it is currently a work-in-progress project, we are frequently adding new o

## Using Docker Image

You can also use [docker image](https://hub.docker.com/r/jqtype/rpxy) instead of directly executing the binary. There are only several docker-specific environment variables.
You can also use `docker` image hosted on [Docker Hub](https://hub.docker.com/r/jqtype/rpxy) and [GitHub Container Registry](https://github.com/junkurihara/rust-rpxy/pkgs/container/rust-rpxy) instead of directly executing the binary. See [`./docker/README.md`](./docker/README.md) for the differences on image tags.

There are only several docker-specific environment variables.

- `HOST_USER` (default: `user`): User name executing `rpxy` inside the container.
- `HOST_UID` (default: `900`): `UID` of `HOST_USER`.
Expand Down
18 changes: 10 additions & 8 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# TODO List

- [Try in v0.6.0] **Cache option for the response with `Cache-Control: public` header directive ([#55](https://github.com/junkurihara/rust-rpxy/issues/55))**
- Improvement of path matcher
- More flexible option for rewriting path
- Refactoring
Expand All @@ -10,14 +11,6 @@
- upstream/upstream group: information on targeted destinations for each set of (a domain + a path)
- load-balance: load balancing mod for a domain + path

- Done in v0.4.0:
~~Split `rpxy` source codes into `rpxy-lib` and `rpxy-bin` to make the core part (reverse proxy) isolated from the misc part like toml file loader. This is in order to make the configuration-related part more flexible (related to [#33](https://github.com/junkurihara/rust-rpxy/issues/33))~~

- Cache option for the response with `Cache-Control: public` header directive ([#55](https://github.com/junkurihara/rust-rpxy/issues/55))
- Consideration on migrating from `quinn` and `h3-quinn` to other QUIC implementations ([#57](https://github.com/junkurihara/rust-rpxy/issues/57))
- Done in v0.4.0:
~~Benchmark with other reverse proxy implementations like Sozu ([#58](https://github.com/junkurihara/rust-rpxy/issues/58)) Currently, Sozu can work only on `amd64` format due to its HTTP message parser limitation... Since the main developer have only `arm64` (Apple M1) laptops, so we should do that on VPS?~~

- Unit tests
- Options to serve custom http_error page.
- Prometheus metrics
Expand All @@ -30,4 +23,13 @@
- Make the session-persistance option for load-balancing sophisticated. (mostly done in v0.3.0)
- add option for sticky cookie name
- add option for sticky cookie duration

- Done in v0.5.0 ~~**Use `gchr.io`**~~
- Done in v0.5.0:
~~Consideration on migrating from `quinn` and `h3-quinn` to other QUIC implementations ([#57](https://github.com/junkurihara/rust-rpxy/issues/57))~~
- Done in v0.4.0:
~~Benchmark with other reverse proxy implementations like Sozu ([#58](https://github.com/junkurihara/rust-rpxy/issues/58)) Currently, Sozu can work only on `amd64` format due to its HTTP message parser limitation... Since the main developer have only `arm64` (Apple M1) laptops, so we should do that on VPS?~~
- Done in v0.4.0:
~~Split `rpxy` source codes into `rpxy-lib` and `rpxy-bin` to make the core part (reverse proxy) isolated from the misc part like toml file loader. This is in order to make the configuration-related part more flexible (related to [#33](https://github.com/junkurihara/rust-rpxy/issues/33))~~

- etc.
15 changes: 10 additions & 5 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,17 @@ FROM --platform=$BUILDPLATFORM base AS builder

ENV CFLAGS=-Ofast
ENV BUILD_DEPS curl make ca-certificates build-essential
ENV TARGET_SUFFIX=unknown-linux-gnu

WORKDIR /tmp

COPY . /tmp/

ARG TARGETARCH
ARG CARGO_FEATURES
ENV CARGO_FEATURES ${CARGO_FEATURES}
ARG ADDITIONAL_DEPS
ENV ADDITIONAL_DEPS ${ADDITIONAL_DEPS}

RUN if [ $TARGETARCH = "amd64" ]; then \
echo "x86_64" > /arch; \
Expand All @@ -29,15 +34,15 @@ ENV RUSTFLAGS "-C link-arg=-s"

RUN update-ca-certificates 2> /dev/null || true

RUN apt-get update && apt-get install -qy --no-install-recommends $BUILD_DEPS && \
RUN apt-get update && apt-get install -qy --no-install-recommends $BUILD_DEPS ${ADDITIONAL_DEPS} && \
curl -sSf https://sh.rustup.rs | bash -s -- -y --default-toolchain stable && \
export PATH="$HOME/.cargo/bin:$PATH" && \
echo "Install toolchain" && \
rustup target add $(cat /arch)-unknown-linux-gnu &&\
rustup target add $(cat /arch)-${TARGET_SUFFIX} && \
echo "Building rpxy from source" && \
cargo build --release --target=$(cat /arch)-unknown-linux-gnu && \
strip --strip-all /tmp/target/$(cat /arch)-unknown-linux-gnu/release/rpxy &&\
cp /tmp/target/$(cat /arch)-unknown-linux-gnu/release/rpxy /tmp/target/release/rpxy
cargo build --release --target=$(cat /arch)-${TARGET_SUFFIX} ${CARGO_FEATURES} && \
strip --strip-all /tmp/target/$(cat /arch)-${TARGET_SUFFIX}/release/rpxy &&\
cp /tmp/target/$(cat /arch)-${TARGET_SUFFIX}/release/rpxy /tmp/target/release/rpxy

########################################
FROM --platform=$TARGETPLATFORM base AS runner
Expand Down
File renamed without changes.
19 changes: 19 additions & 0 deletions docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Docker Images of `rpxy`

The `rpxy` docker images are hosted both on [Docker Hub](https://hub.docker.com/r/jqtype/rpxy) and [GitHub Container Registry](https://github.com/junkurihara/rust-rpxy/pkgs/container/rust-rpxy). Differences among tags are summarized as follows.

## Latest Builds

- `latest`: Built from the `main` branch with default features, running on Ubuntu.
- `latest-slim`, `slim`: Built by `musl` from the `main` branch with default features, running on Alpine.
- `latest-s2n`, `s2n`: Built from the `main` branch with the `http3-s2n` feature, running on Ubuntu.

## Nightly Builds

- `nightly`: Built from the `develop` branch with default features, running on Ubuntu.
- `nightly-slim`: Built by `musl` from the `develop` branch with default features, running on Alpine.
- `nightly-s2n`: Built from the `develop` branch with the `http3-s2n` feature, running on Ubuntu.

## Caveats

Due to some compile errors of `s2n-quic` subpackages with `musl`, `nightly-s2n-slim` or `latest-s2n-slim` are not yet provided.
34 changes: 34 additions & 0 deletions docker/docker-compose-slim.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
version: "3"
services:
rpxy-rp:
image: jqtype/rpxy:slim # ghcr.io/junkurihara/rust-rpxy:slim also works
container_name: rpxy
init: true
restart: unless-stopped
ports:
- 127.0.0.1:8080:8080/tcp
- 127.0.0.1:8443:8443/udp
- 127.0.0.1:8443:8443/tcp
# build: # Uncomment if you build yourself
# context: ../
# additional_contexts:
# - messense/rust-musl-cross:amd64-musl=docker-image://messense/rust-musl-cross:x86_64-musl
# - messense/rust-musl-cross:arm64-musl=docker-image://messense/rust-musl-cross:aarch64-musl
# dockerfile: ./docker/Dockerfile-slim # based on alpine and build x86_64-unknown-linux-musl
# platforms: # Choose your platforms
# - "linux/amd64"
# # - "linux/arm64"
environment:
- LOG_LEVEL=debug
- LOG_TO_FILE=true
- HOST_USER=jun
- HOST_UID=501
- HOST_GID=501
# - WATCH=true
tty: false
privileged: true
volumes:
- ./log:/rpxy/log
- ../example-certs/server.crt:/certs/server.crt:ro
- ../example-certs/server.key:/certs/server.key:ro
- ../config-example.toml:/etc/rpxy.toml:ro
Loading