Writing
Notes from the canopy.
Observations on DevOps tooling, observability, and the small gaps in the ecosystem worth filling — written for the engineers who hit them.
20 posts and counting.
-
OpsCanopy 7 min read
Learn DevOps in 90 Days: the free, incident-first path from developer to DevOps engineer
Why we built Mission: 90 Days DevOps — a free day-by-day path from Linux to Kubernetes with playable incident missions. The full plan, the design decisions, and the honest tradeoffs.
- devops
- career
- learning
-
OpsCanopy 12 min read
Why Isnt My Alert Reaching the Right Receiver? Debugging Alertmanager Routing
Alerts going to the wrong receiver, or no receiver at all? Debug Alertmanager routing — first-match-wins, missing continue, matcher regex and catch-all defaults.
- alertmanager
- observability
- alerting
-
OpsCanopy 10 min read
How Alertmanager Routing Works: Matchers, continue, and the Route Tree
A clear mental model for Alertmanager routing — the route tree, matchers, the continue flag, grouping and receiver inheritance — so you know exactly where an alert goes.
- alertmanager
- observability
- alerting
-
OpsCanopy 9 min read
Why Did Prometheus Drop My Target? Debugging relabel_configs
A target vanished or a label disappeared after relabeling. Debug Prometheus relabel_configs vs metric_relabel_configs, regex anchoring and keep/drop logic.
- prometheus
- observability
- relabeling
-
OpsCanopy 8 min read
Why Your GitHub Actions "if" Condition Always Runs (and How to Fix It)
Your GitHub Actions if condition always runs true? It's the literal-text footgun: any text outside ${{ }} coerces to a truthy string. Here's the cause and the fix.
- github-actions
- ci-cd
-
OpsCanopy 7 min read
Why Your GitHub Actions Workflow Didn't Trigger: branches, tags & paths Filters Explained
Why your GitHub Actions workflow didn't trigger: branch name mismatch, the AND-semantics of branches + paths filters, the ** glob requirement, paths-ignore on pull_request, and the fixes.
- github-actions
- ci-cd
- debugging
-
OpsCanopy 10 min read
Prometheus relabel_configs Explained: A Practical Guide
Understand Prometheus relabel_configs end to end — source_labels, regex, replacement and every action (replace, keep, drop, labelmap, hashmod) — with copy-paste recipes.
- prometheus
- observability
- relabeling
-
OpsCanopy 9 min read
7 Common .gitlab-ci.yml Mistakes (and How to Catch Them)
The .gitlab-ci.yml mistakes that turn pipelines red: undefined stages, jobs without scripts, broken needs and rules, anchor misuse — each with a fix you can copy.
- gitlab-ci
- ci-cd
- yaml
-
OpsCanopy 9 min read
How to Validate .gitlab-ci.yml Before You Push
Stop pushing broken pipelines. Validate your .gitlab-ci.yml for YAML and structural errors in your browser — before the commit, not after the red pipeline.
- gitlab-ci
- ci-cd
- yaml
-
OpsCanopy 10 min read
docker run vs Docker Compose: A Practical Migration Guide
When to use docker run, when to switch to Docker Compose, and how to convert between them in both directions — with volumes, networks and reproducibility handled right.
- docker
- docker-compose
- containers
-
OpsCanopy 10 min read
How to Convert a docker run Command to docker-compose.yml
Convert any docker run command to a docker-compose.yml service, flag by flag — ports, volumes, environment, restart and more. A practical, copy-paste guide.
- docker
- docker-compose
- containers
-
OpsCanopy 5 min read
How to read a PromQL query
A PromQL query is read from the inside out, not left to right. Learn the four layers — selectors, ranges, functions and aggregations — so you can decode any Prometheus expression at a glance.
- promql
- prometheus
- observability
-
OpsCanopy 5 min read
LogQL vs PromQL: the same query in both languages
LogQL borrows PromQL’s shape but starts from log lines, not metrics. Here is how the two query languages line up, where they translate cleanly, and where they simply don’t.
- logql
- promql
- observability
-
OpsCanopy 6 min read
Stop shipping a stale .env.example
Your .env.example is documentation that silently rots. Here is why env drift breaks onboarding and deploys, how to detect missing and unused keys, and how to keep the example file honest.
- configuration
- developer-experience
- twelve-factor
-
OpsCanopy 5 min read
Writing robust regular expressions for log lines
A practical guide to building regexes that parse log lines reliably — anchoring, capture groups, escaping, greediness and the failure modes that bite you in production.
- regex
- logs
- parsing
-
OpsCanopy 5 min read
Migrating from cron to systemd timers
A practical guide to converting crontab entries into systemd .timer and .service units — OnCalendar syntax, logging, randomized delays, catch-up runs, and the gotchas that bite during migration.
- systemd
- cron
- linux
-
OpsCanopy 6 min read
Reading cron expressions: a field-by-field guide
A practical, field-by-field guide to reading cron expressions — the five time fields, ranges, steps, lists and @macros — plus the gotchas that make schedules fire when you least expect.
- cron
- scheduling
- devops
-
OpsCanopy 6 min read
The GitHub Actions security mistakes linters miss
YAML validators catch syntax, not exposure. Here are the five high-impact GitHub Actions misconfigurations — pull_request_target, script injection, unpinned actions, broad GITHUB_TOKEN scopes, and curl|bash — with the bad pattern and the fix for each.
- github-actions
- security
- ci-cd
-
OpsCanopy 5 min read
One CVE, four ignore files: unifying Trivy, Grype, Snyk and osv-scanner
A single triaged CVE suppression has to be re-encoded in .trivyignore, .grype.yaml, .snyk and osv-scanner.toml — each with a different shape. Here is the same suppression in all four formats, what maps cleanly, and what is lossy.
- security
- vulnerability-management
- devops
-
OpsCanopy 5 min read
Unit Testing Loki Alert Rules: the gap promtool leaves
Prometheus has promtool test rules. Loki has nothing equivalent. Here is why testing LogQL alert rules matters, what a Loki rule unit test should look like, and how to close the gap today.
- loki
- observability
- testing