Skip to content

carlHandy/go-tinyproxy

Repository files navigation

tinyproxy

A security-focused reverse proxy and web server — a single-binary alternative to nginx + Traefik with native bot detection and AI crawler prevention built into the request pipeline.

Requirements

  • Go 1.23+ (only if building from source)
  • mkcert (development only)

Installation

You can download pre-compiled binaries and packages for your operating system from the Releases page.

Debian / Ubuntu

Download the .deb package and install it (replace `1.11 with the latest version):

wget https://github.com/carlHandy/go-tinyproxy/releases/download/v1.1.1/go-tinyproxy_1.1.1_linux_amd64.deb
sudo dpkg -i go-tinyproxy_1.1.1_linux_amd64.deb

RHEL / Fedora / AlmaLinux

Download the .rpm package and install it (replace 1.0.0 with the latest version):

wget https://github.com/carlHandy/go-tinyproxy/releases/download/v1.1.1/tinyproxy_1.1.1_linux_amd64.rpm
sudo rpm -i tinyproxy_1.0.0_linux_amd64.rpm

macOS / Linux (Standalone Binary)

Download the .tar.gz archive, extract it, and move the binary to your path:

wget https://github.com/carlHandy/go-tinyproxy/releases/download/v1.1.1/tinyproxy_1.1.1_linux_amd64.tar.gz
tar -xzf tinyproxy_1.0.0_linux_amd64.tar.gz
sudo mv tinyproxy /usr/local/bin/

(Note: If you are on macOS or an ARM64 machine, make sure to grab the darwin or arm64 archive instead!)

Windows

Download tinyproxy_1.0.0_windows_amd64.zip from the releases page and extract it.

Do not double-click tinyproxy.exe — Windows will open and immediately close the console window before you can see any output. Always run it from a Command Prompt or PowerShell session:

# Open PowerShell or Command Prompt, cd to the extracted folder, then:
.\tinyproxy.exe serve

If the window still flashes and exits, the most common cause is a missing or invalid config/vhosts.conf. Make sure the config/ directory (with a valid vhosts.conf) is in the same folder as the binary before running.

Build from Source

If you prefer to compile it yourself:

git clone https://github.com/carlHandy/go-tinyproxy.git
cd go-tinyproxy
go build -o tinyproxy ./cmd/tinyproxy/
sudo mv tinyproxy /usr/local/bin/

Managing the service

When installed via .deb or .rpm, go-tinyproxy runs as a systemd service and starts automatically on boot. Use the built-in CLI to manage it:

go-tinyproxy start      # start the service
go-tinyproxy stop       # stop the service
go-tinyproxy restart    # restart the service
go-tinyproxy reload     # reload config without downtime (sends SIGHUP)
go-tinyproxy status     # show service status
go-tinyproxy config     # open /etc/go-tinyproxy/vhosts.conf in $EDITOR (falls back to nano)
go-tinyproxy logs       # tail live logs via journalctl
go-tinyproxy upgrade    # download and install the latest release, then restart

After editing the config, apply changes without restarting:

go-tinyproxy config     # edit the file
go-tinyproxy reload     # pick up the changes instantly

Default page

Before you configure any virtual hosts, visiting your server's IP in a browser will:

  1. Redirect HTTP → HTTPS automatically
  2. Serve a built-in default page over TLS

Note: Direct IP access uses a self-signed certificate (ACME cannot issue certs for IPs), so your browser will show a security warning. This is expected until you point a domain at the server and configure a vhost.

Running

Development

Dev mode listens on :8080. Both http://localhost:8080 and https://localhost:8080 work — plain HTTP connections are automatically redirected to HTTPS. Generate the local certificates once with mkcert:

mkcert localhost 127.0.0.1 ::1
mkdir -p certs
mv localhost+2.pem certs/
mv localhost+2-key.pem certs/

Then start the server:

ENV=dev go run ./cmd/tinyproxy/

Production

Production mode listens on :443 with automatic TLS via Let's Encrypt (ACME), and spins up an HTTP→HTTPS redirect on :80.

go-tinyproxy

(Note: If not installed via a package manager to run as a service, you may need to run with sudo to bind to ports 80 and 443).

Certificates are obtained automatically for every domain defined in config/vhosts.conf and cached in the certs/ directory. The server must be publicly reachable on port 80 for the ACME challenge.

Configuration

Edit config/vhosts.conf. The format is a custom block DSL — not YAML or TOML.

Reverse proxy

vhosts {
    example.com {
        port 443
        proxy_pass http://backend:8080
    }
}

Static file server

vhosts {
    example.com {
        port 80
        root /var/www/html
    }
}

PHP via FastCGI

vhosts {
    example.com {
        port 80
        root /var/www/html
        fastcgi {
            pass 127.0.0.1:9000
            index index.php
            param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name
        }
    }
}

SSL (production with your own certs)

vhosts {
    example.com {
        port 443
        proxy_pass http://backend:8080
        ssl {
            cert /etc/certs/example.com.crt
            key  /etc/certs/example.com.key
        }
    }
}

SOCKS5 proxy for upstream connections

vhosts {
    example.com {
        proxy_pass http://backend:8080
        socks5 {
            address  127.0.0.1:1080
            username proxy_user
            password proxy_pass
        }
    }
}

Security headers

vhosts {
    example.com {
        proxy_pass http://backend:8080
        security {
            frame_options    DENY
            content_type     nosniff
            xss_protection   "1; mode=block"
            csp              "default-src 'self'"
            hsts             "max-age=31536000; includeSubDomains"
            rate_limit {
                requests 100
                window   1m
            }
        }
    }
}

Defaults applied to every vhost: X-Frame-Options: SAMEORIGIN, X-Content-Type-Options: nosniff, Strict-Transport-Security: max-age=31536000; includeSubDomains, 100 req/min rate limit, 10 MB max body size.

Bot and AI crawler protection

Bot detection is opt-in per vhost. Enable it with a bot_protection block:

vhosts {
    example.com {
        proxy_pass http://backend:8080
        bot_protection {
            enabled        true
            block_scanners true
            honeypot       true
        }
    }
}

enabled — activates the middleware for this vhost.

block_scanners — intercepts requests to known vulnerability-scanning paths: /.env, /.git, /wp-admin, /phpMyAdmin, /actuator, /etc/passwd, and others. Handles URL-encoded variants (/.%65nv) and path normalisation tricks (//wp-admin).

honeypot — instead of returning 403, serve convincing fake content tailored to the requested path (fake .env with bogus credentials, fake WordPress login, fake phpMyAdmin, fake Spring Boot actuator JSON, etc.). Adds a random 150–750 ms delay to slow down automated scanners. Every hit is logged with HONEYPOT prefix for easy filtering. When omitted, blocked requests receive a plain 403.

block_path <path> — block a path prefix that isn't in the built-in list. Applies the same URL-decode and path-normalisation logic as block_scanners, and respects honeypot. Repeat the directive for multiple paths:

bot_protection {
    enabled        true
    block_scanners true
    honeypot       true
    block_path     /jenkins
    block_path     /phpMyAdmin
    block_path     /actuator
    block_path     /wp-admin
}

block <token> — add extra User-Agent substrings to block beyond the built-in list:

bot_protection {
    enabled true
    block   MyCustomScraper
}

allow <token> — permanently allow a User-Agent substring, overriding all block rules:

bot_protection {
    enabled true
    allow   FriendlyPartnerBot
}

Built-in blocked agents

AI crawlers and scrapers blocked by default when enabled true:

Category Agents
AI crawlers GPTBot, ClaudeBot, CCBot, PerplexityBot, YouBot, anthropic-ai, cohere-ai, Bytespider
SEO bots AhrefsBot, SemrushBot, MJ12bot, DotBot, PetalBot
Scrapers python-requests, Scrapy, libwww-perl, masscan, zgrab

Built-in allowed agents

Always permitted through, regardless of block rules:

Googlebot, bingbot, DuckDuckBot, Slurp (Yahoo), Baiduspider, facebookexternalhit, Twitterbot, LinkedInBot, Applebot

Allowlist matching uses word-boundary detection — a UA like EvilGooglebot/1.0 is not treated as Googlebot.

TLS

All TLS connections enforce:

  • TLS 1.2 minimum
  • Forward-secret cipher suites only (ECDHE-AES-GCM, ECDHE-ChaCha20-Poly1305)
  • Preferred curves: X25519, P-256

Development

# Build
go build ./cmd/tinyproxy/

# Run tests
go test ./...

# Vet
go vet ./...

About

A secure and performant web server built with Go

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors