Falco on Ubuntu 24.04 LTS on Azure
This image ships Falco 0.44.1 on Ubuntu 24.04 LTS, watching every syscall on the machine from the first boot of every deployed virtual machine. Falco is installed unmodified from the Falco project's own signed apt repository, so the engine stays patchable through the normal apt path for the life of the release.
Falco is the graduated Cloud Native Computing Foundation project for runtime threat detection. It taps the kernel's syscall stream, enriches each event with process, user and file context, and evaluates the result against a behavioural rule set. When something matches, it emits an alert describing what happened, which process did it, and as whom.
The distinction that matters is between behaviour and signatures. A vulnerability scanner tells you what could be exploited. A network sensor tells you what reached the machine. Falco tells you what a process is doing right now on a host that is already running, and because its rules describe behaviour rather than a catalogue of known-bad files, they keep working against tooling nobody has catalogued yet.
What this image detects out of the box
The image ships Falco's bundled default rule set: 25 rules covering a large part of the way real intrusions look from the inside. A sample:
grep '^- rule:' /etc/falco/falco_rules.yaml | sed 's/^- rule: / /' | head -8
Directory traversal monitored file read
Read sensitive file trusted after startup
Read sensitive file untrusted
Run shell untrusted
System user interactive
Terminal shell in container
Contact K8S API Server From Container
Netcat Remote Code Execution in Container
Others cover kernel module injection, ptrace attaching to a running process, a new binary being written and immediately executed, private keys or cloud credentials being searched for, log files being cleared, and container escape attempts. Every alert carries MITRE ATT&CK tags, so findings map onto a framework your team probably already uses.

What makes this image different
The driver is modern eBPF, never a kernel module. This is the single most consequential decision in the image, and it is the one most likely to be got wrong. Falco needs a kernel side event source, and it offers two: a kernel module built through DKMS, or a modern eBPF probe. The module is compiled against the running kernel, which means the first time your machine installs a new kernel through unattended upgrades and reboots, the module is gone or fails to rebuild, and the sensor silently stops seeing events while still reporting healthy. This image ships the modern eBPF driver instead. It is compiled once and relocated at load time against the running kernel's own type information, so it needs no compiler, no kernel headers and no DKMS, and it survives kernel upgrades untouched. No kernel module is ever built or loaded on this image, and that is verified at build time and again on a freshly captured machine.
There are no credentials anywhere in this image, because the product has none. Falco has no login, no web interface and no user database. Its only HTTP surface is an embedded webserver serving liveness and version endpoints, and this image binds that webserver to the loopback interface only, so it is not reachable from your virtual network at all. There is no default password to rotate and nothing to leak. Administration is over SSH with the key you supplied at deployment.
Alerts actually reach somewhere you can read them. Falco's systemd unit discards standard output, and file output is disabled in the packaged default, so a stock install can run perfectly while recording nothing anywhere you would ever look. This image enables JSON file output to a root only alert log, unbuffered, so alerts land the moment they fire.
The engine refuses to start on a machine that has not been checked. The captured image was built on one kernel and boots on whatever your virtual machine runs. A first boot service verifies that this kernel can actually host the eBPF probe, that the configuration is loopback bound and accepted by the engine itself, and that the alert log is writable, before the engine is allowed to start. Two independent mechanisms enforce it, and both are tested to fail closed rather than assumed to work.
No build time alert history survives. A runtime security sensor's log is a record of everything that ran on the machine. The build of this image is torn down before capture: the alert log, the first boot marker, the instance note and all rule update state are removed, and the packaged rule set is restored verbatim.
1. Deploy the virtual machine
In the Azure portal, search the Marketplace for Falco on Ubuntu 24.04 LTS by cloudimg and select Create. Choose your subscription, resource group and region, set the authentication type to SSH public key and the username to azureuser, then review and create.
To deploy from the Azure CLI instead:
az vm create \
--resource-group my-resource-group \
--name my-falco-vm \
--image cloudimg:falco-ubuntu-24-04:falco-ubuntu-24-04:latest \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
Falco needs no inbound port of its own, so nothing beyond SSH is opened. The engine's health endpoint is bound to the loopback interface and is deliberately not reachable from the network.
Standard_B2s is sufficient for the engine itself. Falco's cost is proportional to syscall volume rather than to the size of the machine, so size the virtual machine for the workload you are protecting, not for Falco.
2. Connect and confirm the engine is running
ssh azureuser@<vm-ip>
Confirm the engine is up:
systemctl is-active falco-modern-bpf.service
active
Check the health endpoint. It answers on the loopback interface only:
curl -s http://127.0.0.1:8765/healthz
{"status": "ok"}
Confirm the versions of the engine, its rules engine and its driver:
falco --version 2>/dev/null | python3 -c 'import sys,json;d=json.load(sys.stdin);print("falco",d["falco_version"],"| engine",d["engine_version_semver"],"| driver",d["default_driver_version"])'
falco 0.44.1 | engine 0.62.0 | driver 10.2.0+driver
Note on readiness. The health endpoint answers within about a second of the service starting, because it reports on the webserver rather than on the probe. The eBPF probe takes a few seconds longer to attach. If you are scripting a readiness check, wait for the engine's own log line rather than for the health endpoint, as shown in the next section.
3. Confirm the driver is modern eBPF
This is the check worth doing on any Falco deployment, because a machine running the kernel module driver looks identical until the day it stops working.
The engine announces which probe it opened:
sudo journalctl -u falco-modern-bpf.service -n 500 --no-pager | grep -E "Opening 'syscall'|Enabled event sources" | sed 's/^.*falco\[[0-9]*\]: //' | tail -2
Enabled event sources: syscall
Opening 'syscall' source with modern BPF probe.
The kernel exposes the type information the probe relocates against:
ls -l /sys/kernel/btf/vmlinux
No Falco kernel module is loaded, and there is no mechanism on the machine to build one:
lsmod | awk '{print $1}' | grep -cE '^(falco|scap)' || true
0
(grep -c prints 0 and exits non zero when it finds nothing, which is the answer you want here, so the || true keeps the command's exit status honest in a script.)

4. See a real detection
Falco writes alerts as JSON, one object per line, to a root only log at /var/log/falco/events.log. To watch alerts arrive live, run sudo tail -f /var/log/falco/events.log in a second session and leave it open.
Now trigger a rule deliberately. Reading the shadow password file is a benign stand in for credential theft, and it matches the shipped rule Read sensitive file untrusted:
sudo cat /etc/shadow > /dev/null
An alert appears within a second or two:
sudo grep -F 'command=cat /etc/shadow' /var/log/falco/events.log | tail -1 | python3 -m json.tool | head -30
The alert names the rule, its priority, the file that was read, the process and its command line, the parent process, and the user. That is the whole detection chain, from a syscall in the kernel to a structured record you can act on:
"rule": "Read sensitive file untrusted",
"priority": "Warning",
"source": "syscall",
"tags": ["T1555", "container", "filesystem", "host", "maturity_stable", "mitre_credential_access"],
"output_fields": {
"fd.name": "/etc/shadow",
"proc.name": "cat",
"proc.cmdline": "cat /etc/shadow",
"proc.pname": "bash",
"user.name": "root",
"user.uid": 0
}
Now the control that shows the rule is keyed on the file rather than on the command. Read a harmless file with the same binary, from the same shell:
sudo cat /etc/hostname > /dev/null; sleep 6; sudo grep -cF 'command=cat /etc/hostname' /var/log/falco/events.log || echo 0
0
No alert. The rule fired on reading a credentials file, not on running cat.

5. Send alerts somewhere useful
The alert log is newline delimited JSON, which every log shipper understands with no parsing configuration. Point your existing agent at /var/log/falco/events.log and you are done.
To check what a shipper would see, or to filter interactively:
sudo tail -20 /var/log/falco/events.log | python3 -c 'import sys,json
for line in sys.stdin:
e = json.loads(line)
print(e["time"], e["priority"], "|", e["rule"])'
To count alerts by rule over the whole log:
sudo cat /var/log/falco/events.log | python3 -c 'import sys,json,collections
c = collections.Counter()
for line in sys.stdin:
c[json.loads(line)["rule"]] += 1
for rule, n in c.most_common():
print(f"{n:6} {rule}")'
Falco can also emit alerts over gRPC, to a program on standard input, or to an HTTP endpoint. Those outputs are configured in the same drop in file described in section 7. If you want fan out to Slack, Teams, PagerDuty, S3 or a SIEM without writing an integration, the Falco project's companion tool Falcosidekick consumes the HTTP output and forwards to more than fifty destinations.
6. Tune the rules for your workload
Every environment produces some benign activity that looks suspicious in the abstract. Falco is designed for this: rules are tuned in your own file, never by editing the shipped rule set.
Add exceptions and your own rules to /etc/falco/falco_rules.local.yaml, which the engine loads after the bundled rules and which is never overwritten by an update. For example, to stop a backup agent triggering the sensitive file rule, append a macro that describes it and add it to the rule's exceptions.
Validate any change before restarting, so a typo cannot take the sensor down:
sudo falco --dry-run
Then reload the engine in place:
sudo systemctl reload falco-modern-bpf.service
Rules can also be enabled or disabled wholesale by name or by tag through the rules configuration key. Falco's rule reference at falco.org documents every shipped rule, its condition and its tuning options.
7. Configuration and how to change it safely
All cloudimg configuration for this image lives in a single drop in file:
grep -vE '^\s*#|^$' /etc/falco/config.d/10-cloudimg.yaml
webserver:
enabled: true
threadiness: 0
listen_port: 8765
listen_address: 127.0.0.1
k8s_healthz_endpoint: /healthz
ssl_enabled: false
file_output:
enabled: true
keep_alive: false
filename: /var/log/falco/events.log
json_output: true
json_include_output_property: true
buffered_outputs: false
Change configuration by adding files to /etc/falco/config.d/, not by editing /etc/falco/falco.yaml. The main configuration file is a packaged file, and editing it in place means every future upgrade of Falco stops to ask an administrator which version to keep. On a machine that patches itself unattended there is nobody to answer, so the upgrade stalls and the security engine quietly stops being patched. Files in config.d are loaded in name order after the defaults and are never touched by an upgrade, which is why this image leaves the packaged files byte identical.
Take care before changing webserver.listen_address. The health endpoint has no authentication, because there is nothing on it worth authenticating. Binding it to 0.0.0.0 exposes an unauthenticated endpoint to your virtual network. This image refuses to start the engine if that binding is changed, and you will see exactly why in the service log.
8. Keeping detections current
Threat detection content ages. Falco ships a companion service that pulls the current published rule set and reloads the engine, so your detections do not freeze on the day the image was built:
systemctl is-active falcoctl-artifact-follow.service
active
Note that this service reports as disabled if you ask systemctl is-enabled. That is correct and not a problem: it has no [Install] section of its own because the engine's own unit pulls it in with Wants=, so it starts whenever Falco starts. Check is-active, not is-enabled.
To see what it is following:
sudo journalctl -u falcoctl-artifact-follow.service -n 6 --no-pager
It needs outbound HTTPS to the container registry that publishes the rules. If your machine has no outbound internet access, the engine runs on its bundled rules indefinitely, which is a supported configuration: you can also copy rule files in yourself and reload.
The engine itself is patched through the normal apt path. It is installed from the Falco project's signed repository, and that repository is wired into this machine's unattended upgrades configuration, so security updates to Falco arrive the same way updates to the rest of the operating system do:
apt-cache policy falco | sed -n '1,4p'
Nothing is held back:
apt-mark showhold || echo "(empty)"
9. Security posture of this image
Read the per instance note written on this machine's own first boot:
sudo head -20 /root/falco-instance.txt
It records the engine version, the driver in use, the kernel, the number of rules loaded, and where alerts are written, and it states plainly that this product has no credentials.
The alert log is readable only by root:
stat -c '%a %U:%G %n' /var/log/falco/events.log
600 root:root /var/log/falco/events.log
Nothing but SSH listens on a network address. The Falco health endpoint is on the loopback interface, alongside the local DNS stub resolver:
ss -Hltn | awk '{print $4}' | sort -u

10. Where Falco fits
Falco is a host runtime sensor. It sees everything that happens on the machine it runs on, and nothing that happens on any other machine. That makes it complementary to, rather than a replacement for, the other controls you are likely running:
| Control | Answers |
|---|---|
| Vulnerability scanning | What on this machine could be exploited |
| Network intrusion detection | What reached this machine over the wire |
| Falco | What a process on this machine is actually doing |
Deploy it on the workloads whose compromise would matter most: jump boxes and bastions, public facing application servers, build agents, and any host handling credentials or customer data. On a fleet, run it on every machine and ship the alerts to one place, since the value compounds when you can compare behaviour across hosts.
Support
Every cloudimg image is backed by 24/7 support. If anything in this guide does not behave as described on your deployment, contact support@cloudimg.co.uk with the output of sudo head -20 /root/falco-instance.txt and we will pick it up from there.