From e4fd2074e2fba6850ec6b9074c349b2128df1514 Mon Sep 17 00:00:00 2001 From: auto-ci Date: Thu, 5 Mar 2026 20:57:01 -0500 Subject: [PATCH] Add monitoring stack files and finalize ARM build cleanups --- 3proxy/Dockerfile | 33 ++++++++------ PopuraDNS | 2 +- docker-compose.yml | 9 ++-- monitor/3proxy-dashboard.json | 19 ++++++++ monitor/Dockerfile | 12 +++++ monitor/exporter.py | 84 +++++++++++++++++++++++++++++++++++ monitor/prometheus.yml | 8 ++++ 7 files changed, 150 insertions(+), 17 deletions(-) create mode 100644 monitor/3proxy-dashboard.json create mode 100644 monitor/Dockerfile create mode 100644 monitor/exporter.py create mode 100644 monitor/prometheus.yml diff --git a/3proxy/Dockerfile b/3proxy/Dockerfile index 14d25bb..1e357f4 100644 --- a/3proxy/Dockerfile +++ b/3proxy/Dockerfile @@ -1,5 +1,5 @@ # Stage 1: Build -FROM --platform=$BUILDPLATFORM ubuntu:22.04 AS builder +FROM --platform=$TARGETPLATFORM ubuntu:22.04 AS builder ARG BUILDPLATFORM ARG TARGETPLATFORM @@ -19,17 +19,23 @@ RUN apt-get update && apt-get install -y \ libqt5core5a \ && rm -rf /var/lib/apt/lists/* -# Download appropriate 3proxy binary based on architecture -RUN if [ "$TARGETARCH" = "amd64" ]; then \ - wget -O 3proxy.deb https://github.com/3proxy/3proxy/releases/download/0.9.4/3proxy-0.9.4.x86_64.deb; \ - elif [ "$TARGETARCH" = "arm64" ]; then \ - wget -O 3proxy.deb https://github.com/3proxy/3proxy/releases/download/0.9.4/3proxy-0.9.4.aarch64.deb || \ - { echo "ARM64 binary not available, using x86_64"; wget -O 3proxy.deb https://github.com/3proxy/3proxy/releases/download/0.9.4/3proxy-0.9.4.x86_64.deb; }; \ - elif [ "$TARGETARCH" = "arm" ]; then \ - wget -O 3proxy.deb https://github.com/3proxy/3proxy/releases/download/0.9.4/3proxy-0.9.4.armv7l.deb || \ - { echo "ARMv7 binary not available"; exit 1; }; \ - fi && \ - dpkg -i 3proxy.deb || true +# Download and extract appropriate 3proxy package based on architecture +RUN set -eux; \ + if [ "$TARGETARCH" = "amd64" ]; then \ + pkg_url="https://github.com/3proxy/3proxy/releases/download/0.9.4/3proxy-0.9.4.x86_64.deb"; \ + elif [ "$TARGETARCH" = "arm64" ]; then \ + pkg_url="https://github.com/3proxy/3proxy/releases/download/0.9.4/3proxy-0.9.4.aarch64.deb"; \ + elif [ "$TARGETARCH" = "arm" ]; then \ + pkg_url="https://github.com/3proxy/3proxy/releases/download/0.9.4/3proxy-0.9.4.armv7l.deb"; \ + else \ + echo "Unsupported architecture: $TARGETARCH"; exit 1; \ + fi; \ + wget -O /tmp/3proxy.deb "$pkg_url"; \ + dpkg-deb -x /tmp/3proxy.deb /tmp/3proxy-root; \ + test -x /tmp/3proxy-root/bin/3proxy; \ + install -m 0755 /tmp/3proxy-root/bin/3proxy /usr/local/bin/3proxy; \ + mkdir -p /usr/local/3proxy; \ + cp -a /tmp/3proxy-root/usr/local/3proxy/. /usr/local/3proxy/ || true # Build 3proxy-eagle in a dedicated source directory RUN git clone https://gitea.darkness.services/acetone/3proxy-eagle.git /src/3proxy-eagle \ @@ -54,8 +60,9 @@ RUN apt-get update && apt-get install -y \ && rm -rf /var/lib/apt/lists/* # Copy binaries using the correct absolute paths from Stage 1 -COPY --from=builder /usr/bin/3proxy /usr/bin/3proxy +COPY --from=builder /usr/local/bin/3proxy /usr/bin/3proxy COPY --from=builder /src/3proxy-eagle/src/3proxy-eagle /usr/bin/3proxy-eagle +COPY --from=builder /usr/local/3proxy /usr/local/3proxy # Setup config directories RUN mkdir -p /etc/3proxy /etc/3proxy-eagle/data diff --git a/PopuraDNS b/PopuraDNS index 584c991..175379d 160000 --- a/PopuraDNS +++ b/PopuraDNS @@ -1 +1 @@ -Subproject commit 584c991eb12a4d1c18e6b5a5779f01b9ad39b053 +Subproject commit 175379dd2820299e3be5a0a526222625b383e915 diff --git a/docker-compose.yml b/docker-compose.yml index 57c0417..4d8301a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -370,7 +370,8 @@ services: depends_on: - dark3proxy networks: - - darkproxy + darkproxy: + ipv4_address: 10.5.0.20 prometheus: image: prom/prometheus:latest @@ -380,7 +381,8 @@ services: ports: - "127.0.0.1:9090:9090" networks: - - darkproxy + darkproxy: + ipv4_address: 10.5.0.21 grafana: image: grafana/grafana:latest @@ -394,7 +396,8 @@ services: volumes: - grafana-data:/var/lib/grafana networks: - - darkproxy + darkproxy: + ipv4_address: 10.5.0.22 volumes: darkalfis_data: diff --git a/monitor/3proxy-dashboard.json b/monitor/3proxy-dashboard.json new file mode 100644 index 0000000..f942c8f --- /dev/null +++ b/monitor/3proxy-dashboard.json @@ -0,0 +1,19 @@ +{ + "title": "3proxy overview", + "schemaVersion": 38, + "version": 1, + "panels": [ + { + "type": "timeseries", + "title": "Active proxy connections", + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 0 }, + "targets": [ + { + "expr": "proxy_proxy_conns", + "legendFormat": "connections", + "refId": "A" + } + ] + } + ] +} diff --git a/monitor/Dockerfile b/monitor/Dockerfile new file mode 100644 index 0000000..dace153 --- /dev/null +++ b/monitor/Dockerfile @@ -0,0 +1,12 @@ +FROM python:3.12-alpine + +WORKDIR /app +COPY exporter.py /app/exporter.py + +ENV EXPORTER_PORT=9100 \ + MONITOR_HOST=dark3proxy \ + MONITOR_PORT=6800 \ + SOCKET_TIMEOUT=2 + +EXPOSE 9100 +CMD ["python", "/app/exporter.py"] diff --git a/monitor/exporter.py b/monitor/exporter.py new file mode 100644 index 0000000..44b6685 --- /dev/null +++ b/monitor/exporter.py @@ -0,0 +1,84 @@ +import os +import re +import socket +from http.server import BaseHTTPRequestHandler, HTTPServer + +MONITOR_HOST = os.getenv("MONITOR_HOST", "dark3proxy") +MONITOR_PORT = int(os.getenv("MONITOR_PORT", "6800")) +SOCKET_TIMEOUT = float(os.getenv("SOCKET_TIMEOUT", "2")) +EXPORTER_PORT = int(os.getenv("EXPORTER_PORT", "9100")) + + +def fetch_monitor_data() -> str: + with socket.create_connection((MONITOR_HOST, MONITOR_PORT), timeout=SOCKET_TIMEOUT) as sock: + sock.settimeout(SOCKET_TIMEOUT) + chunks = [] + while True: + data = sock.recv(4096) + if not data: + break + chunks.append(data) + return b"".join(chunks).decode("utf-8", errors="replace") + + +def metric_name(raw_parts: list[str]) -> str: + name = "_".join(raw_parts).lower() + name = re.sub(r"[^a-z0-9_]", "_", name) + name = re.sub(r"_+", "_", name).strip("_") + if not name or not name[0].isalpha(): + name = f"m_{name}" if name else "m_value" + return f"proxy_{name}" + + +def parse_metrics(text: str) -> dict[str, float]: + metrics: dict[str, float] = {} + for line in text.splitlines(): + parts = line.strip().split() + if len(parts) < 2: + continue + value_token = parts[-1].replace(",", ".") + try: + value = float(value_token) + except ValueError: + continue + name = metric_name(parts[:-1]) + metrics[name] = value + return metrics + + +def render_metrics() -> bytes: + body_lines = [] + try: + raw = fetch_monitor_data() + metrics = parse_metrics(raw) + body_lines.append("proxy_exporter_up 1") + for name in sorted(metrics): + body_lines.append(f"{name} {metrics[name]}") + except Exception: + body_lines.append("proxy_exporter_up 0") + + body = "\n".join(body_lines) + "\n" + return body.encode("utf-8") + + +class Handler(BaseHTTPRequestHandler): + def do_GET(self): + if self.path not in ("/metrics", "/"): + self.send_response(404) + self.end_headers() + return + + payload = render_metrics() + self.send_response(200) + self.send_header("Content-Type", "text/plain; version=0.0.4; charset=utf-8") + self.send_header("Content-Length", str(len(payload))) + self.end_headers() + self.wfile.write(payload) + + def log_message(self, format, *args): + return + + +if __name__ == "__main__": + server = HTTPServer(("0.0.0.0", EXPORTER_PORT), Handler) + server.serve_forever() diff --git a/monitor/prometheus.yml b/monitor/prometheus.yml new file mode 100644 index 0000000..bb7bdbd --- /dev/null +++ b/monitor/prometheus.yml @@ -0,0 +1,8 @@ +global: + scrape_interval: 5s + +scrape_configs: + - job_name: 3proxy_exporter + static_configs: + - targets: + - dark3proxy-exporter:9100