Skip to content

docs(posts): yum said 301, the machine said 2024 - #33

Merged
gounthar merged 3 commits into
mainfrom
docs/yum-301-clock-post
Jul 29, 2026
Merged

docs(posts): yum said 301, the machine said 2024#33
gounthar merged 3 commits into
mainfrom
docs/yum-301-clock-post

Conversation

@gounthar

@gounthar gounthar commented Jul 29, 2026

Copy link
Copy Markdown
Owner

A home lab XCP-ng 8.3 host refused the July update batch with HTTPS Error 301 - Moved Permanently. Every word of that message points outward at the mirrors, and every word of it is about the wrong thing. The mirrors were healthy, the redirect chain was correct, and the host simply thought it was September 2024 — so every certificate it was offered failed its notBefore check.

The reason this one is worth a post rather than a forum reply is what was underneath. chronyd was both active and enabled, which is the state every check an operator would think to run reports as green. It also had zero sources, because /etc/chrony.conf shipped with no server or pool line at all. A time daemon in that state is indistinguishable from a healthy one unless you specifically run chronyc sources, and nobody runs that until they already suspect the clock. So the host holds its install date indefinitely, and the first thing that ever tells you is an unrelated-looking yum error.

There is also a walkthrough of why yum reports the redirect instead of the TLS failure: urlgrabber's header callback advances self.scheme the moment it sees a Location:, while a failed handshake never produces an HTTP response code — so the stale 301 from the hop that worked wins the format string, and libcurl's honest certificate is not yet valid is built and then thrown away.

Notes for review

  • The docs paragraph near the end is deliberately worded as "in review". It links no docs URL because the page does not exist yet — [depends on #514] Document NTP as the canonical clock reference, with yum "HTTPS Error 301" as one symptom xcp-ng/xcp-ng-org#504 is still open (confirmed at time of writing). Please don't upgrade it to "now documented" or add a docs.xcp-ng.org link until that merges.
  • Header image is an Unsplash photo by Arash, credited under the image in the same pattern the other posts use. Added at static/assets/images/2026/07/29/.
  • Publish time is 10:00:00 +0200, not +0000. As +0000 the post was ~2h in the future and Hugo silently dropped it from the build — it would have merged green and simply not appeared. +0200 keeps the same date and the same "10:00" reading while being in the past. Verified the page builds without --buildFuture.

Verification

  • asciidoctor --failure-level=WARN exits 0, no warnings
  • Full Hugo build (hugo --minify, v0.161.1 extended) completes with no warnings or errors
  • Post renders at /2026/07/29/yum-said-301-the-machine-said-2024/ and appears in the homepage listing
  • Header image is copied into the output and the <img> carries the full alt text — the alt needed quoting, since AsciiDoc otherwise splits on the commas and turns the tail into bogus width and height attributes
  • Frontmatter parses as YAML with the same key set as the other posts; file ends with a newline
  • All 11 external links returned 200

Summary by CodeRabbit

  • Documentation
    • Added a new troubleshooting blog post covering misleading HTTPS “301 - Moved Permanently” messages during yum updates on XCP-ng hosts.
    • Explains how system clock issues can cause TLS certificate validation failures that may present as redirect errors.
    • Includes a step-by-step checklist with verification commands, recommended time synchronization actions, mirror configuration cautions, and a brief takeaway, plus references to related discussions.

A home lab XCP-ng 8.3 host refused the July update batch with
"HTTPS Error 301 - Moved Permanently". The mirrors were healthy and
the redirect chain was correct; the host believed it was September
2024, so every certificate it was offered failed its notBefore check.

Underneath that, chronyd was both active and enabled while having zero
sources configured, because /etc/chrony.conf shipped with no server or
pool line at all. A time daemon in that state is indistinguishable
from a healthy one unless you run chronyc sources.

The post also walks through why yum reports the redirect rather than
the TLS error: urlgrabber's header callback advances the scheme on
Location, while the failed handshake never produces a response code,
so the stale 301 from the successful hop wins and the real libcurl
message is discarded.
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@gounthar, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 42 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a8f3b7e6-ccec-49b1-8599-04a566a0530f

📥 Commits

Reviewing files that changed from the base of the PR and between 028ae40 and 64d1aeb.

📒 Files selected for processing (1)
  • content/posts/2026-07-29-yum-said-301-the-machine-said-2024.adoc
📝 Walkthrough

Walkthrough

Adds an AsciiDoc post explaining how an incorrect system clock and an unconfigured chronyd instance can cause a misleading yum HTTPS 301 error, with diagnostic commands, time-correction steps, verification guidance, and supporting references.

Changes

Yum clock diagnosis

Layer / File(s) Summary
Redirect and TLS error analysis
content/posts/2026-07-29-yum-said-301-the-machine-said-2024.adoc
Introduces the incident, explains the mirror redirect chain, compares a second host, and connects the misleading 301 message to TLS certificate validation against an incorrect system clock.
Chrony diagnosis and recovery
content/posts/2026-07-29-yum-said-301-the-machine-said-2024.adoc
Documents the zero-source chronyd state and provides commands to inspect sources, configure NTP servers, correct the clock, and verify yum updates.
Operational guidance and references
content/posts/2026-07-29-yum-said-301-the-machine-said-2024.adoc
Adds mirror failover and certificate-validity notes, references related evidence, and concludes with a diagnostic takeaway.

Estimated code review effort: 1 (Trivial) | ~5 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding a blog post about yum showing a 301 error caused by clock/TLS issues.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/yum-301-clock-post

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@content/posts/2026-07-29-yum-said-301-the-machine-said-2024.adoc`:
- Around line 53-64: Clarify the mirror-validation section around the curl
command by stating that it must be run from a correctly synchronized host or
second machine, not the affected host with the 2024 clock. Ensure the diagnostic
output is presented as coming from that correctly timed environment, or replace
it with a diagnostic that remains valid on the affected host.
- Around line 243-247: Update the command sequence around “yum check-update” to
reflect that it only lists available updates and returns exit code 100 when
updates exist; add “yum update” before the narrative about installing the July
package batch, and revise the stated exit-code claim accordingly.
- Around line 216-235: Update the chrony recovery instructions after the
`/etc/chrony.conf` server entries to reload or restart the running `chronyd`
service, then rerun `chronyc sources` and confirm the configured sources are
active before continuing. Keep the existing `chronyc makestep` guidance, but
ensure the configuration reload occurs before the final source verification.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d4d56069-a24b-43e3-ab55-36b11bb0d085

📥 Commits

Reviewing files that changed from the base of the PR and between 7649fcb and 1597374.

⛔ Files ignored due to path filters (1)
  • static/assets/images/2026/07/29/00-header-rusted-clock.jpg is excluded by !**/*.jpg
📒 Files selected for processing (1)
  • content/posts/2026-07-29-yum-said-301-the-machine-said-2024.adoc

Comment thread content/posts/2026-07-29-yum-said-301-the-machine-said-2024.adoc Outdated
Comment thread content/posts/2026-07-29-yum-said-301-the-machine-said-2024.adoc
Comment thread content/posts/2026-07-29-yum-said-301-the-machine-said-2024.adoc Outdated
gounthar added 2 commits July 29, 2026 17:49
Three issues raised in review on the 2026-07-29 post.

The chronyd recipe did not fix the host the post diagnoses. With zero
sources configured, chronyc makestep has no measured offset to step to:
it reports success and leaves the clock where it was. The text also
referred to a restart it never gave. Split the recipe into the two
cases, sources present versus sources empty, and make the restart and
the follow-up chronyc sources explicit.

The curl chain proving the mirrors healthy was run from a laptop, not
from the failing host, which the text never said. On the affected host
the same command dies at the handshake. Named the machine at the point
the chain is shown, and explained the difference where the reader
learns why it happens.

Dropped the claim that yum check-update returned exit code 0 alongside
28 pending packages, which cannot both be true, and added yum update to
the block since the narrative is about taking the batch. Noted the
actual semantics: check-update returns 100 when updates are waiting.
The post originally claimed yum check-update returned exit 0 alongside
28 pending packages, which cannot happen. Verified against yum 3.4.3,
the same generation dom0 runs: check-update exits 100 with updates
pending and 0 with none, while yum update exits 0 on success.

So the original 0 was a real observation attached to the wrong command
rather than an invented number. Attribute it to yum update, which also
puts it next to the note about check-update returning 100.
@gounthar
gounthar merged commit 21d283c into main Jul 29, 2026
6 checks passed
@gounthar
gounthar deleted the docs/yum-301-clock-post branch July 29, 2026 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant