Level Up

How to Inventory Linux Servers for an AWS Migration with Ansible

Level Up Team

If your AWS migration assessment starts in a spreadsheet, you will spend the first two weeks typing hostnamectl output by hand.

Ansible already knows how to ask Linux hosts the questions a migration engineer needs. Use it.

This is the discovery layer behind Level Up's automated AWS migration assessment. You can run the same idea yourself.

What to collect (and what to skip)

Collect facts that change disposition, sizing, or wave order:

  • OS distribution and version
  • CPU, memory, and disk
  • Listening ports and unit files
  • Installed packages for app and database runtimes
  • Mounts, LVM, and large filesystems
  • Cron and systemd timers
  • Local users that applications actually use

Skip vanity fields. ansible_form_factor will not help you choose RDS.

A starter playbook

---
- name: Linux migration inventory
  hosts: linux
  gather_facts: true
  vars:
    assessment_dir: /tmp/aws-migration-inventory
  tasks:
    - name: Ensure output directory
      ansible.builtin.file:
        path: "{{ assessment_dir }}"
        state: directory
        mode: "0755"
      delegate_to: localhost
      run_once: true

    - name: Collect package facts
      ansible.builtin.package_facts:
        manager: auto

    - name: Collect service facts
      ansible.builtin.service_facts:

    - name: Collect listening sockets
      ansible.builtin.command: ss -lntp
      register: sockets
      changed_when: false

    - name: Collect filesystem usage
      ansible.builtin.command: df -B1 --output=source,fstype,size,used,avail,target
      register: filesystems
      changed_when: false

    - name: Write host evidence
      ansible.builtin.copy:
        dest: "{{ assessment_dir }}/{{ inventory_hostname }}.json"
        content: >-
          {{
            {
              'hostname': inventory_hostname,
              'distribution': ansible_facts.distribution,
              'distribution_version': ansible_facts.distribution_version,
              'cpu': ansible_facts.processor_vcpus,
              'mem_mb': ansible_facts.memtotal_mb,
              'mounts': ansible_facts.mounts,
              'packages': ansible_facts.packages.keys() | list,
              'services': services,
              'sockets': sockets.stdout_lines,
              'df': filesystems.stdout_lines
            } | to_nice_json
          }}
      delegate_to: localhost

Run it against a scoped inventory — one environment, one network zone — before you try the whole estate.

ansible-playbook -i inventories/plant-prod.ini linux-inventory.yml

Turn facts into workloads

A folder of JSON files is not an assessment. Group hosts by:

  • Shared application name or systemd unit
  • Shared database
  • Shared VIP or load balancer
  • Shared Ansible group

That grouping is the start of a workload map. Dependencies come next: connection strings, DNS, and observed ports. See how to detect application dependencies.

Safety notes

  • Use read-only modules and changed_when: false for collection.
  • Do not gather secrets into the inventory artifact.
  • Keep the output machine-readable. Markdown can be generated later.

If you want this inventory to flow into dispositions, waves, and a backlog instead of another spreadsheet, use the open-source assessment or run it with Level Up.