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
+4
View File
@@ -34,6 +34,8 @@ from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
from build_translation_cache import ( # noqa: E402
clean_translation,
protect_technical_terms,
restore_technical_terms,
translate_appimage,
translate_google_web,
translate_googletrans,
@@ -282,6 +284,7 @@ def main() -> int:
for index, key in enumerate(missing, start=1):
en_value = en_flat[key]
protected, placeholders = protect_placeholders(en_value)
protected, technical_terms = protect_technical_terms(protected)
try:
translated = translate_one(
@@ -292,6 +295,7 @@ def main() -> int:
args.timeout,
args.appimage_path,
)
translated = restore_technical_terms(translated, technical_terms)
target_flat[key] = restore_placeholders(translated, placeholders)
print(
f" [{lang} {index}/{len(missing)}] {key}: "
+71 -4
View File
@@ -30,12 +30,75 @@ from urllib.request import Request, urlopen
DEFAULT_LANGUAGES = ("es", "fr", "de", "it", "pt", "sk", "sv")
DEFAULT_CONTEXT = "Context: Technical message for Proxmox and IT. Translate:"
# googletrans and the public Google endpoint used by this workflow do not
# support Cloud Translation glossaries. Protect product names, package names
# and command identifiers with opaque tokens before sending text to any
# provider, then restore the exact source spelling afterwards. Keep longer
# terms first so ``gasket`` cannot consume part of ``gasket-dkms``.
PROTECTED_TECHNICAL_TERMS = (
"google/gasket-driver",
"feranick/gasket-driver",
"libedgetpu1-std",
"Proxmox VE Helper-Scripts",
"Docker Compose",
"gasket-driver",
"gasket-dkms",
"libedgetpu1",
"libedgetpu",
"Google Coral",
"Edge TPU",
"ProxMenux",
"Proxmox",
"AppImage",
"smartctl",
"systemctl",
"pveproxy",
"apt-get",
"Frigate",
"Docker",
"Coral",
"gasket",
"apex",
"lspci",
"dpkg",
"DKMS",
"QEMU",
"LXC",
"ZFS",
"SSH",
"fork",
)
TECHNICAL_TERM_RE = re.compile(
"|".join(
rf"(?<![A-Za-z0-9_]){re.escape(term)}(?![A-Za-z0-9_])"
for term in sorted(PROTECTED_TECHNICAL_TERMS, key=len, reverse=True)
),
re.IGNORECASE,
)
TRANSLATE_CALL_RE = re.compile(
r"""translate\s+(?P<quote>["'])(?P<text>(?:\\.|(?! (?P=quote) ).)*?)(?P=quote)""",
re.VERBOSE | re.DOTALL,
)
def protect_technical_terms(text: str) -> tuple[str, list[str]]:
"""Replace glossary terms with stable tokens before translation."""
protected: list[str] = []
def _swap(match: re.Match[str]) -> str:
protected.append(match.group(0))
return f"__PMX_TERM_{len(protected) - 1}__"
return TECHNICAL_TERM_RE.sub(_swap, text), protected
def restore_technical_terms(text: str, protected: list[str]) -> str:
"""Restore glossary terms exactly as they appeared in the source."""
for index, original in enumerate(protected):
text = text.replace(f"__PMX_TERM_{index}__", original)
return text
def iter_script_files(
scripts_dir: Path, extra_files: Iterable[Path] = ()
) -> Iterable[Path]:
@@ -209,15 +272,19 @@ def translate_text(
timeout: int,
appimage_path: Path,
) -> str:
protected_text, protected_terms = protect_technical_terms(text)
if provider == "googletrans":
translated = translate_googletrans(text, dest_lang, context)
translated = translate_googletrans(protected_text, dest_lang, context)
elif provider == "google-web":
translated = translate_google_web(text, dest_lang, context, timeout)
translated = translate_google_web(protected_text, dest_lang, context, timeout)
elif provider == "appimage":
translated = translate_appimage(text, dest_lang, context, timeout, appimage_path)
translated = translate_appimage(
protected_text, dest_lang, context, timeout, appimage_path
)
else:
raise ValueError(f"Unknown provider: {provider}")
return clean_translation(translated) or text
translated = restore_technical_terms(clean_translation(translated), protected_terms)
return translated or text
def load_language_cache(path: Path) -> dict[str, str]:
+50 -9
View File
@@ -270,6 +270,7 @@ export function Security() {
const [proxmoxCertInfo, setProxmoxCertInfo] = useState<{subject?: string; expires?: string; issuer?: string; is_self_signed?: boolean} | null>(null)
const [loadingSsl, setLoadingSsl] = useState(true)
const [configuringSsl, setConfiguringSsl] = useState(false)
const [reloadingSsl, setReloadingSsl] = useState(false)
const [sslRestarting, setSslRestarting] = useState(false)
const [showCustomCertForm, setShowCustomCertForm] = useState(false)
const [customCertPath, setCustomCertPath] = useState("")
@@ -1779,6 +1780,35 @@ ${(report.sections && report.sections.length > 0) ? `
}
}
const handleReloadSsl = async () => {
setReloadingSsl(true)
setError("")
setSuccess("")
try {
const data = await fetchApi("/api/ssl/reload", {
method: "POST",
})
if (data.success) {
setSslCertPath(data.cert_path || sslCertPath)
setSslKeyPath(data.key_path || sslKeyPath)
if (data.cert_info) {
setProxmoxCertInfo(data.cert_info)
}
setSuccess(data.changed
? st("messages.sslCertificateReloaded")
: st("messages.sslCertificateUnchanged"))
} else {
setError(data.message || st("errors.reloadSslFailed"))
}
} catch (err) {
setError(err instanceof Error ? err.message : st("errors.reloadSslFailed"))
} finally {
setReloadingSsl(false)
}
}
return (
<div className="space-y-6">
<div>
@@ -2154,15 +2184,26 @@ ${(report.sections && report.sections.length > 0) ? `
<p><span className="font-medium text-foreground">{st("ssl.cert")}:</span> <code className="text-xs">{sslCertPath}</code></p>
<p><span className="font-medium text-foreground">{st("ssl.key")}:</span> <code className="text-xs">{sslKeyPath}</code></p>
</div>
<Button
onClick={handleDisableSsl}
variant="outline"
size="sm"
disabled={configuringSsl || sslRestarting}
className="mt-2 text-red-500 border-red-500/30 hover:bg-red-500/10 bg-transparent"
>
{configuringSsl ? st("ssl.disabling") : sslRestarting ? st("ssl.restarting") : st("ssl.disableHttps")}
</Button>
<div className="flex flex-wrap gap-2 pt-2">
<Button
onClick={handleReloadSsl}
variant="outline"
size="sm"
disabled={configuringSsl || reloadingSsl || sslRestarting}
>
<RefreshCw className={`h-4 w-4 mr-2 ${reloadingSsl ? "animate-spin" : ""}`} />
{reloadingSsl ? st("ssl.updatingCertificate") : st("ssl.updateCertificate")}
</Button>
<Button
onClick={handleDisableSsl}
variant="outline"
size="sm"
disabled={configuringSsl || reloadingSsl || sslRestarting}
className="text-red-500 border-red-500/30 hover:bg-red-500/10 bg-transparent"
>
{configuringSsl ? st("ssl.disabling") : sslRestarting ? st("ssl.restarting") : st("ssl.disableHttps")}
</Button>
</div>
</div>
)}
+6 -1
View File
@@ -289,6 +289,7 @@ interface RemoteStorage {
used: number
available: number
percent: number
capacity_known?: boolean
exclude_health: boolean
exclude_notifications: boolean
excluded_at?: string
@@ -1509,7 +1510,8 @@ export function Settings() {
const isExcluded = storage.exclude_health || storage.exclude_notifications
const isSaving = savingStorage === storage.name
const isNamespaceRestricted = storage.status === 'namespace_restricted'
const isOffline = !isNamespaceRestricted && (storage.status === 'error' || storage.total === 0)
const isOffline = !isNamespaceRestricted && storage.status !== 'active'
const capacityKnown = storage.capacity_known ?? storage.total > 0
return (
<div key={storage.name} className="grid grid-cols-[1fr_auto_auto] gap-4 py-3 items-center">
@@ -1530,6 +1532,9 @@ export function Settings() {
{isNamespaceRestricted && (
<p className="text-[11px] text-blue-400 mt-0.5">{t("settings.remoteStorage.namespaceRestricted")}</p>
)}
{!isOffline && !isNamespaceRestricted && !capacityKnown && (
<p className="text-[11px] text-muted-foreground mt-0.5">{t("storage.capacityNotReported")}</p>
)}
</div>
</div>
+41 -35
View File
@@ -148,6 +148,7 @@ interface ProxmoxStorage {
used: number
available: number
percent: number
capacity_known?: boolean
node: string // Added node property for detailed debug logging
}
@@ -1346,6 +1347,7 @@ export function StorageOverview() {
// Check if storage is excluded from monitoring
const isExcluded = storage.excluded === true
const hasError = storage.status === "error" && !isExcluded
const capacityKnown = storage.capacity_known ?? storage.total > 0
return (
<div
@@ -1425,46 +1427,50 @@ export function StorageOverview() {
? t("storage.notMonitored")
: storageStatusLabel(storage.status)}
</Badge>
<span className="text-sm font-medium">{storage.percent}%</span>
{capacityKnown && <span className="text-sm font-medium">{storage.percent}%</span>}
</div>
</div>
<div className="space-y-2">
<Progress
value={storage.percent}
className={`h-2 ${
storage.percent > 90
? "[&>div]:bg-red-500"
: storage.percent > 75
? "[&>div]:bg-yellow-500"
: "[&>div]:bg-blue-500"
}`}
/>
<div className="grid grid-cols-3 gap-4 text-sm">
<div>
<p className="text-muted-foreground">{t("storage.total")}</p>
<p className="font-medium">{formatStorage(storage.total)}</p>
</div>
<div>
<p className="text-muted-foreground">{t("storage.used")}</p>
<p
className={`font-medium ${
storage.percent > 90
? "text-red-400"
: storage.percent > 75
? "text-yellow-400"
: "text-blue-400"
}`}
>
{formatStorage(storage.used)}
</p>
</div>
<div>
<p className="text-muted-foreground">{t("storage.available")}</p>
<p className="font-medium text-green-400">{formatStorage(storage.available)}</p>
{capacityKnown ? (
<div className="space-y-2">
<Progress
value={storage.percent}
className={`h-2 ${
storage.percent > 90
? "[&>div]:bg-red-500"
: storage.percent > 75
? "[&>div]:bg-yellow-500"
: "[&>div]:bg-blue-500"
}`}
/>
<div className="grid grid-cols-3 gap-4 text-sm">
<div>
<p className="text-muted-foreground">{t("storage.total")}</p>
<p className="font-medium">{formatStorage(storage.total)}</p>
</div>
<div>
<p className="text-muted-foreground">{t("storage.used")}</p>
<p
className={`font-medium ${
storage.percent > 90
? "text-red-400"
: storage.percent > 75
? "text-yellow-400"
: "text-blue-400"
}`}
>
{formatStorage(storage.used)}
</p>
</div>
<div>
<p className="text-muted-foreground">{t("storage.available")}</p>
<p className="font-medium text-green-400">{formatStorage(storage.available)}</p>
</div>
</div>
</div>
</div>
) : (
<p className="text-sm text-muted-foreground">{t("storage.capacityNotReported")}</p>
)}
</div>
)
})}
+3 -4
View File
@@ -5296,10 +5296,9 @@ const handleDownloadLogs = async (vmid: number, vmName: string) => {
</button>
</div>
<div className="text-xs text-muted-foreground mb-3 leading-relaxed">
{t("vmLxc.updates.dockerImagesReadOnly")}
{selectedVM.docker_inventory.checked_at
? ` · ${t("vmLxc.updates.lastCheckedPrefix")} ${new Date(selectedVM.docker_inventory.checked_at).toLocaleString()}`
: ""}
{t("vmLxc.updates.lastCheckedPrefix")} {selectedVM.docker_inventory.checked_at
? new Date(selectedVM.docker_inventory.checked_at).toLocaleString()
: "—"}
</div>
{dockerInventoryRefreshing ? (
<div className="text-sm text-muted-foreground flex items-center gap-2">
+6 -1
View File
@@ -188,6 +188,7 @@
"notMonitored": "nicht überwacht",
"namespaceRestricted": "Namespace-beschränkt",
"namespaceRestrictedTitle": "Speicher erreichbar; Durch ACL ausgeblendete Datenspeichergröße (z. B. PBS DatastoreAdmin in einem einzelnen Namespace)",
"capacityNotReported": "Kapazität nicht gemeldet",
"managedByProxmox": "verwaltet von Proxmox",
"readOnlyShort": "ro",
"stale": "abgestanden",
@@ -1284,7 +1285,6 @@
"dockerImagesTitle": "Docker-Images",
"dockerAppTitle": "Docker",
"dockerImagesSubheading": "Images",
"dockerImagesReadOnly": "Image-Tags werden anhand des Registry-Digests verglichen. Compose-Dienste können aus ihrem deklarierten Projekt geladen und neu erstellt werden.",
"dockerEngineManagedByOs": "Docker Engine {version} wird über Pakete verwaltet und durch die obige Betriebssystem-Paketaktion aktualisiert.",
"dockerEngineSubheading": "Engine",
"dockerEngineDetected": "Docker Engine {version} erkannt",
@@ -2176,6 +2176,7 @@
"noTokenReceived": "Vom Server wurde kein Token zurückgegeben.",
"generateTokenRetry": "Token konnte nicht generiert werden. Bitte versuchen Sie es erneut.",
"configureSslFailed": "SSL konnte nicht konfiguriert werden",
"reloadSslFailed": "Das aktive Zertifikat konnte nicht aktualisiert werden",
"disableSslFailed": "SSL konnte nicht deaktiviert werden",
"deleteReportFailed": "Der Bericht konnte nicht gelöscht werden"
},
@@ -2203,6 +2204,8 @@
"apiTokenGenerated": "API-Token wurde generiert.",
"sslEnabledRestarting": "HTTPS ist aktiviert. Dienst wird neu gestartet...",
"sslDisabledRestarting": "HTTPS ist deaktiviert. Dienst wird neu gestartet...",
"sslCertificateReloaded": "Das erneuerte Zertifikat ist jetzt aktiv. Bestehende Verbindungen wurden nicht unterbrochen.",
"sslCertificateUnchanged": "Das aktive Zertifikat entspricht bereits den aktuellen Zertifikatsdateien.",
"reportDeleted": "Auditbericht wurde gelöscht.",
"twoFactorEnabled": "Die Zwei-Faktor-Authentifizierung ist aktiviert."
},
@@ -2267,6 +2270,8 @@
"activeCertificate": "Aktives Zertifikat",
"cert": "Zertifikat",
"key": "Privater Schlüssel",
"updateCertificate": "Zertifikat aktualisieren",
"updatingCertificate": "Wird aktualisiert...",
"disabling": "Deaktivieren...",
"restarting": "Neustart...",
"disableHttps": "Deaktivieren Sie HTTPS",
+6 -1
View File
@@ -187,6 +187,7 @@
"notMonitored": "not monitored",
"namespaceRestricted": "namespace-restricted",
"namespaceRestrictedTitle": "Storage reachable; datastore size hidden by ACL (e.g. PBS DatastoreAdmin on a single namespace)",
"capacityNotReported": "Capacity not reported",
"managedByProxmox": "managed by Proxmox",
"readOnlyShort": "ro",
"stale": "stale",
@@ -1283,7 +1284,6 @@
"dockerImagesTitle": "Docker images",
"dockerAppTitle": "Docker",
"dockerImagesSubheading": "Images",
"dockerImagesReadOnly": "Image tags are compared by registry digest. Compose services can be pulled and recreated from their declared project.",
"dockerEngineManagedByOs": "Docker Engine {version} is package-managed and is updated by the OS packages action above.",
"dockerEngineSubheading": "Engine",
"dockerEngineDetected": "Docker Engine {version} detected",
@@ -2175,6 +2175,7 @@
"noTokenReceived": "No token was returned by the server.",
"generateTokenRetry": "Failed to generate token. Please try again.",
"configureSslFailed": "Failed to configure SSL",
"reloadSslFailed": "Failed to update the active certificate",
"disableSslFailed": "Failed to disable SSL",
"deleteReportFailed": "Failed to delete report"
},
@@ -2202,6 +2203,8 @@
"apiTokenGenerated": "API token was generated.",
"sslEnabledRestarting": "HTTPS is enabled. Restarting service...",
"sslDisabledRestarting": "HTTPS is disabled. Restarting service...",
"sslCertificateReloaded": "The renewed certificate is now active. Existing connections were not interrupted.",
"sslCertificateUnchanged": "The active certificate already matches the current certificate files.",
"reportDeleted": "Audit report was deleted.",
"twoFactorEnabled": "Two-factor authentication is enabled."
},
@@ -2266,6 +2269,8 @@
"activeCertificate": "Active certificate",
"cert": "Certificate",
"key": "Private key",
"updateCertificate": "Update certificate",
"updatingCertificate": "Updating...",
"disabling": "Disabling...",
"restarting": "Restarting...",
"disableHttps": "Disable HTTPS",
+11 -6
View File
@@ -188,6 +188,7 @@
"notMonitored": "no monitoreado",
"namespaceRestricted": "espacio de nombres restringido",
"namespaceRestrictedTitle": "Almacenamiento accesible; Tamaño del almacén de datos oculto por ACL (por ejemplo, PBS DatastoreAdmin en un único espacio de nombres)",
"capacityNotReported": "Capacidad no informada",
"managedByProxmox": "gestionado por Proxmox",
"readOnlyShort": "ro",
"stale": "duro",
@@ -1284,7 +1285,6 @@
"dockerImagesTitle": "Imágenes Docker",
"dockerAppTitle": "Docker",
"dockerImagesSubheading": "Imágenes",
"dockerImagesReadOnly": "Las etiquetas se comparan mediante el digest del registro. Los servicios Compose pueden descargar la imagen y recrearse desde su proyecto declarado.",
"dockerEngineManagedByOs": "Docker Engine {version} está gestionado por paquetes y se actualiza mediante la acción de paquetes del SO anterior.",
"dockerEngineSubheading": "Motor",
"dockerEngineDetected": "Docker Engine {version} detectado",
@@ -1688,7 +1688,7 @@
"label": "Seguridad"
},
"cluster": {
"label": "Grupo"
"label": "Clúster"
},
"services": {
"label": "Servicios"
@@ -1758,13 +1758,13 @@
"burst_auth_fail": "Ráfaga de fallos de autenticación",
"burst_ip_block": "Ráfaga de bloqueos de IP",
"burst_disk_io": "Ráfaga de errores de E/S de disco",
"burst_cluster": "Conexión de clúster aleteando",
"burst_cluster": "Conexión del clúster inestable",
"burst_service_fail": "Múltiples fallas de servicio",
"burst_system": "Múltiples problemas del sistema",
"burst_generic": "Múltiples eventos relacionados",
"split_brain": "Cerebro dividido detectado",
"node_disconnect": "Nodo desconectado",
"node_reconnect": "Nodo reconectado",
"split_brain": "Partición del clúster detectada",
"node_disconnect": "Nodo del clúster desconectado",
"node_reconnect": "Nodo del clúster reconectado",
"system_startup": "Informe de inicio del sistema",
"system_shutdown": "Sistema apagándose",
"system_reboot": "Reinicio del sistema",
@@ -2176,6 +2176,7 @@
"noTokenReceived": "El servidor no devolvió ningún token.",
"generateTokenRetry": "No se pudo generar el token. Por favor inténtalo de nuevo.",
"configureSslFailed": "No se pudo configurar SSL",
"reloadSslFailed": "No se pudo actualizar el certificado activo",
"disableSslFailed": "No se pudo deshabilitar SSL",
"deleteReportFailed": "No se pudo eliminar el informe"
},
@@ -2203,6 +2204,8 @@
"apiTokenGenerated": "Se generó el token API.",
"sslEnabledRestarting": "HTTPS está habilitado. Reiniciando servicio...",
"sslDisabledRestarting": "HTTPS está deshabilitado. Reiniciando servicio...",
"sslCertificateReloaded": "El certificado renovado ya está activo. No se ha interrumpido ninguna conexión.",
"sslCertificateUnchanged": "El certificado activo ya coincide con los archivos actuales.",
"reportDeleted": "Se eliminó el informe de auditoría.",
"twoFactorEnabled": "La autenticación de dos factores está habilitada."
},
@@ -2267,6 +2270,8 @@
"activeCertificate": "Certificado activo",
"cert": "Certificado",
"key": "clave privada",
"updateCertificate": "Actualizar certificado",
"updatingCertificate": "Actualizando...",
"disabling": "Desactivando...",
"restarting": "Reiniciando...",
"disableHttps": "Deshabilitar HTTPS",
+6 -1
View File
@@ -188,6 +188,7 @@
"notMonitored": "non surveillé",
"namespaceRestricted": "espace de noms restreint",
"namespaceRestrictedTitle": "Stockage accessible ; taille de la banque de données masquée par l'ACL (par exemple PBS DatastoreAdmin sur un seul espace de noms)",
"capacityNotReported": "Capacité non indiquée",
"managedByProxmox": "géré par Proxmox",
"readOnlyShort": "ro",
"stale": "vicié",
@@ -1284,7 +1285,6 @@
"dockerImagesTitle": "Images Docker",
"dockerAppTitle": "Docker",
"dockerImagesSubheading": "Images",
"dockerImagesReadOnly": "Les tags sont comparés par digest de registre. Les services Compose peuvent télécharger limage et être recréés depuis leur projet déclaré.",
"dockerEngineManagedByOs": "Docker Engine {version} est géré par paquets et mis à jour par laction des paquets du SE ci-dessus.",
"dockerEngineSubheading": "Moteur",
"dockerEngineDetected": "Docker Engine {version} détecté",
@@ -2176,6 +2176,7 @@
"noTokenReceived": "Aucun jeton n'a été renvoyé par le serveur.",
"generateTokenRetry": "Échec de la génération du jeton. Veuillez réessayer.",
"configureSslFailed": "Échec de la configuration de SSL",
"reloadSslFailed": "Échec de la mise à jour du certificat actif",
"disableSslFailed": "Échec de la désactivation de SSL",
"deleteReportFailed": "Échec de la suppression du rapport"
},
@@ -2203,6 +2204,8 @@
"apiTokenGenerated": "Le jeton API a été généré.",
"sslEnabledRestarting": "HTTPS est activé. Redémarrage du service...",
"sslDisabledRestarting": "HTTPS est désactivé. Redémarrage du service...",
"sslCertificateReloaded": "Le certificat renouvelé est maintenant actif. Les connexions existantes nont pas été interrompues.",
"sslCertificateUnchanged": "Le certificat actif correspond déjà aux fichiers de certificat actuels.",
"reportDeleted": "Le rapport d'audit a été supprimé.",
"twoFactorEnabled": "L'authentification à deux facteurs est activée."
},
@@ -2267,6 +2270,8 @@
"activeCertificate": "Certificat actif",
"cert": "Certificat",
"key": "Clé privée",
"updateCertificate": "Mettre à jour le certificat",
"updatingCertificate": "Mise à jour...",
"disabling": "Désactivation...",
"restarting": "Redémarrage...",
"disableHttps": "Désactiver HTTPS",
+6 -1
View File
@@ -188,6 +188,7 @@
"notMonitored": "non monitorato",
"namespaceRestricted": "limitato allo spazio dei nomi",
"namespaceRestrictedTitle": "Deposito raggiungibile; dimensione del datastore nascosta dall'ACL (ad esempio PBS DatastoreAdmin su un singolo spazio dei nomi)",
"capacityNotReported": "Capacità non indicata",
"managedByProxmox": "gestito da Proxmox",
"readOnlyShort": "ro",
"stale": "stantio",
@@ -1284,7 +1285,6 @@
"dockerImagesTitle": "Immagini Docker",
"dockerAppTitle": "Docker",
"dockerImagesSubheading": "Immagini",
"dockerImagesReadOnly": "I tag vengono confrontati tramite digest del registro. I servizi Compose possono scaricare limmagine ed essere ricreati dal progetto dichiarato.",
"dockerEngineManagedByOs": "Docker Engine {version} è gestito dai pacchetti e viene aggiornato dallazione dei pacchetti del sistema operativo qui sopra.",
"dockerEngineSubheading": "Motore",
"dockerEngineDetected": "Docker Engine {version} rilevato",
@@ -2176,6 +2176,7 @@
"noTokenReceived": "Nessun token è stato restituito dal server.",
"generateTokenRetry": "Impossibile generare il token. Per favore riprova.",
"configureSslFailed": "Impossibile configurare SSL",
"reloadSslFailed": "Impossibile aggiornare il certificato attivo",
"disableSslFailed": "Impossibile disabilitare SSL",
"deleteReportFailed": "Impossibile eliminare il rapporto"
},
@@ -2203,6 +2204,8 @@
"apiTokenGenerated": "Il token API è stato generato.",
"sslEnabledRestarting": "HTTPS è abilitato. Riavvio del servizio...",
"sslDisabledRestarting": "HTTPS è disabilitato. Riavvio del servizio...",
"sslCertificateReloaded": "Il certificato rinnovato è ora attivo. Le connessioni esistenti non sono state interrotte.",
"sslCertificateUnchanged": "Il certificato attivo corrisponde già ai file del certificato correnti.",
"reportDeleted": "Il rapporto di audit è stato eliminato.",
"twoFactorEnabled": "L'autenticazione a due fattori è abilitata."
},
@@ -2267,6 +2270,8 @@
"activeCertificate": "Certificato attivo",
"cert": "Certificato",
"key": "Chiave privata",
"updateCertificate": "Aggiorna certificato",
"updatingCertificate": "Aggiornamento...",
"disabling": "Disabilitazione...",
"restarting": "Riavvio...",
"disableHttps": "Disabilita HTTPS",
+6 -1
View File
@@ -188,6 +188,7 @@
"notMonitored": "não monitorado",
"namespaceRestricted": "restrito ao namespace",
"namespaceRestrictedTitle": "Armazenamento acessível; tamanho do armazenamento de dados oculto pela ACL (por exemplo, PBS DatastoreAdmin em um único namespace)",
"capacityNotReported": "Capacidade não informada",
"managedByProxmox": "gerenciado por Proxmox",
"readOnlyShort": "ro",
"stale": "obsoleto",
@@ -1284,7 +1285,6 @@
"dockerImagesTitle": "Imagens Docker",
"dockerAppTitle": "Docker",
"dockerImagesSubheading": "Imagens",
"dockerImagesReadOnly": "As tags são comparadas pelo digest do registo. Os serviços Compose podem descarregar a imagem e ser recriados a partir do projeto declarado.",
"dockerEngineManagedByOs": "O Docker Engine {version} é gerido por pacotes e atualizado pela ação de pacotes do SO acima.",
"dockerEngineSubheading": "Motor",
"dockerEngineDetected": "Docker Engine {version} detetado",
@@ -2176,6 +2176,7 @@
"noTokenReceived": "Nenhum token foi retornado pelo servidor.",
"generateTokenRetry": "Falha ao gerar token. Por favor, tente novamente.",
"configureSslFailed": "Falha ao configurar SSL",
"reloadSslFailed": "Falha ao atualizar o certificado ativo",
"disableSslFailed": "Falha ao desativar SSL",
"deleteReportFailed": "Falha ao excluir relatório"
},
@@ -2203,6 +2204,8 @@
"apiTokenGenerated": "O token da API foi gerado.",
"sslEnabledRestarting": "HTTPS está ativado. Reiniciando serviço...",
"sslDisabledRestarting": "HTTPS está desativado. Reiniciando serviço...",
"sslCertificateReloaded": "O certificado renovado está agora ativo. As ligações existentes não foram interrompidas.",
"sslCertificateUnchanged": "O certificado ativo já corresponde aos ficheiros de certificado atuais.",
"reportDeleted": "O relatório de auditoria foi excluído.",
"twoFactorEnabled": "A autenticação de dois fatores está habilitada."
},
@@ -2267,6 +2270,8 @@
"activeCertificate": "Certificado ativo",
"cert": "Certificado",
"key": "Chave privada",
"updateCertificate": "Atualizar certificado",
"updatingCertificate": "A atualizar...",
"disabling": "Desativando...",
"restarting": "Reiniciando...",
"disableHttps": "Desativar HTTPS",
+6 -1
View File
@@ -187,6 +187,7 @@
"notMonitored": "nesledované",
"namespaceRestricted": "obmedzený prístup",
"namespaceRestrictedTitle": "Úložisko je dostupné, ale veľkosť datastore je skrytá právami ACL (napr. PBS DatastoreAdmin iba pre jeden namespace)",
"capacityNotReported": "Kapacita nie je uvedená",
"managedByProxmox": "spravuje Proxmox",
"readOnlyShort": "iba čítanie",
"stale": "neodpovedá",
@@ -1283,7 +1284,6 @@
"dockerImagesTitle": "Docker obrazy",
"dockerAppTitle": "Docker",
"dockerImagesSubheading": "Obrazy",
"dockerImagesReadOnly": "Značky sa porovnávajú podľa digestu registra. Služby Compose môžu stiahnuť obraz a znova sa vytvoriť z deklarovaného projektu.",
"dockerEngineManagedByOs": "Docker Engine {version} je spravovaný balíkmi a aktualizuje sa vyššie uvedenou akciou balíkov OS.",
"dockerEngineSubheading": "Engine",
"dockerEngineDetected": "Zistený Docker Engine {version}",
@@ -2175,6 +2175,7 @@
"noTokenReceived": "Server nevrátil žiadny token.",
"generateTokenRetry": "Nepodarilo sa vytvoriť token. Skúste to znova.",
"configureSslFailed": "Nepodarilo sa nastaviť SSL",
"reloadSslFailed": "Aktívny certifikát sa nepodarilo aktualizovať",
"disableSslFailed": "Nepodarilo sa vypnúť SSL",
"deleteReportFailed": "Nepodarilo sa vymazať report"
},
@@ -2202,6 +2203,8 @@
"apiTokenGenerated": "API token bol vytvorený.",
"sslEnabledRestarting": "HTTPS je zapnuté. Reštartujem službu...",
"sslDisabledRestarting": "HTTPS je vypnuté. Reštartujem službu...",
"sslCertificateReloaded": "Obnovený certifikát je teraz aktívny. Existujúce pripojenia neboli prerušené.",
"sslCertificateUnchanged": "Aktívny certifikát už zodpovedá aktuálnym súborom certifikátu.",
"reportDeleted": "Správa z auditu bola vymazaná.",
"twoFactorEnabled": "Dvojfaktorové overenie je zapnuté."
},
@@ -2266,6 +2269,8 @@
"activeCertificate": "Aktívny certifikát",
"cert": "Certifikát",
"key": "Súkromný kľúč",
"updateCertificate": "Aktualizovať certifikát",
"updatingCertificate": "Aktualizuje sa...",
"disabling": "Vypínam...",
"restarting": "Reštartujem...",
"disableHttps": "Vypnúť HTTPS",
+6 -1
View File
@@ -188,6 +188,7 @@
"notMonitored": "inte övervakas",
"namespaceRestricted": "namnutrymmet begränsat",
"namespaceRestrictedTitle": "Lagring nåbar; datalagerstorlek dold av ACL (t.ex. PBS DatastoreAdmin på ett enda namnområde)",
"capacityNotReported": "Kapacitet ej rapporterad",
"managedByProxmox": "hanteras av Proxmox",
"readOnlyShort": "ro",
"stale": "Inaktuell",
@@ -1284,7 +1285,6 @@
"dockerImagesTitle": "Docker-avbilder",
"dockerAppTitle": "Docker",
"dockerImagesSubheading": "Avbilder",
"dockerImagesReadOnly": "Taggar jämförs med registrets digest. Compose-tjänster kan hämta avbilden och återskapas från sitt deklarerade projekt.",
"dockerEngineManagedByOs": "Docker Engine {version} hanteras som paket och uppdateras av OS-paketåtgärden ovan.",
"dockerEngineSubheading": "Motor",
"dockerEngineDetected": "Docker Engine {version} identifierad",
@@ -2176,6 +2176,7 @@
"noTokenReceived": "Ingen token returnerades av servern.",
"generateTokenRetry": "Det gick inte att generera token. Försök igen.",
"configureSslFailed": "Det gick inte att konfigurera SSL",
"reloadSslFailed": "Det gick inte att uppdatera det aktiva certifikatet",
"disableSslFailed": "Det gick inte att inaktivera SSL",
"deleteReportFailed": "Det gick inte att ta bort rapporten"
},
@@ -2203,6 +2204,8 @@
"apiTokenGenerated": "API-token genererades.",
"sslEnabledRestarting": "HTTPS är aktiverat. Startar om tjänsten...",
"sslDisabledRestarting": "HTTPS är inaktiverat. Startar om tjänsten...",
"sslCertificateReloaded": "Det förnyade certifikatet är nu aktivt. Befintliga anslutningar avbröts inte.",
"sslCertificateUnchanged": "Det aktiva certifikatet motsvarar redan de aktuella certifikatfilerna.",
"reportDeleted": "Revisionsrapporten togs bort.",
"twoFactorEnabled": "Tvåfaktorsautentisering är aktiverad."
},
@@ -2267,6 +2270,8 @@
"activeCertificate": "Aktivt certifikat",
"cert": "Certifikat",
"key": "Privat nyckel",
"updateCertificate": "Uppdatera certifikat",
"updatingCertificate": "Uppdaterar...",
"disabling": "Inaktiverar...",
"restarting": "Startar om...",
"disableHttps": "Inaktivera HTTPS",
+79 -15
View File
@@ -1054,6 +1054,12 @@ PROXMOX_KEY_PATH = "/etc/pve/local/pve-ssl.key"
PROXMOX_CUSTOM_CERT_PATH = "/etc/pve/local/pveproxy-ssl.pem"
PROXMOX_CUSTOM_KEY_PATH = "/etc/pve/local/pveproxy-ssl.key"
_SSL_RUNTIME_LOCK = threading.RLock()
_SSL_RUNTIME_CONTEXT = None
_SSL_RUNTIME_FINGERPRINT = ""
_SSL_RUNTIME_CERT_PATH = ""
_SSL_RUNTIME_KEY_PATH = ""
def load_ssl_config():
"""Load SSL configuration from file"""
@@ -1175,26 +1181,84 @@ def validate_certificate_files(cert_path, key_path):
except Exception as e:
return False, f"Error reading certificate files: {str(e)}"
# Verify cert and key match
# Parse the complete chain and verify that the private key matches it.
try:
import subprocess
cert_mod = subprocess.run(
["openssl", "x509", "-noout", "-modulus", "-in", cert_path],
capture_output=True, text=True, timeout=5
)
key_mod = subprocess.run(
["openssl", "rsa", "-noout", "-modulus", "-in", key_path],
capture_output=True, text=True, timeout=5
)
if cert_mod.returncode == 0 and key_mod.returncode == 0:
if cert_mod.stdout.strip() != key_mod.stdout.strip():
return False, "Certificate and key do not match"
except Exception:
pass # Non-critical, proceed anyway
import ssl
test_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
test_context.load_cert_chain(cert_path, key_path)
except Exception as e:
return False, f"Certificate or private key is invalid: {str(e)}"
return True, "Certificate files are valid"
def _certificate_pair_fingerprint(cert_path, key_path):
digest = hashlib.sha256()
for path in (cert_path, key_path):
with open(path, "rb") as source:
for chunk in iter(lambda: source.read(65536), b""):
digest.update(chunk)
return digest.hexdigest()
def _build_server_ssl_context(cert_path, key_path):
import ssl
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain(cert_path, key_path)
return context
def create_reloadable_ssl_context(cert_path, key_path):
"""Create the server context and register it for manual hot reloads."""
global _SSL_RUNTIME_CONTEXT
global _SSL_RUNTIME_FINGERPRINT
global _SSL_RUNTIME_CERT_PATH
global _SSL_RUNTIME_KEY_PATH
context = _build_server_ssl_context(cert_path, key_path)
fingerprint = _certificate_pair_fingerprint(cert_path, key_path)
def _select_active_context(ssl_socket, _server_name, _initial_context):
with _SSL_RUNTIME_LOCK:
active_context = _SSL_RUNTIME_CONTEXT
if active_context is not None and ssl_socket.context is not active_context:
ssl_socket.context = active_context
context.sni_callback = _select_active_context
with _SSL_RUNTIME_LOCK:
_SSL_RUNTIME_CONTEXT = context
_SSL_RUNTIME_FINGERPRINT = fingerprint
_SSL_RUNTIME_CERT_PATH = cert_path
_SSL_RUNTIME_KEY_PATH = key_path
return context
def reload_server_ssl_context(cert_path, key_path):
"""Validate and activate a new certificate for subsequent TLS handshakes."""
global _SSL_RUNTIME_CONTEXT
global _SSL_RUNTIME_FINGERPRINT
global _SSL_RUNTIME_CERT_PATH
global _SSL_RUNTIME_KEY_PATH
before_fingerprint = _certificate_pair_fingerprint(cert_path, key_path)
replacement = _build_server_ssl_context(cert_path, key_path)
after_fingerprint = _certificate_pair_fingerprint(cert_path, key_path)
if before_fingerprint != after_fingerprint:
raise RuntimeError("Certificate files changed while they were being loaded")
with _SSL_RUNTIME_LOCK:
if _SSL_RUNTIME_CONTEXT is None:
raise RuntimeError("The HTTPS runtime is not initialized")
changed = after_fingerprint != _SSL_RUNTIME_FINGERPRINT
if changed:
_SSL_RUNTIME_CONTEXT = replacement
_SSL_RUNTIME_FINGERPRINT = after_fingerprint
_SSL_RUNTIME_CERT_PATH = cert_path
_SSL_RUNTIME_KEY_PATH = key_path
return changed
def configure_ssl(cert_path, key_path, source="custom"):
"""
Configure SSL with given certificate and key paths.
+72
View File
@@ -249,6 +249,78 @@ def ssl_disable():
return jsonify({"success": False, "message": str(e)}), 500
@auth_bp.route('/api/ssl/reload', methods=['POST'])
@require_auth
def ssl_reload():
"""Reload the configured certificate without restarting the Monitor."""
config = auth_manager.load_ssl_config()
if not config.get("enabled"):
return jsonify({
"success": False,
"code": "ssl_not_enabled",
"message": "HTTPS is not enabled",
}), 400
source = config.get("source", "custom")
cert_info = None
if source == "proxmox":
detection = auth_manager.detect_proxmox_certificates()
if not detection.get("proxmox_available"):
return jsonify({
"success": False,
"code": "certificate_unavailable",
"message": "No Proxmox certificate was detected",
}), 404
cert_path = detection.get("proxmox_cert", "")
key_path = detection.get("proxmox_key", "")
cert_info = detection.get("cert_info")
else:
cert_path = config.get("cert_path", "")
key_path = config.get("key_path", "")
valid, validation_message = auth_manager.validate_certificate_files(cert_path, key_path)
if not valid:
return jsonify({
"success": False,
"code": "certificate_invalid",
"message": validation_message,
}), 400
paths_changed = (
cert_path != config.get("cert_path", "") or
key_path != config.get("key_path", "")
)
if paths_changed:
updated_config = dict(config)
updated_config["cert_path"] = cert_path
updated_config["key_path"] = key_path
if not auth_manager.save_ssl_config(updated_config):
return jsonify({
"success": False,
"code": "config_save_failed",
"message": "Failed to save the renewed certificate paths",
}), 500
try:
changed = auth_manager.reload_server_ssl_context(cert_path, key_path)
except Exception as e:
if paths_changed:
auth_manager.save_ssl_config(config)
return jsonify({
"success": False,
"code": "runtime_reload_failed",
"message": str(e),
}), 409
return jsonify({
"success": True,
"changed": changed,
"cert_path": cert_path,
"key_path": key_path,
"cert_info": cert_info,
})
def _refresh_pve_webhook_for_ssl_change():
"""Helper used by both `ssl_configure` and `ssl_disable`.
+1
View File
@@ -454,6 +454,7 @@ def get_remote_storages():
'used': storage.get('used', 0),
'available': storage.get('available', 0),
'percent': storage.get('percent', 0),
'capacity_known': storage.get('capacity_known', storage.get('total', 0) > 0),
'exclude_health': exclusion.get('exclude_health', 0) == 1,
'exclude_notifications': exclusion.get('exclude_notifications', 0) == 1,
'excluded_at': exclusion.get('excluded_at'),
+7 -21
View File
@@ -79,7 +79,7 @@ from smartctl_resolver import ( # noqa: E402
)
from flask_script_runner import script_runner
import threading
from proxmox_storage_monitor import proxmox_storage_monitor
from proxmox_storage_monitor import classify_storage_state, proxmox_storage_monitor
from flask_terminal_routes import ( # noqa: E402
terminal_bp,
init_terminal_routes,
@@ -5328,25 +5328,14 @@ def _get_proxmox_storage_uncached():
used_gb = round(used / (1024**3), 2)
available_gb = round(available / (1024**3), 2)
# Determine storage status. Sprint 11.6: a remote PBS where the
# user only has DatastoreAdmin on their own namespace reports
# `status=available` + `total=0` — the storage IS reachable, the
# ACL just hides the datastore size. Surface as
# 'namespace_restricted' so the UI can render INFO instead of
# CRITICAL. Real outages still flag (status != available).
if total == 0 and status.lower() == "available" and storage_type == 'pbs':
storage_status = 'namespace_restricted'
elif total == 0:
storage_status = 'error'
elif status.lower() != "available":
storage_status = 'error'
else:
storage_status = 'active'
storage_state = classify_storage_state(storage_type, status, total)
storage_info = {
'name': name,
'type': storage_type,
'status': storage_status, # Usar el status determinado (active o error)
'status': storage_state['status'],
'status_detail': storage_state['status_detail'],
'capacity_known': storage_state['capacity_known'],
'total': total_gb,
'used': used_gb,
'available': available_gb,
@@ -22172,8 +22161,7 @@ if __name__ == '__main__':
from gevent import pywsgi
import ssl
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain(ssl_cert, ssl_key)
ssl_context = auth_manager.create_reloadable_ssl_context(ssl_cert, ssl_key)
# Defensive: silence the ~30-line traceback that gevent
# prints whenever a client sends plain HTTP against this
@@ -22242,9 +22230,7 @@ if __name__ == '__main__':
except ImportError as e:
print(f"[ProxMenux] gevent not available ({e})")
# Fallback: Flask dev server with SSL - flask-sock handles WebSockets
import ssl
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain(ssl_cert, ssl_key)
ssl_context = auth_manager.create_reloadable_ssl_context(ssl_cert, ssl_key)
print("[ProxMenux] Starting Flask server with SSL (using flask-sock for WebSockets)...")
app.run(host='::', port=8008, debug=False, ssl_context=ssl_context, threaded=True)
else:
+46 -9
View File
@@ -19,6 +19,7 @@ from collections import defaultdict
import re
from health_persistence import health_persistence, disk_base_name
from proxmox_known_errors import analyze_oom_event, format_oom_diagnosis
from smartctl_resolver import (
is_usb_disk as resolver_is_usb_disk,
probe_smartctl_json,
@@ -4027,10 +4028,21 @@ class HealthMonitor:
return reason
# Out of memory
if 'out of memory' in line_lower or 'oom_kill' in line_lower:
m = re.search(r'Killed process\s+\d+\s+\(([^)]+)\)', line)
process = m.group(1) if m else 'unknown'
return f'Out of memory - system killed process "{process}" to free RAM'
if any(token in line_lower for token in (
'out of memory', 'oom_kill', 'oom-kill', 'invoked oom-killer', 'oom_reaper'
)):
victim = re.search(r'Killed process\s+\d+\s+\(([^)]+)\)', line, re.IGNORECASE)
if victim:
return f'Memory pressure - kernel killed process "{victim.group(1)}"'
invoker = re.search(r'(?:kernel:\s*)?([^\s:]+)\s+invoked oom-killer', line, re.IGNORECASE)
if invoker:
return (
f'Memory pressure triggered the OOM killer while "{invoker.group(1)}" '
'requested memory; this process is not necessarily the main consumer'
)
return 'Memory pressure triggered the OOM killer; inspect the complete kernel OOM block'
# Kernel panic
if 'kernel panic' in line_lower:
@@ -4152,6 +4164,9 @@ class HealthMonitor:
if result_recent.returncode == 0:
recent_lines = result_recent.stdout.strip().split('\n')
previous_lines = result_previous.stdout.strip().split('\n') if result_previous.returncode == 0 else []
recent_oom_analysis = analyze_oom_event(result_recent.stdout)
recent_oom_reason = format_oom_diagnosis(recent_oom_analysis)
processed_oom_patterns = set()
recent_patterns = defaultdict(int)
previous_patterns = defaultdict(int)
@@ -4172,7 +4187,22 @@ class HealthMonitor:
continue
# Normalize to a pattern for grouping
pattern = self._normalize_log_pattern(line)
is_oom_line = any(token in line.lower() for token in (
'out of memory', 'oom_kill', 'oom-kill',
'invoked oom-killer', 'oom_reaper'
))
if is_oom_line and recent_oom_analysis:
scope = recent_oom_analysis.get('scope') or 'unknown'
scope_id = recent_oom_analysis.get('ctid') \
or recent_oom_analysis.get('cgroup_path') \
or 'unknown'
victim = recent_oom_analysis.get('victim_process') or 'unknown'
pattern = f'oom_event_{scope}_{scope_id}_{victim}'
if pattern in processed_oom_patterns:
continue
processed_oom_patterns.add(pattern)
else:
pattern = self._normalize_log_pattern(line)
if severity == 'CRITICAL':
pattern_hash = hashlib.md5(pattern.encode()).hexdigest()[:8]
@@ -4213,7 +4243,10 @@ class HealthMonitor:
if severity == 'CRITICAL':
critical_errors_found[pattern] = line
# Build a human-readable reason from the raw log line
enriched_reason = self._enrich_critical_log_reason(line)
if is_oom_line and recent_oom_reason:
enriched_reason = recent_oom_reason
else:
enriched_reason = self._enrich_critical_log_reason(line)
# Append SMART context to the reason if we checked it
if smart_status_for_log == 'PASSED':
@@ -4230,9 +4263,13 @@ class HealthMonitor:
category='logs',
severity=severity,
reason=enriched_reason,
details={'pattern': pattern, 'raw_line': line[:200],
'smart_status': smart_status_for_log,
'dismissable': True}
details={
'pattern': pattern,
'raw_line': line[:200],
'smart_status': smart_status_for_log,
'oom_analysis': recent_oom_analysis if is_oom_line else None,
'dismissable': True,
}
)
# Cross-reference: filesystem errors also belong in the disks category
+59
View File
@@ -25,6 +25,8 @@ from queue import Queue
from typing import Optional, Dict, Any, Tuple, Callable
from pathlib import Path
from proxmox_known_errors import analyze_oom_event, format_oom_diagnosis
# ─── Shared State for Cross-Watcher Coordination ──────────────────
@@ -489,6 +491,12 @@ class JournalWatcher:
self._recent_events: Dict[str, float] = {}
self._dedup_window = 30 # seconds
# Linux emits an OOM diagnosis as a multi-line kernel block. Buffer it
# until the authoritative `Killed process` line arrives so the alert
# can distinguish a host OOM from a memory-cgroup/LXC limit.
self._oom_lines = []
self._oom_started_at = 0.0
# 24h anti-cascade for disk I/O + filesystem errors. The dict
# key includes a tier suffix (`sdh:warning`, `sdh:critical`)
# so a disk in WARNING cooldown can still escalate to CRITICAL
@@ -830,6 +838,57 @@ class JournalWatcher:
# Only process messages from kernel or systemd (not app-level logs)
if syslog_id and syslog_id not in ('kernel', 'systemd', 'systemd-coredump', ''):
return
now = time.time()
if self._oom_lines and now - self._oom_started_at > 15:
self._oom_lines = []
self._oom_started_at = 0.0
starts_oom_block = bool(re.search(
r'invoked oom-killer|oom-kill:constraint=', msg, re.IGNORECASE
))
ends_oom_block = bool(re.search(
r'(?:Memory cgroup )?Out of memory:\s+Killed process', msg, re.IGNORECASE
))
if starts_oom_block and not self._oom_lines:
self._oom_lines = [msg]
self._oom_started_at = now
return
if self._oom_lines:
self._oom_lines.append(msg)
if len(self._oom_lines) > 500:
self._oom_lines = self._oom_lines[-500:]
if ends_oom_block:
analysis = analyze_oom_event('\n'.join(self._oom_lines))
reason = format_oom_diagnosis(analysis)
if not reason:
reason = f'Out of memory killer activated\n{msg[:300]}'
ctid = analysis.get('ctid') if analysis else ''
victim = analysis.get('victim_process') if analysis else ''
entity_id = f'lxc_{ctid}' if ctid else f'oom_{victim or "unknown"}'
self._emit(
'system_problem',
'CRITICAL',
{
'reason': reason,
'hostname': self._hostname,
'oom_analysis': analysis or {},
},
entity='node',
entity_id=entity_id,
)
self._oom_lines = []
self._oom_started_at = 0.0
return
# `Call Trace:` is part of the buffered OOM evidence, not a second
# independent kernel fault requiring another notification.
if re.search(r'^Call Trace:', msg, re.IGNORECASE):
return
# Filter out normal kernel messages that are NOT problems
_KERNEL_NOISE = [
+133 -5
View File
@@ -18,6 +18,121 @@ Each entry includes:
import re
from typing import Optional, Dict, Any, List
def analyze_oom_event(text: str) -> Optional[Dict[str, Any]]:
"""Extract the scope and victim from a complete Linux OOM block.
The process on the ``invoked oom-killer`` line is only the allocation
trigger. The authoritative scope is carried by ``constraint`` and
``oom_memcg``; the actual victim is carried by ``Killed process``.
"""
if not text or not re.search(
r'invoked oom-killer|oom-kill:|memory cgroup out of memory|out of memory: killed process',
text,
re.IGNORECASE,
):
return None
result: Dict[str, Any] = {
'scope': 'unknown',
'constraint': '',
'cgroup_path': '',
'ctid': '',
'invoker': '',
'victim_process': '',
'victim_pid': '',
'memory_usage_kib': None,
'memory_limit_kib': None,
'swap_usage_kib': None,
'swap_limit_kib': None,
}
constraint = re.search(r'constraint=([A-Z0-9_]+)', text, re.IGNORECASE)
if constraint:
result['constraint'] = constraint.group(1).upper()
cgroup = re.search(r'oom_memcg=([^,\s]+)', text, re.IGNORECASE)
if not cgroup:
cgroup = re.search(r'Memory cgroup stats for\s+([^:\s]+)', text, re.IGNORECASE)
if cgroup:
result['cgroup_path'] = cgroup.group(1)
ctid = re.search(r'/lxc/(\d+)\b', result['cgroup_path'] or text, re.IGNORECASE)
if ctid:
result['ctid'] = ctid.group(1)
result['scope'] = 'lxc'
elif result['constraint'] == 'CONSTRAINT_MEMCG' or re.search(
r'memory cgroup out of memory', text, re.IGNORECASE
):
result['scope'] = 'memory_cgroup'
elif result['constraint']:
result['scope'] = 'host'
invoker = re.search(r'\b([A-Za-z0-9_.+/-]+)\s+invoked oom-killer', text, re.IGNORECASE)
if invoker:
result['invoker'] = invoker.group(1)
victim = re.search(r'Killed process\s+(\d+)\s+\(([^)]+)\)', text, re.IGNORECASE)
if victim:
result['victim_pid'] = victim.group(1)
result['victim_process'] = victim.group(2)
memory = re.search(
r'memory:\s+usage\s+(\d+)kB,\s+limit\s+(\d+)kB', text, re.IGNORECASE
)
if memory:
result['memory_usage_kib'] = int(memory.group(1))
result['memory_limit_kib'] = int(memory.group(2))
swap = re.search(
r'swap:\s+usage\s+(\d+)kB,\s+limit\s+(\d+)kB', text, re.IGNORECASE
)
if swap:
result['swap_usage_kib'] = int(swap.group(1))
result['swap_limit_kib'] = int(swap.group(2))
return result
def format_oom_diagnosis(analysis: Optional[Dict[str, Any]]) -> str:
"""Return a concise evidence-based diagnosis for an OOM analysis."""
if not analysis:
return ''
lines: List[str] = []
scope = analysis.get('scope')
ctid = analysis.get('ctid')
if scope == 'lxc' and ctid:
lines.append(f'OOM scope: LXC {ctid} memory cgroup (not a host-wide OOM)')
elif scope == 'memory_cgroup':
path = analysis.get('cgroup_path') or 'unknown cgroup'
lines.append(f'OOM scope: memory cgroup {path} (not a host-wide OOM)')
elif scope == 'host':
lines.append('OOM scope: host/kernel memory scope')
else:
lines.append('OOM scope: not established from the available log lines')
usage = analysis.get('memory_usage_kib')
limit = analysis.get('memory_limit_kib')
if usage is not None and limit is not None:
lines.append(f'Cgroup memory: {usage / 1024:.1f} MiB used of {limit / 1024:.1f} MiB')
swap_usage = analysis.get('swap_usage_kib')
swap_limit = analysis.get('swap_limit_kib')
if swap_usage is not None and swap_limit is not None:
lines.append(f'Cgroup swap: {swap_usage / 1024:.1f} MiB used of {swap_limit / 1024:.1f} MiB')
victim = analysis.get('victim_process')
victim_pid = analysis.get('victim_pid')
if victim:
lines.append(f'Killed process: {victim}' + (f' (PID {victim_pid})' if victim_pid else ''))
invoker = analysis.get('invoker')
if invoker and invoker != victim:
lines.append(f'Allocation trigger: {invoker} (not necessarily the largest consumer)')
return '\n'.join(lines)
# Known error patterns with causes and solutions
PROXMOX_KNOWN_ERRORS: List[Dict[str, Any]] = [
# ==================== SUBSCRIPTION/LICENSE ====================
@@ -169,11 +284,11 @@ PROXMOX_KNOWN_ERRORS: List[Dict[str, Any]] = [
},
{
"pattern": r"out of memory|OOM.*kill|cannot allocate memory|memory.*exhausted",
"cause": "System or VM ran out of memory",
"cause_detailed": "The Linux OOM (Out Of Memory) killer terminated a process to free memory. This indicates memory pressure from overcommitment or memory leaks.",
"cause": "The kernel invoked the OOM killer under memory pressure",
"cause_detailed": "Linux could not satisfy a memory allocation in the relevant host, cgroup, cpuset or NUMA scope. The process named as having invoked the OOM killer only triggered the allocation; it is not necessarily the largest consumer or the process that was killed. The complete OOM block is required to identify the scope, victim and likely cause.",
"severity": "critical",
"solution": "Increase memory allocation or reduce VM memory usage",
"solution_detailed": "1. Check what was killed: dmesg | grep -i oom\n2. Review memory usage: free -h\n3. Check balloon driver status for VMs\n4. Consider adding swap or RAM\n5. Review VM memory allocations for overcommitment",
"solution": "Inspect the complete OOM event and current host/cgroup memory before changing allocations",
"solution_detailed": "1. Read the complete kernel OOM block, including 'Killed process', 'Mem-Info' and task rows\n2. Determine whether it was a host-wide or memory-cgroup OOM\n3. Review free -h, swap, CommitLimit/Committed_AS and active VM/LXC allocations\n4. On ZFS hosts, compare ARC size and c_max with the configured zfs_arc_max\n5. Adjust the confirmed consumer, ARC cap or workload only after identifying the exhausted scope",
"category": "memory"
},
@@ -316,6 +431,10 @@ def get_error_context(text: str, category: Optional[str] = None, detail_level: s
error = find_matching_error(text, category)
if not error:
return None
oom_diagnosis = ''
if error.get('category') == 'memory':
oom_diagnosis = format_oom_diagnosis(analyze_oom_event(text))
# NOTE: we intentionally do NOT emit a "Severity:" line here.
# The catalogue's severity is the *typical* severity of a class
@@ -329,7 +448,10 @@ def get_error_context(text: str, category: Optional[str] = None, detail_level: s
# carried by the notification's own severity field; repeating a
# different value here is noise at best, misinformation at worst.
if detail_level == "minimal":
return f"Known issue: {error['cause']}"
result = f"Known issue: {error['cause']}"
if oom_diagnosis:
result += f"\n{oom_diagnosis}"
return result
elif detail_level == "standard":
lines = [
@@ -339,6 +461,9 @@ def get_error_context(text: str, category: Optional[str] = None, detail_level: s
]
if error.get("url"):
lines.append(f" Docs: {error['url']}")
if oom_diagnosis:
lines.append(" Event analysis:")
lines.extend(f" {line}" for line in oom_diagnosis.splitlines())
return "\n".join(lines)
else: # detailed
@@ -349,6 +474,9 @@ def get_error_context(text: str, category: Optional[str] = None, detail_level: s
]
if error.get("url"):
lines.append(f" Documentation: {error['url']}")
if oom_diagnosis:
lines.append(" Event analysis:")
lines.extend(f" {line}" for line in oom_diagnosis.splitlines())
return "\n".join(lines)
+33 -20
View File
@@ -12,6 +12,33 @@ import time
from typing import Dict, List, Any, Optional
def classify_storage_state(storage_type: str, status: str, total: int) -> Dict[str, Any]:
"""Classify reachability independently from reported capacity."""
normalized_status = str(status or 'unknown').strip().lower()
normalized_type = str(storage_type or 'unknown').strip().lower()
capacity_known = total > 0
if normalized_status != 'available':
return {
'status': 'error',
'status_detail': normalized_status or 'unknown',
'capacity_known': capacity_known,
}
if not capacity_known and normalized_type == 'pbs':
return {
'status': 'namespace_restricted',
'status_detail': 'namespace_restricted',
'capacity_known': False,
}
return {
'status': 'active',
'status_detail': 'available' if capacity_known else 'capacity_unreported',
'capacity_known': capacity_known,
}
class ProxmoxStorageMonitor:
"""Monitor Proxmox storage configuration and status"""
@@ -177,28 +204,13 @@ class ProxmoxStorageMonitor:
'percent': round(percent, 2),
'node': node
}
# Check if storage is available.
#
# "jc-pbs-friendly" mode (Sprint 11.6): a remote PBS where
# the user only has DatastoreAdmin on their own namespace
# reports `status=available` + `total=0` — the storage IS
# reachable, the user just can't list the datastore size.
# Treat that combination as INFO (namespace-restricted)
# instead of CRITICAL so we don't spam the operator with
# "almacenamiento no disponible" every poll. Real outages
# still flag because they come back with `status != available`.
if total == 0 and status.lower() == "available" and storage_type == 'pbs':
storage_info['status'] = 'namespace_restricted'
storage_info['status_detail'] = 'namespace_restricted'
state = classify_storage_state(storage_type, status, total)
storage_info.update(state)
if state['status'] in ('active', 'namespace_restricted'):
available_storages.append(storage_info)
elif total == 0 or status.lower() != "available":
storage_info['status'] = 'error'
storage_info['status_detail'] = 'unavailable' if total == 0 else status
unavailable_storages.append(storage_info)
else:
storage_info['status'] = 'active'
available_storages.append(storage_info)
unavailable_storages.append(storage_info)
# Check for configured storages that are completely missing
for storage_name, storage_config in self.configured_storages.items():
@@ -212,6 +224,7 @@ class ProxmoxStorageMonitor:
'used': 0,
'available': 0,
'percent': 0,
'capacity_known': False,
'node': local_node
})
+37 -26
View File
@@ -39,12 +39,12 @@
"A ZFS pool with this name already exists.": "Ein ZFS-Pool mit diesem Namen ist bereits vorhanden.",
"A ZFS pool with this name already exists:": "Ein ZFS-Pool mit diesem Namen existiert bereits:",
"A complete restore will:": "Eine vollständige Wiederherstellung führt zu Folgendem:",
"A gasket DKMS registration is still present:": "Eine Dichtung DKMS-Registrierung ist noch vorhanden:",
"A gasket DKMS registration is still present:": "Eine gasket-DKMS-Registrierung ist noch vorhanden:",
"A host reboot is required after this change.": "Nach dieser Änderung ist ein Neustart des Hosts erforderlich.",
"A host reboot is required before starting the VM. Reboot now?": "Vor dem Starten der VM ist ein Host-Neustart erforderlich. Jetzt neu starten?",
"A job with this ID already exists.": "Ein Job mit dieser ID existiert bereits.",
"A keyfile is installed at:": "Eine Schlüsseldatei ist installiert unter:",
"A legacy gasket-dkms package was found on this host, but no Coral M.2 / PCIe hardware is present.": "Auf diesem Host wurde ein Legacy-Gasket-DKMS-Paket gefunden, es ist jedoch keine Coral M.2/PCIe-Hardware vorhanden.",
"A legacy gasket-dkms package was found on this host, but no Coral M.2 / PCIe hardware is present.": "Auf diesem Host wurde ein veraltetes gasket-dkms-Paket gefunden, es ist jedoch keine Coral M.2/PCIe-Hardware vorhanden.",
"A new ProxMenux version is available:": "Eine neue ProxMenux-Version ist verfügbar:",
"A new kernel is staged for the next boot:": "Ein neuer Kernel wird für den nächsten Start bereitgestellt:",
"A newer version is available:": "Eine neuere Version ist verfügbar:",
@@ -374,6 +374,12 @@
"Bandwidth test completed successfully": "Bandbreitentest erfolgreich abgeschlossen",
"Base VM created with ID": "Basis-VM mit ID erstellt",
"Bashrc customization completed": "Bashrc-Anpassung abgeschlossen",
"Bash prompt path": "Pfadanzeige der Bash-Eingabeaufforderung",
"Choose how the current directory is shown in the Bash prompt:": "Wählen Sie, wie das aktuelle Verzeichnis in der Bash-Eingabeaufforderung angezeigt wird:",
"Current directory only": "Nur aktuelles Verzeichnis",
"Full path": "Vollständiger Pfad",
"The new prompt will be used in new terminal sessions.": "Die neue Eingabeaufforderung wird in neuen Terminalsitzungen verwendet.",
"To apply it to the current shell now, run:": "Um sie jetzt auf die aktuelle Shell anzuwenden, führen Sie Folgendes aus:",
"Basic Settings": "Grundeinstellungen",
"Basic Utilities": "Grundlegende Dienstprogramme",
"Before making any changes, we'll create a safety backup.": "Bevor wir Änderungen vornehmen, erstellen wir ein Sicherheitsbackup.",
@@ -415,7 +421,7 @@
"Bridges analyzed": "Brücken analysiert",
"Broken gasket-dkms package state recovered.": "Der Status des defekten „gasket-dkms“-Pakets wurde wiederhergestellt.",
"Browse manually (advanced)...": "Manuell durchsuchen (erweitert)...",
"Build and install the gasket and apex kernel modules (DKMS)": "Erstellen und installieren Sie die Dichtungs- und Apex-Kernel-Module (DKMS).",
"Build and install the gasket and apex kernel modules (DKMS)": "gasket- und apex-Kernelmodule erstellen und installieren (DKMS)",
"Build dependencies installed.": "Build-Abhängigkeiten installiert.",
"CHANGES APPLIED SUCCESSFULLY": "ÄNDERUNGEN WURDEN ERFOLGREICH ANGEWENDET",
"CIFS Client Tools: AVAILABLE": "CIFS-Client-Tools: VERFÜGBAR",
@@ -599,7 +605,7 @@
"Cleanup Complete": "Bereinigung abgeschlossen",
"Cleanup completed. A reboot is recommended to fully apply pending kernel package configurations.": "Bereinigung abgeschlossen.Ein Neustart wird empfohlen, um ausstehende Kernelpaketkonfigurationen vollständig zu übernehmen.",
"Cleanup finished": "Aufräumen abgeschlossen",
"Cleanup legacy gasket-dkms": "Bereinigen Sie ältere Dichtungs-DKMs",
"Cleanup legacy gasket-dkms": "Veraltetes gasket-dkms bereinigen",
"Cleanup partial VM?": "Teilweise VM bereinigen?",
"Clear configured target": "Konfiguriertes Ziel löschen",
"Clear pool error state": "Pool-Fehlerstatus löschen",
@@ -851,12 +857,12 @@
"Copying installer to container": "Installationsprogramm in Container kopieren",
"Copying sources to": "Kopieren von Quellen nach",
"Coral APT repository ready.": "Coral APT-Repository bereit.",
"Coral Actions": "Korallenaktionen",
"Coral M.2 / PCIe detected — installing gasket and apex kernel modules...": "Coral M.2 / PCIe erkannt Installation von Dichtungs- und Apex-Kernelmodulen ...",
"Coral Actions": "Coral-Aktionen",
"Coral M.2 / PCIe detected — installing gasket and apex kernel modules...": "Coral M.2/PCIe erkannt gasket- und apex-Kernelmodule werden installiert ...",
"Coral M.2 Apex configuration added - device ready": "Coral M.2 Apex-Konfiguration hinzugefügt Gerät bereit",
"Coral M.2 Apex configuration added - device will be available after reboot": "Coral M.2 Apex-Konfiguration hinzugefügt Gerät ist nach dem Neustart verfügbar",
"Coral M.2 Apex detected, configuring...": "Coral M.2 Apex erkannt, konfiguriert...",
"Coral TPU Installation": "Korallen-TPU-Installation",
"Coral TPU Installation": "Coral-TPU-Installation",
"Coral TPU Uninstall": "Coral TPU-Deinstallation",
"Coral TPU device nodes detected with correct group (apex).": "Coral TPU-Geräteknoten wurden mit der richtigen Gruppe (Apex) erkannt.",
"Coral TPU driver installed successfully inside the container.": "Der Coral TPU-Treiber wurde erfolgreich im Container installiert.",
@@ -869,7 +875,7 @@
"Coral USB runtime installed. No reboot required.": "Coral USB-Runtime installiert. Kein Neustart erforderlich.",
"Coral hardware configuration completed for container": "Coral-Hardwarekonfiguration für Container abgeschlossen",
"Coral kernel modules unloaded.": "Coral-Kernel-Module wurden entladen.",
"Coral packages purged.": "Korallenpakete gelöscht.",
"Coral packages purged.": "Coral-Pakete vollständig entfernt.",
"Coral uninstallation completed.": "Coral-Deinstallation abgeschlossen.",
"Core Proxmox packages reinstalled successfully": "Kern-Proxmox-Pakete wurden erfolgreich neu installiert",
"Core packages": "Kernpakete",
@@ -879,7 +885,7 @@
"Could not authorize the key via 'pct exec' on": "Der Schlüssel konnte nicht über „pct exec“ autorisiert werden",
"Could not back up the existing auth.json": "Die vorhandene auth.json konnte nicht gesichert werden",
"Could not change VM virtual display to vga: std": "Die virtuelle VM-Anzeige konnte nicht in vga: std geändert werden",
"Could not clone any gasket-driver repository. Check your internet connection and": "Es konnte kein Dichtungstreiber-Repository geklont werden. Überprüfen Sie Ihre Internetverbindung und",
"Could not clone any gasket-driver repository. Check your internet connection and": "Es konnte kein gasket-driver-Repository geklont werden. Überprüfen Sie Ihre Internetverbindung und",
"Could not configure IOMMU kernel parameters automatically. Configure manually and reboot.": "IOMMU-Kernelparameter konnten nicht automatisch konfiguriert werden. Manuell konfigurieren und neu starten.",
"Could not copy the PVE keyfile into place. Check permissions on:": "Die PVE-Schlüsseldatei konnte nicht kopiert werden.Überprüfen Sie die Berechtigungen für:",
"Could not copy the keyfile into place.": "Die Schlüsseldatei konnte nicht kopiert werden.",
@@ -1136,7 +1142,7 @@
"Detected RAM:": "Erkannter RAM:",
"Detected a mounted directory from host. Setting up shared group...": "Ein gemountetes Verzeichnis vom Host erkannt. Geteilte Gruppe einrichten...",
"Detected backups — newest first:": "Erkannte Backups Neueste zuerst:",
"Detected broken gasket-dkms package state:": "Status des defekten Gasket-DKMS-Pakets erkannt:",
"Detected broken gasket-dkms package state:": "Status des defekten gasket-dkms-Pakets erkannt:",
"Detected existing Samba user:": "Vorhandenen Samba-Benutzer erkannt:",
"Detected filesystem:": "Erkanntes Dateisystem:",
"Detected nftables - using nftables ban action": "Nftables erkannt Nftables-Verbotsaktion wird verwendet",
@@ -2380,8 +2386,8 @@
"Launching GPU passthrough assistant for VM": "GPU-Passthrough-Assistent für VM wird gestartet",
"Legacy PVE 8 .list files commented or not present": "Ältere PVE 8 .list-Dateien sind kommentiert oder nicht vorhanden",
"Legacy ceph.list commented or not present": "Die alte ceph.list wurde kommentiert oder ist nicht vorhanden",
"Legacy gasket-dkms cleanup could not be verified as complete.": "Die Bereinigung der alten Gasket-DKMS konnte nicht als abgeschlossen verifiziert werden.",
"Legacy gasket-dkms detected": "Ältere Dichtungs-DKMs erkannt",
"Legacy gasket-dkms cleanup could not be verified as complete.": "Die Bereinigung des veralteten gasket-dkms-Pakets konnte nicht als abgeschlossen verifiziert werden.",
"Legacy gasket-dkms detected": "Veraltetes gasket-dkms erkannt",
"Legacy network tools (e.g., ifconfig)": "Ältere Netzwerk-Tools (z. B. ifconfig)",
"Legend:": "Legende:",
"Let's review your current network configuration.": "Lassen Sie uns Ihre aktuelle Netzwerkkonfiguration überprüfen.",
@@ -2786,7 +2792,7 @@
"No Changes Needed": "Keine Änderungen erforderlich",
"No Cleanup Needed": "Keine Reinigung erforderlich",
"No Controller/NVMe selected for now.": "Derzeit ist kein Controller/NVMe ausgewählt.",
"No Coral Detected": "Keine Koralle entdeckt",
"No Coral Detected": "Kein Coral erkannt",
"No Coral TPU device was found on this host (neither PCIe/M.2 nor USB).": "Auf diesem Host wurde kein Coral TPU-Gerät gefunden (weder PCIe/M.2 noch USB).",
"No Custom Logos Found": "Keine benutzerdefinierten Logos gefunden",
"No Disk Images Found": "Keine Disk-Images gefunden",
@@ -2922,7 +2928,7 @@
"No folders found in /mnt. Please create a new folder.": "Keine Ordner in /mnt gefunden. Bitte erstellen Sie einen neuen Ordner.",
"No folders found inside /mnt in the CT.": "Keine Ordner in /mnt im CT gefunden.",
"No format-safe disks are available.": "Es sind keine formatsicheren Datenträger verfügbar.",
"No gasket DKMS registrations remain.": "Es verbleiben keine Dichtungs-DKMS-Registrierungen.",
"No gasket DKMS registrations remain.": "Es sind keine gasket-DKMS-Registrierungen mehr vorhanden.",
"No group creation required — uses world-writable sticky bit permissions.": "Keine Gruppenerstellung erforderlich verwendet weltweit beschreibbare Sticky-Bit-Berechtigungen.",
"No host VFIO reconfiguration expected": "Keine Host-VFIO-Neukonfiguration erwartet",
"No host VFIO/native binding changes were required.": "Es waren keine Host-VFIO/native Bindungsänderungen erforderlich.",
@@ -3132,7 +3138,7 @@
"PCI passthrough, TPM state, cloud-init, snapshots, Proxmox-specific hooks": "PCI-Passthrough, TPM-Status, Cloud-Init, Snapshots, Proxmox-spezifische Hooks",
"PCI reset method": "PCI-Reset-Methode",
"PCIe GPU passthrough requires:": "PCIe-GPU-Passthrough erfordert:",
"PCIe/M.2 gasket-dkms": "PCIe/M.2-Dichtung-dkms",
"PCIe/M.2 gasket-dkms": "PCIe/M.2 gasket-dkms",
"POSIX ACLs applied (access + default for inheritance).": "POSIX-ACLs angewendet (Zugriff + Standard für Vererbung).",
"PVE application manager updated": "PVE-Anwendungsmanager aktualisiert",
"PVE cache regenerated": "PVE-Cache neu generiert",
@@ -3374,8 +3380,8 @@
"Proxmox web interface: Datacenter > Storage > Add > ZFS": "Proxmox-Weboberfläche: Datencenter > Speicher > Hinzufügen > ZFS",
"Proxmox web interface: Datacenter > Storage > Add > iSCSI": "Proxmox-Weboberfläche: Rechenzentrum > Speicher > Hinzufügen > iSCSI",
"Pulling latest changes from GitHub...": "Aktuelle Änderungen von GitHub abrufen...",
"Purge the gasket-dkms package": "Bereinigen Sie das Gasket-Dkms-Paket",
"Purging gasket-dkms package...": "Gasket-dkms-Paket spülen...",
"Purge the gasket-dkms package": "gasket-dkms-Paket vollständig entfernen",
"Purging gasket-dkms package...": "gasket-dkms-Paket wird vollständig entfernt ...",
"Purging log2ram apt package...": "Log2ram-Apt-Paket wird gelöscht...",
"Quick health check (PASSED / FAILED)": "Schneller Gesundheitscheck (bestanden / nicht bestanden)",
"Quick health status — overall SMART result + key attributes": "Schneller Gesundheitszustand Gesamt-SMART-Ergebnis + Schlüsselattribute",
@@ -3511,7 +3517,7 @@
"Remove Secure Gateway? State will be preserved.": "Secure Gateway entfernen? Der Zustand bleibt erhalten.",
"Remove custom paths": "Benutzerdefinierte Pfade entfernen",
"Remove disk references from affected VM(s)/CT(s) config": "Entfernen Sie Festplattenverweise aus der Konfiguration der betroffenen VM(s)/CT(s).",
"Remove every registered gasket DKMS version": "Entfernen Sie jede registrierte Dichtungs-DKMS-Version",
"Remove every registered gasket DKMS version": "Alle registrierten gasket-DKMS-Versionen entfernen",
"Remove iSCSI Storage": "Entfernen Sie den iSCSI-Speicher",
"Remove iSCSI storage definition:": "Entfernen Sie die iSCSI-Speicherdefinition:",
"Remove invalid port": "Entfernen Sie den ungültigen Port",
@@ -3551,13 +3557,13 @@
"Removing OpenVSwitch...": "OpenVSwitch wird entfernt...",
"Removing ProxMenux persistent NIC .link files...": "Permanente ProxMenux-NIC-.Link-Dateien werden entfernt...",
"Removing VFIO ownership for selected GPU(s)...": "VFIO-Besitz für ausgewählte GPU(s) wird entfernt...",
"Removing any pre-existing gasket-dkms package...": "Entfernen aller bereits vorhandenen Gasket-DKMS-Pakete ...",
"Removing any pre-existing gasket-dkms package...": "Alle bereits vorhandenen gasket-dkms-Pakete werden entfernt ...",
"Removing conflicting utilities...": "In Konflikt stehende Dienstprogramme werden entfernt...",
"Removing entropy generation optimization...": "Optimierung der Entropieerzeugung wird entfernt...",
"Removing every registered gasket DKMS version...": "Entfernen aller registrierten Dichtungen der DKMS-Version ...",
"Removing every registered gasket DKMS version...": "Alle registrierten gasket-DKMS-Versionen werden entfernt ...",
"Removing filesystem signatures...": "Dateisystemsignaturen werden entfernt...",
"Removing from /etc/fstab...": "Aus /etc/fstab entfernen...",
"Removing gasket DKMS modules...": "Dichtung DKMS-Module entfernen...",
"Removing gasket DKMS modules...": "gasket-DKMS-Module werden entfernt ...",
"Removing gateway...": "Gateway wird entfernt...",
"Removing guest agent...": "Gastagent wird entfernt...",
"Removing invalid configurations...": "Ungültige Konfigurationen werden entfernt...",
@@ -4482,7 +4488,7 @@
"This will reinstall the Stable version from the main branch and disable beta update checks.\n\nContinue?": "Dadurch wird die stabile Version aus dem Hauptzweig neu installiert und Beta-Update-Prüfungen deaktiviert.\n\nWeitermachen?",
"This will remove NVIDIA drivers and related configuration. Do you want to continue?": "Dadurch werden NVIDIA-Treiber und die zugehörige Konfiguration entfernt. Möchten Sie fortfahren?",
"This will remove and reinstall Lynis from the latest GitHub source. Continue?": "Dadurch wird Lynis von der neuesten GitHub-Quelle entfernt und neu installiert. Weitermachen?",
"This will remove the Coral TPU drivers (gasket DKMS + libedgetpu) and related configuration. Any LXC container with apex passthrough will lose access to /dev/apex_* after reboot. Continue?": "Dadurch werden die Coral TPU-Treiber (DKMS + libedgetpu) und die zugehörige Konfiguration entfernt. Jeder LXC-Container mit Apex-Passthrough verliert nach dem Neustart den Zugriff auf /dev/apex_*. Weitermachen?",
"This will remove the Coral TPU drivers (gasket DKMS + libedgetpu) and related configuration. Any LXC container with apex passthrough will lose access to /dev/apex_* after reboot. Continue?": "Dadurch werden die Coral TPU-Treiber (gasket DKMS + libedgetpu) und die zugehörige Konfiguration entfernt. Jeder LXC-Container mit apex-Passthrough verliert nach dem Neustart den Zugriff auf /dev/apex_*. Fortfahren?",
"This will remove the mount from /etc/fstab and delete credentials if present.": "Dadurch wird der Mount aus /etc/fstab entfernt und Anmeldeinformationen gelöscht, falls vorhanden.",
"This will remove the mount from /etc/fstab.": "Dadurch wird der Mount aus /etc/fstab entfernt.",
"This will restart the network service and may cause a brief disconnection. Continue?": "Dadurch wird der Netzwerkdienst neu gestartet und es kann zu einer kurzen Unterbrechung der Verbindung kommen. Weitermachen?",
@@ -5016,8 +5022,8 @@
"fail2ban-client could not communicate with the server": "fail2ban-client konnte nicht mit dem Server kommunizieren",
"fail2ban-client successfully communicated with the server": "fail2ban-client hat erfolgreich mit dem Server kommuniziert",
"failed:": "fehlgeschlagen:",
"feranick fork unreachable. Falling back to google/gasket-driver...": "Feranick-Gabel nicht erreichbar. Zurückgreifen auf google/gasket-driver...",
"feranick/gasket-driver cloned (actively maintained, kernel 6.12+ ready).": "Feranick/Gasket-Treiber geklont (aktiv gewartet, Kernel 6.12+ bereit).",
"feranick fork unreachable. Falling back to google/gasket-driver...": "Der feranick-Fork ist nicht erreichbar. Es wird auf google/gasket-driver zurückgegriffen ...",
"feranick/gasket-driver cloned (actively maintained, kernel 6.12+ ready).": "feranick/gasket-driver geklont (aktiv gepflegt, für Kernel 6.12+ vorbereitet).",
"file?": "Datei?",
"files": "Dateien",
"files/folders": "Dateien/Ordner",
@@ -5034,7 +5040,7 @@
"fstab entry exists": "fstab-Eintrag vorhanden",
"fstab line:": "fstab-Zeile:",
"fstab references UUIDs/devices not present on this host:": "fstab verweist auf UUIDs/Geräte, die auf diesem Host nicht vorhanden sind:",
"gasket DKMS entries removed.": "Dichtung DKMS-Einträge entfernt.",
"gasket DKMS entries removed.": "gasket-DKMS-Einträge entfernt.",
"gasket-dkms has been fully removed from this system.": "„gasket-dkms“ wurde vollständig aus diesem System entfernt.",
"gasket-dkms is still reported by dpkg in state:": "„gasket-dkms“ wird immer noch von dpkg im Status gemeldet:",
"gawk installed": "gawk installiert",
@@ -5317,5 +5323,10 @@
"⚠ Disk data will NOT be erased.": "⚠ Festplattendaten werden NICHT gelöscht.",
"⚠ Disk will be unmounted and removed from /etc/fstab.": "⚠ Die Festplatte wird ausgehängt und aus /etc/fstab entfernt.",
"⚠ The /etc/fstab entry will be removed.": "⚠ Der /etc/fstab-Eintrag wird entfernt.",
"⚠ The disk will be unmounted.": "⚠ Die Festplatte wird ausgehängt."
"⚠ The disk will be unmounted.": "⚠ Die Festplatte wird ausgehängt.",
"Conflicting ZFS ARC settings detected in:": "Widersprüchliche ZFS-ARC-Einstellungen erkannt in:",
"Conflicting ZFS ARC settings backed up and reconciled:": "Widersprüchliche ZFS-ARC-Einstellungen gesichert und bereinigt:",
"Failed to reconcile conflicting ZFS ARC settings.": "Widersprüchliche ZFS-ARC-Einstellungen konnten nicht bereinigt werden.",
"External ZFS ARC settings restored:": "Externe ZFS-ARC-Einstellungen wiederhergestellt:",
"External ZFS configuration changed after the ProxMenux migration; current file and backup preserved:": "Die externe ZFS-Konfiguration wurde nach der ProxMenux-Migration geändert; aktuelle Datei und Sicherung wurden beibehalten:"
}
+61 -50
View File
@@ -39,12 +39,12 @@
"A ZFS pool with this name already exists.": "Ya existe un grupo ZFS con este nombre.",
"A ZFS pool with this name already exists:": "Ya existe un grupo ZFS con este nombre:",
"A complete restore will:": "Una restauración completa:",
"A gasket DKMS registration is still present:": "Todavía hay un registro DKMS de junta presente:",
"A gasket DKMS registration is still present:": "Todavía existe un registro de gasket en DKMS:",
"A host reboot is required after this change.": "Es necesario reiniciar el host después de este cambio.",
"A host reboot is required before starting the VM. Reboot now?": "Es necesario reiniciar el host antes de iniciar la VM. ¿Reiniciar ahora?",
"A job with this ID already exists.": "Ya existe un trabajo con este ID.",
"A keyfile is installed at:": "un archivo de claves está instalado en:",
"A legacy gasket-dkms package was found on this host, but no Coral M.2 / PCIe hardware is present.": "Se encontró un paquete de junta-dkms heredado en este host, pero no hay hardware Coral M.2/PCIe.",
"A legacy gasket-dkms package was found on this host, but no Coral M.2 / PCIe hardware is present.": "Se ha encontrado un paquete heredado gasket-dkms en este host, pero no hay ningún dispositivo Coral M.2/PCIe.",
"A new ProxMenux version is available:": "Una nueva versión de ProxMenux está disponible:",
"A new kernel is staged for the next boot:": "Se prepara un nuevo kernel para el siguiente arranque:",
"A newer version is available:": "Hay una versión más nueva disponible:",
@@ -374,6 +374,12 @@
"Bandwidth test completed successfully": "La prueba de ancho de banda se completó con éxito",
"Base VM created with ID": "VM base creada con ID",
"Bashrc customization completed": "Personalización de Bashrc completada",
"Bash prompt path": "Ruta del prompt de Bash",
"Choose how the current directory is shown in the Bash prompt:": "Elija cómo se muestra el directorio actual en el prompt de Bash:",
"Current directory only": "Solo el directorio actual",
"Full path": "Ruta completa",
"The new prompt will be used in new terminal sessions.": "El nuevo prompt se usará en las nuevas sesiones de terminal.",
"To apply it to the current shell now, run:": "Para aplicarlo ahora en la sesión actual, ejecute:",
"Basic Settings": "Ajustes básicos",
"Basic Utilities": "Utilidades básicas",
"Before making any changes, we'll create a safety backup.": "Antes de realizar cualquier cambio, crearemos una copia de seguridad de seguridad.",
@@ -413,9 +419,9 @@
"Bridge Configuration Analysis": "Análisis de configuración de puente",
"Bridge:": "Puente:",
"Bridges analyzed": "Puentes analizados",
"Broken gasket-dkms package state recovered.": "Se recuperó el estado del paquete de junta rota-dkms.",
"Broken gasket-dkms package state recovered.": "Se ha recuperado el estado dañado del paquete gasket-dkms.",
"Browse manually (advanced)...": "Navegar manualmente (avanzado)...",
"Build and install the gasket and apex kernel modules (DKMS)": "Construya e instale los módulos de junta y núcleo apex (DKMS)",
"Build and install the gasket and apex kernel modules (DKMS)": "Compilar e instalar los módulos del kernel gasket y apex (DKMS)",
"Build dependencies installed.": "Construya dependencias instaladas.",
"CHANGES APPLIED SUCCESSFULLY": "CAMBIOS APLICADOS EXITOSAMENTE",
"CIFS Client Tools: AVAILABLE": "Herramientas de cliente CIFS: DISPONIBLES",
@@ -597,9 +603,9 @@
"Cleaning up unused time synchronization services...": "Limpiando servicios de sincronización horaria no utilizados...",
"Cleans duplicate or conflicting sources": "Limpia fuentes duplicadas o conflictivas",
"Cleanup Complete": "Limpieza completa",
"Cleanup completed. A reboot is recommended to fully apply pending kernel package configurations.": "Limpieza completada.Se recomienda reiniciar para aplicar completamente las configuraciones pendientes del paquete del kernel.",
"Cleanup completed. A reboot is recommended to fully apply pending kernel package configurations.": "Limpieza completada. Se recomienda reiniciar para aplicar por completo las configuraciones pendientes de los paquetes del kernel.",
"Cleanup finished": "Limpieza terminada",
"Cleanup legacy gasket-dkms": "Limpieza de juntas heredadas-dkms",
"Cleanup legacy gasket-dkms": "Limpiar el paquete heredado gasket-dkms",
"Cleanup partial VM?": "¿Limpiar VM parcial?",
"Clear configured target": "Borrar destino configurado",
"Clear pool error state": "Borrar estado de error del grupo",
@@ -641,7 +647,7 @@
"Completed with errors —": "Completado con errores.",
"Completed.": "Terminado.",
"Completed. Press Enter to return to menu...": "Terminado. Presione Enter para regresar al menú...",
"Completing pending package configurations...": "Completando configuraciones de paquetes pendientes...",
"Completing pending package configurations...": "Completando las configuraciones de paquetes pendientes...",
"Compliance checking (PCI-DSS, HIPAA, etc.)": "Comprobación de cumplimiento (PCI-DSS, HIPAA, etc.)",
"Component to uninstall manually (no --auto-uninstall yet):": "Componente para desinstalar manualmente (aún no hay desinstalación automática):",
"Component was installed on the backup source but no matching hardware was found on this host.": "El componente se instaló en la fuente de respaldo, pero no se encontró hardware coincidente en este host.",
@@ -851,8 +857,8 @@
"Copying installer to container": "Copiando el instalador al contenedor",
"Copying sources to": "Copiar fuentes a",
"Coral APT repository ready.": "Repositorio Coral APT listo.",
"Coral Actions": "Acciones coralinas",
"Coral M.2 / PCIe detected — installing gasket and apex kernel modules...": "Se detectó Coral M.2/PCIe: instalación de módulos de junta y kernel apex...",
"Coral Actions": "Acciones de Coral",
"Coral M.2 / PCIe detected — installing gasket and apex kernel modules...": "Coral M.2/PCIe detectado: instalando los módulos del kernel gasket y apex...",
"Coral M.2 Apex configuration added - device ready": "Configuración de Coral M.2 Apex agregada: dispositivo listo",
"Coral M.2 Apex configuration added - device will be available after reboot": "Se agregó la configuración de Coral M.2 Apex: el dispositivo estará disponible después del reinicio",
"Coral M.2 Apex detected, configuring...": "Coral M.2 Apex detectado, configurando...",
@@ -869,7 +875,7 @@
"Coral USB runtime installed. No reboot required.": "Tiempo de ejecución Coral USB instalado. No es necesario reiniciar.",
"Coral hardware configuration completed for container": "Configuración de hardware Coral completada para contenedor",
"Coral kernel modules unloaded.": "Módulos del kernel de Coral descargados.",
"Coral packages purged.": "Paquetes de coral purgados.",
"Coral packages purged.": "Paquetes de Coral purgados.",
"Coral uninstallation completed.": "Se completó la desinstalación de Coral.",
"Core Proxmox packages reinstalled successfully": "Paquetes Core Proxmox reinstalados exitosamente",
"Core packages": "Paquetes principales",
@@ -879,7 +885,7 @@
"Could not authorize the key via 'pct exec' on": "No se pudo autorizar la clave a través de 'pct exec' en",
"Could not back up the existing auth.json": "No se pudo realizar una copia de seguridad del auth.json existente",
"Could not change VM virtual display to vga: std": "No se pudo cambiar la pantalla virtual de VM a vga: estándar",
"Could not clone any gasket-driver repository. Check your internet connection and": "No se pudo clonar ningún repositorio de controladores de juntas. Comprueba tu conexión a Internet y",
"Could not clone any gasket-driver repository. Check your internet connection and": "No se pudo clonar ningún repositorio de gasket-driver. Compruebe la conexión a Internet y",
"Could not configure IOMMU kernel parameters automatically. Configure manually and reboot.": "No se pudieron configurar los parámetros del kernel IOMMU automáticamente. Configure manualmente y reinicie.",
"Could not copy the PVE keyfile into place. Check permissions on:": "No se pudo copiar el archivo de claves PVE en su lugar.Verifique los permisos en:",
"Could not copy the keyfile into place.": "no se pudo copiar el archivo de claves en su lugar.",
@@ -1068,7 +1074,7 @@
"DKMS drivers reinstalled for kernel": "controladores DKMS reinstalados para el kernel",
"DKMS install failed.": "La instalación de DKMS falló.",
"DKMS module registered.": "Módulo DKMS registrado.",
"DKMS registrations removed.": "Se eliminaron los registros DKMS.",
"DKMS registrations removed.": "Registros DKMS eliminados.",
"DNS Resolution": "Resolución DNS",
"DNS lookup for a domain": "Búsqueda de DNS para un dominio",
"Data size:": "Tamaño de datos:",
@@ -1127,7 +1133,7 @@
"Detect controller/NVMe BDF": "Detectar controlador/NVMe BDF",
"Detected": "Detectado",
"Detected AMD CPU": "CPU AMD detectada",
"Detected Coral hardware:": "Hardware de coral detectado:",
"Detected Coral hardware:": "Hardware Coral detectado:",
"Detected GPU(s):": "GPU detectadas:",
"Detected Intel CPU": "CPU Intel detectada",
"Detected Proxmox VE": "Proxmox VE detectado",
@@ -1136,7 +1142,7 @@
"Detected RAM:": "RAM detectada:",
"Detected a mounted directory from host. Setting up shared group...": "Se detectó un directorio montado desde el host. Configurando grupo compartido...",
"Detected backups — newest first:": "Copias de seguridad detectadas: las más nuevas primero:",
"Detected broken gasket-dkms package state:": "Estado del paquete de junta rota detectada-dkms:",
"Detected broken gasket-dkms package state:": "Se ha detectado que el paquete gasket-dkms está dañado:",
"Detected existing Samba user:": "Usuario de Samba existente detectado:",
"Detected filesystem:": "Sistema de archivos detectado:",
"Detected nftables - using nftables ban action": "Nftables detectados: uso de la acción de prohibición de nftables",
@@ -1264,7 +1270,7 @@
"Do you want to make this mount permanent?": "¿Quieres que este soporte sea permanente?",
"Do you want to open Switch GPU Mode now?": "¿Quieres abrir el modo Cambiar GPU ahora?",
"Do you want to proceed and run the Proxmox System Update?": "¿Quiere continuar y ejecutar la actualización del sistema Proxmox?",
"Do you want to proceed with the cleanup?": "¿Quieres continuar con la limpieza?",
"Do you want to proceed with the cleanup?": "¿Desea continuar con la limpieza?",
"Do you want to proceed with the system update?": "¿Quieres continuar con la actualización del sistema?",
"Do you want to proceed?": "¿Quieres continuar?",
"Do you want to reboot now?": "¿Quieres reiniciar ahora?",
@@ -1530,8 +1536,8 @@
"Exit the container terminal:": "Salir de la terminal de contenedores:",
"Exit: Stop to create backup manually": "Salir: Detener para crear una copia de seguridad manualmente",
"Exiting for manual repair...": "Saliendo para reparación manual...",
"Expected /tmp/gasket-driver/src not found. The clone seems incomplete or uses an unknown layout.": "Se esperaba /tmp/gasket-driver/src no encontrado. El clon parece incompleto o utiliza un diseño desconocido.",
"Expected Makefile not found in /tmp/gasket-driver/src. Source tree is incomplete.": "Makefile esperado no encontrado en /tmp/gasket-driver/src. El árbol de fuentes está incompleto.",
"Expected /tmp/gasket-driver/src not found. The clone seems incomplete or uses an unknown layout.": "No se encontró /tmp/gasket-driver/src. El clon parece incompleto o utiliza una estructura desconocida.",
"Expected Makefile not found in /tmp/gasket-driver/src. Source tree is incomplete.": "No se encontró el Makefile esperado en /tmp/gasket-driver/src. El árbol de código fuente está incompleto.",
"Expected path:": "Camino esperado:",
"Expected: rootfs/ directory, or /etc /var /root at archive root.": "Se esperaba: directorio rootfs/ o /etc /var /root en la raíz del archivo.",
"Export Format": "Formato de exportación",
@@ -2074,7 +2080,7 @@
"If you are sure you want to use it, please remove the": "Si está seguro de que desea utilizarlo, elimine el",
"If you choose No, install": "Si elige No, instale",
"If you continue, some adjustments may be duplicated or conflict with those already made by xshok.": "Si continúa, es posible que algunos ajustes se dupliquen o entren en conflicto con los que ya realizó xshok.",
"If you have a Coral M.2 / PCIe device that is physically installed but not detected by lspci, cancel here and check your hardware first before proceeding.": "Si tiene un dispositivo Coral M.2/PCIe que está instalado físicamente pero que lspci no detecta, cancele aquí y verifique su hardware antes de continuar.",
"If you have a Coral M.2 / PCIe device that is physically installed but not detected by lspci, cancel here and check your hardware first before proceeding.": "Si tiene un dispositivo Coral M.2/PCIe instalado físicamente que lspci no detecta, cancele esta operación y revise primero el hardware.",
"If you lose connectivity, you can restore from backup using the console.": "Si pierde la conectividad, puede restaurar desde la copia de seguridad usando la consola.",
"If you lose or reinstall this host without a copy of the passphrase somewhere else (password manager, offline note, another host, USB stick...), every encrypted archive in this Borg repository becomes UNRECOVERABLE.": "si pierde o reinstala este host sin una copia de la frase de contraseña en otro lugar (administrador de contraseñas, nota sin conexión, otro host, memoria USB...), todos los archivos cifrados en este repositorio Borg se vuelven IRRECUPERABLES.",
"If you want HDMI/analog audio inside the VM, select the audio controller(s) to pass through along with the GPU.": "Si desea audio HDMI/analógico dentro de la VM, seleccione los controladores de audio para pasar junto con la GPU.",
@@ -2380,8 +2386,8 @@
"Launching GPU passthrough assistant for VM": "Lanzamiento del asistente de transferencia de GPU para VM",
"Legacy PVE 8 .list files commented or not present": "Archivos .list de PVE 8 heredados comentados o no presentes",
"Legacy ceph.list commented or not present": "Legacy ceph.list comentado o no presente",
"Legacy gasket-dkms cleanup could not be verified as complete.": "No se pudo verificar que la limpieza heredada de juntas-dkms esté completa.",
"Legacy gasket-dkms detected": "Se detectaron juntas-dkms heredadas",
"Legacy gasket-dkms cleanup could not be verified as complete.": "No se ha podido verificar que la limpieza del paquete heredado gasket-dkms haya finalizado correctamente.",
"Legacy gasket-dkms detected": "Paquete heredado gasket-dkms detectado",
"Legacy network tools (e.g., ifconfig)": "Herramientas de red heredadas (por ejemplo, ifconfig)",
"Legend:": "Leyenda:",
"Let's review your current network configuration.": "Revisemos su configuración de red actual.",
@@ -2495,7 +2501,7 @@
"Manual guide script not found": "Script de guía manual no encontrado",
"Manual install required inside CT": "Se requiere instalación manual dentro del CT",
"Manual path entry": "Entrada de ruta manual",
"Manual review is required.": "se requiere revisión manual.",
"Manual review is required.": "Se requiere una revisión manual.",
"Manual steps recommended after import": "Pasos manuales recomendados después de la importación",
"Manual upgrade guide step by step": "Guía de actualización manual paso a paso",
"Mapped GID on host": "GID asignado en el host",
@@ -2786,7 +2792,7 @@
"No Changes Needed": "No se necesitan cambios",
"No Cleanup Needed": "No se necesita limpieza",
"No Controller/NVMe selected for now.": "No se ha seleccionado ningún controlador/NVMe por ahora.",
"No Coral Detected": "No se han detectado corales",
"No Coral Detected": "No se ha detectado Coral",
"No Coral TPU device was found on this host (neither PCIe/M.2 nor USB).": "No se encontró ningún dispositivo Coral TPU en este host (ni PCIe/M.2 ni USB).",
"No Custom Logos Found": "No se encontraron logotipos personalizados",
"No Disk Images Found": "No se encontraron imágenes de disco",
@@ -2922,7 +2928,7 @@
"No folders found in /mnt. Please create a new folder.": "No se encontraron carpetas en /mnt. Por favor cree una nueva carpeta.",
"No folders found inside /mnt in the CT.": "No se encontraron carpetas dentro de /mnt en el CT.",
"No format-safe disks are available.": "No hay discos con formato seguro disponibles.",
"No gasket DKMS registrations remain.": "No quedan registros DKMS de juntas.",
"No gasket DKMS registrations remain.": "No quedan registros de gasket en DKMS.",
"No group creation required — uses world-writable sticky bit permissions.": "No se requiere creación de grupos: utiliza permisos de bits adhesivos de escritura mundial.",
"No host VFIO reconfiguration expected": "No se espera reconfiguración del VFIO del host",
"No host VFIO/native binding changes were required.": "No se requirieron cambios de enlace nativo/VFIO del host.",
@@ -2963,7 +2969,7 @@
"No ports configured": "No hay puertos configurados",
"No privileged containers available in Proxmox.": "No hay contenedores privilegiados disponibles en Proxmox.",
"No pve-enterprise.list present (skipped)": "No hay pve-enterprise.list presente (omitido)",
"No reboot was started. Review the log before retrying:": "No se inició ningún reinicio.Revise el registro antes de volver a intentarlo:",
"No reboot was started. Review the log before retrying:": "No se ha iniciado el reinicio. Revise el registro antes de volver a intentarlo:",
"No recent": "No reciente",
"No recent Samba servers found.": "No se encontraron servidores Samba recientes.",
"No routing information found.": "No se encontró información de ruta.",
@@ -3132,7 +3138,7 @@
"PCI passthrough, TPM state, cloud-init, snapshots, Proxmox-specific hooks": "Transferencia de PCI, estado de TPM, inicio de nube, instantáneas, enlaces específicos de Proxmox",
"PCI reset method": "Método de reinicio de PCI",
"PCIe GPU passthrough requires:": "La transferencia de GPU PCIe requiere:",
"PCIe/M.2 gasket-dkms": "Junta PCIe/M.2-dkms",
"PCIe/M.2 gasket-dkms": "gasket-dkms para PCIe/M.2",
"POSIX ACLs applied (access + default for inheritance).": "ACL POSIX aplicadas (acceso + valor predeterminado para herencia).",
"PVE application manager updated": "Administrador de aplicaciones PVE actualizado",
"PVE cache regenerated": "Caché PVE regenerado",
@@ -3140,7 +3146,7 @@
"PVE host, VMID and password are all required for this mode.": "Para este modo se requieren host PVE, VMID y contraseña.",
"PVE9: udev rules reloaded — new interfaces will get correct names without reboot": "PVE9: reglas de udev recargadas: las nuevas interfaces obtendrán nombres correctos sin reiniciar",
"Package Updates Available": "Actualizaciones de paquetes disponibles",
"Package configurations completed.": "Configuraciones del paquete completadas.",
"Package configurations completed.": "Configuraciones de paquetes completadas.",
"Package lists": "Listas de paquetes",
"Package lists updated after GPG fix": "Listas de paquetes actualizadas después de la corrección de GPG",
"Package lists updated successfully": "Listas de paquetes actualizadas exitosamente",
@@ -3258,7 +3264,7 @@
"Power state D3cold/D0 transitions may be inaccessible": "Las transiciones del estado de energía D3cold/D0 pueden ser inaccesibles",
"Pre-check found": "Pre-comprobación encontrada",
"Pre-configure destinations so you don't have to enter them every time you back up.": "preconfigure los destinos para que no tenga que ingresarlos cada vez que realice una copia de seguridad.",
"Pre-existing gasket-dkms package removed.": "Se eliminó el paquete de junta-dkms preexistente.",
"Pre-existing gasket-dkms package removed.": "Se eliminó el paquete gasket-dkms preexistente.",
"Pre-restore backup:": "Copia de seguridad previa a la restauración:",
"Pre-upgrade check FAILED: the simulation shows that 'proxmox-ve' would be REMOVED.\n This indicates a repository or dependency issue and upgrading now could break your Proxmox installation.": "La verificación previa a la actualización FALLÓ: la simulación muestra que 'proxmox-ve' sería ELIMINADO.\n Esto indica un problema de repositorio o dependencia y actualizar ahora podría interrumpir la instalación de Proxmox.",
"Pre-upgrade simulation passed: 'proxmox-ve' will be kept or upgraded safely.": "Se pasó la simulación previa a la actualización: 'proxmox-ve' se mantendrá o se actualizará de forma segura.",
@@ -3374,8 +3380,8 @@
"Proxmox web interface: Datacenter > Storage > Add > ZFS": "Interfaz web de Proxmox: Centro de datos > Almacenamiento > Agregar > ZFS",
"Proxmox web interface: Datacenter > Storage > Add > iSCSI": "Interfaz web de Proxmox: Centro de datos > Almacenamiento > Agregar > iSCSI",
"Pulling latest changes from GitHub...": "Sacando los últimos cambios de GitHub...",
"Purge the gasket-dkms package": "Purgar el paquete de juntas-dkms",
"Purging gasket-dkms package...": "Paquete de purga de junta-dkms...",
"Purge the gasket-dkms package": "Purgar el paquete gasket-dkms",
"Purging gasket-dkms package...": "Purgando el paquete gasket-dkms...",
"Purging log2ram apt package...": "Purgando el paquete log2ram apt...",
"Quick health check (PASSED / FAILED)": "Chequeo de salud rápido (APROBADO / FALLADO)",
"Quick health status — overall SMART result + key attributes": "Estado de salud rápido: resultado SMART general + atributos clave",
@@ -3511,7 +3517,7 @@
"Remove Secure Gateway? State will be preserved.": "¿Quitar Secure Gateway? Se preservará el estado.",
"Remove custom paths": "eliminar rutas personalizadas",
"Remove disk references from affected VM(s)/CT(s) config": "Eliminar referencias de disco de la configuración de VM/CT(s) afectados",
"Remove every registered gasket DKMS version": "Retire todas las versiones DKMS de juntas registradas",
"Remove every registered gasket DKMS version": "Eliminar todas las versiones de gasket registradas en DKMS",
"Remove iSCSI Storage": "Eliminar almacenamiento iSCSI",
"Remove iSCSI storage definition:": "Eliminar la definición de almacenamiento iSCSI:",
"Remove invalid port": "Eliminar puerto no válido",
@@ -3551,13 +3557,13 @@
"Removing OpenVSwitch...": "Eliminando OpenVSwitch...",
"Removing ProxMenux persistent NIC .link files...": "Eliminando archivos .link NIC persistentes de ProxMenux...",
"Removing VFIO ownership for selected GPU(s)...": "Eliminando la propiedad de VFIO para GPU seleccionadas...",
"Removing any pre-existing gasket-dkms package...": "Eliminando cualquier paquete de junta-dkms preexistente...",
"Removing any pre-existing gasket-dkms package...": "Eliminando cualquier paquete gasket-dkms preexistente...",
"Removing conflicting utilities...": "Eliminando utilidades en conflicto...",
"Removing entropy generation optimization...": "Eliminando la optimización de la generación de entropía...",
"Removing every registered gasket DKMS version...": "Eliminación de todas las versiones DKMS de juntas registradas...",
"Removing every registered gasket DKMS version...": "Eliminando todas las versiones de gasket registradas en DKMS...",
"Removing filesystem signatures...": "Eliminando firmas del sistema de archivos...",
"Removing from /etc/fstab...": "Eliminando de /etc/fstab...",
"Removing gasket DKMS modules...": "Extracción de juntas de módulos DKMS...",
"Removing gasket DKMS modules...": "Eliminando los módulos gasket de DKMS...",
"Removing gateway...": "Eliminando puerta de enlace...",
"Removing guest agent...": "Eliminando agente invitado...",
"Removing invalid configurations...": "Eliminando configuraciones no válidas...",
@@ -3678,7 +3684,7 @@
"Run \\\"Install NVIDIA Drivers on Host\\\" first so the installer is cached.": "Primero ejecute \\\"Instalar controladores NVIDIA en el host\\\" para que el instalador se almacene en caché.",
"Run a full security audit": "Ejecute una auditoría de seguridad completa",
"Run a job now": "Ejecute un trabajo ahora",
"Run apt-get install -f to complete any pending package configurations": "ejecute apt-get install -f para completar cualquier configuración de paquete pendiente",
"Run apt-get install -f to complete any pending package configurations": "Ejecutar apt-get install -f para completar las configuraciones de paquetes pendientes",
"Run as server or client? [s/c]:": "¿Ejecutar como servidor o cliente? [Carolina del Sur]:",
"Run checklist again to verify upgrade:": "Ejecute la lista de verificación nuevamente para verificar la actualización:",
"Run from console, or SSH inside tmux/screen": "Ejecutar desde la consola o SSH dentro de tmux/screen",
@@ -4113,13 +4119,13 @@
"Smart restore plan — hardware compatibility check": "Plan de restauración inteligente: verificación de compatibilidad de hardware",
"Snippets — hook scripts / config": "Fragmentos: scripts de enlace/configuración",
"SoC-integrated GPU: tight coupling with other SoC components": "GPU integrada en SoC: estrecho acoplamiento con otros componentes de SoC",
"Some DKMS removals reported errors; final verification will determine the result.": "Algunas eliminaciones de DKMS informaron errores;La verificación final determinará el resultado.",
"Some DKMS removals reported errors; final verification will determine the result.": "Algunas eliminaciones de DKMS han devuelto errores; la verificación final determinará el resultado.",
"Some changes require a reboot to take effect. Do you want to restart now?": "Algunos cambios requieren un reinicio para que surtan efecto. ¿Quieres reiniciar ahora?",
"Some essential Proxmox packages may not have been installed": "Es posible que algunos paquetes esenciales de Proxmox no se hayan instalado",
"Some log2ram files may still exist. Manual cleanup may be required.": "Es posible que aún existan algunos archivos log2ram. Es posible que se requiera una limpieza manual.",
"Some old time services could not be removed (not installed)": "Algunos servicios antiguos no se pudieron eliminar (no instalar)",
"Some operations failed — review messages above. Press Enter to continue...": "Algunas operaciones fallaron: revise los mensajes anteriores. Presione Entrar para continuar...",
"Some packages still need attention; review": "Algunos paquetes todavía necesitan atención;revisar",
"Some packages still need attention; review": "Algunos paquetes aún requieren atención; revise",
"Some repairs failed. Please fix manually and re-run the script.": "Algunas reparaciones fallaron. Corrija manualmente y vuelva a ejecutar el script.",
"Some repositories are not available, continuing with available ones...": "Algunos repositorios no están disponibles, continuando con los disponibles...",
"Some selected GPUs are already configured in this container.": "Algunas GPU seleccionadas ya están configuradas en este contenedor.",
@@ -4327,7 +4333,7 @@
"The current driver will be completely uninstalled before installing the new version. Continue?": "El controlador actual se desinstalará por completo antes de instalar la nueva versión. ¿Continuar?",
"The directory does not exist in the CT.": "El directorio no existe en el CT.",
"The disk": "el disco",
"The dpkg package database is clean.": "La base de datos del paquete dpkg está limpia.",
"The dpkg package database is clean.": "La base de datos de paquetes de dpkg está limpia.",
"The file does not exist, is empty or is not readable.": "El archivo no existe, está vacío o no es legible.",
"The filesystem": "El sistema de archivos",
"The following DKMS-managed drivers will now be rebuilt against it so they keep working after reboot:": "Los siguientes controladores administrados por DKMS ahora se reconstruirán para que sigan funcionando después del reinicio:",
@@ -4352,7 +4358,7 @@
"The new SSH key was installed and is now authorized on the server.\nKey file:": "La nueva clave SSH se instaló y ahora está autorizada en el servidor.\nArchivo clave:",
"The new SSH key was pushed to the LXC via 'pct exec' on": "La nueva clave SSH se envió al LXC a través de 'pct exec' en",
"The next visit to the dashboard will show the initial setup wizard.": "La próxima visita al panel mostrará el asistente de configuración inicial.",
"The package is currently in a broken state and is blocking apt updates on this system.": "El paquete se encuentra actualmente en un estado roto y está bloqueando las actualizaciones adecuadas en este sistema.",
"The package is currently in a broken state and is blocking apt updates on this system.": "El paquete está dañado y bloquea las actualizaciones de APT en este sistema.",
"The passwords do not match. Please try again.": "Las contraseñas no coinciden. Por favor inténtalo de nuevo.",
"The preselected VMID does not exist on this host:": "El VMID preseleccionado no existe en este host:",
"The same GPU cannot be used by two VMs at the same time.": "Dos máquinas virtuales no pueden utilizar la misma GPU al mismo tiempo.",
@@ -4418,7 +4424,7 @@
"This backup includes /etc/zfs/zpool.cache (host-specific ZFS state).": "esta copia de seguridad incluye /etc/zfs/zpool.cache (estado ZFS específico del host).",
"This backup is encrypted.": "esta copia de seguridad está cifrada.",
"This backup was taken on kernel": "Esta copia de seguridad se realizó en el kernel",
"This cleanup will:": "Esta limpieza:",
"This cleanup will:": "Esta limpieza realizará lo siguiente:",
"This container does not have apt-get. NFS client installation only supports Debian/Ubuntu containers.": "Este contenedor no tiene apt-get. La instalación del cliente NFS solo admite contenedores Debian/Ubuntu.",
"This container does not have apt-get. Samba client installation only supports Debian/Ubuntu containers.": "Este contenedor no tiene apt-get. La instalación del cliente Samba solo admite contenedores Debian/Ubuntu.",
"This container has no GPU configured. Coral TPU works best alongside hardware video decoding (Quick Sync, VA-API, NVENC) for apps like Frigate.": "Este contenedor no tiene GPU configurada. Coral TPU funciona mejor junto con la decodificación de video por hardware (Quick Sync, VA-API, NVENC) para aplicaciones como Frigate.",
@@ -4446,7 +4452,7 @@
"This means the credentials are incorrect.": "Esto significa que las credenciales son incorrectas.",
"This might indicate network connectivity issues.": "Esto podría indicar problemas de conectividad de red.",
"This operation may take several minutes and requires internet connectivity.": "Esta operación puede tardar varios minutos y requiere conexión a Internet.",
"This package was installed by older versions of the ProxMenux Coral installer that placed the M.2 kernel driver on every system, including USB-only setups. It is not needed for Coral USB devices, which use libedgetpu1-std / libedgetpu1-max only.": "este paquete fue instalado por versiones anteriores del instalador ProxMenux Coral que colocaba el controlador del kernel M.2 en todos los sistemas, incluidas las configuraciones solo USB.No es necesario para dispositivos Coral USB, que utilizan libedgetpu1-std/libedgetpu1-max únicamente.",
"This package was installed by older versions of the ProxMenux Coral installer that placed the M.2 kernel driver on every system, including USB-only setups. It is not needed for Coral USB devices, which use libedgetpu1-std / libedgetpu1-max only.": "Este paquete fue instalado por versiones antiguas del instalador de Coral de ProxMenux, que instalaban el controlador del kernel para Coral M.2 en todos los sistemas, incluidos aquellos que solo usaban Coral USB. No es necesario para los dispositivos Coral USB, que únicamente utilizan libedgetpu1-std o libedgetpu1-max.",
"This passphrase is the ONLY way to access encrypted Borg backups.": "esta frase de contraseña es la ÚNICA forma de acceder a las copias de seguridad cifradas de Borg.",
"This path is already used as a mount point in this container.": "Esta ruta ya se utiliza como punto de montaje en este contenedor.",
"This path is not a registered mount point. Use it anyway?": "Esta ruta no es un punto de montaje registrado. ¿Usarlo de todos modos?",
@@ -4482,7 +4488,7 @@
"This will reinstall the Stable version from the main branch and disable beta update checks.\n\nContinue?": "Esto reinstalará la versión estable desde la rama principal y deshabilitará las comprobaciones de actualizaciones beta.\n\n¿Continuar?",
"This will remove NVIDIA drivers and related configuration. Do you want to continue?": "Esto eliminará los controladores NVIDIA y la configuración relacionada. ¿Quieres continuar?",
"This will remove and reinstall Lynis from the latest GitHub source. Continue?": "Esto eliminará y reinstalará Lynis desde la última fuente de GitHub. ¿Continuar?",
"This will remove the Coral TPU drivers (gasket DKMS + libedgetpu) and related configuration. Any LXC container with apex passthrough will lose access to /dev/apex_* after reboot. Continue?": "Esto eliminará los controladores Coral TPU (junta DKMS + libedgetpu) y la configuración relacionada. Cualquier contenedor LXC con acceso apex perderá el acceso a /dev/apex_* después del reinicio. ¿Continuar?",
"This will remove the Coral TPU drivers (gasket DKMS + libedgetpu) and related configuration. Any LXC container with apex passthrough will lose access to /dev/apex_* after reboot. Continue?": "Esto eliminará los controladores de Coral TPU (gasket DKMS + libedgetpu) y su configuración. Cualquier contenedor LXC con passthrough de apex perderá el acceso a /dev/apex_* después de reiniciar. ¿Desea continuar?",
"This will remove the mount from /etc/fstab and delete credentials if present.": "Esto eliminará el montaje de /etc/fstab y eliminará las credenciales si están presentes.",
"This will remove the mount from /etc/fstab.": "Esto eliminará el montaje de /etc/fstab.",
"This will restart the network service and may cause a brief disconnection. Continue?": "Esto reiniciará el servicio de red y puede provocar una breve desconexión. ¿Continuar?",
@@ -4511,7 +4517,7 @@
"To revert changes:": "Para revertir cambios:",
"To start the VM:": "Para iniciar la máquina virtual:",
"To stop:": "Para parar:",
"To use Coral from a regular app, install the libedgetpu runtime via the usual method for your distro (community package or build from source). The simplest path is to run an app container that bundles the runtime — e.g. the Frigate Docker image — passing the device through with": "para usar Coral desde una aplicación normal, instale el tiempo de ejecución libedgetpu mediante el método habitual para su distribución (paquete comunitario o compilación desde el código fuente).La ruta más sencilla es ejecutar un contenedor de aplicaciones que incluya el tiempo de ejecución, p.la imagen de Fragate Docker: pasando el dispositivo con",
"To use Coral from a regular app, install the libedgetpu runtime via the usual method for your distro (community package or build from source). The simplest path is to run an app container that bundles the runtime — e.g. the Frigate Docker image — passing the device through with": "Para usar Coral desde una aplicación normal, instale el runtime libedgetpu mediante el método habitual de su distribución (paquete de la comunidad o compilación desde el código fuente). La opción más sencilla es ejecutar un contenedor de aplicación que incluya el runtime, por ejemplo, la imagen Docker de Frigate, pasando el dispositivo con",
"To use GPU passthrough, please create a new VM configured with:": "Para utilizar la transferencia de GPU, cree una nueva máquina virtual configurada con:",
"To use a custom Fastfetch logo, place your ASCII logo file in:\n\n/usr/local/share/fastfetch/logos/\n\nThe file should not exceed 35 lines to fit properly in the terminal.\n\nPress OK to continue and select your logo.": "Para utilizar un logotipo Fastfetch personalizado, coloque su archivo de logotipo ASCII en:\n\n/usr/local/share/fastfetch/logos/\n\nEl archivo no debe exceder las 35 líneas para que quepa correctamente en la terminal.\n\nPresione OK para continuar y seleccionar su logotipo.",
"To use the GPU again in LXC, run Add GPU to LXC from GPUs and Coral-TPU Menu": "Para usar la GPU nuevamente en LXC, ejecute Agregar GPU a LXC desde GPU y Menú Coral-TPU",
@@ -4919,7 +4925,7 @@
"You selected 'Disk image' content on a CIFS/SMB storage.": "Seleccionó el contenido de 'Imagen de disco' en un almacenamiento CIFS/SMB.",
"You should now be able to access the Proxmox web interface.": "Ahora debería poder acceder a la interfaz web de Proxmox.",
"You will need a Tailscale auth key from: https://login.tailscale.com/admin/settings/keys": "Necesitará una clave de autenticación de Tailscale de: https://login.tailscale.com/admin/settings/keys",
"Your Coral USB device and its runtime (libedgetpu1) will NOT be affected.": "Su dispositivo Coral USB y su tiempo de ejecución (libedgetpu1) NO se verán afectados.",
"Your Coral USB device and its runtime (libedgetpu1) will NOT be affected.": "El dispositivo Coral USB y su entorno de ejecución (libedgetpu1) NO se verán afectados.",
"ZFS ARC config removed (kernel defaults will apply on reboot)": "Se eliminó la configuración de ZFS ARC (los valores predeterminados del kernel se aplicarán al reiniciar)",
"ZFS ARC maximum configured:": "ZFS ARC máximo configurado:",
"ZFS ARC optimization completed": "Optimización ZFS ARC completada",
@@ -5007,7 +5013,7 @@
"dkms.conf generated.": "dkms.conf generado.",
"does not exist on this host. Path not added.": "no existe en este host.Ruta no agregada.",
"does not exist. Exiting.": "no existe. Saliendo.",
"dpkg still reports unfinished package work; review": "dpkg todavía informa trabajo de paquete inacabado;revisar",
"dpkg still reports unfinished package work; review": "dpkg todavía informa de tareas de paquetes sin finalizar; revise",
"driver:": "conductor:",
"exFAT (portable: Windows/Linux/macOS)": "exFAT (portátil: Windows/Linux/macOS)",
"exFAT tools installed successfully.": "Herramientas exFAT instaladas correctamente.",
@@ -5016,7 +5022,7 @@
"fail2ban-client could not communicate with the server": "El cliente fail2ban no pudo comunicarse con el servidor.",
"fail2ban-client successfully communicated with the server": "El cliente fail2ban se comunicó exitosamente con el servidor.",
"failed:": "fallido:",
"feranick fork unreachable. Falling back to google/gasket-driver...": "horquilla feranick inalcanzable. Volviendo a google/gasket-driver...",
"feranick fork unreachable. Falling back to google/gasket-driver...": "No se puede acceder al fork de feranick. Se usará google/gasket-driver como alternativa...",
"feranick/gasket-driver cloned (actively maintained, kernel 6.12+ ready).": "feranick/gasket-driver clonado (mantenido activamente, kernel 6.12+ listo).",
"file?": "¿archivo?",
"files": "archivos",
@@ -5034,11 +5040,11 @@
"fstab entry exists": "la entrada fstab existe",
"fstab line:": "línea fstab:",
"fstab references UUIDs/devices not present on this host:": "fstab hace referencia a UUID/dispositivos que no están presentes en este host:",
"gasket DKMS entries removed.": "Se quitaron las entradas DKMS de la junta.",
"gasket-dkms has been fully removed from this system.": "empaquetadura-dkms se ha eliminado por completo de este sistema.",
"gasket-dkms is still reported by dpkg in state:": "dpkg todavía informa de la junta-dkms en el estado:",
"gasket DKMS entries removed.": "Entradas de gasket eliminadas de DKMS.",
"gasket-dkms has been fully removed from this system.": "gasket-dkms se ha eliminado por completo del sistema.",
"gasket-dkms is still reported by dpkg in state:": "dpkg todavía muestra gasket-dkms con el estado:",
"gawk installed": "gawk instalado",
"google/gasket-driver cloned (fallback — will apply local patches).": "google/gasket-driver clonado (respaldo: aplicará parches locales).",
"google/gasket-driver cloned (fallback — will apply local patches).": "google/gasket-driver clonado (alternativa; se aplicarán parches locales).",
"gpg not found; trying apt-key fallback": "gpg no encontrado; probando el respaldo de clave apta",
"gzip replaced with pigz wrapper successfully": "gzip reemplazado con el contenedor pigz exitosamente",
"has": "tiene",
@@ -5317,5 +5323,10 @@
"⚠ Disk data will NOT be erased.": "⚠ Los datos del disco NO se borrarán.",
"⚠ Disk will be unmounted and removed from /etc/fstab.": "⚠ El disco se desmontará y se eliminará de /etc/fstab.",
"⚠ The /etc/fstab entry will be removed.": "⚠ Se eliminará la entrada /etc/fstab.",
"⚠ The disk will be unmounted.": "⚠ El disco se desmontará."
"⚠ The disk will be unmounted.": "⚠ El disco se desmontará.",
"Conflicting ZFS ARC settings detected in:": "Configuración de ZFS ARC en conflicto detectada en:",
"Conflicting ZFS ARC settings backed up and reconciled:": "Configuración de ZFS ARC en conflicto respaldada y corregida:",
"Failed to reconcile conflicting ZFS ARC settings.": "No se pudo resolver la configuración de ZFS ARC en conflicto.",
"External ZFS ARC settings restored:": "Configuración externa de ZFS ARC restaurada:",
"External ZFS configuration changed after the ProxMenux migration; current file and backup preserved:": "La configuración externa de ZFS cambió después de la migración de ProxMenux; se conservaron el archivo actual y la copia de seguridad:"
}
+44 -33
View File
@@ -39,12 +39,12 @@
"A ZFS pool with this name already exists.": "Un pool ZFS portant ce nom existe déjà.",
"A ZFS pool with this name already exists:": "Un pool ZFS portant ce nom existe déjà :",
"A complete restore will:": "Une restauration complète :",
"A gasket DKMS registration is still present:": "Un joint d'immatriculation DKMS est toujours présent :",
"A gasket DKMS registration is still present:": "Un enregistrement DKMS de gasket est toujours présent :",
"A host reboot is required after this change.": "Un redémarrage de l'hôte est requis après cette modification.",
"A host reboot is required before starting the VM. Reboot now?": "Un redémarrage de l'hôte est requis avant de démarrer la VM. Redémarrer maintenant ?",
"A job with this ID already exists.": "Une tâche avec cet ID existe déjà.",
"A keyfile is installed at:": "Un fichier de clés est installé à :",
"A legacy gasket-dkms package was found on this host, but no Coral M.2 / PCIe hardware is present.": "Un ancien package Gasket-dkms a été trouvé sur cet hôte, mais aucun matériel Coral M.2 / PCIe n'est présent.",
"A legacy gasket-dkms package was found on this host, but no Coral M.2 / PCIe hardware is present.": "Un ancien paquet gasket-dkms a été trouvé sur cet hôte, mais aucun matériel Coral M.2/PCIe n'est présent.",
"A new ProxMenux version is available:": "Une nouvelle version de ProxMenux est disponible :",
"A new kernel is staged for the next boot:": "Un nouveau noyau est préparé pour le prochain démarrage :",
"A newer version is available:": "Une version plus récente est disponible :",
@@ -109,7 +109,7 @@
"Add CIFS storage:": "Ajoutez un stockage CIFS :",
"Add Controller or NVMe (PCI passthrough)": "Ajouter un contrôleur ou NVMe (passthrough PCI)",
"Add Controller or NVMe PCIe to VM": "Ajouter un contrôleur ou NVMe PCIe à la VM",
"Add Coral TPU to LXC": "Ajouter du corail TPU à LXC",
"Add Coral TPU to LXC": "Ajouter le TPU Coral au LXC",
"Add GPU to LXC": "Ajouter un GPU à LXC",
"Add GPU to LXC (Intel | AMD | NVIDIA)": "Ajouter un GPU à LXC (Intel | AMD | NVIDIA)",
"Add GPU to VM (Intel | AMD | NVIDIA)": "Ajouter un GPU à la VM (Intel | AMD | NVIDIA)",
@@ -374,6 +374,12 @@
"Bandwidth test completed successfully": "Test de bande passante terminé avec succès",
"Base VM created with ID": "VM de base créée avec l'ID",
"Bashrc customization completed": "Personnalisation de Bashrc terminée",
"Bash prompt path": "Chemin dans linvite Bash",
"Choose how the current directory is shown in the Bash prompt:": "Choisissez comment le répertoire actuel est affiché dans linvite Bash :",
"Current directory only": "Répertoire actuel uniquement",
"Full path": "Chemin complet",
"The new prompt will be used in new terminal sessions.": "La nouvelle invite sera utilisée dans les nouvelles sessions de terminal.",
"To apply it to the current shell now, run:": "Pour lappliquer maintenant à la session shell actuelle, exécutez :",
"Basic Settings": "Paramètres de base",
"Basic Utilities": "Utilitaires de base",
"Before making any changes, we'll create a safety backup.": "Avant d'apporter des modifications, nous créerons une sauvegarde de sécurité.",
@@ -413,9 +419,9 @@
"Bridge Configuration Analysis": "Analyse de la configuration du pont",
"Bridge:": "Pont:",
"Bridges analyzed": "Ponts analysés",
"Broken gasket-dkms package state recovered.": "État du paquet joint-dkms cassé récupéré.",
"Broken gasket-dkms package state recovered.": "L'état défectueux du paquet gasket-dkms a été réparé.",
"Browse manually (advanced)...": "Parcourir manuellement (avancé)...",
"Build and install the gasket and apex kernel modules (DKMS)": "Construire et installer les modules de joint et de noyau apex (DKMS)",
"Build and install the gasket and apex kernel modules (DKMS)": "Compiler et installer les modules noyau gasket et apex (DKMS)",
"Build dependencies installed.": "Dépendances de build installées.",
"CHANGES APPLIED SUCCESSFULLY": "MODIFICATIONS APPLIQUÉES AVEC SUCCÈS",
"CIFS Client Tools: AVAILABLE": "Outils clients CIFS : DISPONIBLES",
@@ -599,7 +605,7 @@
"Cleanup Complete": "Nettoyage terminé",
"Cleanup completed. A reboot is recommended to fully apply pending kernel package configurations.": "Nettoyage terminé.Un redémarrage est recommandé pour appliquer entièrement les configurations de packages de noyau en attente.",
"Cleanup finished": "Nettoyage terminé",
"Cleanup legacy gasket-dkms": "Nettoyer l'ancien joint-dkms",
"Cleanup legacy gasket-dkms": "Nettoyer l'ancien paquet gasket-dkms",
"Cleanup partial VM?": "Nettoyer une VM partielle ?",
"Clear configured target": "Effacer la cible configurée",
"Clear pool error state": "Effacer l'état d'erreur du pool",
@@ -754,7 +760,7 @@
"Conflicting drivers blacklisted successfully.": "Pilotes en conflit mis sur liste noire avec succès.",
"Conflicting path included in backup:": "Chemin d'accès en conflit inclus dans la sauvegarde :",
"Conflicting utilities removed": "Utilitaires en conflit supprimés",
"Connect a Coral Accelerator and try again.": "Connectez un accélérateur de corail et réessayez.",
"Connect a Coral Accelerator and try again.": "Connectez un accélérateur Coral et réessayez.",
"Connected": "Connecté",
"Connecting to PBS and starting backup...": "Connexion à PBS et démarrage de la sauvegarde...",
"Connection Details:": "Détails de connexion :",
@@ -851,12 +857,12 @@
"Copying installer to container": "Copie du programme d'installation dans le conteneur",
"Copying sources to": "Copie des sources vers",
"Coral APT repository ready.": "Le référentiel Coral APT est prêt.",
"Coral Actions": "Actions de corail",
"Coral M.2 / PCIe detected — installing gasket and apex kernel modules...": "Coral M.2 / PCIe détecté — installation des modules de joint et de noyau apex...",
"Coral Actions": "Actions Coral",
"Coral M.2 / PCIe detected — installing gasket and apex kernel modules...": "Coral M.2/PCIe détecté — installation des modules noyau gasket et apex...",
"Coral M.2 Apex configuration added - device ready": "Configuration Coral M.2 Apex ajoutée - appareil prêt",
"Coral M.2 Apex configuration added - device will be available after reboot": "Configuration Coral M.2 Apex ajoutée - l'appareil sera disponible après le redémarrage",
"Coral M.2 Apex detected, configuring...": "Coral M.2 Apex détecté, configuration...",
"Coral TPU Installation": "Installation du TPU corail",
"Coral TPU Installation": "Installation du TPU Coral",
"Coral TPU Uninstall": "Désinstallation de Coral TPU",
"Coral TPU device nodes detected with correct group (apex).": "Nœuds de périphérique Coral TPU détectés avec le groupe correct (apex).",
"Coral TPU driver installed successfully inside the container.": "Pilote Coral TPU installé avec succès dans le conteneur.",
@@ -868,8 +874,8 @@
"Coral USB configured but device not currently connected": "Coral USB configuré mais l'appareil n'est pas actuellement connecté",
"Coral USB runtime installed. No reboot required.": "Le runtime Coral USB est installé. Aucun redémarrage requis.",
"Coral hardware configuration completed for container": "Configuration matérielle Coral terminée pour le conteneur",
"Coral kernel modules unloaded.": "Modules du noyau de corail déchargés.",
"Coral packages purged.": "Colis de corail purgés.",
"Coral kernel modules unloaded.": "Modules noyau Coral déchargés.",
"Coral packages purged.": "Paquets Coral purgés.",
"Coral uninstallation completed.": "Désinstallation de Coral terminée.",
"Core Proxmox packages reinstalled successfully": "Packages Core Proxmox réinstallés avec succès",
"Core packages": "Forfaits de base",
@@ -879,7 +885,7 @@
"Could not authorize the key via 'pct exec' on": "Impossible d'autoriser la clé via 'pct exec' sur",
"Could not back up the existing auth.json": "Impossible de sauvegarder le auth.json existant",
"Could not change VM virtual display to vga: std": "Impossible de changer l'affichage virtuel de la VM en VGA : std",
"Could not clone any gasket-driver repository. Check your internet connection and": "Impossible de cloner un référentiel de pilotes de joints. Vérifiez votre connexion Internet et",
"Could not clone any gasket-driver repository. Check your internet connection and": "Impossible de cloner un dépôt gasket-driver. Vérifiez votre connexion Internet et",
"Could not configure IOMMU kernel parameters automatically. Configure manually and reboot.": "Impossible de configurer automatiquement les paramètres du noyau IOMMU. Configurez manuellement et redémarrez.",
"Could not copy the PVE keyfile into place. Check permissions on:": "Impossible de copier le fichier de clés PVE.Vérifiez les autorisations sur :",
"Could not copy the keyfile into place.": "Impossible de copier le fichier de clés.",
@@ -1136,7 +1142,7 @@
"Detected RAM:": "RAM détectée :",
"Detected a mounted directory from host. Setting up shared group...": "Détection d'un répertoire monté depuis l'hôte. Configuration d'un groupe partagé...",
"Detected backups — newest first:": "Sauvegardes détectées les plus récentes en premier :",
"Detected broken gasket-dkms package state:": "État du paquet joint-dkms cassé détecté :",
"Detected broken gasket-dkms package state:": "État défectueux du paquet gasket-dkms détecté :",
"Detected existing Samba user:": "Utilisateur Samba existant détecté :",
"Detected filesystem:": "Système de fichiers détecté :",
"Detected nftables - using nftables ban action": "Nftables détectés - utilisation de l'action d'interdiction de nftables",
@@ -2380,8 +2386,8 @@
"Launching GPU passthrough assistant for VM": "Lancement de l'assistant de passthrough GPU pour VM",
"Legacy PVE 8 .list files commented or not present": "Fichiers .list hérités PVE 8 commentés ou non présents",
"Legacy ceph.list commented or not present": "Ceph.list hérité commenté ou non présent",
"Legacy gasket-dkms cleanup could not be verified as complete.": "Le nettoyage de l'ancien joint-dkms n'a pas pu être vérifié comme étant terminé.",
"Legacy gasket-dkms detected": "Joint ancien-dkms détecté",
"Legacy gasket-dkms cleanup could not be verified as complete.": "Impossible de confirmer que le nettoyage de l'ancien paquet gasket-dkms est terminé.",
"Legacy gasket-dkms detected": "Ancien paquet gasket-dkms détecté",
"Legacy network tools (e.g., ifconfig)": "Outils réseau hérités (par exemple, ifconfig)",
"Legend:": "Légende:",
"Let's review your current network configuration.": "Passons en revue votre configuration réseau actuelle.",
@@ -2786,7 +2792,7 @@
"No Changes Needed": "Aucun changement nécessaire",
"No Cleanup Needed": "Aucun nettoyage nécessaire",
"No Controller/NVMe selected for now.": "Aucun contrôleur/NVMe sélectionné pour l'instant.",
"No Coral Detected": "Aucun corail détecté",
"No Coral Detected": "Aucun Coral détecté",
"No Coral TPU device was found on this host (neither PCIe/M.2 nor USB).": "Aucun périphérique Coral TPU n'a été trouvé sur cet hôte (ni PCIe/M.2 ni USB).",
"No Custom Logos Found": "Aucun logo personnalisé trouvé",
"No Disk Images Found": "Aucune image disque trouvée",
@@ -2922,7 +2928,7 @@
"No folders found in /mnt. Please create a new folder.": "Aucun dossier trouvé dans /mnt. Veuillez créer un nouveau dossier.",
"No folders found inside /mnt in the CT.": "Aucun dossier trouvé dans /mnt dans le CT.",
"No format-safe disks are available.": "Aucun disque au format sécurisé n'est disponible.",
"No gasket DKMS registrations remain.": "Aucun enregistrement de joint DKMS ne reste.",
"No gasket DKMS registrations remain.": "Il ne reste aucun enregistrement DKMS de gasket.",
"No group creation required — uses world-writable sticky bit permissions.": "Aucune création de groupe requise : utilise des autorisations de bit collant accessibles en écriture dans le monde entier.",
"No host VFIO reconfiguration expected": "Aucune reconfiguration VFIO hôte attendue",
"No host VFIO/native binding changes were required.": "Aucune modification de liaison VFIO/native de lhôte na été requise.",
@@ -3132,7 +3138,7 @@
"PCI passthrough, TPM state, cloud-init, snapshots, Proxmox-specific hooks": "Passthrough PCI, état TPM, cloud-init, instantanés, hooks spécifiques à Proxmox",
"PCI reset method": "Méthode de réinitialisation PCI",
"PCIe GPU passthrough requires:": "Le relais GPU PCIe nécessite :",
"PCIe/M.2 gasket-dkms": "Joint PCIe/M.2-dkms",
"PCIe/M.2 gasket-dkms": "PCIe/M.2 gasket-dkms",
"POSIX ACLs applied (access + default for inheritance).": "ACL POSIX appliquées (accès + valeur par défaut pour l'héritage).",
"PVE application manager updated": "Gestionnaire d'applications PVE mis à jour",
"PVE cache regenerated": "Cache PVE régénéré",
@@ -3258,7 +3264,7 @@
"Power state D3cold/D0 transitions may be inaccessible": "Les transitions de l'état d'alimentation D3cold/D0 peuvent être inaccessibles",
"Pre-check found": "Pré-vérification trouvée",
"Pre-configure destinations so you don't have to enter them every time you back up.": "Préconfigurez les destinations afin de ne pas avoir à les saisir à chaque sauvegarde.",
"Pre-existing gasket-dkms package removed.": "Le paquet joint-dkms préexistant a été supprimé.",
"Pre-existing gasket-dkms package removed.": "Le paquet gasket-dkms préexistant a été supprimé.",
"Pre-restore backup:": "Sauvegarde avant restauration :",
"Pre-upgrade check FAILED: the simulation shows that 'proxmox-ve' would be REMOVED.\n This indicates a repository or dependency issue and upgrading now could break your Proxmox installation.": "ÉCHEC de la vérification avant la mise à niveau : la simulation montre que « proxmox-ve » serait SUPPRIMÉ.\n Cela indique un problème de référentiel ou de dépendance et une mise à niveau maintenant pourrait interrompre votre installation Proxmox.",
"Pre-upgrade simulation passed: 'proxmox-ve' will be kept or upgraded safely.": "Simulation de pré-mise à niveau réussie : « proxmox-ve » sera conservé ou mis à niveau en toute sécurité.",
@@ -3374,8 +3380,8 @@
"Proxmox web interface: Datacenter > Storage > Add > ZFS": "Interface web Proxmox : Datacenter > Stockage > Ajouter > ZFS",
"Proxmox web interface: Datacenter > Storage > Add > iSCSI": "Interface Web Proxmox : Datacenter > Stockage > Ajouter > iSCSI",
"Pulling latest changes from GitHub...": "Extraction des dernières modifications de GitHub...",
"Purge the gasket-dkms package": "Purger le paquet joint-dkms",
"Purging gasket-dkms package...": "Purge du paquet joint-dkms...",
"Purge the gasket-dkms package": "Purger le paquet gasket-dkms",
"Purging gasket-dkms package...": "Purge du paquet gasket-dkms...",
"Purging log2ram apt package...": "Purge du paquet log2ram apt...",
"Quick health check (PASSED / FAILED)": "Bilan de santé rapide (RÉUSSI / ÉCHEC)",
"Quick health status — overall SMART result + key attributes": "État de santé rapide résultat SMART global + attributs clés",
@@ -3511,7 +3517,7 @@
"Remove Secure Gateway? State will be preserved.": "Supprimer Secure Gateway ? L'État sera préservé.",
"Remove custom paths": "Supprimer les chemins personnalisés",
"Remove disk references from affected VM(s)/CT(s) config": "Supprimer les références de disque de la configuration des VM/CT concernées",
"Remove every registered gasket DKMS version": "Supprimer chaque joint enregistré version DKMS",
"Remove every registered gasket DKMS version": "Supprimer toutes les versions DKMS de gasket enregistrées",
"Remove iSCSI Storage": "Supprimer le stockage iSCSI",
"Remove iSCSI storage definition:": "Supprimez la définition de stockage iSCSI :",
"Remove invalid port": "Supprimer le port invalide",
@@ -3551,13 +3557,13 @@
"Removing OpenVSwitch...": "Suppression d'OpenVSwitch...",
"Removing ProxMenux persistent NIC .link files...": "Suppression des fichiers .link de la carte réseau persistante de ProxMenux...",
"Removing VFIO ownership for selected GPU(s)...": "Suppression de la propriété VFIO pour les GPU sélectionnés...",
"Removing any pre-existing gasket-dkms package...": "Suppression de tout paquet joint-dkms préexistant...",
"Removing any pre-existing gasket-dkms package...": "Suppression de tout paquet gasket-dkms préexistant...",
"Removing conflicting utilities...": "Suppression des utilitaires en conflit...",
"Removing entropy generation optimization...": "Suppression de l'optimisation de la génération d'entropie...",
"Removing every registered gasket DKMS version...": "Suppression de chaque joint enregistré version DKMS...",
"Removing every registered gasket DKMS version...": "Suppression de toutes les versions DKMS de gasket enregistrées...",
"Removing filesystem signatures...": "Suppression des signatures du système de fichiers...",
"Removing from /etc/fstab...": "Suppression de /etc/fstab...",
"Removing gasket DKMS modules...": "Retrait du joint des modules DKMS...",
"Removing gasket DKMS modules...": "Suppression des modules DKMS de gasket...",
"Removing gateway...": "Suppression de la passerelle...",
"Removing guest agent...": "Suppression de l'agent invité...",
"Removing invalid configurations...": "Suppression des configurations invalides...",
@@ -4482,7 +4488,7 @@
"This will reinstall the Stable version from the main branch and disable beta update checks.\n\nContinue?": "Cela réinstallera la version stable à partir de la branche principale et désactivera les vérifications de mise à jour bêta.\n\nContinuer?",
"This will remove NVIDIA drivers and related configuration. Do you want to continue?": "Cela supprimera les pilotes NVIDIA et la configuration associée. Voulez-vous continuer ?",
"This will remove and reinstall Lynis from the latest GitHub source. Continue?": "Cela supprimera et réinstallera Lynis de la dernière source GitHub. Continuer?",
"This will remove the Coral TPU drivers (gasket DKMS + libedgetpu) and related configuration. Any LXC container with apex passthrough will lose access to /dev/apex_* after reboot. Continue?": "Cela supprimera les pilotes Coral TPU (joint DKMS + libedgetpu) et la configuration associée. Tout conteneur LXC avec relais apex perdra l'accès à /dev/apex_* après le redémarrage. Continuer?",
"This will remove the Coral TPU drivers (gasket DKMS + libedgetpu) and related configuration. Any LXC container with apex passthrough will lose access to /dev/apex_* after reboot. Continue?": "Cela supprimera les pilotes Coral TPU (gasket DKMS + libedgetpu) et la configuration associée. Tout conteneur LXC avec passthrough apex perdra l'accès à /dev/apex_* après le redémarrage. Continuer ?",
"This will remove the mount from /etc/fstab and delete credentials if present.": "Cela supprimera le montage de /etc/fstab et supprimera les informations d'identification si elles sont présentes.",
"This will remove the mount from /etc/fstab.": "Cela supprimera le montage de /etc/fstab.",
"This will restart the network service and may cause a brief disconnection. Continue?": "Cela redémarrera le service réseau et pourrait provoquer une brève déconnexion. Continuer?",
@@ -4544,7 +4550,7 @@
"USB Accelerators:": "Accélérateurs USB :",
"USB disk target": "cible du disque USB",
"USB drives mounted now:": "Clés USB montées maintenant :",
"USB libedgetpu1": "Libedgetpu1 USB",
"USB libedgetpu1": "USB libedgetpu1",
"UUP Dump script not found.": "Script de vidage UUP introuvable.",
"UUp Dump ISO creator Custom": "UUp Dump Créateur ISO Personnalisé",
"Udev rules for Coral USB devices added and rules reloaded.": "Règles Udev pour les périphériques USB Coral ajoutées et règles rechargées.",
@@ -5016,7 +5022,7 @@
"fail2ban-client could not communicate with the server": "fail2ban-client n'a pas pu communiquer avec le serveur",
"fail2ban-client successfully communicated with the server": "fail2ban-client a communiqué avec succès avec le serveur",
"failed:": "échoué:",
"feranick fork unreachable. Falling back to google/gasket-driver...": "fourchette de Feranick inaccessible. Revenir à google/gasket-driver...",
"feranick fork unreachable. Falling back to google/gasket-driver...": "Le fork feranick est inaccessible. Retour à google/gasket-driver...",
"feranick/gasket-driver cloned (actively maintained, kernel 6.12+ ready).": "feranick/gasket-driver cloné (maintenu activement, noyau 6.12+ prêt).",
"file?": "déposer?",
"files": "fichiers",
@@ -5034,9 +5040,9 @@
"fstab entry exists": "l'entrée fstab existe",
"fstab line:": "ligne fstab :",
"fstab references UUIDs/devices not present on this host:": "fstab fait référence aux UUID/périphériques non présents sur cet hôte :",
"gasket DKMS entries removed.": "les entrées du joint DKMS ont été supprimées.",
"gasket-dkms has been fully removed from this system.": "le joint-dkms a été entièrement supprimé de ce système.",
"gasket-dkms is still reported by dpkg in state:": "Gasket-dkms est toujours signalé par dpkg dans l'état :",
"gasket DKMS entries removed.": "Les entrées DKMS de gasket ont été supprimées.",
"gasket-dkms has been fully removed from this system.": "gasket-dkms a été entièrement supprimé de ce système.",
"gasket-dkms is still reported by dpkg in state:": "gasket-dkms est toujours signalé par dpkg dans l'état :",
"gawk installed": "bouche bée installé",
"google/gasket-driver cloned (fallback — will apply local patches).": "google/gasket-driver cloné (repli appliquera les correctifs locaux).",
"gpg not found; trying apt-key fallback": "gpg introuvable ; essayer la solution de secours apt-key",
@@ -5317,5 +5323,10 @@
"⚠ Disk data will NOT be erased.": "⚠ Les données du disque ne seront PAS effacées.",
"⚠ Disk will be unmounted and removed from /etc/fstab.": "⚠ Le disque sera démonté et supprimé de /etc/fstab.",
"⚠ The /etc/fstab entry will be removed.": "⚠ L'entrée /etc/fstab sera supprimée.",
"⚠ The disk will be unmounted.": "⚠ Le disque sera démonté."
"⚠ The disk will be unmounted.": "⚠ Le disque sera démonté.",
"Conflicting ZFS ARC settings detected in:": "Paramètres ZFS ARC conflictuels détectés dans :",
"Conflicting ZFS ARC settings backed up and reconciled:": "Paramètres ZFS ARC conflictuels sauvegardés et corrigés :",
"Failed to reconcile conflicting ZFS ARC settings.": "Impossible de corriger les paramètres ZFS ARC conflictuels.",
"External ZFS ARC settings restored:": "Paramètres ZFS ARC externes restaurés :",
"External ZFS configuration changed after the ProxMenux migration; current file and backup preserved:": "La configuration ZFS externe a changé après la migration ProxMenux ; le fichier actuel et sa sauvegarde ont été conservés :"
}
+44 -33
View File
@@ -39,12 +39,12 @@
"A ZFS pool with this name already exists.": "Esiste già un pool ZFS con questo nome.",
"A ZFS pool with this name already exists:": "Esiste già un pool ZFS con questo nome:",
"A complete restore will:": "Un ripristino completo:",
"A gasket DKMS registration is still present:": "È ancora presente una registrazione DKMS della guarnizione:",
"A gasket DKMS registration is still present:": "È ancora presente una registrazione DKMS di gasket:",
"A host reboot is required after this change.": "Dopo questa modifica è necessario il riavvio dell'host.",
"A host reboot is required before starting the VM. Reboot now?": "È necessario il riavvio dell'host prima di avviare la VM. Riavviare adesso?",
"A job with this ID already exists.": "Esiste già un lavoro con questo ID.",
"A keyfile is installed at:": "un file di chiavi è installato in:",
"A legacy gasket-dkms package was found on this host, but no Coral M.2 / PCIe hardware is present.": "su questo host è stato trovato un pacchetto legacy seal-dkms, ma non è presente alcun hardware Coral M.2/PCIe.",
"A legacy gasket-dkms package was found on this host, but no Coral M.2 / PCIe hardware is present.": "Su questo host è stato trovato un pacchetto gasket-dkms legacy, ma non è presente alcun hardware Coral M.2/PCIe.",
"A new ProxMenux version is available:": "È disponibile una nuova versione di ProxMenux:",
"A new kernel is staged for the next boot:": "viene messo in scena un nuovo kernel per il prossimo avvio:",
"A newer version is available:": "È disponibile una versione più recente:",
@@ -374,6 +374,12 @@
"Bandwidth test completed successfully": "Test della larghezza di banda completato con successo",
"Base VM created with ID": "VM di base creata con ID",
"Bashrc customization completed": "Personalizzazione Bashrc completata",
"Bash prompt path": "Percorso nel prompt Bash",
"Choose how the current directory is shown in the Bash prompt:": "Scegli come mostrare la directory corrente nel prompt Bash:",
"Current directory only": "Solo directory corrente",
"Full path": "Percorso completo",
"The new prompt will be used in new terminal sessions.": "Il nuovo prompt verrà usato nelle nuove sessioni del terminale.",
"To apply it to the current shell now, run:": "Per applicarlo ora alla sessione shell corrente, esegui:",
"Basic Settings": "Impostazioni di base",
"Basic Utilities": "Utilità di base",
"Before making any changes, we'll create a safety backup.": "Prima di apportare qualsiasi modifica, creeremo un backup di sicurezza.",
@@ -413,9 +419,9 @@
"Bridge Configuration Analysis": "Analisi della configurazione del ponte",
"Bridge:": "Ponte:",
"Bridges analyzed": "Ponti analizzati",
"Broken gasket-dkms package state recovered.": "Stato del pacchetto guarnizione-dkms rotto ripristinato.",
"Broken gasket-dkms package state recovered.": "Lo stato danneggiato del pacchetto gasket-dkms è stato ripristinato.",
"Browse manually (advanced)...": "Sfoglia manualmente (avanzato)...",
"Build and install the gasket and apex kernel modules (DKMS)": "Costruisci e installa i moduli guarnizione e apex kernel (DKMS)",
"Build and install the gasket and apex kernel modules (DKMS)": "Compila e installa i moduli kernel gasket e apex (DKMS)",
"Build dependencies installed.": "Costruisci dipendenze installate.",
"CHANGES APPLIED SUCCESSFULLY": "MODIFICHE APPLICATE CON SUCCESSO",
"CIFS Client Tools: AVAILABLE": "Strumenti client CIFS: DISPONIBILE",
@@ -599,7 +605,7 @@
"Cleanup Complete": "Pulizia completata",
"Cleanup completed. A reboot is recommended to fully apply pending kernel package configurations.": "pulizia completata.Si consiglia un riavvio per applicare completamente le configurazioni del pacchetto kernel in sospeso.",
"Cleanup finished": "La pulizia è terminata",
"Cleanup legacy gasket-dkms": "pulizia della guarnizione legacy-dkms",
"Cleanup legacy gasket-dkms": "Pulisci il pacchetto gasket-dkms legacy",
"Cleanup partial VM?": "Pulire la VM parziale?",
"Clear configured target": "Clear configured target",
"Clear pool error state": "Cancella lo stato di errore del pool",
@@ -851,12 +857,12 @@
"Copying installer to container": "Copia del programma di installazione nel contenitore",
"Copying sources to": "Copia delle fonti in",
"Coral APT repository ready.": "Repository APT Coral pronto.",
"Coral Actions": "Azioni dei coralli",
"Coral M.2 / PCIe detected — installing gasket and apex kernel modules...": "Rilevato Coral M.2 / PCIe: installazione della guarnizione e dei moduli kernel apex...",
"Coral Actions": "Azioni Coral",
"Coral M.2 / PCIe detected — installing gasket and apex kernel modules...": "Rilevato Coral M.2/PCIe: installazione dei moduli kernel gasket e apex...",
"Coral M.2 Apex configuration added - device ready": "Aggiunta configurazione Coral M.2 Apex: dispositivo pronto",
"Coral M.2 Apex configuration added - device will be available after reboot": "Aggiunta configurazione Coral M.2 Apex: il dispositivo sarà disponibile dopo il riavvio",
"Coral M.2 Apex detected, configuring...": "Rilevato Coral M.2 Apex, configurazione in corso...",
"Coral TPU Installation": "Installazione in TPU corallo",
"Coral TPU Installation": "Installazione TPU Coral",
"Coral TPU Uninstall": "Disinstallazione di Coral TPU",
"Coral TPU device nodes detected with correct group (apex).": "Nodi del dispositivo Coral TPU rilevati con il gruppo corretto (apice).",
"Coral TPU driver installed successfully inside the container.": "Driver Coral TPU installato correttamente all'interno del contenitore.",
@@ -869,7 +875,7 @@
"Coral USB runtime installed. No reboot required.": "Runtime USB Coral installato. Nessun riavvio richiesto.",
"Coral hardware configuration completed for container": "Configurazione hardware Coral completata per container",
"Coral kernel modules unloaded.": "Moduli del kernel Coral scaricati.",
"Coral packages purged.": "Pacchetti di corallo eliminati.",
"Coral packages purged.": "Pacchetti Coral eliminati.",
"Coral uninstallation completed.": "Disinstallazione di Coral completata.",
"Core Proxmox packages reinstalled successfully": "I pacchetti Core Proxmox sono stati reinstallati correttamente",
"Core packages": "Pacchetti principali",
@@ -879,7 +885,7 @@
"Could not authorize the key via 'pct exec' on": "Impossibile autorizzare la chiave tramite 'pct exec'",
"Could not back up the existing auth.json": "Impossibile eseguire il backup del file auth.json esistente",
"Could not change VM virtual display to vga: std": "Impossibile modificare la visualizzazione virtuale della VM in vga: std",
"Could not clone any gasket-driver repository. Check your internet connection and": "Impossibile clonare alcun repository di driver di guarnizione. Controlla la tua connessione Internet e",
"Could not clone any gasket-driver repository. Check your internet connection and": "Impossibile clonare un repository gasket-driver. Controlla la connessione Internet e",
"Could not configure IOMMU kernel parameters automatically. Configure manually and reboot.": "Impossibile configurare automaticamente i parametri del kernel IOMMU. Configura manualmente e riavvia.",
"Could not copy the PVE keyfile into place. Check permissions on:": "impossibile copiare il file di chiavi PVE nella sua posizione.Controlla i permessi su:",
"Could not copy the keyfile into place.": "impossibile copiare il file di chiavi in posizione.",
@@ -1127,7 +1133,7 @@
"Detect controller/NVMe BDF": "Rileva controller/NVMe BDF",
"Detected": "Rilevato",
"Detected AMD CPU": "Rilevata CPU AMD",
"Detected Coral hardware:": "Hardware corallo rilevato:",
"Detected Coral hardware:": "Hardware Coral rilevato:",
"Detected GPU(s):": "GPU rilevate:",
"Detected Intel CPU": "Rilevata CPU Intel",
"Detected Proxmox VE": "Rilevato Proxmox VE",
@@ -1136,7 +1142,7 @@
"Detected RAM:": "RAM rilevata:",
"Detected a mounted directory from host. Setting up shared group...": "Rilevata una directory montata dall'host. Configurazione del gruppo condiviso...",
"Detected backups — newest first:": "Backup rilevati: prima il più recente:",
"Detected broken gasket-dkms package state:": "Rilevato stato del pacchetto guarnizione-dkms rotto:",
"Detected broken gasket-dkms package state:": "Rilevato stato danneggiato del pacchetto gasket-dkms:",
"Detected existing Samba user:": "Rilevato utente Samba esistente:",
"Detected filesystem:": "File system rilevato:",
"Detected nftables - using nftables ban action": "Nftable rilevati: utilizzo dell'azione di divieto di nftables",
@@ -2175,7 +2181,7 @@
"Install relevant guest agent": "installa l'agente ospite pertinente",
"Install server packages inside CT:": "Installa i pacchetti server all'interno di CT:",
"Install terminal multiplexers": "Installare multiplexer terminali",
"Install the Edge TPU runtime (libedgetpu1-std)": "Installa il runtime Edge TPU (libdgetpu1-std)",
"Install the Edge TPU runtime (libedgetpu1-std)": "Installa il runtime Edge TPU (libedgetpu1-std)",
"Install with Cloud-Init script": "Installa con lo script Cloud-Init",
"Install with ISO from UUP Dump": "Installa con ISO da UUP Dump",
"Install with personal ISO": "Installa con ISO personale",
@@ -2205,7 +2211,7 @@
"Installing Ceph packages...": "Installazione dei pacchetti Ceph in corso...",
"Installing Ceph support...": "Installazione del supporto Ceph in corso...",
"Installing Coral TPU driver inside the container...": "Installazione del driver Coral TPU all'interno del contenitore...",
"Installing Edge TPU runtime (libedgetpu1-std)...": "Installazione del runtime di Edge TPU (libdgetpu1-std) in corso...",
"Installing Edge TPU runtime (libedgetpu1-std)...": "Installazione del runtime Edge TPU (libedgetpu1-std) in corso...",
"Installing Fail2Ban...": "Installazione di Fail2Ban...",
"Installing Git as a prerequisite...": "Installazione di Git come prerequisito...",
"Installing Intel VA-API drivers in container...": "Installazione dei driver Intel VA-API nel contenitore...",
@@ -2380,8 +2386,8 @@
"Launching GPU passthrough assistant for VM": "Avvio dell'assistente passthrough GPU per VM",
"Legacy PVE 8 .list files commented or not present": "File legacy PVE 8 .list commentati o non presenti",
"Legacy ceph.list commented or not present": "Ceph.list legacy commentato o non presente",
"Legacy gasket-dkms cleanup could not be verified as complete.": "non è stato possibile verificare che la pulizia legacy di seal-dkms sia stata completata.",
"Legacy gasket-dkms detected": "Rilevata guarnizione-dkm preesistente",
"Legacy gasket-dkms cleanup could not be verified as complete.": "Non è stato possibile verificare che la pulizia del pacchetto gasket-dkms legacy sia stata completata.",
"Legacy gasket-dkms detected": "Rilevato gasket-dkms legacy",
"Legacy network tools (e.g., ifconfig)": "Strumenti di rete legacy (ad esempio ifconfig)",
"Legend:": "Leggenda:",
"Let's review your current network configuration.": "Rivediamo la tua attuale configurazione di rete.",
@@ -2786,7 +2792,7 @@
"No Changes Needed": "Nessuna modifica necessaria",
"No Cleanup Needed": "Nessuna pulizia necessaria",
"No Controller/NVMe selected for now.": "Nessun controller/NVMe selezionato per ora.",
"No Coral Detected": "Nessun corallo rilevato",
"No Coral Detected": "Nessun Coral rilevato",
"No Coral TPU device was found on this host (neither PCIe/M.2 nor USB).": "Nessun dispositivo Coral TPU è stato trovato su questo host (né PCIe/M.2 né USB).",
"No Custom Logos Found": "Nessun logo personalizzato trovato",
"No Disk Images Found": "Nessuna immagine disco trovata",
@@ -2922,7 +2928,7 @@
"No folders found in /mnt. Please create a new folder.": "Nessuna cartella trovata in /mnt. Per favore crea una nuova cartella.",
"No folders found inside /mnt in the CT.": "Nessuna cartella trovata all'interno di /mnt nel CT.",
"No format-safe disks are available.": "Non sono disponibili dischi formattati.",
"No gasket DKMS registrations remain.": "non rimangono registrazioni DKMS della guarnizione.",
"No gasket DKMS registrations remain.": "Non rimangono registrazioni DKMS di gasket.",
"No group creation required — uses world-writable sticky bit permissions.": "Non è richiesta la creazione di gruppi: utilizza autorizzazioni sticky bit scrivibili da tutti.",
"No host VFIO reconfiguration expected": "Non è prevista alcuna riconfigurazione VFIO dell'host",
"No host VFIO/native binding changes were required.": "Non sono state necessarie modifiche al VFIO host/associazione nativa.",
@@ -3132,7 +3138,7 @@
"PCI passthrough, TPM state, cloud-init, snapshots, Proxmox-specific hooks": "Passthrough PCI, stato TPM, cloud-init, snapshot, hook specifici di Proxmox",
"PCI reset method": "Metodo di ripristino PCI",
"PCIe GPU passthrough requires:": "Il passthrough GPU PCIe richiede:",
"PCIe/M.2 gasket-dkms": "Guarnizione PCIe/M.2-dkms",
"PCIe/M.2 gasket-dkms": "PCIe/M.2 gasket-dkms",
"POSIX ACLs applied (access + default for inheritance).": "ACL POSIX applicati (accesso + impostazione predefinita per ereditarietà).",
"PVE application manager updated": "Gestore applicazioni PVE aggiornato",
"PVE cache regenerated": "Cache PVE rigenerata",
@@ -3258,7 +3264,7 @@
"Power state D3cold/D0 transitions may be inaccessible": "Le transizioni dello stato di alimentazione D3freddo/D0 potrebbero essere inaccessibili",
"Pre-check found": "Pre-controllo trovato",
"Pre-configure destinations so you don't have to enter them every time you back up.": "Preconfigura le destinazioni in modo da non doverle inserire ogni volta che esegui il backup.",
"Pre-existing gasket-dkms package removed.": "Pacchetto guarnizione-dkms preesistente rimosso.",
"Pre-existing gasket-dkms package removed.": "Pacchetto gasket-dkms preesistente rimosso.",
"Pre-restore backup:": "Backup pre-ripristino:",
"Pre-upgrade check FAILED: the simulation shows that 'proxmox-ve' would be REMOVED.\n This indicates a repository or dependency issue and upgrading now could break your Proxmox installation.": "Controllo pre-aggiornamento FALLITO: la simulazione mostra che 'proxmox-ve' verrebbe RIMOSSO.\n Ciò indica un problema di repository o dipendenza e l'aggiornamento ora potrebbe interrompere l'installazione di Proxmox.",
"Pre-upgrade simulation passed: 'proxmox-ve' will be kept or upgraded safely.": "Simulazione pre-aggiornamento superata: 'proxmox-ve' verrà mantenuto o aggiornato in modo sicuro.",
@@ -3374,8 +3380,8 @@
"Proxmox web interface: Datacenter > Storage > Add > ZFS": "Interfaccia web Proxmox: Datacenter > Archiviazione > Aggiungi > ZFS",
"Proxmox web interface: Datacenter > Storage > Add > iSCSI": "Interfaccia web Proxmox: Datacenter > Archiviazione > Aggiungi > iSCSI",
"Pulling latest changes from GitHub...": "Estrazione delle ultime modifiche da GitHub...",
"Purge the gasket-dkms package": "elimina il pacchetto guarnizione-dkms",
"Purging gasket-dkms package...": "Spurgo del pacchetto guarnizione-dkms...",
"Purge the gasket-dkms package": "Elimina completamente il pacchetto gasket-dkms",
"Purging gasket-dkms package...": "Eliminazione completa del pacchetto gasket-dkms...",
"Purging log2ram apt package...": "Eliminazione del pacchetto apt log2ram in corso...",
"Quick health check (PASSED / FAILED)": "Controllo rapido dello stato (SUPERATO/FALLITO)",
"Quick health status — overall SMART result + key attributes": "Stato di salute rapido: risultato SMART complessivo + attributi chiave",
@@ -3511,7 +3517,7 @@
"Remove Secure Gateway? State will be preserved.": "Rimuovere Secure Gateway? Lo Stato sarà preservato.",
"Remove custom paths": "Rimuovi percorsi personalizzati",
"Remove disk references from affected VM(s)/CT(s) config": "Rimuovere i riferimenti al disco dalla configurazione delle VM/CT interessate",
"Remove every registered gasket DKMS version": "rimuovi ogni versione DKMS della guarnizione registrata",
"Remove every registered gasket DKMS version": "Rimuovi ogni versione DKMS di gasket registrata",
"Remove iSCSI Storage": "Rimuovere l'archiviazione iSCSI",
"Remove iSCSI storage definition:": "Rimuovere la definizione di archiviazione iSCSI:",
"Remove invalid port": "Rimuovi la porta non valida",
@@ -3551,13 +3557,13 @@
"Removing OpenVSwitch...": "Rimozione di OpenVSwitch...",
"Removing ProxMenux persistent NIC .link files...": "Rimozione dei file .link NIC persistenti di ProxMenux...",
"Removing VFIO ownership for selected GPU(s)...": "Rimozione della proprietà VFIO per le GPU selezionate in corso...",
"Removing any pre-existing gasket-dkms package...": "Rimozione dell'eventuale pacchetto guarnizioni-dkms preesistente...",
"Removing any pre-existing gasket-dkms package...": "Rimozione dell'eventuale pacchetto gasket-dkms preesistente...",
"Removing conflicting utilities...": "Rimozione delle utilità in conflitto...",
"Removing entropy generation optimization...": "Rimozione dell'ottimizzazione della generazione di entropia in corso...",
"Removing every registered gasket DKMS version...": "Rimozione di ogni versione DKMS della guarnizione registrata...",
"Removing every registered gasket DKMS version...": "Rimozione di ogni versione DKMS di gasket registrata...",
"Removing filesystem signatures...": "Rimozione delle firme del file system in corso...",
"Removing from /etc/fstab...": "Rimozione da /etc/fstab...",
"Removing gasket DKMS modules...": "Rimozione della guarnizione dei moduli DKMS...",
"Removing gasket DKMS modules...": "Rimozione dei moduli DKMS di gasket...",
"Removing gateway...": "Rimozione del gateway...",
"Removing guest agent...": "Rimozione dell'agente ospite in corso...",
"Removing invalid configurations...": "Rimozione delle configurazioni non valide...",
@@ -4482,7 +4488,7 @@
"This will reinstall the Stable version from the main branch and disable beta update checks.\n\nContinue?": "Ciò reinstallerà la versione stabile dal ramo principale e disabiliterà i controlli degli aggiornamenti beta.\n\nContinuare?",
"This will remove NVIDIA drivers and related configuration. Do you want to continue?": "Ciò rimuoverà i driver NVIDIA e la relativa configurazione. Vuoi continuare?",
"This will remove and reinstall Lynis from the latest GitHub source. Continue?": "Ciò rimuoverà e reinstallerà Lynis dall'ultima fonte GitHub. Continuare?",
"This will remove the Coral TPU drivers (gasket DKMS + libedgetpu) and related configuration. Any LXC container with apex passthrough will lose access to /dev/apex_* after reboot. Continue?": "Ciò rimuoverà i driver Coral TPU (guarnizione DKMS + libedgetpu) e la relativa configurazione. Qualsiasi contenitore LXC con passthrough apex perderà l'accesso a /dev/apex_* dopo il riavvio. Continuare?",
"This will remove the Coral TPU drivers (gasket DKMS + libedgetpu) and related configuration. Any LXC container with apex passthrough will lose access to /dev/apex_* after reboot. Continue?": "Ciò rimuoverà i driver Coral TPU (gasket DKMS + libedgetpu) e la relativa configurazione. Qualsiasi contenitore LXC con passthrough apex perderà l'accesso a /dev/apex_* dopo il riavvio. Continuare?",
"This will remove the mount from /etc/fstab and delete credentials if present.": "Ciò rimuoverà il montaggio da /etc/fstab ed eliminerà le credenziali se presenti.",
"This will remove the mount from /etc/fstab.": "Questo rimuoverà il montaggio da /etc/fstab.",
"This will restart the network service and may cause a brief disconnection. Continue?": "Ciò riavvierà il servizio di rete e potrebbe causare una breve disconnessione. Continuare?",
@@ -4919,7 +4925,7 @@
"You selected 'Disk image' content on a CIFS/SMB storage.": "Hai selezionato il contenuto \"Immagine disco\" su un archivio CIFS/SMB.",
"You should now be able to access the Proxmox web interface.": "Ora dovresti essere in grado di accedere all'interfaccia web di Proxmox.",
"You will need a Tailscale auth key from: https://login.tailscale.com/admin/settings/keys": "Avrai bisogno di una chiave di autenticazione Tailscale da: https://login.tailscale.com/admin/settings/keys",
"Your Coral USB device and its runtime (libedgetpu1) will NOT be affected.": "il tuo dispositivo USB Coral e il suo runtime (libdgetpu1) NON saranno interessati.",
"Your Coral USB device and its runtime (libedgetpu1) will NOT be affected.": "Il dispositivo USB Coral e il relativo runtime (libedgetpu1) NON saranno interessati.",
"ZFS ARC config removed (kernel defaults will apply on reboot)": "Configurazione ZFS ARC rimossa (le impostazioni predefinite del kernel verranno applicate al riavvio)",
"ZFS ARC maximum configured:": "ZFS ARC massimo configurato:",
"ZFS ARC optimization completed": "Ottimizzazione ZFS ARC completata",
@@ -5016,7 +5022,7 @@
"fail2ban-client could not communicate with the server": "fail2ban-client non è riuscito a comunicare con il server",
"fail2ban-client successfully communicated with the server": "fail2ban-client ha comunicato con successo con il server",
"failed:": "fallito:",
"feranick fork unreachable. Falling back to google/gasket-driver...": "Forcella feranick irraggiungibile. Ritornando a google/gasket-driver...",
"feranick fork unreachable. Falling back to google/gasket-driver...": "Il fork feranick non è raggiungibile. Ripiego su google/gasket-driver...",
"feranick/gasket-driver cloned (actively maintained, kernel 6.12+ ready).": "feranick/gasket-driver clonato (mantenuto attivamente, kernel 6.12+ pronto).",
"file?": "file?",
"files": "file",
@@ -5034,9 +5040,9 @@
"fstab entry exists": "esiste la voce fstab",
"fstab line:": "riga fstab:",
"fstab references UUIDs/devices not present on this host:": "fstab fa riferimento a UUID/dispositivi non presenti su questo host:",
"gasket DKMS entries removed.": "voci DKMS della guarnizione rimosse.",
"gasket-dkms has been fully removed from this system.": "la guarnizione-dkms è stata completamente rimossa da questo sistema.",
"gasket-dkms is still reported by dpkg in state:": "guarnizione-dkms è ancora riportato da dpkg nello stato:",
"gasket DKMS entries removed.": "Voci DKMS di gasket rimosse.",
"gasket-dkms has been fully removed from this system.": "gasket-dkms è stato completamente rimosso dal sistema.",
"gasket-dkms is still reported by dpkg in state:": "gasket-dkms è ancora riportato da dpkg nello stato:",
"gawk installed": "gawk installato",
"google/gasket-driver cloned (fallback — will apply local patches).": "google/gasket-driver clonato (fallback: applicherà le patch locali).",
"gpg not found; trying apt-key fallback": "gpg non trovato; provando il fallback con la chiave apt",
@@ -5317,5 +5323,10 @@
"⚠ Disk data will NOT be erased.": "⚠ I dati del disco NON verranno cancellati.",
"⚠ Disk will be unmounted and removed from /etc/fstab.": "⚠ Il disco verrà smontato e rimosso da /etc/fstab.",
"⚠ The /etc/fstab entry will be removed.": "⚠ La voce /etc/fstab verrà rimossa.",
"⚠ The disk will be unmounted.": "⚠ Il disco verrà smontato."
"⚠ The disk will be unmounted.": "⚠ Il disco verrà smontato.",
"Conflicting ZFS ARC settings detected in:": "Impostazioni ZFS ARC in conflitto rilevate in:",
"Conflicting ZFS ARC settings backed up and reconciled:": "Impostazioni ZFS ARC in conflitto salvate e corrette:",
"Failed to reconcile conflicting ZFS ARC settings.": "Impossibile correggere le impostazioni ZFS ARC in conflitto.",
"External ZFS ARC settings restored:": "Impostazioni ZFS ARC esterne ripristinate:",
"External ZFS configuration changed after the ProxMenux migration; current file and backup preserved:": "La configurazione ZFS esterna è cambiata dopo la migrazione ProxMenux; il file attuale e il backup sono stati conservati:"
}
+39 -28
View File
@@ -39,12 +39,12 @@
"A ZFS pool with this name already exists.": "Já existe um pool ZFS com esse nome.",
"A ZFS pool with this name already exists:": "Já existe um pool ZFS com este nome:",
"A complete restore will:": "Uma restauração completa irá:",
"A gasket DKMS registration is still present:": "Um registro de junta DKMS ainda está presente:",
"A gasket DKMS registration is still present:": "Ainda existe um registo DKMS de gasket:",
"A host reboot is required after this change.": "Uma reinicialização do host é necessária após essa alteração.",
"A host reboot is required before starting the VM. Reboot now?": "É necessária uma reinicialização do host antes de iniciar a VM. Reiniciar agora?",
"A job with this ID already exists.": "Já existe um trabalho com este ID.",
"A keyfile is installed at:": "Um arquivo-chave está instalado em:",
"A legacy gasket-dkms package was found on this host, but no Coral M.2 / PCIe hardware is present.": "Um pacote legado gaxeta-dkms foi encontrado neste host, mas nenhum hardware Coral M.2/PCIe está presente.",
"A legacy gasket-dkms package was found on this host, but no Coral M.2 / PCIe hardware is present.": "Foi encontrado neste host um pacote gasket-dkms legado, mas não existe hardware Coral M.2/PCIe.",
"A new ProxMenux version is available:": "Uma nova versão do ProxMenux está disponível:",
"A new kernel is staged for the next boot:": "Um novo kernel está preparado para a próxima inicialização:",
"A newer version is available:": "Uma versão mais recente está disponível:",
@@ -374,6 +374,12 @@
"Bandwidth test completed successfully": "Teste de largura de banda concluído com sucesso",
"Base VM created with ID": "VM base criada com ID",
"Bashrc customization completed": "Personalização do Bashrc concluída",
"Bash prompt path": "Caminho no prompt do Bash",
"Choose how the current directory is shown in the Bash prompt:": "Escolha como o diretório atual é apresentado no prompt do Bash:",
"Current directory only": "Apenas o diretório atual",
"Full path": "Caminho completo",
"The new prompt will be used in new terminal sessions.": "O novo prompt será usado em novas sessões do terminal.",
"To apply it to the current shell now, run:": "Para aplicá-lo agora à sessão shell atual, execute:",
"Basic Settings": "configurações básicas",
"Basic Utilities": "Utilitários básicos",
"Before making any changes, we'll create a safety backup.": "Antes de fazer qualquer alteração, criaremos um backup de segurança.",
@@ -413,9 +419,9 @@
"Bridge Configuration Analysis": "Análise de configuração de ponte",
"Bridge:": "Ponte:",
"Bridges analyzed": "Pontes analisadas",
"Broken gasket-dkms package state recovered.": "Estado quebrado do pacote junta-dkms recuperado.",
"Broken gasket-dkms package state recovered.": "O estado danificado do pacote gasket-dkms foi recuperado.",
"Browse manually (advanced)...": "Navegar manualmente (avançado)...",
"Build and install the gasket and apex kernel modules (DKMS)": "Construir e instalar os módulos de junta e kernel apex (DKMS)",
"Build and install the gasket and apex kernel modules (DKMS)": "Compilar e instalar os módulos de kernel gasket e apex (DKMS)",
"Build dependencies installed.": "Construa dependências instaladas.",
"CHANGES APPLIED SUCCESSFULLY": "ALTERAÇÕES APLICADAS COM SUCESSO",
"CIFS Client Tools: AVAILABLE": "Ferramentas de cliente CIFS: DISPONÍVEIS",
@@ -599,7 +605,7 @@
"Cleanup Complete": "Limpeza concluída",
"Cleanup completed. A reboot is recommended to fully apply pending kernel package configurations.": "Limpeza concluída.Recomenda-se uma reinicialização para aplicar totalmente as configurações pendentes do pacote do kernel.",
"Cleanup finished": "Limpeza concluída",
"Cleanup legacy gasket-dkms": "Limpeza de junta herdada-dkms",
"Cleanup legacy gasket-dkms": "Limpar o pacote gasket-dkms legado",
"Cleanup partial VM?": "Limpar VM parcial?",
"Clear configured target": "Limpar destino configurado",
"Clear pool error state": "Limpar estado de erro do pool",
@@ -851,8 +857,8 @@
"Copying installer to container": "Copiando o instalador para o contêiner",
"Copying sources to": "Copiando fontes para",
"Coral APT repository ready.": "Repositório Coral APT pronto.",
"Coral Actions": "Ações Corais",
"Coral M.2 / PCIe detected — installing gasket and apex kernel modules...": "Coral M.2 / PCIe detectado instalando módulos de junta e kernel apex...",
"Coral Actions": "Ações Coral",
"Coral M.2 / PCIe detected — installing gasket and apex kernel modules...": "Coral M.2/PCIe detetado — a instalar os módulos de kernel gasket e apex...",
"Coral M.2 Apex configuration added - device ready": "Configuração Coral M.2 Apex adicionada - dispositivo pronto",
"Coral M.2 Apex configuration added - device will be available after reboot": "Configuração Coral M.2 Apex adicionada - o dispositivo estará disponível após a reinicialização",
"Coral M.2 Apex detected, configuring...": "Coral M.2 Apex detectado, configurando...",
@@ -869,7 +875,7 @@
"Coral USB runtime installed. No reboot required.": "Tempo de execução Coral USB instalado. Não é necessária reinicialização.",
"Coral hardware configuration completed for container": "Configuração de hardware Coral concluída para contêiner",
"Coral kernel modules unloaded.": "Módulos do kernel Coral descarregados.",
"Coral packages purged.": "Pacotes de coral eliminados.",
"Coral packages purged.": "Pacotes Coral eliminados.",
"Coral uninstallation completed.": "Desinstalação do Coral concluída.",
"Core Proxmox packages reinstalled successfully": "Pacotes principais do Proxmox reinstalados com sucesso",
"Core packages": "Pacotes principais",
@@ -879,7 +885,7 @@
"Could not authorize the key via 'pct exec' on": "Não foi possível autorizar a chave via 'pct exec' em",
"Could not back up the existing auth.json": "Não foi possível fazer backup do auth.json existente",
"Could not change VM virtual display to vga: std": "Não foi possível alterar a exibição virtual da VM para vga: std",
"Could not clone any gasket-driver repository. Check your internet connection and": "Não foi possível clonar nenhum repositório de driver de junta. Verifique sua conexão com a internet e",
"Could not clone any gasket-driver repository. Check your internet connection and": "Não foi possível clonar um repositório gasket-driver. Verifique a ligação à Internet e",
"Could not configure IOMMU kernel parameters automatically. Configure manually and reboot.": "Não foi possível configurar os parâmetros do kernel IOMMU automaticamente. Configure manualmente e reinicie.",
"Could not copy the PVE keyfile into place. Check permissions on:": "Não foi possível copiar o arquivo-chave PVE no lugar.Verifique as permissões em:",
"Could not copy the keyfile into place.": "Não foi possível copiar o arquivo-chave no lugar.",
@@ -1136,7 +1142,7 @@
"Detected RAM:": "RAM detectada:",
"Detected a mounted directory from host. Setting up shared group...": "Detectou um diretório montado do host. Configurando grupo compartilhado...",
"Detected backups — newest first:": "Backups detectados os mais recentes primeiro:",
"Detected broken gasket-dkms package state:": "Estado quebrado do pacote junta-dkms detectado:",
"Detected broken gasket-dkms package state:": "Foi detetado um estado danificado do pacote gasket-dkms:",
"Detected existing Samba user:": "Usuário existente do Samba detectado:",
"Detected filesystem:": "Sistema de arquivos detectado:",
"Detected nftables - using nftables ban action": "Nftables detectados - usando ação de banimento de nftables",
@@ -2380,8 +2386,8 @@
"Launching GPU passthrough assistant for VM": "Lançamento do assistente de passagem de GPU para VM",
"Legacy PVE 8 .list files commented or not present": "Arquivos .list PVE 8 legados comentados ou não presentes",
"Legacy ceph.list commented or not present": "Ceph.list legado comentado ou não presente",
"Legacy gasket-dkms cleanup could not be verified as complete.": "a limpeza do Legacy Gasket-dkms não pôde ser verificada como concluída.",
"Legacy gasket-dkms detected": "Junta-dkms legados detectados",
"Legacy gasket-dkms cleanup could not be verified as complete.": "Não foi possível confirmar a conclusão da limpeza do pacote gasket-dkms legado.",
"Legacy gasket-dkms detected": "gasket-dkms legado detetado",
"Legacy network tools (e.g., ifconfig)": "Ferramentas de rede legadas (por exemplo, ifconfig)",
"Legend:": "Lenda:",
"Let's review your current network configuration.": "Vamos revisar sua configuração de rede atual.",
@@ -2786,7 +2792,7 @@
"No Changes Needed": "Nenhuma alteração necessária",
"No Cleanup Needed": "Nenhuma limpeza necessária",
"No Controller/NVMe selected for now.": "Nenhum controlador/NVMe selecionado no momento.",
"No Coral Detected": "Nenhum coral detectado",
"No Coral Detected": "Nenhum Coral detetado",
"No Coral TPU device was found on this host (neither PCIe/M.2 nor USB).": "Nenhum dispositivo Coral TPU foi encontrado neste host (nem PCIe/M.2 nem USB).",
"No Custom Logos Found": "Nenhum logotipo personalizado encontrado",
"No Disk Images Found": "Nenhuma imagem de disco encontrada",
@@ -2922,7 +2928,7 @@
"No folders found in /mnt. Please create a new folder.": "Nenhuma pasta encontrada em /mnt. Por favor, crie uma nova pasta.",
"No folders found inside /mnt in the CT.": "Nenhuma pasta encontrada dentro de /mnt no CT.",
"No format-safe disks are available.": "Nenhum disco de formato seguro está disponível.",
"No gasket DKMS registrations remain.": "Nenhum registro de junta DKMS permanece.",
"No gasket DKMS registrations remain.": "Não restam registos DKMS de gasket.",
"No group creation required — uses world-writable sticky bit permissions.": "Não é necessária a criação de grupos — usa permissões de sticky bit graváveis mundialmente.",
"No host VFIO reconfiguration expected": "Nenhuma reconfiguração VFIO do host é esperada",
"No host VFIO/native binding changes were required.": "Nenhuma alteração de ligação VFIO/nativa do host foi necessária.",
@@ -3132,7 +3138,7 @@
"PCI passthrough, TPM state, cloud-init, snapshots, Proxmox-specific hooks": "Passagem PCI, estado TPM, inicialização em nuvem, snapshots, ganchos específicos do Proxmox",
"PCI reset method": "Método de redefinição PCI",
"PCIe GPU passthrough requires:": "A passagem de GPU PCIe requer:",
"PCIe/M.2 gasket-dkms": "Junta PCIe/M.2-dkms",
"PCIe/M.2 gasket-dkms": "PCIe/M.2 gasket-dkms",
"POSIX ACLs applied (access + default for inheritance).": "ACLs POSIX aplicadas (acesso + padrão para herança).",
"PVE application manager updated": "Gerenciador de aplicativos PVE atualizado",
"PVE cache regenerated": "Cache PVE regenerado",
@@ -3258,7 +3264,7 @@
"Power state D3cold/D0 transitions may be inaccessible": "As transições do estado de energia D3cold/D0 podem estar inacessíveis",
"Pre-check found": "Pré-verificação encontrada",
"Pre-configure destinations so you don't have to enter them every time you back up.": "Pré-configure destinos para que você não precise inseri-los sempre que fizer backup.",
"Pre-existing gasket-dkms package removed.": "Pacote de junta-dkms pré-existente removido.",
"Pre-existing gasket-dkms package removed.": "Pacote gasket-dkms preexistente removido.",
"Pre-restore backup:": "Backup pré-restauração:",
"Pre-upgrade check FAILED: the simulation shows that 'proxmox-ve' would be REMOVED.\n This indicates a repository or dependency issue and upgrading now could break your Proxmox installation.": "Verificação de pré-atualização FALHOU: a simulação mostra que 'proxmox-ve' seria REMOVIDO.\n Isso indica um problema de repositório ou dependência e a atualização agora pode interromper a instalação do Proxmox.",
"Pre-upgrade simulation passed: 'proxmox-ve' will be kept or upgraded safely.": "Simulação de pré-atualização aprovada: 'proxmox-ve' será mantido ou atualizado com segurança.",
@@ -3374,8 +3380,8 @@
"Proxmox web interface: Datacenter > Storage > Add > ZFS": "Interface web Proxmox: Datacenter > Armazenamento > Adicionar > ZFS",
"Proxmox web interface: Datacenter > Storage > Add > iSCSI": "Interface web Proxmox: Datacenter > Armazenamento > Adicionar > iSCSI",
"Pulling latest changes from GitHub...": "Extraindo as alterações mais recentes do GitHub...",
"Purge the gasket-dkms package": "Limpe o pacote junta-dkms",
"Purging gasket-dkms package...": "Purgando pacote junta-dkms...",
"Purge the gasket-dkms package": "Remover completamente o pacote gasket-dkms",
"Purging gasket-dkms package...": "A remover completamente o pacote gasket-dkms...",
"Purging log2ram apt package...": "Expurgando pacote log2ram apt...",
"Quick health check (PASSED / FAILED)": "Verificação rápida de integridade (APROVADO/FALHA)",
"Quick health status — overall SMART result + key attributes": "Status de saúde rápido resultado SMART geral + atributos principais",
@@ -3511,7 +3517,7 @@
"Remove Secure Gateway? State will be preserved.": "Remover Secure Gateway? O estado será preservado.",
"Remove custom paths": "Remover caminhos personalizados",
"Remove disk references from affected VM(s)/CT(s) config": "Remover referências de disco da configuração de VM(s)/CT(s) afetadas",
"Remove every registered gasket DKMS version": "Remova todas as versões DKMS de juntas registradas",
"Remove every registered gasket DKMS version": "Remover todas as versões DKMS de gasket registadas",
"Remove iSCSI Storage": "Remover armazenamento iSCSI",
"Remove iSCSI storage definition:": "Remova a definição de armazenamento iSCSI:",
"Remove invalid port": "Remover porta inválida",
@@ -3551,13 +3557,13 @@
"Removing OpenVSwitch...": "Removendo OpenVSwitch...",
"Removing ProxMenux persistent NIC .link files...": "Removendo arquivos .link da NIC persistente do ProxMenux...",
"Removing VFIO ownership for selected GPU(s)...": "Removendo propriedade de VFIO para GPU(s) selecionada(s)...",
"Removing any pre-existing gasket-dkms package...": "Removendo qualquer pacote de junta-dkms pré-existente...",
"Removing any pre-existing gasket-dkms package...": "A remover qualquer pacote gasket-dkms preexistente...",
"Removing conflicting utilities...": "Removendo utilitários conflitantes...",
"Removing entropy generation optimization...": "Removendo otimização de geração de entropia...",
"Removing every registered gasket DKMS version...": "Removendo todas as juntas registradas da versão DKMS...",
"Removing every registered gasket DKMS version...": "A remover todas as versões DKMS de gasket registadas...",
"Removing filesystem signatures...": "Removendo assinaturas do sistema de arquivos...",
"Removing from /etc/fstab...": "Removendo de /etc/fstab...",
"Removing gasket DKMS modules...": "Removendo a junta dos módulos DKMS...",
"Removing gasket DKMS modules...": "A remover os módulos DKMS de gasket...",
"Removing gateway...": "Removendo gateway...",
"Removing guest agent...": "Removendo agente convidado...",
"Removing invalid configurations...": "Removendo configurações inválidas...",
@@ -4482,7 +4488,7 @@
"This will reinstall the Stable version from the main branch and disable beta update checks.\n\nContinue?": "Isso reinstalará a versão estável da ramificação principal e desativará as verificações de atualização beta.\n\nContinuar?",
"This will remove NVIDIA drivers and related configuration. Do you want to continue?": "Isso removerá os drivers NVIDIA e configurações relacionadas. Você quer continuar?",
"This will remove and reinstall Lynis from the latest GitHub source. Continue?": "Isso removerá e reinstalará o Lynis da fonte GitHub mais recente. Continuar?",
"This will remove the Coral TPU drivers (gasket DKMS + libedgetpu) and related configuration. Any LXC container with apex passthrough will lose access to /dev/apex_* after reboot. Continue?": "Isso removerá os drivers Coral TPU (junta DKMS + libedgetpu) e a configuração relacionada. Qualquer contêiner LXC com passagem apex perderá acesso a /dev/apex_* após a reinicialização. Continuar?",
"This will remove the Coral TPU drivers (gasket DKMS + libedgetpu) and related configuration. Any LXC container with apex passthrough will lose access to /dev/apex_* after reboot. Continue?": "Isto removerá os drivers Coral TPU (gasket DKMS + libedgetpu) e a configuração relacionada. Qualquer contentor LXC com passthrough apex perderá o acesso a /dev/apex_* após reiniciar. Continuar?",
"This will remove the mount from /etc/fstab and delete credentials if present.": "Isso removerá a montagem de /etc/fstab e excluirá as credenciais, se presentes.",
"This will remove the mount from /etc/fstab.": "Isso removerá a montagem de /etc/fstab.",
"This will restart the network service and may cause a brief disconnection. Continue?": "Isto reiniciará o serviço de rede e poderá causar uma breve desconexão. Continuar?",
@@ -5016,7 +5022,7 @@
"fail2ban-client could not communicate with the server": "fail2ban-client não conseguiu se comunicar com o servidor",
"fail2ban-client successfully communicated with the server": "fail2ban-client se comunicou com sucesso com o servidor",
"failed:": "fracassado:",
"feranick fork unreachable. Falling back to google/gasket-driver...": "garfo feranick inacessível. Voltando ao google/gasket-driver...",
"feranick fork unreachable. Falling back to google/gasket-driver...": "O fork feranick está inacessível. A usar google/gasket-driver como alternativa...",
"feranick/gasket-driver cloned (actively maintained, kernel 6.12+ ready).": "feranick/gasket-driver clonado (mantido ativamente, kernel 6.12+ pronto).",
"file?": "arquivo?",
"files": "arquivos",
@@ -5034,9 +5040,9 @@
"fstab entry exists": "existe entrada fstab",
"fstab line:": "linha fstab:",
"fstab references UUIDs/devices not present on this host:": "fstab faz referência a UUIDs/dispositivos não presentes neste host:",
"gasket DKMS entries removed.": "juntas, entradas DKMS removidas.",
"gasket-dkms has been fully removed from this system.": "junta-dkms foi totalmente removida deste sistema.",
"gasket-dkms is still reported by dpkg in state:": "junta-dkms ainda é relatado pelo dpkg no estado:",
"gasket DKMS entries removed.": "Entradas DKMS de gasket removidas.",
"gasket-dkms has been fully removed from this system.": "gasket-dkms foi totalmente removido deste sistema.",
"gasket-dkms is still reported by dpkg in state:": "gasket-dkms ainda é indicado pelo dpkg no estado:",
"gawk installed": "gawk instalado",
"google/gasket-driver cloned (fallback — will apply local patches).": "google/gasket-driver clonado (substituto aplicará patches locais).",
"gpg not found; trying apt-key fallback": "gpg não encontrado; tentando substituto do apt-key",
@@ -5317,5 +5323,10 @@
"⚠ Disk data will NOT be erased.": "⚠ Os dados do disco NÃO serão apagados.",
"⚠ Disk will be unmounted and removed from /etc/fstab.": "⚠ O disco será desmontado e removido de /etc/fstab.",
"⚠ The /etc/fstab entry will be removed.": "⚠ A entrada /etc/fstab será removida.",
"⚠ The disk will be unmounted.": "⚠ O disco será desmontado."
"⚠ The disk will be unmounted.": "⚠ O disco será desmontado.",
"Conflicting ZFS ARC settings detected in:": "Configurações ZFS ARC em conflito detectadas em:",
"Conflicting ZFS ARC settings backed up and reconciled:": "Configurações ZFS ARC em conflito salvaguardadas e corrigidas:",
"Failed to reconcile conflicting ZFS ARC settings.": "Não foi possível corrigir as configurações ZFS ARC em conflito.",
"External ZFS ARC settings restored:": "Configurações ZFS ARC externas restauradas:",
"External ZFS configuration changed after the ProxMenux migration; current file and backup preserved:": "A configuração ZFS externa foi alterada após a migração do ProxMenux; o ficheiro atual e a cópia de segurança foram preservados:"
}
+23 -12
View File
@@ -39,7 +39,7 @@
"A ZFS pool with this name already exists.": "ZFS pool s týmto názvom už existuje.",
"A ZFS pool with this name already exists:": "ZFS pool s týmto názvom už existuje:",
"A complete restore will:": "Úplná obnova vykoná:",
"A gasket DKMS registration is still present:": "Stále existuje registrácia tesnenia DKMS:",
"A gasket DKMS registration is still present:": "Stále existuje registrácia gasket DKMS:",
"A host reboot is required after this change.": "Po tejto zmene je potrebný reštart hosta.",
"A host reboot is required before starting the VM. Reboot now?": "Pred spustením VM je potrebný reštart servera. Reštartovať teraz?",
"A job with this ID already exists.": "Úloha s týmto ID už existuje.",
@@ -374,6 +374,12 @@
"Bandwidth test completed successfully": "Test priepustnosti bol úspešne dokončený",
"Base VM created with ID": "Základná VM bola vytvorená s ID",
"Bashrc customization completed": "Úprava bashrc je dokončená",
"Bash prompt path": "Cesta v príkazovom riadku Bash",
"Choose how the current directory is shown in the Bash prompt:": "Vyberte, ako sa má aktuálny adresár zobrazovať v príkazovom riadku Bash:",
"Current directory only": "Len aktuálny adresár",
"Full path": "Úplná cesta",
"The new prompt will be used in new terminal sessions.": "Nový príkazový riadok sa použije v nových reláciách terminálu.",
"To apply it to the current shell now, run:": "Ak ho chcete použiť v aktuálnej relácii shellu, spustite:",
"Basic Settings": "Základné nastavenia",
"Basic Utilities": "Základné nástroje",
"Before making any changes, we'll create a safety backup.": "Pred akoukoľvek zmenou vytvoríme bezpečnostnú zálohu.",
@@ -599,7 +605,7 @@
"Cleanup Complete": "Čistenie je dokončené",
"Cleanup completed. A reboot is recommended to fully apply pending kernel package configurations.": "Čistenie dokončené.Na úplné uplatnenie čakajúcich konfigurácií balíkov jadra sa odporúča reštart.",
"Cleanup finished": "Čistenie je dokončené",
"Cleanup legacy gasket-dkms": "Vyčistenie staršieho tesnenia-dkms",
"Cleanup legacy gasket-dkms": "Vyčist starší balík gasket-dkms",
"Cleanup partial VM?": "Vyčistiť čiastočne vytvorenú VM?",
"Clear configured target": "Vymazať nastavený cieľ",
"Clear pool error state": "Vyčistiť chybový stav poolu",
@@ -2380,8 +2386,8 @@
"Launching GPU passthrough assistant for VM": "Spúšťam sprievodcu priamym priradením GPU pre VM",
"Legacy PVE 8 .list files commented or not present": "Staré .list súbory PVE 8 boli zakomentované alebo neexistujú",
"Legacy ceph.list commented or not present": "Starý ceph.list bol zakomentovaný alebo neexistuje",
"Legacy gasket-dkms cleanup could not be verified as complete.": "Vyčistenie starého tesnenia-dkms nebolo možné overiť ako dokončené.",
"Legacy gasket-dkms detected": "Bolo zistené staršie tesnenie-dkms",
"Legacy gasket-dkms cleanup could not be verified as complete.": "Dokončenie čistenia staršieho balíka gasket-dkms nebolo možné overiť.",
"Legacy gasket-dkms detected": "Bol zistený starší balík gasket-dkms",
"Legacy network tools (e.g., ifconfig)": "Staršie sieťové nástroje (napr. ifconfig)",
"Legend:": "Vysvetlivky:",
"Let's review your current network configuration.": "Pozrime si aktuálne nastavenie siete.",
@@ -2922,7 +2928,7 @@
"No folders found in /mnt. Please create a new folder.": "V /mnt sa nenašli žiadne priečinky. Vytvorte nový priečinok.",
"No folders found inside /mnt in the CT.": "V kontajneri sa v /mnt nenašli žiadne priečinky.",
"No format-safe disks are available.": "Nie sú dostupné žiadne disky vhodné na bezpečné formátovanie.",
"No gasket DKMS registrations remain.": "Nezostávajú žiadne registrácie DKMS tesnení.",
"No gasket DKMS registrations remain.": "Nezostávajú žiadne registrácie gasket DKMS.",
"No group creation required — uses world-writable sticky bit permissions.": "Nie je potrebné vytvárať skupinu - používa sa zápis pre všetkých so sticky bitom.",
"No host VFIO reconfiguration expected": "Neočakáva sa zmena VFIO nastavenia hosta",
"No host VFIO/native binding changes were required.": "Nebolo potrebné meniť VFIO ani natívne priradenie na serveri.",
@@ -3374,8 +3380,8 @@
"Proxmox web interface: Datacenter > Storage > Add > ZFS": "Webové rozhranie Proxmoxu: Datacenter > Storage > Add > ZFS",
"Proxmox web interface: Datacenter > Storage > Add > iSCSI": "Webové rozhranie Proxmoxu: Datacenter > Storage > Add > iSCSI",
"Pulling latest changes from GitHub...": "Sťahujem najnovšie zmeny z GitHubu...",
"Purge the gasket-dkms package": "Vyčistite balík tesnenia-dkms",
"Purging gasket-dkms package...": "Čistenie tesnenia-dkms balík...",
"Purge the gasket-dkms package": "Úplne odstrániť balík gasket-dkms",
"Purging gasket-dkms package...": "Balík gasket-dkms sa úplne odstraňuje...",
"Purging log2ram apt package...": "Úplne odstraňujem balík log2ram cez APT...",
"Quick health check (PASSED / FAILED)": "Rýchla kontrola stavu (PASSED / FAILED)",
"Quick health status — overall SMART result + key attributes": "Rýchly stav zdravia - celkový SMART výsledok + hlavné údaje",
@@ -3511,7 +3517,7 @@
"Remove Secure Gateway? State will be preserved.": "Odstrániť Secure Gateway? Stav bude zachovaný.",
"Remove custom paths": "Odstrániť vlastné cesty",
"Remove disk references from affected VM(s)/CT(s) config": "Odstrániť referencie na disk z nastavení dotknutých VM/CT",
"Remove every registered gasket DKMS version": "Odstráňte všetky registrované tesnenia verzie DKMS",
"Remove every registered gasket DKMS version": "Odstrániť všetky registrované verzie gasket DKMS",
"Remove iSCSI Storage": "Odstrániť iSCSI úložisko",
"Remove iSCSI storage definition:": "Odstrániť definíciu iSCSI úložiska:",
"Remove invalid port": "Odstrániť neplatný port",
@@ -3554,7 +3560,7 @@
"Removing any pre-existing gasket-dkms package...": "Odstraňujem prípadný existujúci balík gasket-dkms...",
"Removing conflicting utilities...": "Odstraňujem konfliktné nástroje...",
"Removing entropy generation optimization...": "Odstraňujem optimalizáciu generovania entropie...",
"Removing every registered gasket DKMS version...": "Odstránenie všetkých registrovaných tesnení verzie DKMS...",
"Removing every registered gasket DKMS version...": "Odstraňujú sa všetky registrované verzie gasket DKMS...",
"Removing filesystem signatures...": "Odstraňujem podpisy súborových systémov...",
"Removing from /etc/fstab...": "Odstraňujem z /etc/fstab...",
"Removing gasket DKMS modules...": "Odstraňujem gasket DKMS moduly...",
@@ -5035,8 +5041,8 @@
"fstab line:": "riadok vo fstab:",
"fstab references UUIDs/devices not present on this host:": "fstab odkazuje na UUID/zariadenia, ktoré na tomto hostovi nie sú:",
"gasket DKMS entries removed.": "gasket DKMS záznamy boli odstránené.",
"gasket-dkms has been fully removed from this system.": "tesnenie-dkms bolo z tohto systému úplne odstránené.",
"gasket-dkms is still reported by dpkg in state:": "tesnenie-dkms stále hlási dpkg v stave:",
"gasket-dkms has been fully removed from this system.": "gasket-dkms bol z tohto systému úplne odstránený.",
"gasket-dkms is still reported by dpkg in state:": "dpkg stále hlási gasket-dkms v stave:",
"gawk installed": "gawk je nainštalovaný",
"google/gasket-driver cloned (fallback — will apply local patches).": "google/gasket-driver bol naklonovaný (náhradná možnosť - použijú sa lokálne záplaty).",
"gpg not found; trying apt-key fallback": "gpg sa nenašiel; skúšam náhradný apt-key postup",
@@ -5317,5 +5323,10 @@
"⚠ Disk data will NOT be erased.": "⚠ Dáta na disku sa NEVYMAŽÚ.",
"⚠ Disk will be unmounted and removed from /etc/fstab.": "⚠ Disk sa odpojí a odstráni z /etc/fstab.",
"⚠ The /etc/fstab entry will be removed.": "⚠ Záznam v /etc/fstab bude odstránený.",
"⚠ The disk will be unmounted.": "⚠ Disk bude odpojený."
"⚠ The disk will be unmounted.": "⚠ Disk bude odpojený.",
"Conflicting ZFS ARC settings detected in:": "Konfliktné nastavenia ZFS ARC boli zistené v:",
"Conflicting ZFS ARC settings backed up and reconciled:": "Konfliktné nastavenia ZFS ARC boli zálohované a opravené:",
"Failed to reconcile conflicting ZFS ARC settings.": "Konfliktné nastavenia ZFS ARC sa nepodarilo opraviť.",
"External ZFS ARC settings restored:": "Externé nastavenia ZFS ARC boli obnovené:",
"External ZFS configuration changed after the ProxMenux migration; current file and backup preserved:": "Externá konfigurácia ZFS sa po migrácii ProxMenux zmenila; aktuálny súbor aj záloha zostali zachované:"
}
+41 -30
View File
@@ -39,12 +39,12 @@
"A ZFS pool with this name already exists.": "En ZFS-pool med detta namn finns redan.",
"A ZFS pool with this name already exists:": "En ZFS-pool med detta namn finns redan:",
"A complete restore will:": "En fullständig återställning kommer att:",
"A gasket DKMS registration is still present:": "En packning DKMS-registrering finns fortfarande:",
"A gasket DKMS registration is still present:": "En gasket DKMS-registrering finns fortfarande:",
"A host reboot is required after this change.": "En omstart av värddatorn krävs efter denna ändring.",
"A host reboot is required before starting the VM. Reboot now?": "En omstart av värddatorn krävs innan den virtuella datorn startas. Starta om nu?",
"A job with this ID already exists.": "Ett jobb med detta ID finns redan.",
"A keyfile is installed at:": "En nyckelfil är installerad på:",
"A legacy gasket-dkms package was found on this host, but no Coral M.2 / PCIe hardware is present.": "Ett äldre packet-dkms-paket hittades på denna värd, men ingen Coral M.2/PCIe-hårdvara finns.",
"A legacy gasket-dkms package was found on this host, but no Coral M.2 / PCIe hardware is present.": "Ett äldre gasket-dkms-paket hittades på denna värd, men ingen Coral M.2/PCIe-hårdvara finns.",
"A new ProxMenux version is available:": "En ny ProxMenux-version är tillgänglig:",
"A new kernel is staged for the next boot:": "En ny kärna är iscensatt för nästa uppstart:",
"A newer version is available:": "En nyare version finns tillgänglig:",
@@ -374,6 +374,12 @@
"Bandwidth test completed successfully": "Bandbreddstestet slutförts framgångsrikt",
"Base VM created with ID": "Bas-VM skapad med ID",
"Bashrc customization completed": "Bashrc-anpassning slutförd",
"Bash prompt path": "Sökväg i Bash-prompten",
"Choose how the current directory is shown in the Bash prompt:": "Välj hur den aktuella katalogen visas i Bash-prompten:",
"Current directory only": "Endast aktuell katalog",
"Full path": "Fullständig sökväg",
"The new prompt will be used in new terminal sessions.": "Den nya prompten används i nya terminalsessioner.",
"To apply it to the current shell now, run:": "För att använda den i den aktuella shellsessionen nu, kör:",
"Basic Settings": "Grundinställningar",
"Basic Utilities": "Grundläggande verktyg",
"Before making any changes, we'll create a safety backup.": "Innan vi gör några ändringar skapar vi en säkerhetskopia.",
@@ -413,9 +419,9 @@
"Bridge Configuration Analysis": "Bryggkonfigurationsanalys",
"Bridge:": "Bro:",
"Bridges analyzed": "Broar analyserade",
"Broken gasket-dkms package state recovered.": "Trasig packning-dkms-pakettillstånd återställd.",
"Broken gasket-dkms package state recovered.": "Det trasiga pakettillståndet för gasket-dkms återställdes.",
"Browse manually (advanced)...": "Bläddra manuellt (avancerat)...",
"Build and install the gasket and apex kernel modules (DKMS)": "Bygg och installera packningen och apex kernel moduler (DKMS)",
"Build and install the gasket and apex kernel modules (DKMS)": "Bygg och installera kärnmodulerna gasket och apex (DKMS)",
"Build dependencies installed.": "Byggberoenden installerade.",
"CHANGES APPLIED SUCCESSFULLY": "ÄNDRINGAR HAR TILLÄMPATS",
"CIFS Client Tools: AVAILABLE": "CIFS-klientverktyg: TILLGÄNGLIGT",
@@ -851,8 +857,8 @@
"Copying installer to container": "Kopierar installationsprogram till container",
"Copying sources to": "Kopiera källor till",
"Coral APT repository ready.": "Coral APT-arkivet är klart.",
"Coral Actions": "Korallåtgärder",
"Coral M.2 / PCIe detected — installing gasket and apex kernel modules...": "Coral M.2/PCIe upptäckt — installerar packnings- och apexkärnmoduler...",
"Coral Actions": "Coral-åtgärder",
"Coral M.2 / PCIe detected — installing gasket and apex kernel modules...": "Coral M.2/PCIe upptäckt — installerar kärnmodulerna gasket och apex...",
"Coral M.2 Apex configuration added - device ready": "Coral M.2 Apex-konfiguration har lagts till - enheten är klar",
"Coral M.2 Apex configuration added - device will be available after reboot": "Coral M.2 Apex-konfiguration tillagd - enheten kommer att vara tillgänglig efter omstart",
"Coral M.2 Apex detected, configuring...": "Coral M.2 Apex upptäcktes, konfigurerar...",
@@ -867,9 +873,9 @@
"Coral USB configuration added - device detected": "Coral USB-konfiguration tillagd - enhet upptäckt",
"Coral USB configured but device not currently connected": "Coral USB konfigurerad men enheten är inte ansluten för närvarande",
"Coral USB runtime installed. No reboot required.": "Coral USB runtime installerad. Ingen omstart krävs.",
"Coral hardware configuration completed for container": "Korallhårdvarukonfiguration slutförd för container",
"Coral hardware configuration completed for container": "Coral-maskinvarukonfiguration slutförd för behållaren",
"Coral kernel modules unloaded.": "Coral kernel moduler urladdade.",
"Coral packages purged.": "Korallpaket rensade.",
"Coral packages purged.": "Coral-paket rensade.",
"Coral uninstallation completed.": "Coral avinstallation slutförd.",
"Core Proxmox packages reinstalled successfully": "Core Proxmox-paket har installerats om",
"Core packages": "Kärnpaket",
@@ -879,7 +885,7 @@
"Could not authorize the key via 'pct exec' on": "Kunde inte auktorisera nyckeln via 'pct exec' på",
"Could not back up the existing auth.json": "Det gick inte att säkerhetskopiera den befintliga auth.json",
"Could not change VM virtual display to vga: std": "Det gick inte att ändra virtuell skärm till vga: std",
"Could not clone any gasket-driver repository. Check your internet connection and": "Kunde inte klona någon packningsdrivrutin. Kontrollera din internetanslutning och",
"Could not clone any gasket-driver repository. Check your internet connection and": "Kunde inte klona något gasket-driver-arkiv. Kontrollera internetanslutningen och",
"Could not configure IOMMU kernel parameters automatically. Configure manually and reboot.": "Kunde inte konfigurera IOMMU kärnparametrar automatiskt. Konfigurera manuellt och starta om.",
"Could not copy the PVE keyfile into place. Check permissions on:": "Det gick inte att kopiera PVE-nyckelfilen på plats. Kontrollera behörigheter på:",
"Could not copy the keyfile into place.": "Kunde inte kopiera nyckelfilen på plats.",
@@ -1136,7 +1142,7 @@
"Detected RAM:": "Upptäckt RAM:",
"Detected a mounted directory from host. Setting up shared group...": "Upptäckte en monterad katalog från värden. Konfigurerar delad grupp...",
"Detected backups — newest first:": "Upptäckta säkerhetskopior — senaste först:",
"Detected broken gasket-dkms package state:": "Detekterat trasigt packet-dkms-pakettillstånd:",
"Detected broken gasket-dkms package state:": "Ett trasigt pakettillstånd för gasket-dkms upptäcktes:",
"Detected existing Samba user:": "Upptäckte befintlig Samba-användare:",
"Detected filesystem:": "Upptäckt filsystem:",
"Detected nftables - using nftables ban action": "Upptäckt nftables - med nftables förbudsåtgärd",
@@ -2380,8 +2386,8 @@
"Launching GPU passthrough assistant for VM": "Lanserar GPU-passthrough-assistent för virtuella datorer",
"Legacy PVE 8 .list files commented or not present": "Äldre PVE 8 .list-filer kommenterade eller saknas",
"Legacy ceph.list commented or not present": "Legacy ceph.list kommenterade eller inte närvarande",
"Legacy gasket-dkms cleanup could not be verified as complete.": "Rengöring av äldre packning-dkms kunde inte verifieras som slutförd.",
"Legacy gasket-dkms detected": "Äldre packning-dkms upptäcktes",
"Legacy gasket-dkms cleanup could not be verified as complete.": "Rensningen av det äldre gasket-dkms-paketet kunde inte verifieras som slutförd.",
"Legacy gasket-dkms detected": "Äldre gasket-dkms upptäcktes",
"Legacy network tools (e.g., ifconfig)": "Äldre nätverksverktyg (t.ex. ifconfig)",
"Legend:": "Legend:",
"Let's review your current network configuration.": "Låt oss granska din nuvarande nätverkskonfiguration.",
@@ -2786,7 +2792,7 @@
"No Changes Needed": "Inga ändringar behövs",
"No Cleanup Needed": "Ingen rengöring behövs",
"No Controller/NVMe selected for now.": "Ingen styrenhet/NVMe har valts för tillfället.",
"No Coral Detected": "Ingen korall upptäckt",
"No Coral Detected": "Ingen Coral upptäckt",
"No Coral TPU device was found on this host (neither PCIe/M.2 nor USB).": "Ingen Coral TPU-enhet hittades på denna värd (varken PCIe/M.2 eller USB).",
"No Custom Logos Found": "Inga anpassade logotyper hittades",
"No Disk Images Found": "Inga diskbilder hittades",
@@ -2922,7 +2928,7 @@
"No folders found in /mnt. Please create a new folder.": "Inga mappar hittades i /mnt. Skapa en ny mapp.",
"No folders found inside /mnt in the CT.": "Inga mappar hittades inuti /mnt i CT.",
"No format-safe disks are available.": "Inga formatsäkra diskar är tillgängliga.",
"No gasket DKMS registrations remain.": "Inga DKMS-registreringar kvar.",
"No gasket DKMS registrations remain.": "Inga gasket DKMS-registreringar finns kvar.",
"No group creation required — uses world-writable sticky bit permissions.": "Inget gruppskapande krävs använder världsskrivbara sticky bit-behörigheter.",
"No host VFIO reconfiguration expected": "Ingen värd VFIO-omkonfiguration förväntas",
"No host VFIO/native binding changes were required.": "Inga värd VFIO/native bindningsändringar krävdes.",
@@ -3132,7 +3138,7 @@
"PCI passthrough, TPM state, cloud-init, snapshots, Proxmox-specific hooks": "PCI-genomföring, TPM-tillstånd, moln-init, ögonblicksbilder, Proxmox-specifika krokar",
"PCI reset method": "PCI-återställningsmetod",
"PCIe GPU passthrough requires:": "PCIe GPU-genomföring kräver:",
"PCIe/M.2 gasket-dkms": "PCIe/M.2 packning-dkms",
"PCIe/M.2 gasket-dkms": "PCIe/M.2 gasket-dkms",
"POSIX ACLs applied (access + default for inheritance).": "POSIX ACL:er tillämpas (åtkomst + standard för arv).",
"PVE application manager updated": "PVE-applikationshanteraren uppdaterad",
"PVE cache regenerated": "PVE-cache regenererad",
@@ -3258,7 +3264,7 @@
"Power state D3cold/D0 transitions may be inaccessible": "Strömtillstånd D3cold/D0-övergångar kan vara otillgängliga",
"Pre-check found": "Förhandskontroll hittades",
"Pre-configure destinations so you don't have to enter them every time you back up.": "Förkonfigurera destinationer så att du inte behöver ange dem varje gång du säkerhetskopierar.",
"Pre-existing gasket-dkms package removed.": "Redan existerande packning-dkms-paket borttaget.",
"Pre-existing gasket-dkms package removed.": "Det befintliga gasket-dkms-paketet har tagits bort.",
"Pre-restore backup:": "Föråterställ säkerhetskopia:",
"Pre-upgrade check FAILED: the simulation shows that 'proxmox-ve' would be REMOVED.\n This indicates a repository or dependency issue and upgrading now could break your Proxmox installation.": "Kontroll före uppgraderingen MISSLYCKades: simuleringen visar att \"proxmox-ve\" skulle tas bort.\n Detta indikerar ett arkiv eller beroendeproblem och uppgradering nu kan bryta din Proxmox-installation.",
"Pre-upgrade simulation passed: 'proxmox-ve' will be kept or upgraded safely.": "Simulering före uppgradering godkänd: 'proxmox-ve' kommer att bevaras eller uppgraderas säkert.",
@@ -3374,8 +3380,8 @@
"Proxmox web interface: Datacenter > Storage > Add > ZFS": "Proxmox webbgränssnitt: Datacenter > Lagring > Lägg till > ZFS",
"Proxmox web interface: Datacenter > Storage > Add > iSCSI": "Proxmox webbgränssnitt: Datacenter > Lagring > Lägg till > iSCSI",
"Pulling latest changes from GitHub...": "Hämtar senaste ändringarna från GitHub...",
"Purge the gasket-dkms package": "Rensa packning-dkms-paketet",
"Purging gasket-dkms package...": "Rensa packning-dkms-paket...",
"Purge the gasket-dkms package": "Ta bort gasket-dkms-paketet helt",
"Purging gasket-dkms package...": "Tar bort gasket-dkms-paketet helt...",
"Purging log2ram apt package...": "Rensar log2ram apt-paket...",
"Quick health check (PASSED / FAILED)": "Snabb hälsokontroll (GODKÄND / MISLYCKAD)",
"Quick health status — overall SMART result + key attributes": "Snabb hälsostatus — övergripande SMART-resultat + nyckelattribut",
@@ -3511,7 +3517,7 @@
"Remove Secure Gateway? State will be preserved.": "Ta bort Secure Gateway? Staten kommer att bevaras.",
"Remove custom paths": "Ta bort anpassade sökvägar",
"Remove disk references from affected VM(s)/CT(s) config": "Ta bort diskreferenser från berörda virtuella datorer/CT-konfigurationer",
"Remove every registered gasket DKMS version": "Ta bort alla registrerade DKMS-versioner av packningar",
"Remove every registered gasket DKMS version": "Ta bort alla registrerade gasket DKMS-versioner",
"Remove iSCSI Storage": "Ta bort iSCSI-lagring",
"Remove iSCSI storage definition:": "Ta bort iSCSI-lagringsdefinition:",
"Remove invalid port": "Ta bort ogiltig port",
@@ -3551,13 +3557,13 @@
"Removing OpenVSwitch...": "Tar bort OpenVSwitch...",
"Removing ProxMenux persistent NIC .link files...": "Tar bort ProxMenux beständiga NIC .link-filer...",
"Removing VFIO ownership for selected GPU(s)...": "Tar bort VFIO-äganderätten för valda GPU(er)...",
"Removing any pre-existing gasket-dkms package...": "Ta bort eventuellt redan existerande packning-dkms-paket...",
"Removing any pre-existing gasket-dkms package...": "Tar bort eventuella befintliga gasket-dkms-paket...",
"Removing conflicting utilities...": "Tar bort motstridiga verktyg...",
"Removing entropy generation optimization...": "Tar bort entropigenereringsoptimering...",
"Removing every registered gasket DKMS version...": "Ta bort alla registrerade packningar DKMS-versioner...",
"Removing every registered gasket DKMS version...": "Tar bort alla registrerade gasket DKMS-versioner...",
"Removing filesystem signatures...": "Tar bort filsystemsignaturer...",
"Removing from /etc/fstab...": "Tar bort från /etc/fstab...",
"Removing gasket DKMS modules...": "Tar bort packningen DKMS-moduler...",
"Removing gasket DKMS modules...": "Tar bort gasket DKMS-moduler...",
"Removing gateway...": "Tar bort gateway...",
"Removing guest agent...": "Tar bort gästagent...",
"Removing invalid configurations...": "Tar bort ogiltiga konfigurationer...",
@@ -4327,7 +4333,7 @@
"The current driver will be completely uninstalled before installing the new version. Continue?": "Den aktuella drivrutinen kommer att avinstalleras helt innan den nya versionen installeras. Fortsätta?",
"The directory does not exist in the CT.": "Katalogen finns inte i CT.",
"The disk": "Disken",
"The dpkg package database is clean.": "Dpkg-paketdatabasen är ren.",
"The dpkg package database is clean.": "Paketdatabasen för dpkg är ren.",
"The file does not exist, is empty or is not readable.": "Filen finns inte, är tom eller är inte läsbar.",
"The filesystem": "Filsystemet",
"The following DKMS-managed drivers will now be rebuilt against it so they keep working after reboot:": "Följande DKMS-hanterade drivrutiner kommer nu att byggas om mot det så att de fortsätter att fungera efter omstart:",
@@ -4421,7 +4427,7 @@
"This cleanup will:": "Denna rensning kommer:",
"This container does not have apt-get. NFS client installation only supports Debian/Ubuntu containers.": "Den här behållaren har inte apt-get. NFS-klientinstallation stöder endast Debian/Ubuntu-behållare.",
"This container does not have apt-get. Samba client installation only supports Debian/Ubuntu containers.": "Den här behållaren har inte apt-get. Samba-klientinstallationen stöder endast Debian/Ubuntu-behållare.",
"This container has no GPU configured. Coral TPU works best alongside hardware video decoding (Quick Sync, VA-API, NVENC) for apps like Frigate.": "Den här behållaren har ingen GPU konfigurerad. Coral TPU fungerar bäst tillsammans med hårdvaruvideoavkodning (Quick Sync, VA-API, NVENC) för appar som Fregate.",
"This container has no GPU configured. Coral TPU works best alongside hardware video decoding (Quick Sync, VA-API, NVENC) for apps like Frigate.": "Den här behållaren har ingen GPU konfigurerad. Coral TPU fungerar bäst tillsammans med hårdvaruvideoavkodning (Quick Sync, VA-API, NVENC) för appar som Frigate.",
"This converts all directory UIDs/GIDs by adding 100000": "Detta konverterar alla katalog-UID:n/GID:n genom att lägga till 100000",
"This converts all file UIDs/GIDs by adding 100000": "Detta konverterar alla fil-UID:n/GID:n genom att lägga till 100000",
"This creates a backup in case you need to revert changes": "Detta skapar en säkerhetskopia om du behöver återställa ändringar",
@@ -4482,7 +4488,7 @@
"This will reinstall the Stable version from the main branch and disable beta update checks.\n\nContinue?": "Detta kommer att installera om den stabila versionen från huvudgrenen och inaktivera betauppdateringskontroller.\n\nFortsätta?",
"This will remove NVIDIA drivers and related configuration. Do you want to continue?": "Detta tar bort NVIDIA-drivrutiner och relaterad konfiguration. Vill du fortsätta?",
"This will remove and reinstall Lynis from the latest GitHub source. Continue?": "Detta kommer att ta bort och installera om Lynis från den senaste GitHub-källan. Fortsätta?",
"This will remove the Coral TPU drivers (gasket DKMS + libedgetpu) and related configuration. Any LXC container with apex passthrough will lose access to /dev/apex_* after reboot. Continue?": "Detta kommer att ta bort Coral TPU-drivrutinerna (packning DKMS + libedgetpu) och relaterad konfiguration. Alla LXC-behållare med apex-passthrough kommer att förlora åtkomst till /dev/apex_* efter omstart. Fortsätta?",
"This will remove the Coral TPU drivers (gasket DKMS + libedgetpu) and related configuration. Any LXC container with apex passthrough will lose access to /dev/apex_* after reboot. Continue?": "Detta kommer att ta bort Coral TPU-drivrutinerna (gasket DKMS + libedgetpu) och relaterad konfiguration. Alla LXC-behållare med apex-passthrough kommer att förlora åtkomst till /dev/apex_* efter omstart. Fortsätta?",
"This will remove the mount from /etc/fstab and delete credentials if present.": "Detta kommer att ta bort monteringen från /etc/fstab och ta bort referenser om det finns.",
"This will remove the mount from /etc/fstab.": "Detta tar bort monteringen från /etc/fstab.",
"This will restart the network service and may cause a brief disconnection. Continue?": "Detta kommer att starta om nätverkstjänsten och kan orsaka en kort frånkoppling. Fortsätta?",
@@ -4511,7 +4517,7 @@
"To revert changes:": "Så här återställer du ändringar:",
"To start the VM:": "Så här startar du VM:n:",
"To stop:": "För att stoppa:",
"To use Coral from a regular app, install the libedgetpu runtime via the usual method for your distro (community package or build from source). The simplest path is to run an app container that bundles the runtime — e.g. the Frigate Docker image — passing the device through with": "För att använda Coral från en vanlig app, installera libedgetpu runtime via den vanliga metoden för din distro (community-paket eller bygg från källkod). Den enklaste vägen är att köra en app-behållare som buntar ihop körtiden — t.ex. Fregate Docker-bilden — skickar enheten igenom med",
"To use Coral from a regular app, install the libedgetpu runtime via the usual method for your distro (community package or build from source). The simplest path is to run an app container that bundles the runtime — e.g. the Frigate Docker image — passing the device through with": "För att använda Coral från en vanlig app, installera libedgetpu runtime via den vanliga metoden för din distro (community-paket eller bygg från källkod). Den enklaste vägen är att köra en app-behållare som inkluderar runtime-miljön — till exempel Docker-avbildningen för Frigate — och skicka enheten vidare med",
"To use GPU passthrough, please create a new VM configured with:": "För att använda GPU-passthrough, skapa en ny virtuell dator konfigurerad med:",
"To use a custom Fastfetch logo, place your ASCII logo file in:\n\n/usr/local/share/fastfetch/logos/\n\nThe file should not exceed 35 lines to fit properly in the terminal.\n\nPress OK to continue and select your logo.": "För att använda en anpassad Fastfetch-logotyp, placera din ASCII-logotypfil i:\n\n/usr/local/share/fastfetch/logos/\n\nFilen bör inte överstiga 35 rader för att passa ordentligt i terminalen.\n\nTryck på OK för att fortsätta och välj din logotyp.",
"To use the GPU again in LXC, run Add GPU to LXC from GPUs and Coral-TPU Menu": "För att använda GPU igen i LXC, kör Lägg till GPU till LXC från GPU:er och Coral-TPU Menu",
@@ -4883,7 +4889,7 @@
"Without a usable reset path, passthrough reliability is poor and VM": "Utan en användbar återställningsväg är tillförlitligheten för genomkoppling dålig och VM",
"Working directory:": "Arbetskatalog:",
"Works with LVM, ZFS, and BTRFS storage types": "Fungerar med LVM, ZFS och BTRFS lagringstyper",
"Would you like to continue in passthrough-only mode? The libedgetpu APT install will be skipped, the Coral device will still be visible inside the container (e.g. /dev/apex_0), and you can install the runtime yourself or use an app container that bundles it (e.g. the Frigate Docker image).": "Vill du fortsätta i endast passthrough-läge? Libedgetpu APT-installationen kommer att hoppas över, Coral-enheten kommer fortfarande att vara synlig inuti behållaren (t.ex. /dev/apex_0), och du kan installera körtiden själv eller använda en appbehållare som paketerar den (t.ex. Fregate Docker-bilden).",
"Would you like to continue in passthrough-only mode? The libedgetpu APT install will be skipped, the Coral device will still be visible inside the container (e.g. /dev/apex_0), and you can install the runtime yourself or use an app container that bundles it (e.g. the Frigate Docker image).": "Vill du fortsätta i endast passthrough-läge? Installationen av libedgetpu via APT hoppas över, Coral-enheten förblir synlig i behållaren (t.ex. /dev/apex_0), och du kan installera runtime-miljön själv eller använda en appbehållare som inkluderar den (t.ex. Docker-avbildningen för Frigate).",
"Would you like to see the current": "Vill du se strömmen",
"Write access confirmed for user:": "Skrivåtkomst bekräftad för användare:",
"Write access confirmed.": "Skrivåtkomst bekräftad.",
@@ -5016,7 +5022,7 @@
"fail2ban-client could not communicate with the server": "fail2ban-client kunde inte kommunicera med servern",
"fail2ban-client successfully communicated with the server": "fail2ban-klient kommunicerade med servern",
"failed:": "misslyckades:",
"feranick fork unreachable. Falling back to google/gasket-driver...": "feranick gaffel oåtkomlig. Faller tillbaka till google/gasket-driver...",
"feranick fork unreachable. Falling back to google/gasket-driver...": "feranick-forken kan inte nås. Faller tillbaka google/gasket-driver...",
"feranick/gasket-driver cloned (actively maintained, kernel 6.12+ ready).": "feranick/gasket-driver klonad (aktivt underhållen, kärna 6.12+ redo).",
"file?": "fil?",
"files": "filer",
@@ -5034,7 +5040,7 @@
"fstab entry exists": "fstab-posten finns",
"fstab line:": "fstab rad:",
"fstab references UUIDs/devices not present on this host:": "fstab refererar till UUID/enheter som inte finns på denna värd:",
"gasket DKMS entries removed.": "packning DKMS-poster borttagna.",
"gasket DKMS entries removed.": "gasket DKMS-poster har tagits bort.",
"gasket-dkms has been fully removed from this system.": "gasket-dkms har tagits bort helt från detta system.",
"gasket-dkms is still reported by dpkg in state:": "gasket-dkms rapporteras fortfarande av dpkg i tillstånd:",
"gawk installed": "gawk installerad",
@@ -5317,5 +5323,10 @@
"⚠ Disk data will NOT be erased.": "⚠ Diskdata kommer INTE att raderas.",
"⚠ Disk will be unmounted and removed from /etc/fstab.": "⚠ Disken kommer att avmonteras och tas bort från /etc/fstab.",
"⚠ The /etc/fstab entry will be removed.": "⚠ /etc/fstab-posten kommer att tas bort.",
"⚠ The disk will be unmounted.": "⚠ Disken kommer att avmonteras."
"⚠ The disk will be unmounted.": "⚠ Disken kommer att avmonteras.",
"Conflicting ZFS ARC settings detected in:": "Motstridiga ZFS ARC-inställningar upptäcktes i:",
"Conflicting ZFS ARC settings backed up and reconciled:": "Motstridiga ZFS ARC-inställningar säkerhetskopierades och rättades:",
"Failed to reconcile conflicting ZFS ARC settings.": "Det gick inte att rätta de motstridiga ZFS ARC-inställningarna.",
"External ZFS ARC settings restored:": "Externa ZFS ARC-inställningar återställdes:",
"External ZFS configuration changed after the ProxMenux migration; current file and backup preserved:": "Den externa ZFS-konfigurationen ändrades efter ProxMenux-migreringen; aktuell fil och säkerhetskopia bevarades:"
}
+23 -6
View File
@@ -441,8 +441,8 @@ EOF
# ==========================================================
optimize_memory_settings() {
local FUNC_VERSION="1.1"
# description: Tune swappiness, dirty page ratios, overcommit and compaction proactiveness for VM hosts.
local FUNC_VERSION="1.2"
# description: Tune swappiness, dirty page ratios and compaction proactiveness for VM hosts without overriding the kernel's memory-overcommit policy.
msg_info "$(translate "Optimizing memory settings...")"
NECESSARY_REBOOT=1
@@ -451,7 +451,6 @@ optimize_memory_settings() {
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
vm.overcommit_memory = 1
vm.max_map_count = 262144
EOF
@@ -626,13 +625,29 @@ EOF
# ==========================================================
customize_bashrc() {
local FUNC_VERSION="1.0"
# description: Inject the ProxMenux core bashrc block (aliases, prompt, history) into root's .bashrc, idempotent via begin/end markers.
local FUNC_VERSION="1.1"
# description: Install the managed ProxMenux Bash prompt and aliases while preserving or selecting the short/full working-directory style.
msg_info "$(translate "Customizing bashrc for root user...")"
local bashrc="/root/.bashrc"
local bash_profile="/root/.bash_profile"
local marker_begin="# BEGIN PMX_CORE_BASHRC"
local marker_end="# END PMX_CORE_BASHRC"
local prompt_path_escape='\W'
# Automated installs remain non-interactive. Preserve a previous
# ProxMenux choice on re-run and use the compact \W style on first use.
if sed -n "/^${marker_begin}$/,/^${marker_end}$/p" "$bashrc" 2>/dev/null | grep -Fq '\w'; then
prompt_path_escape='\w'
fi
case "${PMX_BASHRC_PATH_STYLE:-}" in
short) prompt_path_escape='\W' ;;
"") ;;
full) prompt_path_escape='\w' ;;
*)
msg_error "PMX_BASHRC_PATH_STYLE must be 'short' or 'full'."
return 1
;;
esac
[ -f "${bashrc}.bak" ] || cp "$bashrc" "${bashrc}.bak" > /dev/null 2>&1
@@ -647,7 +662,7 @@ customize_bashrc() {
${marker_begin}
# ProxMenux core customizations
export HISTTIMEFORMAT="%d/%m/%y %T "
export PS1="\[\e[31m\][\[\e[m\]\[\e[38;5;172m\]\u\[\e[m\]@\[\e[38;5;153m\]\h\[\e[m\] \[\e[38;5;214m\]\W\[\e[m\]\[\e[31m\]]\[\e[m\]\\$ "
export PS1="\[\e[31m\][\[\e[m\]\[\e[38;5;172m\]\u\[\e[m\]@\[\e[38;5;153m\]\h\[\e[m\] \[\e[38;5;214m\]${prompt_path_escape}\[\e[m\]\[\e[31m\]]\[\e[m\]\\$ "
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
@@ -665,6 +680,8 @@ EOF
fi
msg_ok "$(translate "Bashrc customization completed")"
msg_info "$(translate "The new prompt will be used in new terminal sessions.")"
msg_info "$(translate "To apply it to the current shell now, run:") source /root/.bashrc"
register_tool "bashrc_custom" true "$FUNC_VERSION"
}
+158 -21
View File
@@ -1208,11 +1208,77 @@ EOF
_reconcile_external_zfs_arc_settings() {
local managed_conf="$1"
local backup_dir="$BASE_DIR/backups/zfs_arc"
local manifest="$backup_dir/manifest.tsv"
local conf_file backup_file tmp_file tmp_manifest post_hash
while IFS= read -r -d '' conf_file; do
[[ "$conf_file" == "$managed_conf" ]] && continue
if ! grep -Eq \
'^[[:space:]]*options[[:space:]]+zfs([[:space:]]|$).*zfs_arc_(min|max)=' \
"$conf_file" 2>/dev/null; then
continue
fi
msg_warn "$(translate "Conflicting ZFS ARC settings detected in:") $conf_file"
mkdir -p "$backup_dir" || return 1
touch "$manifest" || return 1
backup_file="$backup_dir/$(basename "$conf_file").before-proxmenux"
if [[ ! -f "$backup_file" ]]; then
cp -p "$conf_file" "$backup_file" || return 1
fi
tmp_file=$(mktemp "${conf_file}.proxmenux.XXXXXX") || return 1
cp -p "$conf_file" "$tmp_file" || {
rm -f "$tmp_file"
return 1
}
# Remove only zfs_arc_min/max tokens from active `options zfs`
# directives. Other ZFS module options and comments stay untouched.
awk '
/^[[:space:]]*options[[:space:]]+zfs([[:space:]]|$)/ {
line = $0
gsub(/[[:space:]]+zfs_arc_(min|max)=[^[:space:]#]+/, "", line)
if (line ~ /^[[:space:]]*options[[:space:]]+zfs[[:space:]]*$/) {
next
}
if (line ~ /^[[:space:]]*options[[:space:]]+zfs[[:space:]]*#/) {
sub(/^[[:space:]]*options[[:space:]]+zfs[[:space:]]*/, "", line)
}
print line
next
}
{ print }
' "$conf_file" > "$tmp_file" || {
rm -f "$tmp_file"
return 1
}
mv -f "$tmp_file" "$conf_file" || return 1
post_hash=$(sha256sum "$conf_file" | awk '{print $1}')
tmp_manifest=$(mktemp "${manifest}.XXXXXX") || return 1
awk -F '\t' -v path="$conf_file" '$1 != path' "$manifest" > "$tmp_manifest"
printf '%s\t%s\t%s\n' "$conf_file" "$backup_file" "$post_hash" >> "$tmp_manifest"
mv -f "$tmp_manifest" "$manifest" || return 1
msg_ok "$(translate "Conflicting ZFS ARC settings backed up and reconciled:") $conf_file"
done < <(find /etc/modprobe.d -maxdepth 1 -type f -name '*.conf' -print0 2>/dev/null)
}
optimize_zfs_arc() {
local FUNC_VERSION="1.1"
# description: Cap ZFS ARC max to a sensible fraction of host RAM so VMs don't fight the kernel for memory. Only sets zfs_arc_max; other OpenZFS tunables stay at their defaults.
local FUNC_VERSION="1.3"
# description: Cap ZFS ARC max using Proxmox VE's 10%-of-RAM policy (16 GiB ceiling), safely reconcile conflicting module settings and report the pool-size guideline before applying it.
local zfs_conf="/etc/modprobe.d/99-zfsarc.conf"
local ram_bytes arc_max
local gib=$((1024 * 1024 * 1024))
local tib=$((1024 * 1024 * 1024 * 1024))
local ram_kib ram_bytes arc_max current_arc_max pool_bytes=0 pool_size
local pool_tib pool_guideline arc_max_human current_arc_max_human pool_guideline_human
msg_info2 "$(translate "Optimizing ZFS ARC maximum size...")"
@@ -1225,20 +1291,51 @@ optimize_zfs_arc() {
return 0
fi
ram_bytes=$(awk '/MemTotal:/ { print $2 * 1024 }' /proc/meminfo)
if [[ -z "$ram_bytes" || "$ram_bytes" -le 0 ]]; then
ram_kib=$(awk '/MemTotal:/ { print $2; exit }' /proc/meminfo)
if [[ ! "$ram_kib" =~ ^[0-9]+$ || "$ram_kib" -le 0 ]]; then
msg_error "$(translate "Unable to determine the installed memory.")"
return 1
fi
ram_bytes=$((ram_kib * 1024))
if (( ram_bytes <= 16 * 1024 * 1024 * 1024 )); then
arc_max=$((512 * 1024 * 1024))
elif (( ram_bytes <= 32 * 1024 * 1024 * 1024 )); then
arc_max=$((1024 * 1024 * 1024))
else
arc_max=$((ram_bytes / 8))
arc_max=$((ram_bytes / 10))
(( arc_max > 16 * gib )) && arc_max=$((16 * gib))
(( arc_max < 64 * 1024 * 1024 )) && arc_max=$((64 * 1024 * 1024))
while read -r pool_size; do
[[ "$pool_size" =~ ^[0-9]+$ ]] || continue
pool_bytes=$((pool_bytes + pool_size))
done < <(zpool list -H -p -o size 2>/dev/null)
pool_tib=$(((pool_bytes + tib - 1) / tib))
pool_guideline=$((2 * gib + pool_tib * gib))
current_arc_max=$(awk '$1 == "c_max" { print $3; exit }' /proc/spl/kstat/zfs/arcstats 2>/dev/null || true)
if [[ ! "$current_arc_max" =~ ^[0-9]+$ ]]; then
current_arc_max=$(cat /sys/module/zfs/parameters/zfs_arc_max 2>/dev/null || true)
fi
if command -v numfmt >/dev/null 2>&1; then
arc_max_human=$(numfmt --to=iec-i --suffix=B "$arc_max")
pool_guideline_human=$(numfmt --to=iec-i --suffix=B "$pool_guideline")
if [[ "$current_arc_max" =~ ^[0-9]+$ ]]; then
current_arc_max_human=$(numfmt --to=iec-i --suffix=B "$current_arc_max")
fi
fi
arc_max_human=${arc_max_human:-"$arc_max bytes"}
pool_guideline_human=${pool_guideline_human:-"$pool_guideline bytes"}
current_arc_max_human=${current_arc_max_human:-${current_arc_max:-unknown}}
msg_info "$(translate "Current effective ZFS ARC maximum:") $current_arc_max_human"
msg_info "$(translate "Proposed ZFS ARC maximum:") $arc_max_human"
if (( arc_max < pool_guideline )); then
msg_warn "$(translate "The proposed ARC maximum is below Proxmox VE's pool-size guideline:") $pool_guideline_human"
msg_info2 "$(translate "Consider adding RAM or reducing the host workload if ZFS performance is insufficient.")"
fi
if ! _reconcile_external_zfs_arc_settings "$zfs_conf"; then
msg_error "$(translate "Failed to reconcile conflicting ZFS ARC settings.")"
return 1
fi
(( arc_max < 512 * 1024 * 1024 )) && arc_max=$((512 * 1024 * 1024))
if [[ -f "$zfs_conf" && ! -f "${zfs_conf}.bak" ]]; then
cp -p "$zfs_conf" "${zfs_conf}.bak"
@@ -1260,7 +1357,7 @@ EOF
fi
NECESSARY_REBOOT=1
msg_ok "$(translate "ZFS ARC maximum configured:") $arc_max $(translate "bytes")"
msg_ok "$(translate "ZFS ARC maximum configured:") $arc_max_human"
msg_success "$(translate "ZFS ARC optimization completed")"
register_tool "zfs_arc" true "$FUNC_VERSION"
}
@@ -1813,8 +1910,8 @@ enable_vfio_iommu() {
customize_bashrc() {
local FUNC_VERSION="1.0"
# description: Inject the ProxMenux core bashrc block (aliases, prompt, history) into root's .bashrc, idempotent via begin/end markers.
local FUNC_VERSION="1.1"
# description: Install the managed ProxMenux Bash prompt and aliases while preserving or selecting the short/full working-directory style.
msg_info2 "$(translate "Customizing bashrc for root user...")"
msg_info "$(translate "Customizing bashrc for root user...")"
@@ -1822,6 +1919,47 @@ customize_bashrc() {
local bash_profile="/root/.bash_profile"
local marker_begin="# BEGIN PMX_CORE_BASHRC"
local marker_end="# END PMX_CORE_BASHRC"
local prompt_path_escape='\W'
local prompt_path_style="${PMX_BASHRC_PATH_STYLE:-}"
local short_state="on"
local full_state="off"
local choice=""
# Preserve an existing ProxMenux-managed choice when the function is
# re-run. \W shows only the current directory; \w shows the full path.
if sed -n "/^${marker_begin}$/,/^${marker_end}$/p" "$bashrc" 2>/dev/null | grep -Fq '\w'; then
prompt_path_escape='\w'
short_state="off"
full_state="on"
fi
case "$prompt_path_style" in
short)
prompt_path_escape='\W'
;;
full)
prompt_path_escape='\w'
;;
"")
if [[ -t 0 && -t 1 ]] && command -v whiptail >/dev/null 2>&1; then
if ! choice=$(whiptail \
--title "$(translate "Bash prompt path")" \
--radiolist "$(translate "Choose how the current directory is shown in the Bash prompt:")" \
14 76 2 \
"short" "$(translate "Current directory only") (\\W)" "$short_state" \
"full" "$(translate "Full path") (\\w)" "$full_state" \
3>&1 1>&2 2>&3); then
msg_warn "$(translate "Cancelled by user.")"
return 1
fi
[[ "$choice" == "full" ]] && prompt_path_escape='\w' || prompt_path_escape='\W'
fi
;;
*)
msg_error "PMX_BASHRC_PATH_STYLE must be 'short' or 'full'."
return 1
;;
esac
[ -f "${bashrc}.bak" ] || cp "$bashrc" "${bashrc}.bak" > /dev/null 2>&1
@@ -1836,7 +1974,7 @@ customize_bashrc() {
${marker_begin}
# ProxMenux core customizations
export HISTTIMEFORMAT="%d/%m/%y %T "
export PS1="\[\e[31m\][\[\e[m\]\[\e[38;5;172m\]\u\[\e[m\]@\[\e[38;5;153m\]\h\[\e[m\] \[\e[38;5;214m\]\W\[\e[m\]\[\e[31m\]]\[\e[m\]\\$ "
export PS1="\[\e[31m\][\[\e[m\]\[\e[38;5;172m\]\u\[\e[m\]@\[\e[38;5;153m\]\h\[\e[m\] \[\e[38;5;214m\]${prompt_path_escape}\[\e[m\]\[\e[31m\]]\[\e[m\]\\$ "
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
@@ -1854,6 +1992,8 @@ EOF
fi
msg_ok "$(translate "Bashrc customization completed")"
msg_info "$(translate "The new prompt will be used in new terminal sessions.")"
msg_info "$(translate "To apply it to the current shell now, run:") source /root/.bashrc"
register_tool "bashrc_custom" true "$FUNC_VERSION"
}
@@ -1985,8 +2125,8 @@ remove_subscription_banner() {
optimize_memory_settings() {
local FUNC_VERSION="1.1"
# description: Tune swappiness, dirty page ratios, overcommit and compaction proactiveness for VM hosts.
local FUNC_VERSION="1.2"
# description: Tune swappiness, dirty page ratios and compaction proactiveness for VM hosts without overriding the kernel's memory-overcommit policy.
msg_info2 "$(translate "Optimizing memory settings...")"
NECESSARY_REBOOT=1
@@ -2010,9 +2150,6 @@ vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
# Allow memory overcommit to reduce allocation issues
vm.overcommit_memory = 1
# Avoid excessive virtual memory areas (safe for most applications)
vm.max_map_count = 262144
EOF
+42
View File
@@ -908,6 +908,11 @@ uninstall_pigz() {
}
uninstall_zfs_arc() {
local backup_dir="$BASE_DIR/backups/zfs_arc"
local manifest="$backup_dir/manifest.tsv"
local remaining_manifest=""
local original backup post_hash current_hash
msg_info2 "$(translate 'Reverting ZFS ARC tuning...')"
if [[ -f /etc/modprobe.d/99-zfsarc.conf.bak ]]; then
mv -f /etc/modprobe.d/99-zfsarc.conf.bak /etc/modprobe.d/99-zfsarc.conf
@@ -916,6 +921,43 @@ uninstall_zfs_arc() {
rm -f /etc/modprobe.d/99-zfsarc.conf
msg_ok "$(translate 'ZFS ARC config removed (kernel defaults will apply on reboot)')"
fi
if [[ -s "$manifest" ]]; then
remaining_manifest=$(mktemp "${manifest}.XXXXXX") || remaining_manifest=""
while IFS=$'\t' read -r original backup post_hash; do
[[ -n "$original" && -n "$backup" ]] || continue
current_hash=""
if [[ -f "$original" ]]; then
current_hash=$(sha256sum "$original" 2>/dev/null | awk '{print $1}')
fi
if [[ ! -e "$original" || "$current_hash" == "$post_hash" ]]; then
if [[ -f "$backup" ]] && cp -p "$backup" "$original"; then
rm -f "$backup"
msg_ok "$(translate 'External ZFS ARC settings restored:') $original"
elif [[ -n "$remaining_manifest" ]]; then
printf '%s\t%s\t%s\n' "$original" "$backup" "$post_hash" >> "$remaining_manifest"
fi
else
msg_warn "$(translate 'External ZFS configuration changed after the ProxMenux migration; current file and backup preserved:') $original"
if [[ -n "$remaining_manifest" ]]; then
printf '%s\t%s\t%s\n' "$original" "$backup" "$post_hash" >> "$remaining_manifest"
fi
fi
done < "$manifest"
if [[ -n "$remaining_manifest" ]]; then
if [[ -s "$remaining_manifest" ]]; then
mv -f "$remaining_manifest" "$manifest"
else
rm -f "$remaining_manifest" "$manifest"
fi
fi
rmdir "$backup_dir" 2>/dev/null || true
rmdir "$BASE_DIR/backups" 2>/dev/null || true
fi
update-initramfs -u -k all >/dev/null 2>&1 || true
if command -v proxmox-boot-tool >/dev/null 2>&1; then
proxmox-boot-tool refresh >/dev/null 2>&1 || true
@@ -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.",
"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