Home · About · Services · Industries · Projects · Products · Process · Blog · FAQ · Contact
IT infrastructure audit checklist for growing companies (2026) How to audit your own servers, cloud accounts and release process: what to check in each area, the commands that gather the evidence, and how to rank what you…
A company grows from one server to twelve over three years. Each machine was set up by whoever needed it that month. Then a customer sends a security questionnaire, or an investor asks how the platform would survive losing a server, and nobody can answer with confidence. That is usually when people search for an infrastructure audit.
The short answer: an IT infrastructure audit is a structured review of everything your software runs on. It covers inventory, access, server and network security, backups, monitoring, the release process, containers and cost. For each area you collect evidence, not opinions, then rank the findings so the riskiest few get fixed first.
This is the checklist we work through. You can run most of it yourself with read-only access and a few days of focused time. The commands below are for Linux servers, AWS and Azure, but the questions apply to any setup.
Start by writing down what is in scope: which cloud accounts, which servers, which environments. Staging often matters more than people think, because it tends to hold copies of production data with weaker controls. Decide also what is out of scope, such as office laptops or a third-party SaaS, so the audit finishes.
Use read-only access. On AWS that is the ReadOnlyAccess or SecurityAudit managed policy; on Azure, the Reader role on the subscription. On servers, a named account with sudo for the duration of the audit, removed afterwards. For every finding, save the evidence: the command, its output and the date. A finding without evidence turns into an argument later.
1. Inventory and cost: what exists and who pays for it You cannot secure or pay for things you do not know about. List every running resource in every region, because forgotten instances in a region nobody uses are a common source of both cost and risk.
# AWS: running EC2 instances in every enabled region
for r in $(aws ec2 describe-regions --query 'Regions[].RegionName' --output text); do
aws ec2 describe-instances --region "$r" \
--filters Name=instance-state-name,Values=running \
--query 'Reservations[].Instances[].[InstanceId,InstanceType,LaunchTime]' \
--output text | sed "s/^/$r\t/"
done
# Azure: every resource in the current subscription
az resource list --query "[].{name:name, type:type, group:resourceGroup}" -o tableServers, containers and managed services, each with an owner and a purpose. Domains and DNS zones, who the registrar is, and when each domain expires. TLS certificates and how each one renews. Third-party services that hold data or send email on your behalf. A diagram of how a request travels from the internet to the database. Draw it from what you found, not from memory. Cost belongs in the same pass, because waste and risk usually come from the same place: resources nobody owns. Look for stopped instances still paying for volumes, unattached disks, old snapshots, oversized instances running at low CPU for weeks, and data transfer you cannot explain. On AWS, Cost Explorer grouped by service and region shows where to look; on Azure, Cost Management does the same. Put an estimated monthly saving next to each item so it can be weighed against the effort.
2. Access and identity Access problems cause more damage in growing companies than clever attacks do. Look for accounts belonging to people who have left, shared logins, missing multi-factor authentication and long-lived keys.
# AWS: IAM credential report (MFA, password and key usage per user)
aws iam generate-credential-report
aws iam get-credential-report --query Content --output text | base64 --decode > creds.csv
# Linux: every authorized_keys file and the keys in it
sudo find / -xdev -path '*/.ssh/authorized_keys' -exec sh -c 'echo "== $1"; cat "$1"' _ {} \;
# Effective SSH settings, not just what the config file says
sudo sshd -T | grep -Ei '^(permitrootlogin|passwordauthentication|pubkeyauthentication) 'The cloud root user or global administrator has MFA and no access keys. Every person has a named login; no shared admin accounts. Access keys older than 90 days or unused for 90 days are flagged. Every SSH key can be matched to a current person or system. Database users are per application, not one superuser everywhere. At least two people can reach the registrar, DNS and cloud accounts. 3. Servers, network and TLS Check what is exposed from outside first, then what is running inside. Scan only addresses you own or have written permission to test. An outside scan often finds a database or admin panel that was opened 'temporarily' and never closed.
# From outside: which ports answer on your public IP
nmap -Pn --top-ports 1000 203.0.113.10
# On the server: what is listening, and which process owns it
sudo ss -tlnp
# Pending updates and whether a reboot is outstanding
apt list --upgradable 2>/dev/null | tail -n +2 | wc -l
ls /var/run/reboot-required 2>/dev/null
# Certificate expiry date
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -enddate
# Broad hardening review
sudo lynis audit system --quickFlag anything past end of support. As of late 2026 that includes Ubuntu 20.04 (standard support ended in May 2025), PostgreSQL 13 (ended November 2025) and Node.js 20 (ended April 2026). Unsupported software stops getting security fixes, so it should appear near the top of the report even if nothing is broken today. For TLS configuration in depth, testssl.sh against each public hostname reports protocol versions, weak ciphers and chain problems.
4. Backups, monitoring and single points of failure The backup question is not whether backups exist. It is when one was last restored, how long it took, and whether the copy lives somewhere a compromised server cannot delete. If nobody can answer, the finding is 'backups unverified', and that is a high-severity item.
Every database, uploaded files and configuration are backed up, and the list matches the inventory. Copies are stored off the server, ideally in a different account or provider, with deletion restricted. A restore has been tested in the last three months, and the time it took is written down. Uptime checks cover each public service from outside your own network. Alerts exist for disk space, certificate expiry and failed backups, and they reach a person, not an unread inbox. Logs are kept long enough to investigate an incident found a few weeks late. You know which single server, disk or person would take the service down if lost. 5. Release process, secrets and containers Ask someone to walk you through the last deployment. If it ran from a laptop, or only one person knows how, that is a finding. Check where secrets live: in a secrets manager or CI secret store is fine; in the repository, a wiki page or a chat message is not.
# Secrets committed anywhere in Git history
gitleaks git -v .
# Known vulnerabilities in a production image
trivy image --severity HIGH,CRITICAL registry.example.com/api:prod
# Misconfigurations in Dockerfiles, Compose and Kubernetes manifests
trivy config .Deploys run from CI, and a bad release can be rolled back by one documented step. Builds are reproducible: pinned base images and lock files committed. Containers do not run as root unless there is a stated reason. Production secrets are different from staging secrets, and rotating one is a documented task. Database migrations run as part of the release, not by hand on the server. Ranking findings and writing the report An audit that produces eighty equal findings gets ignored. Give each one a severity based on two questions: how bad would it be if this went wrong, and how likely is it? Then sort them into three groups.
Fix this week: exposed databases or admin panels, root keys without MFA, ex-staff with access, unverified backups, certificates or domains close to expiry. Fix this quarter: end-of-support operating systems and runtimes, missing alerts, manual deploys, secrets in Git history, single points of failure. Accept or plan: items where the fix costs more than the risk. Write down who accepted it and when to revisit. For each finding, the report should say what was found, the evidence, why it matters in plain language, the recommended fix and a rough effort. Add a one-page summary at the top for whoever approves the work. Then book a follow-up in three months to check what was closed. Running the same checklist every year turns the audit from a one-off scare into a measure of progress.
When to bring in outside help A self-audit is worth doing, but it has a blind spot: the people who built a system tend to check what they already know about. An outside review makes sense when you need the result for a customer, investor or insurer, when the person who set everything up has left, when you are about to migrate or scale, or when the inventory alone turns up more than you expected.
Whether you run it yourself or hand it over, the order of work is the same:
Agree scope and read-only access before anyone starts. Inventory every region, account, domain and certificate. Check access, exposure, patch levels and end-of-support software. Prove a backup restores, and time it. Review deploys, secrets and images. Rank findings into this week, this quarter and accepted, with evidence for each. Revoke audit access when you are done, and repeat the audit yearly.
Infigini IT Services · 11 Kanwali Road, Dehradun 248001, India · info@infigini.com · +91 95684 87789