perf/deploy: optimize hot-path allocs (cut per-session ad_tag allocations), split metrics module, and add ENV config support

Three independent changes bundled here — performance, maintainability, and
deployment DX.

1. Hot-path Allocations (ad_tag caching):
Every middle-relay session was doing a hex::decode of the user's ad_tag (plus a fallback to the global one) on every single connection. That's two string allocations and two hex decodes per session for data that only changes on config reload. Moved the decoding into ProxyConfig load/hot-reload into a precomputed runtime_ad_tags cache (same #[serde(skip)] pattern as runtime_user_auth). The session path now does a single O(1) lookup via config.effective_ad_tag(&user). Falls back to on-demand decode if the cache isn't built (e.g. in tests), so existing behavior is preserved. This eliminates two useless allocations and hex decodes per connection.

2. Metrics Monolith Split(structural refactor):
Broke up the massive 4,200-line `metrics.rs` into a proper `metrics/` directory module (`mod.rs`, `tls_front.rs`, `tests.rs`). I isolated the giant `render_metrics` function into its own `render.rs` file. This was a purely structural move—no locks or function bodies were changed, keeping things build-safe while making the crate significantly easier to navigate. The /metrics endpoint output is byte-identical.

3. GitOps / Dokploy Auto-Deployment Support (deployment DX):
Added `figment` to `Cargo.toml` to seamlessly merge TOML config files with Environment Variables. You can now configure the proxy entirely using `TELEMT_` prefixed ENV variables (e.g., `TELEMT_GENERAL__PORT=443`) without needing to manually mount a physical `config.toml` via Docker volumes. The Dockerfile and compose setups now gracefully handle missing config files by generating an empty placeholder, making stateless auto-deployments on platforms like Dokploy frictionless.
This commit is contained in:
ali_rajabpour
2026-06-26 16:09:51 +04:00
parent d851200e47
commit 721b75c687
13 changed files with 1218 additions and 912 deletions
+48 -37
View File
@@ -3,6 +3,50 @@
ARG TELEMT_REPOSITORY=telemt/telemt
ARG TELEMT_VERSION=latest
# ==========================
# Rust Builder (compiles from source, static musl binary)
# ==========================
FROM rust:1.88-bookworm AS builder
ARG TARGETARCH
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends musl-tools; \
rm -rf /var/lib/apt/lists/*
# Determine the musl target triple based on the build architecture.
RUN set -eux; \
case "${TARGETARCH:-amd64}" in \
amd64) echo "x86_64-unknown-linux-musl" > /tmp/target.txt ;; \
arm64) echo "aarch64-unknown-linux-musl" > /tmp/target.txt ;; \
*) echo "Unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \
esac
RUN rustup target add "$(cat /tmp/target.txt)"
WORKDIR /build
# Copy dependency manifests first for layer caching.
COPY Cargo.toml Cargo.lock ./
COPY .cargo .cargo/
# Create a dummy src/main.rs so cargo can fetch and compile dependencies
# without the full source tree. This layer is cached as long as
# Cargo.toml/Cargo.lock don't change.
RUN mkdir -p src && echo "fn main() {}" > src/main.rs && \
cargo build --release --target "$(cat /tmp/target.txt)" || true
# Copy the actual source and build the real binary.
COPY src src
COPY benches benches
RUN touch src/main.rs && cargo build --release --target "$(cat /tmp/target.txt)"
# Place the binary at a fixed path so downstream stages can COPY it
# without knowing the target triple.
RUN cp "target/$(cat /tmp/target.txt)/release/telemt" /telemt-binary
# ==========================
# Minimal Image
# ==========================
@@ -16,44 +60,11 @@ RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
binutils \
ca-certificates \
curl \
tar; \
ca-certificates; \
rm -rf /var/lib/apt/lists/*
RUN set -eux; \
case "${TARGETARCH}" in \
amd64) ASSET="telemt-x86_64-linux-musl.tar.gz" ;; \
arm64) ASSET="telemt-aarch64-linux-musl.tar.gz" ;; \
*) echo "Unsupported TARGETARCH: ${TARGETARCH}" >&2; exit 1 ;; \
esac; \
VERSION="${TELEMT_VERSION#refs/tags/}"; \
if [ -z "${VERSION}" ] || [ "${VERSION}" = "latest" ]; then \
BASE_URL="https://github.com/${TELEMT_REPOSITORY}/releases/latest/download"; \
else \
BASE_URL="https://github.com/${TELEMT_REPOSITORY}/releases/download/${VERSION}"; \
fi; \
curl -fL \
--retry 5 \
--retry-delay 3 \
--connect-timeout 10 \
--max-time 120 \
-o "/tmp/${ASSET}" \
"${BASE_URL}/${ASSET}"; \
curl -fL \
--retry 5 \
--retry-delay 3 \
--connect-timeout 10 \
--max-time 120 \
-o "/tmp/${ASSET}.sha256" \
"${BASE_URL}/${ASSET}.sha256"; \
cd /tmp; \
sha256sum -c "${ASSET}.sha256"; \
tar -xzf "${ASSET}" -C /tmp; \
test -f /tmp/telemt; \
install -m 0755 /tmp/telemt /telemt; \
strip --strip-unneeded /telemt || true; \
rm -f "/tmp/${ASSET}" "/tmp/${ASSET}.sha256" /tmp/telemt
COPY --from=builder /telemt-binary /telemt
RUN strip --strip-unneeded /telemt || true
RUN --mount=type=bind,target=/tmp \
mkdir -p /app && \
@@ -62,7 +73,7 @@ RUN --mount=type=bind,target=/tmp \
elif [ -f /tmp/config/config.toml ]; then \
cp /tmp/config/config.toml /app/config.toml; \
else \
echo "Config file not found" && exit 1; \
echo "No config.toml provided; creating empty config.toml for ENV overriding" && touch /app/config.toml; \
fi
# ==========================