ip2nginx
ip2nginx is a lightweight and secure system for dynamically updating NGINX reverse proxy configurations based on IP address changes reported by remote systems (e.g., pfSense). It is particularly useful in scenarios where IP addresses change dynamically and need to be synchronized with a web server’s reverse proxy configuration.
⚙️ Features
- Accepts remote updates via update.php (must be present on the server).
- Logs all changes to log.json.
- Access is controlled using tokens stored in token.json.
- Protects against abuse by blocking IPs after repeated failed attempts, using blocklist.json and failures.json.
- The core function is to locate a specific location block inside the domain’s nginx.conf and update only the proxy_pass value — without overwriting the entire file.
- Automatically reloads NGINX using nginx -t && systemctl reload nginx.
📁 Project Structure
ip2nginx/
├── .htaccess # Restricts access, routes all requests to updater
├── updater.php # Applies proxy_pass updates to nginx.conf
├── update.php # Processes and applies external IP update requests
├── run.sh # CLI wrapper script for triggering update
├── index.php # Default entry point and fallback error handling
├── data/ # Data storage directory
│ ├── meta.json # Central metadata file for all domains
│ ├── token.json # Authorized tokens for each client
│ ├── log.json # Log of updates and timestamps
│ ├── blocklist.json # IPs blocked after repeated failed attempts
│ └── failures.json # Failed authentication tracking
✅ Example Entry in token.json
{
"domain1.to.com": "SECRET_TOKEN_8v73jDKsdLzAq9DkeUz1",
"domain2.to.com": "SECRET_TOKEN_3im83jUj28mjo2mI23un"
}
✅ Example Entry in meta.json
{
"domain1.to.com": {
"domain": "domain.from.com",
"ip": "192.0.2.4",
"port": "443",
"protocol": "https",
"location": "/",
"time": "2025-05-16T09:00:00+00:00",
"changed": 1
}
}
🚀 Remote update Process: update.php
The API supports both GET and POST requests, though POST is recommended to prevent token caching by proxies or browsers.
| Parameter | Required | Description |
|---|---|---|
name |
✅ | Identifier for the configuration entry (e.g., domain1.to.com) |
token |
✅ | Secret token assigned to the client for authentication |
ip |
❌ | New public IP address (auto-detected if omitted) |
domain |
❌ | Target domain name to connect to (e.g., domain.from.com) |
| (default: IP address) | ||
port |
❌ | Proxy port (default: 443 for HTTPS, 80 for HTTP) |
protocol |
❌ | Protocol to use: http or https (default: http) |
location |
❌ | Specific location block in NGINX to update (default: /) |
If the domain, IP, port, or protocol differ from the previously saved values, the entry in meta.json is automatically marked with "changed": 1.
🚀 Local update Process: updater.php
This script is meant to be run via CLI (e.g. cronjob). It will:
- Load all entries from
meta.json - Process only those marked as
"changed": 1 - Locate the virtual host config:
/var/www/vhosts/system/<domain>/conf/nginx.conf - Replace only the
proxy_passinside the matchinglocationblock - Validate and reload Nginx (
sudo nginx -t && sudo systemctl reload nginx) - Reset the
"changed"flag inmeta.json
⏱ Cronjob Setup: Running run.sh Every 5 Minutes
To automatically apply updates to nginx.conf when new data is received via update.php, you should schedule the run.sh script to run regularly. This ensures that any entries marked as "changed": 1 in meta.json are processed and deployed without manual intervention.
🔧 Recommended Cron Configuration
To run the update script every 5 or 10 minutes as root (required for writing to NGINX config files and reloading the server):
- Open the root user’s crontab:
sudo crontab -e
- Add the following line:
*/5 * * * * /path/to/ip2nginx/run.sh
Replace /path/to/ip2nginx/ with the actual path where your run.sh script is located.
✅ Why It Must Run as Root
The updater modifies system-level files, typically located in:
/var/www/vhosts/system/<domain>/conf/nginx.conf
These files usually require root privileges for writing. Additionally, reloading NGINX via:
sudo nginx -t && sudo systemctl reload nginx
also requires elevated permissions. If run.sh is not run as root, the updates will silently fail or be skipped due to insufficient access rights.
🛡 Security
.htaccessblocks direct access to internal logic.- Only HTTPS connections should be used.
- Only
update.phpis directly accessible. All other access is routed throughindex.php. - All access is name and token-authenticated
- IP addresses are blocked for 48 hours after 3 failed attempts
- API responses are intentionally generic to prevent brute-force probing
🔄 Usage Example from pfSense
You can create a cron task in pfSense or use a shell script to send updated IP info to the server:
#!/bin/sh
SERVER="https://your-server.com/ip2nginx"
NAME="domain1.to.com"
DOMAIN="domain.from.com"
TOKEN="YOUR_SECRET_TOKEN"
curl -s -X POST "$SERVER/update.php" \
-d "name=$NAME" \
-d "domain=$DOMAIN" \
-d "protocol=https" \
-d "port=443" \
-d "token=$TOKEN"
OR
curl -s -X POST "https://your-server.com/ip2nginx/update.php" "name=domain1.to.com" -d "token=SECRET_TOKEN_8v73jDKsdLzAq9DkeUz1" -d "protocol=https"
Add this script to pfSense via System > Advanced > Cron and run it every 5 or 10 minutes.
✅ Dependencies
- PHP 7.4+
nginxinstalled with permissions to reload viasystemctlcurlfor shell scripts (on client side)- Token-based access configuration in
token.json
📜 License
MIT or similar — free to use, modify, and deploy.
Created by SAFE-CAP / https://safe-cap.com / Alexander Schiemann