Quickstart
Five minutes from a clean Linux host to a Tiyi instance blocking real OWASP CRS attacks against a real upstream. We'll install the signed binary, start tiyi run, create one site, and watch the WAF do its job.
Prerequisites
- Linux on amd64 or arm64. Windows and macOS are not target hosts.
- curl to run the public binary installer.
- A spare backend you can put behind Tiyi — anything that speaks HTTP. The examples below use a Python
http.server.
1. Install the signed binary
Use the canonical public installer. It selects the matching Linux release, verifies its SHA-256 manifest, and installs tiyi into /usr/local/bin:
$ curl -fsSL https://www.tiyisec.com/install.sh | bash
$ tiyi --version
See Installation for version pinning, install-prefix overrides, and the Gitee mirror.
Existing v3.4.0 or earlier installation? Do not continue with the new-install flow or restart after a generic update. First make a complete verified backup, then follow the v3.5.3 full-uninstall upgrade.
2. Run in complete runtime
Pick the option that matches your privileges. As root the defaults work — state lands in /var/lib/tiyi and the proxy binds ports 80/443:
$ sudo tiyi run
As a normal user (no sudo), point Tiyi at writable paths and high ports:
$ tiyi run \
--state-db /tmp/tiyi.db \
--caddy-admin-socket /tmp/tiyi-caddy.sock \
--admin-socket /tmp/tiyi-admin.sock \
--proxy-http-addr 127.0.0.1:18080 \
--proxy-https-addr 127.0.0.1:18443
Tiyi prints a banner with the API URL, the bootstrap admin password (printed once on first run), and the Caddy admin socket path:
tiyi v3.5.3 run
api http://127.0.0.1:8080
proxy http://127.0.0.1:18080 https://127.0.0.1:18443
state /tmp/tiyi.db
bootstrap admin password: <random-shown-once>
Open http://127.0.0.1:8080/ in a browser. Log in as admin with the password above. The console opens at Overview. Its stable task areas are Overview, Application Delivery, Protection, Fleet, Events & Logs, Detection & Response, Monitoring, and Administration; permission filtering hides empty groups without changing deep links.
The bootstrap password is shown exactly once. Copy it from the terminal. If it is lost, do not delete state.db: on the Tiyi host run tiyi user list, then tiyi user reset-password <user-id> --password <new> over the local admin socket.
Choose your own admin password (optional)
For automation, container images, or CI, skip the generated password: set TIYI_AUTH_BOOTSTRAP_ADMIN_PASSWORD before the first boot and Tiyi uses it verbatim — no banner is printed. The username defaults to admin, and auto-generation only fires when no users exist yet, so restarts are no-ops.
$ mkdir -p /tmp/waf
$ TIYI_AUTH_BOOTSTRAP_ADMIN_PASSWORD='admin123@xxxxxxm' \
tiyi run \
--addr 0.0.0.0:8080 \
--state-db /tmp/waf/state.db \
--caddy-admin-socket /tmp/waf/caddy.sock \
--proxy-http-addr 0.0.0.0:8180 \
--proxy-https-addr 0.0.0.0:18443 \
--admin-socket /tmp/waf/admin.sock
3. Stand up a backend
In a second terminal, start something Tiyi can proxy to. Anything HTTP works — for the demo we'll use Python:
$ python3 -m http.server 9000
4. Create your first site
You can do this in the UI or via the CLI. The CLI uses the local admin socket and needs no token:
# 1. Create the site pointing at the demo server
$ tiyi site create \
--name demo \
--host demo.local \
--upstream-url http://127.0.0.1:9000 \
--tls none
# The site is active immediately after create.
The one-step path creates an upstream pool, uses the built-in Standard policy, translates the site into Caddy JSON, and hot-reloads Caddy through its admin socket. If anything fails, the previous config stays active and the site row is restored.
5. Verify the WAF blocks attacks
From a third terminal, send a baseline request and three classic attacks against the proxy port:
# Baseline — should pass
$ curl -sS -o /dev/null -w "%{http_code}\n" -H "Host: demo.local" http://127.0.0.1:18080/
200
# SQL injection
$ curl -sS -o /dev/null -w "%{http_code}\n" -H "Host: demo.local" \
"http://127.0.0.1:18080/?id=1'%20OR%20'1'='1"
403
# XSS
$ curl -sS -o /dev/null -w "%{http_code}\n" -H "Host: demo.local" \
"http://127.0.0.1:18080/?q=<script>alert(1)</script>"
403
# Path traversal
$ curl -sS -o /dev/null -w "%{http_code}\n" -H "Host: demo.local" \
"http://127.0.0.1:18080/../../../../etc/passwd"
403
In the dashboard at http://127.0.0.1:8080/#/logs/security, the three blocked requests appear immediately with the Coraza rule id, severity, attack tag, and the matching CRS message. The dashboard's traffic chart shows the 1:3 baseline-to-block ratio in real time.
What to read next
- Installation — signed binary installation, config files, Controller and Agent operation, and production-hardening fields you should set before going live.
- Domain model — what sites, upstreams, certificates, policies, agents, telemetry, and the audit chain actually are.
- CLI reference — current v3.5.3 operator commands grouped by resource; use built-in help for the complete flag surface.