<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>OpsCanopy Blog</title>
    <link>https://opscanopy.com/blog/</link>
    <description>DevOps articles, guides, and tutorials from the OpsCanopy team — delivered right to your reader.</description>
    <language>en</language>
    <lastBuildDate>Sun, 12 Jul 2026 00:00:00 GMT</lastBuildDate>
    <atom:link href="https://opscanopy.com/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Learn DevOps in 90 Days: the free, incident-first path from developer to DevOps engineer</title>
      <link>https://opscanopy.com/blog/learn-devops-in-90-days/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/learn-devops-in-90-days/</guid>
      <description>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.</description>
      <pubDate>Sun, 12 Jul 2026 00:00:00 GMT</pubDate>
      <category>devops</category>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>Why Isnt My Alert Reaching the Right Receiver? Debugging Alertmanager Routing</title>
      <link>https://opscanopy.com/blog/debug-alertmanager-routing/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/debug-alertmanager-routing/</guid>
      <description>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.</description>
      <pubDate>Thu, 18 Jun 2026 00:00:00 GMT</pubDate>
      <category>alertmanager</category>
      <category>observability</category>
      <category>alerting</category>
    </item>
    <item>
      <title>How Alertmanager Routing Works: Matchers, continue, and the Route Tree</title>
      <link>https://opscanopy.com/blog/how-alertmanager-routing-works/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/how-alertmanager-routing-works/</guid>
      <description>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.</description>
      <pubDate>Wed, 17 Jun 2026 00:00:00 GMT</pubDate>
      <category>alertmanager</category>
      <category>observability</category>
      <category>alerting</category>
    </item>
    <item>
      <title>Why Did Prometheus Drop My Target? Debugging relabel_configs</title>
      <link>https://opscanopy.com/blog/debug-prometheus-relabeling/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/debug-prometheus-relabeling/</guid>
      <description>A target vanished or a label disappeared after relabeling. Debug Prometheus relabel_configs vs metric_relabel_configs, regex anchoring and keep/drop logic.</description>
      <pubDate>Tue, 16 Jun 2026 00:00:00 GMT</pubDate>
      <category>prometheus</category>
      <category>observability</category>
      <category>relabeling</category>
    </item>
    <item>
      <title>Why Your GitHub Actions &quot;if&quot; Condition Always Runs (and How to Fix It)</title>
      <link>https://opscanopy.com/blog/github-actions-if-condition-always-true/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/github-actions-if-condition-always-true/</guid>
      <description>Your GitHub Actions if condition always runs true? It&apos;s the literal-text footgun: any text outside ${{ }} coerces to a truthy string. Here&apos;s the cause and the fix.</description>
      <pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate>
      <category>github-actions</category>
      <category>ci-cd</category>
    </item>
    <item>
      <title>Why Your GitHub Actions Workflow Didn&apos;t Trigger: branches, tags &amp; paths Filters Explained</title>
      <link>https://opscanopy.com/blog/github-actions-workflow-not-triggering-filters/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/github-actions-workflow-not-triggering-filters/</guid>
      <description>Why your GitHub Actions workflow didn&apos;t trigger: branch name mismatch, the AND-semantics of branches + paths filters, the ** glob requirement, paths-ignore on pull_request, and the fixes.</description>
      <pubDate>Sun, 14 Jun 2026 00:00:00 GMT</pubDate>
      <category>github-actions</category>
      <category>ci-cd</category>
      <category>debugging</category>
    </item>
    <item>
      <title>Prometheus relabel_configs Explained: A Practical Guide</title>
      <link>https://opscanopy.com/blog/prometheus-relabel-configs-explained/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/prometheus-relabel-configs-explained/</guid>
      <description>Understand Prometheus relabel_configs end to end — source_labels, regex, replacement and every action (replace, keep, drop, labelmap, hashmod) — with copy-paste recipes.</description>
      <pubDate>Sat, 13 Jun 2026 00:00:00 GMT</pubDate>
      <category>prometheus</category>
      <category>observability</category>
      <category>relabeling</category>
    </item>
    <item>
      <title>7 Common .gitlab-ci.yml Mistakes (and How to Catch Them)</title>
      <link>https://opscanopy.com/blog/common-gitlab-ci-mistakes/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/common-gitlab-ci-mistakes/</guid>
      <description>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.</description>
      <pubDate>Fri, 12 Jun 2026 00:00:00 GMT</pubDate>
      <category>gitlab-ci</category>
      <category>ci-cd</category>
      <category>yaml</category>
    </item>
    <item>
      <title>How to Validate .gitlab-ci.yml Before You Push</title>
      <link>https://opscanopy.com/blog/validate-gitlab-ci-yml/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/validate-gitlab-ci-yml/</guid>
      <description>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.</description>
      <pubDate>Thu, 11 Jun 2026 00:00:00 GMT</pubDate>
      <category>gitlab-ci</category>
      <category>ci-cd</category>
      <category>yaml</category>
    </item>
    <item>
      <title>docker run vs Docker Compose: A Practical Migration Guide</title>
      <link>https://opscanopy.com/blog/docker-run-vs-compose/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/docker-run-vs-compose/</guid>
      <description>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.</description>
      <pubDate>Wed, 10 Jun 2026 00:00:00 GMT</pubDate>
      <category>docker</category>
      <category>docker-compose</category>
      <category>containers</category>
    </item>
    <item>
      <title>How to Convert a docker run Command to docker-compose.yml</title>
      <link>https://opscanopy.com/blog/convert-docker-run-to-compose/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/convert-docker-run-to-compose/</guid>
      <description>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.</description>
      <pubDate>Tue, 09 Jun 2026 00:00:00 GMT</pubDate>
      <category>docker</category>
      <category>docker-compose</category>
      <category>containers</category>
    </item>
    <item>
      <title>How to read a PromQL query</title>
      <link>https://opscanopy.com/blog/reading-promql/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/reading-promql/</guid>
      <description>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.</description>
      <pubDate>Mon, 08 Jun 2026 00:00:00 GMT</pubDate>
      <category>promql</category>
      <category>prometheus</category>
      <category>observability</category>
    </item>
    <item>
      <title>LogQL vs PromQL: the same query in both languages</title>
      <link>https://opscanopy.com/blog/logql-vs-promql/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/logql-vs-promql/</guid>
      <description>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.</description>
      <pubDate>Fri, 05 Jun 2026 00:00:00 GMT</pubDate>
      <category>logql</category>
      <category>promql</category>
      <category>observability</category>
    </item>
    <item>
      <title>Stop shipping a stale .env.example</title>
      <link>https://opscanopy.com/blog/env-example-drift/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/env-example-drift/</guid>
      <description>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.</description>
      <pubDate>Tue, 02 Jun 2026 00:00:00 GMT</pubDate>
      <category>configuration</category>
      <category>developer-experience</category>
      <category>twelve-factor</category>
    </item>
    <item>
      <title>Writing robust regular expressions for log lines</title>
      <link>https://opscanopy.com/blog/regex-for-log-lines/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/regex-for-log-lines/</guid>
      <description>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.</description>
      <pubDate>Wed, 27 May 2026 00:00:00 GMT</pubDate>
      <category>regex</category>
      <category>logs</category>
      <category>parsing</category>
    </item>
    <item>
      <title>Migrating from cron to systemd timers</title>
      <link>https://opscanopy.com/blog/cron-to-systemd-timers/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/cron-to-systemd-timers/</guid>
      <description>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.</description>
      <pubDate>Wed, 20 May 2026 00:00:00 GMT</pubDate>
      <category>systemd</category>
      <category>cron</category>
      <category>linux</category>
    </item>
    <item>
      <title>Reading cron expressions: a field-by-field guide</title>
      <link>https://opscanopy.com/blog/cron-expressions-explained/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/cron-expressions-explained/</guid>
      <description>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.</description>
      <pubDate>Wed, 13 May 2026 00:00:00 GMT</pubDate>
      <category>cron</category>
      <category>scheduling</category>
      <category>devops</category>
    </item>
    <item>
      <title>The GitHub Actions security mistakes linters miss</title>
      <link>https://opscanopy.com/blog/github-actions-security-misconfigurations/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/github-actions-security-misconfigurations/</guid>
      <description>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.</description>
      <pubDate>Wed, 06 May 2026 00:00:00 GMT</pubDate>
      <category>github-actions</category>
      <category>security</category>
      <category>ci-cd</category>
    </item>
    <item>
      <title>One CVE, four ignore files: unifying Trivy, Grype, Snyk and osv-scanner</title>
      <link>https://opscanopy.com/blog/unifying-cve-ignore-files/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/unifying-cve-ignore-files/</guid>
      <description>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.</description>
      <pubDate>Wed, 29 Apr 2026 00:00:00 GMT</pubDate>
      <category>security</category>
      <category>vulnerability-management</category>
      <category>devops</category>
    </item>
    <item>
      <title>Unit Testing Loki Alert Rules: the gap promtool leaves</title>
      <link>https://opscanopy.com/blog/unit-testing-loki-alert-rules/</link>
      <guid isPermaLink="true">https://opscanopy.com/blog/unit-testing-loki-alert-rules/</guid>
      <description>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.</description>
      <pubDate>Wed, 15 Apr 2026 00:00:00 GMT</pubDate>
      <category>loki</category>
      <category>observability</category>
      <category>testing</category>
    </item>
  </channel>
</rss>