Skip to content

Commit

Permalink
Merge pull request #66 from junkurihara/develop
Browse files Browse the repository at this point in the history
Closes #57
Release 0.5.0
  • Loading branch information
junkurihara authored Aug 2, 2023
2 parents e3397c3 + 738b400 commit 19b0294
Show file tree
Hide file tree
Showing 29 changed files with 703 additions and 310 deletions.
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

0 comments on commit 19b0294

Please sign in to comment.