Every IPAuth flow has the same two parts. You click an auth URL from your browser whenever your IP changes. Your server polls a server URL on a cron and updates its firewall to match. That's the whole product.
Zero Trust comes down to one habit: deny everything, then allow only what you can currently verify. The hard part was never the deny. It is keeping the allow current as people and devices move, which is why teams reach for a platform. IPAuth does that with a bookmark and a cron. Default-deny your SSH, your staging, your API, your admin panel, then let each person's live IP flow in through IPAuth and out to the edge you already run.
Every port and path starts closed. Nothing is reachable until a verified IP is on the list.
Each person or service is a named pair you can add, audit, and revoke on its own.
The allowlist refreshes every 2 minutes and a stale IP drops itself after 24 hours. No pruning.
No agent, no per-seat license, no vendor stack. Zero Trust posture on an operator budget.
Both connections initiate from your side. Your browser hits IPAuth. Your server polls IPAuth. We never push anything inbound. The firewall change happens entirely inside your own boundary, by code you control.
Clicking the auth URL is a normal HTTPS GET from your browser. IPAuth sees your public IP and stores it under your key.
Cron polls the server URL on a schedule you choose. Reads the IP IPAuth has stored. Nothing on your box accepts incoming connections from IPAuth.
Your shell script updates ufw / pf / Windows Firewall. The change never leaves the server. Your control plane stays yours.
Choose one on the left. Each is a real pattern we or our customers run. Want the deeper story behind any of them, the problem it solves and how people handle it today, follow the write-up link in each.
You run 5+ servers. Exposing port 22 means constant brute-force noise in auth.log and the risk that a stolen key gets used from anywhere. IPAuth locks 22 to a single IP (yours), and follows you when you move.
#!/bin/sh SERVER_URL="https://ipauth.net/serverquery/?key=YOUR_KEY" STATE=/var/cache/ipauth-last CURIP=$(curl --max-time 5 -fsS "$SERVER_URL" | grep -oE '"ipaddress":"[0-9.]+' | cut -d'"' -f4) [ -z "$CURIP" ] && exit 0 OLDIP=$(cat "$STATE" 2>/dev/null) [ "$CURIP" = "$OLDIP" ] && exit 0 [ -n "$OLDIP" ] && ufw delete allow from "$OLDIP" to any port 22 proto tcp >/dev/null 2>&1 ufw allow from "$CURIP" to any port 22 proto tcp comment "ipauth" echo "$CURIP" > "$STATE"
Drop it in cron every 2 minutes. The state file at /var/cache/ipauth-last lets the script delete the prior allow before adding the new one, so your firewall never grows. Combine with a bastion failsafe rule (a stable IP you control as a backup recovery path) so you never lock yourself out.
You're running staging.mycompany.com on ports 80/443 for previews. A half-built feature your QA team wants to see, a customer demo, a marketing review URL. You don't want it indexed, scraped, or screenshotted by anyone outside the team. A VPN feels heavy. IPAuth gives each team member a personal auth URL; the staging server allows only their current IPs.
Each team member has their own pair. The script reads all their server URLs and rebuilds an ipset that's referenced by an iptables rule on ports 80 + 443. Replace the KEYS list with each member's server key.
#!/bin/sh
SET=ipauth_team
KEYS="key_alice key_bob key_carol"
ipset create $SET hash:ip -exist
ipset flush $SET
for K in $KEYS; do
IP=$(curl --max-time 5 -fsS "https://ipauth.net/serverquery/?key=$K" \
| grep -oE '"ipaddress":"[0-9.]+' | cut -d'"' -f4)
[ -n "$IP" ] && ipset add $SET "$IP" -exist
done
Reference the set once in iptables (paired with a default-deny for those ports):
iptables -I INPUT -m set --match-set ipauth_team src \ -p tcp -m multiport --dports 80,443 -j ACCEPT
Cron every 2 minutes. Works the same way with nftables sets, pf tables, or Windows Firewall remote-address lists. Pick the primitive your stack uses.
You're a product owner. You want one specific person (your engineering lead, a customer, a contractor) to reach a gated URL behind your firewall or CDN. You don't want to expose the resource publicly, and you don't want to manually paste their current IP every time they switch networks. IPAuth issues each person a private bookmark, bundles them in an access group, and exposes one endpoint your sync script pulls from to keep your allowlist current.
Pulls the group's plain-text IP list, stores it in a state file, and only pushes downstream when the set changes. Replaces the prior set, so your firewall never accumulates stale entries even as users hop networks.
#!/bin/sh GROUP_URL="https://ipauth.net/api/g/YOUR_GROUP_TOKEN/ips.txt" STATE=/var/cache/ipauth-group.last NEW=$(curl --max-time 10 -fsS "$GROUP_URL" | tr '\n' ' ' | xargs) OLD=$(cat "$STATE" 2>/dev/null) [ "$NEW" = "$OLD" ] && exit 0 # unchanged → no-op # REPLACE downstream allowlist with current set. # Example for NOC.org CDN. Swap for your firewall / CDN / WAF. curl -fsS "https://my.noc.org/api?apikey=$NOC_KEY&action=cdn/set/whitelistedips&website=$DOMAIN&value=$(echo $NEW | jq -sRr @uri)" echo "$NEW" > "$STATE"
Same pattern works for ufw, iptables, Cloudflare rulesets, AWS security groups, pf tables. Only the downstream push command changes. Keep your firewall lean: always replace, never append.
You can't leave /login or /register open to the whole internet, but your users roam between networks and you don't want to hand each of them an account. Drop a small middleware in front of the page. Invite each user once; they click their personal bookmark, which marks that browser as a safe browser with a short-lived signed cookie, and the page opens. It follows the browser, not the IP, so it works from anywhere, and you can revoke any one browser from the dashboard.
One file, no dependencies beyond PHP's built-in crypto. Turn it on for the whole app without touching your code:
# php-fpm (Apache or nginx): a .user.ini in your web root auto_prepend_file=/var/www/ipauth-gate.php
Register the app in your dashboard, link a group, and it hands you the file and the exact config. References ship for PHP and FastAPI, and the same signed-cookie check drops into nginx, any framework, or the NOC edge with no app code.
Our own API sits behind NOC, our CDN and WAF. The edge is default-deny. Every developer has an IPAuth pair, bundled into one access group. A cron pushes the group's live IP list to NOC's allowlist for the API hostname every 2 minutes. A dev moves from the office to home to a hotel, clicks one bookmark, and their new IP is allowed at the edge within 2 minutes. To everyone else the API does not answer.
#!/bin/sh GROUP_URL="https://ipauth.net/api/g/YOUR_GROUP_TOKEN/ips.txt" STATE=/var/cache/ipauth-noc.last NEW=$(curl --max-time 10 -fsS "$GROUP_URL" | tr '\n' ' ' | xargs) OLD=$(cat "$STATE" 2>/dev/null) [ "$NEW" = "$OLD" ] && exit 0 # unchanged, no-op # Replace NOC's allowlist for the API hostname with the current set. curl -fsS "https://my.noc.org/api?apikey=$NOC_KEY&action=cdn/set/whitelistedips&website=$API_DOMAIN&value=$(echo $NEW | jq -sRr @uri)" echo "$NEW" > "$STATE"
Always replace, never append, so the edge stays lean as devs roam. The same pattern protects the IPAuth API itself, and swaps cleanly for Cloudflare, a WAF rule, or a cloud security group.
Your provisioning box or CI runner holds one IPAuth API key to register servers and manage allowlists. API keys leak: a committed env file, a CI log, a screenshot. IPAuth lets you bind a key's second factor, its allowed origin, to a roving IP that IPAuth itself tracks. The box reports its IP through a bookmark, and the key then authenticates only from whatever IP that bookmark currently reports. The allowed origin follows the box automatically, and a stale IP stops authorizing on its own after 24 hours.
Mint the key in the dashboard with "lock to a roving IP" ticked. From the box, register each new server as a pair and read back the poll URL. The same key from anywhere else fails closed.
#!/bin/sh
# Runs on your provisioning box, whose IP IPAuth tracks via the key's bookmark.
curl -fsS https://ipauth.net/api/v1/pairs \
-H "Authorization: Bearer $IPAUTH_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"web-prod-07"}'
# 201 with the server poll URL. From any unlisted IP: 403 forbidden_origin.
From any browser. IPAuth records the IP that hit it.
Cron / scheduled task hits it every few minutes. Reads the current registered IP.
Your shell script swaps the allow rule. Any port you choose, any service.
Generate a pair and wire up your first server in under 5 minutes.
Create a key pair →