From b0e1e2dbabfbf0f081bbf42b1c7dd1b28b4198e7 Mon Sep 17 00:00:00 2001 From: Jorge Maturana Date: Sun, 26 Jul 2026 22:50:09 -0400 Subject: [PATCH 1/5] test: add test on gh action --- .github/workflows/test.yml | 35 +++++++++++++++++++++++++++++++++++ .gitignore | 7 ++++++- 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..4b0c850 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,35 @@ +name: Smoke test +on: + push: + branches: [main] + pull_request: + branches: [main] +jobs: + smoke: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: docker/setup-buildx-action@v3 + - run: echo "CONTROL_PASSWORD=test-$(openssl rand -base64 12)" > .env + - run: docker compose up -d --build --scale tor=3 + - name: Wait for Tor bootstrap + run: sleep 120 + - name: Test proxy + run: | + result=$(curl --socks5-hostname 127.0.0.1:1080 -s --max-time 30 https://check.torproject.org/api/ip) + echo "check.torproject.org: $result" + echo "$result" | grep -q '"IsTor": true' || { echo "FAIL: not Tor exit"; exit 1; } + - name: Test DNS leak + run: | + status=$(curl --socks5-hostname 127.0.0.1:1080 -s -o /dev/null -w "%{http_code}" --max-time 30 https://dnsleaktest.com) + echo "dnsleaktest.com: HTTP $status" + [ "$status" = "200" ] || { echo "FAIL: HTTP $status"; exit 1; } + - name: Show backends + run: | + docker compose exec discovery bash -c 'echo "show servers state tor_pool" | socat - tcp:haproxy:5555' | awk '!/^#/ && NF>0 {print $4, $5, "op="$6}' || true + docker compose logs discovery --since 10m | grep -c "Only servers in maintenance mode" | xargs -I{} echo "errors: {}" + - name: Logs on failure + if: failure() + run: | + docker compose logs --tail 50 discovery + docker compose logs --tail 20 haproxy diff --git a/.gitignore b/.gitignore index b1ef287..9727c58 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,9 @@ tor_data/ # Docker artifacts *.tar -docs/plans \ No newline at end of file +# Superseded — moved to docs/resources/scripts/ +scripts/generate-compose.sh + +docs/plans +docs/resources +docs/reports \ No newline at end of file From 6b017cc698f010c13f6f000cc0313a3bfc6728c8 Mon Sep 17 00:00:00 2001 From: Jorge Maturana Date: Sun, 26 Jul 2026 22:50:27 -0400 Subject: [PATCH 2/5] fix: template haproxy --- .gitignore | 3 --- config/haproxy/haproxy.cfg.template | 5 +++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 9727c58..b072dbf 100644 --- a/.gitignore +++ b/.gitignore @@ -16,9 +16,6 @@ tor_data/ # Docker artifacts *.tar -# Superseded — moved to docs/resources/scripts/ -scripts/generate-compose.sh - docs/plans docs/resources docs/reports \ No newline at end of file diff --git a/config/haproxy/haproxy.cfg.template b/config/haproxy/haproxy.cfg.template index 2d2073b..8f9a946 100644 --- a/config/haproxy/haproxy.cfg.template +++ b/config/haproxy/haproxy.cfg.template @@ -1,12 +1,13 @@ global maxconn 4096 - log stdout format raw local0 + log stdout format raw local0 info stats socket ipv4@0.0.0.0:5555 level admin defaults mode tcp log global option tcplog + log-format "%ci:%cp [%t] %ft %b/%s %Tw/%Tc/%Tt %B %ts %si:%sp %ac/%fc/%bc/%sc/%rc %sq/%bq" timeout connect 10s timeout client 120s timeout server 120s @@ -27,4 +28,4 @@ listen stats mode http stats enable stats uri /stats - stats refresh 10s + stats refresh 1s From e2019401270d967a58a4ad9ac34a8f0fe3c6150b Mon Sep 17 00:00:00 2001 From: Jorge Maturana Date: Sun, 26 Jul 2026 23:00:23 -0400 Subject: [PATCH 3/5] fix: copy haproxy.cfg.template (tracked) instead of haproxy.cfg (gitignored) The Dockerfile was copying haproxy.cfg which is gitignored and doesn't exist on fresh CI clones. Use haproxy.cfg.template (which is tracked) as the build source. --- config/haproxy/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/haproxy/Dockerfile b/config/haproxy/Dockerfile index 97efe45..529869b 100644 --- a/config/haproxy/Dockerfile +++ b/config/haproxy/Dockerfile @@ -1,6 +1,6 @@ FROM haproxy:3.0-alpine@sha256:dee54db8b27cd6c21519ea4f0ba0604f3742e8e7369bc16fb5b69133dec3f47f -COPY haproxy.cfg /usr/local/etc/haproxy/haproxy.cfg +COPY haproxy.cfg.template /usr/local/etc/haproxy/haproxy.cfg HEALTHCHECK --interval=15s --timeout=3s --retries=2 \ CMD nc -z 127.0.0.1 1080 || exit 1 From 995eb2620ec046666a592c311be383fe783d0503 Mon Sep 17 00:00:00 2001 From: Jorge Maturana Date: Sun, 26 Jul 2026 23:38:53 -0400 Subject: [PATCH 4/5] fix: grep pattern for IsTor json key without space check.torproject.org returns {"IsTor":true,...} without space after colon, causing the grep '"IsTor": true' to fail. --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4b0c850..a30676f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: run: | result=$(curl --socks5-hostname 127.0.0.1:1080 -s --max-time 30 https://check.torproject.org/api/ip) echo "check.torproject.org: $result" - echo "$result" | grep -q '"IsTor": true' || { echo "FAIL: not Tor exit"; exit 1; } + echo "$result" | grep -q '"IsTor":' || { echo "FAIL: not Tor exit"; exit 1; } - name: Test DNS leak run: | status=$(curl --socks5-hostname 127.0.0.1:1080 -s -o /dev/null -w "%{http_code}" --max-time 30 https://dnsleaktest.com) From 522ac45ea44140040c093e74c992d771a92d7159 Mon Sep 17 00:00:00 2001 From: Jorge Maturana Date: Sun, 26 Jul 2026 23:47:06 -0400 Subject: [PATCH 5/5] fix: validate IsTor is true, not just presence of key Use 'IsTor:[ ]*true' pattern to match both 'IsTor:true' and 'IsTor: true' but reject false. --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a30676f..966230b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -18,7 +18,7 @@ jobs: run: | result=$(curl --socks5-hostname 127.0.0.1:1080 -s --max-time 30 https://check.torproject.org/api/ip) echo "check.torproject.org: $result" - echo "$result" | grep -q '"IsTor":' || { echo "FAIL: not Tor exit"; exit 1; } + echo "$result" | grep -q '"IsTor":[ ]*true' || { echo "FAIL: not Tor exit"; exit 1; } - name: Test DNS leak run: | status=$(curl --socks5-hostname 127.0.0.1:1080 -s -o /dev/null -w "%{http_code}" --max-time 30 https://dnsleaktest.com)