When I run updates, my biggest fear isn’t that something will break. It’s that something will fail or change silently, and I will only find out days, weeks or months later.
Loud failures are the easy ones. When a server crashes or an app goes offline, a myriad of systems like Grafana or PRTG alert me. When an app opens a new port, or moves to another one because its default was taken, firewalls at the host and network level usually limit the damage. But when an app flips a default setting, moves its config data somewhere else, or one of its components quietly fails to install, nothing catches it.
I ran into that last scenario with a Harbor deployment. During an update I forgot to pass the --with-trivy flag to the installer,
so the vulnerability scanner was never installed. From then on, pushed images silently skipped SBOM generation and vulnerability
scanning. Every dashboard was green. I only found out by accident, when I pushed a deliberately vulnerable image for a test and
watched it sail through.
That is when I knew I needed a way to declare the state I want a system or app to be in, and then validate it every time I change that system. I started with a handful of Bash scripts, but they quickly became cumbersome to manage and extend.
That is how ref*point started. You take a reference point: a declaration of how a system or app should be configured. Then you
validate against it on every run. It is written in Go, so it is fast and ships as a single binary. Profiles are written in HashiCorp’s
HCL, so they are easy to read and familiar to anyone who has touched Terraform or OpenTofu.
InstallationSection titled Installation
ref*point ships as a single binary, with packages for the most common platforms on the
GitHub releases page. Pick your platform below, and set RP_VER to the
version you want to install.
RP_VER=1.0.0curl -LO "https://github.com/refpoint-dev/refpoint/releases/download/v${RP_VER}/refpoint_${RP_VER}_linux_amd64.deb"sudo apt install "./refpoint_${RP_VER}_linux_amd64.deb"RP_VER=1.0.0curl -LO "https://github.com/refpoint-dev/refpoint/releases/download/v${RP_VER}/refpoint_${RP_VER}_linux_amd64.rpm"sudo dnf install "./refpoint_${RP_VER}_linux_amd64.rpm"RP_VER=1.0.0curl -LO "https://github.com/refpoint-dev/refpoint/releases/download/v${RP_VER}/refpoint_${RP_VER}_darwin_arm64.tar.gz"tar -xzf "refpoint_${RP_VER}_darwin_arm64.tar.gz"sudo mv refpoint /usr/local/bin/$RP_VER = "1.0.0"Invoke-WebRequest -Uri "https://github.com/refpoint-dev/refpoint/releases/download/v${RP_VER}/refpoint_${RP_VER}_windows_amd64.zip" -OutFile "refpoint_${RP_VER}_windows_amd64.zip"Expand-Archive -Path "refpoint_${RP_VER}_windows_amd64.zip" -DestinationPath "$env:LOCALAPPDATA\refpoint"Then add %LOCALAPPDATA%\refpoint to your PATH.
Check that it works:
refpoint versionWriting your first profileSection titled Writing%20your%20first%20profile
A profile is a collection of controls, where each control is one expectation about a system. ref*point provides an init command
that bootstraps a new profile with an example control:
refpoint init linux-baseline --title "Linux Baseline" --author "Ops Team"This creates the folder structure and the minimum required files: profile.rpp, which holds the metadata used to manage the
profile, and an example control.
linux-baseline/├── profile.rpp└── controls/ └── example.rpcTo run the profile against the local system, use the run command:
refpoint run linux-baselineAdding a real controlSection titled Adding%20a%20real%20control
Now let’s add a control that actually matters. In the controls folder, create a file called ssh.rpc (.rpc stands for
refpoint controls) with the following content:
control "ssh-01" { title = "SSH root login is disabled" description = "Direct root login over SSH removes accountability." impact = 0.9 remediation = "Set PermitRootLogin no in /etc/ssh/sshd_config and reload sshd."
platform = ["linux"]
tags = { category = "ssh" }
only_if "package" { name = "openssh-server" installed = true }
check "root-login" "sshd_config" { option "PermitRootLogin" { value = "no" } }}This control verifies that SSH doesn’t allow direct login as root. Forcing people to log in with their own account first means
the audit log records who actually did what. If anyone can log in directly as root, it becomes very hard to tell whether a server
was compromised, or who ran the command that destabilized it.
A few things worth pointing out:
impactis a score from 0 to 1 that tells you how much a failure matters, so you can triage a long report quickly.platformandonly_ifkeep the control from running where it doesn’t make sense. Ifopenssh-serverisn’t installed, the control is skipped instead of reported as a failure.remediationis the fix, written down next to the check. More on why that matters below.
Controls in ref*point are idempotent and read-only, with one exception: the command resource. It exists for cases where
ref*point doesn’t have a dedicated resource yet, and it runs whatever command you give it. A carelessly crafted command can
write to the target system, so review what your profiles are allowed to execute, especially profiles you didn’t write yourself.
Validating the profileSection titled Validating%20the%20profile
ref*point has a built-in profile validator. refpoint check verifies that the profile has all the required fields and that every
control and resource is properly configured:
refpoint check linux-baselineRunning the above command will result in the following output:
Profile "linux-baseline" is valid (2 controls loaded)Run it before committing profile changes, or better, as a step in the CI pipeline of your profiles repository, so a broken profile never reaches the servers.
Running the profile against remote systemsSection titled Running%20the%20profile%20against%20remote%20systems
Running locally is useful while writing a profile, but the real value comes from running the same profile against your fleet.
ref*point connects over SSH to Unix-like systems and over WinRM to Windows machines. SSH to Windows should work too, but I haven’t
tested it yet.
For larger profiles, like the ones I’ve shared on GitHub that covers both Debian and
Red Hat based systems, I recommend doing a dry run first. ref*point identifies the target system and shows which controls would run,
without running them:
refpoint 0.1.0config loaded: /home/ops.cafe/.refpoint/config.tomlprofiles run: /home/ops.cafe/profiles/linux-baseline
Dry run — execution plan only, no checks are executed
Profile: Linux Baseline (v0.1.0)════════════════════════════════════════════════════════════Target: [email protected] · linux/ubuntu════════════════════════════════════════════════════════════ ▶ run [example-01] Example control ▶ run [ssh-01] SSH root login is disabled — only_if package "openssh-server" decided at run time──────────────────────────────────────────────────────────── 2 to run (1 conditional)Note: I used the
rootuser above only to keep the example short. In practice, connect with a dedicated, least-privileged user whenever possible.
Reading the resultsSection titled Reading%20the%20results
When the profile runs, ref*point reports every control as passed, failed or skipped. For a failed control, it shows what it expected,
what it actually found and, if the control has one, the remediation.
refpoint 1.0.0config loaded: /home/ops.cafe/.refpoint/config.tomlprofiles run: /home/ops.cafe/profiles/linux-baseline
════════════════════════════════════════════════════════════Target: [email protected] · Linux Baseline v0.1.0════════════════════════════════════════════════════════════ ✓ [example-01] Example control impact: 0.5 ✓ file-exists[file: /etc/hostname]
✗ [ssh-01] SSH root login is disabled impact: 0.9 ✗ root-login[sshd_config] ✗ option[permitrootlogin]: got "yes", want "no" remediation: Set PermitRootLogin no in /etc/ssh/sshd_config and reload sshd.
════════════════════════════════════════════════════════════Summary════════════════════════════════════════════════════════════Linux Baseline v0.1.0 ✗ [email protected] 50.0% 1/2 controls passed · 1 failed════════════════════════════════════════════════════════════Average compliance score: 35.7%The remediation field pays off most in a team. The controls double as documentation: a senior engineer can write a control once,
together with the steps to fix it, and then anyone on the team can run the profile and bring a system back in line when it drifts.
Besides the terminal report, ref*point can produce JSON or JUnit XML. That makes it easy to feed results into a CI pipeline or
any tool that already understands test reports.
Back to Harbor: making updates boringSection titled Back%20to%20Harbor%3A%20making%20updates%20boring
This is the workflow that would have saved me with Harbor:
- Describe the expected state. Write a profile for the app that covers what matters, not only that the service is up. For Harbor that includes: the Trivy scanner is installed and registered as the default scanner, scan-on-push is enabled for the projects that need it, and the expected ports are listening.
- Run it before the update. A clean baseline tells you that any failure afterwards was caused by the update, not by something that was already broken.
- Update.
- Run it again. Anything that changed silently now shows up as a failed control, with the fix right next to it.
refpoint 1.0.0config loaded: /home/ops.cafe/.refpoint/config.tomlprofiles run: /home/ops.cafe/profiles/harbor-health
════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
...
✓ [harbor-health-09] Log collector container is running and uses the expected goharbor image impact: 0.7 ✓ running[command: docker inspect -f '{{.State.Running}}' 'harbor-log'] ✓ image[command: docker inspect -f '{{.Config.Image}}' 'harbor-log']
✓ [harbor-health-10] Trivy adapter container is running and uses the expected goharbor image impact: 0.7 ✓ running[command: docker inspect -f '{{.State.Running}}' 'trivy-adapter'] ✓ image[command: docker inspect -f '{{.Config.Image}}' 'trivy-adapter']
...
✓ [harbor-health-12] All components run the same release impact: 0.5 ✓ single-tag[command: docker ps --format '{{.Names}}' | grep -xE '(nginx|harbor-core|harbor-p…]
✓ [harbor-health-13] Health endpoint reports the system and every core component healthy impact: 0.8 ✓ fetch[command: curl -ksS -o '/tmp/refpoint-harbor-health.json' -w '%{http_code}' 'http…] ✓ components[json: /tmp/refpoint-harbor-health.json]
✓ [harbor-health-14] Health endpoint reports the Trivy scanner healthy impact: 0.6 ✓ fetch[command: curl -ksS -o '/tmp/refpoint-harbor-health.json' -w '%{http_code}' 'http…] ✓ trivy[json: /tmp/refpoint-harbor-health.json]
════════════════════════════════════════════════════════════Summary════════════════════════════════════════════════════════════Harbor Health and Image Check 1.0.0════════════════════════════════════════════════════════════Average compliance score: 100.0%Had I run this after that Harbor update, the missing scanner would have been one red line in the report, instead of weeks of unscanned images.
ConclusionSection titled Conclusion
ref*point has become an invaluable tool for me as the infrastructure I manage keeps growing. I no longer fear unattended updates,
skipped steps or changes that slip past me. It also makes migrations much less risky. Take an older application stuck on an OS that
no longer receives security updates: I can capture how it is configured today, rebuild it on a new machine, and run the same profile
to confirm nothing got lost in the move.
It also changed when I think about validation. I can set expectations before a system is even deployed: read the app’s documentation, write a profile for it, and wire that profile into the tools I deploy with, be it Ansible or OpenTofu/Terraform.
Finally, it lets me harden systems gradually without fear of breaking them. I capture a profile of the current, working state first, then add a new security layer and confirm that everything that worked before still works. That makes my work faster and a lot less error-prone.
If you give ref*point a try, I’d love to hear which controls you write first.