[{"data":1,"prerenderedAt":693},["ShallowReactive",2],{"navigation_docs":3,"-quayel-gateway-getting-started-project-structure":91,"-quayel-gateway-getting-started-project-structure-surround":688},[4],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":90},"Quayel Gateway","i-lucide-network","\u002Fquayel-gateway","quayel-gateway",[10,29,68],{"title":11,"icon":12,"path":13,"stem":14,"children":15},"Getting Started","i-lucide-rocket","\u002Fquayel-gateway\u002Fgetting-started","quayel-gateway\u002F01.getting-started\u002Findex",[16,19,24],{"title":17,"path":13,"stem":14,"icon":18},"Introduction","i-lucide-book-open",{"title":20,"path":21,"stem":22,"icon":23},"Installation","\u002Fquayel-gateway\u002Fgetting-started\u002Finstallation","quayel-gateway\u002F01.getting-started\u002F1.installation","i-lucide-container",{"title":25,"path":26,"stem":27,"icon":28},"Project Structure","\u002Fquayel-gateway\u002Fgetting-started\u002Fproject-structure","quayel-gateway\u002F01.getting-started\u002F2.project-structure","i-lucide-folder-tree",{"title":30,"icon":31,"path":32,"stem":33,"children":34},"Plugins","i-lucide-puzzle","\u002Fquayel-gateway\u002Fplugins","quayel-gateway\u002F02.plugins\u002Findex",[35,38,43,48,53,58,63],{"title":36,"path":32,"stem":33,"icon":37},"Overview","i-lucide-workflow",{"title":39,"path":40,"stem":41,"icon":42},"IP Intelligence","\u002Fquayel-gateway\u002Fplugins\u002Fip-intel","quayel-gateway\u002F02.plugins\u002F1.ip-intel","i-lucide-radar",{"title":44,"path":45,"stem":46,"icon":47},"Firewall","\u002Fquayel-gateway\u002Fplugins\u002Ffirewall","quayel-gateway\u002F02.plugins\u002F2.firewall","i-lucide-shield",{"title":49,"path":50,"stem":51,"icon":52},"Rate Limiting","\u002Fquayel-gateway\u002Fplugins\u002Frate-limiting","quayel-gateway\u002F02.plugins\u002F3.rate-limiting","i-lucide-gauge",{"title":54,"path":55,"stem":56,"icon":57},"Cache","\u002Fquayel-gateway\u002Fplugins\u002Fcache","quayel-gateway\u002F02.plugins\u002F4.cache","i-lucide-database",{"title":59,"path":60,"stem":61,"icon":62},"Load Balancer","\u002Fquayel-gateway\u002Fplugins\u002Fload-balancer","quayel-gateway\u002F02.plugins\u002F5.load-balancer","i-lucide-scale",{"title":64,"path":65,"stem":66,"icon":67},"Auto-SSL","\u002Fquayel-gateway\u002Fplugins\u002Fauto-ssl","quayel-gateway\u002F02.plugins\u002F6.auto-ssl","i-lucide-lock",{"title":69,"icon":70,"path":71,"stem":72,"children":73},"AI","i-lucide-bot","\u002Fquayel-gateway\u002Fai","quayel-gateway\u002F03.ai\u002Findex",[74,75,80,85],{"title":36,"path":71,"stem":72,"icon":70},{"title":76,"path":77,"stem":78,"icon":79},"The Quayel Gateway Skill","\u002Fquayel-gateway\u002Fai\u002Fskill","quayel-gateway\u002F03.ai\u002F1.skill","i-lucide-wand-sparkles",{"title":81,"path":82,"stem":83,"icon":84},"Installing the Skill","\u002Fquayel-gateway\u002Fai\u002Finstallation","quayel-gateway\u002F03.ai\u002F2.installation","i-lucide-download",{"title":86,"path":87,"stem":88,"icon":89},"AI Agent Guide","\u002Fquayel-gateway\u002Fai\u002Fagent-guide","quayel-gateway\u002F03.ai\u002F3.agent-guide","i-lucide-braces",false,{"id":92,"title":25,"body":93,"description":681,"extension":682,"links":683,"meta":684,"navigation":685,"path":26,"seo":686,"stem":27,"__hash__":687},"docs\u002Fquayel-gateway\u002F01.getting-started\u002F2.project-structure.md",{"type":94,"value":95,"toc":672},"minimark",[96,100,105,116,263,270,417,431,452,456,516,566,570,629,633,636,660],[97,98,25],"h1",{"id":99},"project-structure",[101,102,104],"h2",{"id":103},"repository-layout","Repository layout",[106,107,112],"pre",{"className":108,"code":110,"language":111},[109],"language-text","quayel-gateway\u002F\n├── setup.sh              # bootstrap: datasets + cargo packages\n├── Dockerfile            # multi-stage image build (rust:1-bookworm → debian-slim)\n├── docker-compose.yml    # SSL-ready compose file (ports 80\u002F443, cert volume)\n├── Cargo.toml            # crate dependencies\n├── config.json           # live config (hot-reloaded on change)\n├── config.demo.json      # full-featured demo config\n├── config.all-rules.json # every feature enabled — used by the test suite\n├── src\u002F\n│   ├── main.rs           # entry point\n│   ├── gateway\u002F          # Pingora proxy pipeline\n│   ├── plugins\u002F          # ip_intel, firewall, rate_limit, cache, load_balancer\n│   ├── auto_ssl\u002F         # ACME \u002F Let's Encrypt automation\n│   ├── condition\u002F        # request matching engine\n│   ├── config\u002F           # JSON config loader + hot reload\n│   ├── data\u002F             # embedded MMDB + CIDR datasets (setup.sh)\n│   └── utils\u002F            # embedded_data, CIDR sets, helpers\n├── docs\u002F                 # full documentation (+ ai-guide.md, config.schema.json)\n├── skills\u002F               # AI skill package (skills\u002Fquayel-gateway\u002FSKILL.md)\n└── scripts\u002F              # benchmarks, live test suite, nginx\u002FAPISIX mirrors\n","text",[113,114,110],"code",{"__ignoreMap":115},"",[117,118,119,132],"table",{},[120,121,122],"thead",{},[123,124,125,129],"tr",{},[126,127,128],"th",{},"Path",[126,130,131],{},"What it is for",[133,134,135,146,156,166,176,186,204,217,234,249],"tbody",{},[123,136,137,143],{},[138,139,140],"td",{},[113,141,142],{},"setup.sh",[138,144,145],{},"One-time bootstrap: downloads embedded datasets and installs the Rust toolchain + crates",[123,147,148,153],{},[138,149,150],{},[113,151,152],{},"src\u002Fgateway\u002F",[138,154,155],{},"The Pingora proxy pipeline: request context, upstream selection, response handling",[123,157,158,163],{},[138,159,160],{},[113,161,162],{},"src\u002Fplugins\u002F",[138,164,165],{},"Plugin implementations — IP intel, firewall, rate limiting, cache, load balancer",[123,167,168,173],{},[138,169,170],{},[113,171,172],{},"src\u002Fauto_ssl\u002F",[138,174,175],{},"On-demand ACME \u002F Let's Encrypt certificate automation",[123,177,178,183],{},[138,179,180],{},[113,181,182],{},"src\u002Fcondition\u002F",[138,184,185],{},"The matching engine shared by firewall, rate limit, cache, and LB rules",[123,187,188,193],{},[138,189,190],{},[113,191,192],{},"src\u002Fconfig\u002F",[138,194,195,196,199,200,203],{},"Config schema (",[113,197,198],{},"schema.rs"," — authoritative) and loader (",[113,201,202],{},"loader.rs"," — startup validation)",[123,205,206,211],{},[138,207,208],{},[113,209,210],{},"src\u002Fdata\u002F",[138,212,213,214],{},"MMDB databases + CIDR lists, compiled into the binary via ",[113,215,216],{},"include_str!",[123,218,219,224],{},[138,220,221],{},[113,222,223],{},"docs\u002F",[138,225,226,227,230,231],{},"Markdown docs, ",[113,228,229],{},"ai-guide.md",", and ",[113,232,233],{},"config.schema.json",[123,235,236,241],{},[138,237,238],{},[113,239,240],{},"skills\u002F",[138,242,243,244,248],{},"The portable AI skill package (",[245,246,247],"a",{"href":82},"install it",")",[123,250,251,256],{},[138,252,253],{},[113,254,255],{},"scripts\u002F",[138,257,258,259,262],{},"Benchmarks and ",[113,260,261],{},"test-all-rules.sh"," (the 57-assertion live suite)",[101,264,266,267,269],{"id":265},"what-setupsh-does","What ",[113,268,142],{}," does",[271,272,273,399],"ol",{},[274,275,276,280,281,283,284],"li",{},[277,278,279],"strong",{},"Downloads the embedded datasets"," into ",[113,282,210],{}," (latest versions):",[117,285,286,296],{},[120,287,288],{},[123,289,290,293],{},[126,291,292],{},"File",[126,294,295],{},"Content",[133,297,298,308,318,328,338,348,358,368,378],{},[123,299,300,305],{},[138,301,302],{},[113,303,304],{},"dbip-city-lite.mmdb",[138,306,307],{},"DB-IP City Lite — country, region, city, lat\u002Flon",[123,309,310,315],{},[138,311,312],{},[113,313,314],{},"dbip-asn-lite.mmdb",[138,316,317],{},"DB-IP ASN Lite — ASN + organization",[123,319,320,325],{},[138,321,322],{},[113,323,324],{},"dbip-country.mmdb",[138,326,327],{},"DB-IP Country Lite — country fallback",[123,329,330,335],{},[138,331,332],{},[113,333,334],{},"cloudflare.txt",[138,336,337],{},"Cloudflare edge ranges (IPv4 + IPv6)",[123,339,340,345],{},[138,341,342],{},[113,343,344],{},"hosting-asns.txt",[138,346,347],{},"ASNs known for hosting \u002F abuse",[123,349,350,355],{},[138,351,352],{},[113,353,354],{},"proxy.txt",[138,356,357],{},"FireHOL anonymous proxy ranges",[123,359,360,365],{},[138,361,362],{},[113,363,364],{},"tor.txt",[138,366,367],{},"Tor Project exit nodes",[123,369,370,375],{},[138,371,372],{},[113,373,374],{},"vpn.txt",[138,376,377],{},"X4BNet VPN provider ranges",[123,379,380,385],{},[138,381,382],{},[113,383,384],{},"provider-asns.txt",[138,386,387,391,392,395,396,248],{},[388,389,390],"em",{},"(versioned in repo, not downloaded)"," — provider ASN registry: ",[113,393,394],{},"ASN|Label"," (e.g. ",[113,397,398],{},"47583|Hostinger",[274,400,401,404,405,408,409,412,413,416],{},[277,402,403],{},"Installs cargo packages"," — Rust toolchain (",[113,406,407],{},"rustup",") and system build tools if missing, then fetches every crate dependency from ",[113,410,411],{},"Cargo.toml"," \u002F ",[113,414,415],{},"Cargo.lock",".",[418,419,420,421,424,425,424,428],"p",{},"Flags: ",[113,422,423],{},".\u002Fsetup.sh --data-only"," · ",[113,426,427],{},".\u002Fsetup.sh --asns-only",[113,429,430],{},".\u002Fsetup.sh --cargo-only",[418,432,433,434,437,438,440,441,443,444,447,448,451],{},"Datacenter\u002Fhosting detection is ",[277,435,436],{},"ASN-based",": the ASN MMDB resolves any client IP to its ASN, and ",[113,439,384],{}," + ",[113,442,344],{}," classify the network. ",[277,445,446],{},"Adding a provider is one line"," in ",[113,449,450],{},"src\u002Fdata\u002Fprovider-asns.txt",", then rebuild.",[101,453,455],{"id":454},"runtime-layout-docker-image","Runtime layout (Docker image)",[117,457,458,467],{},[120,459,460],{},[123,461,462,464],{},[126,463,128],{},[126,465,466],{},"Purpose",[133,468,469,479,496,506],{},[123,470,471,476],{},[138,472,473],{},[113,474,475],{},"\u002Fusr\u002Flocal\u002Fbin\u002Fquayel-gateway",[138,477,478],{},"The gateway binary (entrypoint)",[123,480,481,486],{},[138,482,483],{},[113,484,485],{},"\u002Fetc\u002Fquayel-gateway\u002Fconfig.json",[138,487,488,489,492,493,248],{},"The config file (image ",[113,490,491],{},"WORKDIR"," is ",[113,494,495],{},"\u002Fetc\u002Fquayel-gateway",[123,497,498,503],{},[138,499,500],{},[113,501,502],{},"\u002Fvar\u002Flib\u002Fquayel\u002Fcerts",[138,504,505],{},"Auto-SSL certificate storage — persist this as a volume",[123,507,508,513],{},[138,509,510],{},[113,511,512],{},"\u002Fvar\u002Flog\u002Fquayel\u002Faccess.jsonl",[138,514,515],{},"Structured JSONL access log",[117,517,518,527],{},[120,519,520],{},[123,521,522,525],{},[126,523,524],{},"Port",[126,526,466],{},[133,528,529,542,555],{},[123,530,531,536],{},[138,532,533],{},[113,534,535],{},"80",[138,537,538,539,248],{},"HTTP — ACME HTTP-01 challenges + plain HTTP (map to container ",[113,540,541],{},"8080",[123,543,544,549],{},[138,545,546],{},[113,547,548],{},"443",[138,550,551,552,248],{},"HTTPS — SNI cert resolver \u002F Auto-SSL (map to container ",[113,553,554],{},"8443",[123,556,557,563],{},[138,558,559,412,561],{},[113,560,541],{},[113,562,554],{},[138,564,565],{},"The demo config's listeners inside the container",[101,567,569],{"id":568},"environment-variables","Environment variables",[117,571,572,585],{},[120,573,574],{},[123,575,576,579,582],{},[126,577,578],{},"Variable",[126,580,581],{},"Default",[126,583,584],{},"Description",[133,586,587,614],{},[123,588,589,594,599],{},[138,590,591],{},[113,592,593],{},"RUST_LOG",[138,595,596],{},[113,597,598],{},"info",[138,600,601,602,605,606,605,608,605,611,248],{},"Log level (",[113,603,604],{},"debug",", ",[113,607,598],{},[113,609,610],{},"warn",[113,612,613],{},"error",[123,615,616,621,626],{},[138,617,618],{},[113,619,620],{},"QUAYEL_IP_INTEL_CACHE_SIZE",[138,622,623],{},[113,624,625],{},"65536",[138,627,628],{},"LRU cache size for IP lookups",[101,630,632],{"id":631},"config-and-hot-reload","Config and hot reload",[418,634,635],{},"The gateway watches its config file and reloads it on change:",[637,638,639,650,657],"ul",{},[274,640,641,642,645,646,649],{},"A ",[277,643,644],{},"valid"," save is applied without a restart (log line: ",[113,647,648],{},"Config hot-reloaded successfully",").",[274,651,652,653,656],{},"An ",[277,654,655],{},"invalid"," save is rejected and the previous config keeps serving.",[274,658,659],{},"Edit atomically (write to a temp file, then rename) so the watcher never sees a half-written file.",[661,662,663,664,667,668,416],"tip",{},"Bump ",[113,665,666],{},"config_version"," on every config change — it is stamped into every log line so you can tell exactly which config handled a request. See ",[245,669,671],{"href":670},"\u002Fquayel-gateway\u002Fversioning","Versioning",{"title":115,"searchDepth":673,"depth":673,"links":674},2,[675,676,678,679,680],{"id":103,"depth":673,"text":104},{"id":265,"depth":673,"text":677},"What setup.sh does",{"id":454,"depth":673,"text":455},{"id":568,"depth":673,"text":569},{"id":631,"depth":673,"text":632},"How the Quayel Gateway repository is organized and where the gateway keeps its files at runtime.","md",null,{},{"icon":28},{"title":25,"description":681},"R6-XvrurJVbQ_7OaHgO3kCLDbXomvEjgamVwTTR-ik4",[689,691],{"title":20,"path":21,"stem":22,"description":690,"icon":23,"children":-1},"Run Quayel Gateway with Docker in minutes. APT packages and direct downloads are coming soon.",{"title":36,"path":32,"stem":33,"description":692,"icon":37,"children":-1},"The plugin pipeline: IP intelligence, firewall, rate limiting, cache, load balancing, auto-SSL, and logging.",1791649767382]