Batfish 2026.08.27.3685 on AWS User Guide
Overview
This guide covers launching and using Batfish 2026.08.27.3685 on Ubuntu 24.04 from cloudimg on Amazon EC2. It is one version of the cloudimg Hardened FRRouting, OpenBGPD & BGP Routing and Peering AMIs listing on AWS Marketplace; you pick it as the software version when you subscribe and launch. The other routing and peering products in the listing are described on the listing's guide hub.
Batfish is an open source (Apache-2.0) network configuration analysis tool. You give it the configuration files of your routers, switches and firewalls (Cisco IOS, IOS-XR and NX-OS, Juniper Junos, Arista EOS, Palo Alto, Fortinet, Check Point, Cumulus, SONiC, AWS VPC data and more), and it builds a model of the whole network without touching a single device. You then ask it questions through its Python client, pybatfish: which BGP sessions come up, where a packet from host A to host B goes and why, which ACL line blocks it, which references are undefined, and what a change would do before you deploy it. Network teams use it to validate changes in CI, to audit configurations and to answer reachability questions without a lab.
What the cloudimg image adds:
- HTTPS only, on 9996. nginx serves TLS 1.3 and TLS 1.2 (ECDHE with AEAD ciphers only) on port 9996, the port pybatfish uses, and passes requests to Batfish, which listens on
127.0.0.1:19996only. Port 80 is closed, and TLS 1.1 and 1.0 are refused (Step 9). - A certificate made on your instance. At first boot the instance gets a TLS key and an end-entity certificate for its own names and addresses. It can only vouch for this server and can never sign other certificates. You point pybatfish at it (Step 6), or replace it with one for your own DNS name (Step 12).
- An API key on every request, generated for your instance. Batfish's own default setup accepts any client, and pybatfish ships a published default key of 64 zeros. Here every request needs this instance's 256-bit API key (the
X-Batfish-Apikeyheader pybatfish sends, orAuthorization: Bearer) or this instance's HTTP Basic login. Everything else gets401, including/v2/version. The key is checked twice: by nginx, and by Batfish's own file authorizer, which is switched on. The published default key is refused at both layers (Step 8). - No network access for Batfish. Batfish analyses the files you upload; it never needs to connect anywhere. On this image the Batfish service can reach
127.0.0.1and::1only: no instance metadata, no VPC, no DNS and no internet (Step 10). - Services that refuse to start with a bad credential. Before each start, a preflight check refuses a missing, unreadable, malformed, empty or default key file, login file, certificate or gate map. The service is then left failed and not restarting, and nothing listens on 9996 (Step 11).
- A source build with three security dependency raises. The Batfish jar is a cloudimg build of the Batfish project's v2026.08.27 release commit (
329c14bf), unchanged, with three bundled libraries raised to the versions the Batfish project itself adopted on its main branch after that release:jackson-bom2.22.1 to 2.23.0,guava-bom33.6.0-jre to 33.7.2-jre andlz4-java1.11.2 to 1.14.0. The project's own release jar bundles the older versions, which have published security advisories. The build record, the exact dependency diff and the jar's SHA-256 digest are shipped on the image (Step 14). Batfish has no telemetry. Ubuntu 24.04 LTS is fully patched at build time.
What is on the image:
- Batfish 2026.08.27.3685: the jar
/opt/batfish/allinone-bundle.jar, run bybatfish.serviceon the Ubuntu OpenJDK 21 runtime as the locked system userbatfish; analysis storage in/var/lib/batfish - pybatfish 2026.08.27.3685, the Python client, in
/opt/batfish/pybatfish-venv - nginx from Ubuntu 24.04 as the TLS front on 9996
batfish-firstboot.service, which prepares the key, the login and the certificate on first boot, and the helpersbatfish-demo,batfish-preflightandbatfish-tls-renew- The Batfish example network (15 devices) in
/usr/share/batfish/example-snapshot, the question templates, the build record, and the licences in/usr/share/doc/batfish/and/usr/share/batfish/THIRD-PARTY-NOTICES
Default user: ubuntu · Architecture: x86_64 · Root volume: 8 GiB gp3
Prerequisites
- An AWS account and permission to launch EC2 instances
- An EC2 key pair in the Region you launch in
- A VPC subnet, and the addresses of the workstations or CI runners that will run pybatfish
- A security group that allows:
| Port | Protocol | Source | Purpose |
|---|---|---|---|
| 22 | TCP | your admin network | SSH |
| 9996 | TCP | the workstations and CI runners that run pybatfish | Batfish over HTTPS |
Nothing else needs to be open. Batfish's own port 19996 is bound to 127.0.0.1 and port 80 is not served, so opening them achieves nothing.
Recommended instance type: m5.large. Batfish runs in a Java virtual machine whose heap is sized at first boot to 55% of the instance's memory (4.2 GB on an 8 GiB instance). Larger networks, with hundreds of devices or very large firewall rule bases, need more memory: launch on r5.large or r5.xlarge and the first boot sizes the heap from that instance's memory (to change it on a running instance, see Step 13).
Connecting to your instance
| Version | Operating system | SSH user |
|---|---|---|
| Batfish 2026.08.27.3685 on Ubuntu 24.04 | Ubuntu 24.04 LTS | ubuntu |
Step 1: Launch the instance
Option A: AWS Marketplace console
- Open the cloudimg Hardened FRRouting, OpenBGPD & BGP Routing and Peering AMIs listing on AWS Marketplace and choose View purchase options, then Subscribe. One subscription covers every version in the listing.
- Once the subscription is active, choose Launch your software.
- Choose One-click launch from AWS Marketplace (or Launch from EC2 Console for the full launch wizard). In Version, choose Batfish 2026.08.27.3685 on Ubuntu 24.04, then choose your Region.
- Pick an instance type (
m5.largerecommended) and your key pair. - Security group: allow SSH (22) from your own address, and TCP 9996 from the networks that will run pybatfish.
- Choose your VPC and subnet, leave the metadata defaults (the image already requires IMDSv2), then choose Launch.
Option B: AWS CLI
Run this on your own workstation. Replace the AMI ID with the one shown for your Region on the Marketplace launch page, and the VPC, subnet, key pair and CIDRs with your own:
SG=$(aws ec2 create-security-group --group-name batfish \
--description "Batfish" --vpc-id vpc-0123456789abcdef0 \
--query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 22 --cidr <your-mgmt-cidr>
aws ec2 authorize-security-group-ingress --group-id "$SG" --protocol tcp --port 9996 --cidr <your-client-cidr>
aws ec2 run-instances \
--image-id ami-0123456789abcdef0 \
--instance-type m5.large \
--key-name my-key-pair \
--security-group-ids "$SG" \
--subnet-id subnet-0123456789abcdef0 \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=batfish}]'
You do not need --metadata-options: the AMI already makes IMDSv2 required.
Step 2: Connect and read your instance's details
Connect as ubuntu with the key pair you chose:
ssh -i ~/.ssh/my-key-pair.pem ubuntu@<public-ip>
First boot finishes within a minute of launch. It generates this instance's API key, its HTTP Basic password, the TLS certificate and the heap size, and records them in /root/batfish-credentials.txt, readable by root only. It starts nothing itself: systemd starts Batfish and nginx once it has finished, and Batfish is ready about 20 seconds later. The lines that are not secret:
sudo stat -c '%a %U %n' /root/batfish-credentials.txt
sudo grep -E '^BATFISH_(HOST|PORT|URL|USERNAME|TLS_CERT|TLS_SHA256_FINGERPRINT)=' /root/batfish-credentials.txt
600 root /root/batfish-credentials.txt
BATFISH_HOST=44.202.20.163
BATFISH_PORT=9996
BATFISH_URL=https://44.202.20.163:9996
BATFISH_USERNAME=batfish
BATFISH_TLS_CERT=/etc/batfish/tls/cert.pem
BATFISH_TLS_SHA256_FINGERPRINT=8F:86:B3:C8:15:1B:22:A6:C6:79:ED:5E:E9:FD:FD:59:DE:32:E4:2E:35:83:1B:44:2D:0A:88:84:7F:1C:FF:A6
The file also holds BATFISH_API_KEY, the key pybatfish uses, and BATFISH_PASSWORD, the password of the HTTP Basic login batfish. View them with sudo cat /root/batfish-credentials.txt. Keep them in files with mode 0600 or in your CI system's secret store, never on a command line (a command line is visible to every user on a machine through ps) or in shell history.
Step 3: Check the services and the listening set
systemctl is-active batfish-firstboot batfish nginx
sudo ss -tlnp | grep -E ':(22|80|443|9996|19996) '
sudo ss -ulnp | grep -E 'java|nginx' || echo 'no UDP socket from Batfish or nginx'
active
active
active
LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1090,fd=3),("systemd",pid=1,fd=57))
LISTEN 0 511 0.0.0.0:9996 0.0.0.0:* users:(("nginx",pid=1155,fd=5),("nginx",pid=1154,fd=5),("nginx",pid=1153,fd=5))
LISTEN 0 4096 [::ffff:127.0.0.1]:19996 *:* users:(("java",pid=1020,fd=6))
LISTEN 0 4096 [::]:22 [::]:* users:(("sshd",pid=1090,fd=4),("systemd",pid=1,fd=58))
LISTEN 0 511 [::]:9996 [::]:* users:(("nginx",pid=1155,fd=6),("nginx",pid=1154,fd=6),("nginx",pid=1153,fd=6))
no UDP socket from Batfish or nginx
batfish-firstboot prepared the credentials, batfish is the analysis service and nginx is the TLS front. Only nginx listens on the network (9996, IPv4 and IPv6). The Java process listens on 127.0.0.1:19996 only (shown in its IPv4-mapped form [::ffff:127.0.0.1]). Batfish's analysis worker runs inside the same process and opens no port of its own.
Step 4: Check the certificate
The server's certificate is self-signed, made on your instance:
sudo openssl x509 -in /etc/batfish/tls/cert.pem -noout -subject -enddate -ext subjectAltName,basicConstraints,extendedKeyUsage
subject=CN = 44.202.20.163, O = cloudimg
notAfter=Feb 12 22:59:36 2029 GMT
X509v3 Subject Alternative Name:
IP Address:44.202.20.163, DNS:ec2-44-202-20-163.compute-1.amazonaws.com, IP Address:172.31.87.25, DNS:ip-172-31-87-25.ec2.internal, IP Address:127.0.0.1, DNS:localhost
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Extended Key Usage:
TLS Web Server Authentication
It names the instance's public and private addresses and DNS names, so a client can verify it whichever address it connects to. CA:FALSE means it can never be used to sign another certificate, so trusting it in your client trusts this one server and nothing else. The SHA-256 fingerprint in the credentials file lets you check a copy of it before you trust it.
Step 5: Run the demo
The image ships the Batfish project's example network: 15 devices across three autonomous systems, with configurations for border, core, distribution and department routers, two hosts and a set of external BGP announcements. batfish-demo connects pybatfish to this instance over TLS on 9996 with the instance's API key, uploads that network and lists its devices:
sudo batfish-demo
as1border1
as1border2
as1core1
as2border1
as2border2
as2core1
as2core2
as2dept1
as2dist1
as2dist2
as3border1
as3border2
as3core1
host1
host2
BATFISH_DEMO_OK nodes=15
The first analysis of a snapshot takes about 20 seconds; later questions on the same snapshot answer in about a second.
Step 6: Connect pybatfish from your workstation
Most people run pybatfish on their own workstation or in CI and point it at the instance. Install the client version that matches the server, copy the instance's certificate, and keep the API key in a file only you can read:
python3 -m venv ~/batfish-client && . ~/batfish-client/bin/activate
pip install 'pybatfish==2026.8.27.3685'
scp -i ~/.ssh/my-key-pair.pem ubuntu@<public-ip>:/etc/batfish/tls/cert.pem ~/batfish-cert.pem
openssl x509 -in ~/batfish-cert.pem -noout -fingerprint -sha256 # compare with BATFISH_TLS_SHA256_FINGERPRINT
( umask 077; ssh -i ~/.ssh/my-key-pair.pem ubuntu@<public-ip> \
"sudo sed -n 's/^BATFISH_API_KEY=//p' /root/batfish-credentials.txt" > ~/.batfish-api-key )
Then connect with TLS on, the certificate as the trust anchor and the key from the file:
from pathlib import Path
from pybatfish.client.session import Session
bf = Session(host="<public-ip>", port=9996, ssl=True,
verify_ssl_certs=str(Path.home() / "batfish-cert.pem"),
api_key=(Path.home() / ".batfish-api-key").read_text().strip())
bf.set_network("my-network")
bf.init_snapshot("path/to/snapshot", name="baseline", overwrite=True)
print(len(bf.q.nodeProperties().answer().frame()), "devices")
From a second instance in the same VPC, connecting to this instance's private address, the same code against the example network printed:
pybatfish off-host nodeProperties rows: 15
Three settings matter. ssl=True, because the instance serves HTTPS only. verify_ssl_certs set to the certificate file, so the client checks it is talking to your instance; the system CA store does not know this certificate, so leaving it at the default fails with a certificate error. api_key, because without it pybatfish sends its published default key, which this instance refuses with 401 Client Error: Unauthorized.
Step 7: Analyse a network
A snapshot is a directory with your device configurations in a configs folder (one file per device, as the device prints it with show running-config or the equivalent), and optionally hosts, iptables and external_bgp_announcements.json:
snapshot/
configs/ router1.cfg, router2.cfg, firewall1.cfg ...
hosts/ optional: end hosts as JSON
external_bgp_announcements.json optional: routes your border routers receive
These questions run against the bundled example on the instance itself; on your workstation the same calls work on the Session from Step 6:
sudo /opt/batfish/pybatfish-venv/bin/python3 -I - <<'EOF'
import logging
logging.disable(logging.WARNING)
import pandas as pd
pd.set_option("display.width", 200)
cfg = dict(l.strip().split("=", 1) for l in open("/root/batfish-credentials.txt") if "=" in l and not l.startswith("#"))
from pybatfish.client.session import Session
from pybatfish.datamodel.flow import HeaderConstraints
bf = Session(host="127.0.0.1", port=9996, ssl=True, verify_ssl_certs=cfg["BATFISH_TLS_CERT"], api_key=cfg["BATFISH_API_KEY"])
bf.set_network("example-dc")
bf.init_snapshot("/usr/share/batfish/example-snapshot", name="baseline", overwrite=True)
print("parse issues:", len(bf.q.initIssues().answer().frame()))
s = bf.q.bgpSessionStatus().answer().frame()
print(s[["Node", "Remote_Node", "Session_Type", "Established_Status"]].head(4).to_string(index=False))
print("BGP sessions:", len(s), s["Established_Status"].value_counts().to_dict())
u = bf.q.undefinedReferences().answer().frame()
print(u[["File_Name", "Struct_Type", "Ref_Name"]].to_string(index=False))
t = bf.q.traceroute(startLocation="host1", headers=HeaderConstraints(dstIps="2.128.1.101", applications=["ssh"])).answer().frame()
tr = t.iloc[0]["Traces"][0]
print("host1 -> 2.128.1.101 ssh:", tr.disposition, "via", " -> ".join(h.node for h in tr.hops))
EOF
parse issues: 0
Node Remote_Node Session_Type Established_Status
as1border1 None EBGP_SINGLEHOP NOT_COMPATIBLE
as1border1 as1core1 IBGP ESTABLISHED
as1border1 None EBGP_SINGLEHOP NOT_COMPATIBLE
as1border1 as2border1 EBGP_SINGLEHOP ESTABLISHED
BGP sessions: 37 {'ESTABLISHED': 34, 'NOT_COMPATIBLE': 3}
File_Name Struct_Type Ref_Name
configs/as2core2.cfg route-map filter-bogons
host1 -> 2.128.1.101 ssh: ACCEPTED via host1 -> as2dept1 -> host2
Batfish found every configuration parseable, 34 BGP sessions that come up and 3 that point at peers outside the snapshot, a route map that as2core2 refers to but never defines, and the path an SSH connection from host1 takes to host2. The Batfish documentation lists every question, including filterLineReachability (ACL lines that can never match), searchFilters, reachability, differentialReachability (what a change breaks) and compareFilters.
Step 8: Authentication
Every request to 9996 needs this instance's API key or its HTTP Basic login; only /nginx-health answers without one. This block reads the key and the password into files in /dev/shm (never onto a command line) and tries each case:
sudo bash -s <<'EOF'
umask 077
D=$(mktemp -d /dev/shm/bf.XXXXXX); trap 'rm -rf "$D"' EXIT
printf 'X-Batfish-Apikey: %s\n' "$(sed -n 's/^BATFISH_API_KEY=//p' /root/batfish-credentials.txt)" > "$D/key"
printf 'X-Batfish-Apikey: %s\n' 0000000000000000000000000000000000000000000000000000000000000000 > "$D/default"
printf 'machine 127.0.0.1 login batfish password %s\n' "$(sed -n 's/^BATFISH_PASSWORD=//p' /root/batfish-credentials.txt)" > "$D/netrc"
C=/etc/batfish/tls/cert.pem; U=https://127.0.0.1:9996
echo "no credential: $(curl -s -o /dev/null -w '%{http_code}' --cacert $C $U/v2/version)"
echo "published default key: $(curl -s -o /dev/null -w '%{http_code}' --cacert $C -H @"$D/default" $U/v2/version)"
echo "instance API key: $(curl -s -o /dev/null -w '%{http_code}' --cacert $C -H @"$D/key" $U/v2/version)"
echo "HTTP Basic login: $(curl -s -o /dev/null -w '%{http_code}' --cacert $C --netrc-file "$D/netrc" $U/v2/version)"
echo "health, no credential: $(curl -s --cacert $C $U/nginx-health)"
curl -s --cacert $C -H @"$D/key" $U/v2/version; echo
EOF
no credential: 401
published default key: 401
instance API key: 200
HTTP Basic login: 200
health, no credential: ok
{"Batfish":"2026.08.27.3685","api_version":"0.0.0"}
The same matrix from a second instance in the VPC, against this instance's private address, gave 401 with no credential, the published default key, a key that differs in one character, the key of the image's build machine and a wrong Basic password, and 200 with the instance key (as X-Batfish-Apikey or Authorization: Bearer) and the Basic login.
How it works: nginx admits a request only with the instance key (in X-Batfish-Apikey, Authorization: Bearer or X-Api-Key) or the bcrypt-hashed Basic login in /etc/nginx/batfish.htpasswd. It then removes the client's Authorization, X-Api-Key and cookies, and hands Batfish the instance key itself. Batfish runs its own file authorizer (-authorizertype file) against that key, so a request that somehow reached 127.0.0.1:19996 without the key would be refused too. The Basic login is there for tools that speak HTTP Basic; pybatfish uses the API key.
Step 9: TLS only
for v in tls1 tls1_1 tls1_2 tls1_3; do
r=$(echo | timeout 8 openssl s_client -connect 127.0.0.1:9996 -$v 2>/dev/null </dev/null | grep -E '^New, ' | head -1)
echo "$v: ${r:-refused}"
done
echo "plain HTTP to 9996: $(curl -s -o /dev/null -w '%{http_code}' -m 5 http://127.0.0.1:9996/v2/version)"
curl -s -m 5 http://127.0.0.1/ >/dev/null && echo "port 80 answered" || echo "port 80: connection refused"
tls1: New, (NONE), Cipher is (NONE)
tls1_1: New, (NONE), Cipher is (NONE)
tls1_2: New, TLSv1.2, Cipher is ECDHE-RSA-AES256-GCM-SHA384
tls1_3: New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
plain HTTP to 9996: 400
port 80: connection refused
TLS 1.0 and 1.1 handshakes fail (Cipher is (NONE)). Plain HTTP sent to 9996 gets nginx's 400 The plain HTTP request was sent to HTTPS port and never reaches Batfish, and nothing listens on port 80.
Step 10: No network access for Batfish
Batfish works only on the files you upload, so on this image it has no network access at all beyond loopback. systemd enforces this on the service's control group:
systemctl show batfish -p User -p IPAddressAllow -p IPAddressDeny -p CapabilityBoundingSet -p NoNewPrivileges -p ProtectSystem -p Restart
systemctl show nginx -p IPAddressDeny -p BindsTo
Restart=on-abnormal
IPAddressAllow=127.0.0.1/32 ::1/128
IPAddressDeny=0.0.0.0/0 ::/0
CapabilityBoundingSet=
User=batfish
ProtectSystem=strict
NoNewPrivileges=yes
IPAddressDeny=::ffff:168.63.129.16/128 168.63.129.16/32 ::ffff:169.254.169.254/128 169.254.169.254/32 fd00:ec2::254/128
BindsTo=batfish.service
Batfish runs as the locked user batfish with no capabilities, a read-only system, and every address except 127.0.0.1 and ::1 denied: from inside the service, connections to the instance metadata service, the VPC DNS resolver, the local DNS stub and the internet are all refused, while the same connections from root succeed. nginx needs the network to serve you, but it cannot reach the instance metadata service. The TLS key and the login file are invisible to the Batfish process.
Step 11: Fail closed and crash recovery
Each service checks its credentials before every start (batfish-preflight). If the API key file, the login file, the TLS key or certificate, or nginx's gate map is missing, unreadable, malformed, empty or the shipped default, the service is left failed and not restarting, and nothing listens on 9996. These are the results of breaking each one on a test instance:
gate-map missing: nginx failed (exit-code), NRestarts 0 -> 0 after 11 s, nothing on 9996
htpasswd sha1: nginx failed (exit-code), NRestarts 0 -> 0 after 11 s, nothing on 9996
htpasswd plaintext: nginx failed (exit-code), NRestarts 0 -> 0 after 11 s, nothing on 9996
tls-key malformed: nginx failed (exit-code), NRestarts 0 -> 0 after 11 s, nothing on 9996
users missing: batfish failed (exit-code), NRestarts 0 -> 0 after 21 s, nothing on 9996
users default-key: batfish failed (exit-code), NRestarts 0 -> 0 after 21 s, nothing on 9996
20 cases refused (failed, not restarting, nothing on 9996) and each restored to 200
A crash is different: if the Java process or nginx is killed, systemd restarts it and the API key is served again. nginx is bound to Batfish (BindsTo=), so it never serves on 9996 while Batfish is down. To see why a service refused to start:
sudo journalctl -u batfish -u nginx -b --no-pager | tail -n 20
Step 12: Use your own DNS name for the certificate
If you reach the instance by a DNS name of your own (for example batfish.example.com pointing at an Elastic IP), mint a new certificate that includes it. The helper keeps the instance's own names and addresses, updates the fingerprint in /root/batfish-credentials.txt and reloads nginx:
sudo batfish-tls-renew batfish.example.com
Copy the new /etc/batfish/tls/cert.pem to your clients afterwards. To use a certificate from your own CA instead, replace /etc/batfish/tls/cert.pem and /etc/batfish/tls/key.pem (owner root, key mode 0600) and run sudo systemctl restart nginx; the preflight check refuses a key that does not match its certificate.
Step 13: Manage the service
systemctl status batfish --no-pager -n 0 | head -n 6
sudo grep -E '^BATFISH_HEAP_OPTS=' /etc/default/batfish
● batfish.service - Batfish network configuration analysis service (cloudimg; loopback only, behind nginx TLS on 9996)
Loaded: loaded (/etc/systemd/system/batfish.service; enabled; preset: enabled)
Drop-In: /etc/systemd/system/batfish.service.d
└─50-cloudimg-imds-deny.conf
Active: active (running) since Tue 2026-11-10 22:59:44 UTC; 21min ago
Docs: https://www.cloudimg.co.uk/guides/batfish-2026-08-27-3685-on-ubuntu-24-04-aws/
BATFISH_HEAP_OPTS=-Xms256m -Xmx4298m
Batfish keeps uploaded snapshots and answers under /var/lib/batfish/containers until you delete them (bf.delete_network("name") or bf.delete_snapshot("name")). To change the heap after resizing the instance, edit -Xmx in /etc/default/batfish (1024 to 12288 MB) and run sudo systemctl restart batfish. Common commands:
sudo systemctl restart batfish # restart the analysis service (nginx follows)
sudo journalctl -u batfish -f # follow the Batfish log
sudo batfish-demo # re-run the end-to-end check
Step 14: Check what you are running
cat /usr/share/batfish/VERSION
sed -n '1,4p;9p' /usr/share/batfish/BUILD-INFO
sha256sum /opt/batfish/allinone-bundle.jar
/opt/batfish/pybatfish-venv/bin/python3 -I -c 'import pybatfish; print("pybatfish", pybatfish.__version__)'
2026.08.27.3685
product: Batfish 2026.08.27.3685 (allinone uber-jar), built by cloudimg (orchestrator ruling d-5235 C1)
commit: 329c14bf712f81b1522147abb00419c8e34e8f4a (v2026.08.27 release commit; no source change)
raises: jackson-bom 2.22.1 -> 2.23.0 (upstream e8e8dedb3f1c5a1edc9b0076663c0ba5a5cc5666)
raises: guava-bom 33.6.0-jre -> 33.7.2-jre (upstream 3ed9fb5e7b26029410f33c6c0d80c794684a46c1)
jar: sha256 a78c208cbb42aef31e8543f2177d05275aa4ef0de9ba4419fdde637f7bb1387b
a78c208cbb42aef31e8543f2177d05275aa4ef0de9ba4419fdde637f7bb1387b /opt/batfish/allinone-bundle.jar
pybatfish 2026.08.27.3685
The full build record, including the third raise (lz4-java 1.11.2 to 1.14.0), the build tool and the lock file digest, is in /usr/share/batfish/BUILD-INFO, and the exact dependency change is in /usr/share/batfish/raises.diff. Each raised version is the one the Batfish project adopted on its own main branch after the release (the upstream commits are named in the record).
Security recommendations
- Keep the security group tight. Allow 9996 only from the workstations and CI runners that run pybatfish, and SSH only from your management address.
- Treat the API key as a password. Anyone with it can upload networks and read every analysis on the instance. Keep it in a 0600 file or your CI secret store. To replace it, launch a new instance from the listing: every instance mints its own key at first boot.
- Treat uploaded configurations as sensitive. Snapshots contain your devices' full configurations, often with password hashes and SNMP communities. Delete networks you no longer need, and keep the root volume's EBS snapshots private.
- Keep the OS patched. Unattended security upgrades are on for the Ubuntu packages. Batfish itself is the jar on the image, so updating it means a newer cloudimg version from the listing.
Support and licensing
Batfish and pybatfish are developed by the Batfish project and distributed under the Apache License 2.0. The licence texts are in /usr/share/doc/batfish/, and every library bundled in the jar and the pybatfish environment, with its licence, is listed in /usr/share/batfish/THIRD-PARTY-NOTICES. cloudimg provides the source build, the TLS front, the per-instance key, login and certificate, the secure defaults and 24/7 support.
cloudimg is not affiliated with or endorsed by the Batfish project. Batfish is a mark of its owner and is used here only to identify the software.
For help with deployment or configuration, email support@cloudimg.co.uk or visit cloudimg support.