fix: improve host diagnostics, storage handling, and maintenance workflows

- add zero-downtime Proxmox TLS certificate refresh from the Security panel (#307)
- classify storage availability independently from missing capacity information (#309)
- update ZFS ARC sizing and safely reconcile conflicting module configurations
- preserve and restore migrated ZFS settings without overwriting later administrator changes
- stop memory optimization from forcing the kernel overcommit policy
- correlate multi-line OOM events and identify the affected LXC, cgroup limits, swap and killed process
- add selectable Bash prompt path styles and clearer shell activation guidance
- protect technical names during automatic translation and correct localized terminology
- update the Coral and VM/LXC Apps and Updates documentation, translations and screenshots
This commit is contained in:
MacRimi
2026-08-25 18:48:39 +02:00
parent 2302b0967b
commit 46158209f1
48 changed files with 2449 additions and 2466 deletions
@@ -41,6 +41,7 @@ export default async function InstallCoralTPUHostPage({
pcie: { items: StringItem[]; kernelPatches: StringItem[]; afterItems: StringItem[] }
usb: { items: StringItem[] }
}
legacyCleanup: { items: StringItem[] }
reinstallUninstall: { uninstallItems: StringItem[] }
related: { items: RelatedItem[] }
} } }
@@ -50,6 +51,7 @@ export default async function InstallCoralTPUHostPage({
const kernelPatches = messages.docs.hardware.installCoralTpuHost.walkthrough.pcie.kernelPatches
const pcieAfterItems = messages.docs.hardware.installCoralTpuHost.walkthrough.pcie.afterItems
const usbItems = messages.docs.hardware.installCoralTpuHost.walkthrough.usb.items
const legacyCleanupItems = messages.docs.hardware.installCoralTpuHost.legacyCleanup.items
const uninstallItems = messages.docs.hardware.installCoralTpuHost.reinstallUninstall.uninstallItems
const relatedItems = messages.docs.hardware.installCoralTpuHost.related.items
@@ -165,54 +167,18 @@ export default async function InstallCoralTPUHostPage({
<p className="mb-4 text-gray-800 leading-relaxed">{t("howRuns.body")}</p>
<pre className="bg-gray-100 text-gray-800 p-4 rounded-md overflow-x-auto text-sm my-4 border border-gray-200 leading-snug">
{`┌────────────────────────────────────────────────┐
│ 1. detect_coral_hardware()
│ → count PCIe (vendor 1ac1) + USB (IDs) │
└────────────────┬───────────────────────────────┘
┌───────────┴───────────┐
▼ ▼
None At least one
│ │
▼ ▼
Dialog pre_install_prompt()
"No Coral" → shows what was detected
exit 0 and what will be installed
┌────────────────┴────────────────┐
│ │
▼ ▼
PCIe detected? USB detected?
│ │
Yes Yes
▼ ▼
install_gasket_apex_dkms install_libedgetpu_runtime
├─ cleanup_broken_gasket_dkms ├─ add Google GPG keyring
├─ apt install deps │ /etc/apt/keyrings/...
│ (git, dkms, build-essential, ├─ add APT repo (signed-by)
│ proxmox-headers-$(uname-r)) │ /etc/apt/sources.list.d/
├─ clone feranick/gasket-driver │ coral-edgetpu.list
│ (google fallback + patches) ├─ apt install libedgetpu1-std
├─ copy src/ → /usr/src/ └─ udev reload + trigger
│ gasket-1.0/
├─ generate dkms.conf
├─ dkms add / build / install
└─ modprobe gasket + apex
+ ensure_apex_group_and_udev
│ │
└────────────────┬────────────────┘
┌────────────────┴────────────────┐
│ │
PCIe ran? USB only
│ │
▼ ▼
restart_prompt() "No reboot required"
(reboot required to (runtime + udev rules
load fresh kernel are already active)
module cleanly)`}
{`Detect Coral hardware
├─ PCIe / M.2 detected ──► build gasket + apex with DKMS
│ └─ reboot recommended
├─ USB detected ─────────► install libedgetpu runtime
└─ no reboot required
└─ no PCIe / M.2 detected
├─ no legacy gasket-dkms state ─► no PCIe changes
└─ legacy gasket-dkms state ────► offer optional cleanup
└─ USB runtime untouched`}
</pre>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("walkthrough.heading")}</h2>
@@ -290,6 +256,19 @@ export default async function InstallCoralTPUHostPage({
</Steps.Step>
</Steps>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("legacyCleanup.heading")}</h2>
<p className="mb-4 text-gray-800 leading-relaxed">
{t.rich("legacyCleanup.intro", { code, strong })}
</p>
<ul className="list-disc pl-6 mb-4 text-gray-800 leading-relaxed space-y-1">
{legacyCleanupItems.map((_, idx) => (
<li key={idx}>{t.rich(`legacyCleanup.items.${idx}`, { code, strong })}</li>
))}
</ul>
<Callout variant="warning" title={t("legacyCleanup.warningTitle")}>
{t("legacyCleanup.warningBody")}
</Callout>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("reinstallUninstall.heading")}</h2>
<p className="mb-4 text-gray-800 leading-relaxed">
@@ -1,10 +1,10 @@
import type { Metadata } from "next"
import type React from "react"
import { getTranslations, getMessages, setRequestLocale } from "next-intl/server"
import { getMessages, getTranslations, setRequestLocale } from "next-intl/server"
import { Link } from "@/i18n/navigation"
import { DocHeader } from "@/components/ui/doc-header"
import { Callout } from "@/components/ui/callout"
import CopyableCode from "@/components/CopyableCode"
import { DocHeader } from "@/components/ui/doc-header"
export async function generateMetadata({
params,
@@ -16,21 +16,15 @@ export async function generateMetadata({
return { title: t("title"), description: t("description") }
}
type TableRow = { method: string; when: string }
type BreakdownRow = { part: string; meaning: string }
type ExampleRow = { text: string; regex: string; result: string }
type DetectorRow = { method: string; use: string }
type StateRow = { state: string; display: string; meaning: string }
type ProblemRow = { problem: string; resolution: string }
function Figure({ src, alt, caption }: { src: string; alt: string; caption: string }) {
return (
<figure className="my-6">
<img
src={src}
alt={alt}
className="rounded-lg border border-gray-200 shadow-sm w-full"
/>
<figcaption className="text-sm text-gray-500 mt-2 text-center italic">
{caption}
</figcaption>
<img src={src} alt={alt} className="w-full rounded-lg border border-gray-200 shadow-sm" />
<figcaption className="mt-2 text-center text-sm italic text-gray-500">{caption}</figcaption>
</figure>
)
}
@@ -43,362 +37,178 @@ export default async function AppTabPage({
const { locale } = await params
setRequestLocale(locale)
const t = await getTranslations({ locale, namespace: "docs.monitor.dashboard.vmsLxcsApp" })
const messages = (await getMessages({ locale })) as unknown as {
docs: { monitor: { dashboard: { vmsLxcsApp: {
whatYouGet: { items: string[] }
registerSuggested: { steps: string[] }
manual: { linksItems: string[] }
multiple: { usefulItems: string[] }
tracking: {
ingredients: string[]
methodsTable: { rows: TableRow[] }
sourceItems: string[]
regexTwoItems: string[]
step2Items: string[]
step2Breakdown: { rows: BreakdownRow[] }
step3Examples: { rows: ExampleRow[] }
step4Items: string[]
step6CorrectItems: string[]
}
state: { items: string[] }
manage: { items: string[] }
options: { items: string[] }
notDetected: { steps: string[] }
overview: { items: string[] }
discovery: { items: string[] }
registration: { steps: string[] }
catalog: { items: string[] }
docker: { items: string[] }
webLinks: { items: string[] }
tracking: { detectorRows: DetectorRow[]; sources: string[]; regexRules: string[] }
updater: { items: string[] }
states: { rows: StateRow[] }
management: { items: string[] }
troubleshooting: { rows: ProblemRow[] }
} } } }
}
const v = messages.docs.monitor.dashboard.vmsLxcsApp
const whatYouGetItems = v.whatYouGet.items
const registerSteps = v.registerSuggested.steps
const manualLinks = v.manual.linksItems
const multipleUseful = v.multiple.usefulItems
const ingredients = v.tracking.ingredients
const methodsRows = v.tracking.methodsTable.rows
const sourceItems = v.tracking.sourceItems
const regexTwoItems = v.tracking.regexTwoItems
const step2Items = v.tracking.step2Items
const breakdownRows = v.tracking.step2Breakdown.rows
const exampleRows = v.tracking.step3Examples.rows
const step4Items = v.tracking.step4Items
const step6CorrectItems = v.tracking.step6CorrectItems
const stateItems = v.state.items
const manageItems = v.manage.items
const optionsItems = v.options.items
const notDetectedSteps = v.notDetected.steps
// Rich-text tag handlers
const strong = (chunks: React.ReactNode) => <strong>{chunks}</strong>
const em = (chunks: React.ReactNode) => <em>{chunks}</em>
const code = (chunks: React.ReactNode) => (
<code className="text-sm bg-gray-100 px-1 rounded">{chunks}</code>
)
const code = (chunks: React.ReactNode) => <code className="rounded bg-gray-100 px-1 text-sm">{chunks}</code>
const linkUpdates = (chunks: React.ReactNode) => (
<Link href="/docs/monitor/dashboard/vms-lxcs/updates" className="text-blue-600 hover:underline">
{chunks}
</Link>
)
const richList = (base: string, items: string[]) => (
<ul className="mt-2 list-disc space-y-2 pl-6 text-gray-800">
{items.map((_, idx) => (
<li key={idx}>{t.rich(`${base}.${idx}`, { strong, em, code, link: linkUpdates })}</li>
))}
</ul>
)
return (
<div className="max-w-4xl mx-auto px-4 py-8">
<DocHeader
title={t("header.title")}
description={t("header.description")}
estimatedMinutes={12}
/>
<div className="mx-auto max-w-4xl px-4 py-8">
<DocHeader title={t("header.title")} description={t("header.description")} estimatedMinutes={11} />
<p className="text-gray-800 mt-6">{t.rich("intro.p1", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t.rich("intro.p2", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t.rich("intro.p3", { strong, em, code, link: linkUpdates })}</p>
<p className="mt-6 text-gray-800">{t.rich("intro.p1", { strong, em, code })}</p>
<p className="mt-4 text-gray-800">{t.rich("intro.p2", { strong, em, code, link: linkUpdates })}</p>
<Callout variant="info">{t.rich("intro.callout", { strong, em, code })}</Callout>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("whatYouGet.heading")}</h2>
<p className="text-gray-800">{t("whatYouGet.lead")}</p>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{whatYouGetItems.map((_, idx) => (
<li key={idx}>{t.rich(`whatYouGet.items.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t.rich("whatYouGet.trailing", { strong, em, code })}</p>
<Callout variant="warning">{t.rich("whatYouGet.callout", { strong, em, code })}</Callout>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("overview.heading")}</h2>
<p className="text-gray-800">{t("overview.lead")}</p>
{richList("overview.items", v.overview.items)}
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("firstOpening.heading")}</h2>
<p className="text-gray-800">{t.rich("firstOpening.p1", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t.rich("firstOpening.p2", { strong, em, code })}</p>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("discovery.heading")}</h2>
<p className="text-gray-800">{t.rich("discovery.lead", { strong, em, code })}</p>
{richList("discovery.items", v.discovery.items)}
<Callout variant="tip">{t.rich("discovery.callout", { strong, em, code })}</Callout>
<Figure
src="/monitor/vms-modal-app-01.png"
alt={t("figures.f01.alt")}
caption={t("figures.f01.caption")}
/>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("registerSuggested.heading")}</h3>
<ol className="list-decimal pl-6 space-y-1 text-gray-800">
{registerSteps.map((_, idx) => (
<li key={idx}>{t.rich(`registerSuggested.steps.${idx}`, { strong, em, code })}</li>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("registration.heading")}</h2>
<p className="text-gray-800">{t("registration.lead")}</p>
<ol className="mt-2 list-decimal space-y-2 pl-6 text-gray-800">
{v.registration.steps.map((_, idx) => (
<li key={idx}>{t.rich(`registration.steps.${idx}`, { strong, em, code })}</li>
))}
</ol>
<p className="text-gray-800 mt-4">{t.rich("registerSuggested.trailing", { strong, em, code })}</p>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("catalog.heading")}</h2>
<p className="text-gray-800">{t.rich("catalog.p1", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t.rich("catalog.p2", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t.rich("catalog.p3", { strong, em, code })}</p>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("catalog.heading")}</h2>
<p className="text-gray-800">{t.rich("catalog.lead", { strong, em, code })}</p>
{richList("catalog.items", v.catalog.items)}
<Figure
src="/monitor/vms-modal-app-02.png"
alt={t("figures.f02.alt")}
caption={t("figures.f02.caption")}
alt={t("figures.catalog.alt")}
caption={t("figures.catalog.caption")}
/>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("manual.heading")}</h2>
<p className="text-gray-800">{t.rich("manual.p1", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t.rich("manual.p2", { strong, em, code })}</p>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("manual.nameHeading")}</h3>
<p className="text-gray-800">{t.rich("manual.nameBody", { strong, em, code })}</p>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("manual.linksHeading")}</h3>
<p className="text-gray-800">{t("manual.linksLead")}</p>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{manualLinks.map((_, idx) => (
<li key={idx}>{t.rich(`manual.linksItems.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t.rich("manual.linksTrailing", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t.rich("manual.linksConfirm", { strong, em, code })}</p>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("docker.heading")}</h2>
<p className="text-gray-800">{t.rich("docker.lead", { strong, em, code })}</p>
{richList("docker.items", v.docker.items)}
<Callout variant="info">{t.rich("docker.callout", { strong, em, code })}</Callout>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("webLinks.heading")}</h2>
<p className="text-gray-800">{t("webLinks.lead")}</p>
{richList("webLinks.items", v.webLinks.items)}
<Figure
src="/monitor/vms-modal-app-03.png"
alt={t("figures.f03.alt")}
caption={t("figures.f03.caption")}
alt={t("figures.webLinks.alt")}
caption={t("figures.webLinks.caption")}
/>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("multiple.heading")}</h2>
<p className="text-gray-800">{t.rich("multiple.intro", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t("multiple.usefulLead")}</p>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{multipleUseful.map((_, idx) => (
<li key={idx}>{t.rich(`multiple.usefulItems.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t.rich("multiple.dontGroup", { strong, em, code })}</p>
<Figure
src="/monitor/vms-modal-app-04.png"
alt={t("figures.f04.alt")}
caption={t("figures.f04.caption")}
/>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("tracking.heading")}</h2>
<p className="text-gray-800">{t("tracking.intro")}</p>
<ol className="list-decimal pl-6 mt-2 space-y-1 text-gray-800">
{ingredients.map((_, idx) => (
<li key={idx}>{t.rich(`tracking.ingredients.${idx}`, { strong, em, code })}</li>
))}
</ol>
<p className="text-gray-800 mt-4">{t.rich("tracking.trailing", { strong, em, code })}</p>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("tracking.methodsHeading")}</h3>
<p className="text-gray-800">{t("tracking.methodsLead")}</p>
<div className="overflow-x-auto my-4">
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("tracking.heading")}</h2>
<p className="text-gray-800">{t.rich("tracking.lead", { strong, em, code })}</p>
<div className="my-4 overflow-x-auto">
<table className="w-full border-collapse text-sm">
<thead>
<tr className="bg-gray-100">
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.methodsTable.colMethod")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.methodsTable.colWhen")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.colMethod")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.colUse")}</th>
</tr>
</thead>
<tbody>
{methodsRows.map((row, idx) => (
{v.tracking.detectorRows.map((row, idx) => (
<tr key={idx}>
<td className="border border-gray-300 px-3 py-2 font-mono text-xs">{row.method}</td>
<td className="border border-gray-300 px-3 py-2">{row.when}</td>
<td className="border border-gray-300 px-3 py-2">{row.use}</td>
</tr>
))}
</tbody>
</table>
</div>
<p className="text-gray-800 mt-4">{t.rich("tracking.methodsTrailing", { strong, em, code })}</p>
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.commandHeading")}</h4>
<p className="text-gray-800">{t.rich("tracking.commandP1", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t("tracking.commandP2")}</p>
<CopyableCode code={t("tracking.commandExample1")} language="text" />
<p className="text-gray-800 mt-4">{t("tracking.commandP3")}</p>
<CopyableCode code={t("tracking.commandExample2")} language="text" />
<p className="text-gray-800 mt-4">{t.rich("tracking.commandP4", { strong, em, code })}</p>
<h3 className="mt-8 mb-2 text-lg font-semibold text-gray-900">{t("tracking.sourcesHeading")}</h3>
{richList("tracking.sources", v.tracking.sources)}
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("tracking.sourceHeading")}</h3>
<p className="text-gray-800">{t("tracking.sourceLead")}</p>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{sourceItems.map((_, idx) => (
<li key={idx}>{t.rich(`tracking.sourceItems.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t.rich("tracking.sourceTrailing", { strong, em, code })}</p>
<h3 className="mt-8 mb-2 text-lg font-semibold text-gray-900">{t("tracking.regexHeading")}</h3>
<p className="text-gray-800">{t.rich("tracking.regexLead", { strong, em, code })}</p>
{richList("tracking.regexRules", v.tracking.regexRules)}
<p className="mt-4 text-gray-800">{t("tracking.regexExampleLead")}</p>
<CopyableCode code={t.raw("tracking.regexExample") as string} language="text" />
<Callout variant="warning">{t.rich("tracking.regexCallout", { strong, em, code })}</Callout>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("tracking.regexHeading")}</h3>
<p className="text-gray-800">{t.rich("tracking.regexIntro", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t.rich("tracking.regexOptional", { strong, em, code })}</p>
<Figure
src="/monitor/vms-modal-app-05.png"
alt={t("figures.tracking.alt")}
caption={t("figures.tracking.caption")}
/>
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.regexTwoHeading")}</h4>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{regexTwoItems.map((_, idx) => (
<li key={idx}>{t.rich(`tracking.regexTwoItems.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t.rich("tracking.regexTwoTrailing", { strong, em, code })}</p>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("updater.heading")}</h2>
<p className="text-gray-800">{t.rich("updater.lead", { strong, em, code, link: linkUpdates })}</p>
{richList("updater.items", v.updater.items)}
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.step1Heading")}</h4>
<p className="text-gray-800">{t("tracking.step1P1")}</p>
<p className="text-gray-800 mt-4">{t("tracking.step1P2")}</p>
<p className="text-gray-800 mt-4">{t("tracking.step1P3")}</p>
<CopyableCode code={t("tracking.step1Cmd")} language="sh" />
<p className="text-gray-800 mt-4">{t("tracking.step1P4")}</p>
<CopyableCode code={t("tracking.step1Output")} language="text" />
<p className="text-gray-800 mt-4">{t("tracking.step1P5")}</p>
<p className="text-gray-800 mt-4">{t("tracking.step1P6")}</p>
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.step2Heading")}</h4>
<p className="text-gray-800">{t.rich("tracking.step2Lead", { strong, em, code })}</p>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{step2Items.map((_, idx) => (
<li key={idx}>{t.rich(`tracking.step2Items.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t("tracking.step2Recommended")}</p>
<CopyableCode code={t("tracking.step2Regex")} language="text" />
<p className="text-gray-800 mt-4">{t("tracking.step2ReadLead")}</p>
<div className="overflow-x-auto my-4">
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("states.heading")}</h2>
<div className="my-4 overflow-x-auto">
<table className="w-full border-collapse text-sm">
<thead>
<tr className="bg-gray-100">
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.step2Breakdown.colPart")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.step2Breakdown.colMeaning")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("states.colState")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("states.colDisplay")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("states.colMeaning")}</th>
</tr>
</thead>
<tbody>
{breakdownRows.map((row, idx) => (
{v.states.rows.map((row, idx) => (
<tr key={idx}>
<td className="border border-gray-300 px-3 py-2 font-mono text-xs">{row.part}</td>
<td className="border border-gray-300 px-3 py-2 font-medium">{row.state}</td>
<td className="border border-gray-300 px-3 py-2">{row.display}</td>
<td className="border border-gray-300 px-3 py-2">{row.meaning}</td>
</tr>
))}
</tbody>
</table>
</div>
<p className="text-gray-800 mt-4">{t.rich("tracking.step2DotNote", { strong, em, code })}</p>
<Figure
src="/monitor/vms-modal-app-06.png"
alt={t("figures.card.alt")}
caption={t("figures.card.caption")}
/>
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.step3Heading")}</h4>
<p className="text-gray-800">{t("tracking.step3Lead")}</p>
<div className="overflow-x-auto my-4">
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("management.heading")}</h2>
<p className="text-gray-800">{t("management.lead")}</p>
{richList("management.items", v.management.items)}
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("troubleshooting.heading")}</h2>
<div className="my-4 overflow-x-auto">
<table className="w-full border-collapse text-sm">
<thead>
<tr className="bg-gray-100">
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.step3Examples.colText")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.step3Examples.colRegex")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("tracking.step3Examples.colResult")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("troubleshooting.colProblem")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("troubleshooting.colResolution")}</th>
</tr>
</thead>
<tbody>
{exampleRows.map((row, idx) => (
{v.troubleshooting.rows.map((row, idx) => (
<tr key={idx}>
<td className="border border-gray-300 px-3 py-2 font-mono text-xs">{row.text}</td>
<td className="border border-gray-300 px-3 py-2 font-mono text-xs">{row.regex}</td>
<td className="border border-gray-300 px-3 py-2 font-mono text-xs">{row.result}</td>
<td className="border border-gray-300 px-3 py-2 font-medium">{row.problem}</td>
<td className="border border-gray-300 px-3 py-2">{row.resolution}</td>
</tr>
))}
</tbody>
</table>
</div>
<p className="text-gray-800 mt-4">{t.rich("tracking.step3Note1", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t.rich("tracking.step3Note2", { strong, em, code })}</p>
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.step4Heading")}</h4>
<p className="text-gray-800">{t("tracking.step4Intro")}</p>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{step4Items.map((_, idx) => (
<li key={idx}>{t.rich(`tracking.step4Items.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t.rich("tracking.step4Trailing", { strong, em, code })}</p>
<p className="text-gray-800 mt-4"><strong>{t("tracking.step4RecLabel")}</strong></p>
<CopyableCode code={t.raw("tracking.step4RecRegex") as string} language="text" />
<p className="text-gray-800 mt-4"><strong>{t("tracking.step4LessLabel")}</strong></p>
<CopyableCode code={t("tracking.step4LessRegex")} language="text" />
<p className="text-gray-800 mt-4">{t.rich("tracking.step4Note", { strong, em, code })}</p>
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.step5Heading")}</h4>
<p className="text-gray-800">{t("tracking.step5Lead")}</p>
<CopyableCode code={t("tracking.step5Regex")} language="text" />
<p className="text-gray-800 mt-4">{t.rich("tracking.step5P1", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t("tracking.step5P2")}</p>
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("tracking.step6Heading")}</h4>
<p className="text-gray-800">{t.rich("tracking.step6Lead", { strong, em, code })}</p>
<CopyableCode code={t("tracking.step6Output")} language="text" />
<p className="text-gray-800 mt-4">{t("tracking.step6CorrectLead")}</p>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{step6CorrectItems.map((_, idx) => (
<li key={idx}>{t.rich(`tracking.step6CorrectItems.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t.rich("tracking.step6ErrorNote", { strong, em, code })}</p>
<Callout variant="tip">{t.rich("tracking.step6Callout", { strong, em, code })}</Callout>
<Figure
src="/monitor/vms-modal-app-05.png"
alt={t("figures.f05.alt")}
caption={t("figures.f05.caption")}
/>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("state.heading")}</h2>
<Figure
src="/monitor/vms-modal-app-06.png"
alt={t("figures.f06.alt")}
caption={t("figures.f06.caption")}
/>
<p className="text-gray-800">{t("state.lead")}</p>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{stateItems.map((_, idx) => (
<li key={idx}>{t.rich(`state.items.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t.rich("state.trailing", { strong, em, code })}</p>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("manage.heading")}</h2>
<p className="text-gray-800">{t("manage.lead")}</p>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{manageItems.map((_, idx) => (
<li key={idx}>{t.rich(`manage.items.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t.rich("manage.trailing", { strong, em, code })}</p>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("options.heading")}</h2>
<p className="text-gray-800">{t("options.lead")}</p>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{optionsItems.map((_, idx) => (
<li key={idx}>{t.rich(`options.items.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t.rich("options.trailing", { strong, em, code })}</p>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("notDetected.heading")}</h2>
<p className="text-gray-800">{t("notDetected.intro")}</p>
<ol className="list-decimal pl-6 mt-2 space-y-1 text-gray-800">
{notDetectedSteps.map((_, idx) => (
<li key={idx}>{t.rich(`notDetected.steps.${idx}`, { strong, em, code, link: linkUpdates })}</li>
))}
</ol>
<p className="text-gray-800 mt-4">{t.rich("notDetected.trailing", { strong, em, code })}</p>
<Figure
src="/monitor/vms-modal-app-07.png"
alt={t("figures.f07.alt")}
caption={t("figures.f07.caption")}
/>
</div>
)
}
@@ -225,38 +225,34 @@ export default async function VmsLxcsTabPage({
<h4 className="text-base font-semibold mt-6 mb-2 text-gray-900">{t("drillIn.ipsTitle")}</h4>
<p className="mb-6 text-gray-800 leading-relaxed">{t("drillIn.ipsBody")}</p>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">App</h3>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("drillIn.appTitle")}</h3>
<p className="mb-4 text-gray-800 leading-relaxed">
The <strong>App</strong> section lets you register the applications running inside an LXC, wire quick web
links, and optionally track installed vs. upstream versions. Registrations feed the App-level notifications
and the update flows on the next section.
{t.rich("drillIn.appIntro", { strong, em, code })}
</p>
<p className="mb-6 text-gray-800 leading-relaxed">
See the{" "}
{t("drillIn.appLinkLead")}{" "}
<Link
href="/docs/monitor/dashboard/vms-lxcs/app"
className="text-blue-600 hover:underline"
>
dedicated App page
{t("drillIn.appLinkLabel")}
</Link>{" "}
for the catalog, manual registration, version-tracking methods and regex patterns.
{t("drillIn.appLinkTail")}
</p>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">Updates</h3>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("drillIn.updatesTitle")}</h3>
<p className="mb-4 text-gray-800 leading-relaxed">
The <strong>Updates</strong> section covers OS package updates (APT / APK) and application updates via
Community Scripts helpers or custom commands. Detection runs unconditionally on running LXCs; whether pending
updates also trigger a notification is controlled from <strong>Settings Notifications</strong>.
{t.rich("drillIn.updatesIntro", { strong, em, code })}
</p>
<p className="mb-6 text-gray-800 leading-relaxed">
See the{" "}
{t("drillIn.updatesLinkLead")}{" "}
<Link
href="/docs/monitor/dashboard/vms-lxcs/updates"
className="text-blue-600 hover:underline"
>
dedicated Updates page
{t("drillIn.updatesLinkLabel")}
</Link>{" "}
for the decision matrix, custom-command guidance, backup / restart preferences and scheduled updates.
{t("drillIn.updatesLinkTail")}
</p>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("drillIn.mountsTitle")}</h3>
@@ -1,11 +1,11 @@
import type { Metadata } from "next"
import type React from "react"
import { getTranslations, getMessages, setRequestLocale } from "next-intl/server"
import { Link } from "@/i18n/navigation"
import { getMessages, getTranslations, setRequestLocale } from "next-intl/server"
import { ExternalLink } from "lucide-react"
import { DocHeader } from "@/components/ui/doc-header"
import { Link } from "@/i18n/navigation"
import { Callout } from "@/components/ui/callout"
import CopyableCode from "@/components/CopyableCode"
import { DocHeader } from "@/components/ui/doc-header"
export async function generateMetadata({
params,
@@ -17,20 +17,15 @@ export async function generateMetadata({
return { title: t("title"), description: t("description") }
}
type DecisionRow = { situation: string; action: string }
type DifferenceRow = { field: string; location: string; role: string }
type MechanismRow = { source: string; action: string; notes: string }
type StatusRow = { state: string; appearance: string; meaning: string }
type ProblemRow = { problem: string; resolution: string }
function Figure({ src, alt, caption }: { src: string; alt: string; caption: string }) {
return (
<figure className="my-6">
<img
src={src}
alt={alt}
className="rounded-lg border border-gray-200 shadow-sm w-full"
/>
<figcaption className="text-sm text-gray-500 mt-2 text-center italic">
{caption}
</figcaption>
<img src={src} alt={alt} className="w-full rounded-lg border border-gray-200 shadow-sm" />
<figcaption className="mt-2 text-center text-sm italic text-gray-500">{caption}</figcaption>
</figure>
)
}
@@ -43,58 +38,31 @@ export default async function UpdatesTabPage({
const { locale } = await params
setRequestLocale(locale)
const t = await getTranslations({ locale, namespace: "docs.monitor.dashboard.vmsLxcsUpdates" })
const messages = (await getMessages({ locale })) as unknown as {
docs: { monitor: { dashboard: { vmsLxcsUpdates: {
decision: { table: { rows: DecisionRow[] } }
figureOut: {
step3Items: string[]
step4Items: string[]
}
requirements: { items: string[] }
difference: { table: { rows: DifferenceRow[] } }
apply: {
steps: string[]
systemItems: string[]
appItems: string[]
}
scheduled: { createSteps: string[] }
overview: { items: string[] }
mechanisms: { rows: MechanismRow[] }
docker: { items: string[] }
actions: { items: string[]; statusRows: StatusRow[] }
custom: { items: string[] }
bulk: { items: string[] }
options: { items: string[] }
scheduled: { items: string[] }
completion: { items: string[] }
troubleshooting: { rows: ProblemRow[] }
} } } }
}
const v = messages.docs.monitor.dashboard.vmsLxcsUpdates
const decisionRows = v.decision.table.rows
const step3Items = v.figureOut.step3Items
const step4Items = v.figureOut.step4Items
const reqItems = v.requirements.items
const diffRows = v.difference.table.rows
const applySteps = v.apply.steps
const applySystem = v.apply.systemItems
const applyApp = v.apply.appItems
const schedSteps = v.scheduled.createSteps
// Rich-text tag handlers
const strong = (chunks: React.ReactNode) => <strong>{chunks}</strong>
const em = (chunks: React.ReactNode) => <em>{chunks}</em>
const code = (chunks: React.ReactNode) => (
<code className="text-sm bg-gray-100 px-1 rounded">{chunks}</code>
)
const code = (chunks: React.ReactNode) => <code className="rounded bg-gray-100 px-1 text-sm">{chunks}</code>
const linkApp = (chunks: React.ReactNode) => (
<Link href="/docs/monitor/dashboard/vms-lxcs/app" className="text-blue-600 hover:underline">
{chunks}
</Link>
)
const linkHelperHome = (chunks: React.ReactNode) => (
<a
href="https://community-scripts.org"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 text-blue-600 hover:underline"
>
{chunks}
<ExternalLink className="h-3.5 w-3.5" aria-hidden="true" />
</a>
)
const linkHelperDocs = (chunks: React.ReactNode) => (
const linkHelper = (chunks: React.ReactNode) => (
<a
href="https://community-scripts.org/docs/tools/pve/update-apps"
target="_blank"
@@ -106,244 +74,134 @@ export default async function UpdatesTabPage({
</a>
)
return (
<div className="max-w-4xl mx-auto px-4 py-8">
<DocHeader
title={t("header.title")}
description={t("header.description")}
estimatedMinutes={12}
/>
const richList = (base: string, items: string[]) => (
<ul className="mt-2 list-disc space-y-2 pl-6 text-gray-800">
{items.map((_, idx) => (
<li key={idx}>{t.rich(`${base}.${idx}`, { strong, em, code, link: linkApp, helper: linkHelper })}</li>
))}
</ul>
)
<p className="text-gray-800 mt-6">{t.rich("intro.p1", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t.rich("intro.p2", { strong, em, code, link: linkApp })}</p>
return (
<div className="mx-auto max-w-4xl px-4 py-8">
<DocHeader title={t("header.title")} description={t("header.description")} estimatedMinutes={10} />
<p className="mt-6 text-gray-800">{t.rich("intro.p1", { strong, em, code, link: linkApp })}</p>
<p className="mt-4 text-gray-800">{t.rich("intro.p2", { strong, em, code })}</p>
<Callout variant="info">{t.rich("intro.callout", { strong, em, code })}</Callout>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("mechanisms.heading")}</h2>
<p className="text-gray-800">{t("mechanisms.intro")}</p>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("mechanisms.osHeading")}</h3>
<p className="text-gray-800">{t("mechanisms.osP1")}</p>
<p className="text-gray-800 mt-4">{t.rich("mechanisms.osP2", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t("mechanisms.osP3")}</p>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("mechanisms.helperHeading")}</h3>
<p className="text-gray-800">{t.rich("mechanisms.helperP1", { strong, em, code, linkHelperHome })}</p>
<p className="text-gray-800 mt-4">{t.rich("mechanisms.helperP2", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">
{t.rich("mechanisms.helperP3", { strong, em, code, linkHelperHome, linkHelperDocs })}
</p>
<p className="text-gray-800 mt-4">{t.rich("mechanisms.helperP4", { strong, em, code })}</p>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("mechanisms.customHeading")}</h3>
<p className="text-gray-800">{t.rich("mechanisms.customP1", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t("mechanisms.customP2")}</p>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("decision.heading")}</h2>
<div className="overflow-x-auto my-4">
<table className="w-full border-collapse text-sm">
<thead>
<tr className="bg-gray-100">
<th className="border border-gray-300 px-3 py-2 text-left">{t("decision.table.colSituation")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("decision.table.colAction")}</th>
</tr>
</thead>
<tbody>
{decisionRows.map((row, idx) => (
<tr key={idx}>
<td className="border border-gray-300 px-3 py-2">{row.situation}</td>
<td className="border border-gray-300 px-3 py-2 font-mono text-xs">{row.action}</td>
</tr>
))}
</tbody>
</table>
</div>
<p className="text-gray-800 mt-4">{t("decision.trailing")}</p>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("overview.heading")}</h2>
<p className="text-gray-800">{t("overview.lead")}</p>
{richList("overview.items", v.overview.items)}
<Figure
src="/monitor/vms-modal-updates-01.png"
alt={t("figures.f01.alt")}
caption={t("figures.f01.caption")}
/>
<Figure
src="/monitor/vms-modal-updates-02.png"
alt={t("figures.f02.alt")}
caption={t("figures.f02.caption")}
alt={t("figures.osPending.alt")}
caption={t("figures.osPending.caption")}
/>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("custom.heading")}</h2>
<p className="text-gray-800">{t.rich("custom.p1", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t("custom.p2")}</p>
<Figure
src="/monitor/vms-modal-updates-03.png"
alt={t("figures.f03.alt")}
caption={t("figures.f03.caption")}
/>
<Figure
src="/monitor/vms-modal-updates-04.png"
alt={t("figures.f04.alt")}
caption={t("figures.f04.caption")}
/>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("figureOut.heading")}</h2>
<p className="text-gray-800">{t("figureOut.intro")}</p>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("figureOut.step1Heading")}</h3>
<p className="text-gray-800">{t.rich("figureOut.step1P1", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t("figureOut.step1P2")}</p>
<CopyableCode code={t("figureOut.step1Cmd1")} language="sh" />
<p className="text-gray-800 mt-4">{t("figureOut.step1P3")}</p>
<CopyableCode code={t("figureOut.step1Cmd2")} language="sh" />
<p className="text-gray-800 mt-4">{t.rich("figureOut.step1P4", { strong, em, code })}</p>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("figureOut.step2Heading")}</h3>
<p className="text-gray-800">{t.rich("figureOut.step2P1", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t("figureOut.step2P2")}</p>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("figureOut.step3Heading")}</h3>
<p className="text-gray-800">{t("figureOut.step3Lead")}</p>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{step3Items.map((_, idx) => (
<li key={idx}>{t.rich(`figureOut.step3Items.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t("figureOut.step3P1")}</p>
<CopyableCode code={t("figureOut.step3Cmd")} language="sh" />
<p className="text-gray-800 mt-4">{t.rich("figureOut.step3P2", { strong, em, code })}</p>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("figureOut.step4Heading")}</h3>
<p className="text-gray-800">{t("figureOut.step4Lead")}</p>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{step4Items.map((_, idx) => (
<li key={idx}>{t.rich(`figureOut.step4Items.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t("figureOut.step4Note")}</p>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("figureOut.step5Heading")}</h3>
<p className="text-gray-800">{t("figureOut.step5P1")}</p>
<CopyableCode code={t.raw("figureOut.step5Cmd1") as string} language="text" />
<p className="text-gray-800 mt-4">{t.rich("figureOut.step5P2", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t("figureOut.step5P3")}</p>
<CopyableCode code={t("figureOut.step5Cmd2")} language="sh" />
<p className="text-gray-800 mt-4">{t("figureOut.step5P4")}</p>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("requirements.heading")}</h2>
<p className="text-gray-800">{t("requirements.lead")}</p>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{reqItems.map((_, idx) => (
<li key={idx}>{t.rich(`requirements.items.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t.rich("requirements.trailing", { strong, em, code })}</p>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("difference.heading")}</h2>
<p className="text-gray-800">{t("difference.lead")}</p>
<div className="overflow-x-auto my-4">
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("mechanisms.heading")}</h2>
<p className="text-gray-800">{t.rich("mechanisms.lead", { strong, em, code, helper: linkHelper })}</p>
<div className="my-4 overflow-x-auto">
<table className="w-full border-collapse text-sm">
<thead>
<tr className="bg-gray-100">
<th className="border border-gray-300 px-3 py-2 text-left">{t("difference.table.colField")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("difference.table.colLocation")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("difference.table.colRole")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("mechanisms.colSource")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("mechanisms.colAction")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("mechanisms.colNotes")}</th>
</tr>
</thead>
<tbody>
{diffRows.map((row, idx) => (
{v.mechanisms.rows.map((row, idx) => (
<tr key={idx}>
<td className="border border-gray-300 px-3 py-2 font-medium">{row.field}</td>
<td className="border border-gray-300 px-3 py-2 text-xs">{row.location}</td>
<td className="border border-gray-300 px-3 py-2 text-xs">{row.role}</td>
<td className="border border-gray-300 px-3 py-2 font-medium">{row.source}</td>
<td className="border border-gray-300 px-3 py-2">{row.action}</td>
<td className="border border-gray-300 px-3 py-2">{row.notes}</td>
</tr>
))}
</tbody>
</table>
</div>
<p className="text-gray-800 mt-4">{t.rich("difference.trailing", { strong, em, code })}</p>
<Callout variant="warning">{t.rich("mechanisms.callout", { strong, em, code })}</Callout>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("apply.heading")}</h2>
<p className="text-gray-800">{t("apply.lead")}</p>
<ol className="list-decimal pl-6 mt-2 space-y-1 text-gray-800">
{applySteps.map((_, idx) => (
<li key={idx}>{t.rich(`apply.steps.${idx}`, { strong, em, code })}</li>
))}
</ol>
<p className="text-gray-800 mt-4">{t("apply.trailing1")}</p>
<p className="text-gray-800 mt-4">{t("apply.systemLead")}</p>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{applySystem.map((_, idx) => (
<li key={idx}>{t.rich(`apply.systemItems.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t("apply.appLead")}</p>
<ul className="list-disc pl-6 mt-2 space-y-1 text-gray-800">
{applyApp.map((_, idx) => (
<li key={idx}>{t.rich(`apply.appItems.${idx}`, { strong, em, code })}</li>
))}
</ul>
<p className="text-gray-800 mt-4">{t("apply.trailing2")}</p>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("docker.heading")}</h2>
<p className="text-gray-800">{t.rich("docker.lead", { strong, em, code })}</p>
{richList("docker.items", v.docker.items)}
<Callout variant="info">{t.rich("docker.callout", { strong, em, code })}</Callout>
<Figure
src="/monitor/vms-modal-updates-05.png"
alt={t("figures.f05.alt")}
caption={t("figures.f05.caption")}
/>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("actions.heading")}</h2>
<p className="text-gray-800">{t("actions.lead")}</p>
{richList("actions.items", v.actions.items)}
<div className="my-4 overflow-x-auto">
<table className="w-full border-collapse text-sm">
<thead>
<tr className="bg-gray-100">
<th className="border border-gray-300 px-3 py-2 text-left">{t("actions.statusColState")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("actions.statusColAppearance")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("actions.statusColMeaning")}</th>
</tr>
</thead>
<tbody>
{v.actions.statusRows.map((row, idx) => (
<tr key={idx}>
<td className="border border-gray-300 px-3 py-2 font-medium">{row.state}</td>
<td className="border border-gray-300 px-3 py-2">{row.appearance}</td>
<td className="border border-gray-300 px-3 py-2">{row.meaning}</td>
</tr>
))}
</tbody>
</table>
</div>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("backup.heading")}</h2>
<p className="text-gray-800">{t.rich("backup.p1", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t("backup.p2")}</p>
<p className="text-gray-800 mt-4">{t("backup.p3")}</p>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("custom.heading")}</h2>
<p className="text-gray-800">{t.rich("custom.lead", { strong, em, code })}</p>
{richList("custom.items", v.custom.items)}
<p className="mt-4 text-gray-800">{t("custom.exampleLead")}</p>
<CopyableCode code={t("custom.example")} language="sh" />
<Callout variant="warning">{t.rich("custom.callout", { strong, em, code })}</Callout>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("restart.heading")}</h2>
<p className="text-gray-800">{t.rich("restart.p1", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t("restart.p2")}</p>
<p className="text-gray-800 mt-4">{t("restart.p3")}</p>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("bulk.heading")}</h2>
<p className="text-gray-800">{t.rich("bulk.lead", { strong, em, code })}</p>
{richList("bulk.items", v.bulk.items)}
<Callout variant="info">{t.rich("bulk.callout", { strong, em, code })}</Callout>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("options.heading")}</h2>
<p className="text-gray-800">{t("options.lead")}</p>
{richList("options.items", v.options.items)}
<Figure
src="/monitor/vms-modal-updates-06.png"
alt={t("figures.f06.alt")}
caption={t("figures.f06.caption")}
alt={t("figures.options.alt")}
caption={t("figures.options.caption")}
/>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("scheduled.heading")}</h2>
<p className="text-gray-800">{t.rich("scheduled.p1", { strong, em, code })}</p>
<p className="text-gray-800 mt-4">{t("scheduled.createLead")}</p>
<ol className="list-decimal pl-6 mt-2 space-y-1 text-gray-800">
{schedSteps.map((_, idx) => (
<li key={idx}>{t.rich(`scheduled.createSteps.${idx}`, { strong, em, code })}</li>
))}
</ol>
<p className="text-gray-800 mt-4">{t("scheduled.p2")}</p>
<p className="text-gray-800 mt-4">{t("scheduled.p3")}</p>
<Callout variant="tip">{t("scheduled.callout")}</Callout>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("scheduled.heading")}</h2>
<p className="text-gray-800">{t.rich("scheduled.lead", { strong, em, code })}</p>
{richList("scheduled.items", v.scheduled.items)}
<Callout variant="tip">{t.rich("scheduled.callout", { strong, em, code })}</Callout>
<Figure
src="/monitor/vms-modal-updates-07.png"
alt={t("figures.f07.alt")}
caption={t("figures.f07.caption")}
/>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("completion.heading")}</h2>
<p className="text-gray-800">{t("completion.lead")}</p>
{richList("completion.items", v.completion.items)}
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("verify.heading")}</h2>
<p className="text-gray-800">{t("verify.p1")}</p>
<p className="text-gray-800 mt-4">{t.rich("verify.p2", { strong, em, code, link: linkApp })}</p>
<p className="text-gray-800 mt-4">{t("verify.p3")}</p>
<h2 className="text-2xl font-semibold mt-10 mb-4 text-gray-900">{t("troubleshoot.heading")}</h2>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("troubleshoot.noButtonHeading")}</h3>
<Callout variant="troubleshoot">{t.rich("troubleshoot.noButtonBody", { strong, em, code })}</Callout>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("troubleshoot.aptHeading")}</h3>
<Callout variant="troubleshoot">{t.rich("troubleshoot.aptBody", { strong, em, code })}</Callout>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("troubleshoot.noUpdaterHeading")}</h3>
<Callout variant="troubleshoot">{t.rich("troubleshoot.noUpdaterBody", { strong, em, code })}</Callout>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("troubleshoot.helperDetectedHeading")}</h3>
<Callout variant="troubleshoot">{t.rich("troubleshoot.helperDetectedBody", { strong, em, code })}</Callout>
<h3 className="text-lg font-semibold mt-8 mb-2 text-gray-900">{t("troubleshoot.customFailsHeading")}</h3>
<Callout variant="troubleshoot">{t.rich("troubleshoot.customFailsBody", { strong, em, code })}</Callout>
<h2 className="mt-10 mb-4 text-2xl font-semibold text-gray-900">{t("troubleshooting.heading")}</h2>
<div className="my-4 overflow-x-auto">
<table className="w-full border-collapse text-sm">
<thead>
<tr className="bg-gray-100">
<th className="border border-gray-300 px-3 py-2 text-left">{t("troubleshooting.colProblem")}</th>
<th className="border border-gray-300 px-3 py-2 text-left">{t("troubleshooting.colResolution")}</th>
</tr>
</thead>
<tbody>
{v.troubleshooting.rows.map((row, idx) => (
<tr key={idx}>
<td className="border border-gray-300 px-3 py-2 font-medium">{row.problem}</td>
<td className="border border-gray-300 px-3 py-2">{row.resolution}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)
}
@@ -105,6 +105,18 @@
"imageAlt": "Final summary + reboot prompt after a PCIe install"
}
},
"legacyCleanup": {
"heading": "Cleaning up legacy gasket-dkms on USB-only hosts",
"intro": "If the host has <strong>no detected PCIe / M.2 Coral</strong> but still contains a previous <code>gasket-dkms</code> installation, ProxMenux identifies that state separately and offers an optional cleanup. Nothing is removed without confirmation.",
"items": [
"If a PCIe / M.2 Coral is present, this cleanup is never offered; the normal DKMS rebuild path is used instead.",
"The cleanup purges <code>gasket-dkms</code>, removes stale gasket DKMS registrations and source trees, and repairs pending <code>dpkg</code> / APT state.",
"The USB runtime packages <code>libedgetpu1-std</code> and <code>libedgetpu1-max</code> are left untouched, so a USB Coral keeps its runtime.",
"The script verifies that the legacy package is gone and that package management is healthy before reporting success."
],
"warningTitle": "Confirm the hardware first",
"warningBody": "If a PCIe / M.2 Coral may be installed but is not being detected, cancel the cleanup and check the card, slot and firmware settings before continuing."
},
"reinstallUninstall": {
"heading": "Reinstall or uninstall",
"intro": "Running the installer on a host where Coral is already installed (PCIe via <code>gasket-dkms</code>, USB via <code>libedgetpu1-std</code>/<code>libedgetpu1-max</code>, or both) no longer drops straight into another fresh install. Instead, ProxMenux detects the existing setup and shows an action menu so you can decide what to do.",
@@ -1,281 +1,183 @@
{
"meta": {
"title": "App — register and monitor LXC applications | ProxMenux",
"description": "Declare the apps running inside an LXC container from the ProxMenux Monitor and optionally track their versions."
"title": "LXC App tab: discovery, links and version tracking | ProxMenux",
"description": "Discover and register LXC applications, create web links and optionally track installed and available versions."
},
"header": {
"title": "App — register and monitor LXC applications",
"description": "Declare the apps running inside a container, wire quick web links, and optionally track installed vs. upstream versions."
"title": "LXC App tab: discovery, links and version tracking",
"description": "Give each LXC application a persistent identity, web access and optional version evidence without coupling registration to updates."
},
"intro": {
"p1": "The <strong>App</strong> tab records which applications run inside an LXC container. Each registered app can expose a display name, an icon, one or several web links and — optionally — its version status.",
"p2": "A single LXC can host several registered applications. A main service can share the container with an administration interface, an API or any other application reachable on a different port.",
"p3": "Registering an application does not modify it or update it. This tab is about identification and display. The mechanisms that <em>execute</em> an update are configured and used from the <link>Updates tab</link>."
"p1": "The <strong>App</strong> tab records which applications belong to an LXC. A registration can contain only a name and web link, or also include an installed-version detector and an upstream source.",
"p2": "The procedure that changes software is configured separately on the <link>Updates tab</link>. Saving an app never runs an installer or updater.",
"callout": "Registration, version tracking and updating are three independent capabilities. Any one can be used without requiring the other two."
},
"whatYouGet": {
"heading": "What you get by registering an app",
"lead": "Depending on the data configured, ProxMenux can surface:",
"overview": {
"heading": "What an application record can provide",
"lead": "A single saved record can include:",
"items": [
"A one-click shortcut to the application's web UI.",
"Multiple links when the LXC exposes more than one service or port.",
"The version currently installed.",
"The latest version published by the project.",
"A notice when a newer version is available.",
"Notifications on new releases if enabled in Monitor settings."
"A display name and a theme-aware logo.",
"One or more clickable web links built from the LXC address, scheme and saved port.",
"An optional detector for the version currently installed inside the LXC.",
"An optional GitHub, HTTP JSON or Docker Hub source for the latest available version.",
"Per-application release notifications and update-counter inclusion preferences.",
"A corresponding section on the Updates tab, even when version tracking is disabled."
]
},
"discovery": {
"heading": "Cached discovery and Find applications",
"lead": "Application suggestions are part of the per-LXC modal cache. The startup scan prepares them in the background so opening the App tab can show cached results immediately.",
"items": [
"Opening the App tab does <strong>not</strong> start a new catalog scan and does not repeatedly query the LXC.",
"<strong>Find applications</strong> explicitly runs a fresh discovery pass for that LXC. Use it after installing new software while ProxMenux is already running.",
"The previous list remains visible while the explicit scan runs. New matches are added when it finishes.",
"If no new match is found, the result is stated beside the actions and <strong>Register application</strong> remains available for manual entry.",
"Saving, removing or restoring an app updates the same cache immediately. Starting or restoring an LXC refreshes only that guest through its existing lifecycle event."
],
"trailing": "Version tracking is optional. An app can be registered purely to keep its name, icon and web links handy.",
"callout": "The <strong>Update available</strong> label means ProxMenux found a difference between the installed and the published version. It does not automatically mean it also knows how to upgrade the app — that is a separate setup, done on the Updates tab."
"callout": "A suggestion is not a registration. It stays read-only until <strong>Register</strong> is pressed and the form is saved."
},
"firstOpening": {
"heading": "First time opening the App tab",
"p1": "On first open, ProxMenux tries to recognise apps in the container using the information it has: the installer used when the LXC was created, detected services, and ports that are listening.",
"p2": "When matches are found, they show up as suggestions. Always review the proposal before saving — auto-detection speeds up registration, but it cannot guarantee that every detected service corresponds exactly to the app you intended."
},
"figures": {
"f01": {
"alt": "Empty App tab showing detected app suggestions",
"caption": "Empty state with one or more detected suggestions"
},
"f02": {
"alt": "Catalog search showing matches for the typed name",
"caption": "Catalog search and match selection"
},
"f03": {
"alt": "App registration form with name, icon and two web links",
"caption": "Basic form with name, icon and two web links"
},
"f04": {
"alt": "LXC with Docmost and Redis both registered as separate apps, each with its own version state",
"caption": "Two apps in the same LXC — a file-tracked app and a dpkg-tracked one, each with its own version state"
},
"f05": {
"alt": "Advanced tracking options showing the installed-version method and the upstream source",
"caption": "Advanced options with the installed-version method and the upstream source"
},
"f06": {
"alt": "Registered app card with the installed version, the latest upstream version and an Update available indicator",
"caption": "A wired card shows Installed, Latest upstream, an Update-available arrow when they differ, and the web link"
},
"f07": {
"alt": "Minimal registered app showing just its name and a single web link, no version tracking",
"caption": "Link-only record — just a name and a web link, without version tracking"
}
},
"registerSuggested": {
"heading": "Registering a suggested app",
"registration": {
"heading": "Registering an application",
"lead": "A detected suggestion and a manual record use the same editor:",
"steps": [
"Open the LXC from the <strong>VMs & LXCs</strong> card.",
"Select the <strong>App</strong> tab.",
"Locate the suggested app.",
"Press <strong>Register</strong>.",
"Check the name, links and auto-filled data.",
"Save the app."
],
"trailing": "If a suggestion doesn't match anything you actually want to register, you can hide it. Hidden suggestions can be brought back from <strong>Register a different app</strong>."
"Press <strong>Register</strong> on a suggestion or <strong>Register application</strong> to choose from the catalog or enter a custom name.",
"Review the name and logo proposed by the catalog.",
"Add the required web links. Detected listening ports are offered as shortcuts, but none is saved automatically.",
"Leave <strong>Track upstream version</strong> disabled for a link-only record, or enable it and review the installed-version detector and upstream source.",
"Use <strong>Test detector</strong> when tracking is enabled, then save the record.",
"Press <strong>Done</strong> after editing. The App and Updates tabs reuse the updated cached record."
]
},
"catalog": {
"heading": "Using the catalog",
"p1": "The catalog helps you find known applications and pre-fill some of their data. Typing into the name field shows the closest matches — picking one can autofill the name, icon, typical ports and, when a verified profile exists, the version-tracking options too.",
"p2": "The catalog is a helper, not a complete list of every piece of software an LXC might host. Some entries only carry basic information; others also include a ready-made way to read the installed version.",
"p3": "If the application isn't in the catalog, register it manually."
"heading": "Catalog-assisted registration",
"lead": "The catalog supplies defaults, but the saved record remains editable.",
"items": [
"Search results can prefill the canonical name, logo and common web ports.",
"Known version detectors are based on real package names, binaries, files, Python distributions, OCI labels or commands rather than a universal <code>/root/.app</code> assumption.",
"Verified runtime overrides take precedence when an installation uses a path that differs from its installer metadata.",
"Proxmox VE Helper-Scripts markers such as <code>/root/.slug</code> remain one compatibility signal for newer helper installations, not the only detector.",
"Every proposed value can be edited before saving to cover official installers and manual installations."
]
},
"manual": {
"heading": "Register an application manually",
"p1": "Use <strong>Register a different app</strong> when the LXC has no apps yet. If it already has at least one, use <strong>Add another application</strong>.",
"p2": "The basic configuration only needs a name. Everything else is added according to what you want to display.",
"nameHeading": "Name and icon",
"nameBody": "Give the app a name that makes it easy to recognise. The icon is optional and can be supplied as a URL.",
"linksHeading": "Web links and ports",
"linksLead": "Each link can carry:",
"linksItems": [
"Protocol <code>http</code> or <code>https</code>.",
"Port.",
"Description, such as <em>Web UI</em>, <em>Administration</em> or <em>API</em>.",
"An optional per-link icon."
"docker": {
"heading": "How Docker LXCs are represented",
"lead": "For an LXC whose primary platform is Docker, <strong>Docker</strong> is the application registered at LXC level.",
"items": [
"A containerized workload such as Portainer, Frigate or Vaultwarden is not suggested as an independent native LXC application.",
"Running Docker services with published TCP ports are offered inside the Docker editor as optional web links.",
"Each suggested link shows the service, host port and container port. Only links that provide a web interface should be saved.",
"The global Docker logo is used when a link has no specific logo. A per-link logo overrides it when one is configured.",
"After Docker is registered, Docker Engine and image updates are shown together in its section on the Updates tab."
],
"linksTrailing": "ProxMenux combines protocol and port with the LXC's IP address to build the URL. Add as many links as the app needs when a single container exposes several related services.",
"linksConfirm": "Before saving, confirm the port really corresponds to the service and that you can reach it from the browser."
"callout": "This structure prevents a Docker workload from looking like software installed directly in the LXC while preserving quick links to its interfaces."
},
"multiple": {
"heading": "Registering several apps in the same LXC",
"intro": "After saving the first app, press <strong>Add another application</strong> and repeat. Each record keeps its own links, detection method and version state independently.",
"usefulLead": "This is useful when:",
"usefulItems": [
"An LXC hosts several independent services.",
"An installation includes a main app plus companion tooling.",
"Each service has its own web interface or its own release cycle."
],
"dontGroup": "Don't group under a single record programs that publish and update independently. Registering them separately makes it clear which one has a new release and lets each one carry its own update method on the Updates tab."
"webLinks": {
"heading": "Web links and logos",
"lead": "Web links work with or without version tracking.",
"items": [
"Each link stores a scheme, port, optional description and optional logo URL.",
"The displayed URL uses the current address already detected for the LXC; the address is not duplicated in every app record.",
"A link without its own logo falls back to the app-level logo.",
"Several links can represent an admin interface, API, secondary UI or another endpoint of the same app.",
"A saved link-only app also appears on Updates, where a custom updater can be configured later."
]
},
"tracking": {
"heading": "Version tracking",
"intro": "Open the advanced options in the form to configure version tracking. Two different pieces of information are needed:",
"ingredients": [
"<strong>Installed version</strong> — how to read the version currently running inside the LXC.",
"<strong>Latest available version</strong> — where to read the version published by the project."
"heading": "Optional version tracking",
"lead": "Tracking combines an installed-version detector with an optional upstream source. The two sides are checked independently.",
"colMethod": "Installed-version method",
"colUse": "Use",
"detectorRows": [
{ "method": "dpkg / apk", "use": "Reads the installed package version from Debian, Ubuntu or Alpine package metadata." },
{ "method": "binary", "use": "Runs an absolute binary path or a command name with version arguments." },
{ "method": "file + regex", "use": "Reads a real file and extracts the version with one capture group." },
{ "method": "docker label / docker exec", "use": "Reads an OCI version label or runs a version command inside a Docker container." },
{ "method": "python distribution", "use": "Uses importlib.metadata through the selected Python interpreter." },
{ "method": "command", "use": "Runs an advanced argv-style command without a shell and extracts the version from its output." },
{ "method": "manual", "use": "Stores a version entered manually; it must be changed after upgrading the app." }
],
"trailing": "If only the installed version is configured, ProxMenux can show it, but cannot tell whether an update exists. For an <strong>Update available</strong> label to appear, both values have to be readable and comparable.",
"methodsHeading": "Methods to read the installed version",
"methodsLead": "Pick the method that matches how the app was installed:",
"methodsTable": {
"colMethod": "Method",
"colWhen": "When to use it",
"rows": [
{ "method": "None (link only)", "when": "You only need the name and web links." },
{ "method": "dpkg package", "when": "The application is installed as a Debian or Ubuntu package." },
{ "method": "apk package", "when": "The application is installed as an Alpine package." },
{ "method": "Binary", "when": "An executable returns its version through an argument like --version." },
{ "method": "File + regex", "when": "The version string is written inside a file." },
{ "method": "Python distribution", "when": "The application is installed as a Python package." },
{ "method": "Command", "when": "A specific command must be executed to obtain the version." },
{ "method": "Manual", "when": "The user enters the installed version by hand." }
]
},
"methodsTrailing": "Use the most direct and stable method. If the application comes from a system package, prefer querying that package over parsing the output of a generic command.",
"commandHeading": "The Command method does not update the app",
"commandP1": "In this form, <strong>Command</strong> serves exclusively to read the installed version. Its arguments are entered comma-separated and ProxMenux runs them directly, without a shell interpreter.",
"commandP2": "If your usual query is:",
"commandExample1": "myapp version --short",
"commandP3": "Form arguments would be:",
"commandExample2": "myapp, version, --short",
"commandP4": "Don't use operators like <code>&&</code>, redirections or pipes here. If you need a full procedure to upgrade the application, that is configured later on the Updates tab.",
"sourceHeading": "Source for the latest available version",
"sourceLead": "ProxMenux can query a public source of the project, for example:",
"sourceItems": [
"The releases or tags of a GitHub repository.",
"An HTTP endpoint that returns the version inside a JSON response."
"sourcesHeading": "Available-version sources",
"sources": [
"<strong>GitHub repository</strong>: latest release or tag from a public <code>owner/name</code> repository.",
"<strong>HTTP JSON</strong>: a public endpoint plus a dotted path such as <code>data.version</code> or <code>releases[0].tag_name</code>.",
"<strong>Docker Hub</strong>: versioned tags filtered by a regular expression. A live preview shows real matching tags before the record is saved.",
"Moving tags such as <code>latest</code>, <code>stable</code> or <code>lts</code> do not contain a version. Track those images by digest from Docker image updates instead."
],
"sourceTrailing": "Always use the app's official source. A fork or a third-party endpoint may announce versions that don't match the installation in the LXC.",
"regexHeading": "Version regular expressions",
"regexIntro": "A regular expression, or <strong>regex</strong>, isolates the version number inside a longer text. Most projects don't publish a ready-made regex — the user builds one from real output or a real release name.",
"regexOptional": "It is not always needed. Leave it empty first if the source already returns a clean value like <code>2.14.3</code>. Add one only when ProxMenux needs to separate the version from other words, symbols or numbers.",
"regexTwoHeading": "There are two different regex fields",
"regexTwoItems": [
"<strong>Installed version regex</strong> is applied to the output read inside the LXC.",
"<strong>Version regex</strong> or <strong>Tag regex</strong> is applied to the release / tag name published by the external source."
"regexHeading": "Writing the capture expression",
"regexLead": "A detector regular expression must return the version in its <strong>first capture group</strong>.",
"regexRules": [
"Match the text emitted by the selected binary, file, command or tag source; do not guess a generic path.",
"Escape literal dots as <code>\\.</code> so they cannot match arbitrary characters.",
"Allow a leading <code>v</code> only when the source can include it.",
"Include suffixes such as prerelease or distro revisions only when they are meaningful for the comparison.",
"Use <strong>Test detector</strong> before saving and verify that the displayed installed version matches the LXC."
],
"regexTwoTrailing": "Both must produce comparable values. For instance, if the local app returns <code>MyApp v2.14.3</code> and GitHub publishes <code>release-2.14.3</code>, both expressions should extract <code>2.14.3</code>.",
"step1Heading": "1. Capture a real sample",
"step1P1": "Before writing the pattern, capture exactly the text ProxMenux will have to interpret.",
"step1P2": "For the installed version, run the same binary and arguments configured in the form from the LXC console. Depending on the method, you may also query the corresponding package or file.",
"step1P3": "For example:",
"step1Cmd": "myapp --version",
"step1P4": "Suppose the real output is:",
"step1Output": "MyApp version v2.14.3 (stable)",
"step1P5": "For the published version, check the exact release or tag name in the official repository. If you use a JSON endpoint, inspect the value the configured path returns.",
"step1P6": "Do not build the pattern against an invented example — a single space, prefix or extra number can change the result.",
"step2Heading": "2. Identify the part to keep",
"step2Lead": "In the example above we want to keep <code>2.14.3</code> and drop:",
"step2Items": [
"The text <code>MyApp version</code>.",
"The letter <code>v</code>.",
"The text <code>(stable)</code>."
],
"step2Recommended": "The recommended expression:",
"step2Regex": "version[ :=]+v?([0-9]+\\.[0-9]+\\.[0-9]+)",
"step2ReadLead": "Read piece by piece:",
"step2Breakdown": {
"colPart": "Fragment",
"colMeaning": "Meaning",
"rows": [
{ "part": "version", "meaning": "Anchors the search on that word to avoid matching an unrelated number." },
{ "part": "[ :=]+", "meaning": "Accepts one or more spaces, colons or equal signs." },
{ "part": "v?", "meaning": "The letter v may appear once or not at all." },
{ "part": "( and )", "meaning": "Mark the portion ProxMenux should keep." },
{ "part": "[0-9]+", "meaning": "Matches one or more digits." },
{ "part": "\\.", "meaning": "Matches a literal dot between the numbers." }
]
},
"step2DotNote": "The dot is written as <code>\\.</code> because, in a regex, a bare dot means \"any character\".",
"step3Heading": "3. Pick a pattern that fits the format",
"step3Lead": "These patterns cover the most common cases:",
"step3Examples": {
"colText": "Sample text",
"colRegex": "Recommended regex",
"colResult": "Result",
"rows": [
{ "text": "v2.14.3", "regex": "v?([0-9]+\\.[0-9]+\\.[0-9]+)", "result": "2.14.3" },
{ "text": "Version: 2.14", "regex": "Version[ :=]+v?([0-9]+(?:\\.[0-9]+){1,3})", "result": "2.14" },
{ "text": "release-2.14.3.1", "regex": "release-v?([0-9]+(?:\\.[0-9]+){1,3})", "result": "2.14.3.1" },
{ "text": "build 2026.08.10", "regex": "build[ :=]+([0-9]{4}\\.[0-9]{1,2}\\.[0-9]{1,2})", "result": "2026.08.10" },
{ "text": "{\"version\":\"2.14.3\"}", "regex": "\"version\"\\s*:\\s*\"v?([0-9]+(?:\\.[0-9]+){1,3})\"", "result": "2.14.3" }
]
},
"step3Note1": "<code>(?: ... )</code> groups a fragment of the pattern without producing an extra output value. This form is convenient to accept versions with two, three or four blocks without complicating the result.",
"step3Note2": "Enter the regex exactly as shown in the table: without surrounding quotes and without the <code>/.../</code> delimiters some online tools use.",
"step4Heading": "4. Prefer a single capture",
"step4Intro": "ProxMenux uses capture groups to decide which value to return:",
"step4Items": [
"With no capture groups it keeps the whole match.",
"With one capture, it keeps that capture's content.",
"With several captures, it joins them with dots."
],
"step4Trailing": "For predictable results, wrap the whole version in a single capture and use <code>(?: ... )</code> for helper groups.",
"step4RecLabel": "Recommended:",
"step4RecRegex": "v?([0-9]+(?:\\.[0-9]+){1,3})",
"step4LessLabel": "Less clear for beginners:",
"step4LessRegex": "v?([0-9]+)\\.([0-9]+)\\.([0-9]+)",
"step4Note": "Both can produce <code>2.14.3</code>, but the first is easier to maintain if the format changes.",
"step5Heading": "5. Avoid overly broad matches",
"step5Lead": "A pattern like this one is usually too open:",
"step5Regex": "([0-9.]+)",
"step5P1": "It can capture a year, a port, a dependency version or the first number that appears in the output. Anchor it with a nearby word such as <code>version</code>, <code>release</code> or <code>build</code> when the text carries several numbers.",
"step5P2": "Also confirm the upstream source isn't mixing stable releases with beta, nightly or development builds. The regex must select the same channel that is installed in the LXC.",
"step6Heading": "6. Save and verify the result",
"step6Lead": "After saving the app, press <strong>Check</strong> and read the two values ProxMenux reports:",
"step6Output": "Installed: 2.14.3\nLatest: 2.15.0",
"step6CorrectLead": "The regex is correct when:",
"step6CorrectItems": [
"Both fields contain only the expected version.",
"The application name and extra text are not captured.",
"The version is not confused with any other number.",
"Local and published values use the same format."
],
"step6ErrorNote": "If the match errors out, capture the real output again and compare it character by character. Pay particular attention to uppercase, spaces, hyphens, the letter <code>v</code> and the number of version blocks.",
"step6Callout": "If you can't build a reliable pattern, prefer to disable upstream tracking temporarily and keep the app as a link-only record. A wrong regex can raise false alerts or hide a real update."
"regexExampleLead": "Common semantic-version capture:",
"regexExample": "v?(\\d+\\.\\d+\\.\\d+)",
"regexCallout": "A successful regex match is not proof that the detector path is correct. The path or package must also exist in the real installation being registered."
},
"state": {
"heading": "Reading an app's state",
"lead": "A registered app can display any of the following states:",
"updater": {
"heading": "Version tracking and updating are independent",
"lead": "The <link>Updates tab</link> creates an app section as soon as any application record is saved.",
"items": [
"<strong>Up to date</strong> — versions match.",
"<strong>Update available</strong> — the source publishes a newer version.",
"<strong>Checking</strong> — the check is in progress.",
"<strong>Version tracking pending</strong> — no check has completed yet.",
"<strong>Error</strong> — one of the versions could not be read or parsed."
],
"trailing": "Use <strong>Check</strong> to repeat the query manually after tweaking the configuration. If an error appears, review the installed-version method, the upstream source and the regex patterns first."
"A link-only record shows that version tracking is not configured, but can still receive a custom update command.",
"An app with tracking but without an executable method shows a neutral message asking for a custom command.",
"An app with a verified Proxmox VE Helper-Scripts wrapper can use that integrated updater even when the registration began from a web link.",
"Adding or editing an updater does not change the detector or upstream source stored on the App tab."
]
},
"manage": {
"heading": "Managing existing records",
"lead": "Enter management mode to:",
"states": {
"heading": "Version states on the App card",
"colState": "State",
"colDisplay": "Display",
"colMeaning": "Meaning",
"rows": [
{ "state": "Update available", "display": "Available version in purple with an upward-arrow icon", "meaning": "The installed and upstream versions differ." },
{ "state": "Current", "display": "Installed and latest versions without the purple alert", "meaning": "The last check found no newer upstream version." },
{ "state": "Tracking pending", "display": "Checking or pending state", "meaning": "The record is configured but has not completed both checks yet." },
{ "state": "Tracking disabled", "display": "Web links only; no version comparison block", "meaning": "The record remains valid and can still have an updater." },
{ "state": "Check error", "display": "Amber explanation inside the card", "meaning": "The previous saved state remains visible while the detector or upstream error is reported." }
]
},
"management": {
"heading": "Managing saved and suggested apps",
"lead": "The actions at the bottom of the tab have distinct roles:",
"items": [
"Re-check an app.",
"Edit its name, links or version tracking.",
"Delete a record that is no longer needed.",
"Add another app to the same LXC."
],
"trailing": "Deleting a record does not uninstall or stop the app. It only removes the information ProxMenux uses to display it and monitor its version."
"<strong>Find applications</strong> refreshes discovery for this LXC only.",
"<strong>Register another application</strong> opens the catalog and manual editor without rescanning the LXC.",
"<strong>Edit</strong> reveals per-card Remove, Check, notification and Edit fields actions.",
"<strong>Hide</strong> removes an unwanted suggestion. Hidden detections can be restored from the registration browser.",
"<strong>Check</strong> refreshes the selected saved app's version evidence; it does not search for new apps."
]
},
"options": {
"heading": "Optional toggles",
"lead": "Two independent switches sit under the version tracking options:",
"items": [
"<strong>Notify me when a new upstream version is available</strong> — sends the <code>app_update_available</code> event to the channels enabled in <strong>Settings → Notifications</strong>.",
"<strong>Exclude from the LXC updates counter</strong> — leaves this app out of the aggregate updates badge shown on the LXC list card."
],
"trailing": "Both toggles can be set independently. The App tab still shows the real state of each registered app regardless of these choices."
"troubleshooting": {
"heading": "Common situations",
"colProblem": "Situation",
"colResolution": "Resolution",
"rows": [
{ "problem": "Software was installed after ProxMenux started", "resolution": "Press Find applications. The explicit scan updates cached suggestions for that LXC." },
{ "problem": "No application was detected", "resolution": "Register it manually. A name and one web link are sufficient; tracking can be added later." },
{ "problem": "The suggested detector returns the wrong version", "resolution": "Open Edit fields, select the real package, binary or file path and test the detector before saving." },
{ "problem": "A Docker workload is not offered as an LXC app", "resolution": "Register Docker and add the workload's published interface as a Docker web link. Image updates remain in the Docker section." },
{ "problem": "A saved app has no update button", "resolution": "Open the Updates tab and configure its update method. Version tracking alone does not define how an update is installed." }
]
},
"notDetected": {
"heading": "If the app is not detected",
"intro": "Automatic detection is not required to use this feature. If no suggestion appears:",
"steps": [
"Register the app manually.",
"Add its known links and ports.",
"Leave it as <strong>None (link only)</strong> if you only need a shortcut.",
"Configure version tracking only when a reliable source has been identified for both values.",
"Configure the update method later from <link>Updates</link>, if you want ProxMenux to run it."
],
"trailing": "Don't invent a package name, path or regex just to fill the form. A simple, correct record beats an automatic tracking based on unverified data."
"figures": {
"catalog": {
"alt": "Application registration catalog with search results, logos, ports and detector fields",
"caption": "Catalog metadata accelerates registration while every proposed value remains editable."
},
"webLinks": {
"alt": "Saved LXC application card containing a clickable web link",
"caption": "A link-only record is valid: version tracking can stay disabled and an updater can be added independently."
},
"tracking": {
"alt": "Optional installed-version detector and upstream source fields",
"caption": "Installed-version detection and the upstream source are configured and tested separately."
},
"card": {
"alt": "Saved application card with installed and available versions plus a web link",
"caption": "The card combines identity, version evidence and web access without running update actions from this tab."
}
}
}
@@ -1,231 +1,194 @@
{
"meta": {
"title": "Updates — updating an LXC's system and apps | ProxMenux",
"description": "Which mechanisms ProxMenux can use to update the operating system and the applications registered in an LXC container."
"title": "LXC updates: OS, apps and Docker | ProxMenux",
"description": "Configure and run operating-system, application, Docker Engine and Docker image updates from an LXC container."
},
"header": {
"title": "Updates — updating an LXC's system and apps",
"description": "Where ProxMenux decides how to upgrade a container: OS packages, Community Scripts helper, or a custom command."
"title": "LXC updates: OS, apps and Docker",
"description": "Review every update target in one place, run it independently, or combine selected targets in a controlled bulk action."
},
"intro": {
"p1": "The <strong>Updates</strong> tab gathers the mechanisms ProxMenux can run to upgrade the operating system and the applications registered inside an LXC container.",
"p2": "The <link>App tab</link> declares which applications exist and, optionally, compares their versions. <strong>Updates</strong> is about the action: it decides which mechanism is available, presents the matching button and runs the upgrade inside the container.",
"callout": "<strong>Core idea:</strong> detecting a new version and knowing how to install it are two different jobs. An app can show <strong>Update available</strong> on the App tab and still not have a working update button until a valid method is defined."
"p1": "The <strong>Updates</strong> tab separates version detection from the action that installs an update. Registration and optional version tracking live on the <link>App tab</link>; executable update methods live here.",
"p2": "A saved application appears in Updates even when it contains only a web link. Version tracking is optional, and an updater can be configured independently.",
"callout": "No action is inferred from an application name alone. ProxMenux runs an integrated method only after verifying it, or a custom command that has been explicitly saved."
},
"overview": {
"heading": "What the tab contains",
"lead": "Each available target has its own section and action:",
"items": [
"<strong>OS packages</strong> for Debian, Ubuntu and Alpine containers.",
"One section for every <strong>registered application</strong>, including link-only records.",
"A <strong>Docker</strong> section when Docker is registered, with Docker Engine and tagged images grouped together.",
"A configurable <strong>Bulk update</strong> section, followed by backup, restart and scheduling options."
]
},
"mechanisms": {
"heading": "Available update mechanisms",
"intro": "Depending on how the app was installed and where its updates come from, ProxMenux picks from three mechanisms.",
"osHeading": "Operating system packages",
"osP1": "On Debian or Ubuntu containers, ProxMenux queries and updates packages through APT. On Alpine, it uses APK.",
"osP2": "Registered apps whose install method is <code>dpkg</code> or <code>apk</code> are part of this pass. They don't need a second command in the app section — they update as part of <strong>Apply OS update</strong>.",
"osP3": "The section shows the number of pending packages, how many are security updates, the OS family and the time of the last check.",
"helperHeading": "Proxmox VE Helper-Scripts updater",
"helperP1": "When the LXC was created with a helper from the <linkHelperHome>Proxmox VE Helper-Scripts</linkHelperHome> project, ProxMenux recognises its updater. The matching app must be registered on the App tab so the Monitor can associate the helper with the service shown to the user.",
"helperP2": "<strong>The update logic itself is maintained by the Proxmox VE Helper-Scripts project</strong>, not by ProxMenux. Each helper ships its own <code>update_script</code> function; ProxMenux fetches it and runs it inside the container in silent mode (<code>PHS_SILENT=1</code>), without prompts. There is no need to copy the helper or write a custom command on the ProxMenux side.",
"helperP3": "Full documentation for the update mechanism lives on the project site — <linkHelperDocs>community-scripts.org / update-apps</linkHelperDocs>. Each helper also has its own entry on the <linkHelperHome>project site</linkHelperHome> with a description of what the script does, its default configuration and the source of the update logic — use that page as the reference for what the updater will change inside the LXC.",
"helperP4": "Not every helper supports in-place updates. If the catalog marks an application as non-upgradable, the tab will surface that state and won't present this method as available.",
"customHeading": "Custom command",
"customP1": "A registered app can store its own update command. ProxMenux runs it inside the LXC when the user presses <strong>Apply update</strong> or when a scheduled task includes that app.",
"customP2": "This method is designed for apps whose installer provides no recognised helper and that don't update as part of APT or APK."
"heading": "How an update method is selected",
"lead": "The integrated Proxmox VE Helper-Scripts path follows the official <helper>update-apps mechanism</helper>. Other install types use the matching package, Docker or custom path.",
"colSource": "Source",
"colAction": "Displayed action",
"colNotes": "What runs",
"rows": [
{
"source": "APT or APK packages",
"action": "Apply OS updates",
"notes": "Updates the container packages. Registered apps installed as dpkg or apk packages are covered by this same pass."
},
{
"source": "Proxmox VE Helper-Scripts",
"action": "Apply update",
"notes": "Uses the verified /usr/bin/update wrapper. A legacy marker without a valid wrapper is identified, but never executed automatically."
},
{
"source": "Custom command",
"action": "Run updater",
"notes": "Runs the saved command inside the LXC and replaces any integrated app updater for that record."
},
{
"source": "Docker Engine",
"action": "Update Docker Engine",
"notes": "Updates only installed Docker packages and their required dependencies. Other OS packages and containers are not changed."
},
{
"source": "Docker image",
"action": "Update image",
"notes": "Pulls the selected image and recreates its Compose service group or protected standalone container."
}
],
"callout": "A custom command always <strong>replaces</strong> the integrated Proxmox VE Helper-Scripts updater for that application. The two methods are not run one after the other."
},
"decision": {
"heading": "How ProxMenux picks the action to show",
"table": {
"colSituation": "Situation",
"colAction": "Action",
"rows": [
{ "situation": "APT or APK packages pending", "action": "Apply OS update" },
{ "situation": "The app uses a dpkg or apk package", "action": "Apply OS update — no separate app command needed" },
{ "situation": "A compatible helper exists and the app is registered", "action": "Apply update via Community Scripts" },
{ "situation": "The registered app has a custom command", "action": "Apply update using that command" },
{ "situation": "A new version exists but no helper or command is configured", "action": "Shows No updater configured; offers to add a command" },
{ "situation": "System and app updates are both available", "action": "Combined Apply OS + Apps updates action may appear" }
]
},
"trailing": "An app registered only as a link is never shown as upgradable — ProxMenux doesn't have enough information to wire an update method to it."
"docker": {
"heading": "Docker Engine and Docker images",
"lead": "After Docker is registered on the App tab, its engine and image inventory appear inside the same <strong>Docker</strong> section.",
"items": [
"Docker Engine version tracking is separate from the OS package counter and has its own update button.",
"Tagged local images are compared with their registry by immutable digest. <strong>Check now</strong> refreshes this inventory without pulling images or restarting containers.",
"Compose services are updated from their declared project. Images that belong to the same service group are handled together so the project is not recreated repeatedly.",
"A standalone container is recreated from its current configuration. The protected flow keeps rollback data and restores the previous container if recreation fails.",
"Every image can be selected separately in manual, bulk and scheduled updates, except declared Compose dependencies that must follow their parent service."
],
"callout": "Containers running inside Docker are not shown as independent LXC applications. Their published web ports can be saved as links under the Docker registration, while image updates remain in the Docker section."
},
"figures": {
"f01": {
"alt": "OS packages card showing pending updates count, security-updates count and the Apply OS update button",
"caption": "Pending OS packages: total count, security-updates count, and the Apply OS update button"
},
"f02": {
"alt": "Same OS packages card after applying updates — no packages pending, OS up to date badge",
"caption": "After applying: 'No OS updates pending' and the OS up to date badge"
},
"f03": {
"alt": "Registered app card showing 'No update method available' and an Add custom update command button",
"caption": "'No update method available' — ProxMenux tracks the app but has nothing wired to upgrade it yet"
},
"f04": {
"alt": "Custom update command editor with the example placeholder visible inside the textarea",
"caption": "The custom command editor with its placeholder example, Cancel and Save buttons"
},
"f05": {
"alt": "Terminal panel labelled 'Apply updates — CT 103' showing live apt output as packages are unpacked",
"caption": "Terminal panel streaming the update output live while apt unpacks packages inside the CT"
},
"f06": {
"alt": "Options card with snapshot before applying enabled, backup storage set to pbs, and restart after applying enabled",
"caption": "Options card with vzdump snapshot, backup storage and restart-after-applying enabled together"
},
"f07": {
"alt": "Scheduled updates section enabled — Frequency set to Daily at 3:00, cron expression 0 3 * * *, and What to update set to OS + application",
"caption": "Scheduled updates enabled — frequency preset, matching cron expression and target scope selected"
}
"actions": {
"heading": "Individual actions and status colours",
"lead": "Every section remains independently actionable, whether or not a bulk update is configured.",
"items": [
"The <strong>Edit</strong> button is always available. Integrated methods open with their current command, which can be reviewed, replaced or cleared.",
"When version tracking is disabled but an updater exists, the neutral <strong>Run updater</strong> action is shown. ProxMenux does not claim that an update is pending.",
"When no method is available, <strong>Configure</strong> opens the custom-command editor.",
"The <strong>Update image</strong> action applies only to the selected Docker unit; it does not update Docker Engine or unrelated images."
],
"statusColState": "Known state",
"statusColAppearance": "Appearance",
"statusColMeaning": "Meaning",
"statusRows": [
{
"state": "Verified update available",
"appearance": "Purple text, upward-arrow icon and purple action",
"meaning": "Installed and available versions or image digests differ."
},
{
"state": "Verified current",
"appearance": "Green check and green Updated action",
"meaning": "The latest completed check confirms that the target is current."
},
{
"state": "Version unknown",
"appearance": "Neutral text and neutral action",
"meaning": "An updater can run, but no version evidence exists to label it pending or current."
}
]
},
"custom": {
"heading": "Adding a custom update command",
"p1": "When an app has version tracking but no update method, the tab shows <strong>No updater configured</strong>. Press <strong>Add custom update command</strong> to open the editor.",
"p2": "The command must represent the real, complete procedure that upgrades that app. Don't just paste the command that reads its version."
},
"figureOut": {
"heading": "How to figure out the correct command",
"intro": "There is no universal update command. Before saving one, identify how the software was installed and what the project's recommended upgrade path is.",
"step1Heading": "1. Check whether the system already handles it",
"step1P1": "If the app was installed from Debian, Ubuntu or Alpine repositories it usually upgrades with system packages. In that case don't add a custom command — use <strong>Apply OS update</strong>.",
"step1P2": "You can check the package origin from the LXC console with the distro's tooling. For example:",
"step1Cmd1": "dpkg -l | grep -i name",
"step1P3": "or:",
"step1Cmd2": "apk info | grep -i name",
"step1P4": "Replace <code>name</code> with the package you are investigating. A match doesn't automatically confirm it's the main package — cross-check the name against the app's documentation.",
"step2Heading": "2. Consult the official documentation",
"step2P1": "Look in the official docs or repository for sections like <strong>Upgrade</strong>, <strong>Update</strong>, <strong>Maintenance</strong> or <strong>Manual installation</strong>. The procedure must match the method used to install the app in that LXC.",
"step2P2": "Don't use instructions targeting a different distribution, a different install type or a different version.",
"step3Heading": "3. Inspect the existing installation",
"step3Lead": "If you don't remember how the app was installed, look at:",
"step3Items": [
"The history or notes of the original installer.",
"The path where its files live.",
"The service definition that starts it.",
"Any maintenance scripts shipped by the app.",
"The documentation stored inside its install directory."
],
"step3P1": "For a systemd service, this can help locate the binary and its working directory:",
"step3Cmd": "systemctl show service-name -p ExecStart -p WorkingDirectory",
"step3P2": "This helps identify the installation, but it does not automatically translate the <code>ExecStart</code> line into an update command.",
"step4Heading": "4. Test the procedure in the LXC console",
"step4Lead": "Open a console into the container and run the procedure manually before saving it in ProxMenux. Verify that it:",
"step4Items": [
"Finishes without prompts or interactive menus.",
"Returns a correct exit code.",
"Restarts or reloads only the services that need it.",
"Leaves the app reachable afterwards.",
"Changes the installed version as expected."
],
"step4Note": "When feasible, take a container backup before testing.",
"step5Heading": "5. Save only the in-container command",
"step5P1": "Enter only what would be executed inside the LXC. Don't include:",
"step5Cmd1": "pct exec <vmid> --",
"step5P2": "ProxMenux already handles entering the container. The command runs as <code>root</code> via <code>sh -c</code>, so it accepts chained operations and directory changes.",
"step5P3": "If the updater must run from a specific path, include it explicitly:",
"step5Cmd2": "cd /opt/my-app && ./update.sh",
"step5P4": "If the project ships an updater at a different path, use the path and arguments named by the official documentation."
},
"requirements": {
"heading": "Requirements for a reliable command",
"lead": "Before running it from the Monitor, confirm the command:",
"heading": "Custom update commands",
"lead": "Use a custom command when the installation has no verified integrated updater, or when its normal procedure must be replaced.",
"items": [
"Runs without user interaction.",
"Uses absolute paths or changes into the correct directory first.",
"Stops, migrates and restarts services as required by the official instructions.",
"Exits with an error when the update fails.",
"Does not contain visible passwords, tokens or other secrets.",
"Does not download or execute scripts from untrusted sources."
"Open <strong>Configure</strong> when the field is empty, or <strong>Edit</strong> when a method already exists.",
"For an integrated app or Docker Engine, the editor shows the command currently used. Saving different content turns it into the explicit override for that record.",
"Test the complete procedure in the LXC terminal first. It must be non-interactive, use the correct working directory and return a non-zero exit status on failure.",
"Do not include <code>pct exec</code>; ProxMenux already enters the container and runs the command as root."
],
"trailing": "The content is stored in the LXC's configuration and executed with administrator privileges. Treat it with the same care as any command run as <code>root</code>."
"exampleLead": "Example of a complete in-container procedure:",
"example": "cd /opt/my-app && ./update.sh",
"callout": "A version command such as <code>myapp --version</code> only reads a version; it is not an updater. Commands run with administrative privileges, so stored content must be reviewed with the same care as a root shell command."
},
"difference": {
"heading": "Difference between the detection command and the update command",
"lead": "Both fields have different goals:",
"table": {
"colField": "Field",
"colLocation": "Location",
"colRole": "Role",
"rows": [
{
"field": "Command for the installed version",
"location": "App → advanced tracking",
"role": "Reads and returns the current version; executed as an argument list without a shell."
},
{
"field": "Custom update command",
"location": "Updates",
"role": "Runs the upgrade procedure; interpreted via sh -c."
}
]
},
"trailing": "Don't blindly copy the value of one into the other. A command like <code>myapp --version</code> may correctly detect the version but won't install a new one."
},
"apply": {
"heading": "Applying an update",
"lead": "Before pressing an apply button:",
"steps": [
"Confirm what will be updated: system, one app or both.",
"Check the backup and restart options.",
"Press the matching button.",
"Follow the process output in the terminal panel.",
"Verify the final result and that the service responds again."
"bulk": {
"heading": "Bulk update",
"lead": "Bulk update creates one reusable action for an exact set of targets in the LXC. It is placed after the individual app and Docker sections and before <strong>Options</strong>.",
"items": [
"OS packages are mandatory. At least one additional app, Docker Engine or Docker image unit must be selected.",
"Applications and Docker units are selected individually. A Compose parent shows the dependencies that will be updated with it.",
"Unavailable or removed targets are marked as stale and must be removed before the configuration can be saved.",
"The <strong>Apply updates</strong> button is purple when any selected target has a verified update, green when all selected targets are verified current, and neutral when the result is unknown.",
"Removing the bulk configuration does not remove individual update methods or scheduled-update settings."
],
"trailing1": "If the LXC is stopped, ProxMenux starts it to run the process. If the update finishes correctly and the restart option is enabled, the container is restarted at the end.",
"systemLead": "On a system update:",
"systemItems": [
"Debian and Ubuntu run the upgrade via APT.",
"Alpine runs it via APK."
],
"appLead": "On an app update:",
"appItems": [
"The compatible helper is used, when it exists.",
"The custom command stored for the app is executed, when configured.",
"If several apps are selected, their methods run in sequence."
],
"trailing2": "The terminal panel shows progress and ends with a successful result or the process's error code."
"callout": "Bulk update does not replace the individual buttons. It is an optional shortcut for a selection that should run together."
},
"backup": {
"heading": "Backup before updating",
"p1": "Enable <strong>Snapshot the container before applying</strong> to create a <code>vzdump</code> backup before touching the LXC. You can also choose the target storage.",
"p2": "If the backup is requested and it fails, ProxMenux won't continue with the update. This prevents changes from starting without the requested recovery point.",
"p3": "This option applies to both manual runs and scheduled runs."
},
"restart": {
"heading": "Restart after updating",
"p1": "<strong>Restart the container after applying</strong> is a preference, not a signal that the restart is mandatory. Enable it when the app's procedure or the installed packages require it.",
"p2": "The restart only happens after a successful run. If the update fails, the container stays up so the error can be inspected.",
"p3": "The backup and restart options are saved for that LXC and also apply to its scheduled tasks."
"options": {
"heading": "Backup and restart options",
"lead": "The same options apply to manual, bulk and scheduled runs:",
"items": [
"<strong>Snapshot before applying</strong> creates a vzdump backup on the selected storage. If the required backup fails, the update does not start.",
"<strong>Restart after applying</strong> restarts the LXC only after a successful run.",
"The selections are stored per LXC and remain independent from the target list."
]
},
"scheduled": {
"heading": "Scheduled updates",
"p1": "The <strong>Scheduled updates</strong> section runs automatically the same flow the manual buttons use.",
"createLead": "To create a schedule:",
"createSteps": [
"Open <strong>Options</strong> and press <strong>Edit</strong>.",
"Enable <strong>Scheduled updates</strong>.",
"Choose a preset frequency or enter a cron expression.",
"Select what will be updated: system packages only, applications only, or system and applications.",
"Review the backup and restart options.",
"Save the configuration."
"lead": "Scheduled updates use the same executable targets and safety options as manual actions.",
"items": [
"Choose a preset or cron expression, then select exact targets: OS packages, individual apps, Docker Engine, standalone Docker units or Compose service groups.",
"A release hold applies only to selected applications with version tracking. Apps without tracking run their updater whenever their schedule is due.",
"The last-run state distinguishes success, partial completion, failure, safety hold and a run with nothing pending.",
"External host schedules detected from Proxmox VE Helper-Scripts are shown separately so overlapping automation is visible."
],
"p2": "The card shows whether the schedule is active, what it covers and the outcome of the last run. A disabled schedule can be kept for later re-activation, or removed entirely.",
"p3": "If ProxMenux detects an external schedule created by Community Scripts on the host, it surfaces it so the user knows another automation is already in place.",
"callout": "Before scheduling app updates, test every helper or command manually. A scheduled task can't answer prompts or fix an incomplete procedure."
"callout": "Run every selected method manually before enabling a schedule. Scheduled commands cannot answer prompts."
},
"verify": {
"heading": "Checking the result",
"p1": "After applying system packages, ProxMenux forces a fresh check to update the pending-package counter without waiting for the next periodic cycle.",
"p2": "For an app, go back to the <link>App tab</link> and press <strong>Check</strong> if the version number doesn't refresh immediately. This runs the configured installed-version method again and queries the upstream source.",
"p3": "Confirm additionally that the app's web links respond correctly. A command finishing without errors is not a substitute for functional verification of the service."
"completion": {
"heading": "What happens after an update",
"lead": "The update is not considered finished when the terminal command merely exits.",
"items": [
"The same run records its final result and refreshes OS package state, registered app versions and Docker inventory as applicable.",
"The LXC cache is replaced with the verified post-update state, so badges and buttons do not retain the previous result.",
"If a stopped or restored LXC starts, the existing lifecycle event refreshes that LXC again. Docker inventory waits for the daemon to become ready instead of caching an empty startup result as final.",
"Enabled notifications are emitted from the finalized run, including partial failures and grouped Docker image results."
]
},
"troubleshoot": {
"heading": "Common problems",
"noButtonHeading": "Update available appears, but there's no Apply update button",
"noButtonBody": "Version detection works, but no method to install the update was found. Check whether the app updates via system packages, a compatible helper or a custom command.",
"aptHeading": "The app updates through APT or APK",
"aptBody": "Use <strong>Apply OS update</strong>. Don't add a second command for the same operation — the app is already part of the system update.",
"noUpdaterHeading": "No updater configured is shown",
"noUpdaterBody": "ProxMenux tracks the app but doesn't know how to update it. Check its official documentation, test the procedure in the console and, if appropriate, save it via <strong>Add custom update command</strong>.",
"helperDetectedHeading": "The helper is detected but can't be used",
"helperDetectedBody": "The helper may be marked as non-upgradable or fall outside the recognised methods. Follow the app's official instructions and don't assume every LXC built with Community Scripts supports automatic updates.",
"customFailsHeading": "The custom command fails",
"customFailsBody": "Re-run it in the LXC console. Check the working path, permissions, dependencies, non-interactive arguments and exit code. Don't swap the command for a different variant until you've verified the recommended procedure with the project."
"troubleshooting": {
"heading": "Common situations",
"colProblem": "Situation",
"colResolution": "Resolution",
"rows": [
{
"problem": "No update method has been identified",
"resolution": "Open Configure, add the official non-interactive procedure and test it manually before scheduling it."
},
{
"problem": "A Proxmox VE Helper-Scripts identity is shown but no action exists",
"resolution": "The LXC has legacy identification data but no verified /usr/bin/update wrapper. Add a custom method only after confirming the correct procedure."
},
{
"problem": "Docker images are temporarily empty after startup or restore",
"resolution": "Wait for Docker to become ready or press Check now. The inventory retries startup and does not treat a transient empty result as final."
},
{
"problem": "A saved bulk target is no longer available",
"resolution": "Edit the bulk configuration, remove the stale target and select its current replacement if one exists."
},
{
"problem": "A custom command fails",
"resolution": "Run it in the LXC terminal and review its path, dependencies, non-interactive flags and exit code."
}
]
},
"figures": {
"osPending": {
"alt": "Operating-system packages section with pending and security update counts",
"caption": "The operating-system section keeps package updates independent from application and Docker actions."
},
"options": {
"alt": "LXC update options with pre-update backup and post-update restart",
"caption": "Backup and restart preferences apply to manual, bulk and scheduled executions."
}
}
}
@@ -52,7 +52,7 @@
},
"drillIn": {
"heading": "Per-guest drill-in modal",
"intro": "The modal opens with a header showing the guest name, VMID, type badge (LXC / VM), state badge (RUNNING / STOPPED / …) and current uptime. Below the header are <strong>two tabs</strong> — <em>Status</em> and <em>Backups</em> — and a fixed action bar at the bottom of the modal with the four lifecycle controls (Start / Shutdown / Reboot / Force Stop) and, on running LXC containers, a Console button.",
"intro": "The modal opens with the guest name, VMID, type, state and uptime. Its navigation adapts to the guest: <strong>Status</strong>, <strong>App</strong> and <strong>Updates</strong> for LXC application management, <strong>Mounts</strong> when an LXC has mount points, plus <strong>Backups</strong> and <strong>Firewall</strong>. The fixed action bar keeps the lifecycle controls and the LXC terminal available from every tab.",
"statusTitle": "Tab 1 — Status",
"statusImageAlt": "Per-guest drill-in modal — Status tab with CPU / Memory / Disk live cards, Disk and Network I/O totals, the OS distro logo, and the Resources / IP Addresses block",
"statusImageCaption": "Status tab — live CPU / Memory / Disk with progress bars at the top, accumulated I/O totals (disk read/write, network down/up) below, then the static Resources block with Notes and + Info expansions and the IP Addresses pill list.",
@@ -77,7 +77,17 @@
],
"ipsTitle": "4. IP Addresses",
"ipsBody": "Pill list of every IPv4 / IPv6 address the guest currently exposes — green pill per address. Empty when the guest is stopped or when the QEMU agent isn't installed in a VM (LXCs always report addresses directly).",
"mountsTitle": "Tab 2 — Mounts (LXC only)",
"appTitle": "Tab 2 — App (LXC only)",
"appIntro": "Registers applications that belong to the LXC, saves web links and optionally compares installed and available versions. Suggestions come from the startup cache; <strong>Find applications</strong> explicitly refreshes discovery for this LXC after new software is installed.",
"appLinkLead": "See the",
"appLinkLabel": "dedicated App page",
"appLinkTail": "for cached discovery, catalog-assisted registration, Docker web links and version detectors.",
"updatesTitle": "Tab 3 — Updates (LXC only)",
"updatesIntro": "Keeps <strong>OS packages</strong>, registered applications, <strong>Docker Engine</strong> and Docker images as separate targets. Each target can run independently; an optional bulk action and a schedule can select the exact methods that should run together.",
"updatesLinkLead": "See the",
"updatesLinkLabel": "dedicated Updates page",
"updatesLinkTail": "for integrated and custom updaters, Docker recreation, bulk selection, safety options and scheduling.",
"mountsTitle": "Tab 4 — Mounts (LXC only, when present)",
"mountsImageAlt": "LXC drill-in modal — Mounts tab listing every mount point the container is using: PVE volumes, host binds, binds from PVE storage and ad-hoc NFS/CIFS mounts the operator mounted from inside the CT. Each card carries a type badge, capacity bar, used/total bytes, mount options, and a colour-coded state dot (green healthy, amber readonly/divergent, red stale)",
"mountsImageCaption": "Mounts tab — only renders for LXC containers, and only when at least one mount point or ad-hoc remote mount is present. A CT without mounts gets no tab.",
"mountsIntro": "Proxmox's own UI shows the mount-point entries defined in the container config (<code>mpX</code>) but stops there — anything you mount from inside the CT later (<code>mount.cifs</code>, NFS via <code>autofs</code>, …) is invisible. This tab merges <strong>both views</strong>: the configured mounts <strong>and</strong> the runtime mounts ProxMenux probes from inside the container, with a per-mount health status and a capacity bar wherever the backend can resolve one.",
@@ -96,7 +106,7 @@
],
"mountsCalloutTitle": "What this gives you over the native UI",
"mountsCalloutBody": "A truthful, capacity-aware view of every place the container reads or writes. NFS or CIFS shares mounted from inside the CT — invisible to the Proxmox web UI — appear here with the same look and the same health probe as any configured mount point. Stale remote mounts and zombie binds are flagged before they bite during a backup.",
"backupsTitle": "Tab 3 — Backups",
"backupsTitle": "Tab 5 — Backups",
"backupsImageAlt": "Per-guest drill-in modal — Backups tab with the available backups list, destination tag, sizes and the Create Backup button",
"backupsImageCaption": "Backups tab — every backup stored on configured Proxmox storages for this guest, sorted newest first. The tab header carries the count badge.",
"backupsIntro": "Lists every backup stored across configured Proxmox storages for this guest, sorted newest first. The tab title carries a count badge so you see at a glance whether the guest is backed up. Per row:",
@@ -106,23 +116,7 @@
"<strong>Size</strong> — final on-disk size of the backup."
],
"backupsOutro": "The <strong>+ Create Backup</strong> button at the top right kicks off a new run on the storage marked as \"Backup target\" in the Proxmox storage config. Restore lives in the Proxmox web UI — the Monitor exposes the \"is this guest backed up recently?\" view, not the recovery flow.",
"updatesTitle": "Updates badge (LXC only)",
"updatesImageAlt": "LXC drill-in modal — clickable violet 'updates available' badge in the header of a container that has pending apt or apk updates. Clicking it expands a panel listing every upgradable package with its current and target versions, plus a security-only counter when the underlying repo flags any of them as security",
"updatesImageCaption": "The badge only appears on running LXC containers that have at least one upgradable package. Click it to open the package list inside the modal — no separate tab in the nav strip.",
"updatesIntro": "ProxMenux probes every running container on the host once a day and counts the upgradable packages. Currently supported in this phase: <strong>Debian / Ubuntu</strong> via <code>apt list --upgradable</code> and <strong>Alpine</strong> via <code>apk list -u</code>. Containers running other distributions (CentOS, Arch, …) are skipped for now — they show no badge instead of a misleading zero.",
"updatesPanelTitle": "What the panel shows",
"updatesPanelItems": [
"<strong>Total upgradable count</strong> at the top, plus a separate <strong>security</strong> counter when the underlying repository flags any of the packages as security (Debian/Ubuntu \"-security\" suite). Alpine doesn't expose a separate security suite via apk metadata, so security is always 0 on Alpine containers.",
"<strong>Per-package list</strong> with name, current version and target version. Use this to decide whether to run the upgrade now or wait for a maintenance window."
],
"updatesScopeTitle": "What the system tracks vs what the script counts",
"updatesScopeBody": "This update detector follows whatever is already installed inside the container — it does <strong>not</strong> install anything new and does <strong>not</strong> know about applications that were deployed outside apt / apk (a Docker container running inside the LXC, a Vaultwarden installed from source, a binary dropped into <code>/usr/local/bin</code>). It is a <em>package-manager</em> view, not an <em>application</em> view. Future phases of this work will integrate community-script application metadata so per-app upstream tracking (Vaultwarden, Jellyfin, …) becomes possible.",
"updatesToggleTitle": "Detection vs notification — toggle semantics",
"updatesToggleCalloutTitle": "Detection is always on; the toggle only controls the notification",
"updatesToggleCalloutBody": "The package-update detection on running containers runs unconditionally — the badge appears in this modal whenever there are updates pending, regardless of any other setting. The <code>lxc_updates_available</code> notification toggle in <strong>Settings → Notifications</strong> only controls whether a grouped \"N CT(s) have pending updates\" message is delivered to your channels. This keeps the toggle semantics consistent with every other update stream (NVIDIA driver, Coral driver, ProxMenux optimizations): turning notifications off never hides the information in the dashboard.",
"updatesApplyTitle": "Applying the updates",
"updatesApplyBody": "Open the container shell from the bottom action bar, or use <code>pct exec &lt;vmid&gt; -- apt full-upgrade -y</code> / <code>pct exec &lt;vmid&gt; -- apk upgrade -y</code> from the host. The dashboard re-scans on its 24h cycle (or after the next manual refresh) and the badge updates.",
"firewallTitle": "Tab 5 — Firewall",
"firewallTitle": "Tab 6 — Firewall",
"firewallIntro": "Reads the per-guest Proxmox firewall log straight from the host (no extra service, no polling). The tab is always present in the navigation strip; the panel decides what to render depending on whether the firewall is enabled for that guest and whether any rule is actually logging:",
"firewallItems": [
"<strong>Firewall disabled</strong> — an amber notice explains exactly where to enable it in the Proxmox UI (<em>&lt;Container|VM&gt; → Firewall → Options</em>) and reminds you that at least one rule needs <code>log: info</code> (or higher) before packets show up.",
@@ -105,6 +105,18 @@
"imageAlt": "Resumen final + prompt de reinicio después de una instalación PCIe"
}
},
"legacyCleanup": {
"heading": "Limpieza de gasket-dkms antiguo en hosts con Coral USB",
"intro": "Si el host <strong>no tiene ninguna Coral PCIe / M.2 detectada</strong>, pero conserva una instalación anterior de <code>gasket-dkms</code>, ProxMenux identifica ese estado por separado y ofrece una limpieza opcional. No se elimina nada sin confirmación.",
"items": [
"Si hay una Coral PCIe / M.2 presente, esta limpieza nunca se ofrece; se utiliza la ruta normal de reconstrucción DKMS.",
"La limpieza purga <code>gasket-dkms</code>, elimina registros DKMS y árboles de código gasket residuales, y repara cualquier estado pendiente de <code>dpkg</code> o APT.",
"Los paquetes del runtime USB <code>libedgetpu1-std</code> y <code>libedgetpu1-max</code> no se modifican, por lo que una Coral USB conserva su runtime.",
"Antes de indicar que ha terminado correctamente, el script verifica que el paquete antiguo ya no existe y que el gestor de paquetes está en buen estado."
],
"warningTitle": "Confirma primero el hardware",
"warningBody": "Si puede haber una Coral PCIe / M.2 instalada pero no está siendo detectada, cancela la limpieza y comprueba la tarjeta, la ranura y la configuración del firmware antes de continuar."
},
"reinstallUninstall": {
"heading": "Reinstalar o desinstalar",
"intro": "Ejecutar el instalador en un host donde Coral ya está instalada (PCIe vía <code>gasket-dkms</code>, USB vía <code>libedgetpu1-std</code>/<code>libedgetpu1-max</code>, o ambos) ya no cae directamente en otra instalación fresca. En su lugar, ProxMenux detecta el setup existente y muestra un menú de acciones para que decidas qué hacer.",
@@ -1,281 +1,183 @@
{
"meta": {
"title": "App — registrar y supervisar aplicaciones de un LXC | ProxMenux",
"description": "Indica qué aplicaciones se ejecutan dentro de un contenedor LXC desde ProxMenux Monitor y sigue opcionalmente su versión."
"title": "Pestaña App de LXC: detección, enlaces y versiones | ProxMenux",
"description": "Detecta y registra aplicaciones LXC, crea enlaces web y, opcionalmente, sigue las versiones instalada y disponible."
},
"header": {
"title": "App — registrar y supervisar aplicaciones de un LXC",
"description": "Registra las aplicaciones que corren dentro del contenedor, añade accesos web rápidos y, opcionalmente, haz seguimiento de la versión instalada frente a la publicada."
"title": "Pestaña App de LXC: detección, enlaces y versiones",
"description": "Asigna a cada aplicación LXC una identidad persistente, acceso web y datos opcionales de versión sin vincular el registro con la actualización."
},
"intro": {
"p1": "La pestaña <strong>App</strong> permite indicar qué aplicaciones se ejecutan dentro de un contenedor LXC. Cada aplicación registrada puede mostrar un nombre, un icono, uno o varios accesos web y, de forma opcional, el estado de su versión.",
"p2": "Un mismo LXC puede tener varias aplicaciones registradas. Por ejemplo, un servicio principal puede compartir el contenedor con una interfaz de administración, una API o cualquier otra aplicación accesible desde un puerto distinto.",
"p3": "Registrar una aplicación no la modifica ni la actualiza. Esta pestaña se ocupa de identificarla y mostrar su información. Los métodos que <em>ejecutan</em> una actualización se configuran y utilizan desde la <link>pestaña Updates</link>."
"p1": "La pestaña <strong>App</strong> registra qué aplicaciones pertenecen a un LXC. Un registro puede contener solo un nombre y un enlace web o incluir también un detector de la versión instalada y una fuente para la versión disponible.",
"p2": "El procedimiento que modifica el software se configura por separado en la <link>pestaña Actualizaciones</link>. Guardar una app nunca ejecuta un instalador ni un actualizador.",
"callout": "El registro, el seguimiento de versiones y la actualización son tres capacidades independientes. Cada una puede utilizarse sin exigir las otras dos."
},
"whatYouGet": {
"heading": "Qué se obtiene al registrar una aplicación",
"lead": "Según los datos que se configuren, ProxMenux puede ofrecer:",
"overview": {
"heading": "Qué puede contener un registro",
"lead": "Un registro guardado puede incluir:",
"items": [
"Un acceso directo a la interfaz web de la aplicación.",
"Varios enlaces cuando el LXC expone más de un servicio o puerto.",
"La versión instalada actualmente.",
"La última versión publicada por el proyecto.",
"Un aviso cuando hay una versión más reciente.",
"Notificaciones de nuevas versiones, si están habilitadas en los ajustes del monitor."
"Un nombre visible y un logotipo adaptado al tema.",
"Uno o varios enlaces web creados con la dirección del LXC, el esquema y el puerto guardado.",
"Un detector opcional de la versión instalada dentro del LXC.",
"Una fuente opcional de GitHub, HTTP JSON o Docker Hub para obtener la última versión disponible.",
"Preferencias de notificación y de inclusión en el contador de actualizaciones por aplicación.",
"Una sección correspondiente en la pestaña Actualizaciones, aunque el seguimiento esté desactivado."
]
},
"discovery": {
"heading": "Detección en caché y Buscar aplicaciones",
"lead": "Las aplicaciones sugeridas forman parte de la caché del modal de cada LXC. El escaneo de arranque las prepara en segundo plano para que la pestaña App pueda mostrar inmediatamente los resultados almacenados.",
"items": [
"Abrir la pestaña App <strong>no</strong> inicia otro escaneo del catálogo ni consulta repetidamente el LXC.",
"<strong>Buscar aplicaciones</strong> ejecuta expresamente una detección nueva solo para ese LXC. Se utiliza después de instalar software mientras ProxMenux ya está en ejecución.",
"La lista anterior permanece visible durante la búsqueda. Las nuevas coincidencias se añaden al finalizar.",
"Si no se encuentra ninguna coincidencia nueva, el resultado aparece junto a las acciones y <strong>Registrar aplicación</strong> continúa disponible para introducirla manualmente.",
"Guardar, eliminar o restaurar una app actualiza la misma caché inmediatamente. El arranque o la restauración de un LXC actualiza únicamente ese sistema mediante su evento de ciclo de vida existente."
],
"trailing": "El seguimiento de versiones es opcional. También es posible registrar una aplicación únicamente para disponer de su nombre, icono y enlaces web.",
"callout": "El aviso <strong>Update available</strong> indica que ProxMenux ha encontrado una diferencia entre la versión instalada y la última versión publicada. No significa necesariamente que ya conozca el procedimiento para actualizar la aplicación."
"callout": "Una sugerencia no es un registro. Permanece en modo de solo lectura hasta que se pulsa <strong>Registrar</strong> y se guarda el formulario."
},
"firstOpening": {
"heading": "Primera apertura de la pestaña App",
"p1": "Al abrir la pestaña, ProxMenux intenta reconocer las aplicaciones del contenedor utilizando la información disponible, como el instalador con el que se creó el LXC, los servicios detectados y los puertos que están escuchando.",
"p2": "Si encuentra coincidencias, las presenta como sugerencias. Revise siempre la propuesta antes de guardarla: la detección facilita el registro, pero no puede garantizar que cada servicio encontrado corresponda exactamente con la aplicación esperada."
},
"figures": {
"f01": {
"alt": "Pestaña App vacía mostrando sugerencias detectadas",
"caption": "Estado inicial sin aplicaciones registradas, con una o varias sugerencias detectadas"
},
"f02": {
"alt": "Búsqueda en el catálogo mostrando coincidencias para el nombre introducido",
"caption": "Búsqueda en el catálogo y selección de una coincidencia"
},
"f03": {
"alt": "Formulario de registro de aplicación con nombre, icono y dos enlaces web",
"caption": "Formulario básico con nombre, icono y dos enlaces web"
},
"f04": {
"alt": "LXC con Docmost y Redis registrados como aplicaciones separadas, cada una con su propio estado de versión",
"caption": "Dos aplicaciones en el mismo LXC — una registrada con file y otra con dpkg, cada una con su propio estado de versión"
},
"f05": {
"alt": "Opciones avanzadas de seguimiento mostrando el método de versión instalada y la fuente upstream",
"caption": "Opciones avanzadas con el método de versión instalada y la fuente de la última versión"
},
"f06": {
"alt": "Aplicación registrada mostrando la versión instalada, la última versión upstream y un indicador de Update available",
"caption": "Una aplicación cableada muestra Installed, Latest upstream, la flecha de Update available cuando difieren y el enlace web"
},
"f07": {
"alt": "Aplicación registrada mínima mostrando solo su nombre y un único enlace web, sin seguimiento de versión",
"caption": "Registro solo con enlace — un nombre y un enlace web, sin seguimiento de versión"
}
},
"registerSuggested": {
"heading": "Registrar una aplicación sugerida",
"registration": {
"heading": "Registrar una aplicación",
"lead": "Las sugerencias detectadas y los registros manuales utilizan el mismo editor:",
"steps": [
"Abra el LXC desde la tarjeta <strong>VMs & LXCs</strong>.",
"Seleccione la pestaña <strong>App</strong>.",
"Localice la aplicación sugerida.",
"Pulse <strong>Register</strong>.",
"Compruebe el nombre, los enlaces y los datos rellenados automáticamente.",
"Guarde la aplicación."
],
"trailing": "Si la sugerencia no corresponde con ningún servicio que quiera registrar, puede ocultarla. Las sugerencias ocultas se pueden recuperar más adelante desde <strong>Register a different app</strong>."
"Pulsa <strong>Registrar</strong> en una sugerencia o <strong>Registrar aplicación</strong> para elegir una entrada del catálogo o escribir un nombre personalizado.",
"Revisa el nombre y el logotipo propuestos por el catálogo.",
"Añade los enlaces web necesarios. Los puertos en escucha se ofrecen como accesos rápidos, pero ninguno se guarda automáticamente.",
"Deja <strong>Seguir versión disponible</strong> desactivado para un registro de solo enlace o actívalo y revisa el detector instalado y la fuente disponible.",
"Utiliza <strong>Probar detector</strong> cuando el seguimiento esté activado y guarda el registro.",
"Pulsa <strong>Hecho</strong> al terminar la edición. Las pestañas App y Actualizaciones reutilizan el registro actualizado de la caché."
]
},
"catalog": {
"heading": "Usar el catálogo",
"p1": "El catálogo ayuda a localizar aplicaciones conocidas y a rellenar algunos de sus datos. Al escribir en el campo del nombre, ProxMenux muestra las coincidencias más cercanas. Al seleccionar una de ellas puede completar automáticamente el nombre, el icono, los puertos habituales y, cuando existe una configuración comprobada, las opciones de seguimiento de versiones.",
"p2": "El catálogo es una ayuda, no una lista completa de todo el software que puede ejecutarse en un LXC. Algunas aplicaciones solo incluyen información básica y otras disponen también de un método preparado para consultar su versión.",
"p3": "Si la aplicación no aparece, puede registrarla manualmente."
"heading": "Registro asistido por el catálogo",
"lead": "El catálogo proporciona valores iniciales, pero el registro guardado sigue siendo editable.",
"items": [
"Los resultados pueden rellenar el nombre canónico, el logotipo y los puertos web habituales.",
"Los detectores conocidos se basan en paquetes, binarios, archivos, distribuciones Python, etiquetas OCI o comandos reales, no en una suposición universal como <code>/root/.app</code>.",
"Las correcciones verificadas en instalaciones reales tienen prioridad cuando una ruta difiere de los datos del instalador.",
"Los marcadores de Proxmox VE Helper-Scripts, como <code>/root/.slug</code>, se mantienen como una señal de compatibilidad para instalaciones recientes, pero no son el único detector.",
"Todos los valores propuestos se pueden editar antes de guardar para cubrir instaladores oficiales e instalaciones manuales."
]
},
"manual": {
"heading": "Registrar una aplicación manualmente",
"p1": "Use <strong>Register a different app</strong> cuando todavía no haya aplicaciones registradas. Si el LXC ya contiene alguna, use <strong>Add another application</strong>.",
"p2": "La configuración básica solo necesita un nombre. Los demás campos se añaden según la información que quiera mostrar.",
"nameHeading": "Nombre e icono",
"nameBody": "Introduzca un nombre que permita reconocer la aplicación fácilmente. El icono es opcional y puede indicarse mediante una URL.",
"linksHeading": "Enlaces web y puertos",
"linksLead": "Cada enlace puede tener:",
"linksItems": [
"Protocolo <code>http</code> o <code>https</code>.",
"Puerto.",
"Descripción, como <em>Web UI</em>, <em>Administration</em> o <em>API</em>.",
"Un icono propio opcional."
"docker": {
"heading": "Representación de los LXC con Docker",
"lead": "En un LXC cuya plataforma principal es Docker, <strong>Docker</strong> es la aplicación que se registra a nivel de LXC.",
"items": [
"Una carga contenerizada como Portainer, Frigate o Vaultwarden no se sugiere como aplicación nativa independiente del LXC.",
"Los servicios Docker en ejecución con puertos TCP publicados aparecen dentro del editor de Docker como enlaces web opcionales.",
"Cada enlace sugerido muestra el servicio, el puerto del host y el puerto del contenedor. Solo deben guardarse los enlaces que ofrecen una interfaz web.",
"Se usa el logotipo general de Docker cuando un enlace no tiene uno específico. El logotipo del enlace tiene prioridad cuando se configura.",
"Después de registrar Docker, Docker Engine y las actualizaciones de imágenes aparecen juntas en su sección de Actualizaciones."
],
"linksTrailing": "ProxMenux combina el protocolo y el puerto con la dirección IP del LXC para crear el acceso web. Añada tantos enlaces como necesite si una aplicación usa varias interfaces o si el contenedor aloja varios servicios relacionados.",
"linksConfirm": "Antes de guardar, compruebe que el puerto corresponde realmente con el servicio y que puede acceder a él desde el navegador."
"callout": "Esta estructura evita que una carga de Docker parezca software instalado directamente en el LXC y conserva los accesos rápidos a sus interfaces."
},
"multiple": {
"heading": "Registrar varias aplicaciones en el mismo LXC",
"intro": "Después de guardar la primera aplicación, pulse <strong>Add another application</strong> y repita el proceso. Cada registro mantiene de forma independiente sus enlaces, su método de detección y su estado de versión.",
"usefulLead": "Esto resulta útil cuando:",
"usefulItems": [
"Un LXC ejecuta varios servicios independientes.",
"Una instalación incluye una aplicación principal y herramientas auxiliares.",
"Cada servicio tiene su propia interfaz web o su propio ciclo de versiones."
],
"dontGroup": "No agrupe bajo un único registro programas que se publican y actualizan por separado. Registrarlos individualmente permite saber con claridad cuál tiene una nueva versión y asignarle su propio método de actualización desde la pestaña Updates."
"webLinks": {
"heading": "Enlaces web y logotipos",
"lead": "Los enlaces web funcionan con o sin seguimiento de versiones.",
"items": [
"Cada enlace guarda un esquema, un puerto, una descripción opcional y una URL de logotipo opcional.",
"La URL mostrada utiliza la dirección actual ya detectada para el LXC; esa dirección no se duplica en cada registro.",
"Un enlace sin logotipo propio utiliza el logotipo general de la app.",
"Varios enlaces pueden representar una interfaz de administración, una API, una interfaz secundaria u otro punto final de la misma app.",
"Una app guardada solo con enlaces también aparece en Actualizaciones, donde se puede configurar posteriormente un actualizador personalizado."
]
},
"tracking": {
"heading": "Seguimiento de versiones",
"intro": "Abra las opciones avanzadas del formulario para configurar el seguimiento. Se necesitan dos datos diferentes:",
"ingredients": [
"<strong>Versión instalada</strong>: cómo consultar la versión que está ejecutándose dentro del LXC.",
"<strong>Última versión disponible</strong>: dónde consultar la versión publicada por el proyecto."
"heading": "Seguimiento opcional de versiones",
"lead": "El seguimiento combina un detector de la versión instalada con una fuente opcional para la versión disponible. Ambos lados se comprueban de forma independiente.",
"colMethod": "Método de versión instalada",
"colUse": "Uso",
"detectorRows": [
{ "method": "dpkg / apk", "use": "Lee la versión del paquete instalado desde los metadatos de Debian, Ubuntu o Alpine." },
{ "method": "binary", "use": "Ejecuta una ruta binaria absoluta o un nombre de comando con sus parámetros de versión." },
{ "method": "file + regex", "use": "Lee un archivo real y extrae la versión mediante un grupo de captura." },
{ "method": "docker label / docker exec", "use": "Lee una etiqueta de versión OCI o ejecuta un comando de versión dentro de un contenedor Docker." },
{ "method": "python distribution", "use": "Usa importlib.metadata mediante el intérprete de Python seleccionado." },
{ "method": "command", "use": "Ejecuta un comando avanzado en formato argv, sin shell, y extrae la versión de su salida." },
{ "method": "manual", "use": "Guarda una versión introducida manualmente; debe cambiarse después de actualizar la app." }
],
"trailing": "Si solo se configura la versión instalada, ProxMenux puede mostrarla, pero no puede determinar si existe una actualización. Para mostrar <strong>Update available</strong>, debe poder obtener y comparar ambos valores.",
"methodsHeading": "Métodos para obtener la versión instalada",
"methodsLead": "Seleccione el método que corresponda con la forma en que se instaló la aplicación:",
"methodsTable": {
"colMethod": "Método",
"colWhen": "Cuándo utilizarlo",
"rows": [
{ "method": "None (link only)", "when": "Solo se necesitan el nombre y los accesos web." },
{ "method": "dpkg package", "when": "La aplicación está instalada como paquete de Debian o Ubuntu." },
{ "method": "apk package", "when": "La aplicación está instalada como paquete de Alpine." },
{ "method": "Binary", "when": "Un ejecutable devuelve su versión mediante un argumento como --version." },
{ "method": "File + regex", "when": "La versión está escrita dentro de un archivo." },
{ "method": "Python distribution", "when": "La aplicación está instalada como un paquete de Python." },
{ "method": "Command", "when": "Es necesario ejecutar un comando específico para obtener la versión." },
{ "method": "Manual", "when": "El usuario introduce la versión instalada." }
]
},
"methodsTrailing": "Utilice el método más directo y estable. Si la aplicación procede de un paquete del sistema, es preferible consultar ese paquete antes que analizar la salida de un comando genérico.",
"commandHeading": "El método Command no actualiza la aplicación",
"commandP1": "En este formulario, <strong>Command</strong> sirve exclusivamente para leer la versión instalada. Sus argumentos se introducen separados por comas y ProxMenux los ejecuta directamente, sin intérprete de shell.",
"commandP2": "Por ejemplo, si la consulta normal es:",
"commandExample1": "myapp version --short",
"commandP3": "Los argumentos del formulario serían:",
"commandExample2": "myapp, version, --short",
"commandP4": "No utilice aquí operadores como <code>&&</code>, redirecciones o tuberías. Si necesita un procedimiento completo para actualizar la aplicación, se configura después en la pestaña Updates.",
"sourceHeading": "Fuente de la última versión disponible",
"sourceLead": "ProxMenux puede consultar una fuente pública del proyecto, por ejemplo:",
"sourceItems": [
"Las releases o tags de un repositorio de GitHub.",
"Un endpoint HTTP que devuelva la versión dentro de una respuesta JSON."
"sourcesHeading": "Fuentes para la versión disponible",
"sources": [
"<strong>Repositorio de GitHub</strong>: último lanzamiento o etiqueta de un repositorio público <code>propietario/nombre</code>.",
"<strong>HTTP JSON</strong>: un punto final público y una ruta como <code>data.version</code> o <code>releases[0].tag_name</code>.",
"<strong>Docker Hub</strong>: etiquetas versionadas filtradas con una expresión regular. La vista previa muestra etiquetas reales coincidentes antes de guardar.",
"Las etiquetas móviles como <code>latest</code>, <code>stable</code> o <code>lts</code> no contienen una versión. Esas imágenes se siguen por digest desde las actualizaciones de imágenes Docker."
],
"sourceTrailing": "Use siempre la fuente oficial de la aplicación. Un repositorio derivado o un endpoint de terceros puede anunciar versiones que no correspondan con la instalación del LXC.",
"regexHeading": "Expresiones regulares de versión",
"regexIntro": "Una expresión regular, o <strong>regex</strong>, sirve para localizar el número de versión dentro de un texto más largo. La mayoría de los proyectos no publican una regex preparada: el usuario debe construirla a partir de una salida real del programa o del nombre de una release.",
"regexOptional": "No siempre es necesaria. Déjela vacía primero si la fuente ya devuelve solo un valor limpio como <code>2.14.3</code>. Añádala únicamente cuando ProxMenux necesite separar la versión de otras palabras, símbolos o números.",
"regexTwoHeading": "Hay dos regex diferentes",
"regexTwoItems": [
"<strong>Installed version regex</strong> se aplica a la salida obtenida dentro del LXC.",
"<strong>Version regex</strong> o <strong>Tag regex</strong> se aplica al nombre de la versión publicada por la fuente externa."
"regexHeading": "Expresión de captura",
"regexLead": "La expresión regular del detector debe devolver la versión en su <strong>primer grupo de captura</strong>.",
"regexRules": [
"Haz coincidir el texto emitido por el binario, archivo, comando o fuente de etiquetas seleccionada; no supongas una ruta genérica.",
"Escapa los puntos literales como <code>\\.</code> para que no coincidan con cualquier carácter.",
"Admite una <code>v</code> inicial solo cuando la fuente pueda incluirla.",
"Incluye sufijos de prepublicación o revisión de distribución únicamente cuando sean relevantes para la comparación.",
"Utiliza <strong>Probar detector</strong> antes de guardar y confirma que la versión mostrada coincide con el LXC."
],
"regexTwoTrailing": "Ambas deben producir valores comparables. Por ejemplo, si la aplicación local devuelve <code>MyApp v2.14.3</code> y GitHub publica <code>release-2.14.3</code>, las dos expresiones deberían extraer <code>2.14.3</code>.",
"step1Heading": "1. Obtener una muestra real",
"step1P1": "Antes de escribir el patrón, obtenga exactamente el texto que ProxMenux tendrá que interpretar.",
"step1P2": "Para la versión instalada, ejecute en la consola del LXC el mismo binario y los mismos argumentos configurados en el formulario. Según el método elegido, también puede consultar el paquete o el archivo correspondiente.",
"step1P3": "Ejemplo:",
"step1Cmd": "myapp --version",
"step1P4": "Supongamos que la salida real es:",
"step1Output": "MyApp version v2.14.3 (stable)",
"step1P5": "Para la versión publicada, revise el nombre exacto de la release o el tag en el repositorio oficial. Si utiliza un endpoint JSON, examine el valor que devuelve la ruta configurada.",
"step1P6": "No construya el patrón a partir de un ejemplo inventado: un espacio, un prefijo o un número adicional puede cambiar el resultado.",
"step2Heading": "2. Identificar la parte que debe conservarse",
"step2Lead": "En el ejemplo anterior queremos conservar <code>2.14.3</code> y descartar:",
"step2Items": [
"El texto <code>MyApp version</code>.",
"La letra <code>v</code>.",
"El texto <code>(stable)</code>."
],
"step2Recommended": "La expresión recomendada sería:",
"step2Regex": "version[ :=]+v?([0-9]+\\.[0-9]+\\.[0-9]+)",
"step2ReadLead": "Se puede leer por partes:",
"step2Breakdown": {
"colPart": "Fragmento",
"colMeaning": "Significado",
"rows": [
{ "part": "version", "meaning": "Busca esa palabra para no confundir la versión con otro número." },
{ "part": "[ :=]+", "meaning": "Admite uno o varios espacios, dos puntos o signos igual." },
{ "part": "v?", "meaning": "La letra v puede aparecer una vez o no aparecer." },
{ "part": "( y )", "meaning": "Marcan la parte que ProxMenux debe conservar." },
{ "part": "[0-9]+", "meaning": "Busca uno o varios dígitos." },
{ "part": "\\.", "meaning": "Busca un punto real entre los números." }
]
},
"step2DotNote": "El punto se escribe como <code>\\.</code> porque, en una regex, un punto sin la barra significa «cualquier carácter».",
"step3Heading": "3. Utilizar un patrón adecuado para el formato",
"step3Lead": "Estos patrones cubren muchos casos habituales:",
"step3Examples": {
"colText": "Texto de ejemplo",
"colRegex": "Regex recomendada",
"colResult": "Resultado",
"rows": [
{ "text": "v2.14.3", "regex": "v?([0-9]+\\.[0-9]+\\.[0-9]+)", "result": "2.14.3" },
{ "text": "Version: 2.14", "regex": "Version[ :=]+v?([0-9]+(?:\\.[0-9]+){1,3})", "result": "2.14" },
{ "text": "release-2.14.3.1", "regex": "release-v?([0-9]+(?:\\.[0-9]+){1,3})", "result": "2.14.3.1" },
{ "text": "build 2026.08.10", "regex": "build[ :=]+([0-9]{4}\\.[0-9]{1,2}\\.[0-9]{1,2})", "result": "2026.08.10" },
{ "text": "{\"version\":\"2.14.3\"}", "regex": "\"version\"\\s*:\\s*\"v?([0-9]+(?:\\.[0-9]+){1,3})\"", "result": "2.14.3" }
]
},
"step3Note1": "<code>(?: ... )</code> agrupa una parte del patrón sin crear un valor de salida adicional. Esta forma es útil para aceptar versiones con dos, tres o cuatro bloques sin complicar el resultado.",
"step3Note2": "Introduzca la regex tal como aparece en la tabla: sin comillas alrededor y sin las barras <code>/.../</code> que utilizan algunas herramientas en línea.",
"step4Heading": "4. Usar una sola captura siempre que sea posible",
"step4Intro": "ProxMenux utiliza los paréntesis de captura para decidir qué valor devolver:",
"step4Items": [
"Sin paréntesis de captura, conserva toda la coincidencia.",
"Con una captura, conserva el contenido de esa captura.",
"Con varias capturas, une sus valores mediante puntos."
],
"step4Trailing": "Para evitar resultados inesperados, lo más sencillo es encerrar toda la versión en una sola captura y utilizar <code>(?: ... )</code> para los grupos auxiliares.",
"step4RecLabel": "Recomendado:",
"step4RecRegex": "v?([0-9]+(?:\\.[0-9]+){1,3})",
"step4LessLabel": "Menos claro para un usuario principiante:",
"step4LessRegex": "v?([0-9]+)\\.([0-9]+)\\.([0-9]+)",
"step4Note": "Los dos pueden producir <code>2.14.3</code>, pero el primero es más fácil de mantener si el formato cambia.",
"step5Heading": "5. Evitar coincidencias demasiado generales",
"step5Lead": "Un patrón como este suele ser demasiado abierto:",
"step5Regex": "([0-9.]+)",
"step5P1": "Puede capturar un año, un puerto, la versión de una dependencia o el primer número que aparezca en la salida. Añada una palabra cercana como <code>version</code>, <code>release</code> o <code>build</code> cuando el texto contenga varios números.",
"step5P2": "También debe comprobar que la fuente de versiones no está mezclando releases estables con versiones beta, nightly o de desarrollo. La regex debe seleccionar el mismo tipo de versión que está instalado en el LXC.",
"step6Heading": "6. Guardar y comprobar el resultado",
"step6Lead": "Después de guardar la aplicación, pulse <strong>Check</strong> y revise los dos valores que muestra ProxMenux:",
"step6Output": "Installed: 2.14.3\nLatest: 2.15.0",
"step6CorrectLead": "La regex es correcta si:",
"step6CorrectItems": [
"Ambos campos contienen únicamente la versión esperada.",
"No se ha capturado el nombre de la aplicación ni texto adicional.",
"No se ha confundido la versión con otro número.",
"La versión local y la publicada utilizan el mismo formato."
],
"step6ErrorNote": "Si aparece un error de coincidencia, vuelva a obtener la salida real y compare carácter por carácter. Revise especialmente mayúsculas, espacios, guiones, la letra <code>v</code> y el número de bloques de la versión.",
"step6Callout": "Si no puede construir un patrón fiable, es preferible desactivar temporalmente el seguimiento de la última versión y mantener la aplicación como un registro con enlaces. Una regex incorrecta puede generar avisos falsos o esconder una actualización real."
"regexExampleLead": "Captura habitual de una versión semántica:",
"regexExample": "v?(\\d+\\.\\d+\\.\\d+)",
"regexCallout": "Una coincidencia correcta de la expresión no demuestra que la ruta sea válida. El paquete, binario o archivo también debe existir en la instalación real registrada."
},
"state": {
"heading": "Interpretar el estado de una aplicación",
"lead": "Una aplicación registrada puede mostrar los siguientes estados:",
"updater": {
"heading": "El seguimiento y la actualización son independientes",
"lead": "La <link>pestaña Actualizaciones</link> crea una sección de app desde el momento en que se guarda cualquier registro.",
"items": [
"<strong>Up to date</strong>: las versiones coinciden.",
"<strong>Update available</strong>: la fuente publica una versión más reciente.",
"<strong>Checking</strong>: la comprobación está en curso.",
"<strong>Version tracking pending</strong>: todavía no se ha completado una comprobación.",
"<strong>Error</strong>: no se ha podido obtener o interpretar alguna de las versiones."
],
"trailing": "Use <strong>Check</strong> para repetir la consulta manualmente después de cambiar la configuración. Si aparece un error, revise primero el método de la versión instalada, la fuente de la última versión y las expresiones regulares."
"Un registro de solo enlace indica que el seguimiento no está configurado, pero puede recibir un comando de actualización personalizado.",
"Una app con seguimiento, pero sin un método ejecutable, muestra un mensaje neutro que solicita un comando personalizado.",
"Una app con un wrapper verificado de Proxmox VE Helper-Scripts puede usar ese actualizador integrado aunque el registro comenzara únicamente con un enlace web.",
"Añadir o editar un actualizador no cambia el detector ni la fuente disponible guardados en la pestaña App."
]
},
"manage": {
"heading": "Administrar los registros existentes",
"lead": "Active el modo de administración para:",
"states": {
"heading": "Estados de versión en la tarjeta",
"colState": "Estado",
"colDisplay": "Presentación",
"colMeaning": "Significado",
"rows": [
{ "state": "Actualización disponible", "display": "Versión disponible en morado con un icono de flecha ascendente", "meaning": "Las versiones instalada y disponible son diferentes." },
{ "state": "Actualizada", "display": "Versiones instalada y disponible sin la alerta morada", "meaning": "La última comprobación no encontró una versión superior." },
{ "state": "Seguimiento pendiente", "display": "Estado de comprobación o pendiente", "meaning": "El registro está configurado, pero aún no ha completado las dos comprobaciones." },
{ "state": "Seguimiento desactivado", "display": "Solo enlaces web, sin bloque de comparación", "meaning": "El registro sigue siendo válido y puede tener un actualizador." },
{ "state": "Error de comprobación", "display": "Explicación en ámbar dentro de la tarjeta", "meaning": "El estado guardado anterior permanece visible mientras se informa del error del detector o de la fuente." }
]
},
"management": {
"heading": "Gestionar apps guardadas y sugeridas",
"lead": "Las acciones inferiores tienen funciones distintas:",
"items": [
"Comprobar de nuevo una aplicación.",
"Editar su nombre, enlaces o seguimiento de versiones.",
"Eliminar un registro que ya no sea necesario.",
"Añadir otra aplicación al mismo LXC."
],
"trailing": "Eliminar el registro no desinstala ni detiene la aplicación. Solo borra la información que ProxMenux utiliza para mostrarla y supervisar su versión."
"<strong>Buscar aplicaciones</strong> actualiza la detección únicamente para este LXC.",
"<strong>Registrar otra aplicación</strong> abre el catálogo y el editor manual sin volver a escanear el LXC.",
"<strong>Editar</strong> muestra en cada tarjeta las acciones Eliminar, Comprobar, notificaciones y Editar campos.",
"<strong>Ocultar</strong> retira una sugerencia no deseada. Las detecciones ocultas pueden restaurarse desde el navegador de registro.",
"<strong>Comprobar</strong> actualiza los datos de versión de la app guardada; no busca aplicaciones nuevas."
]
},
"options": {
"heading": "Opciones adicionales",
"lead": "Debajo de las opciones de seguimiento de versión hay dos casillas independientes:",
"items": [
"<strong>Notificarme cuando haya una nueva versión disponible</strong> — envía el evento <code>app_update_available</code> a los canales activos en <strong>Ajustes → Notificaciones</strong>.",
"<strong>Excluir del contador de actualizaciones del LXC</strong> — no suma esta aplicación al badge agregado de actualizaciones del card del LXC."
],
"trailing": "Ambas casillas se marcan por separado. La pestaña App sigue mostrando el estado real de cada aplicación registrada al margen de esta elección."
"troubleshooting": {
"heading": "Situaciones habituales",
"colProblem": "Situación",
"colResolution": "Resolución",
"rows": [
{ "problem": "Se instaló software después de arrancar ProxMenux", "resolution": "Pulsa Buscar aplicaciones. El escaneo explícito actualiza las sugerencias en caché de ese LXC." },
{ "problem": "No se detectó la aplicación", "resolution": "Regístrala manualmente. Un nombre y un enlace web son suficientes; el seguimiento puede añadirse después." },
{ "problem": "El detector sugerido devuelve una versión incorrecta", "resolution": "Abre Editar campos, selecciona el paquete, binario o archivo real y prueba el detector antes de guardar." },
{ "problem": "Una carga Docker no se ofrece como app LXC", "resolution": "Registra Docker y añade la interfaz publicada de la carga como enlace web de Docker. Las actualizaciones de imágenes permanecen en la sección Docker." },
{ "problem": "Una app guardada no tiene botón de actualización", "resolution": "Abre Actualizaciones y configura su método. El seguimiento de versiones no define por sí solo cómo se instala una actualización." }
]
},
"notDetected": {
"heading": "Si la aplicación no se detecta",
"intro": "La detección automática no es necesaria para utilizar esta función. Si no aparece ninguna sugerencia:",
"steps": [
"Registre la aplicación manualmente.",
"Añada sus enlaces y puertos conocidos.",
"Déjela como <strong>None (link only)</strong> si solo necesita un acceso directo.",
"Configure el seguimiento de versiones únicamente cuando haya identificado una fuente fiable para ambos valores.",
"Configure después el método de actualización desde <link>Updates</link>, si quiere que ProxMenux pueda ejecutarlo."
],
"trailing": "No invente un nombre de paquete, una ruta o una expresión regular para completar el formulario. Es preferible un registro sencillo y correcto que un seguimiento automático basado en datos que no se hayan verificado."
"figures": {
"catalog": {
"alt": "Catálogo de registro con resultados, logotipos, puertos y campos de detección",
"caption": "Los metadatos del catálogo aceleran el registro y todos los valores propuestos siguen siendo editables."
},
"webLinks": {
"alt": "Tarjeta de aplicación LXC guardada con un enlace web",
"caption": "Un registro de solo enlace es válido: el seguimiento puede quedar desactivado y el actualizador se añade de forma independiente."
},
"tracking": {
"alt": "Campos opcionales del detector instalado y de la fuente disponible",
"caption": "La detección instalada y la fuente disponible se configuran y prueban por separado."
},
"card": {
"alt": "Tarjeta guardada con versiones instalada y disponible y un enlace web",
"caption": "La tarjeta combina identidad, datos de versión y acceso web sin ejecutar actualizaciones desde esta pestaña."
}
}
}
@@ -1,231 +1,194 @@
{
"meta": {
"title": "Updates — actualizar el sistema y las aplicaciones de un LXC | ProxMenux",
"description": "Qué mecanismos puede utilizar ProxMenux para actualizar el sistema operativo y las aplicaciones registradas en un contenedor LXC."
"title": "Actualizaciones LXC: SO, apps y Docker | ProxMenux",
"description": "Configura y ejecuta actualizaciones del sistema operativo, aplicaciones, Docker Engine e imágenes Docker desde un contenedor LXC."
},
"header": {
"title": "Updates — actualizar el sistema y las aplicaciones de un LXC",
"description": "Dónde ProxMenux decide cómo actualizar un contenedor: paquetes del sistema operativo, ayudante de Community Scripts o un comando personalizado."
"title": "Actualizaciones LXC: SO, apps y Docker",
"description": "Revisa cada objetivo de actualización, ejecútalo por separado o combina una selección exacta en una actualización en bloque."
},
"intro": {
"p1": "La pestaña <strong>Updates</strong> reúne los métodos que ProxMenux puede ejecutar para actualizar el sistema operativo y las aplicaciones registradas en un contenedor LXC.",
"p2": "La <link>pestaña App</link> indica qué aplicaciones existen y, opcionalmente, compara sus versiones. <strong>Updates</strong> se ocupa de la acción: determina qué mecanismo está disponible, muestra el botón correspondiente y ejecuta la actualización dentro del contenedor.",
"callout": "<strong>Idea principal:</strong> detectar una versión nueva y saber cómo instalarla son tareas diferentes. Una aplicación puede mostrar <strong>Update available</strong> en la pestaña App y no tener todavía un botón de actualización hasta que se defina un método válido."
"p1": "La pestaña <strong>Actualizaciones</strong> separa la detección de versiones de la acción que instala una actualización. El registro y el seguimiento opcional viven en la <link>pestaña App</link>; los métodos ejecutables se gestionan aquí.",
"p2": "Una aplicación guardada aparece en Actualizaciones aunque solo contenga un enlace web. El seguimiento de versiones es opcional y el actualizador se puede configurar de forma independiente.",
"callout": "No se deduce una acción únicamente por el nombre de una aplicación. ProxMenux solo ejecuta un método integrado después de verificarlo o un comando personalizado guardado expresamente."
},
"overview": {
"heading": "Contenido de la pestaña",
"lead": "Cada objetivo disponible tiene su propia sección y acción:",
"items": [
"<strong>Paquetes del SO</strong> para contenedores Debian, Ubuntu y Alpine.",
"Una sección por cada <strong>aplicación registrada</strong>, incluidos los registros que solo contienen enlaces.",
"Una sección <strong>Docker</strong> cuando Docker está registrado, con Docker Engine y las imágenes etiquetadas dentro del mismo bloque.",
"Una <strong>Actualización en bloque</strong> configurable, seguida de las opciones de copia, reinicio y programación."
]
},
"mechanisms": {
"heading": "Métodos de actualización disponibles",
"intro": "En función de cómo se instaló la aplicación y de dónde vengan sus actualizaciones, ProxMenux elige entre tres mecanismos.",
"osHeading": "Paquetes del sistema operativo",
"osP1": "En contenedores Debian o Ubuntu, ProxMenux consulta y actualiza los paquetes mediante APT. En Alpine utiliza APK.",
"osP2": "Las aplicaciones registradas cuyo método de instalación sea <code>dpkg</code> o <code>apk</code> forman parte de esta actualización. No necesitan un segundo comando en la sección de la aplicación: se actualizan al aplicar <strong>Apply OS update</strong>.",
"osP3": "La sección muestra el número de paquetes pendientes, cuántos son de seguridad, la familia del sistema y la hora de la última comprobación.",
"helperHeading": "Ayudante Proxmox VE Helper-Scripts",
"helperP1": "Cuando el LXC se creó con un helper del proyecto <linkHelperHome>Proxmox VE Helper-Scripts</linkHelperHome>, ProxMenux reconoce su actualizador. La aplicación correspondiente debe estar registrada en la pestaña App para que el monitor pueda relacionar el helper con el servicio que se muestra al usuario.",
"helperP2": "<strong>La lógica de actualización la mantiene el proyecto Proxmox VE Helper-Scripts</strong>, no ProxMenux. Cada helper incluye su propia función <code>update_script</code>; ProxMenux la descarga y la ejecuta dentro del contenedor en modo silencioso (<code>PHS_SILENT=1</code>), sin prompts. No es necesario copiar el helper ni escribir un comando personalizado en ProxMenux.",
"helperP3": "La documentación completa del mecanismo de actualización vive en la web del proyecto — <linkHelperDocs>community-scripts.org / update-apps</linkHelperDocs>. Cada helper tiene además su propia entrada en la <linkHelperHome>web del proyecto</linkHelperHome> con la descripción de lo que hace el script, su configuración por defecto y la fuente de la lógica de actualización — utilice esa página como referencia de lo que el actualizador cambiará dentro del LXC.",
"helperP4": "No todos los helpers admiten actualización in situ. Si el catálogo marca una aplicación como no actualizable, la pestaña lo indicará y no presentará ese método como disponible.",
"customHeading": "Comando personalizado",
"customP1": "Una aplicación registrada puede guardar su propio comando de actualización. ProxMenux lo ejecuta dentro del LXC cuando el usuario pulsa <strong>Apply update</strong> o cuando una tarea programada incluye esa aplicación.",
"customP2": "Este método está pensado para aplicaciones cuyo instalador no proporciona un helper reconocido y que tampoco se actualizan como parte de APT o APK."
"heading": "Cómo se selecciona el método",
"lead": "La vía integrada de Proxmox VE Helper-Scripts sigue el mecanismo oficial <helper>update-apps</helper>. El resto de instalaciones usa el método de paquetes, Docker o el comando personalizado correspondiente.",
"colSource": "Origen",
"colAction": "Acción mostrada",
"colNotes": "Qué se ejecuta",
"rows": [
{
"source": "Paquetes APT o APK",
"action": "Aplicar actualizaciones de SO",
"notes": "Actualiza los paquetes del contenedor. Las apps registradas como paquetes dpkg o apk quedan cubiertas en la misma ejecución."
},
{
"source": "Proxmox VE Helper-Scripts",
"action": "Aplicar actualización",
"notes": "Usa el wrapper /usr/bin/update verificado. Un marcador antiguo sin wrapper válido se identifica, pero nunca se ejecuta automáticamente."
},
{
"source": "Comando personalizado",
"action": "Ejecutar actualizador",
"notes": "Ejecuta el comando guardado dentro del LXC y reemplaza cualquier actualizador integrado de esa aplicación."
},
{
"source": "Docker Engine",
"action": "Actualizar Docker Engine",
"notes": "Actualiza únicamente los paquetes Docker instalados y sus dependencias necesarias. No modifica otros paquetes ni los contenedores."
},
{
"source": "Imagen Docker",
"action": "Actualizar imagen",
"notes": "Descarga la imagen seleccionada y recrea su grupo de servicios Compose o su contenedor independiente protegido."
}
],
"callout": "Un comando personalizado siempre <strong>reemplaza</strong> al actualizador integrado de Proxmox VE Helper-Scripts para esa aplicación. Los dos métodos no se ejecutan uno detrás de otro."
},
"decision": {
"heading": "Cómo decide ProxMenux qué acción mostrar",
"table": {
"colSituation": "Situación",
"colAction": "Acción adecuada",
"rows": [
{ "situation": "Hay paquetes APT o APK pendientes", "action": "Apply OS update" },
{ "situation": "La aplicación usa un paquete dpkg o apk", "action": "Apply OS update — no necesita un comando propio" },
{ "situation": "Hay un helper compatible y la aplicación está registrada", "action": "Apply update mediante Community Scripts" },
{ "situation": "La aplicación registrada tiene un comando personalizado", "action": "Apply update mediante ese comando" },
{ "situation": "Hay una versión nueva, pero no existe helper ni comando", "action": "Muestra No updater configured y ofrece añadir un comando" },
{ "situation": "Hay actualizaciones del sistema y métodos de aplicaciones disponibles", "action": "Puede aparecer una acción combinada Apply OS + Apps updates" }
]
},
"trailing": "Una aplicación registrada únicamente como enlace no aparece como actualizable, porque ProxMenux no dispone de información suficiente para asociarle un método."
"docker": {
"heading": "Docker Engine e imágenes Docker",
"lead": "Después de registrar Docker en la pestaña App, el motor y el inventario de imágenes aparecen dentro de la misma sección <strong>Docker</strong>.",
"items": [
"El seguimiento de Docker Engine es independiente del contador de paquetes del SO y dispone de su propio botón de actualización.",
"Las imágenes locales con etiqueta se comparan con el registro mediante un digest inmutable. <strong>Comprobar ahora</strong> actualiza el inventario sin descargar imágenes ni reiniciar contenedores.",
"Los servicios Compose se actualizan desde el proyecto declarado. Las imágenes de un mismo grupo se procesan juntas para no recrear repetidamente el proyecto.",
"Un contenedor independiente se recrea con su configuración actual. El flujo protegido conserva datos de reversión y restaura el contenedor anterior si falla la recreación.",
"Cada imagen se puede seleccionar por separado en actualizaciones manuales, en bloque y programadas, salvo las dependencias Compose declaradas que deben acompañar a su servicio principal."
],
"callout": "Los contenedores que se ejecutan dentro de Docker no aparecen como aplicaciones LXC independientes. Sus puertos web publicados se pueden guardar como enlaces de Docker; las actualizaciones de imágenes permanecen en la sección Docker."
},
"figures": {
"f01": {
"alt": "Sección OS packages mostrando el conteo de paquetes pendientes, el conteo de security y el botón Apply OS update",
"caption": "Paquetes del sistema pendientes: total, actualizaciones de seguridad y botón Apply OS update"
},
"f02": {
"alt": "La misma sección OS packages tras aplicar — sin paquetes pendientes, badge OS up to date",
"caption": "Tras aplicar: 'No OS updates pending' y el badge OS up to date"
},
"f03": {
"alt": "Aplicación registrada mostrando 'No update method available' y un botón Add custom update command",
"caption": "'No update method available' — ProxMenux hace seguimiento pero no tiene aún ningún método para actualizarla"
},
"f04": {
"alt": "Editor del comando personalizado con el placeholder de ejemplo visible dentro del textarea",
"caption": "El editor del comando personalizado con su placeholder de ejemplo y los botones Cancel y Save"
},
"f05": {
"alt": "Panel de terminal titulado 'Apply updates — CT 103' mostrando la salida de apt en vivo mientras se desempaquetan paquetes",
"caption": "Panel de terminal transmitiendo la salida de la actualización en vivo mientras apt desempaqueta paquetes dentro del CT"
},
"f06": {
"alt": "Tarjeta Options con Snapshot before applying activo, Backup storage a pbs y Restart after applying activo",
"caption": "Tarjeta Options con snapshot vzdump, almacenamiento de backup y reinicio-tras-aplicar activados a la vez"
},
"f07": {
"alt": "Sección Scheduled updates habilitada — Frequency en Daily at 3:00, expresión cron 0 3 * * * y What to update en OS + application",
"caption": "Scheduled updates activadas — preset de frecuencia, expresión cron correspondiente y ámbito seleccionado"
}
"actions": {
"heading": "Acciones individuales y colores de estado",
"lead": "Cada sección conserva su propia acción aunque exista una actualización en bloque configurada.",
"items": [
"El botón <strong>Editar</strong> está siempre disponible. Los métodos integrados muestran su comando actual para poder revisarlo, reemplazarlo o borrarlo.",
"Si el seguimiento de versiones está desactivado pero existe un actualizador, aparece la acción neutra <strong>Ejecutar actualizador</strong>. ProxMenux no afirma que exista una actualización pendiente.",
"Si no existe ningún método, <strong>Configurar</strong> abre el editor del comando personalizado.",
"La acción <strong>Actualizar imagen</strong> solo afecta a la unidad Docker seleccionada; no actualiza Docker Engine ni imágenes no relacionadas."
],
"statusColState": "Estado conocido",
"statusColAppearance": "Aspecto",
"statusColMeaning": "Significado",
"statusRows": [
{
"state": "Actualización verificada",
"appearance": "Texto morado, icono de flecha ascendente y acción morada",
"meaning": "La versión instalada y la disponible, o los digests de imagen, son diferentes."
},
{
"state": "Actualizado y verificado",
"appearance": "Comprobación verde y acción Actualizado en verde",
"meaning": "La última comprobación terminada confirma que el objetivo está actualizado."
},
{
"state": "Versión desconocida",
"appearance": "Texto y acción neutros",
"meaning": "El actualizador puede ejecutarse, pero no existen datos de versión para marcarlo como pendiente o actualizado."
}
]
},
"custom": {
"heading": "Añadir un comando de actualización",
"p1": "Cuando una aplicación tiene seguimiento de versiones pero no dispone de un método de actualización, la pestaña muestra <strong>No updater configured</strong>. Pulse <strong>Add custom update command</strong> para abrir el editor.",
"p2": "El comando debe representar el procedimiento real y completo que actualiza esa aplicación. No debe ser simplemente el comando que muestra su versión."
},
"figureOut": {
"heading": "Cómo averiguar el comando correcto",
"intro": "No existe un comando universal para actualizar todas las aplicaciones. Antes de guardar uno, identifique cómo se instaló el software y cuál es el procedimiento recomendado por su proyecto.",
"step1Heading": "1. Comprobar si ya lo gestiona el sistema",
"step1P1": "Si la aplicación se instaló desde los repositorios de Debian, Ubuntu o Alpine, normalmente se actualizará con los paquetes del sistema. En ese caso no añada un comando personalizado: utilice <strong>Apply OS update</strong>.",
"step1P2": "Puede comprobar el origen del paquete desde la consola del LXC con las herramientas de su distribución. Por ejemplo:",
"step1Cmd1": "dpkg -l | grep -i nombre",
"step1P3": "o:",
"step1Cmd2": "apk info | grep -i nombre",
"step1P4": "Sustituya <code>nombre</code> por el paquete que está investigando. Que el texto aparezca en la búsqueda no confirma por sí solo que sea el paquete principal; verifique su nombre en la documentación de la aplicación.",
"step2Heading": "2. Consultar la documentación oficial",
"step2P1": "Busque en la documentación o el repositorio oficial apartados como <strong>Upgrade</strong>, <strong>Update</strong>, <strong>Maintenance</strong> o <strong>Manual installation</strong>. El procedimiento debe corresponder con el método que se utilizó para instalar la aplicación en ese LXC.",
"step2P2": "No use instrucciones destinadas a otra distribución, otro tipo de instalación o una versión diferente del programa.",
"step3Heading": "3. Revisar la instalación existente",
"step3Lead": "Si no recuerda cómo se instaló la aplicación, revise:",
"step3Items": [
"El historial o las notas del instalador original.",
"La ruta donde se encuentran sus archivos.",
"La definición del servicio que la inicia.",
"Los scripts de mantenimiento incluidos por la propia aplicación.",
"La documentación guardada dentro de su directorio de instalación."
],
"step3P1": "Para un servicio systemd, este comando puede ayudar a localizar el ejecutable y su directorio de trabajo:",
"step3Cmd": "systemctl show nombre-del-servicio -p ExecStart -p WorkingDirectory",
"step3P2": "Esto ayuda a identificar la instalación, pero no convierte automáticamente la línea <code>ExecStart</code> en un comando de actualización.",
"step4Heading": "4. Probar el procedimiento en la consola del LXC",
"step4Lead": "Abra la consola del contenedor y ejecute el procedimiento manualmente antes de guardarlo en ProxMenux. Compruebe que:",
"step4Items": [
"Finaliza sin preguntas ni menús interactivos.",
"Devuelve un código de salida correcto.",
"Reinicia o recarga únicamente los servicios necesarios.",
"La aplicación vuelve a estar disponible.",
"La versión instalada cambia como se esperaba."
],
"step4Note": "Cuando sea posible, haga antes una copia de seguridad del contenedor.",
"step5Heading": "5. Guardar solo el comando interno",
"step5P1": "Escriba únicamente lo que se ejecutaría dentro del LXC. No incluya:",
"step5Cmd1": "pct exec <vmid> --",
"step5P2": "ProxMenux ya se encarga de entrar en el contenedor. El comando se ejecuta como <code>root</code> mediante <code>sh -c</code>, por lo que admite operaciones encadenadas y cambios de directorio.",
"step5P3": "Si el actualizador debe ejecutarse desde una ruta concreta, inclúyala de forma explícita:",
"step5Cmd2": "cd /opt/mi-aplicacion && ./update.sh",
"step5P4": "Si el proyecto proporciona un actualizador en otra ruta, use siempre la ruta y los argumentos indicados por su documentación oficial."
},
"requirements": {
"heading": "Requisitos de un comando fiable",
"lead": "Antes de utilizarlo desde el monitor, compruebe que el comando:",
"heading": "Comandos de actualización personalizados",
"lead": "El comando personalizado cubre instalaciones sin un actualizador integrado verificado y permite reemplazar el procedimiento normal cuando sea necesario.",
"items": [
"Puede ejecutarse sin intervención del usuario.",
"Utiliza rutas absolutas o cambia primero al directorio correcto.",
"Detiene, migra y reinicia los servicios según las instrucciones oficiales.",
"Devuelve un error cuando la actualización falla.",
"No contiene contraseñas, tokens ni otros secretos visibles.",
"No descarga ni ejecuta scripts procedentes de fuentes que no sean de confianza."
"Abre <strong>Configurar</strong> cuando el campo está vacío o <strong>Editar</strong> cuando ya existe un método.",
"En una app integrada o en Docker Engine, el editor muestra el comando utilizado actualmente. Al guardar otro contenido pasa a ser la sustitución explícita de ese registro.",
"El procedimiento completo debe probarse antes en el terminal del LXC. Debe ser no interactivo, usar el directorio correcto y devolver un código distinto de cero cuando falle.",
"No incluyas <code>pct exec</code>; ProxMenux ya entra en el contenedor y ejecuta el comando como root."
],
"trailing": "El contenido se guarda en la configuración asociada a ese LXC y se ejecuta con privilegios de administrador. Trátelo con el mismo cuidado que cualquier comando ejecutado como <code>root</code>."
"exampleLead": "Ejemplo de procedimiento completo dentro del contenedor:",
"example": "cd /opt/mi-app && ./update.sh",
"callout": "Un comando de versión como <code>miapp --version</code> solo lee una versión; no instala nada. Los comandos se ejecutan con privilegios administrativos y deben revisarse con el mismo cuidado que un comando de shell como root."
},
"difference": {
"heading": "Diferencia entre el comando de detección y el de actualización",
"lead": "Los dos campos tienen objetivos distintos:",
"table": {
"colField": "Campo",
"colLocation": "Ubicación",
"colRole": "Función",
"rows": [
{
"field": "Command para la versión instalada",
"location": "App → seguimiento avanzado",
"role": "Consulta y devuelve la versión actual; se ejecuta como una lista de argumentos, sin shell."
},
{
"field": "Custom update command",
"location": "Updates",
"role": "Ejecuta el procedimiento de actualización; se interpreta mediante sh -c."
}
]
},
"trailing": "No copie automáticamente el comando de un campo al otro. Un comando como <code>myapp --version</code> puede detectar correctamente la versión, pero no instala una nueva versión."
},
"apply": {
"heading": "Aplicar una actualización",
"lead": "Antes de pulsar un botón de aplicación:",
"steps": [
"Revise qué sección se va a actualizar: sistema, una aplicación o ambas.",
"Compruebe las opciones de copia de seguridad y reinicio.",
"Pulse el botón correspondiente.",
"Siga la salida del proceso en la ventana de terminal.",
"Compruebe el resultado final y que el servicio vuelva a responder."
"bulk": {
"heading": "Actualización en bloque",
"lead": "La actualización en bloque crea una acción reutilizable para un conjunto exacto de objetivos del LXC. Aparece después de las secciones de apps y Docker y antes de <strong>Opciones</strong>.",
"items": [
"Los paquetes del SO son obligatorios. Debe seleccionarse al menos una app, Docker Engine o unidad de imagen Docker adicional.",
"Las aplicaciones y unidades Docker se seleccionan individualmente. Un servicio principal de Compose muestra las dependencias que se actualizarán con él.",
"Los objetivos eliminados o no disponibles se marcan como obsoletos y deben retirarse antes de guardar la configuración.",
"El botón <strong>Aplicar actualizaciones</strong> es morado si algún objetivo seleccionado tiene una actualización verificada, verde si todos están verificados como actualizados y neutro cuando el resultado es desconocido.",
"Eliminar la configuración en bloque no borra los métodos individuales ni la programación."
],
"trailing1": "Si el LXC está detenido, ProxMenux lo inicia para ejecutar el proceso. Si la actualización finaliza correctamente y está activada la opción de reinicio, el contenedor se reinicia al terminar.",
"systemLead": "En una actualización del sistema:",
"systemItems": [
"Debian y Ubuntu ejecutan la actualización mediante APT.",
"Alpine ejecuta la actualización mediante APK."
],
"appLead": "En una actualización de aplicación:",
"appItems": [
"Se ejecuta el helper compatible, si existe.",
"Se ejecuta el comando personalizado guardado para la aplicación, si está configurado.",
"Si se han seleccionado varias aplicaciones, se ejecutan sus métodos en secuencia."
],
"trailing2": "La ventana de terminal muestra el progreso y termina con un resultado correcto o con el código de error devuelto por el proceso."
"callout": "La actualización en bloque no reemplaza los botones individuales. Es un acceso opcional para una selección que debe ejecutarse junta."
},
"backup": {
"heading": "Copia de seguridad antes de actualizar",
"p1": "Active <strong>Snapshot the container before applying</strong> para crear una copia de seguridad con <code>vzdump</code> antes de modificar el LXC. También puede elegir el almacenamiento de destino.",
"p2": "Si se solicita la copia de seguridad y esta falla, ProxMenux no continúa con la actualización. De este modo se evita iniciar los cambios sin disponer del punto de recuperación solicitado.",
"p3": "Esta opción se aplica tanto a las ejecuciones manuales como a las programadas."
},
"restart": {
"heading": "Reinicio después de actualizar",
"p1": "<strong>Restart the container after applying</strong> es una preferencia, no un aviso de que el reinicio sea obligatorio. Active la opción cuando el procedimiento de la aplicación o los paquetes instalados lo requieran.",
"p2": "El reinicio solo se realiza después de una ejecución correcta. Si la actualización falla, el contenedor permanece iniciado para facilitar la revisión del error.",
"p3": "Las opciones de copia de seguridad y reinicio se guardan para ese LXC y se utilizan también en sus tareas programadas."
"options": {
"heading": "Opciones de copia y reinicio",
"lead": "Las mismas opciones se aplican a ejecuciones manuales, en bloque y programadas:",
"items": [
"<strong>Instantánea antes de aplicar</strong> crea una copia vzdump en el almacenamiento seleccionado. Si la copia solicitada falla, la actualización no comienza.",
"<strong>Reiniciar después de aplicar</strong> reinicia el LXC únicamente tras una ejecución correcta.",
"Las selecciones se guardan por LXC y son independientes de la lista de objetivos."
]
},
"scheduled": {
"heading": "Actualizaciones programadas",
"p1": "La sección <strong>Scheduled updates</strong> permite ejecutar automáticamente el mismo flujo utilizado por los botones manuales.",
"createLead": "Para crear una programación:",
"createSteps": [
"Abra <strong>Options</strong> y pulse <strong>Edit</strong>.",
"Active <strong>Scheduled updates</strong>.",
"Elija una frecuencia predefinida o introduzca una expresión cron.",
"Seleccione qué se actualizará: solo paquetes del sistema, solo aplicaciones o sistema y aplicaciones.",
"Revise las opciones de copia de seguridad y reinicio.",
"Guarde la configuración."
"lead": "La programación usa los mismos objetivos ejecutables y opciones de seguridad que las acciones manuales.",
"items": [
"Selecciona una frecuencia o expresión cron y después objetivos exactos: paquetes del SO, apps individuales, Docker Engine, unidades Docker independientes o grupos de servicios Compose.",
"La espera tras una versión solo se aplica a las apps seleccionadas con seguimiento. Las apps sin seguimiento ejecutan su actualizador cuando vence la programación.",
"El estado de la última ejecución diferencia entre éxito, finalización parcial, error, retención de seguridad y ausencia de elementos pendientes.",
"Las programaciones externas detectadas de Proxmox VE Helper-Scripts se muestran aparte para hacer visible cualquier automatización coincidente."
],
"p2": "La tarjeta muestra si la programación está activa, qué elementos incluye y el resultado de la última ejecución. También puede conservar una programación desactivada para volver a habilitarla más adelante o eliminarla por completo.",
"p3": "Si ProxMenux detecta una programación externa creada por Community Scripts en el host, la muestra para que el usuario sepa que ya existe otra automatización.",
"callout": "Antes de programar actualizaciones de aplicaciones, pruebe manualmente cada helper o comando. Una tarea programada no puede responder a confirmaciones ni corregir un procedimiento incompleto."
"callout": "Cada método seleccionado debe probarse manualmente antes de programarlo. Una tarea programada no puede responder a preguntas interactivas."
},
"verify": {
"heading": "Comprobar el resultado",
"p1": "Después de aplicar paquetes del sistema, ProxMenux fuerza una nueva comprobación para actualizar el contador de paquetes pendientes sin esperar al siguiente ciclo periódico.",
"p2": "Para una aplicación, vuelva a la <link>pestaña App</link> y pulse <strong>Check</strong> si el número de versión no se actualiza inmediatamente. Esta comprobación ejecuta de nuevo el método configurado para la versión instalada y consulta la última versión publicada.",
"p3": "Compruebe además que los enlaces web de la aplicación responden correctamente. Que el comando termine sin errores no sustituye una verificación funcional del servicio."
"completion": {
"heading": "Qué ocurre al terminar",
"lead": "La actualización no se considera terminada únicamente porque el comando del terminal haya finalizado.",
"items": [
"La misma ejecución guarda el resultado final y actualiza, según corresponda, los paquetes del SO, las versiones de las apps y el inventario Docker.",
"La caché del LXC se reemplaza con el estado verificado tras la actualización para que insignias y botones no conserven el resultado anterior.",
"Si arranca un LXC parado o restaurado, el evento de ciclo de vida existente vuelve a actualizar ese LXC. El inventario Docker espera a que el daemon esté disponible en lugar de guardar como definitivo un resultado vacío del arranque.",
"Las notificaciones activadas se emiten desde la ejecución finalizada e incluyen fallos parciales y resultados agrupados de imágenes Docker."
]
},
"troubleshoot": {
"heading": "Problemas habituales",
"noButtonHeading": "Aparece Update available, pero no hay botón Apply update",
"noButtonBody": "La detección de versiones funciona, pero no se ha encontrado un método para instalar la actualización. Compruebe si la aplicación se actualiza mediante los paquetes del sistema, un helper compatible o un comando personalizado.",
"aptHeading": "La aplicación se actualiza mediante APT o APK",
"aptBody": "Use <strong>Apply OS update</strong>. No añada un segundo comando para la misma operación, porque la aplicación ya forma parte de la actualización del sistema.",
"noUpdaterHeading": "Se muestra No updater configured",
"noUpdaterBody": "ProxMenux conoce y supervisa la aplicación, pero no sabe cómo actualizarla. Consulte su documentación oficial, pruebe el procedimiento en la consola y, si corresponde, guárdelo mediante <strong>Add custom update command</strong>.",
"helperDetectedHeading": "El helper está detectado, pero no se puede utilizar",
"helperDetectedBody": "El helper puede estar marcado como no actualizable o no formar parte de los métodos reconocidos. Siga las instrucciones oficiales de la aplicación y no asuma que todos los LXC creados mediante Community Scripts admiten una actualización automática.",
"customFailsHeading": "El comando personalizado falla",
"customFailsBody": "Vuelva a ejecutarlo en la consola del LXC. Revise la ruta de trabajo, los permisos, las dependencias, los argumentos no interactivos y el código de salida. No sustituya el comando por una variante distinta hasta comprobar el procedimiento recomendado por el proyecto."
"troubleshooting": {
"heading": "Situaciones habituales",
"colProblem": "Situación",
"colResolution": "Resolución",
"rows": [
{
"problem": "No se ha identificado un método de actualización",
"resolution": "Abre Configurar, añade el procedimiento oficial no interactivo y pruébalo manualmente antes de programarlo."
},
{
"problem": "Aparece la identidad de Proxmox VE Helper-Scripts, pero no existe una acción",
"resolution": "El LXC conserva datos de identificación antiguos, pero no tiene un wrapper /usr/bin/update verificado. Añade un método solo después de confirmar el procedimiento correcto."
},
{
"problem": "Las imágenes Docker aparecen vacías temporalmente después de arrancar o restaurar",
"resolution": "Espera a que Docker esté disponible o pulsa Comprobar ahora. El inventario reintenta el arranque y no considera definitivo un resultado vacío transitorio."
},
{
"problem": "Un objetivo guardado en bloque ya no está disponible",
"resolution": "Edita la configuración, elimina el objetivo obsoleto y selecciona su sustituto actual si existe."
},
{
"problem": "Falla un comando personalizado",
"resolution": "Ejecútalo en el terminal del LXC y revisa la ruta, las dependencias, los parámetros no interactivos y el código de salida."
}
]
},
"figures": {
"osPending": {
"alt": "Sección de paquetes del sistema operativo con contadores de actualizaciones y de seguridad",
"caption": "La sección del sistema operativo mantiene los paquetes separados de las acciones de aplicaciones y Docker."
},
"options": {
"alt": "Opciones de actualización LXC con copia previa y reinicio posterior",
"caption": "Las preferencias de copia y reinicio se aplican a ejecuciones manuales, en bloque y programadas."
}
}
}
@@ -52,7 +52,7 @@
},
"drillIn": {
"heading": "Modal de vista en detalle por guest",
"intro": "La modal abre con una cabecera que muestra el nombre del guest, VMID, insignia de tipo (LXC / VM), insignia de estado (RUNNING / STOPPED / …) y el uptime actual. Bajo la cabecera hay <strong>dos pestañas</strong> — <em>Status</em> y <em>Backups</em> — y una barra de acciones fija al pie de la modal con los cuatro controles de ciclo de vida (Start / Shutdown / Reboot / Force Stop) y, en contenedores LXC en ejecución, un botón Console.",
"intro": "El modal se abre con el nombre, VMID, tipo, estado y tiempo de actividad del sistema. La navegación se adapta al elemento: <strong>Estado</strong>, <strong>App</strong> y <strong>Actualizaciones</strong> para gestionar aplicaciones LXC, <strong>Montajes</strong> cuando existen puntos de montaje, además de <strong>Copias</strong> y <strong>Cortafuegos</strong>. La barra inferior mantiene los controles de ciclo de vida y el terminal LXC disponibles desde cualquier pestaña.",
"statusTitle": "Pestaña 1 — Status",
"statusImageAlt": "Modal de vista en detalle por guest — pestaña Status con tarjetas en vivo de CPU / Memoria / Disco, totales de E/S de disco y red, el logo de distro del SO y el bloque Resources / IP Addresses",
"statusImageCaption": "Pestaña Status — CPU / Memoria / Disco en vivo con barras de progreso arriba, totales de E/S acumulados (lectura/escritura de disco, descarga/subida de red) abajo, después el bloque estático Resources con expansiones de Notes y + Info y la lista de pastillas IP Addresses.",
@@ -77,7 +77,17 @@
],
"ipsTitle": "4. IP Addresses",
"ipsBody": "Lista de pastillas con cada dirección IPv4 / IPv6 que el guest expone actualmente — pastilla verde por dirección. Vacía cuando el guest está parado o cuando el QEMU agent no está instalado en una VM (los LXCs siempre reportan direcciones directamente).",
"mountsTitle": "Pestaña 2 — Mounts (solo LXC)",
"appTitle": "Pestaña 2 — App (solo LXC)",
"appIntro": "Registra las aplicaciones que pertenecen al LXC, guarda enlaces web y, opcionalmente, compara las versiones instalada y disponible. Las sugerencias proceden de la caché de arranque; <strong>Buscar aplicaciones</strong> actualiza expresamente la detección de este LXC después de instalar software nuevo.",
"appLinkLead": "Consulta la",
"appLinkLabel": "página específica de App",
"appLinkTail": "para conocer la detección en caché, el registro asistido por catálogo, los enlaces web de Docker y los detectores de versión.",
"updatesTitle": "Pestaña 3 — Actualizaciones (solo LXC)",
"updatesIntro": "Mantiene como objetivos separados los <strong>paquetes del SO</strong>, las aplicaciones registradas, <strong>Docker Engine</strong> y las imágenes Docker. Cada objetivo puede ejecutarse por separado; una acción en bloque y una programación opcionales seleccionan los métodos exactos que deben ejecutarse juntos.",
"updatesLinkLead": "Consulta la",
"updatesLinkLabel": "página específica de Actualizaciones",
"updatesLinkTail": "para conocer los actualizadores integrados y personalizados, la recreación Docker, la selección en bloque, las opciones de seguridad y la programación.",
"mountsTitle": "Pestaña 4 — Montajes (solo LXC, cuando existen)",
"mountsImageAlt": "Modal de vista en detalle LXC — pestaña Mounts listando cada mount point que está usando el contenedor: volúmenes PVE, host binds, binds desde almacenamiento PVE y montajes ad-hoc NFS/CIFS que el operador montó desde dentro del CT. Cada tarjeta lleva una insignia de tipo, barra de capacidad, bytes used/total, opciones de montaje y un punto de estado por color (verde sano, ámbar readonly/divergente, rojo stale)",
"mountsImageCaption": "Pestaña Mounts — solo se renderiza para contenedores LXC, y solo cuando hay al menos un mount point o un montaje remoto ad-hoc presente. Un CT sin mounts no recibe pestaña.",
"mountsIntro": "La propia UI de Proxmox muestra las entradas de mount-point definidas en la config del contenedor (<code>mpX</code>) pero se queda ahí — cualquier cosa que montes desde dentro del CT después (<code>mount.cifs</code>, NFS vía <code>autofs</code>, …) es invisible. Esta pestaña funde <strong>ambas vistas</strong>: los mounts configurados <strong>y</strong> los mounts en runtime que ProxMenux sonda desde dentro del contenedor, con un estado de salud por mount y una barra de capacidad cuando el backend la puede resolver.",
@@ -96,7 +106,7 @@
],
"mountsCalloutTitle": "Lo que esto te da sobre la UI nativa",
"mountsCalloutBody": "Una vista veraz y consciente de la capacidad de cada sitio donde el contenedor lee o escribe. Shares NFS o CIFS montados desde dentro del CT — invisibles para la UI web de Proxmox — aparecen aquí con el mismo aspecto y la misma sonda de salud que cualquier mount point configurado. Mounts remotos stale y zombie binds salen marcados antes de que muerdan durante un backup.",
"backupsTitle": "Pestaña 3Backups",
"backupsTitle": "Pestaña 5Copias",
"backupsImageAlt": "Modal de vista en detalle por guest — pestaña Backups con la lista de backups disponibles, etiqueta de destino, tamaños y el botón Create Backup",
"backupsImageCaption": "Pestaña Backups — cada backup almacenado en los almacenamientos Proxmox configurados para este guest, ordenados de más nuevo a más viejo. La cabecera de la pestaña lleva la insignia de recuento.",
"backupsIntro": "Lista cada backup almacenado en los almacenamientos Proxmox configurados para este guest, ordenados de más nuevo a más viejo. El título de la pestaña lleva una insignia de recuento para que veas de un vistazo si el guest está backupeado. Por fila:",
@@ -106,23 +116,7 @@
"<strong>Size</strong> — tamaño final en disco del backup."
],
"backupsOutro": "El botón <strong>+ Create Backup</strong> arriba a la derecha arranca una nueva ejecución en el almacenamiento marcado como \"Backup target\" en la config de almacenamiento de Proxmox. El restore vive en la UI web de Proxmox — el Monitor expone la vista \"¿este guest tiene backup reciente?\", no el flujo de recuperación.",
"updatesTitle": "Insignia de updates (solo LXC)",
"updatesImageAlt": "Modal de vista en detalle LXC — insignia violeta pulsable 'updates available' en la cabecera de un contenedor que tiene updates pendientes de apt o apk. Pulsarla expande un panel listando cada paquete actualizable con sus versiones actual y objetivo, más un contador security-only cuando el repo subyacente marca alguno como security",
"updatesImageCaption": "La insignia solo aparece en contenedores LXC en ejecución que tengan al menos un paquete actualizable. Pulsa para abrir la lista de paquetes dentro de la modal — no hay pestaña separada en la barra de navegación.",
"updatesIntro": "ProxMenux sondea cada contenedor en ejecución del host una vez al día y cuenta los paquetes actualizables. Soportado actualmente en esta fase: <strong>Debian / Ubuntu</strong> vía <code>apt list --upgradable</code> y <strong>Alpine</strong> vía <code>apk list -u</code>. Los contenedores corriendo otras distribuciones (CentOS, Arch, …) se omiten por ahora — no muestran insignia en lugar de un cero engañoso.",
"updatesPanelTitle": "Lo que muestra el panel",
"updatesPanelItems": [
"<strong>Recuento total de actualizables</strong> arriba, más un contador <strong>security</strong> separado cuando el repositorio subyacente marca alguno de los paquetes como security (suite \"-security\" de Debian/Ubuntu). Alpine no expone una suite security separada vía metadatos de apk, así que security siempre es 0 en contenedores Alpine.",
"<strong>Lista por paquete</strong> con nombre, versión actual y versión objetivo. Úsala para decidir si lanzar la actualización ahora o esperar a una ventana de mantenimiento."
],
"updatesScopeTitle": "Qué rastrea el sistema vs qué cuenta el script",
"updatesScopeBody": "Este detector de actualizaciones sigue lo que ya hay instalado dentro del contenedor — <strong>no</strong> instala nada nuevo y <strong>no</strong> sabe de aplicaciones desplegadas fuera de apt / apk (un contenedor Docker corriendo dentro del LXC, un Vaultwarden instalado desde fuente, un binario soltado en <code>/usr/local/bin</code>). Es una vista de <em>gestor de paquetes</em>, no una vista de <em>aplicación</em>. Las fases futuras de este trabajo integrarán metadatos de aplicación de community-scripts para que el seguimiento upstream por app (Vaultwarden, Jellyfin, …) sea posible.",
"updatesToggleTitle": "Detección vs notificación — semántica del toggle",
"updatesToggleCalloutTitle": "La detección siempre está activa; el toggle solo controla la notificación",
"updatesToggleCalloutBody": "La detección de actualizaciones de paquetes en contenedores en ejecución corre incondicionalmente — la insignia aparece en esta modal siempre que haya updates pendientes, independientemente de cualquier otro ajuste. El toggle de notificación <code>lxc_updates_available</code> en <strong>Settings → Notifications</strong> solo controla si se entrega a tus canales un mensaje agrupado \"N CT(s) have pending updates\". Esto mantiene la semántica del toggle consistente con los otros streams de update (driver NVIDIA, driver Coral, optimizaciones ProxMenux): apagar las notificaciones nunca oculta la información en el panel.",
"updatesApplyTitle": "Aplicar las actualizaciones",
"updatesApplyBody": "Abre la shell del contenedor desde la barra de acciones del pie, o usa <code>pct exec &lt;vmid&gt; -- apt full-upgrade -y</code> / <code>pct exec &lt;vmid&gt; -- apk upgrade -y</code> desde el host. El panel reescanea en su ciclo de 24h (o tras el siguiente refresco manual) y la insignia se actualiza.",
"firewallTitle": "Pestaña 5 — Firewall",
"firewallTitle": "Pestaña 6 — Cortafuegos",
"firewallIntro": "Lee el log de firewall de Proxmox por guest directamente del host (sin servicio extra, sin polling). La pestaña siempre está presente en la barra de navegación; el panel decide qué renderizar dependiendo de si el firewall está activo para ese guest y si alguna regla está logueando realmente:",
"firewallItems": [
"<strong>Firewall disabled</strong> — un aviso ámbar explica exactamente dónde activarlo en la UI de Proxmox (<em>&lt;Container|VM&gt; → Firewall → Options</em>) y te recuerda que al menos una regla necesita <code>log: info</code> (o superior) antes de que aparezcan paquetes.",
@@ -1,343 +1,183 @@
{
"meta": {
"title": "App — registrácia a sledovanie aplikácií v LXC | ProxMenux",
"description": "Zapíšte aplikácie bežiace v LXC kontajneri cez ProxMenux Monitor a voliteľne sledujte ich verzie."
"title": "Karta LXC App: zisťovanie, odkazy a verzie | ProxMenux",
"description": "Vyhľadávanie a registrácia aplikácií LXC, vytvorenie webových odkazov a voliteľné sledovanie nainštalovanej a dostupnej verzie."
},
"header": {
"title": "App — registrácia a sledovanie aplikácií v LXC",
"description": "Zapíšte aplikácie bežiace v kontajneri, pridajte rýchle webové odkazy a voliteľne sledujte nainštalovanú a najnovšiu verziu."
"title": "Karta LXC App: zisťovanie, odkazy a verzie",
"description": "Priraďte aplikácii v LXC trvalú identitu, webový prístup a voliteľné údaje o verzii bez prepojenia registrácie s aktualizáciou."
},
"intro": {
"p1": "Záložka <strong>App</strong> ukladá informácie o aplikáciách, ktoré bežia v LXC kontajneri. Každá registrovaná aplikácia môže mať zobrazený názov, ikonu, jeden alebo viac webových odkazov a voliteľne aj stav verzie.",
"p2": "Jeden LXC môže obsahovať viac registrovaných aplikácií. Hlavná služba môže zdieľať kontajner s administračným rozhraním, API alebo inou aplikáciou dostupnou na inom porte.",
"p3": "Registrácia aplikáciu nemení ani neaktualizuje. Táto záložka slúži na pomenovanie, zobrazenie a sledovanie. Mechanizmy, ktoré aktualizáciu skutočne <em>spúšťajú</em>, sa nastavujú a používajú v <link>záložke Aktualizácie</link>."
"p1": "Karta <strong>App</strong> zaznamenáva, ktoré aplikácie patria do LXC. Záznam môže obsahovať iba názov a webový odkaz alebo aj detektor nainštalovanej verzie a zdroj dostupnej verzie.",
"p2": "Postup, ktorý mení softvér, sa nastavuje samostatne na <link>karte Aktualizácie</link>. Uloženie aplikácie nikdy nespúšťa inštalátor ani aktualizátor.",
"callout": "Registrácia, sledovanie verzie a aktualizácia sú tri nezávislé možnosti. Každú možno používať bez ostatných dvoch."
},
"whatYouGet": {
"heading": "Čo získate registráciou aplikácie",
"lead": "Podľa nastavených údajov vie ProxMenux zobraziť:",
"overview": {
"heading": "Čo môže obsahovať záznam aplikácie",
"lead": "Jeden uložený záznam môže obsahovať:",
"items": [
"Skratku jedným kliknutím do webového rozhrania aplikácie.",
"Viac odkazov, ak LXC poskytuje viac služieb alebo portov.",
"Aktuálne nainštalovanú verziu.",
"Najnovšiu verziu vydanú projektom.",
"Upozornenie, keď je dostupná novšia verzia.",
"Notifikácie o nových vydaniach, ak sú povolené v nastaveniach Monitoru."
"Zobrazovaný názov a logo prispôsobené téme.",
"Jeden alebo viac webových odkazov vytvorených z adresy LXC, schémy a uloženého portu.",
"Voliteľný detektor verzie nainštalovanej v LXC.",
"Voliteľný zdroj GitHub, HTTP JSON alebo Docker Hub pre najnovšiu dostupnú verziu.",
"Nastavenia upozornení a zahrnutia do počítadla aktualizácií pre každú aplikáciu.",
"Príslušnú sekciu na karte Aktualizácie aj pri vypnutom sledovaní verzie."
]
},
"discovery": {
"heading": "Zisťovanie vo vyrovnávacej pamäti a Hľadať aplikácie",
"lead": "Návrhy aplikácií sú súčasťou vyrovnávacej pamäte modálneho okna každého LXC. Úvodné skenovanie ich pripraví na pozadí, takže karta App môže okamžite zobraziť uložené výsledky.",
"items": [
"Otvorenie karty App <strong>nespustí</strong> nové skenovanie katalógu ani opakované dotazy do LXC.",
"<strong>Hľadať aplikácie</strong> výslovne spustí nové zisťovanie iba pre daný LXC. Používa sa po inštalácii softvéru počas behu ProxMenux.",
"Predchádzajúci zoznam zostáva počas hľadania viditeľný. Nové zhody sa pridajú po dokončení.",
"Ak sa nenájde nová zhoda, výsledok sa zobrazí pri akciách a <strong>Registrovať aplikáciu</strong> zostáva dostupné pre manuálne zadanie.",
"Uloženie, odstránenie alebo obnovenie aplikácie okamžite aktualizuje rovnakú pamäť. Štart alebo obnova LXC aktualizuje iba daný systém cez existujúcu udalosť životného cyklu."
],
"trailing": "Sledovanie verzie je voliteľné. Aplikáciu môžete zaregistrovať aj len preto, aby ste mali poruke jej názov, ikonu a webové odkazy.",
"callout": "Štítok <strong>Dostupná aktualizácia</strong> znamená, že ProxMenux našiel rozdiel medzi nainštalovanou a vydanou verziou. Neznamená to automaticky, že vie aplikáciu aj aktualizovať — to je samostatné nastavenie v záložke Aktualizácie."
"callout": "Návrh nie je registrácia. Zostáva iba na čítanie, kým sa nestlačí <strong>Registrovať</strong> a formulár sa neuloží."
},
"firstOpening": {
"heading": "Prvé otvorenie záložky App",
"p1": "Pri prvom otvorení sa ProxMenux pokúsi rozpoznať aplikácie v kontajneri podľa dostupných informácií: inštalátora použitého pri vytvorení LXC, nájdených služieb a otvorených portov.",
"p2": "Ak nájde zhodu, zobrazí ju ako návrh. Pred uložením návrh vždy skontrolujte — automatická detekcia registráciu zrýchli, ale nevie zaručiť, že každá nájdená služba presne zodpovedá aplikácii, ktorú chcete zapísať."
},
"figures": {
"f01": {
"alt": "Prázdna záložka App so zobrazenými návrhmi nájdených aplikácií",
"caption": "Prázdny stav s jedným alebo viacerými nájdenými návrhmi"
},
"f02": {
"alt": "Vyhľadávanie v katalógu so zhodami podľa zadaného názvu",
"caption": "Vyhľadávanie v katalógu a výber zhody"
},
"f03": {
"alt": "Formulár registrácie aplikácie s názvom, ikonou a dvoma webovými odkazmi",
"caption": "Základný formulár s názvom, ikonou a dvoma webovými odkazmi"
},
"f04": {
"alt": "LXC s aplikáciami Docmost a Redis zaregistrovanými samostatne, každá s vlastným stavom verzie",
"caption": "Dve aplikácie v rovnakom LXC — jedna sleduje verziu zo súboru, druhá cez dpkg, každá má vlastný stav verzie"
},
"f05": {
"alt": "Pokročilé možnosti sledovania s metódou nainštalovanej verzie a zdrojom najnovšej verzie",
"caption": "Pokročilé možnosti s metódou nainštalovanej verzie a zdrojom najnovšej verzie"
},
"f06": {
"alt": "Karta registrovanej aplikácie s nainštalovanou verziou, najnovšou upstream verziou a indikátorom dostupnej aktualizácie",
"caption": "Nastavená karta zobrazuje Nainštalované, Najnovšia upstream, šípku dostupnej aktualizácie pri rozdiele verzií a webový odkaz"
},
"f07": {
"alt": "Minimálna registrovaná aplikácia iba s názvom a jedným webovým odkazom, bez sledovania verzie",
"caption": "Záznam iba s odkazom — len názov a webový odkaz, bez sledovania verzie"
}
},
"registerSuggested": {
"heading": "Registrácia navrhnutej aplikácie",
"registration": {
"heading": "Registrácia aplikácie",
"lead": "Zistený návrh aj manuálny záznam používajú rovnaký editor:",
"steps": [
"Otvorte LXC z karty <strong>VM a LXC</strong>.",
"Vyberte záložku <strong>App</strong>.",
"Nájdite navrhnutú aplikáciu.",
"Kliknite na <strong>Registrovať</strong>.",
"Skontrolujte názov, odkazy a automaticky doplnené údaje.",
"Uložte aplikáciu."
],
"trailing": "Ak návrh nezodpovedá ničomu, čo chcete registrovať, môžete ho skryť. Skryté návrhy sa dajú znovu zobraziť cez <strong>Registrovať inú aplikáciu</strong>."
"Stlačte <strong>Registrovať</strong> pri návrhu alebo <strong>Registrovať aplikáciu</strong> a vyberte položku katalógu alebo zadajte vlastný názov.",
"Skontrolujte názov a logo navrhnuté katalógom.",
"Pridajte potrebné webové odkazy. Zistené otvorené porty sa ponúknu ako skratky, ale neuložia sa automaticky.",
"Pre záznam iba s odkazom nechajte <strong>Sledovať dostupnú verziu</strong> vypnuté alebo ho zapnite a skontrolujte detektor a zdroj verzie.",
"Pri zapnutom sledovaní použite <strong>Otestovať detektor</strong> a potom záznam uložte.",
"Po úpravách stlačte <strong>Hotovo</strong>. Karty App a Aktualizácie použijú aktualizovaný záznam z pamäte."
]
},
"catalog": {
"heading": "Používanie katalógu",
"p1": "Katalóg pomáha nájsť známe aplikácie a predvyplniť časť údajov. Pri písaní do poľa názvu zobrazí najbližšie zhody — výber zhody môže doplniť názov, ikonu, typické porty a pri overenom profile aj možnosti sledovania verzie.",
"p2": "Katalóg je pomocník, nie úplný zoznam každého softvéru, ktorý môže LXC obsahovať. Niektoré položky majú iba základné informácie, iné obsahujú aj pripravený spôsob čítania nainštalovanej verzie.",
"p3": "Ak aplikácia v katalógu nie je, zaregistrujte ju ručne."
"heading": "Registrácia s pomocou katalógu",
"lead": "Katalóg poskytuje počiatočné hodnoty, uložený záznam však zostáva upraviteľný.",
"items": [
"Výsledky môžu predvyplniť kanonický názov, logo a bežné webové porty.",
"Známe detektory používajú skutočné balíky, binárne súbory, súbory, Python distribúcie, OCI značky alebo príkazy, nie univerzálny predpoklad <code>/root/.app</code>.",
"Overené opravy z reálnych inštalácií majú prednosť, keď sa cesta líši od údajov inštalátora.",
"Markery Proxmox VE Helper-Scripts, napríklad <code>/root/.slug</code>, zostávajú jedným signálom kompatibility pre nové inštalácie, nie jediným detektorom.",
"Každú navrhnutú hodnotu možno pred uložením upraviť pre oficiálne aj manuálne inštalácie."
]
},
"manual": {
"heading": "Ručná registrácia aplikácie",
"p1": "Použite <strong>Registrovať inú aplikáciu</strong>, ak LXC ešte nemá žiadne aplikácie. Ak už aspoň jednu má, použite <strong>Pridať ďalšiu aplikáciu</strong>.",
"p2": "Základné nastavenie potrebuje iba názov. Všetko ostatné doplníte podľa toho, čo chcete zobrazovať.",
"nameHeading": "Názov a ikona",
"nameBody": "Zadajte aplikácii názov, podľa ktorého ju ľahko rozpoznáte. Ikona je voliteľná a môže byť zadaná ako URL.",
"linksHeading": "Webové odkazy a porty",
"linksLead": "Každý odkaz môže obsahovať:",
"linksItems": [
"Protokol <code>http</code> alebo <code>https</code>.",
"Port.",
"Popis, napríklad <em>Web UI</em>, <em>Administrácia</em> alebo <em>API</em>.",
"Voliteľnú ikonu pre konkrétny odkaz."
"docker": {
"heading": "Zobrazenie LXC s Dockerom",
"lead": "V LXC, ktorého hlavnou platformou je Docker, sa na úrovni LXC registruje aplikácia <strong>Docker</strong>.",
"items": [
"Kontajnerová služba ako Portainer, Frigate alebo Vaultwarden sa nenavrhuje ako samostatná natívna aplikácia LXC.",
"Bežiace služby Dockeru s publikovanými TCP portmi sa ponúknu v editore Dockeru ako voliteľné webové odkazy.",
"Každý návrh zobrazuje službu, port hostiteľa a port kontajnera. Ukladať treba iba odkazy poskytujúce webové rozhranie.",
"Ak odkaz nemá vlastné logo, použije sa všeobecné logo Dockeru. Logo odkazu má po nastavení prednosť.",
"Po registrácii Dockeru sa Docker Engine a aktualizácie obrazov zobrazia spolu v jeho sekcii Aktualizácie."
],
"linksTrailing": "ProxMenux spojí protokol a port s IP adresou LXC a vytvorí URL. Ak jeden kontajner poskytuje viac súvisiacich služieb, pridajte toľko odkazov, koľko aplikácia potrebuje.",
"linksConfirm": "Pred uložením overte, že port naozaj patrí danej službe a že sa naň viete dostať z prehliadača."
"callout": "Takéto usporiadanie zabraňuje tomu, aby kontajnerová služba vyzerala ako softvér nainštalovaný priamo v LXC, a pritom zachováva rýchle odkazy na jej rozhrania."
},
"multiple": {
"heading": "Registrácia viacerých aplikácií v rovnakom LXC",
"intro": "Po uložení prvej aplikácie kliknite na <strong>Pridať ďalšiu aplikáciu</strong> a postup zopakujte. Každý záznam si nezávisle drží vlastné odkazy, metódu detekcie aj stav verzie.",
"usefulLead": "Hodí sa to, keď:",
"usefulItems": [
"Jeden LXC hostí viac samostatných služieb.",
"Inštalácia obsahuje hlavnú aplikáciu aj doplnkové nástroje.",
"Každá služba má vlastné webové rozhranie alebo vlastný cyklus vydávania."
],
"dontGroup": "Nespájajte do jedného záznamu programy, ktoré sa vydávajú a aktualizujú samostatne. Oddelená registrácia jasne ukáže, ktorá aplikácia má novú verziu, a každej umožní mať vlastnú metódu aktualizácie v záložke Aktualizácie."
"webLinks": {
"heading": "Webové odkazy a logá",
"lead": "Webové odkazy fungujú so sledovaním verzie aj bez neho.",
"items": [
"Každý odkaz ukladá schému, port, voliteľný popis a voliteľnú URL loga.",
"Zobrazená URL používa aktuálnu adresu už zistenú pre LXC; adresa sa neduplikuje v každom zázname.",
"Odkaz bez vlastného loga použije logo aplikácie.",
"Viac odkazov môže reprezentovať administračné rozhranie, API, sekundárne rozhranie alebo iný koncový bod rovnakej aplikácie.",
"Aplikácia uložená iba s odkazmi sa zobrazí aj v Aktualizáciách, kde možno neskôr nastaviť vlastný aktualizátor."
]
},
"tracking": {
"heading": "Sledovanie verzie",
"intro": "Sledovanie verzie nastavíte otvorením pokročilých možností vo formulári. Potrebné sú dve rôzne informácie:",
"ingredients": [
"<strong>Nainštalovaná verzia</strong> — ako prečítať verziu, ktorá práve beží v LXC.",
"<strong>Najnovšia dostupná verzia</strong> — odkiaľ prečítať verziu vydanú projektom."
"heading": "Voliteľné sledovanie verzie",
"lead": "Sledovanie spája detektor nainštalovanej verzie s voliteľným zdrojom dostupnej verzie. Obe strany sa kontrolujú nezávisle.",
"colMethod": "Metóda nainštalovanej verzie",
"colUse": "Použitie",
"detectorRows": [
{ "method": "dpkg / apk", "use": "Číta verziu nainštalovaného balíka z metadát Debianu, Ubuntu alebo Alpine." },
{ "method": "binary", "use": "Spustí absolútnu cestu binárneho súboru alebo názov príkazu s parametrami verzie." },
{ "method": "file + regex", "use": "Číta skutočný súbor a extrahuje verziu pomocou jednej zachytávacej skupiny." },
{ "method": "docker label / docker exec", "use": "Číta OCI značku verzie alebo spustí príkaz verzie v Docker kontajneri." },
{ "method": "python distribution", "use": "Používa importlib.metadata cez vybraný interpreter Pythonu." },
{ "method": "command", "use": "Spustí pokročilý príkaz vo formáte argv bez shellu a extrahuje verziu z výstupu." },
{ "method": "manual", "use": "Uloží manuálne zadanú verziu; po aktualizácii aplikácie ju treba zmeniť." }
],
"trailing": "Ak je nastavená iba nainštalovaná verzia, ProxMenux ju vie zobraziť, ale nevie povedať, či existuje aktualizácia. Aby sa zobrazil štítok <strong>Dostupná aktualizácia</strong>, obe hodnoty musia byť čitateľné a porovnateľné.",
"methodsHeading": "Metódy čítania nainštalovanej verzie",
"methodsLead": "Vyberte metódu podľa toho, ako bola aplikácia nainštalovaná:",
"methodsTable": {
"colMethod": "Metóda",
"colWhen": "Kedy ju použiť",
"rows": [
{
"method": "Žiadna (iba odkaz)",
"when": "Potrebujete len názov a webové odkazy."
},
{
"method": "dpkg balík",
"when": "Aplikácia je nainštalovaná ako Debian alebo Ubuntu balík."
},
{
"method": "apk balík",
"when": "Aplikácia je nainštalovaná ako Alpine balík."
},
{
"method": "Binárka",
"when": "Spustiteľný súbor vracia verziu cez argument ako --version."
},
{
"method": "Súbor + regex",
"when": "Reťazec verzie je zapísaný v súbore."
},
{
"method": "Python distribúcia",
"when": "Aplikácia je nainštalovaná ako Python balík."
},
{
"method": "Príkaz",
"when": "Na získanie verzie treba spustiť konkrétny príkaz."
},
{
"method": "Ručne",
"when": "Používateľ zadá nainštalovanú verziu ručne."
}
]
},
"methodsTrailing": "Použite čo najpriamejšiu a najstabilnejšiu metódu. Ak aplikácia pochádza zo systémového balíka, uprednostnite dotaz na balík pred parsovaním výstupu všeobecného príkazu.",
"commandHeading": "Metóda Príkaz aplikáciu neaktualizuje",
"commandP1": "V tomto formulári slúži <strong>Príkaz</strong> výhradne na prečítanie nainštalovanej verzie. Argumenty sa zadávajú oddelené čiarkou a ProxMenux ich spúšťa priamo, bez shell interpretera.",
"commandP2": "Ak je váš bežný dotaz:",
"commandExample1": "myapp version --short",
"commandP3": "Argumenty vo formulári budú:",
"commandExample2": "myapp, version, --short",
"commandP4": "Nepoužívajte tu operátory ako <code>&&</code>, presmerovania ani pipes. Ak potrebujete celý postup na aktualizáciu aplikácie, nastavuje sa neskôr v záložke Aktualizácie.",
"sourceHeading": "Zdroj najnovšej dostupnej verzie",
"sourceLead": "ProxMenux vie čítať verejný zdroj projektu, napríklad:",
"sourceItems": [
"Releases alebo tagy GitHub repozitára.",
"HTTP endpoint, ktorý vracia verziu v JSON odpovedi."
"sourcesHeading": "Zdroje dostupnej verzie",
"sources": [
"<strong>GitHub repozitár</strong>: najnovšie vydanie alebo značka verejného repozitára <code>vlastník/názov</code>.",
"<strong>HTTP JSON</strong>: verejný koncový bod a cesta ako <code>data.version</code> alebo <code>releases[0].tag_name</code>.",
"<strong>Docker Hub</strong>: verzované značky filtrované regulárnym výrazom. Živý náhľad pred uložením ukáže skutočné zodpovedajúce značky.",
"Pohyblivé značky ako <code>latest</code>, <code>stable</code> alebo <code>lts</code> neobsahujú verziu. Tieto obrazy sledujte podľa digestu v aktualizáciách Docker obrazov."
],
"sourceTrailing": "Vždy používajte oficiálny zdroj aplikácie. Fork alebo endpoint tretej strany môže oznamovať verzie, ktoré nezodpovedajú inštalácii v LXC.",
"regexHeading": "Regulárne výrazy pre verziu",
"regexIntro": "Regulárny výraz, teda <strong>regex</strong>, vytiahne číslo verzie z dlhšieho textu. Väčšina projektov neposkytuje hotový regex — používateľ si ho vytvorí podľa reálneho výstupu alebo skutočného názvu vydania.",
"regexOptional": "Nie vždy je potrebný. Najprv ho nechajte prázdny, ak zdroj vracia čistú hodnotu ako <code>2.14.3</code>. Pridajte ho až vtedy, keď ProxMenux potrebuje oddeliť verziu od ďalších slov, symbolov alebo čísel.",
"regexTwoHeading": "Existujú dve rôzne regex polia",
"regexTwoItems": [
"<strong>Regex nainštalovanej verzie</strong> sa použije na výstup prečítaný vo vnútri LXC.",
"<strong>Regex verzie</strong> alebo <strong>regex tagu</strong> sa použije na názov release / tagu z externého zdroja."
"regexHeading": "Zachytávací výraz",
"regexLead": "Regulárny výraz detektora musí vrátiť verziu vo svojej <strong>prvej zachytávacej skupine</strong>.",
"regexRules": [
"Výraz musí zodpovedať textu vybraného binárneho súboru, súboru, príkazu alebo zdroja značiek; nepoužívajte odhadovanú všeobecnú cestu.",
"Doslovné bodky escapujte ako <code>\\.</code>, aby nezodpovedali ľubovoľnému znaku.",
"Počiatočné <code>v</code> povoľte iba vtedy, keď ho zdroj môže obsahovať.",
"Prípony predbežného vydania alebo revízie distribúcie zahrňte iba vtedy, keď sú dôležité pre porovnanie.",
"Pred uložením použite <strong>Otestovať detektor</strong> a overte, že zobrazená verzia zodpovedá LXC."
],
"regexTwoTrailing": "Obe hodnoty musia byť porovnateľné. Napríklad ak lokálna aplikácia vráti <code>MyApp v2.14.3</code> a GitHub publikuje <code>release-2.14.3</code>, oba výrazy by mali vytiahnuť <code>2.14.3</code>.",
"step1Heading": "1. Zachyťte reálnu ukážku",
"step1P1": "Pred písaním vzoru zachyťte presný text, ktorý bude musieť ProxMenux spracovať.",
"step1P2": "Pri nainštalovanej verzii spustite rovnakú binárku a argumenty, aké sú nastavené vo formulári, priamo z konzoly LXC. Podľa metódy môžete dotazovať aj príslušný balík alebo súbor.",
"step1P3": "Napríklad:",
"step1Cmd": "myapp --version",
"step1P4": "Predpokladajme, že reálny výstup je:",
"step1Output": "MyApp version v2.14.3 (stable)",
"step1P5": "Pri publikovanej verzii skontrolujte presný názov release alebo tagu v oficiálnom repozitári. Ak používate JSON endpoint, pozrite hodnotu, ktorú vracia nastavená cesta.",
"step1P6": "Nevytvárajte vzor podľa vymysleného príkladu — jediná medzera, prefix alebo číslo navyše môže zmeniť výsledok.",
"step2Heading": "2. Určite časť, ktorú chcete ponechať",
"step2Lead": "V príklade vyššie chceme ponechať <code>2.14.3</code> a zahodiť:",
"step2Items": [
"Text <code>MyApp version</code>.",
"Písmeno <code>v</code>.",
"Text <code>(stable)</code>."
],
"step2Recommended": "Odporúčaný výraz:",
"step2Regex": "version[ :=]+v?([0-9]+\\.[0-9]+\\.[0-9]+)",
"step2ReadLead": "Čítané po častiach:",
"step2Breakdown": {
"colPart": "Časť",
"colMeaning": "Význam",
"rows": [
{
"part": "version",
"meaning": "Ukotví hľadanie na tomto slove, aby sa nezhodovalo nesúvisiace číslo."
},
{
"part": "[ :=]+",
"meaning": "Povolí jednu alebo viac medzier, dvojbodiek alebo znamienok rovnosti."
},
{
"part": "v?",
"meaning": "Písmeno v sa môže objaviť raz alebo vôbec."
},
{
"part": "( and )",
"meaning": "Označuje časť, ktorú má ProxMenux ponechať."
},
{
"part": "[0-9]+",
"meaning": "Zodpovedá jednej alebo viacerým čísliciam."
},
{
"part": "\\.",
"meaning": "Zodpovedá skutočnej bodke medzi číslami."
}
]
},
"step2DotNote": "Bodka sa píše ako <code>\\.</code>, pretože samotná bodka v regexe znamená „ľubovoľný znak“.",
"step3Heading": "3. Vyberte vzor podľa formátu",
"step3Lead": "Tieto vzory pokrývajú najčastejšie prípady:",
"step3Examples": {
"colText": "Ukážkový text",
"colRegex": "Odporúčaný regex",
"colResult": "Výsledok",
"rows": [
{
"text": "v2.14.3",
"regex": "v?([0-9]+\\.[0-9]+\\.[0-9]+)",
"result": "2.14.3"
},
{
"text": "Version: 2.14",
"regex": "Version[ :=]+v?([0-9]+(?:\\.[0-9]+){1,3})",
"result": "2.14"
},
{
"text": "release-2.14.3.1",
"regex": "release-v?([0-9]+(?:\\.[0-9]+){1,3})",
"result": "2.14.3.1"
},
{
"text": "build 2026.08.10",
"regex": "build[ :=]+([0-9]{4}\\.[0-9]{1,2}\\.[0-9]{1,2})",
"result": "2026.08.10"
},
{
"text": "{\"version\":\"2.14.3\"}",
"regex": "\"version\"\\s*:\\s*\"v?([0-9]+(?:\\.[0-9]+){1,3})\"",
"result": "2.14.3"
}
]
},
"step3Note1": "<code>(?: ... )</code> zoskupí časť vzoru bez vytvorenia ďalšej výstupnej hodnoty. Hodí sa na prijatie verzií s dvoma, tromi alebo štyrmi blokmi bez komplikovania výsledku.",
"step3Note2": "Regex zadajte presne ako v tabuľke: bez úvodzoviek okolo a bez oddeľovačov <code>/.../</code>, ktoré používajú niektoré online nástroje.",
"step4Heading": "4. Uprednostnite jednu zachytávaciu skupinu",
"step4Intro": "ProxMenux používa zachytávacie skupiny na rozhodnutie, ktorú hodnotu vráti:",
"step4Items": [
"Bez zachytávacích skupín ponechá celú zhodu.",
"S jednou skupinou ponechá obsah tejto skupiny.",
"S viacerými skupinami ich spojí bodkami."
],
"step4Trailing": "Pre predvídateľný výsledok obaľte celú verziu do jednej skupiny a pomocné skupiny zapisujte ako <code>(?: ... )</code>.",
"step4RecLabel": "Odporúčané:",
"step4RecRegex": "v?([0-9]+(?:\\.[0-9]+){1,3})",
"step4LessLabel": "Menej jasné pre začiatočníkov:",
"step4LessRegex": "v?([0-9]+)\\.([0-9]+)\\.([0-9]+)",
"step4Note": "Oba výrazy môžu vytvoriť <code>2.14.3</code>, ale prvý sa ľahšie udržiava, ak sa formát zmení.",
"step5Heading": "5. Vyhnite sa príliš širokým zhodám",
"step5Lead": "Takýto vzor býva zvyčajne príliš voľný:",
"step5Regex": "([0-9.]+)",
"step5P1": "Môže zachytiť rok, port, verziu závislosti alebo prvé číslo, ktoré sa vo výstupe objaví. Ak text obsahuje viac čísel, ukotvite ho blízkym slovom ako <code>version</code>, <code>release</code> alebo <code>build</code>.",
"step5P2": "Overte aj to, že upstream zdroj nemieša stabilné vydania s beta, nightly alebo vývojovými buildmi. Regex musí vybrať rovnaký kanál, aký je nainštalovaný v LXC.",
"step6Heading": "6. Uložte a overte výsledok",
"step6Lead": "Po uložení aplikácie kliknite na <strong>Skontrolovať</strong> a pozrite si dve hodnoty, ktoré ProxMenux zobrazí:",
"step6Output": "Nainštalované: 2.14.3\nNajnovšia: 2.15.0",
"step6CorrectLead": "Regex je správny, keď:",
"step6CorrectItems": [
"Obe polia obsahujú iba očakávanú verziu.",
"Názov aplikácie ani ďalší text nie sú zachytené.",
"Verzia nie je zamenená s iným číslom.",
"Lokálna aj publikovaná hodnota používajú rovnaký formát."
],
"step6ErrorNote": "Ak zhoda skončí chybou, znovu zachyťte reálny výstup a porovnajte ho znak po znaku. Pozor najmä na veľké písmená, medzery, pomlčky, písmeno <code>v</code> a počet blokov verzie.",
"step6Callout": "Ak neviete vytvoriť spoľahlivý vzor, radšej dočasne vypnite upstream sledovanie a nechajte aplikáciu ako záznam iba s odkazom. Nesprávny regex môže vytvárať falošné upozornenia alebo skryť reálnu aktualizáciu."
"regexExampleLead": "Bežné zachytenie sémantickej verzie:",
"regexExample": "v?(\\d+\\.\\d+\\.\\d+)",
"regexCallout": "Úspešná zhoda regulárneho výrazu nedokazuje správnosť cesty. Balík, binárny súbor alebo súbor musí existovať aj v skutočnej registrovanej inštalácii."
},
"state": {
"heading": "Čítanie stavu aplikácie",
"lead": "Registrovaná aplikácia môže zobraziť niektorý z týchto stavov:",
"updater": {
"heading": "Sledovanie verzie a aktualizácia sú nezávislé",
"lead": "<link>Karta Aktualizácie</link> vytvorí sekciu aplikácie ihneď po uložení ľubovoľného záznamu.",
"items": [
"<strong>Aktuálne</strong> — verzie sa zhodujú.",
"<strong>Dostupná aktualizácia</strong> — zdroj publikuje novšiu verziu.",
"<strong>Kontroluje sa</strong> — kontrola práve prebieha.",
"<strong>Sledovanie verzie čaká</strong> — ešte neprebehla žiadna kontrola.",
"<strong>Chyba</strong> — jednu z verzií sa nepodarilo prečítať alebo spracovať."
],
"trailing": "Po úprave nastavení použite <strong>Skontrolovať</strong> na opakovanie dotazu. Ak sa zobrazí chyba, najprv skontrolujte metódu nainštalovanej verzie, upstream zdroj a regex vzory."
"Záznam iba s odkazom uvádza, že sledovanie verzie nie je nastavené, ale stále môže dostať vlastný aktualizačný príkaz.",
"Aplikácia so sledovaním bez spustiteľnej metódy zobrazí neutrálnu požiadavku na vlastný príkaz.",
"Aplikácia s overeným wrapperom Proxmox VE Helper-Scripts môže použiť integrovaný aktualizátor aj vtedy, keď registrácia začala iba webovým odkazom.",
"Pridanie alebo úprava aktualizátora nemení detektor ani zdroj dostupnej verzie na karte App."
]
},
"manage": {
"heading": "Správa existujúcich záznamov",
"lead": "V režime správy môžete:",
"states": {
"heading": "Stavy verzie na karte aplikácie",
"colState": "Stav",
"colDisplay": "Zobrazenie",
"colMeaning": "Význam",
"rows": [
{ "state": "Dostupná aktualizácia", "display": "Dostupná verzia fialovo s ikonou šípky nahor", "meaning": "Nainštalovaná a dostupná verzia sa líšia." },
{ "state": "Aktuálne", "display": "Nainštalovaná a dostupná verzia bez fialového upozornenia", "meaning": "Posledná kontrola nenašla novšiu verziu." },
{ "state": "Sledovanie čaká", "display": "Stav kontroly alebo čakania", "meaning": "Záznam je nastavený, ale ešte nedokončil obe kontroly." },
{ "state": "Sledovanie vypnuté", "display": "Iba webové odkazy bez porovnania verzií", "meaning": "Záznam zostáva platný a môže mať aktualizátor." },
{ "state": "Chyba kontroly", "display": "Jantárové vysvetlenie na karte", "meaning": "Predchádzajúci uložený stav zostane viditeľný a zobrazí sa chyba detektora alebo zdroja." }
]
},
"management": {
"heading": "Správa uložených a navrhnutých aplikácií",
"lead": "Akcie v spodnej časti karty majú odlišné úlohy:",
"items": [
"Znovu skontrolovať aplikáciu.",
"Upraviť jej názov, odkazy alebo sledovanie verzie.",
"Odstrániť záznam, ktorý už nepotrebujete.",
"Pridať ďalšiu aplikáciu do rovnakého LXC."
],
"trailing": "Odstránenie záznamu aplikáciu neodinštaluje ani nezastaví. Odstráni iba informácie, ktoré ProxMenux používa na jej zobrazenie a sledovanie verzie."
"<strong>Hľadať aplikácie</strong> obnoví zisťovanie iba pre tento LXC.",
"<strong>Registrovať ďalšiu aplikáciu</strong> otvorí katalóg a manuálny editor bez nového skenovania LXC.",
"<strong>Upraviť</strong> zobrazí na kartách akcie Odstrániť, Skontrolovať, upozornenia a Upraviť polia.",
"<strong>Skryť</strong> odstráni nechcený návrh. Skryté detekcie možno obnoviť v prehliadači registrácie.",
"<strong>Skontrolovať</strong> obnoví údaje verzie uloženej aplikácie; nehľadá nové aplikácie."
]
},
"options": {
"heading": "",
"lead": "",
"items": [
"",
""
],
"trailing": ""
"troubleshooting": {
"heading": "Bežné situácie",
"colProblem": "Situácia",
"colResolution": "Riešenie",
"rows": [
{ "problem": "Softvér bol nainštalovaný po štarte ProxMenux", "resolution": "Stlačte Hľadať aplikácie. Výslovné skenovanie aktualizuje návrhy v pamäti daného LXC." },
{ "problem": "Aplikácia nebola zistená", "resolution": "Zaregistrujte ju manuálne. Stačí názov a jeden webový odkaz; sledovanie možno pridať neskôr." },
{ "problem": "Navrhnutý detektor vracia nesprávnu verziu", "resolution": "Otvorte Upraviť polia, vyberte skutočný balík, binárny súbor alebo súbor a pred uložením otestujte detektor." },
{ "problem": "Služba Dockeru sa neponúka ako aplikácia LXC", "resolution": "Zaregistrujte Docker a pridajte publikované rozhranie služby ako webový odkaz Dockeru. Aktualizácie obrazov zostanú v sekcii Docker." },
{ "problem": "Uložená aplikácia nemá tlačidlo aktualizácie", "resolution": "Otvorte Aktualizácie a nastavte jej metódu. Samotné sledovanie verzie neurčuje, ako sa aktualizácia nainštaluje." }
]
},
"notDetected": {
"heading": "Ak aplikácia nebola nájdená",
"intro": "Automatická detekcia nie je nutná na používanie tejto funkcie. Ak sa nezobrazí žiadny návrh:",
"steps": [
"Zaregistrujte aplikáciu ručne.",
"Pridajte jej známe odkazy a porty.",
"Nechajte ju ako <strong>Žiadna (iba odkaz)</strong>, ak potrebujete iba skratku.",
"Sledovanie verzie nastavte až vtedy, keď máte pre obe hodnoty spoľahlivý zdroj.",
"Metódu aktualizácie nastavte neskôr cez <link>Aktualizácie</link>, ak chcete, aby ju ProxMenux spúšťal."
],
"trailing": "Nevymýšľajte názov balíka, cestu ani regex len preto, aby bol formulár vyplnený. Jednoduchý a správny záznam je lepší než automatické sledovanie postavené na neoverených údajoch."
"figures": {
"catalog": {
"alt": "Katalóg registrácie s výsledkami, logami, portmi a poľami detektora",
"caption": "Metadáta katalógu urýchľujú registráciu, pričom všetky navrhnuté hodnoty zostávajú upraviteľné."
},
"webLinks": {
"alt": "Uložená karta aplikácie LXC s webovým odkazom",
"caption": "Záznam iba s odkazom je platný: sledovanie môže zostať vypnuté a aktualizátor sa pridáva nezávisle."
},
"tracking": {
"alt": "Voliteľné polia detektora nainštalovanej verzie a zdroja dostupnej verzie",
"caption": "Detekcia nainštalovanej verzie a zdroj dostupnej verzie sa nastavujú a testujú samostatne."
},
"card": {
"alt": "Uložená karta s nainštalovanou a dostupnou verziou a webovým odkazom",
"caption": "Karta spája identitu, údaje o verzii a webový prístup bez spúšťania aktualizácií z tejto karty."
}
}
}
@@ -1,231 +1,194 @@
{
"meta": {
"title": "Aktualizácie — aktualizácia systému a aplikácií v LXC | ProxMenux",
"description": "Mechanizmy, ktoré vie ProxMenux použiť na aktualizáciu operačného systému a aplikácií registrovaných v LXC kontajneri."
"title": "Aktualizácie LXC: OS, aplikácie a Docker | ProxMenux",
"description": "Nastavenie a spúšťanie aktualizácií operačného systému, aplikácií, Docker Engine a Docker obrazov v LXC kontajneri."
},
"header": {
"title": "Aktualizácie — aktualizácia systému a aplikácií v LXC",
"description": "Miesto, kde ProxMenux rozhoduje, ako aktualizovať kontajner: systémové balíky, pomocník Community Scripts alebo vlastný príkaz."
"title": "Aktualizácie LXC: OS, aplikácie a Docker",
"description": "Skontrolujte každý cieľ samostatne alebo spojte presný výber do riadenej hromadnej aktualizácie."
},
"intro": {
"p1": "Záložka <strong>Aktualizácie</strong> zhromažďuje mechanizmy, ktoré vie ProxMenux spustiť na aktualizáciu operačného systému a aplikácií registrovaných vo vnútri LXC kontajnera.",
"p2": "<link>Záložka App</link> určuje, ktoré aplikácie existujú, a voliteľne porovnáva ich verzie. <strong>Aktualizácie</strong> riešia samotnú akciu: rozhodnú, ktorý mechanizmus je dostupný, zobrazia príslušné tlačidlo a spustia aktualizáciu v kontajneri.",
"callout": "<strong>Základná myšlienka:</strong> zistenie novej verzie a znalosť spôsobu jej inštalácie sú dve rozdielne veci. Aplikácia môže v záložke App ukazovať <strong>Dostupná aktualizácia</strong>, ale stále nemusí mať funkčné tlačidlo na aktualizáciu, kým nie je nastavená platná metóda."
"p1": "Karta <strong>Aktualizácie</strong> oddeľuje zisťovanie verzie od akcie, ktorá aktualizáciu nainštaluje. Registrácia a voliteľné sledovanie verzie sú na <link>karte Aplikácia</link>; spustiteľné metódy aktualizácie sa spravujú tu.",
"p2": "Uložená aplikácia sa zobrazí v Aktualizáciách aj vtedy, keď obsahuje iba webový odkaz. Sledovanie verzie je voliteľné a aktualizátor možno nastaviť nezávisle.",
"callout": "Akcia sa neurčuje iba podľa názvu aplikácie. ProxMenux spustí integrovanú metódu až po jej overení alebo výslovne uložený vlastný príkaz."
},
"overview": {
"heading": "Obsah karty",
"lead": "Každý dostupný cieľ má vlastnú sekciu a akciu:",
"items": [
"<strong>Balíky OS</strong> pre kontajnery Debian, Ubuntu a Alpine.",
"Samostatnú sekciu pre každú <strong>registrovanú aplikáciu</strong> vrátane záznamov iba s odkazom.",
"Sekciu <strong>Docker</strong> po registrácii Dockeru, v ktorej sú spolu Docker Engine a označené obrazy.",
"Nastaviteľnú <strong>Hromadnú aktualizáciu</strong>, za ktorou nasledujú možnosti zálohy, reštartu a plánovania."
]
},
"mechanisms": {
"heading": "Dostupné mechanizmy aktualizácie",
"intro": "Podľa toho, ako bola aplikácia nainštalovaná a odkiaľ pochádzajú jej aktualizácie, vyberá ProxMenux z troch mechanizmov.",
"osHeading": "Balíky operačného systému",
"osP1": "V Debian alebo Ubuntu kontajneroch ProxMenux kontroluje a aktualizuje balíky cez APT. V Alpine používa APK.",
"osP2": "Registrované aplikácie, ktorých metóda inštalácie je <code>dpkg</code> alebo <code>apk</code>, sú súčasťou tejto kontroly. V sekcii aplikácie nepotrebujú druhý príkaz — aktualizujú sa spolu s akciou <strong>Použiť aktualizáciu OS</strong>.",
"osP3": "Sekcia zobrazuje počet čakajúcich balíkov, počet bezpečnostných aktualizácií, rodinu OS a čas poslednej kontroly.",
"helperHeading": "Aktualizátor Proxmox VE Helper-Scripts",
"helperP1": "Ak bol LXC vytvorený pomocou helpera z projektu <linkHelperHome>Proxmox VE Helper-Scripts</linkHelperHome>, ProxMenux rozpozná jeho aktualizátor. Príslušná aplikácia musí byť zaregistrovaná v záložke App, aby ju Monitor vedel prepojiť so službou zobrazenou používateľovi.",
"helperP2": "<strong>Samotnú logiku aktualizácie spravuje projekt Proxmox VE Helper-Scripts</strong>, nie ProxMenux. Každý helper má vlastnú funkciu <code>update_script</code>; ProxMenux ju stiahne a spustí vo vnútri kontajnera v tichom režime (<code>PHS_SILENT=1</code>), bez otázok. Na strane ProxMenuxu netreba helper kopírovať ani písať vlastný príkaz.",
"helperP3": "Úplná dokumentácia k mechanizmu aktualizácie je na stránke projektu — <linkHelperDocs>community-scripts.org / update-apps</linkHelperDocs>. Každý helper má zároveň vlastnú položku na <linkHelperHome>stránke projektu</linkHelperHome> s opisom toho, čo skript robí, aké má predvolené nastavenia a odkiaľ pochádza aktualizačná logika — túto stránku používajte ako referenciu pre to, čo aktualizátor zmení vo vnútri LXC.",
"helperP4": "Nie každý helper podporuje aktualizáciu na mieste. Ak katalóg označí aplikáciu ako neaktualizovateľnú, záložka tento stav zobrazí a túto metódu neponúkne ako dostupnú.",
"customHeading": "Vlastný príkaz",
"customP1": "Registrovaná aplikácia môže mať uložený vlastný aktualizačný príkaz. ProxMenux ho spustí vo vnútri LXC, keď používateľ klikne na <strong>Použiť aktualizáciu</strong> alebo keď ho zahrnie plánovaná úloha.",
"customP2": "Táto metóda je určená pre aplikácie, ktorých inštalátor neposkytuje rozpoznaného helpera a ktoré sa neaktualizujú cez APT alebo APK."
"heading": "Výber metódy aktualizácie",
"lead": "Integrovaná cesta Proxmox VE Helper-Scripts používa oficiálny mechanizmus <helper>update-apps</helper>. Ostatné inštalácie používajú príslušnú metódu balíkov, Dockeru alebo vlastného príkazu.",
"colSource": "Zdroj",
"colAction": "Zobrazená akcia",
"colNotes": "Čo sa spustí",
"rows": [
{
"source": "Balíky APT alebo APK",
"action": "Použiť aktualizácie OS",
"notes": "Aktualizuje balíky kontajnera. Registrované aplikácie nainštalované ako dpkg alebo apk sú zahrnuté v rovnakom behu."
},
{
"source": "Proxmox VE Helper-Scripts",
"action": "Použiť aktualizáciu",
"notes": "Používa overený wrapper /usr/bin/update. Starý marker bez platného wrappera sa identifikuje, ale automaticky sa nespustí."
},
{
"source": "Vlastný príkaz",
"action": "Spustiť aktualizátor",
"notes": "Spustí uložený príkaz v LXC a nahradí integrovaný aktualizátor danej aplikácie."
},
{
"source": "Docker Engine",
"action": "Aktualizovať Docker Engine",
"notes": "Aktualizuje iba nainštalované balíky Dockeru a potrebné závislosti. Ostatné balíky ani kontajnery nemení."
},
{
"source": "Docker obraz",
"action": "Aktualizovať obraz",
"notes": "Stiahne vybraný obraz a znova vytvorí jeho skupinu služieb Compose alebo chránený samostatný kontajner."
}
],
"callout": "Vlastný príkaz vždy <strong>nahrádza</strong> integrovaný aktualizátor Proxmox VE Helper-Scripts pre danú aplikáciu. Obe metódy sa nespúšťajú za sebou."
},
"decision": {
"heading": "Ako ProxMenux vyberá zobrazenú akciu",
"table": {
"colSituation": "Situácia",
"colAction": "Akcia",
"rows": [
{ "situation": "Čakajú balíky APT alebo APK", "action": "Použiť aktualizáciu OS" },
{ "situation": "Aplikácia používa dpkg alebo apk balík", "action": "Použiť aktualizáciu OS — samostatný príkaz aplikácie nie je potrebný" },
{ "situation": "Existuje kompatibilný helper a aplikácia je registrovaná", "action": "Použiť aktualizáciu cez Community Scripts" },
{ "situation": "Registrovaná aplikácia má vlastný príkaz", "action": "Použiť aktualizáciu týmto príkazom" },
{ "situation": "Existuje nová verzia, ale nie je nastavený helper ani príkaz", "action": "Zobrazí Nie je nastavený aktualizátor a ponúkne pridanie príkazu" },
{ "situation": "Dostupné sú systémové aj aplikačné aktualizácie", "action": "Môže sa zobraziť spoločná akcia Použiť aktualizácie OS + aplikácií" }
]
},
"trailing": "Aplikácia registrovaná iba ako odkaz sa nikdy nezobrazí ako aktualizovateľná — ProxMenux nemá dosť informácií na prepojenie s metódou aktualizácie."
"docker": {
"heading": "Docker Engine a Docker obrazy",
"lead": "Po registrácii Dockeru na karte Aplikácia sa engine a inventár obrazov zobrazia v rovnakej sekcii <strong>Docker</strong>.",
"items": [
"Sledovanie verzie Docker Engine je oddelené od počítadla balíkov OS a má vlastné tlačidlo aktualizácie.",
"Označené lokálne obrazy sa porovnávajú s registrom pomocou nemenného digestu. <strong>Skontrolovať teraz</strong> obnoví inventár bez sťahovania obrazov alebo reštartu kontajnerov.",
"Služby Compose sa aktualizujú z deklarovaného projektu. Obrazy rovnakej skupiny sa spracujú spolu, aby sa projekt nevytváral opakovane.",
"Samostatný kontajner sa znova vytvorí z aktuálnej konfigurácie. Chránený postup uchová údaje na návrat a pri chybe obnoví pôvodný kontajner.",
"Každý obraz možno vybrať samostatne pre manuálne, hromadné aj plánované aktualizácie, okrem deklarovaných závislostí Compose, ktoré musia nasledovať hlavnú službu."
],
"callout": "Kontajnery spustené v Dockeri sa nezobrazujú ako samostatné aplikácie LXC. Ich publikované webové porty možno uložiť ako odkazy Dockeru; aktualizácie obrazov zostávajú v sekcii Docker."
},
"figures": {
"f01": {
"alt": "Karta systémových balíkov s počtom čakajúcich aktualizácií, počtom bezpečnostných aktualizácií a tlačidlom Použiť aktualizáciu OS",
"caption": "Čakajúce systémové balíky: celkový počet, počet bezpečnostných aktualizácií a tlačidlo Použiť aktualizáciu OS"
},
"f02": {
"alt": "Rovnaká karta systémových balíkov po aktualizácii — žiadne čakajúce balíky a štítok OS je aktuálny",
"caption": "Po použití: „Žiadne čakajúce aktualizácie OS“ a štítok OS je aktuálny"
},
"f03": {
"alt": "Karta registrovanej aplikácie so stavom Nie je dostupná metóda aktualizácie a tlačidlom Pridať vlastný aktualizačný príkaz",
"caption": "„Nie je dostupná metóda aktualizácie“ — ProxMenux aplikáciu sleduje, ale ešte nemá nastavené nič, čo by ju aktualizovalo"
},
"f04": {
"alt": "Editor vlastného aktualizačného príkazu s ukážkovým placeholderom v textovom poli",
"caption": "Editor vlastného príkazu s ukážkovým placeholderom, tlačidlami Zrušiť a Uložiť"
},
"f05": {
"alt": "Terminálový panel s názvom Použiť aktualizácie — CT 103, ktorý zobrazuje živý apt výstup pri rozbaľovaní balíkov",
"caption": "Terminálový panel zobrazuje živý výstup aktualizácie, kým apt rozbaľuje balíky vo vnútri CT"
},
"f06": {
"alt": "Karta možností so zapnutým snapshotom pred použitím, záložným úložiskom nastaveným na pbs a zapnutým reštartom po použití",
"caption": "Karta možností so súčasne zapnutým vzdump snapshotom, záložným úložiskom a reštartom po použití"
},
"f07": {
"alt": "Sekcia plánovaných aktualizácií je zapnutá — frekvencia denne o 3:00, cron výraz 0 3 * * * a cieľ nastavený na OS + aplikácia",
"caption": "Plánované aktualizácie sú zapnuté — predvoľba frekvencie, zodpovedajúci cron výraz a vybraný rozsah aktualizácie"
}
"actions": {
"heading": "Samostatné akcie a farby stavu",
"lead": "Každá sekcia zostáva samostatne ovládateľná aj po nastavení hromadnej aktualizácie.",
"items": [
"Tlačidlo <strong>Upraviť</strong> je vždy dostupné. Integrované metódy zobrazia aktuálny príkaz, ktorý možno skontrolovať, nahradiť alebo vymazať.",
"Ak je sledovanie verzie vypnuté, ale aktualizátor existuje, zobrazí sa neutrálna akcia <strong>Spustiť aktualizátor</strong>. ProxMenux netvrdí, že je dostupná aktualizácia.",
"Ak metóda neexistuje, <strong>Nastaviť</strong> otvorí editor vlastného príkazu.",
"Akcia <strong>Aktualizovať obraz</strong> ovplyvní iba vybranú jednotku Dockeru, nie Docker Engine ani nesúvisiace obrazy."
],
"statusColState": "Známy stav",
"statusColAppearance": "Vzhľad",
"statusColMeaning": "Význam",
"statusRows": [
{
"state": "Overená dostupná aktualizácia",
"appearance": "Fialový text, ikona šípky nahor a fialová akcia",
"meaning": "Nainštalovaná a dostupná verzia alebo digesty obrazov sa líšia."
},
{
"state": "Overene aktuálne",
"appearance": "Zelená kontrola a zelená akcia Aktualizované",
"meaning": "Posledná dokončená kontrola potvrdila, že cieľ je aktuálny."
},
{
"state": "Neznáma verzia",
"appearance": "Neutrálny text a neutrálna akcia",
"meaning": "Aktualizátor sa dá spustiť, ale bez údajov o verzii nemožno určiť stav."
}
]
},
"custom": {
"heading": "Pridanie vlastného aktualizačného príkazu",
"p1": "Keď má aplikácia sledovanie verzie, ale nemá metódu aktualizácie, záložka zobrazí <strong>Nie je nastavený aktualizátor</strong>. Kliknutím na <strong>Pridať vlastný aktualizačný príkaz</strong> otvoríte editor.",
"p2": "Príkaz musí predstavovať reálny a úplný postup, ktorý danú aplikáciu aktualizuje. Nevkladajte sem iba príkaz, ktorý číta jej verziu."
},
"figureOut": {
"heading": "Ako zistiť správny príkaz",
"intro": "Neexistuje univerzálny aktualizačný príkaz. Pred uložením najprv zistite, ako bol softvér nainštalovaný a aký postup aktualizácie odporúča jeho projekt.",
"step1Heading": "1. Skontrolujte, či to už nerieši systém",
"step1P1": "Ak bola aplikácia nainštalovaná z repozitárov Debianu, Ubuntu alebo Alpine, zvyčajne sa aktualizuje spolu so systémovými balíkmi. Vtedy nepridávajte vlastný príkaz — použite <strong>Použiť aktualizáciu OS</strong>.",
"step1P2": "Pôvod balíka môžete overiť z konzoly LXC nástrojmi danej distribúcie. Napríklad:",
"step1Cmd1": "dpkg -l | grep -i name",
"step1P3": "alebo:",
"step1Cmd2": "apk info | grep -i name",
"step1P4": "Nahraďte <code>name</code> balíkom, ktorý skúmate. Zhoda ešte automaticky nepotvrdzuje, že ide o hlavný balík — porovnajte názov s dokumentáciou aplikácie.",
"step2Heading": "2. Pozrite oficiálnu dokumentáciu",
"step2P1": "V oficiálnych dokumentoch alebo repozitári hľadajte sekcie ako <strong>Upgrade</strong>, <strong>Update</strong>, <strong>Maintenance</strong> alebo <strong>Manual installation</strong>. Postup musí zodpovedať spôsobu, akým je aplikácia nainštalovaná v danom LXC.",
"step2P2": "Nepoužívajte návody určené pre inú distribúciu, iný typ inštalácie alebo inú verziu.",
"step3Heading": "3. Skontrolujte existujúcu inštaláciu",
"step3Lead": "Ak si nepamätáte, ako bola aplikácia nainštalovaná, pozrite:",
"step3Items": [
"Históriu alebo poznámky pôvodného inštalátora.",
"Cestu, kde sú uložené jej súbory.",
"Definíciu služby, ktorá ju spúšťa.",
"Údržbové skripty dodané aplikáciou.",
"Dokumentáciu uloženú v jej inštalačnom priečinku."
],
"step3P1": "Pri systemd službe môže toto pomôcť nájsť binárku a pracovný priečinok:",
"step3Cmd": "systemctl show service-name -p ExecStart -p WorkingDirectory",
"step3P2": "Pomôže to identifikovať inštaláciu, ale automaticky to neznamená, že riadok <code>ExecStart</code> je aktualizačný príkaz.",
"step4Heading": "4. Otestujte postup v konzole LXC",
"step4Lead": "Otvorte konzolu kontajnera a spustite postup ručne ešte pred uložením do ProxMenuxu. Overte, že:",
"step4Items": [
"Skončí bez otázok alebo interaktívnych menu.",
"Vráti správny exit code.",
"Reštartuje alebo znovu načíta iba služby, ktoré to potrebujú.",
"Aplikácia je po ňom znovu dostupná.",
"Nainštalovaná verzia sa zmení podľa očakávania."
],
"step4Note": "Ak je to možné, pred testom vytvorte zálohu kontajnera.",
"step5Heading": "5. Uložte iba príkaz spúšťaný vo vnútri kontajnera",
"step5P1": "Zadajte iba to, čo sa má vykonať vo vnútri LXC. Nevkladajte:",
"step5Cmd1": "pct exec <vmid> --",
"step5P2": "ProxMenux už vstup do kontajnera rieši sám. Príkaz sa spúšťa ako <code>root</code> cez <code>sh -c</code>, takže podporuje reťazenie operácií aj zmenu priečinka.",
"step5P3": "Ak musí aktualizátor bežať z konkrétnej cesty, uveďte ju priamo:",
"step5Cmd2": "cd /opt/my-app && ./update.sh",
"step5P4": "Ak projekt dodáva aktualizátor na inej ceste, použite cestu a argumenty uvedené v oficiálnej dokumentácii."
},
"requirements": {
"heading": "Požiadavky na spoľahlivý príkaz",
"lead": "Pred spustením z Monitoru overte, že príkaz:",
"heading": "Vlastné aktualizačné príkazy",
"lead": "Vlastný príkaz pokrýva inštalácie bez overeného integrovaného aktualizátora a môže nahradiť bežný postup.",
"items": [
"Beží bez zásahu používateľa.",
"Používa absolútne cesty alebo sa najprv prepne do správneho priečinka.",
"Zastaví, migruje a reštartuje služby tak, ako vyžadujú oficiálne pokyny.",
"Skončí chybou, ak aktualizácia zlyhá.",
"Neobsahuje viditeľné heslá, tokeny ani iné tajné údaje.",
"Nesťahuje ani nespúšťa skripty z nedôveryhodných zdrojov."
"Ak je pole prázdne, otvorte <strong>Nastaviť</strong>; ak metóda existuje, otvorte <strong>Upraviť</strong>.",
"Pri integrovanej aplikácii alebo Docker Engine editor zobrazí používaný príkaz. Uložením iného obsahu sa vytvorí výslovná náhrada pre daný záznam.",
"Úplný postup najprv otestujte v termináli LXC. Musí byť neinteraktívny, používať správny adresár a pri chybe vrátiť nenulový kód.",
"Nepridávajte <code>pct exec</code>; ProxMenux už vstupuje do kontajnera a príkaz spúšťa ako root."
],
"trailing": "Obsah sa ukladá do konfigurácie LXC a spúšťa sa s administrátorskými právami. Pristupujte k nemu rovnako opatrne ako ku každému príkazu spustenému ako <code>root</code>."
"exampleLead": "Príklad úplného postupu v kontajneri:",
"example": "cd /opt/moja-aplikacia && ./update.sh",
"callout": "Príkaz ako <code>myapp --version</code> iba číta verziu a nič neaktualizuje. Príkazy sa spúšťajú s oprávneniami správcu a musia sa kontrolovať ako príkazy shellu root."
},
"difference": {
"heading": "Rozdiel medzi detekčným a aktualizačným príkazom",
"lead": "Obe polia majú rozdielny účel:",
"table": {
"colField": "Pole",
"colLocation": "Umiestnenie",
"colRole": "Úloha",
"rows": [
{
"field": "Príkaz pre nainštalovanú verziu",
"location": "App → pokročilé sledovanie",
"role": "Prečíta a vráti aktuálnu verziu; spúšťa sa ako zoznam argumentov bez shellu."
},
{
"field": "Vlastný aktualizačný príkaz",
"location": "Aktualizácie",
"role": "Spúšťa aktualizačný postup; interpretuje sa cez sh -c."
}
]
},
"trailing": "Nekopírujte slepo hodnotu z jedného poľa do druhého. Príkaz ako <code>myapp --version</code> môže správne zistiť verziu, ale nenainštaluje novú."
},
"apply": {
"heading": "Použitie aktualizácie",
"lead": "Pred kliknutím na tlačidlo použitia:",
"steps": [
"Overte, čo sa bude aktualizovať: systém, jedna aplikácia alebo oboje.",
"Skontrolujte možnosti zálohy a reštartu.",
"Kliknite na príslušné tlačidlo.",
"Sledujte výstup procesu v terminálovom paneli.",
"Overte výsledok a to, že služba znovu odpovedá."
"bulk": {
"heading": "Hromadná aktualizácia",
"lead": "Hromadná aktualizácia vytvorí jednu opakovane použiteľnú akciu pre presný súbor cieľov v LXC. Nachádza sa za sekciami aplikácií a Dockeru a pred <strong>Možnosťami</strong>.",
"items": [
"Balíky OS sú povinné. Musí byť vybraná aspoň jedna ďalšia aplikácia, Docker Engine alebo jednotka Docker obrazu.",
"Aplikácie a jednotky Dockeru sa vyberajú samostatne. Hlavná služba Compose zobrazuje závislosti, ktoré sa aktualizujú spolu s ňou.",
"Odstránené alebo nedostupné ciele sa označia ako neaktuálne a pred uložením ich treba odstrániť.",
"Tlačidlo <strong>Použiť aktualizácie</strong> je fialové, ak má niektorý vybraný cieľ overenú aktualizáciu, zelené, ak sú všetky overene aktuálne, a neutrálne pri neznámom výsledku.",
"Odstránenie hromadnej konfigurácie neodstráni samostatné metódy ani plánovanie."
],
"trailing1": "Ak je LXC zastavený, ProxMenux ho spustí, aby mohol proces prebehnúť. Ak aktualizácia skončí správne a je zapnutý reštart, kontajner sa na konci reštartuje.",
"systemLead": "Pri systémovej aktualizácii:",
"systemItems": [
"Debian a Ubuntu spúšťajú upgrade cez APT.",
"Alpine ho spúšťa cez APK."
],
"appLead": "Pri aktualizácii aplikácie:",
"appItems": [
"Použije sa kompatibilný helper, ak existuje.",
"Spustí sa vlastný príkaz uložený pre aplikáciu, ak je nastavený.",
"Ak je vybraných viac aplikácií, ich metódy sa spustia postupne."
],
"trailing2": "Terminálový panel zobrazuje priebeh a skončí úspešným výsledkom alebo chybovým kódom procesu."
"callout": "Hromadná aktualizácia nenahrádza samostatné tlačidlá. Je to voliteľná skratka pre výber, ktorý sa má spustiť spolu."
},
"backup": {
"heading": "Záloha pred aktualizáciou",
"p1": "Zapnite <strong>Snapshot kontajnera pred použitím</strong>, aby sa pred zásahom do LXC vytvorila záloha <code>vzdump</code>. Môžete vybrať aj cieľové úložisko.",
"p2": "Ak je záloha vyžadovaná a zlyhá, ProxMenux nebude v aktualizácii pokračovať. Zmeny sa tak nezačnú bez požadovaného bodu obnovy.",
"p3": "Táto voľba platí pre ručné spustenia aj plánované úlohy."
},
"restart": {
"heading": "Reštart po aktualizácii",
"p1": "<strong>Reštartovať kontajner po použití</strong> je preferencia, nie dôkaz, že reštart je povinný. Zapnite ju, keď to vyžaduje postup aplikácie alebo nainštalované balíky.",
"p2": "Reštart nastane iba po úspešnom behu. Ak aktualizácia zlyhá, kontajner ostane spustený, aby sa dala chyba skontrolovať.",
"p3": "Možnosti zálohy a reštartu sa ukladajú pre dané LXC a platia aj pre jeho plánované úlohy."
"options": {
"heading": "Možnosti zálohy a reštartu",
"lead": "Rovnaké možnosti platia pre manuálne, hromadné aj plánované behy:",
"items": [
"<strong>Snímka pred použitím</strong> vytvorí zálohu vzdump vo vybranom úložisku. Ak požadovaná záloha zlyhá, aktualizácia sa nespustí.",
"<strong>Reštartovať po použití</strong> reštartuje LXC iba po úspešnom behu.",
"Voľby sa ukladajú pre každý LXC a sú nezávislé od zoznamu cieľov."
]
},
"scheduled": {
"heading": "Plánované aktualizácie",
"p1": "Sekcia <strong>Plánované aktualizácie</strong> automaticky spúšťa rovnaký tok, aký používajú ručné tlačidlá.",
"createLead": "Plán vytvoríte takto:",
"createSteps": [
"Otvorte <strong>Možnosti</strong> a kliknite na <strong>Upraviť</strong>.",
"Zapnite <strong>Plánované aktualizácie</strong>.",
"Vyberte predvolenú frekvenciu alebo zadajte cron výraz.",
"Vyberte, čo sa bude aktualizovať: iba systémové balíky, iba aplikácie alebo systém aj aplikácie.",
"Skontrolujte možnosti zálohy a reštartu.",
"Uložte nastavenie."
"lead": "Plán používa rovnaké spustiteľné ciele a bezpečnostné možnosti ako manuálne akcie.",
"items": [
"Vyberte predvoľbu alebo cron výraz a potom presné ciele: balíky OS, jednotlivé aplikácie, Docker Engine, samostatné jednotky Dockeru alebo skupiny služieb Compose.",
"Oneskorenie po vydaní platí iba pre vybrané aplikácie so sledovaním verzie. Aplikácie bez sledovania spustia aktualizátor pri každom termíne.",
"Stav posledného behu rozlišuje úspech, čiastočné dokončenie, zlyhanie, bezpečnostné pozdržanie a stav bez čakajúcich aktualizácií.",
"Zistené externé plány Proxmox VE Helper-Scripts sa zobrazia samostatne, aby bola viditeľná prekrývajúca sa automatizácia."
],
"p2": "Karta zobrazuje, či je plán aktívny, čo zahŕňa a ako dopadol posledný beh. Vypnutý plán môžete ponechať na neskoršie zapnutie alebo ho úplne odstrániť.",
"p3": "Ak ProxMenux na hostiteľovi nájde externý plán vytvorený cez Community Scripts, zobrazí ho, aby používateľ vedel, že už existuje iná automatizácia.",
"callout": "Pred plánovaním aktualizácií aplikácií ručne otestujte každý helper alebo príkaz. Plánovaná úloha nevie odpovedať na otázky ani opraviť neúplný postup."
"callout": "Pred zapnutím plánu otestujte každú vybranú metódu manuálne. Plánovaný príkaz nemôže odpovedať na interaktívne otázky."
},
"verify": {
"heading": "Kontrola výsledku",
"p1": "Po použití systémových balíkov ProxMenux vynúti čerstvú kontrolu, aby sa počítadlo čakajúcich balíkov aktualizovalo bez čakania na ďalší pravidelný cyklus.",
"p2": "Pri aplikácii sa vráťte do <link>záložky App</link> a kliknite na <strong>Skontrolovať</strong>, ak sa číslo verzie neobnoví hneď. Znovu sa spustí nastavená metóda nainštalovanej verzie a dotaz na upstream zdroj.",
"p3": "Navyše overte, že webové odkazy aplikácie správne odpovedajú. Príkaz, ktorý skončí bez chýb, ešte nenahrádza funkčnú kontrolu služby."
"completion": {
"heading": "Čo sa stane po dokončení",
"lead": "Aktualizácia sa nepovažuje za dokončenú iba preto, že príkaz v termináli skončil.",
"items": [
"Rovnaký beh uloží konečný výsledok a podľa potreby obnoví stav balíkov OS, verzie aplikácií a inventár Dockeru.",
"Vyrovnávacia pamäť LXC sa nahradí overeným stavom po aktualizácii, takže odznaky a tlačidlá nezostanú v starom stave.",
"Po spustení zastaveného alebo obnoveného LXC existujúca udalosť životného cyklu znova obnoví tento LXC. Inventár Dockeru čaká na pripravenosť démona a dočasne prázdny výsledok nepovažuje za konečný.",
"Povolené upozornenia sa odošlú z dokončeného behu vrátane čiastočných zlyhaní a zoskupených výsledkov Docker obrazov."
]
},
"troubleshoot": {
"heading": "Časté problémy",
"noButtonHeading": "Zobrazuje sa Dostupná aktualizácia, ale chýba tlačidlo Použiť aktualizáciu",
"noButtonBody": "Detekcia verzie funguje, ale nenašla sa metóda na inštaláciu aktualizácie. Skontrolujte, či sa aplikácia aktualizuje cez systémové balíky, kompatibilného helpera alebo vlastný príkaz.",
"aptHeading": "Aplikácia sa aktualizuje cez APT alebo APK",
"aptBody": "Použite <strong>Použiť aktualizáciu OS</strong>. Nepridávajte druhý príkaz pre rovnakú operáciu — aplikácia už je súčasťou systémovej aktualizácie.",
"noUpdaterHeading": "Zobrazuje sa Nie je nastavený aktualizátor",
"noUpdaterBody": "ProxMenux aplikáciu sleduje, ale nevie, ako ju aktualizovať. Skontrolujte jej oficiálnu dokumentáciu, otestujte postup v konzole a ak je vhodný, uložte ho cez <strong>Pridať vlastný aktualizačný príkaz</strong>.",
"helperDetectedHeading": "Helper je nájdený, ale nedá sa použiť",
"helperDetectedBody": "Helper môže byť označený ako neaktualizovateľný alebo nespadá medzi rozpoznané metódy. Riaďte sa oficiálnymi pokynmi aplikácie a nepredpokladajte, že každý LXC vytvorený cez Community Scripts podporuje automatické aktualizácie.",
"customFailsHeading": "Vlastný príkaz zlyhá",
"customFailsBody": "Spustite ho znovu v konzole LXC. Skontrolujte pracovnú cestu, oprávnenia, závislosti, neinteraktívne argumenty a exit code. Nemeňte príkaz za inú verziu, kým neoveríte odporúčaný postup podľa projektu."
"troubleshooting": {
"heading": "Bežné situácie",
"colProblem": "Situácia",
"colResolution": "Riešenie",
"rows": [
{
"problem": "Nebola zistená metóda aktualizácie",
"resolution": "Otvorte Nastaviť, pridajte oficiálny neinteraktívny postup a pred plánovaním ho otestujte manuálne."
},
{
"problem": "Zobrazí sa identita Proxmox VE Helper-Scripts, ale nie akcia",
"resolution": "LXC obsahuje staré identifikačné údaje bez overeného wrappera /usr/bin/update. Vlastnú metódu pridajte až po potvrdení správneho postupu."
},
{
"problem": "Docker obrazy sú po štarte alebo obnovení dočasne prázdne",
"resolution": "Počkajte na pripravenosť Dockeru alebo stlačte Skontrolovať teraz. Inventár štart opakuje a dočasne prázdny výsledok nepovažuje za konečný."
},
{
"problem": "Uložený hromadný cieľ už nie je dostupný",
"resolution": "Upravte konfiguráciu, odstráňte neaktuálny cieľ a vyberte jeho aktuálnu náhradu, ak existuje."
},
{
"problem": "Vlastný príkaz zlyhá",
"resolution": "Spustite ho v termináli LXC a skontrolujte cestu, závislosti, neinteraktívne parametre a návratový kód."
}
]
},
"figures": {
"osPending": {
"alt": "Sekcia balíkov operačného systému s počtom čakajúcich a bezpečnostných aktualizácií",
"caption": "Sekcia operačného systému udržiava balíky oddelené od akcií aplikácií a Dockeru."
},
"options": {
"alt": "Možnosti aktualizácie LXC so zálohou pred a reštartom po použití",
"caption": "Nastavenia zálohy a reštartu platia pre manuálne, hromadné aj plánované behy."
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 154 KiB

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 162 KiB

After

Width:  |  Height:  |  Size: 158 KiB