Skip to content

EA GUI — Server Setup

How to enable the optional EA GUI overlay on a DCS server. This is for server admins and mission makers. EA pilots only need the client install; players on the F10 menu need none of this — the overlay is purely additive.

TL;DR — most servers need three things

  1. Put aegis-ea-hook.lua in the server's Scripts/Hooks/.
  2. Desanitize require + package in MissionScripting.lua, and make sure LuaSocket/ exists.
  3. Load an AEGIS v0.8.1+ mission. Confirm EA socket: listening on UDP 19410 in the log.

Auto-connect then works with zero address config on a public-IP server (rented/VPS) or on a LAN. The only exception is hosting at home for players over the internet — that needs one extra line (below).


Auto-connect — do you configure anything?

Players never type an address; the server tells them. Whether you configure anything depends only on where the server lives:

Your server Address config Port forward
Rented / cloud (public IP) none none
LAN only none none
Home, players over the internet one line (serverHost) UDP 19410

This is exactly how DCS-SRS works: a normal SRS server sets SERVER_SRS_HOST once; our serverHost is the same field. (SRS's "auto" mode skips even that, but only because SRS has a separate external client app that recovers the IP — AEGIS-EA is an in-game hook with no external app, so it can't, and there's no in-game way to read the server IP you connected to.)


Prerequisites

  • AEGIS IADS v0.8.1+ loaded in the mission (current: v0.8.4). The socket listener is built in.
  • require and package available in MissionScripting.lua (so the script can require('socket')).
  • LuaSocket present in the server's DCS install.
  • aegis-ea-hook.lua in the server's Scripts/Hooks/ (drives the auto-connect chat).

Setup (every server)

Saved Games paths are relative to the server's profile — e.g. Saved Games/DCS.release_server/, not a client's Saved Games/DCS/. Using the wrong profile folder is the #1 setup mistake.

1. Install the hook

Saved Games/DCS.release_server/Scripts/Hooks/aegis-ea-hook.lua

Same file clients use. It auto-detects its role: on the server (DCS.isServer() and DCS.isMultiplayer()) it only runs the auto-connect logic — no panel. On player connect / slot change it sends a chat AEGIS-EA:<host>:<port> to that player; the client hook reads it (only from host player id 1) and connects. Same pattern as DCS-SRS.

2. Desanitize MissionScripting.lua + check LuaSocket

In <DCS Server Install>/Scripts/MissionScripting.lua, comment out:

--sanitizeModule('require')
--sanitizeModule('package')

The DCS dedicated server edition may not ship LuaSocket. The mission script prepends LuaSocket/?.lua + bin/?.dll and require('socket'); if the folder is missing the log shows require('socket') not available. Copy it from any DCS client install:

<DCS Client Install>/LuaSocket/    ->    <DCS Server Install>/LuaSocket/

Desanitizing require is a security decision

It gives every mission script on the server access to require(), not just AEGIS — any .miz you host can load arbitrary Lua. Same trade-off DCS-gRPC, SRS, LotATC, and Tacview require; if you run any of those it's already done. Note that DCS patches can revert this file — re-check after every update.

3. Load the mission

Load aegis-iads.lua (v0.8.1+) via triggers as usual — the socket starts inside AEGIS:Activate(). On a public-IP server or LAN, you're done — players auto-connect with nothing else to set.


Hosting at home for internet players

The one case that needs more. Behind a home router, gethostname() resolves to the server's private LAN address, so the auto-connect chat would advertise something remote clients can't reach. Two one-time fixes:

a. Tell the server its public address. Create Config/aegis-ea-config.lua in the server's profile:

return {
    serverHost = "myserver.example.org",  -- public IP, or a DDNS hostname if your IP is dynamic
    serverPort = 19410,                   -- default
}

Set it once on the server — it goes into the chat to every player, so clients still configure nothing. Use a DDNS hostname and you never touch it again. (LAN clients of the same home server don't need this; they can reach the LAN address fine.)

a-alt. …or let the server find its own public IP. Dynamic IP and a router that can't do DDNS? Set autoPublicIP instead of serverHost — the server hook fetches its public IP over HTTP once at mission start and advertises that in the chat:

return {
    serverHost   = nil,    -- leave nil; a set serverHost overrides autoPublicIP
    serverPort   = 19410,
    autoPublicIP = true,
}

Needs socket.http in the hook env (ships with DCS — verify with test/aegis-http-probe.lua) and the hook installed on the server. The fetch is one-shot at load (the blocking HTTP call is kept off the live sim thread by design), so a mid-session IP change needs a server restart. Full details: EA GUI → Dynamic-IP servers.

b. Forward the port. Forward UDP 19410 on your router to the server's LAN IP and allow it in the firewall — same as you already forward your DCS ports:

netsh advfirewall firewall add rule name="AEGIS-EA" dir=in action=allow protocol=UDP localport=19410

(The client always sends first, so the server's reply rides the client's NAT mapping back — you only need this inbound forward so the client's first packet reaches the server.)


Server-side mission config

In your setup script (where you call AEGIS:New()):

Field Default Description
eaEnabled true Master EA toggle. false disables jamming entirely.
eaDebugLabels false true shows full group names on emitter rows instead of NATO designations.

The UDP port (19410) is fixed in the script; change it only by editing the constant (and the client serverPort to match).


How discovery actually works

So there's no confusion about magic that isn't there — the client finds the server in exactly this order, and nothing reads dcs.log:

  1. Singleplayer → 127.0.0.1
  2. Auto-connect chat from the server (the normal MP path)
  3. Explicit serverHost in the client's own config (manual override)
  4. Manual entry in the panel's setup field

The mission-side socket is purely reactive: it binds *:19410 and replies to whatever address a REQ/CMD packet came from. It never advertises an address — that's the hook's chat job.


Verification

Work top-down — confirm the socket opened before chasing client issues.

Check Where Expected
Socket opened server dcs.log [AEGIS] EA socket: listening on UDP 19410
Socket not opened server dcs.log EA socket: require('socket') not available → fix step 2
Client connected client dcs.log AEGIS-EA: Auto-connect from chat: <ip>:19410
Panel renders client EA panel appears within ~2s of spawning into an EA- slot
Round-trip works client clicking WIDE updates the panel and the F10 menu shows the active mode

Troubleshooting

Symptom Cause Fix
require('socket') not available (server log) require/package still sanitized, or LuaSocket/ missing Step 2
Socket line never appears Mission isn't AEGIS v0.8.1+, or the script errored earlier Check the log for earlier [AEGIS] errors
Auto-connect never fires Hook not in the server's Scripts/Hooks/, or wrong Saved Games profile Put it in DCS.release_server/Scripts/Hooks/; verify the profile
Remote clients fail, LAN works Home server advertising its private LAN IP Set serverHost + forward UDP 19410 (above)
One client fails, others fine That client's firewall, or chat from host suppressed for them Have that client set serverHost in their own config as a fallback

Singleplayer / listen server

In SP your machine is both ends — the hook connects to 127.0.0.1:19410 with no config. You still need require/package desanitized and LuaSocket present (the mission script opens the same socket). See the SP slot-order note on the EA GUI page.

Architecture (why a UDP socket at all)

On a dedicated server the AEGIS data lives in the mission Lua VM, and the hook can't reach it (net.dostring_in("mission", …) hits a separate VM where AEGIS is nil). So the mission script opens a UDP socket inside its own VM and the client talks to it over the network — which is why the identical path works in SP, on a listen server, and on a dedicated server. The same socket also answers the companion visualizer's DUMP request.

See also