Real addresses, not tricks
Every service gets a genuine IP on a real network interface — one your router and the rest of your network can see. It isn't hidden away inside a container or a namespace.
Splitter lets one Linux server host many services — each with its own real IP address — and manage them all from a browser. Point a domain at your backends and Splitter creates the network interface, balances the traffic, sets up TLS, and firewalls it for you. No config files. No SSH. You watch every command it runs.
$ splitter apply site4.example.com → resolving bind target ip link add link eth0.50 name mv-web-0 type macvlan ip addr add 192.168.50.20/24 dev mv-web-0 ✓ sub-interface up — 52:54:00:fa:bb:04 → writing /etc/nginx/stream.d/site4.conf upstream pool → 192.168.50.10:443, .11:443 least_conn · tls · acl: office → nginx -t ✓ configuration file test is successful ✓ reloaded — listening on 192.168.50.20:443
Normally, exposing several sites or services from a single server means hand-editing nginx, juggling IP addresses and VLANs over SSH, and praying a typo doesn't take everything offline. Splitter does all of that for you — from one dashboard — and shows you exactly what it changed.
Every service gets a genuine IP on a real network interface — one your router and the rest of your network can see. It isn't hidden away inside a container or a namespace.
Add a domain, choose its backends, and Splitter writes the config, brings the interface up and reloads the proxy — safely, in seconds. No editing files, no restarting anything by hand.
Every risky step has a guard rail: the config is tested before each reload, the firewall can't lock you out, and a single click rolls everything back to a known-good state.
Splitter runs directly on the host — no network namespaces, no overlay. The
interfaces and IPs it creates are real, routable and visible in ip link show.
Bind straight to an interface's existing IP, or give the mapping its own dedicated
address on a real macvlan device — unique MAC, optional VLAN tag, static IP.
# its own MAC, inside VLAN 50 ip link add link eth0.50 name mv-web-0 \ address 52:54:00:fa:bb:04 type macvlan
An upstream {} pool is rendered for your backends with the load-balancing
method you picked, plus TLS, access lists and L4 rate limits.
upstream pool_924cb { server 192.168.50.10:443; server 192.168.50.11:443; least_conn; }
nginx -t runs before every reload, so a bad block is rolled back and the live
proxy is never reloaded against a broken config. Each step is streamed back to the UI.
nginx -t # config OK nginx -s reload ✓ 192.168.50.20:443 → pool_924cb
Each domain binds its own address, flows through the proxy host, and fans out to its backend pool. Downed backends light up red the moment a health probe fails.
Built with Python + Flask and a single-page dashboard. Mappings, users and settings persist to plain JSON — there is nothing else to run.
Dedicated IP per mapping with its own MAC — optionally inside an 802.1Q VLAN. Not a
namespace trick: the device shows up in ip link and answers ARP.
Round-robin, least_conn, hash (+consistent), random, or random-two —
with weights, health probes and active-passive priority failover.
Security-group style iptables rules — every interface gets its own ordered rule set and default policy. Off by default, with lockout protection and a one-click panic switch.
Upload a cert, generate a SAN self-signed pair with openssl, or reuse a managed
cert across mappings. Keys land at 0600, shared certs are refcounted.
Named IP/CIDR allow lists rendered to nginx snippets. Auto-refreshing from a source URL — the built-in tas-ix feed replaces a cron job entirely.
Install the OWASP Core Rule Set from the dashboard, bind it to any HTTPS mapping, and switch Off → Detection → Enforce once you've tuned the false positives.
Host CPU/RAM/disk, per-interface throughput, backend health probes, and an n8n-style canvas of every route — with downed backends flagged in red.
One-click backup of everything — mappings, users, certs, sub-interfaces, audit log — on a schedule, in-process. Restore or roll back to any point.
Admin and creator roles behind a login, PBKDF2-hashed passwords, and a persistent audit trail of every privileged action taken in the UI.
Splitter runs privileged commands on a production host. Every destructive path has a guard rail, and every one of them is on by default.
nginx -t gates every reload, so the live
proxy never restarts against a broken config.# established + the dashboard, always first iptables -A SFW-IN-eth0 -m conntrack \ --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A SFW-IN-eth0 -p tcp --dport 8088 -j ACCEPT # your rules, by priority iptables -A SFW-IN-eth0 -p tcp --dport 22 \ -s 203.0.113.0/24 -j ACCEPT iptables -A SFW-IN-eth0 -p tcp --dport 443 -j ACCEPT # fallback = interface default policy iptables -A SFW-IN-eth0 -j DROP iptables -I INPUT 1 -i eth0 -j SFW-IN-eth0
Ships as a single self-contained image — nginx + the stream module, the WAF and the app. It runs in the host network namespace, so the IPs it creates are real, and auto-detects your uplink NIC.
$ git clone <repo> splitter && cd splitter $ docker compose up -d --build
Then open http://<server-ip>:8088 and create your
admin account. Runs on any Linux host with Docker — named volumes keep your data, and
docker compose up -d --build is safe to re-run.
Self-hosted and ready to deploy in minutes.