IB Gateway Docker Setup After IBC: Headless, 2FA and Restarts
You can still run IB Gateway in Docker after IBC was retired on September 1, 2026 and its repository archived, but not fully unattended within IBKR's documented rules. IBKR does not support a headless session without a GUI and requires a manual login with a second factor once a week. The workable pattern as of November 2026 is a pinned container with a virtual display and VNC, Gateway's built-in Auto restart, an attended weekly login over an SSH tunnel, and a bot that reconnects, reconciles and reports to an alert-only watchdog. Tools that also automate the second factor exist, but they are young and keep both login factors on the server.
What happened to IBC, and does it still work?
IBC, the successor of IBController, filled in the login dialog of TWS and IB Gateway, handled pop-ups and retried missed IBKR Mobile 2FA alerts. Many Docker images, including gnzsnz/ib-gateway-docker, use it for logins without a person at the screen.
On March 24, 2026, the maintainer announced in GitHub Discussion 347 that he would support IBC until September 1, 2026 and then stop, citing personal reasons and noting that the auto-restart built into Gateway and TWS has reduced the need for IBC. The repository is archived and read-only; releases can still be downloaded and the code forked. The newest release, 3.24.2 from August 21, 2026, supports TWS and Gateway 10.48 and later and needs a Java 25 runtime on ARM hardware.
Existing setups do not stop on a fixed date. The gnzsnz images still ship new Gateway builds (stable 10.50.1f, latest 10.51.1e in early November 2026) with IBC 3.24.2. The risk is gradual: any Gateway update can change a dialog IBC reacts to, and apart from fixes for significant bugs and a planned final release, IBC is no longer developed. To have the container, reconnect logic and alerting set up for you, see trading bot development for Interactive Brokers.
IB Gateway auto restart and the weekly login: what IBKR supports
According to IBKR, TWS and IB Gateway were designed to be restarted daily, for example to reload contract definitions. Beginning with version 974, both can restart without user intervention, so a session can potentially run from Sunday to Sunday without re-authenticating. Under Global Configuration, Lock and Exit, IBKR recommends “Never lock Trader Workstation” and “Auto restart” for API users; IB Gateway does not lock due to inactivity.
The weekly login stays manual, and IBKR's pages disagree on its timing: one names the nightly server reset on Saturday night, another a weekly cycle that starts every Monday, and IBC's user guide places it at the first start after 01:00 ET on Sunday. Schedule the login before your bot's first trading window of the week and record when your Gateway actually asks. If the log shows Soft token=0 received instead of expected permanent, IBKR says the weekly login is due.
According to IBC's user guide, the auto-restart only preserves the session when it happens at the configured time; after a crash, a manual exit or a power failure, the next start needs a full login. By the same logic, so does a start after docker compose down, an image update or a host reboot. Plan updates for the weekly login window.
| Task | Typical with IBC | Without IBC (as of November 2026) |
|---|---|---|
| Daily restart | IBC setting or Gateway option | Gateway's own Auto restart |
| Weekly login with 2FA | Credentials filled in, alert repeated | Attended, over VNC |
| Start after crash or container restart | IBC re-enters credentials; IB Key still needs your approval | Full login with second factor |
Can IB Gateway run headless in Docker?
Not in the sense IBKR uses the word. IBKR writes that users must enter username and password in a login window and that a headless TWS or Gateway session without a GUI is not supported for security reasons. Docker images replace the screen with a virtual framebuffer (Xvfb) and a VNC server and let IBC or a successor type the credentials. That runs without a monitor, but the unattended login is outside IBKR's documented model.
A container still pins the version and makes the setup reproducible. In a container, Gateway beats TWS: IBKR says it consumes about 40% fewer resources.
Guard the API port. The gnzsnz README points out that the TWS API is an unencrypted, unauthenticated TCP socket: anyone who reaches the port can use your account through the Gateway. Bind published ports to 127.0.0.1 and never expose 4001, 4002 or 5900 to the internet. Do not count on ufw as a backstop: Docker's documentation says traffic to published container ports is diverted before ufw's rules apply.
The Web API is no shortcut around the login for individual accounts either; see IBKR Web API vs TWS API.
IB Gateway Docker Compose example with secrets and a healthcheck
This typical example uses the gnzsnz image and is a starting point, not a production file: paper account, read-only API, a pinned Gateway version, Docker secrets, settings in a volume and ports on localhost only. The image still logs in through IBC 3.24.2, so test it before every Gateway update.
# Typical example: paper account first, ports on localhost only
services:
ib-gateway:
image: ghcr.io/gnzsnz/ib-gateway:10.50.1f # exact version, not :latest
restart: unless-stopped
environment:
TWS_USERID: ${TWS_USERID:?Variable not set} # from .env
TWS_PASSWORD_FILE: /run/secrets/tws_password
TRADING_MODE: paper
READ_ONLY_API: "yes" # switch to "no" only after testing
VNC_SERVER_PASSWORD_FILE: /run/secrets/vnc_password
AUTO_RESTART_TIME: "11:45 PM" # a time when your bot is idle
TWOFA_TIMEOUT_ACTION: restart
TIME_ZONE: Etc/UTC
TWS_SETTINGS_PATH: /home/ibgateway/tws_settings
volumes:
- ./tws_settings:/home/ibgateway/tws_settings
secrets:
- tws_password
- vnc_password
ports:
- "127.0.0.1:4002:4004" # TWS API, paper (socat relay)
- "127.0.0.1:5900:5900" # VNC, for the weekly login only
healthcheck: # Gateway's own paper port, not the relay
test: ["CMD", "bash", "-c", "exec 3<>/dev/tcp/127.0.0.1/4002"]
interval: 60s
timeout: 5s
retries: 3
start_period: 5m
secrets:
tws_password:
file: ./secrets/tws_password.txt
vnc_password:
file: ./secrets/vnc_password.txt.env holds the line TWS_USERID=..., secrets/ the two password files; keep both out of version control. Docker's documentation gives the reason for secrets: environment variables are often available to all processes, while a secret is mounted as a file under /run/secrets/. Test condition: on November 3, 2026, the file was parsed with PyYAML and checked against the Compose Specification schema; the healthcheck command ran in bash against a local dummy listener and an unused port. It was not started with Docker or against an IBKR account.
| Port | Where | Role |
|---|---|---|
| 4001 / 4002 | Container; accepts only 127.0.0.1 by default | Gateway's own API port, live / paper |
| 4003 / 4004 | Container, all interfaces | socat relay to 4001 / 4002; other containers use the service name and this port |
| 127.0.0.1:4002 | Docker host | Published paper relay for a bot on the host |
| 5900 | Container and host (127.0.0.1) | VNC, only if a VNC password is set |
The healthcheck targets Gateway's own port 4002 inside the container, not the relay; for a live account, change it to 4001. The image's scripts start socat before Gateway, and socat accepts a connection before it connects onward, so the relay port can accept connections while Gateway is down. Never pair the healthcheck with a tool that restarts unhealthy containers: each restart outside the auto-restart time forces a full login.
With IB Key, the login still waits for you: IBC enters the credentials and you approve the notification in IBKR Mobile. For the weekly login, open a tunnel with ssh -N -L 5900:127.0.0.1:5900 user@your-server and point a VNC client at localhost:5900.
Give the bot its own username. According to IBKR, a Gateway session cannot reconnect automatically after the next disconnection, such as the server reset, if its username also logs in to Client Portal during that session.
Which 2FA methods work with IB Gateway?
Two-factor authentication is required for all IBKR users. Because the API does not support account management, IBKR's TWS API documentation lists only some methods for API logins and asks you to enable one beforehand:
- Supported: IB Key, Handy Key (smartphone applications), SMS text messages and Digital Security Card+ (DSC+).
- Not supported: Security Code Card, Temporary Security Code Card and Online Code Card.
IBKR's Secure Login System page also lists passkeys and Mobile Authenticator apps and calls SMS a temporary method. The TWS API page mentions neither passkeys nor authenticator apps, so confirm with IBKR before you build a Gateway setup around them. According to the ibg-controller README, some regions, among them Hong Kong and Japan, had been moved to passkeys by August 2026, and a passkey prompt inside a container needs an authenticator running alongside it.
How does your bot survive IB Gateway restarts and disconnects?
IBKR says you are very likely to lose connectivity to its servers at least once a day because of server maintenance; Gateway then reconnects by itself. The daily auto-restart also drops the socket between bot and Gateway. Three system messages matter most:
- 1100: connectivity between IBKR and Gateway lost.
- 1101: restored, market data requests lost and to be re-submitted.
- 1102: restored, market data requests maintained.
During a reset, native orders keep working, but execution reports and simulated orders are delayed, and IBKR does not recommend operating during scheduled reset times. A robust bot needs a reconnect loop with a fixed, unique client ID, a heartbeat such as a cheap server-time request, and a reconciliation after every connect that compares positions, open orders and executions with its own state and blocks new orders on any mismatch. Typical example with ib_async, where alert() and the other helpers stand for your own logic:
import asyncio
from ib_async import IB
HOST, PORT = "127.0.0.1", 4002 # paper port as published in the compose file
CLIENT_ID = 7 # fixed and unique per process
ib = IB()
trading_blocked = True # stays blocked until reconciliation passes
def on_error(req_id, code, msg, contract):
if code in (1100, 1101, 1102):
alert(f"IBKR connectivity {code}: {msg}")
if code == 1101: # restored, market data lost
resubscribe_market_data()
ib.errorEvent += on_error
async def reconcile():
global trading_blocked
positions = await ib.reqPositionsAsync()
open_trades = await ib.reqAllOpenOrdersAsync()
fills = await ib.reqExecutionsAsync()
trading_blocked = differs_from_local_state(positions, open_trades, fills)
if trading_blocked:
alert("Broker state differs from local state, trading blocked")
async def run():
global trading_blocked
while True:
if not ib.isConnected():
trading_blocked = True # no new orders until reconciled
try:
await ib.connectAsync(HOST, PORT, clientId=CLIENT_ID, timeout=15)
await reconcile()
except Exception as exc:
alert(f"Connect or reconciliation failed: {exc}")
ib.disconnect() # next loop retries both steps
await asyncio.sleep(60)
continue
try:
await asyncio.wait_for(ib.reqCurrentTimeAsync(), 10)
report_heartbeat() # e.g. write time.time() to the watchdog's file
except Exception:
ib.disconnect()
await asyncio.sleep(30)
asyncio.run(run())The heartbeat covers only the path between bot and Gateway; whether Gateway is connected to IBKR comes from codes 1100 to 1102. The Watchdog class in ib_async requires an IBC controller instance in its source code, so it cannot be used without IBC. Migration details are in ib_async vs ib_insync.
IB Gateway watchdog: a tested Python check of the API port and heartbeat
The watchdog belongs outside the bot, because a hung process cannot report its own failure. This typical example uses only Python's standard library. Every 60 seconds it checks whether the published API port holds a connection and whether the bot's heartbeat file is fresh. A connection that the far end closes at once counts as down; the socat relay does exactly that when Gateway is not listening.
#!/usr/bin/env python3
"""Alert-only watchdog for a bot behind IB Gateway. Standard library only.
It never restarts the container: a restart outside the auto-restart time
forces a full login with a second factor."""
import socket
import sys
import time
from pathlib import Path
HOST, PORT = "127.0.0.1", 4002 # published paper port from the compose file
HEARTBEAT = Path("/var/lib/bot/heartbeat") # the bot writes time.time() here
MAX_AGE = 120 # seconds without a bot heartbeat
FAILS_BEFORE_ALERT = 3 # checks in a row, covers short restarts
def port_state(host, port, hold=1.0):
"""'open', 'closed' (accepted, then dropped at once) or 'unreachable'."""
try:
with socket.create_connection((host, port), timeout=3) as s:
s.settimeout(hold)
try:
return "closed" if s.recv(1) == b"" else "open"
except socket.timeout:
return "open" # connection held open: something listens
except OSError:
return "closed" # reset by the far end
except OSError:
return "unreachable" # refused or timed out
def heartbeat_age(path):
try:
return time.time() - float(path.read_text())
except (OSError, ValueError):
return float("inf")
def problems(host=HOST, port=PORT, heartbeat=HEARTBEAT):
found = []
state = port_state(host, port)
if state != "open":
found.append(f"API port {port}: {state}")
age = heartbeat_age(heartbeat)
if age > MAX_AGE:
found.append(f"no bot heartbeat for {age:.0f} s")
return found
def alert(text): # replace with email, Telegram, a paging service ...
print(time.strftime("%Y-%m-%d %H:%M:%S"), "ALERT:", text, file=sys.stderr, flush=True)
def main():
fails = 0
while True:
found = problems()
if found:
fails += 1
if fails == FAILS_BEFORE_ALERT:
alert("; ".join(found))
else:
if fails >= FAILS_BEFORE_ALERT:
alert("recovered")
fails = 0
time.sleep(60)
if __name__ == "__main__":
main()Test condition: run on November 3, 2026 with Python 3.9 and 3.12 against local dummy servers on 127.0.0.1. A listener that holds the connection gave open; one that closes at once, one that resets and a relay with its backend down gave closed; an unused port gave unreachable. Heartbeat files and the alert-once logic were tested too; a real Gateway was not. Like the healthcheck, each check connects without the API handshake, so watch Gateway's log on paper first and set FAILS_BEFORE_ALERT to cover your daily restart.
Run it as a systemd service on the host or in its own container; in a container, set HOST to the service name, PORT to 4004 and share the heartbeat file through a volume. For a failure of the whole server, add an outside service that alerts when a regular ping from it stops.
IBC successors and fully unattended logins: what to weigh
ibg-controller, public on GitHub since April 2026, combines a Python controller with a small Java agent inside Gateway's JVM; its newest release as of November 3, 2026 is 0.16.3 from October 27. It builds on the gnzsnz image and can complete the weekly login without a phone, using the TOTP secret from IBKR's Mobile Authenticator enrollment. A Java fork of IBC was also announced in Discussion 347.
Before using any of them on a live account, weigh four points:
- Maturity: months of history, against 23 years for IBC and its predecessor.
- Security: with password and TOTP secret on one server, the second factor no longer protects you if that server is taken over.
- Trust: the tool runs inside the Gateway process and receives your credentials.
- Official scope: IBKR documents a login in a window and no headless session; whether automated logins are acceptable for your account is a question for IBKR.
For a live account, the more conservative combination is Gateway's own auto-restart, an attended weekly login and solid reconnect logic. Without a person, such a system runs a week at most. If the weekly login is missed, the bot stops trading while open positions stay in the market, so protective orders resting at the broker, such as stop orders, are part of risk control, alongside the usual risks of automated trading: code errors, leverage and, in the worst case, total loss.
Checklist: IB Gateway in Docker without IBC (as of November 2026)
| When | Task |
|---|---|
| Once | Auto restart at an idle time; a supported 2FA method; a separate bot username if you use Client Portal. |
| Once | Pinned image, Docker secrets, API and VNC on 127.0.0.1, VNC only through an SSH tunnel. |
| Once | Reconnect, heartbeat, codes 1100 to 1102, reconciliation, healthcheck, alert-only watchdog. |
| Paper phase | Read-only API; test the daily auto-restart and a deliberately stopped container. |
| Weekly | Log in before the first trading window and check that reconciliation found no differences; plan for weeks when nobody can log in. |
| On updates | Read the release notes, test on paper, switch inside the weekly login window. |
Still on IBC? Confirm Gateway's own auto-restart is active and replace IBC-dependent pieces such as the ib_async Watchdog. Before going live, work through the pre-live checklist for trading bots.
Frequently asked questions
Can IB Gateway run headless in Docker?
It can run without a monitor, using a virtual display such as Xvfb and a VNC server inside the container. IBKR, however, states that a headless TWS or Gateway session without a GUI is not supported for security reasons and that users enter their credentials in a login window. Fully unattended logins rely on third-party tools that drive the login dialog and remain outside IBKR's documented model.
Does IBC still work after it was archived?
Existing installations keep running as long as IBKR does not change something IBC depends on. IBC was retired on September 1, 2026, and its repository is archived and read-only. The newest release as of November 2026 is 3.24.2 from August 21, 2026, which supports TWS and Gateway 10.48 and later. Apart from fixes for significant bugs and a planned final release, IBC is no longer developed, so test every Gateway update on a paper account first.
How often do I have to log in to IB Gateway with 2FA?
With Auto restart enabled, once a week. Gateway restarts daily without a new login, but IBKR requires a manual login with a second factor every week. IBKR's pages differ on the timing: one mentions the server reset on Saturday night, another a cycle that starts on Monday. Any restart outside the configured auto-restart time, such as a crash or a container restart, also requires a full login.
Can IB Gateway run without 2FA, and which methods work?
No. IBKR requires two-factor authentication for all users. Its TWS API documentation lists IB Key, Handy Key (smartphone applications), SMS and Digital Security Card+ as supported for API logins; Security Code Card, Temporary Security Code Card and Online Code Card are not supported. Passkeys and Mobile Authenticator apps appear on IBKR's Secure Login System page but not on the API page, so check with IBKR before relying on them for Gateway logins.
Which ports does the IB Gateway Docker image use?
In gnzsnz/ib-gateway-docker, Gateway uses 4001 for live and 4002 for paper and by default accepts connections only from the container's 127.0.0.1. socat relays these to 4003 and 4004 on all container interfaces, and the sample Compose file publishes them on the host as 127.0.0.1:4001 and 127.0.0.1:4002. VNC uses 5900 and starts only if a VNC password is set. Other containers on the same Docker network connect to the service name on 4003 or 4004.
Should a watchdog restart the IB Gateway container automatically?
Usually not. According to IBC's user guide, Gateway's auto-restart reuses the current session but does not operate when Gateway shuts down at any other time, for example after a crash or a power failure; the next start then needs a full login with a second factor. A watchdog that restarts the container on a failed check can therefore turn a short outage into a stopped bot until someone logs in. Let it alert instead, and decide by hand whether a restart is worth the new login.
Is the IBKR Web API a way around the Gateway login?
Not for most private traders. For individual accounts, IBKR lists the Client Portal Gateway as the Web API authentication method, while the fully programmatic OAuth methods are listed for advisors, brokers, funds, proprietary trading groups and third-party developers. Whether the Web API suits your bot better depends on the features you need, not on avoiding the login.
What should my bot do after IB Gateway restarts?
Reconnect with a fixed, unique client ID, re-request market data after code 1101, and compare positions, open orders and executions with its own state before sending anything new. On any mismatch it should block new orders and raise an alert. An external watchdog should alert when the bot stops reporting a heartbeat, because a hung process cannot report its own failure.
Sources and status
- IBC: Project Retirement (README) — IbcAlpha / GitHub (retrieved November 3, 2026)
- The future of IBC (Discussion 347) — IbcAlpha / GitHub (retrieved November 3, 2026)
- IBC release 3.24.2 — IbcAlpha / GitHub (retrieved November 3, 2026)
- IBC User Guide (auto-restart and weekly authentication) — IbcAlpha / GitHub (retrieved November 3, 2026)
- Download TWS or IB Gateway (What is the IB Gateway?) — Interactive Brokers, TWS API documentation (retrieved November 3, 2026)
- Daily & Weekly Reauthentication — Interactive Brokers, TWS API documentation (retrieved November 3, 2026)
- Supported Two Factor Authentication (2FA) — Interactive Brokers, TWS API documentation (retrieved November 3, 2026)
- Error Codes (section System Message Codes) — Interactive Brokers, TWS API documentation (retrieved November 3, 2026)
- Logging into multiple applications — Interactive Brokers, TWS API documentation (retrieved November 3, 2026)
- Secure Login System — Interactive Brokers (retrieved November 3, 2026)
- Web API Authentication: Introduction — Interactive Brokers, Web API documentation (retrieved November 3, 2026)
- ib-gateway-docker (README: tags, ports, security, credentials) — gnzsnz / GitHub (retrieved November 3, 2026)
- ib-gateway-docker, stable image: Dockerfile and scripts (common.sh, run.sh, run_socat.sh) — gnzsnz / GitHub (retrieved November 3, 2026)
- socat(1) manual page (life cycle, TCP-LISTEN) — Debian manpages (socat documentation) (retrieved November 3, 2026)
- ibg-controller: Unattended IB Gateway in Docker (README, releases) — code-hustler-ft3d / GitHub (retrieved November 3, 2026)
- ib_async ibcontroller.py (IBC and Watchdog classes) — ib-api-reloaded / GitHub (retrieved November 3, 2026)
- Manage secrets securely in Docker Compose — Docker Docs (retrieved November 3, 2026)
- Packet filtering and firewalls (Docker and ufw) — Docker Docs (retrieved November 3, 2026)
As of November 2026. Third-party rules, prices and APIs may have changed since; the providers' current documentation and the official texts are authoritative.
This article is also available in German: IB Gateway im Dauerbetrieb: was nach dem Ende von IBC gilt.
Need your IB Gateway setup and bot built or reviewed? Get in touch — covering the server, Docker setup, reconnect logic, alerting and a weekly login routine. More: Trading bot development for Interactive Brokers and MetaTrader 5.