Surge Script Automatically Registers Service to Consul

Introduction⌗
I often deploy and test distributed services on an idle local server, but network issues add significant learning costs. To solve this, I’ve directed all VM or Docker proxies on my local server to my macOS host, which helps avoid many service deployment failures caused by network issues!
However, a problem arises when my macOS connects to the internet through a shared office Wi-Fi with a DHCP-assigned IP address. Setting it manually could cause conflicts, so I wanted to use Consul’s service registration to dynamically register Surge’s HTTP Proxy service.
Surge Script⌗
Add the following settings to your Surge configuration file:
[Script]
consul = type=event,event-name=network-changed,debug=1,script-path=network-changed.js
After saving the configuration file and reloading Surge, you can see the following settings in the UI:
Surge can modify requests or listen to events through Scripts, then send requests. Surge supports the following script trigger modes:
- HTTP Request
- HTTP Response
- Rule
- Event
- DNS
- Cron
- Generic
I’m using the Event mode here. Surge exposes two types of events:
- network-changed
- notification
When the network changes, the network-changed
event is triggered, which then calls my defined Script.
$httpClient.put({
url: "http://consul.service.betterde.consul:8500/v1/agent/service/register",
body: {
"id": "surge-http",
"name": "surge",
"port": 6152,
"address": $network.v4.primaryAddress,
"check": {
"Name": "Surge HTTP proxy service check",
"TCP": $network.v4.primaryAddress + ":6152",
"Interval": "60s"
}
}
}, function(error, response, data) {
if (error) {
$done(error);
} else {
$done({response});
}
});
In the script, Surge exposes some global variables. To get the internal IP, you can use $network.v4.primaryAddress
, and then use Surge’s built-in $httpClient
to register the service with Consul.
Server Configuration⌗
sudo mkdir -p /etc/systemd/resolved.conf.d
sudo vim /etc/systemd/resolved.conf.d/consul.conf
Write the following configuration to the /etc/systemd/resolved.conf.d/consul.conf
configuration file:
[Resolve]
DNS=127.0.0.1:8600
DNSSEC=false
Domains=~consul
Note: Since my Consul is installed on a virtual machine, the address here is the local Loopback IP.
Then restart the DNS resolution service:
sudo systemctl restart systemd-resolved
Verifying Results⌗
dig surge.service.betterde.consul
; <<>> DiG 9.18.1-1ubuntu1.3-Ubuntu <<>> surge.service.betterde.consul
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 18152
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;surge.service.betterde.consul. IN A
;; ANSWER SECTION:
surge.service.betterde.consul. 0 IN A 10.192.6.137
;; Query time: 0 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Thu Apr 13 13:40:02 CST 2023
;; MSG SIZE rcvd: 74
As you can see, the resolved IP is indeed my current macOS IP. This way, I can use surge.service.betterde.consul
as the proxy server address in Docker or environment variables, instead of the dynamic IP of macOS.
I hope this is helpful, Happy hacking…