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
135 changes: 135 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
name: ci

on:
push:
branches: [main, canary]
pull_request:
branches: [main, canary]

env:
CARGO_TERM_COLOR: always

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
- name: format_check
run: cargo fmt --check
- name: clippy
run: cargo clippy --all-targets -- -D warnings
- name: unit_tests
run: cargo test --all
- name: script_syntax
run: bash -n setup uninstall build update

api_e2e:
runs-on: ubuntu-latest
env:
ADMIN_TOKEN: admin_test_token
READONLY_TOKEN: readonly_test_token
DOCKER_SOCKET: /var/run/docker.sock
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: build_binary
run: cargo build --release --bin docker-proxy
- name: write_ci_config
run: |
cat > ci-config.yaml <<'YAML'
global:
port: 2376
bind: 127.0.0.1
metrics:
enabled: true
path: /metrics
auth:
type: bearer
tokens:
- token: "${ADMIN_TOKEN}"
role: admin
- token: "${READONLY_TOKEN}"
role: readonly
rules:
- name: block_secrets
conditions:
- field: path
operator: starts_with
value: /secrets
action: deny
status: 403
message: secrets blocked
YAML
- name: start_proxy
run: |
./target/release/docker-proxy --config ci-config.yaml &
echo "proxy_pid=$!" >> "$GITHUB_ENV"
for i in $(seq 1 40); do
c=$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:2376/version || true)
if [ -n "$c" ] && [ "$c" != "000" ]; then break; fi
sleep 0.5
done
- name: assert_api
run: |
fail() { echo "::error::$1"; kill "$proxy_pid" 2>/dev/null; exit 1; }
code() { curl -s -o /dev/null -w '%{http_code}' "$@"; }

c=$(code http://127.0.0.1:2376/version)
[ "$c" = "401" ] || fail "no_token expected 401 got $c"

c=$(code -H "Authorization: Bearer $ADMIN_TOKEN" http://127.0.0.1:2376/version)
[ "$c" = "200" ] || fail "admin /version expected 200 got $c"

c=$(code -H "Authorization: Bearer $ADMIN_TOKEN" http://127.0.0.1:2376/secrets)
[ "$c" = "403" ] || fail "deny rule expected 403 got $c"

c=$(code -H "Authorization: Bearer $ADMIN_TOKEN" http://127.0.0.1:2376/metrics)
[ "$c" = "200" ] || fail "metrics expected 200 got $c"
- name: stop_proxy
if: always()
run: kill "$proxy_pid" 2>/dev/null || true

build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-musl
zig: true
- os: ubuntu-latest
target: aarch64-unknown-linux-musl
zig: true
- os: macos-latest
target: aarch64-apple-darwin
zig: false
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: install_zigbuild
if: matrix.zig
run: |
curl -fsSL https://ziglang.org/download/0.13.0/zig-linux-x86_64-0.13.0.tar.xz | tar -xJ
echo "$PWD/zig-linux-x86_64-0.13.0" >> "$GITHUB_PATH"
cargo install cargo-zigbuild
- name: build_zig
if: matrix.zig
run: cargo zigbuild --release --target ${{ matrix.target }}
- name: build_native
if: ${{ !matrix.zig }}
run: cargo build --release --target ${{ matrix.target }}
- uses: actions/upload-artifact@v4
with:
name: docker-proxy-${{ matrix.target }}
path: target/${{ matrix.target }}/release/docker-proxy
126 changes: 126 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
name: release

on:
push:
tags:
- "v*.*.*"
workflow_dispatch:
inputs:
tag:
description: version tag to publish, e.g. v1.0.1
required: true

permissions:
contents: write

env:
bin_name: docker-proxy
zig_version: "0.13.0"

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: true
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-musl
asset: docker-proxy-linux-x86_64
zig: true
- os: ubuntu-latest
target: aarch64-unknown-linux-musl
asset: docker-proxy-linux-aarch64
zig: true
- os: macos-latest
target: x86_64-apple-darwin
asset: docker-proxy-macos-x86_64
zig: false
- os: macos-latest
target: aarch64-apple-darwin
asset: docker-proxy-macos-arm64
zig: false
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: install_zigbuild
if: matrix.zig
run: |
curl -fsSL "https://ziglang.org/download/${zig_version}/zig-linux-x86_64-${zig_version}.tar.xz" | tar -xJ
echo "$PWD/zig-linux-x86_64-${zig_version}" >> "$GITHUB_PATH"
cargo install cargo-zigbuild
- name: build_zig
if: matrix.zig
run: cargo zigbuild --release --target ${{ matrix.target }} --bin "$bin_name"
- name: build_native
if: ${{ !matrix.zig }}
run: cargo build --release --target ${{ matrix.target }} --bin "$bin_name"
- name: stage_asset
run: |
mkdir -p dist
cp "target/${{ matrix.target }}/release/${bin_name}" "dist/${{ matrix.asset }}"
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.asset }}
path: dist/${{ matrix.asset }}
if-no-files-found: error

publish:
needs: build
runs-on: ubuntu-latest
env:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
gpg_passphrase: ${{ secrets.GPG_PASSPHRASE }}
steps:
- name: resolve_tag
run: echo "release_tag=${{ github.event.inputs.tag || github.ref_name }}" >> "$GITHUB_ENV"
- uses: actions/download-artifact@v4
with:
path: dist
merge-multiple: true
- name: generate_checksums
working-directory: dist
run: sha256sum ${bin_name}-* > SHA256SUMS
- name: sign_checksums
working-directory: dist
run: |
if [ -z "$gpg_private_key" ]; then
echo "no signing key configured, publishing checksums without a signature"
exit 0
fi
echo "$gpg_private_key" | gpg --batch --import
key_id=$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/{print $5; exit}')
gpg --batch --pinentry-mode loopback --passphrase "$gpg_passphrase" \
--armor --detach-sign --local-user "$key_id" \
-o SHA256SUMS.asc SHA256SUMS
- name: publish_release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.release_tag }}
name: ${{ env.release_tag }}
fail_on_unmatched_files: false
files: |
dist/docker-proxy-linux-x86_64
dist/docker-proxy-linux-aarch64
dist/docker-proxy-macos-x86_64
dist/docker-proxy-macos-arm64
dist/SHA256SUMS
dist/SHA256SUMS.asc
body: |
## install

```bash
curl -fsSL https://raw.githubusercontent.com/Nemu-Bridge/docker-proxy/main/setup -o setup
sudo bash setup
```

The installer downloads the matching binary for your platform, verifies it against `SHA256SUMS`, generates admin and readonly tokens into `/etc/docker-proxy/config.yaml`, and installs and starts the systemd service.

Linux builds are statically linked (musl). macOS builds: `arm64` for Apple Silicon, `x86_64` for Intel.

If `SHA256SUMS.asc` is attached, verify it with the project release signing key before trusting the checksums.
26 changes: 26 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ serde_yaml = "0.9"
serde_json = "1"
regex = "1"
ipnet = "2"
secrecy = { version = "0.10", features = ["serde"] }
zeroize = { version = "1", features = ["derive"] }
dialoguer = { version = "0.11", features = ["fuzzy-select"] }
tokio-rustls = { version = "0.26", default-features = false, features = ["ring", "tls12", "logging"] }
rustls = { version = "0.23", default-features = false, features = ["std", "ring", "tls12", "logging"] }
Expand Down
Loading
Loading