Networking AWS

FOG Project on AWS User Guide

| Product: FOG Project on AWS

Overview

This image runs FOG Project 1.5.10.1903. FOG is a free, open source network cloning and imaging platform. You capture a disk image once from a reference machine, store it centrally, and then deploy that image to as many machines as you need over the network, driven by a PXE network boot rather than by anyone carrying media from desk to desk.

Around that core, FOG provides the management work that surrounds imaging: a hardware inventory of every machine that has checked in, a record of which image each one is running, machine groups, scheduled capture and deploy tasks, and snapins that install software or apply a change to a group of machines after imaging.

The appliance has two planes, and they have deliberately different security postures:

  • The management plane - the FOG web console and REST API on port 80. It is authenticated, with a console password and API tokens generated uniquely on your instance's first boot.
  • The boot plane - TFTP on 69/udp serving the iPXE bootloaders, plus NFS on 2049 serving the image store. It is anonymous by protocol necessity: a machine that is powering on cannot present credentials, and TFTP has no authentication in the protocol at all. You scope it with your EC2 security group and the subnet-scoped NFS export.

This image deliberately ships no DHCP server. FOG can install and run one, and on a cloud VPC that would be actively harmful - it would compete with the VPC's own platform DHCP and can break networking for every instance on the subnet. This image is built with FOG's DHCP server disabled, and the build fails if any DHCP server package is found installed or anything is found listening on 67/udp. You point your existing DHCP server at this server instead, which is covered in Step 9.

What is included:

  • FOG Project 1.5.10.1903, installed by the project's own installer from the pinned upstream commit c8a5665
  • Apache 2.4 with PHP 8.3 serving the web console and REST API at /fog/management
  • MariaDB, bound to 127.0.0.1 only - the database is a purely local dependency of the web application
  • tftpd-hpa on 69/udp serving the full set of iPXE bootloaders from /tftpboot (BIOS, UEFI, Secure Boot, arm64 and per-NIC variants)
  • nfs-kernel-server serving the image store at /images, scoped at first boot to your instance's own subnet rather than upstream's export-to-every-host default
  • vsftpd for FOG's own image file management
  • The seven FOG service daemons (scheduler, image replicator, multicast manager, ping hosts, snapin hash, snapin replicator, image size), all enabled
  • A dedicated EBS data volume mounted at /images for the captured image library, independently resizable and separate from the OS disk
  • A per-instance console password, REST API token and user API token generated on first boot into /root/fog-project-credentials.txt, readable only by root. No shared or default login exists in the image - FOG's documented fog / password default does not work on your instance
  • The complete corresponding source at /opt/fog-source with the GPLv3 licence text, satisfying the licence's source obligation on the image itself
  • A fully patched Ubuntu 24.04 LTS base with unattended security upgrades enabled
  • 24/7 cloudimg support

Before you start: what PXE imaging requires

FOG images machines by PXE network boot, and that imposes real network requirements. Read this before you design your deployment, because it determines where this instance belongs.

A machine being imaged powers on, asks its local DHCP server for an address, and that DHCP server tells it where to fetch a bootloader (options 66 and 67). The machine then fetches the bootloader over TFTP, chains to FOG over HTTP, and moves image data over NFS.

  • The DHCP handoff happens on the client's local broadcast domain, so the DHCP server that answers must be one you can configure. This appliance does not provide it.
  • Everything after that handoff - TFTP, HTTP, NFS - is routed unicast, so the FOG server itself does not need to be on the same layer 2 segment as the clients. It needs to be routable from them.

The supported topology on AWS is therefore: this instance in your VPC, your client machines on premises or in a connected network, reached over VPN or Direct Connect, with your existing on-premises DHCP server setting options 66 and 67 to point at this instance's private address.

Two FOG capabilities genuinely do not work on a cloud VPC, and no configuration changes that:

  • Multicast deployment, which images many machines simultaneously from one stream. VPC subnets do not carry multicast. Unicast deployment to each machine works normally.
  • FOG's proxyDHCP mode, which supplies boot options without running a full DHCP server. It depends on broadcast traffic, which VPC subnets also do not carry. Setting options 66 and 67 on your own DHCP server is the supported path, and is what Step 9 covers.

Be realistic about bandwidth as well. Disk images are tens of gigabytes; deploying them from AWS to on-premises machines pulls that volume across your VPN or Direct Connect link for every machine. For large on-premises fleets, a FOG storage node on the client network is the usual answer, with this instance as the management server.

Prerequisites

An AWS account, an EC2 key pair, and a VPC plus subnet in the target region. m5.large (2 vCPU / 8 GiB RAM) is the recommended instance type - FOG runs Apache, PHP, MariaDB, NFS and TFTP together.

The captured image library lives on a dedicated EBS data volume mounted at /images, separate from the OS disk and independently resizable. Grow it as your image library grows.

Security group inbound rules: allow 22/tcp from your management network, 80/tcp from the networks that need the console, and 69/udp, 2049/tcp and 21/tcp from the subnets whose machines will be imaged. Do not expose any of these to the internet. The boot plane is anonymous by design, so the security group is what scopes it.

Connecting to your instance

Connect over SSH as the login user for the operating system variant you launched:

OS variant SSH login user
Ubuntu 24.04 LTS ubuntu
ssh ubuntu@<instance-public-ip>

Step 1 - Launch from the AWS Marketplace

In the AWS Marketplace, search for FOG Project - Network Imaging and Cloning Server AMI by cloudimg and choose Continue to Subscribe, then Continue to Configuration and Continue to Launch. Select the m5.large instance type, your VPC and subnet, and your EC2 key pair. Set the security group to allow inbound 22/tcp from your management network only, and add the remaining rules from the Prerequisites section after launch.

Step 2 - Launch from the AWS CLI

Run these on your own workstation, not on the instance. Replace the AMI id with the one shown for your Region on the Marketplace launch page, and use your own key pair, subnet and security group ids:

aws ec2 run-instances \
  --image-id ami-xxxxxxxxxxxxxxxxx \
  --instance-type m5.large \
  --key-name your-key \
  --subnet-id subnet-xxxxxxxx \
  --security-group-ids sg-xxxxxxxx \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=fog-server}]'

Step 3 - Connect to your instance

ssh ubuntu@<instance-public-ip>

Step 4 - Confirm the services are running

FOG is several cooperating services, so check them together. All should report active.

sudo systemctl is-active apache2 mariadb tftpd-hpa nfs-kernel-server vsftpd
active
active
active
active
active

The seven FOG daemons run alongside them:

sudo systemctl is-active FOGScheduler FOGImageReplicator FOGImageSize FOGMulticastManager FOGPingHosts FOGSnapinHash FOGSnapinReplicator
active
active
active
active
active
active
active

The web console answers on the loopback interface:

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/fog/management/index.php
200

Step 5 - Confirm no DHCP server is running

This is the property that makes FOG safe to run on a cloud network, so verify it yourself. FOG records its DHCP decision in its own settings file:

sudo grep -E '^(bldhcp|dodhcp)=' /opt/fog/.fogsettings
dodhcp='N'
bldhcp='0'

No DHCP server package is installed:

for p in isc-dhcp-server kea-dhcp4-server dnsmasq; do
  if dpkg-query -W -f='${Status}' "$p" 2>/dev/null | grep -q '^install ok installed$'; then
    echo "$p: INSTALLED"
  else
    echo "$p: not installed"
  fi
done
isc-dhcp-server: not installed
kea-dhcp4-server: not installed
dnsmasq: not installed

And nothing is listening on the DHCP server port:

ss -lnu | grep -c ':67 ' || echo 0
0

Step 6 - Retrieve your per-instance credentials

Every credential on this instance was generated on its own first boot. The file is readable only by root.

sudo cat /root/fog-project-credentials.txt

You will see the console login, both API tokens, the server address and the database credentials. The console password is what you use in Step 8:

sudo grep -E '^(fog_web_url|fog_admin_user|fog_server_address|fog_tftp_bootfile|fog_uefi_bootfile)=' /root/fog-project-credentials.txt
fog_web_url=http://<instance-public-ip>/fog/management
fog_admin_user=fog
fog_server_address=<instance-private-ip>
fog_tftp_bootfile=undionly.kpxe
fog_uefi_bootfile=snponly.efi

The file is 0600 root:root:

sudo ls -l /root/fog-project-credentials.txt

FOG's documented default login, fog / password, does not work on your instance - the build replaces it with the generated password before the image is captured, and the first boot then sets a value unique to your machine.

Step 7 - Confirm the boot plane and image store

Fetch a PXE bootloader over TFTP exactly as a booting machine would:

cd /tmp && rm -f undionly.kpxe && tftp 127.0.0.1 -c get undionly.kpxe && ls -l undionly.kpxe
-rw-rw-r-- 1 ubuntu ubuntu 105509 Jul 21 09:50 undionly.kpxe

The iPXE chain file tells booting machines where to find the FOG server. It is regenerated with your instance's address on first boot:

sudo tail -1 /tftpboot/default.ipxe
chain http://<instance-private-ip>/fog/service/ipxe/boot.php##params

The image store lives on its own EBS data volume and is exported over NFS, scoped to your instance's own subnet rather than to every host:

findmnt -no SOURCE,TARGET,FSTYPE,SIZE /images
/dev/nvme1n1 /images ext4   97.9G
sudo exportfs -s
/images  172.31.80.0/20(sync,no_wdelay,hide,insecure_locks,fsid=0,anonuid=1002,anongid=1002,sec=sys,ro,secure,root_squash,all_squash)
/images/dev  172.31.80.0/20(async,no_wdelay,hide,fsid=1,anonuid=1002,anongid=1002,sec=sys,rw,secure,root_squash,all_squash)

If your machines are imaged from a different subnet reached over VPN or Direct Connect, add that CIDR to /etc/exports and re-export. This block is an example to adapt, not something to run as is:

# /etc/exports - add your imaging subnet alongside the local one
/images      10.50.0.0/16(ro,sync,no_wdelay,subtree_check,insecure_locks,all_squash,anonuid=1002,anongid=1002,fsid=0)
/images/dev  10.50.0.0/16(rw,async,no_wdelay,subtree_check,all_squash,anonuid=1002,anongid=1002,fsid=1)

Step 8 - Sign in to the FOG console

Browse to http://<instance-public-ip>/fog/management. Sign in as fog with the fog_admin_password value from Step 6.

The FOG Project console login page

The dashboard shows the server at a glance: storage group activity, disk usage on the storage node and imaging activity over the last 30 days.

The FOG Project dashboard showing system overview, storage group activity and storage node disk usage

Step 9 - Point your DHCP server at the FOG server

FOG needs your existing DHCP server to tell booting machines where to find it. Set two options on the scope serving the machines you want to image:

  • Option 66 (next-server / TFTP server name) - this instance's private IP address, the fog_server_address value from Step 6
  • Option 67 (filename / bootfile name) - undionly.kpxe for BIOS machines, or snponly.efi for UEFI machines

On an ISC DHCP server, the scope looks like this. Adapt the addresses to your network; this is an example, not something to run on this instance:

# dhcpd.conf - point PXE clients at the FOG server
subnet 10.50.0.0 netmask 255.255.0.0 {
  range 10.50.10.100 10.50.10.200;
  option routers 10.50.0.1;
  next-server 172.31.91.112;     # your FOG server's private IP
  filename "undionly.kpxe";      # use "snponly.efi" for UEFI clients
}

On a Windows DHCP server, set scope option 066 Boot Server Host Name to the FOG server's IP and 067 Bootfile Name to undionly.kpxe or snponly.efi.

Mixed BIOS and UEFI fleets need your DHCP server to select the bootfile by client architecture. Both ISC DHCP and Windows Server support this; FOG's documentation covers the exact syntax.

Step 10 - Register a machine

With DHCP pointing at the server, boot a client machine from the network. It fetches the bootloader, chains to FOG, and presents the FOG boot menu. Choose Perform Full Host Registration and Inventory to add it to FOG with its hardware inventory.

Registered machines appear under Host Management, where you assign an image, put them in groups and schedule tasks.

FOG Project Host Management showing the host list and per-host controls

Step 11 - Define an image and capture

Under Image Management, select Create New Image and give it a name, a storage group and an image type. Single Disk - Resizable suits most single-disk Windows and Linux workstations.

FOG Project Image Management showing the image library

To capture, assign the image to your reference machine under Host Management, schedule a Capture task, and network boot that machine - it boots into FOG's imaging environment and uploads the image to /images. To deploy, assign the same image to the target machines, schedule a Deploy task, and boot them.

Step 12 - Use the REST API

FOG's REST API is enabled on this image with tokens generated for your instance. Both tokens are stored ready to paste straight into the request headers.

API_TOKEN=$(sudo grep '^fog_api_token=' /root/fog-project-credentials.txt | cut -d= -f2-)
USER_TOKEN=$(sudo grep '^fog_user_api_token=' /root/fog-project-credentials.txt | cut -d= -f2-)
curl -s -H "fog-api-token: ${API_TOKEN}" -H "fog-user-token: ${USER_TOKEN}" \
  http://127.0.0.1/fog/system/info
success

List the registered machines as JSON:

API_TOKEN=$(sudo grep '^fog_api_token=' /root/fog-project-credentials.txt | cut -d= -f2-)
USER_TOKEN=$(sudo grep '^fog_user_api_token=' /root/fog-project-credentials.txt | cut -d= -f2-)
curl -s -H "fog-api-token: ${API_TOKEN}" -H "fog-user-token: ${USER_TOKEN}" \
  http://127.0.0.1/fog/host | head -c 200

Requests without valid tokens are rejected:

curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1/fog/system/info
403

Note that FOG's hostName column is 16 characters, so machine names are truncated beyond that.

Security

  • No DHCP server. FOG's own DHCP server is not installed and is not running. This is asserted at build time and again on every first boot; the appliance refuses to start it.
  • No default credentials. FOG's documented fog / password default does not authenticate on your instance. The console password, both API tokens, both database passwords and the storage account password are generated on your instance's first boot and exist nowhere else. They are written to /root/fog-project-credentials.txt at 0600 root:root.
  • The database is not reachable off the instance. MariaDB is bound to 127.0.0.1 with name resolution disabled.
  • The image store is scoped. Upstream FOG exports /images to every host with /images/dev writable. This image exports it to your instance's own subnet instead, and you widen it deliberately as shown in Step 7.
  • The boot plane is anonymous by protocol necessity. TFTP has no authentication and a machine that is powering on cannot present credentials. Scope 69/udp, 2049/tcp and 21/tcp with your security group to the subnets that image machines, and never expose them to the internet.
  • FOG stores console passwords as unsalted MD5. That is upstream FOG's scheme and cannot be changed without forking its authentication. Treat the console as a trusted-network service, put it behind your security group, and do not reuse the console password anywhere else.
  • Change the console password from Users in the web console if you want a value you have chosen rather than the generated one.

Maintenance

Ubuntu security updates apply automatically through unattended upgrades. Restart the appliance after a kernel update:

sudo systemctl restart apache2 mariadb tftpd-hpa nfs-kernel-server

Back up the FOG database and your image library. The database holds the inventory, groups, tasks and settings:

sudo mysqldump fog | gzip > /tmp/fog-backup.sql.gz && ls -lh /tmp/fog-backup.sql.gz

Watch free space on /images - it fills as your image library grows, and it is a dedicated EBS volume you can resize independently of the OS disk:

df -h /images | tail -1
/dev/nvme1n1     98G   44K   93G   1% /images

Licence and source

FOG Project is licensed under the GNU General Public License, version 3 or later. The complete corresponding source for the version in this image ships on the image:

ls /opt/fog-source/LICENSE /opt/fog-source/CLOUDIMG-SOURCE-NOTICE.txt

The notice file records the exact upstream commit, the source URLs for the bundled iPXE and Syslinux bootloaders, and a written offer for machine-readable source. Nothing in cloudimg's terms restricts your rights in the FOG software or any other GPL-licensed component.

Support

cloudimg provides 24/7 support for this image. Contact support@cloudimg.co.uk. For questions about FOG itself, the project's own documentation is at docs.fogproject.org and its community forum is at forums.fogproject.org.