File size: 39,520 Bytes
fe0c0f8 9133d1e fe0c0f8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | <!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>OpenVox Puppet Migration — check your files for free</title>
<meta name="description" content="This free tool flags Puppet package, repository, image and gem references and shows the OpenVox replacement.">
<style>
:root{color-scheme:light}body{margin:0;font:15px/1.55 system-ui,-apple-system,"Segoe UI",sans-serif;background:#faf9f5;color:#1a1512}
.wrap{max-width:960px;margin:0 auto;padding:28px 18px 60px}h1{font-size:26px;margin:0 0 6px}.lede{color:#4a403a;margin:0 0 16px}
textarea{width:100%;min-height:260px;font:13px/1.45 ui-monospace,Menlo,Consolas,monospace;padding:12px;border:1px solid #d9d0c4;border-radius:8px;box-sizing:border-box}
.bar{display:flex;gap:10px;align-items:center;margin:12px 0}button{font:600 15px system-ui;padding:10px 18px;border:0;border-radius:8px;background:#1a1512;color:#fff;cursor:pointer}
input[type=date]{font:14px system-ui;padding:8px;border:1px solid #d9d0c4;border-radius:6px}
table{border-collapse:collapse;width:100%;font-size:14px;margin-top:10px}th,td{text-align:left;padding:8px 10px;border-bottom:1px solid #eee;vertical-align:top}th{font-size:12px;letter-spacing:.06em;text-transform:uppercase;color:#7a6e65}
.sev.error{color:#a8551f;font-weight:700}.sev.warn,.sev.warning{color:#96691f}.ok{color:#2a6446;font-weight:600}.sum{font-weight:600}
.note{font-size:13px;color:#7a6e65;margin-top:18px}#paid{margin-top:22px;padding:14px 16px;border:1px solid #e2d8cb;border-radius:10px;background:#fffdfa}
</style>
<script data-grow-initializer="">!(function(){window.growMe||((window.growMe=function(e){window.growMe._.push(e);}),(window.growMe._=[]));var e=document.createElement("script");(e.type="text/javascript"),(e.src="https://faves.grow.me/main.js"),(e.defer=!0),e.setAttribute("data-grow-faves-site-id","U2l0ZTphZjljMzgyMC0yMmU5LTRhYjgtYTIxNS03OTRhMGY1N2ExYzM=");var t=document.getElementsByTagName("script")[0];t.parentNode.insertBefore(e,t);})();</script>
<!--yj-canon-s101--><link rel="canonical" href="https://getreadystack.com/tools/openvox-migration-check"><style data-yj-mfit="1">#out{max-width:100%}#out td,#out th{overflow-wrap:anywhere}#out pre,#out code{white-space:pre-wrap;overflow-wrap:anywhere}@media (max-width:640px){table{display:block;max-width:100%;overflow-x:auto}pre{max-width:100%;overflow-x:auto}code,a{overflow-wrap:anywhere}img,svg,video,canvas,iframe{max-width:100%}textarea,input,select{max-width:100%;box-sizing:border-box}.yj-lgbar{position:static!important;justify-content:flex-end;margin:0 0 10px}#out table:not(:has(tr>:nth-child(4))){display:table;table-layout:fixed;width:100%}#out table:has(tr>:nth-child(4)),#out table:has(tr>:nth-child(4)) tbody,#out table:has(tr>:nth-child(4)) tr,#out table:has(tr>:nth-child(4)) td{display:block;width:auto;overflow:visible}#out table:has(tr>:nth-child(4)) thead{display:none}#out table:has(tr>:nth-child(4)) tr{padding:10px 0;border-bottom:1px solid rgba(128,128,128,.28)}#out table:has(tr>:nth-child(4)) td{border:0;padding:1px 0}#out table:has(tr>:nth-child(4)) td:nth-child(-n+3){display:inline-block;margin-right:10px;font-size:12px;opacity:.78}}</style>
</head>
<body>
<div class="wrap">
<h1>OpenVox Puppet Migration — check your files for free</h1>
<p class="lede">Flags Puppet package names, yum/apt.puppetlabs.com repos, puppet8-release, Docker images and gems that must change when you move a fleet from Puppet to OpenVox, with the exact OpenVox replacement. Runs entirely in your browser — nothing is uploaded.</p>
<textarea id="src" spellcheck="false">#!/bin/sh
# Node bootstrap for the config-management fleet (Rocky 9)
set -eu
curl -fsSLo /etc/yum.repos.d/puppet8.repo https://yum.puppetlabs.com/el/9/puppet8/x86_64/
dnf install -y puppet8-release
dnf install -y puppet-agent
dnf install -y puppetdb-termini
gem install puppet -v 8.10.0
docker pull puppet/puppetserver:8.10.0
/opt/puppetlabs/bin/puppet agent --test --server puppet.example.internal</textarea>
<div class="bar"><button id="go">Check</button><label>as of <input type="date" id="today"></label></div>
<div id="out" aria-live="polite"></div>
<div id="paid"><strong>Free here:</strong> Scan one bootstrap script, manifest, Dockerfile or CI file and see every Puppet package, repo, image and gem line with its OpenVox replacement.. <strong>In the editor:</strong> Scan every file in the repository at once and export one Markdown migration checklist for the change ticket. — that part asks for a licence key.</div>
<p class="note">Same engine as the VS Code extension, byte for byte.</p>
</div>
<script>var OVX_RULES = [
{"id": "OVX001", "sev": "error", "scope": "any", "re": "\\byum\\.puppet(?:labs)?\\.com\\b", "fix": "yum.voxpupuli.org", "freeze": true,
"msg": "Perforce open source yum repo — no new release since 2024-10-22 (Puppet 8.10). Point it at yum.voxpupuli.org."},
{"id": "OVX002", "sev": "error", "scope": "any", "re": "\\b(?:apt|deb)\\.puppet(?:labs)?\\.com\\b", "fix": "apt.voxpupuli.org", "freeze": true,
"msg": "Perforce open source apt repo — no new release since 2024-10-22 (Puppet 8.10). Point it at apt.voxpupuli.org."},
{"id": "OVX003", "sev": "error", "scope": "any", "re": "\\bpuppet[5-8]?-release\\b", "fix": "openvox8-release", "freeze": true,
"msg": "Puppet release package wires the frozen Perforce repo. Install openvox8-release instead."},
{"id": "OVX004", "sev": "error", "scope": "pkg", "re": "\\bpuppet-agent\\b", "fix": "openvox-agent",
"msg": "Package puppet-agent comes from Perforce. The OpenVox package is openvox-agent (same commands, same config paths)."},
{"id": "OVX005", "sev": "error", "scope": "pkg", "re": "\\bpuppetserver\\b", "fix": "openvox-server",
"msg": "Package puppetserver comes from Perforce. The OpenVox package is openvox-server."},
{"id": "OVX006", "sev": "error", "scope": "pkg", "re": "\\bpuppetdb(?:-termini)?\\b", "fix": "openvoxdb / openvoxdb-termini",
"msg": "Package puppetdb / puppetdb-termini comes from Perforce. The OpenVox packages are openvoxdb and openvoxdb-termini."},
{"id": "OVX007", "sev": "warning", "scope": "any", "re": "\\bpuppet-bolt\\b", "fix": "openbolt",
"msg": "Package puppet-bolt comes from Perforce. The OpenVox task runner package is openbolt."},
{"id": "OVX008", "sev": "error", "scope": "any", "re": "(?:^|[\\s\"'=:])(?:docker\\.io/)?puppet/(?:puppetserver|puppet-agent|puppetdb)\\b", "fix": "ghcr.io/openvoxproject/openvoxserver | openvoxagent | openvoxdb",
"msg": "Perforce container image. OpenVox images are ghcr.io/openvoxproject/openvoxserver, openvoxagent and openvoxdb."},
{"id": "OVX009", "sev": "warning", "scope": "any", "re": "(?:\\bgem\\s+install\\b.*\\spuppet(?=\\s|$))|(?:\\bgem\\s+['\"]puppet['\"])", "fix": "gem 'openvox'",
"msg": "Ruby gem puppet is the Perforce build. Use the openvox gem."},
{"id": "OVX010", "sev": "error", "scope": "any", "re": "\\bpuppet7\\b|\\bpuppet-agent[-=_ ]+7\\.\\d", "fix": "openvox8-release / openvox-agent 8.x",
"msg": "Open source Puppet 7 reached end of life on 2025-04-30. Move to OpenVox 8."},
{"id": "OVX011", "sev": "warning", "scope": "any", "re": "\\b[\\w.-]*puppetcore[\\w.-]*\\.puppet\\.com\\b", "fix": "yum.voxpupuli.org / apt.voxpupuli.org",
"msg": "Puppet Core repo — the free developer licence covers up to 25 nodes; above that Perforce requires a subscription."},
{"id": "OVX012", "sev": "error", "scope": "mixed", "re": "\\bopenvox(?:-agent|-server|db)\\b", "fix": "remove the Puppet package first",
"msg": "This file installs OpenVox and still installs a Puppet package. Puppet and OpenVox cannot be installed on the same system."}
]
;</script>
<script>/* OpenVox migration check — shared engine (VS Code + web page). */
(function () {
var RULES = (typeof module !== 'undefined' && module.exports) ? require('./rules.json')
: (typeof window !== 'undefined' ? window.OVX_RULES : []);
var PKG_CTX = /\b(install|package|packages|ensure|pkg|dnf|yum|apt-get|apt|zypper|rpm|dpkg|choco)\b|_package\b/i;
var PUPPET_PKG = /\b(puppet-agent|puppetserver|puppetdb(?:-termini)?)\b/;
var FREEZE = Date.UTC(2024, 9, 22);
function frozenDays(today) {
var m = /^(\d{4})-(\d{2})-(\d{2})/.exec(String(today || ''));
if (!m) return null;
var t = Date.UTC(+m[1], +m[2] - 1, +m[3]);
if (isNaN(t) || t < FREEZE) return null;
return Math.round((t - FREEZE) / 86400000);
}
// Join backslash-continued lines and flatten whitespace; keep the first line number.
function logicalLines(text) {
var raw = String(text || '').replace(/\r\n?/g, '\n').split('\n'), out = [], buf = '', start = 0;
for (var i = 0; i < raw.length; i++) {
var l = raw[i];
if (!buf) start = i + 1;
if (/\\\s*$/.test(l)) { buf += l.replace(/\\\s*$/, ' '); continue; }
buf += l;
out.push({ line: start, text: buf.replace(/\s+/g, ' ').trim() });
buf = '';
}
if (buf) out.push({ line: start, text: buf.replace(/\s+/g, ' ').trim() });
return out;
}
function check(text, opts) {
opts = opts || {};
var days = frozenDays(opts.today), findings = [], lines = logicalLines(text), hasPuppetPkg = false;
lines.forEach(function (L) {
if (!L.text || L.text.charAt(0) === '#' || L.text.indexOf('//') === 0) return;
if (PKG_CTX.test(L.text) && PUPPET_PKG.test(L.text)) hasPuppetPkg = true;
});
lines.forEach(function (L) {
var s = L.text;
if (!s || s.charAt(0) === '#' || s.indexOf('//') === 0) return;
RULES.forEach(function (r) {
if (r.scope === 'mixed') return;
if (r.scope === 'pkg' && !PKG_CTX.test(s)) return;
if (!new RegExp(r.re).test(s)) return;
var msg = r.msg + (r.freeze && days !== null ? ' Frozen ' + days + ' days as of ' + String(opts.today).slice(0, 10) + '.' : '');
findings.push({ check: r.id, sev: r.sev, msg: msg, line: L.line, fix: r.fix, text: s });
});
});
if (hasPuppetPkg) {
var mixed = RULES.filter(function (r) { return r.scope === 'mixed'; })[0];
if (mixed) {
var hit = lines.filter(function (L) { return L.text.charAt(0) !== '#' && PKG_CTX.test(L.text) && new RegExp(mixed.re).test(L.text); })[0];
if (hit) findings.push({ check: mixed.id, sev: mixed.sev, msg: mixed.msg, line: hit.line, fix: mixed.fix, text: hit.text });
}
}
findings.sort(function (a, b) { return a.line - b.line; });
return { findings: findings, frozen_days: days };
}
var api = { engine: { check: check }, RULES: RULES, RULE_COUNT: RULES.length };
if (typeof module !== 'undefined' && module.exports) module.exports = api;
if (typeof window !== 'undefined') window.OVXENGINE = api;
})();
</script>
<script>// ⛔뼈대 — kit/scaffold.py 가 찍는다 (s143). findings [{check,sev,msg,line?}] → 글/HTML. 같은 파일이 Node 와 브라우저에서 산다.
'use strict';
function escapeHtml(s) { return String(s == null ? '' : s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"'); }
function summaryLine(res) {
const f = (res && res.findings) || []; const e = f.filter(function (x) { return String(x.sev || 'error').toLowerCase().startsWith('err'); }).length;
return f.length ? (f.length + ' finding' + (f.length === 1 ? '' : 's') + ' (' + e + ' error' + (e === 1 ? '' : 's') + ')') : 'Clean — no findings.';
}
function toText(res, label) {
const f = (res && res.findings) || [];
const lines = ['== ' + (label || '') + ' — ' + summaryLine(res)];
f.forEach(function (x) { lines.push(' ' + String(x.sev || 'error').toUpperCase().slice(0, 4) + ' ' + (x.line ? 'L' + x.line + ' ' : '') + (x.check || x.id || '') + ' ' + (x.msg || x.message || '')); });
return lines.join('\n');
}
function toHtml(res) {
const f = (res && res.findings) || [];
if (!f.length) return '<p class="ok">' + escapeHtml(summaryLine(res)) + '</p>';
const rows = f.map(function (x) { return '<tr><td class="sev ' + escapeHtml(String(x.sev || 'error')) + '">' + escapeHtml(String(x.sev || 'error')) + '</td><td>' + (x.line ? 'L' + escapeHtml(x.line) : '') + '</td><td><code>' + escapeHtml(x.check || x.id || '') + '</code></td><td>' + escapeHtml(x.msg || x.message || '') + '</td></tr>'; }).join('');
return '<p class="sum">' + escapeHtml(summaryLine(res)) + '</p><table><thead><tr><th>Level</th><th>Line</th><th>Check</th><th>What</th></tr></thead><tbody>' + rows + '</tbody></table>';
}
var OVXREPORT = { escapeHtml: escapeHtml, summaryLine: summaryLine, toText: toText, toHtml: toHtml };
if (typeof module !== 'undefined' && module.exports) module.exports = OVXREPORT;
else window.OVXREPORT = OVXREPORT;
</script>
<script>
(function(){
var src=document.getElementById('src'), out=document.getElementById('out'), go=document.getElementById('go'), today=document.getElementById('today');
today.value=new Date().toISOString().slice(0,10);
function run(){ try { var res=window.OVXENGINE.engine.check(src.value,{today:today.value}); out.innerHTML=window.OVXREPORT.toHtml(res); } catch(e){ out.innerHTML='<p class="sev error">Could not run: '+String(e.message||e)+'</p>'; } }
go.onclick=run; if (src.value.trim()) run();
})();
</script>
<section data-yj-install="free" style="margin:2rem auto 1rem;max-width:46rem;padding:1.25rem 1.25rem;border:1px solid #cfe3d6;border-radius:12px;background:#f6fbf8;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .4rem;font-size:1.2rem">Install free</h2><p style="margin:0 0 .8rem;color:#41505f">Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.</p><a href="https://open-vsx.org/extension/readystack/openvox-migration-check" rel="noopener" data-yj-install-door="ovsx" onclick="try{navigator.sendBeacon('/api/ev',new Blob([JSON.stringify({t:'install',slug:'openvox-migration-check',src:'ovsx',path:location.pathname})],{type:'application/json'}))}catch(e){}" style="display:inline-block;margin:0 .5rem .5rem 0;padding:.6rem 1rem;border-radius:8px;background:#0f7b3f;color:#fff;text-decoration:none;font-weight:600">Open VSX (Cursor, VSCodium)</a><p style="margin:.6rem 0 0;font-size:.92rem;color:#41505f"><a href="https://getreadystack.com/api/buy/team" rel="nofollow" style="color:#0f7b3f;text-decoration:underline">Team? One key for every ReadyStack linter, 5 seats, $149 once</a></p></section>
<section data-yj-alert="rule" style="margin:1rem auto 1.5rem;max-width:46rem;padding:1.1rem 1.25rem;border:1px solid #d9dee6;border-radius:12px;background:#fbfcfd;font:15px/1.55 system-ui,-apple-system,Segoe UI,sans-serif"><b style="font-size:1.05rem">Get one email when this rule changes</b><div style="opacity:.78;margin:.35rem 0 .8rem">We watch the regulation and vendor sources behind OpenVox Migration Check for Puppet every day. When a rule changes, you get a single email with what changed and the updated check. No newsletter.</div><div style="display:flex;gap:8px;flex-wrap:wrap"><input id="yjae" type="email" placeholder="you@example.com" style="flex:1;min-width:210px;padding:11px 13px;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:#fff;color:inherit"><button id="yjab" style="padding:11px 18px;border-radius:8px;border:0;cursor:pointer;background:#0f7b3f;color:#fff;font:600 15px system-ui,sans-serif">Notify me</button></div><div id="yjao" hidden style="margin-top:.6rem;color:#0f7b3f">You're on the list. One email when it changes.</div><script>(function(){var b=document.getElementById("yjab"),e=document.getElementById("yjae");if(!b||!e)return;b.addEventListener("click",function(){var v=e.value.trim();if(!/.+@.+\..+/.test(v))return;try{localStorage.setItem("yj_em","1");}catch(_){}fetch(location.origin+"/api/subscribe",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:v,slug:"openvox-migration-check",lang:"en",source:"rule_alert"+((b.closest&&b.closest("section")&&b.closest("section").getAttribute("data-yj-moved"))?"_at_result":"")})}).then(function(r){var o=document.getElementById("yjao");o.hidden=false;if(!r.ok){o.textContent="Could not save - please try again.";}}).catch(function(){var o=document.getElementById("yjao");o.hidden=false;o.textContent="Could not save - please try again.";});});})();</script><script>(function(){var e=document.getElementById("yjae"),s=e&&e.closest?e.closest("section"):null,o=document.getElementById("out");if(!s||!o)return;var d=false;function mv(ev){if(d)return;if(ev&&ev.target&&s.contains(ev.target))return;d=true;var b=o;while(b.parentNode&&b.parentNode!==document.body&&b.parentNode.tagName!=="MAIN"&&b.parentNode.tagName!=="ARTICLE")b=b.parentNode;if(!b.parentNode||b===s||b.contains(s))return;try{b.parentNode.insertBefore(s,b.nextSibling);s.setAttribute("data-yj-moved","1");}catch(_){}}document.addEventListener("input",mv,true);document.addEventListener("change",mv,true);document.addEventListener("click",function(ev){var b=ev.target&&ev.target.closest?ev.target.closest("button,input[type=submit]"):null;if(b&&!b.closest("[data-yj],[data-yj-cta],[data-yj-install],[data-yj-alert],.yj-find,.yj-related,#yj-ask,.yjp"))mv(ev);},true);})();</script></section>
<section data-yj-cta="paid" style="margin:3rem auto;max-width:46rem;padding:1.5rem 1.25rem;border:1px solid #d8dee9;border-radius:12px;background:#fbfcfe;font:16px/1.6 system-ui,-apple-system,Segoe UI,sans-serif"><h2 style="margin:0 0 .5rem;font-size:1.25rem">Get the full version <span class="yj-price">$29</span></h2><p class="yj-cta-paid" style="margin:.25rem 0 .6rem;color:#1f2a37">Scan every file in the repository at once and export one Markdown migration checklist for the change ticket.</p><p class="yj-cta-pay" style="margin:.25rem 0 1rem;color:#5b6b7c;font-size:.94rem">One payment, one licence key for this tool. The key is shown right after payment.</p><p class="yj-cta-anchor" style="margin:0 0 1rem;color:#5b6b7c;font-size:.94rem">The alternative is a Puppet Core subscription for every fleet above 25 nodes.</p><a href="https://getreadystack.com/api/buy/cl/polar_cl_Ve91SzjeercooN02smDHoIMcFxYMuJzF6uwPs4fvB9Q" rel="nofollow" style="display:inline-block;padding:.7rem 1.3rem;border-radius:8px;background:#1b64f2;color:#fff;text-decoration:none;font-weight:600">Buy the full version — $29</a></section>
<!--yj-share-s101--><div style="margin:28px 0 8px;text-align:center"><button id="yjcp" type="button" style="font:inherit;padding:10px 18px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Copy link</button><button id="yjimg" type="button" style="font:inherit;padding:10px 18px;margin-left:8px;border:1px solid #8884;border-radius:10px;background:transparent;cursor:pointer">Save result as image</button></div><script>(function(){var b=document.getElementById("yjimg");if(!b)return;b.addEventListener("click",function(){var o=document.getElementById("out");var txt=(o&&(o.innerText||o.textContent)||"").trim();if(!txt){b.textContent="(no result yet)";setTimeout(function(){b.textContent="Save result as image";},1500);return;}var lines=txt.split(String.fromCharCode(10)).filter(function(x){return x.trim();}).slice(0,10);var W=1200,P=56,c=document.createElement("canvas");c.width=W;var lh=38,H=P*2+70+lines.length*lh+60;c.height=H;var x=c.getContext("2d");x.fillStyle="#1a1512";x.fillRect(0,0,W,H);x.fillStyle="#f3e9d2";x.font="600 34px system-ui,Segoe UI,Arial";var t=(document.title||"").split("|")[0].trim();x.fillText(t.slice(0,54),P,P+34);x.font="22px ui-monospace,Menlo,Consolas,monospace";x.fillStyle="#e8dcc4";for(var i=0;i<lines.length;i++){x.fillText(lines[i].slice(0,88),P,P+70+i*lh+22);}x.font="600 22px system-ui,Segoe UI,Arial";x.fillStyle="#c9a227";var d=location.hostname.replace("www.","");x.fillText(d,W-P-x.measureText(d).width,H-P+6);c.toBlob(function(bl){var u=URL.createObjectURL(bl),a=document.createElement("a");a.href=u;a.download=(t||"result").replace(/[^a-z0-9]+/gi,"-").toLowerCase()+"-"+d+".png";document.body.appendChild(a);a.click();setTimeout(function(){URL.revokeObjectURL(u);a.remove();},2000);},"image/png");});})();</script><script>(function(){var b=document.getElementById("yjcp");if(!b)return;var t=b.textContent;b.addEventListener("click",function(){var u=location.href.split("#")[0];function d(){b.textContent="Link copied";setTimeout(function(){b.textContent=t;},1800);}if(navigator.clipboard&&navigator.clipboard.writeText){navigator.clipboard.writeText(u).then(d,function(){prompt("",u);});}else{prompt("",u);}});})();</script>
<script data-yj="yj-view-beacon">(function(){try{var p=location.pathname;var k='yjv:'+p;if(sessionStorage.getItem(k))return;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",ref:(document.referrer||''),src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}catch(e){}})();</script>
<script data-yj="yj-use-beacon">(function(){try{var o=document.getElementById('out');if(!o)return;var p=location.pathname,k='yju:'+p,sent=false;function fire(){if(sent||sessionStorage.getItem(k))return;if(!(o.textContent||'').replace(/\s+/g,'').length)return;sent=true;sessionStorage.setItem(k,'1');fetch('/api/ev',{method:'POST',keepalive:true,headers:{'Content-Type':'application/json'},body:JSON.stringify({path:p,lang:"en",t:'use',src:(function(){try{return (new URLSearchParams(location.search).get('ref')||'').replace(/[^a-z_]/g,'').slice(0,12)}catch(e){return ''}})()})}).catch(function(){});}var mo=new MutationObserver(function(){fire();if(sent)mo.disconnect();});mo.observe(o,{childList:true,characterData:true,subtree:true});}catch(e){}})();</script><div class="yj-home-find"><div class="yj-lgbar"><a href="/" class="yj-lg on">EN</a><a href="/de/" class="yj-lg">DE</a><a href="/ja/" class="yj-lg">JA</a><a href="/es/" class="yj-lg">ES</a><a href="/pt/" class="yj-lg">PT</a></div><section class="yj-find"><h2>Find a tool</h2><input id="yjq" type="search" autocomplete="off" placeholder="Type a product name, format or task"><div id="yjr"></div></section><style>.yj-lgbar{position:absolute;top:14px;right:18px;display:flex;gap:6px;z-index:60}.yj-lg{font:600 12px/1 system-ui,sans-serif;padding:6px 9px;border-radius:4px;text-decoration:none;color:#8b96a3;border:1px solid rgba(140,150,165,.28)}.yj-lg:hover{color:#e8eaed;border-color:rgba(160,175,195,.6)}.yj-lg.on{color:#0e1116;background:#cfd6de;border-color:#cfd6de}.yj-find{max-width:760px;margin:34px auto 8px;padding:0 20px}.yj-find h2{font:600 20px/1.3 system-ui,sans-serif;margin:0 0 10px}#yjq{width:100%;box-sizing:border-box;padding:13px 15px;font:400 15.5px system-ui,sans-serif;border:1px solid rgba(140,150,165,.34);border-radius:8px;background:rgba(255,255,255,.04);color:inherit}#yjq:focus{outline:none;border-color:#7FD1C4}#yjr{margin-top:10px;display:flex;flex-direction:column;gap:6px}#yjr a{display:flex;justify-content:space-between;gap:12px;padding:11px 14px;border:1px solid rgba(140,150,165,.22);border-radius:6px;text-decoration:none;font:400 14.5px/1.4 system-ui,sans-serif;color:inherit}#yjr a:hover{border-color:#7FD1C4}#yjr .pr{font:600 13px system-ui,sans-serif;color:#5fbf9a;white-space:nowrap}</style><script>(function(){var q=document.getElementById("yjq"),r=document.getElementById("yjr"),D=null;function load(){if(D)return Promise.resolve(D);return fetch("/search-index.json").then(function(x){return x.json();}).then(function(j){D=j;return j;}).catch(function(){D=[];return D;});}function esc(t){return String(t).replace(/[&<>"]/g,function(c){return {"&":"&","<":"<",">":">",'"':"""}[c];});}function run(){var v=q.value.trim().toLowerCase();if(v.length<2){r.innerHTML="";return;}load().then(function(j){var w=v.split(/\s+/),o=[];for(var i=0;i<j.length&&o.length<12;i++){var t=j[i].t.toLowerCase();var ok=true;for(var k=0;k<w.length;k++){if(t.indexOf(w[k])<0){ok=false;break;}}if(ok)o.push(j[i]);}r.innerHTML=o.length?o.map(function(x){return "<a href=\""+esc(x.u)+"\">"+"<span>"+esc(x.t)+"</span>"+(x.p?"<span class=\"pr\">$"+x.p+"</span>":"")+"</a>";}).join(""):"";});}q.addEventListener("input",run);q.addEventListener("focus",load);})();</script></div><section data-yj="yj-facts-v1" style="max-width:920px;margin:48px auto 0;padding:0 20px;font-family:system-ui,sans-serif"><style>.yj-article p{font:400 15.5px/1.7 system-ui,sans-serif;color:#26313b;margin:0 0 12px;max-width:72ch}.yj-article h2,.yj-article h3,.yj-article h4{font:600 17px/1.35 system-ui,sans-serif;color:#1b1f24;margin:22px 0 8px}.yj-article table{border-collapse:collapse;margin:10px 0 16px;font:14px/1.45 system-ui,sans-serif}.yj-article th,.yj-article td{border:1px solid #e2e6ea;padding:6px 10px;text-align:left}.yj-article th{background:#f4f6f8}.yj-article pre{background:#0f1720;color:#e6edf3;padding:12px 14px;border-radius:8px;overflow:auto;font:13px/1.5 ui-monospace,Menlo,monospace}.yj-article code{font:13px ui-monospace,Menlo,monospace;background:#f1f3f5;padding:1px 4px;border-radius:3px}.yj-article pre code{background:none;padding:0}.yj-article ul,.yj-article ol{font:15px/1.6 system-ui,sans-serif;color:#26313b}</style><p style="font:400 13px/1.5 system-ui,sans-serif;color:#6b7680;margin:0 0 14px"><time datetime="2026-09-29">Updated 2026-09-29</time> · ReadyStack</p><script type="application/ld+json">{"@context":"https://schema.org","@type":"WebPage","dateModified":"2026-09-29","author":{"@type":"Organization","name":"ReadyStack"}}</script><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Worked example</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 16px;color:#5b6570">Real numbers from this tool, line by line.</p><div class="yj-article"><p><img src="https://getreadystack.com/img/promo/sku400370_result_card.jpg" alt="OpenVox Migration Check for Puppet" loading="lazy" style="max-width:100%;border-radius:6px"></p>
<p>openvox migration: 6 findings in one 10-line Rocky 9 bootstrap script. That is what a platform engineer moving a Puppet fleet to OpenVox gets back when the script that builds every new node is checked line by line.</p>
<h3>What Perforce changed, and when</h3>
<p>In November 2024 Perforce announced that new Puppet binaries would move to a private, licence-gated location. The product is now Puppet Core: a free developer licence covers up to 25 nodes, and a subscription is needed above that. The old open source repos at yum.puppetlabs.com and apt.puppetlabs.com stay online, but the last release to them was Puppet 8.10 on 2024-10-22. On 2026-09-29 that is 707 days without a package. Open source Puppet 7 reached end of life on 2025-04-30.</p>
<p>The community answer is OpenVox, the Vox Pupuli fork, first released on 2025-01-21. From 8.11 it is functionally equivalent to Puppet: the commands are the same and the config paths are the same. What changes is everything your automation names: packages, repos, container images and the Ruby gem.</p>
<h3>The script</h3>
<p>Here is the bootstrap we checked, a normal one for a Rocky 9 node:</p>
<pre><code>curl -fsSLo /etc/yum.repos.d/puppet8.repo https://yum.puppetlabs.com/el/9/puppet8/x86_64/
dnf install -y puppet8-release
dnf install -y puppet-agent
dnf install -y puppetdb-termini
gem install puppet -v 8.10.0
docker pull puppet/puppetserver:8.10.0
/opt/puppetlabs/bin/puppet agent --test --server puppet.example.internal</code></pre>
<p>The check returns six findings:</p>
<ul><li>L4 OVX001: yum.puppetlabs.com → yum.voxpupuli.org</li><li>L5 OVX003: puppet8-release → openvox8-release</li><li>L6 OVX004: puppet-agent → openvox-agent</li><li>L7 OVX006: puppetdb-termini → openvoxdb-termini</li><li>L8 OVX009: gem puppet → gem openvox</li><li>L9 OVX008: puppet/puppetserver → ghcr.io/openvoxproject/openvoxserver</li></ul>
<p>The last line, <code>puppet agent --test</code>, is not flagged. OpenVox keeps that command and the /opt/puppetlabs path. That is exactly why a search-and-replace on the word "puppet" fails: it rewrites the lines that must stay and still misses the release package name.</p>
<h3>Why a chatbot is not enough here</h3>
<p>Ask an assistant for a Puppet agent install and it will usually write <code>dnf install puppet-agent</code> from yum.puppet.com, because that is what years of docs say. The repo still answers, so nothing errors; you just keep installing a build frozen at 8.10. The check knows the replacement for each line.</p>
<h3>The 12 rules</h3>
<p>Repos (yum and apt), release packages, puppet-agent, puppetserver, puppetdb and puppetdb-termini, puppet-bolt (now openbolt), the three Perforce images, the puppet gem, Puppet 7 pins, Puppet Core repo hosts, and one rule for a file that installs OpenVox while still installing a Puppet package. Vox Pupuli is explicit that you cannot install both on the same system, so a half-migrated profile is a real failure.</p>
<p>Package rules only fire on install, package or ensure lines, so <code>puppetserver ca list</code> in a runbook stays quiet. Comment lines are skipped and backslash-continued shell lines are joined before matching.</p>
<h3>Try it on your own file</h3>
<p>The free web page and the VS Code extension use the same engine. Paste one bootstrap script, manifest, Dockerfile or CI file and every Puppet line comes back with its OpenVox fix; the clean OpenVox version of the script above returns 0 findings. A licence key adds a whole-repository scan and one Markdown migration checklist for the change ticket.</p></div><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:30px 0 10px;color:#1b1f24">15 seconds — what it actually does</h2><video controls muted playsinline preload="none" poster="/img/promo/sku400370_result_card.jpg" style="width:100%;max-width:360px;border-radius:10px;display:block;margin:0 auto"><source src="/media/sku400370_short.mp4" type="video/mp4"></video><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:34px 0 6px;color:#1b1f24">Questions people ask</h2><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What does OpenVox Migration Check do?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">It reads bootstrap scripts, Puppet manifests, Dockerfiles, Gemfiles and CI YAML and flags every line that still pulls Perforce Puppet: yum or apt.puppetlabs.com repos, puppet8-release, puppet-agent, puppetserver, puppetdb, puppet-bolt, Docker images, the puppet gem and Puppet 7 pins. Each finding names the exact OpenVox replacement, such as openvox-agent or yum.voxpupuli.org. It runs 12 rules.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Who is this for?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Platform, DevOps and infrastructure engineers who run a Puppet fleet on open source packages and are moving it to OpenVox, the Vox Pupuli fork, after Perforce put new Puppet builds behind the Puppet Core licence. It suits teams with more than 25 nodes, where the free Puppet Core developer licence no longer covers the fleet.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">Why not just search and replace 'puppet' or ask a chatbot?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">OpenVox keeps the same commands and config paths, so /opt/puppetlabs/bin/puppet agent and puppetserver ca list must stay unchanged while package names, repos, images and the gem change. A blind replace breaks the first group. Chat assistants still suggest dnf install puppet-agent from yum.puppet.com, a repo with no release since 2024-10-22.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What is free and what needs a licence key?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Checking one file is free and complete: open a script or manifest, run the check, and every Puppet line appears with its OpenVox replacement, in VS Code or on the web page. A licence key adds scanning every file in the repository at once and exporting one Markdown migration checklist you can attach to a change ticket.</p></details><details style="border-bottom:1px solid #e6e9ed;padding:10px 0"><summary style="cursor:pointer;font:600 15px/1.4 system-ui,sans-serif;color:#1b1f24">What does staying on Puppet cost instead?</summary><p style="margin:8px 0 2px;font:400 14.5px/1.6 system-ui,sans-serif;color:#33404b">Perforce offers new Puppet builds as Puppet Core. The free developer licence covers up to 25 nodes; above that Perforce requires a subscription. The old open source repos stay online but have shipped nothing since Puppet 8.10 on 2024-10-22, and open source Puppet 7 reached end of life on 2025-04-30.</p></details><script type="application/ld+json" data-yj="yj-faq-ld">{"@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [{"@type": "Question", "name": "What does OpenVox Migration Check do?", "acceptedAnswer": {"@type": "Answer", "text": "It reads bootstrap scripts, Puppet manifests, Dockerfiles, Gemfiles and CI YAML and flags every line that still pulls Perforce Puppet: yum or apt.puppetlabs.com repos, puppet8-release, puppet-agent, puppetserver, puppetdb, puppet-bolt, Docker images, the puppet gem and Puppet 7 pins. Each finding names the exact OpenVox replacement, such as openvox-agent or yum.voxpupuli.org. It runs 12 rules."}}, {"@type": "Question", "name": "Who is this for?", "acceptedAnswer": {"@type": "Answer", "text": "Platform, DevOps and infrastructure engineers who run a Puppet fleet on open source packages and are moving it to OpenVox, the Vox Pupuli fork, after Perforce put new Puppet builds behind the Puppet Core licence. It suits teams with more than 25 nodes, where the free Puppet Core developer licence no longer covers the fleet."}}, {"@type": "Question", "name": "Why not just search and replace 'puppet' or ask a chatbot?", "acceptedAnswer": {"@type": "Answer", "text": "OpenVox keeps the same commands and config paths, so /opt/puppetlabs/bin/puppet agent and puppetserver ca list must stay unchanged while package names, repos, images and the gem change. A blind replace breaks the first group. Chat assistants still suggest dnf install puppet-agent from yum.puppet.com, a repo with no release since 2024-10-22."}}, {"@type": "Question", "name": "What is free and what needs a licence key?", "acceptedAnswer": {"@type": "Answer", "text": "Checking one file is free and complete: open a script or manifest, run the check, and every Puppet line appears with its OpenVox replacement, in VS Code or on the web page. A licence key adds scanning every file in the repository at once and exporting one Markdown migration checklist you can attach to a change ticket."}}, {"@type": "Question", "name": "What does staying on Puppet cost instead?", "acceptedAnswer": {"@type": "Answer", "text": "Perforce offers new Puppet builds as Puppet Core. The free developer licence covers up to 25 nodes; above that Perforce requires a subscription. The old open source repos stay online but have shipped nothing since Puppet 8.10 on 2024-10-22, and open source Puppet 7 reached end of life on 2025-04-30."}}]}</script><div id="yj-ask" style="margin:36px 0 0;padding:18px 18px 16px;border:1px solid #e2e6ea;border-radius:10px;background:#fbfbfc"><h2 style="font:600 19px/1.3 system-ui,sans-serif;margin:0 0 4px;color:#1b1f24">Ask about this tool</h2><p style="font:400 13.5px/1.5 system-ui,sans-serif;margin:0 0 12px;color:#5b6570">One question, answered by the person who built it. Your email only if you want the answer sent.</p><form onsubmit="return yjAsk(event)" style="display:grid;gap:8px"><textarea name="question" required minlength="10" maxlength="2000" rows="3" placeholder="Your question" style="font:14px/1.5 system-ui,sans-serif;padding:10px;border:1px solid #cfd6dd;border-radius:6px"></textarea><div style="display:flex;gap:8px;flex-wrap:wrap"><input type="email" name="email" placeholder="Email (optional)" style="flex:1;min-width:200px;font:14px system-ui,sans-serif;padding:9px 10px;border:1px solid #cfd6dd;border-radius:6px"><button type="submit" style="font:600 14px system-ui,sans-serif;padding:9px 18px;border:0;border-radius:6px;background:#1b1f24;color:#fff;cursor:pointer">Send</button></div><p id="yj-ask-msg" style="font:13px system-ui,sans-serif;margin:2px 0 0;color:#0a6238;min-height:1em"></p></form><script>function yjAsk(e){e.preventDefault();var f=e.target,m=document.getElementById("yj-ask-msg");m.style.color="#0a6238";fetch(location.origin+"/api/ask",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sku:400370,slug:"openvox-migration-check",lang:"en",question:f.question.value,email:f.email.value,page:location.pathname})}).then(function(r){if(!r.ok)throw 0;m.textContent="Thanks \u2014 noted. Answers land on this page and, if you left an email, in your inbox.";f.question.value="";}).catch(function(){m.style.color="#a8551f";m.textContent="Could not send. Please try again in a minute.";});return false;}</script></div></section><section class="yj-related" style="max-width:920px;margin:56px auto 40px;padding:0 20px"><h2 style="font:600 21px/1.3 system-ui,sans-serif;margin:0 0 6px;color:#1b1f24">Same job, next tool</h2><p style="font:400 14.5px/1.5 system-ui,sans-serif;margin:0 0 20px;color:#5b6570">Free in the browser. The full version is a one-time licence.</p><div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:14px"><a class="yj-rel-c" href="https://getreadystack.com/tools/cinc-migration-check"><span class="yj-rel-t">Cinc Migration Check: Chef Infra licence gate lint</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/pekko-migration-gate"><span class="yj-rel-t">Pekko Migration Gate — Akka BSL licence check</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/pyside6-migration-lint"><span class="yj-rel-t">PySide6 Migration Lint: PyQt5/PyQt6 Licence Gate</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/vscodium-extension-licence-lint"><span class="yj-rel-t">VSCodium Migration Lint: Microsoft-only Extensions</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/ai-model-license-lint"><span class="yj-rel-t">AI Model License Lint</span><span class="yj-rel-p">$29</span></a><a class="yj-rel-c" href="https://getreadystack.com/tools/almalinux-migration-lint"><span class="yj-rel-t">AlmaLinux Migration Lint — CentOS 7/8</span><span class="yj-rel-p">$29</span></a></div><style>.yj-rel-c{display:flex;flex-direction:column;gap:8px;padding:15px 16px;border:1px solid #e2e6ea;border-radius:6px;text-decoration:none;background:#fff}.yj-rel-c:hover{border-color:#b9c2cb;background:#fafbfc}.yj-rel-t{font:500 14.5px/1.42 system-ui,sans-serif;color:#1b1f24}.yj-rel-p{font:600 13px system-ui,sans-serif;color:#0a6238}</style></section></body>
</html>
|