Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/klzgrad/naiveproxy/llms.txt

Use this file to discover all available pages before exploring further.

HAProxy is a battle-tested, high-performance load balancer and proxy that can serve as an alternative frontend for NaïveProxy. Compared to the Caddy-based setup, the HAProxy approach is more complex — it involves separate tools for certificate management, the forward proxy backend, and TLS termination — but it is widely used in production environments and offers granular control over routing and authentication. This guide walks through each component in order.
Before going live, change name, pass, and login-key.test in the HAProxy configuration to values that are hard to guess. Leaving the defaults in place exposes your proxy to anyone who reads this guide.
1
Configure Let’s Encrypt Certificates
2
HAProxy requires certificates in a bundled PEM format and benefits from serving both an ECC and an RSA certificate for maximum client compatibility. Use acme.sh to issue and install both.
3
As root, install acme.sh:
4
git clone https://github.com/Neilpang/acme.sh.git
cd ./acme.sh
./acme.sh --install
. ~/.bashrc
5
Issue both an ECC (P-256) and an RSA (2048-bit) certificate for your domain:
6
site=example.org
acme.sh -k ec-256 -d $site -d www.$site --issue -w /var/www/html
acme.sh -k 2048  -d $site -d www.$site --issue -w /var/www/html
7
Install the certificates in the bundled format HAProxy expects:
8
mkdir -p /etc/haproxy/certs
acme.sh --install-cert --ecc -d $site \
  --key-file /tmp/$site.key \
  --fullchain-file /tmp/$site.crt \
  --reloadcmd "cat /tmp/$site.* >/etc/haproxy/certs/$site.pem.ecdsa; rm /tmp/$site.*; service haproxy restart"

acme.sh --install-cert -d $site \
  --key-file /tmp/$site.key \
  --fullchain-file /tmp/$site.crt \
  --reloadcmd "cat /tmp/$site.* >/etc/haproxy/certs/$site.pem.rsa; rm /tmp/$site.*; service haproxy restart"
9
The --reloadcmd concatenates the key and full-chain into a single PEM file that HAProxy can read, then restarts HAProxy automatically whenever acme.sh renews the certificate.
10
Install and Configure tinyproxy
11
tinyproxy acts as the local forward proxy backend that HAProxy routes authenticated requests to. It listens only on localhost so it is never directly reachable from the internet.
12
Install the package:
13
apt install tinyproxy
14
Edit /etc/tinyproxy/tinyproxy.conf to contain the following:
15
User tinyproxy
Group tinyproxy
PidFile "/run/tinyproxy/tinyproxy.pid"
MaxClients 100
MinSpareServers 5
MaxSpareServers 20
StartServers 10
Port 8888

Listen 127.0.0.1
LogFile "/dev/null"
DisableViaHeader Yes
16
Key settings to note:
17
  • Listen 127.0.0.1 — Binds only to localhost; tinyproxy is never exposed directly.
  • DisableViaHeader Yes — Suppresses the Via header that would reveal a proxy is in the path.
  • LogFile "/dev/null" — Discards logs to avoid recording user activity.
  • 18
    Install and Configure HAProxy
    19
    Check the NaïveProxy issues for the currently tested and recommended HAProxy version before installing.
    20
    Install HAProxy:
    21
    apt install haproxy
    
    22
    Append the following to /etc/haproxy/haproxy.cfg:
    23
    userlist users
            user name insecure-password pass
    
    frontend haproxy_tls
            bind :443 ssl crt /etc/haproxy/certs/ alpn h2,http/1.1
            option http-use-proxy-header
            acl login base_dom login-key.test
            acl auth_ok http_auth(users)
            http-request auth if login !auth_ok
            http-request redirect location https://google.com if login auth_ok
            use_backend proxy if auth_ok
            default_backend masquerade
    
    backend proxy
            http-request del-header proxy-authorization
            server proxy 127.0.0.1:8888
    
    backend masquerade
            server nginx 127.0.0.1:80
    
    24
    How it works:
    25
  • The userlist users block defines the credentials HAProxy checks against.
  • The frontend haproxy_tls block terminates TLS on port 443, advertising both HTTP/2 and HTTP/1.1 via ALPN, and loading all certificate PEM files from /etc/haproxy/certs/.
  • The login ACL matches requests to your secret login domain (e.g. login-key.test). Visiting that domain in a browser triggers an HTTP auth prompt; a successful login redirects to google.com.
  • Clients that have already supplied valid Proxy-Authorization credentials are routed to the proxy backend (tinyproxy on port 8888). The Proxy-Authorization header is stripped before forwarding.
  • All other requests — including any active probing attempts — are routed to the masquerade backend, which serves your regular website from a local web server on port 80.
  • 26
    Replace name, pass, and login-key.test with values that are hard to guess. Anyone who knows these values can use your proxy or confirm its existence.
    27
    To authenticate from a browser, visit https://login-key.test (the https:// scheme is required — http:// will not work through HAProxy’s TLS frontend).
    28
    (Optional) Add Android WiFi PAC File Support
    29
    HTTPS proxying on Android via the system WiFi proxy setting requires a PAC (Proxy Auto-Config) file URL rather than a direct proxy address.
    30
    Add the following lines to the frontend haproxy_tls section, directly after the bind line:
    31
            acl pac path /proxy-key.pac
            errorfile 200 /etc/haproxy/errors/proxy.pac.http
            http-request deny deny_status 200 if pac
    
    32
    Create the file /etc/haproxy/errors/proxy.pac.http with this content:
    33
    HTTP/1.0 200 OK
    Cache-Control: no-cache
    Connection: close
    Content-Type: text/plain
    
    function FindProxyForURL(url, host) {
      if (shExpMatch(host, "localhost")) return "DIRECT";
      if (shExpMatch(host, "192.168.*")) return "DIRECT";
      if (shExpMatch(host, "127.0.*")) return "DIRECT";
      return "HTTPS example.org";
    }
    
    
    34
    Replace example.org with your actual domain. On Android, configure the WiFi proxy to use the PAC URL https://example.org/proxy-key.pac. The proxy-key.pac path should be something hard to guess so the PAC file is not publicly discoverable.

    Next Steps

    • For the simpler, Caddy-based setup that handles certificates automatically, see Caddy Setup.
    • To run Caddy as a persistent systemd service, see Run as Daemon.

    Build docs developers (and LLMs) love