Networking Azure

GNS3 Server on Ubuntu 24.04 on Azure User Guide

| Product: GNS3 Server on Ubuntu 24.04 LTS on Azure

Overview

This guide covers the deployment and configuration of GNS3 Server on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. GNS3 is the widely used open source network emulation platform for designing, building and testing network topologies without physical hardware. It runs virtual labs made of emulated Cisco routers, Docker containers, QEMU virtual machines and lightweight virtual PCs, wired together into topologies you can start, stop and inspect.

This image ships the server component: the headless controller and compute engine that actually runs the labs. You drive it from the bundled browser web interface, or by pointing the GNS3 desktop client at it. Running the server on Azure rather than a laptop means labs keep running when you close your machine, they get server grade CPU and memory, and a whole team can share them.

The image installs GNS3 Server 2.2.60 and the complete emulation stack at pinned versions from the official GNS3 package archive, whose signing key is verified by full fingerprint before the archive is trusted. The baked versions are recorded in /var/lib/gns3/VERSION. GNS3 runs under systemd as the unprivileged gns3 system user, bound to loopback only (127.0.0.1:3080). nginx is the sole network facing surface: it terminates TLS on port 443, enforces HTTP basic authentication on every request and reverse proxies to GNS3. Port 80 redirects to HTTPS.

Secure by default, and it matters more here than for most software. An unprotected GNS3 interface lets anyone who can reach it create and start containers and virtual machines on the host, which makes an open one equivalent to handing out shell access. This image closes it at two independent layers using a single credential: GNS3's own HTTP authentication is enabled on the loopback listener, and nginx enforces HTTP basic authentication on every path in front of it. A unique credential is generated on each virtual machine's first boot and applied to both layers. Only a one way bcrypt hash is stored for nginx; the plain password is placed in a root only file. There are no shared or default credentials and nothing usable is baked into the image. Device consoles are bound to the loopback interface rather than the network, and are reached over an SSH tunnel (Step 8).

What is included:

  • GNS3 Server 2.2.60 run under systemd as the unprivileged gns3 system user, with projects, images and configs under /var/lib/gns3

  • The complete emulation stack at pinned versions: Dynamips 0.2.23 (Cisco IOS router emulation), ubridge 1.0.1 (node networking), VPCS 0.8.3 (lightweight virtual PCs), QEMU 8.2.2 (full virtual machines) and Docker (container nodes)

  • A ready to run Docker appliance template (alpine:3.24.1, pinned by digest) so you can start a real node immediately without downloading anything

  • GNS3 bound to loopback only (127.0.0.1:3080) with its own authentication enabled; it is never network exposed directly

  • nginx terminating TLS on :443, enforcing HTTP basic authentication and reverse proxying to GNS3, with HSTS and sensible security headers

  • Port :80 returns a 301 redirect to HTTPS for every path except an unauthenticated /healthz endpoint (HTTP 200) for load balancer probes

  • A unique API credential generated per VM on first boot and applied to both authentication layers; only the one way bcrypt hash is stored for nginx, the plain password lands in a root only file

  • Device consoles pinned to loopback (console_host = 127.0.0.1), because telnet consoles are unauthenticated by protocol

  • A self signed TLS certificate regenerated per VM on first boot (its Subject Alternative Names include the VM public IP, hostname and 127.0.0.1); replace it with your own CA signed certificate for production

  • A built in self test at /usr/local/bin/gns3-selftest that proves the authenticated API end to end and starts a real emulated node

  • Ubuntu 24.04 LTS base with the latest security patches applied at build time

  • Azure Linux Agent for seamless cloud integration and SSH key injection

  • 24/7 cloudimg support with a guaranteed 24 hour response SLA

Prerequisites

  • An Azure subscription with permission to deploy virtual machines

  • An SSH key pair for the azureuser account

  • A network security group that allows inbound 443 from your users and 22 from your management network only

  • Choose the right VM size for the emulation you need. See Step 3 before you deploy: Dynamips, Docker and VPCS nodes run on any size, while QEMU virtual machine nodes need a size that supports nested virtualisation.

Step 1: Choose a VM size for the emulation you need

GNS3 emulates devices in several ways, and they do not all have the same hardware requirement. This is the single most important sizing decision for this image, so make it before you deploy.

Node type What it emulates Needs nested virtualisation?
Dynamips Classic Cisco IOS routers No — runs on any VM size
Docker Container based appliances and hosts No — runs on any VM size
VPCS Lightweight virtual PCs for testing reachability No — runs on any VM size
Ethernet switch / hub / cloud Built in switching and connectivity No — runs on any VM size
QEMU / KVM Full virtual machines (vendor appliance images, firewalls, full OS nodes) Yes — needs /dev/kvm

QEMU nodes are hardware accelerated through KVM, which on Azure requires nested virtualisation. Azure's B series does not support nested virtualisation, so /dev/kvm is absent there and QEMU based appliance nodes cannot be accelerated. The Dv3, Dsv3, Dv5 and Dsv5 series (and later) do support it.

  • If you will use Dynamips, Docker or VPCS nodes only, any size works. Standard_B2s is enough to get started.

  • If you will use QEMU virtual machine nodes, deploy on Standard_D2s_v3 or larger (any v3 or later D series). This is the recommended size for this image, and it is what the marketplace listing recommends.

Emulation is CPU and memory hungry in general: size for the lab you intend to run, not the smallest node count.

Step 2: Deploy from the Azure Portal

  1. Locate the GNS3 Server on Ubuntu 24.04 LTS image in the Azure Marketplace and select Create.

  2. Choose your subscription, resource group and region.

  3. Select a VM size using Step 1 (Standard_D2s_v3 or larger if you need QEMU nodes) and provide your SSH public key for the azureuser account.

  4. On the Networking tab, allow inbound 443 from your users, and restrict 22 to your management network.

  5. Review and create. When the VM is running, browse to https://<your-public-ip>/.

Step 3: Deploy from the Azure CLI

Deploy the image from the command line, restricting SSH to your management network. Replace the placeholder values with your own before running:

az vm create \
  --resource-group my-resource-group \
  --name gns3-server \
  --image <marketplace-image-urn> \
  --size Standard_D2s_v3 \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_rsa.pub \
  --public-ip-sku Standard

# Allow the web UI from your users and SSH from your management network only
az vm open-port --resource-group my-resource-group --name gns3-server --port 443 --priority 1001
az network nsg rule create --resource-group my-resource-group --nsg-name gns3-serverNSG \
  --name allow-ssh --priority 1002 --destination-port-ranges 22 \
  --source-address-prefixes <your-mgmt-cidr> --access Allow --protocol Tcp

When the VM is running, browse to https://<public-ip>/.

Step 4: Retrieve your per instance API credential

Access is protected by HTTP basic authentication at the proxy and by GNS3's own authentication behind it. Each VM generates its own username and password on first boot, written to a root only file. Read it over SSH:

ssh azureuser@<vm-ip> 'sudo cat /root/gns3-server-credentials.txt'

The file contains the GNS3_USER, GNS3_PASS and GNS3_URL for this specific VM. Keep it secret: this credential can start containers and virtual machines on the server. nginx only ever stores a one way bcrypt hash of the password.

Step 5: Sign in and register the server in the web interface

Browse to https://<vm-ip>/. Because the certificate is self signed per VM, your browser will show a certificate warning the first time; accept it to proceed (or place a CA signed certificate in front, as covered in Step 11). Your browser then prompts for the basic authentication username and password from Step 4.

The GNS3 Web UI opens on its Servers page. The web interface is a client: you tell it which GNS3 server to talk to. Click Add server and fill in the connection details for this VM, choosing Basic authorization and entering the credential from Step 4.

The GNS3 Web UI Add server dialog, with fields for Name, Location set to Remote, Host, Port, Protocol set to HTTPS, and an Authorization selector showing the No authorization and Basic authorization options

Once added, the server appears in the Servers table with its host, port and location, and an arrow action to open it.

The GNS3 Web UI Servers table listing the registered cloudimg-gns3 server with its ID, name, location, host and port, and actions to open or delete it

Step 6: Create a project

Open the server to reach its Projects page. From here you can create a blank project, import an existing one, or open a project you already have. Projects are stored on the VM under /var/lib/gns3/projects.

The GNS3 Web UI Projects page for the registered server, showing a project table with the demo-lab project and buttons to add a blank project, import a project, and go to system status or preferences

Click a project to open its topology canvas.

Step 7: Build and start a topology

Open the project to reach the topology canvas. Add nodes from the toolbar, drag links between their ports, and use the toolbar controls to start, pause and stop the lab. Started nodes show a green marker, and the node panel lists each node's console address.

The example below is a three node lab: two Docker based hosts wired to an Ethernet switch, all started. Note that each console is a telnet://127.0.0.1:<port> address, because consoles are deliberately bound to the loopback interface — Step 8 covers how to reach them.

The GNS3 Web UI topology canvas showing a running lab of PC1 and PC2 connected through Switch1 with port labels on each link, and a node panel listing all three nodes with green started markers and their loopback telnet console addresses

You can drive the same operations from the REST API. This creates a project, adds a Docker node from the bundled alpine:3.24.1 template, starts it, then removes the project again:

GUSER=$(sudo grep -m1 '^GNS3_USER=' /root/gns3-server-credentials.txt | cut -d= -f2-)
GPASS=$(sudo grep -m1 '^GNS3_PASS=' /root/gns3-server-credentials.txt | cut -d= -f2-)

PID=$(curl -sk -u "$GUSER:$GPASS" -X POST -H 'Content-Type: application/json' \
  --data '{"name":"api-demo"}' https://127.0.0.1/v2/projects \
  | sed -n 's/.*"project_id": *"\([^"]*\)".*/\1/p')

curl -sk -u "$GUSER:$GPASS" -X POST -H 'Content-Type: application/json' \
  --data '{"name":"host1","node_type":"docker","compute_id":"local","console_type":"telnet",
           "properties":{"image":"alpine:3.24.1","adapters":1,"start_command":"/bin/sh"}}' \
  -o /dev/null -w 'create node -> HTTP %{http_code}\n' https://127.0.0.1/v2/projects/$PID/nodes

curl -sk -u "$GUSER:$GPASS" -X POST -o /dev/null -w 'start nodes -> HTTP %{http_code}\n' \
  https://127.0.0.1/v2/projects/$PID/nodes/start

curl -sk -u "$GUSER:$GPASS" -X DELETE -o /dev/null -w 'cleanup -> HTTP %{http_code}\n' \
  https://127.0.0.1/v2/projects/$PID

Note that console_type is required when creating a node; GNS3 does not default it.

Step 8: Reach a device console

Device consoles are telnet, which is unauthenticated by protocol. This image therefore binds them to the loopback interface (console_host = 127.0.0.1) so they are never reachable from the network. Reach one by forwarding the console port over SSH from your workstation, then connecting to the forwarded port locally:

# On your workstation. The console port is shown in the node panel, e.g. 5000.
ssh -L 5000:127.0.0.1:5000 azureuser@<vm-ip>
telnet 127.0.0.1 5000

Do not change console_host to 0.0.0.0: that would expose every device console to the network without authentication.

Step 9: Verify the deployment

SSH to the VM as azureuser and confirm the services are running and GNS3 is bound to loopback only:

systemctl is-active gns3-server nginx docker
sudo ss -tlnp | grep -E ':(80|443|3080)\b'

All three services report active, and GNS3 listens on 127.0.0.1:3080 only. nginx is the only component exposed on :80 and :443.

systemctl reporting gns3-server, nginx and docker all active, and ss showing the gns3server process bound to 127.0.0.1:3080 loopback only with nginx listening on port 80 and port 443

Run the built in self test. It reads this VM's credential and proves the whole path: the health probe answers, an unauthenticated API request is refused, an authenticated request succeeds, a project is created through the API, and a real Docker backed node is started. It also reports the hardware virtualisation state of this VM:

sudo /usr/local/bin/gns3-selftest

The gns3-selftest output reporting OK with healthz 200, unauthenticated version and projects requests both 401, authenticated API 200 on GNS3 2.2.60, a project created through the API and a Docker backed node started, followed by the hardware virtualisation report

Step 10: The authentication gate and the API

nginx terminates TLS on port 443 and redirects plain HTTP on port 80 to HTTPS. Confirm the redirect, the unauthenticated health probe, and that the API is refused without the per VM credential and succeeds with it:

curl -s -o /dev/null -w 'port 80 -> HTTP %{http_code}\n' http://127.0.0.1/
curl -sk -o /dev/null -w 'healthz -> HTTP %{http_code}\n' https://127.0.0.1/healthz
curl -sk -o /dev/null -w 'API, no creds -> HTTP %{http_code}\n' https://127.0.0.1/v2/version
curl -sk -o /dev/null -w 'API, direct to loopback, no creds -> HTTP %{http_code}\n' http://127.0.0.1:3080/v2/version

Port 80 returns 301 and the health endpoint returns 200. The API returns 401 without credentials — both through the proxy and when addressed directly on the loopback listener, which is the proof that GNS3's own authentication layer is enforcing and not merely shadowed by nginx.

With the credential, the API answers and reports the node types this server can emulate:

GUSER=$(sudo grep -m1 '^GNS3_USER=' /root/gns3-server-credentials.txt | cut -d= -f2-)
GPASS=$(sudo grep -m1 '^GNS3_PASS=' /root/gns3-server-credentials.txt | cut -d= -f2-)
curl -sk -u "$GUSER:$GPASS" https://127.0.0.1/v2/version
curl -sk -u "$GUSER:$GPASS" https://127.0.0.1/v2/computes | jq -r '.[0].capabilities.node_types | join(", ")'

The authenticated GNS3 API returning version 2.2.60, the list of emulated node types including dynamips, docker, qemu, vpcs and the built in switches, and the project list showing the demo-lab project

Step 11: Connect the GNS3 desktop client

The desktop client is the richer way to build large topologies, and it talks to this same server. In the client, choose to connect to a remote server and supply the VM's address on port 443 with HTTPS, plus the username and password from Step 4. Because the certificate is self signed, either accept it or install a CA signed certificate first (below).

Use a matching client version — a GNS3 2.2.x client for this 2.2.60 server.

Step 12: Replace the certificate for production

The per VM certificate is self signed, so browsers and the desktop client warn on first use. For a real deployment, put a trusted certificate in front. The simplest path is to point a DNS name at the VM and obtain a free certificate with Certbot:

# Point https://<your-domain> at this VM first, then:
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <your-domain>

Alternatively, terminate TLS at an Azure Application Gateway or a load balancer in front of the VM and forward to port 443.

Step 13: Baked versions and emulator inventory

The baked GNS3 and emulator versions are recorded on the VM, along with the pinned Docker appliance template and the archive signing key that was verified at build time:

cat /var/lib/gns3/VERSION
dynamips --version | head -1
vpcs -v | head -1
ubridge -v
qemu-system-x86_64 --version | head -1

The last command in the screenshot below checks for /dev/kvm. On a B series VM it is absent, which is expected and only affects QEMU nodes — Dynamips, Docker and VPCS nodes are unaffected. On a Standard_D2s_v3 or larger it is present and QEMU nodes are hardware accelerated.

The /var/lib/gns3/VERSION file listing the pinned GNS3 server, dynamips, ubridge and vpcs package versions, the alpine appliance template digest and the verified PPA signing key, followed by the reported emulator versions and the /dev/kvm check

Step 14: Service management

systemctl status gns3-server --no-pager | head -12
sudo journalctl -u gns3-server -n 20 --no-pager

The server log is also written to /var/log/gns3/gns3-server.log. Projects, images, configs and appliances live under /var/lib/gns3 — back that directory up to preserve your labs.

Security notes

  • No default login. Access is protected at two layers with a single credential generated on each VM's first boot: nginx HTTP basic authentication, and GNS3's own authentication on the loopback listener. Only a one way bcrypt hash is stored for nginx; the plain password lives in the root only /root/gns3-server-credentials.txt.

  • Treat the credential as shell access. The GNS3 API can create and start containers and virtual machines on the server. Anyone with this credential can run code on the VM. Share it accordingly, and put an identity aware proxy in front if you need per user access.

  • Loopback only application. GNS3 binds to 127.0.0.1:3080 and is only reachable through the nginx TLS reverse proxy on :443. Keep it that way and let nginx (or a load balancer) be the sole network facing surface.

  • Consoles stay on loopback. Device telnet consoles are unauthenticated by protocol, so console_host is pinned to 127.0.0.1. Reach them over an SSH tunnel (Step 8) rather than changing that setting.

  • Restrict access. Allow 443 only from the networks that need it, keep 22 restricted to your management network, and replace the self signed certificate with a CA signed one for production.

  • Rotate the credential with sudo /usr/local/sbin/gns3-write-credentials <new-user> <new-password>, then restart the services. This updates both authentication layers together.

  • Version pinning. The GNS3 packages are installed at exact validated versions from the official GNS3 archive, whose signing key is verified by fingerprint at build time. They are deliberately not placed on apt hold: Ubuntu's unattended upgrades only apply the security origin, so a third party archive is never upgraded automatically, and holding packages would misrepresent the patch posture of the machine. OS security updates continue to apply as normal, and you remain free to upgrade GNS3 yourself when you choose to.

Support

This image is backed by 24/7 cloudimg support with a guaranteed 24 hour response SLA. Contact support@cloudimg.co.uk for assistance. GNS3 is open source software distributed under the GNU General Public License v3.0 and is free; the cloudimg charge covers packaging, hardening, security patching, image maintenance and support.