Compare commits

...
163 Commits
Author SHA1 Message Date
github-actions[bot] 88fa230e10 Update AppImage beta build (2026-11-05 19:26:42) 2026-11-05 19:26:42 +00:00
MacRimi 795f77f76f fix(oci): write the Nextcloud MariaDB bootstrap as the application user 2026-11-05 20:14:39 +01:00
MacRimi ecd94b45ec fix(oci): keep Tailscale starting once its web client is on 2026-11-05 20:09:40 +01:00
ProxMenuxBot eea782e4d1 chore(lang): auto-rebuild translation cache
Source: dc18463
Triggered by: push
2026-11-05 18:51:08 +00:00
MacRimiandGitHub dc18463965 Merge pull request #590 from jcastro/feature/oci-nextcloud-mariadb
feat(oci): add LinuxServer Nextcloud with MariaDB and Redis
2026-11-05 19:50:06 +01:00
MacRimi 256d1d911d fix(oci): generate the Nextcloud MariaDB administrator and keep its umask private
- The administrator password is generated at install and written to
  autoconfig.php, so Nextcloud installs itself on the first request and
  the setup page cannot be claimed by anyone else. The summary shows it.
- The private umask applies to the bootstrap only, not to /init.
- The bootstrap creates its files without following links and gives
  them to the application user with lchown.
- The startup check leaves out the default port of its scheme, so an
  application that trusts the host of its first request, like
  Nextcloud, opens from the LAN address.

Installed on a Proxmox host: Nextcloud 35.0.2 installs with the
generated administrator, opens from its LAN address and accepts a
WebDAV upload; the application runs with umask 0022.
2026-11-05 19:48:39 +01:00
MacRimi 745896e617 Merge develop into feature/oci-nextcloud-mariadb 2026-11-05 19:21:29 +01:00
MacRimi 13ac55ac82 fix(monitor): show a light Hermes logo in the dark theme 2026-11-05 19:20:37 +01:00
ProxMenuxBot 683595aefc chore(lang): auto-rebuild translation cache
Source: 3d19c93
Triggered by: push
2026-11-05 18:13:08 +00:00
MacRimiandGitHub 3d19c93c02 Merge pull request #468 from jcastro/feature/usbip-ssh-sharing
Add USB/IP device sharing over SSH
2026-11-05 19:11:55 +01:00
MacRimi 1753d3aaa5 fix(usbip): remove the transport account on uninstall and refuse USB NICs
- Uninstall removes the proxmenux-usbip account and its home when
  ProxMenux created them, so a reinstall does not revive old client keys.
- The client tunnel port can be bound again while earlier connections
  are in TIME_WAIT; restarting a client no longer waits a minute.
- USB network adapters are not offered: on many mini PCs one is the
  management link of the host.
- The share dialog explains the exceptional case that needs a reboot.
- The hardware menu keeps its name, so the scripts and docs that point
  to it stay correct.
2026-11-05 19:10:49 +01:00
MacRimi 7783f9a2ec Merge develop into feature/usbip-ssh-sharing 2026-11-05 19:04:00 +01:00
MacRimiandGitHub e30c592217 Merge pull request #595 from jcastro/feature/monitor-ovs-topology
feat(monitor): show Open vSwitch network topology
2026-11-05 18:46:54 +01:00
MacRimi 3090f1d772 fix(monitor): place guests behind the firewall on their OVS bridge
On an OVS bridge Proxmox links the firewall bridge fwbrNiM through its
own internal port fwlnNoM and creates no fwprNpM peer, so the guest was
shown on fwbrNiM. Check both links. Verified on an OVS 3.5 host with a
firewalled container.
2026-11-05 18:40:33 +01:00
MacRimi 163317f727 Merge develop into feature/monitor-ovs-topology 2026-11-05 18:40:33 +01:00
MacRimiandGitHub ce8ccab4de Merge pull request #596 from jcastro/feature/monitor-native-arm64-build
feat(monitor): add native ARM64 AppImage build validation
2026-11-05 18:21:10 +01:00
MacRimiandGitHub 202557f540 Merge pull request #594 from jcastro/fix/provider-model-availability
fix(ai): refresh Groq ordering and unavailable OpenRouter models
2026-11-05 18:20:32 +01:00
MacRimi d4525fb13e fix(oci): keep a device GID changed in Proxmox since the last operation 2026-11-05 18:19:49 +01:00
MacRimi 2d1d7bcc7b fix(build): pin the ARM AppImage runtime and align two translations
appimagetool 1.9.1 embeds the unpinned continuous runtime unless one
is given. Use the 20251108 release checked by its digest. The package
index refresh no longer fails the job on a broken runner repository.
2026-11-05 18:11:29 +01:00
MacRimi 7a73fa03f1 Merge develop into feature/monitor-native-arm64-build 2026-11-05 18:10:41 +01:00
MacRimi 9d6c1edbc7 ci: run the AI model availability tests in Feature tests 2026-11-05 18:10:23 +01:00
MacRimi c2fd894083 Merge develop into fix/provider-model-availability 2026-11-05 18:10:05 +01:00
ProxMenuxBot cd6b331a84 chore(lang): auto-rebuild translation cache
Source: 50a1d05
Triggered by: push
2026-11-05 17:09:21 +00:00
MacRimiandGitHub 50a1d050bc Merge pull request #601 from jcastro/fix/oci-preserve-container-device-gid
fix(oci): preserve recorded container device GIDs
2026-11-05 18:07:24 +01:00
MacRimiandGitHub bb697c4c23 Merge pull request #598 from jcastro/fix/oci-private-image-import
fix(oci): import private cached images with restrictive caller permissions
2026-11-05 18:06:52 +01:00
MacRimiandGitHub 41cc933e0a Merge pull request #591 from jcastro/fix/oci-stack-https-readiness
fix(oci): align stack HTTPS readiness with the single-container installer
2026-11-05 18:06:18 +01:00
MacRimiandGitHub b37e6610d1 Merge pull request #597 from jcastro/fix/oci-pbs-backup-umask
fix(oci): keep PBS backups working with a private caller umask
2026-11-05 18:05:52 +01:00
MacRimi 2ef15f94a5 fix(oci): read device lines Proxmox writes without path= 2026-11-05 17:21:37 +01:00
github-actions[bot] 8644d5021e Update AppImage beta build (2026-11-04 21:45:44) 2026-11-04 21:45:44 +00:00
MacRimiandGitHub a8d1146e66 Delete AppImage/ProxMenux-1.2.8.AppImage 2026-11-04 22:42:38 +01:00
MacRimiandGitHub 321ebadea3 Delete AppImage/ProxMenux-Monitor.AppImage.sha256 2026-11-04 22:42:27 +01:00
github-actions[bot] 7775a29172 Update AppImage beta build (2026-11-04 21:32:42) 2026-11-04 21:32:42 +00:00
MacRimiandGitHub 20a4d08d05 Merge pull request #600 from jcastro/fix/stirling-pdf-ghcr
Use official GHCR image for Stirling PDF
2026-11-04 22:30:01 +01:00
MacRimi a18a008108 Merge develop into fix/stirling-pdf-ghcr
Keep the Slovak menu test fix already on develop.
2026-11-04 22:24:30 +01:00
MacRimi 9aa378fccb fix(monitor): announce the NVIDIA driver the installer itself recommends 2026-11-04 22:20:44 +01:00
MacRimi 05ed3925da test: give the Slovak menu test the catalog and update entry labels 2026-11-04 22:11:04 +01:00
MacRimiandGitHub 0c98bb2c6c Merge pull request #593 from jcastro/fix/nvidia-subsystem-device-detection
fix: recognize subsystem-qualified NVIDIA GPUs
2026-11-04 22:04:41 +01:00
Jonatan Castro 7605a6a2fa fix(oci): preserve recorded container device GIDs 2026-11-04 21:24:04 +01:00
Jonatan Castro 0e42f658da Return text labels from OCI menu test checkers 2026-11-04 19:55:16 +01:00
Jonatan Castro b6006554c6 Use official GHCR image for Stirling PDF 2026-11-04 19:47:43 +01:00
ProxMenuxBot 6324d41a1d chore(lang): auto-rebuild translation cache
Source: ef00a34
Triggered by: push
2026-11-04 18:05:56 +00:00
MacRimi ef00a34654 feat(oci): show new and installed application counts in the OCI menu entries, lined up in one column 2026-11-04 19:02:03 +01:00
ProxMenuxBot 143c7db610 chore(lang): auto-rebuild translation cache
Source: 17786e0
Triggered by: push
2026-11-04 17:20:16 +00:00
MacRimi 17786e0f54 perf(oci): read the Proxmox version from the package database when opening the OCI menu 2026-11-04 18:19:13 +01:00
MacRimi 5c91e1c661 Merge branch 'develop' of https://github.com/MacRimi/ProxMenux into develop 2026-11-04 18:18:17 +01:00
MacRimi f0871607fa i18n: translate the Selkies NVIDIA acceleration label 2026-11-04 18:16:33 +01:00
ProxMenuxBot 8e1b2ccc9d chore(lang): auto-rebuild translation cache
Source: b7167ac
Triggered by: push
2026-11-04 17:14:35 +00:00
MacRimi b7167ac498 feat(oci): offer GPU acceleration to the ArtCraft apps built on the LinuxServer Selkies base 2026-11-04 18:11:41 +01:00
MacRimi e916c3b8bb fix(oci): offer what the AMD GPU can run without warning about ROCm support 2026-11-04 17:25:08 +01:00
MacRimi 64e9e0e8dd fix(monitor): read the error frequency for AI context from the real errors table columns 2026-11-04 17:05:44 +01:00
MacRimi 7cbe92ad9f fix(monitor): read the error frequency for AI context from the real errors table columns 2026-11-04 16:57:51 +01:00
MacRimi 8ca445ff3b fix(oci): let AdGuard Home pass its update check on the web port once it is set up 2026-11-04 16:47:35 +01:00
Jonatan Castro 007cf78ec2 Authorize USB/IP imports and retain USB references through hotplug cleanup 2026-11-04 11:05:19 +01:00
Jonatan Castro 0ca936f3b4 fix(oci): stage private images for the mapped Proxmox reader 2026-11-04 03:25:39 +01:00
Jonatan Castro bf27c3e1da fix(oci): isolate retained PBS backup creation permissions 2026-11-04 03:09:47 +01:00
Jonatan Castro 150d15950d fix(backup): isolate native Borg from AppImage Python and library paths 2026-11-04 02:52:29 +01:00
Jonatan Castro fd061054d4 fix(monitor): avoid foreign Borg binary in ARM builds and smoke-test launcher 2026-11-04 02:52:05 +01:00
Jonatan Castro d3005bbaff Wait for disposable SSH account processes before fixture cleanup 2026-11-04 02:48:31 +01:00
Jonatan Castro e361195abc Fail closed when the kernel retains an unplugged USB/IP match 2026-11-04 02:48:06 +01:00
Jonatan Castro 5d2c95a22b Exercise restricted SSH with an accessible isolated account home 2026-11-04 02:47:01 +01:00
Jonatan Castro 76696a5271 fix(monitor): preserve an OVS VLAN tag of zero 2026-11-04 02:46:58 +01:00
Jonatan Castro 2bcc0c1e61 feat(monitor): validate native ARM64 and AMD64 AppImage builds 2026-11-04 02:46:13 +01:00
Jonatan Castro 2fd55f8c88 feat(monitor): discover Open vSwitch network topology 2026-11-04 02:45:28 +01:00
Jonatan Castro 3c09800ab5 Restrict USB/IP SSH access and clean stale device matches 2026-11-04 02:45:19 +01:00
Jonatan Castro 84d860f71b test(ai): run availability regressions on provider catalog changes 2026-11-04 02:42:43 +01:00
Jonatan Castro 344346ff9d fix(ai): refresh Groq recommendations and remove unavailable OpenRouter models 2026-11-04 02:41:58 +01:00
Jonatan Castro e1243ea2ff fix: detect subsystem-qualified NVIDIA GPU support 2026-11-04 02:41:45 +01:00
Jonatan Castro 0a4824e2f1 Preserve installed Nextcloud cache settings and configuration ownership 2026-11-04 00:40:52 +01:00
Jonatan Castro a97dafacf6 Fix local HTTPS readiness for native OCI stacks 2026-11-04 00:17:35 +01:00
Jonatan Castro eef425666a Fix native Nextcloud bootstrap quoting and initial configuration seeding 2026-11-04 00:04:57 +01:00
Jonatan Castro f4e7f7d525 Keep the MariaDB catalog description aligned with the recipe 2026-11-03 23:40:23 +01:00
Jonatan Castro 0d4c6e6bd3 Merge remote-tracking branch 'origin/develop' into feature/oci-nextcloud-mariadb 2026-11-03 23:39:23 +01:00
Jonatan Castro 3ff9885394 Add LinuxServer Nextcloud stack with MariaDB and Redis 2026-11-03 23:39:23 +01:00
github-actions[bot] a026ab5926 Update AppImage beta build (2026-11-03 22:24:19) 2026-11-03 22:24:20 +00:00
MacRimi 1dca76aaa5 fix(oci): check high availability in the preflight so tests without Proxmox keep working 2026-11-03 23:16:25 +01:00
MacRimi dcb1d65ec8 fix(monitor): keep the theme-aware logo list and add Tailscale 2026-11-03 23:08:30 +01:00
ProxMenuxBot 7bb99d30ff chore(lang): auto-rebuild translation cache
Source: a89eb92
Triggered by: push
2026-11-03 22:00:23 +00:00
MacRimi a89eb921cc fix(oci): refuse an HA-managed container before downloading the image and explain how to proceed 2026-11-03 22:49:47 +01:00
github-actions[bot] 97da4321c8 Update AppImage beta build (2026-11-03 20:27:40) 2026-11-03 20:27:40 +00:00
MacRimi 11c0c683d7 fix(monitor): run scheduled backup jobs detached and follow them by their task UPID 2026-11-03 21:15:40 +01:00
MacRimi 6628744900 Merge branch 'develop' of https://github.com/MacRimi/ProxMenux into develop 2026-11-03 21:02:17 +01:00
MacRimi 194a959492 fix(monitor): show the light variant of selfh.st logos in the dark theme 2026-11-03 21:02:06 +01:00
MacRimiandGitHub 74e5b7a4ff Merge pull request #587 from MaEscalanteHe/docs/drift-utils
docs(web): fix Utils drift
2026-11-03 20:58:55 +01:00
MacRimiandGitHub 244181f9df Merge pull request #586 from MaEscalanteHe/docs/drift-backup-restore
docs(web): fix Backup & Restore drift
2026-11-03 20:58:33 +01:00
Manuel Escalante e3f85b3e09 docs(web): translate utils drift fixes 2026-11-03 20:00:03 +01:00
Manuel Escalante c0067d35a6 docs(web): fix Utils drift found in docs audit 2026-11-03 19:59:52 +01:00
Manuel Escalante cd3d4061d0 docs(web): translate backup-restore drift fixes 2026-11-03 19:52:20 +01:00
Manuel Escalante e9272c90a0 docs(web): fix Backup & Restore drift found in docs audit 2026-11-03 19:52:20 +01:00
MacRimi e51553ada8 test: give the cached health check a safe margin before the cache expires 2026-11-03 19:50:03 +01:00
MacRimiandGitHub c07b328bb9 Merge pull request #582 from jcastro/feature/oci-catalog-refresh
Refresh the OCI application catalog automatically with a local cache
2026-11-03 19:46:54 +01:00
MacRimiandGitHub 9a9d0f2379 Merge pull request #576 from dodog/main
Refine Slovak translations in common.json
2026-11-03 19:42:30 +01:00
MacRimiandGitHub 389a07c265 Merge pull request #575 from MaEscalanteHe/docs/drift-monitor
docs(web): fix Monitor drift
2026-11-03 19:41:56 +01:00
MacRimiandGitHub c5df337db6 Merge pull request #574 from MaEscalanteHe/docs/drift-settings-intro
docs(web): fix Settings, Introduction and Installation drift
2026-11-03 19:41:29 +01:00
ProxMenuxBot 3e2b8d72d1 chore(lang): auto-rebuild translation cache
Source: 3bf4c0d
Triggered by: push
2026-11-03 18:14:42 +00:00
MacRimiandGitHub 3bf4c0d82f Merge pull request #585 from jcastro/feature/oci-artcraft-suite
feat(oci): add thirteen ArtCraft desktop applications
2026-11-03 19:00:47 +01:00
MacRimi c3024b8448 Merge develop into feature/oci-artcraft-suite 2026-11-03 18:52:37 +01:00
ProxMenuxBot ab76ab161b chore(lang): auto-rebuild translation cache
Source: 7f59ee5
Triggered by: push
2026-11-03 17:50:46 +00:00
MacRimi f61c59d093 Merge develop into feature/oci-artcraft-suite
Resolve the catalog conflicts and regenerate VALIDATION.md.
2026-11-03 18:43:52 +01:00
MacRimiandGitHub 7f59ee5103 Merge pull request #580 from jcastro/feature/oci-app-catalog-additions
Add KitchenOwl, Krusader, Spoolman, Unbound and Z-Wave JS UI
2026-11-03 18:30:15 +01:00
github-actions[bot] cef1dc7422 Update AppImage beta build (2026-11-03 17:25:45) 2026-11-03 17:25:45 +00:00
MacRimi 888b99330b Merge develop into feature/oci-app-catalog-additions 2026-11-03 18:20:08 +01:00
ProxMenuxBot af0dd74067 chore(lang): auto-rebuild translation cache
Source: 7ec022a
Triggered by: push
2026-11-03 17:13:55 +00:00
Jonatan Castro 75a96b2658 Complete Swedish Authelia label after syncing develop 2026-11-03 18:06:58 +01:00
MacRimi 114882fcba Merge develop into feature/oci-app-catalog-additions
Resolve the catalog conflicts and regenerate VALIDATION.md.
2026-11-03 18:06:57 +01:00
Jonatan Castro 79c0f268fd Merge develop and refresh the OCI validation summary 2026-11-03 18:05:19 +01:00
MacRimiandGitHub 7ec022af81 Merge pull request #584 from jcastro/feature/oci-airdcpp
feat(oci): add AirDC++ Web Client
2026-11-03 18:02:36 +01:00
Jonatan Castro 07f7f9a6a1 Apply profile compatibility gate using effective menu visibility 2026-11-03 17:58:52 +01:00
Jonatan Castro fec97c57d9 Prune catalog snapshots and defer recipes requiring newer profile keys 2026-11-03 17:56:15 +01:00
MacRimi 4ba0d6a236 Merge develop into feature/oci-airdcpp
Resolve the catalog index conflict and regenerate VALIDATION.md.
2026-11-03 17:47:35 +01:00
ProxMenuxBot 96b3a919ba chore(lang): auto-rebuild translation cache
Source: c628e65
Triggered by: push
2026-11-03 16:46:28 +00:00
MacRimiandGitHub c628e65e2f Merge pull request #581 from jcastro/feature/oci-authelia
Add Authelia to the OCI catalog
2026-11-03 17:42:30 +01:00
MacRimi 1e08a5939b ci: cancel superseded test runs on the same branch or pull request 2026-11-03 17:10:11 +01:00
MacRimiandGitHub 163c7c3505 Merge pull request #583 from jcastro/fix/oci-failed-update-recovery
fix(oci): recover automatically after failed image replacements
2026-11-03 16:50:36 +01:00
MacRimi eb46fffd45 fix(oci): apply the llama.cpp context size and stable Vulkan settings for integrated GPUs 2026-11-03 16:46:38 +01:00
Manuel Escalante a4c2c34597 fix(i18n): use localized UI labels in Monitor docs 2026-11-03 16:04:15 +01:00
Jonatan Castro aa19af66eb Add thirteen ArtCraft desktop applications to the OCI catalog 2026-11-03 14:50:20 +01:00
Jonatan Castro f19c300387 Restore the previous OCI installation after a failed image replacement 2026-11-03 13:32:16 +01:00
Jonatan Castro c1183bdeed Use the AirDC++ index page for startup health checks 2026-11-03 13:22:55 +01:00
Jonatan Castro 19e35a567f Add AirDC++ Web Client OCI recipe 2026-11-03 12:51:00 +01:00
Jonatan Castro f428dc76f0 Isolate catalog worker in offline Slovak menu regression 2026-11-03 12:38:57 +01:00
Jonatan Castro e412d3161d Harden OCI catalog refresh recovery and retries 2026-11-03 12:30:54 +01:00
Jonatan Castro 13a8ac1001 Refresh OCI catalog automatically with local cache and app counters 2026-11-03 12:20:23 +01:00
Jonatan Castro f0d54fca13 Leave lab verification to maintainers 2026-11-03 11:35:59 +01:00
Jonatan Castro d9973635fb Add Authelia to OCI catalog 2026-11-03 11:34:27 +01:00
Manuel Escalante 75b13d87da fix(i18n/de): correct the backups tab alt text in the guest detail dialog 2026-11-03 10:25:41 +01:00
Manuel Escalante ac97e2c5a6 docs(web): apply review feedback on Monitor docs 2026-11-03 09:54:33 +01:00
Manuel Escalante 700f72babd docs(web): fix release channel wording from review 2026-11-03 09:45:39 +01:00
Jonatan Castro 0ab40b4eea feat(oci): add five application recipes 2026-11-03 00:27:00 +01:00
MacRimi 9940f05adf fix(oci): llama.cpp lists the models in /models, with resources and notes to add one 2026-11-02 23:45:10 +01:00
Jozef GaalandJozef Gaal 8328d5d366 Refine 'onServer' explanation in common.json 2026-11-02 23:17:00 +01:00
Jozef GaalandJozef Gaal 7e6a942d16 Fix Slovak translations in common.json 2026-11-02 23:17:00 +01:00
Jozef GaalandJozef Gaal 03928c4277 Refine Slovak translations in common.json 2026-11-02 23:16:59 +01:00
MacRimiandGitHub 8aefd70e52 Merge pull request #578 from jcastro/feature/oci-paperclip
Add Paperclip to the OCI catalog
2026-11-02 23:02:03 +01:00
MacRimiandGitHub 6bee13114c Merge pull request #579 from f3rs3n/fix/log2ram-journal-transition
fix(log2ram): keep journal protection enabled until disk migration
2026-11-02 23:00:50 +01:00
martino 6a1513a014 fix(log2ram): keep journal protection enabled until disk migration 2026-11-02 22:32:28 +01:00
Jonatan Castro fb083e92cb feat(oci): add Paperclip application recipe 2026-11-02 20:37:29 +01:00
github-actions[bot] 781d2500ad Update AppImage beta build (2026-11-02 18:39:06) 2026-11-02 18:39:06 +00:00
MacRimi 98931fe4a7 New version 1.2.8 2026-11-02 19:22:47 +01:00
MacRimi 46337f162f New version 1.2.8 2026-11-02 19:20:30 +01:00
MacRimiandGitHub 064c2a6c39 Merge pull request #557 from MaEscalanteHe/feature/web-refresh
fix(web): dependency cleanup, HTML entity rendering and sidebar fixes
2026-11-02 19:10:00 +01:00
MacRimi 3feb5ca5cb fix(web): wrap inline code and scroll tables on narrow screens 2026-11-02 19:01:03 +01:00
MacRimi b0215d4bbb fix: OCI image data paths, LAN endpoints for OpenAI-compatible AI and lab-validated apps 2026-11-02 18:42:32 +01:00
MacRimi 9f3fffd249 fix: one source for the disk type and a config volume for SearXNG 2026-11-02 17:28:31 +01:00
Manuel Escalante 511211f10b fix(web): keep ICU quotes out of messages inserted as raw HTML 2026-11-02 10:32:41 +01:00
github-actions[bot] 41081121f8 Update AppImage beta build (2026-11-02 07:28:12) 2026-11-02 07:28:12 +00:00
MacRimi e83794b7e2 fix(web): send only the client translations to each page 2026-11-02 08:25:28 +01:00
Manuel Escalante 418afe385b docs(web): translate AI explanations of backup errors 2026-11-01 14:38:05 +01:00
Manuel Escalante 9ed09cc28e docs(web): document AI explanations of backup errors 2026-11-01 14:36:54 +01:00
Manuel Escalante 4261019549 docs(web): translate settings-intro drift fixes 2026-11-01 14:05:13 +01:00
Manuel Escalante 5dc98e9daf docs(web): translate monitor drift fixes 2026-11-01 14:05:13 +01:00
Manuel Escalante 488044e0b9 docs(web): fix remaining Settings and Introduction drift from docs audit 2026-11-01 14:05:13 +01:00
Manuel Escalante 7320fc6ff6 docs(web): fix Monitor drift found in docs audit 2026-11-01 14:05:13 +01:00
Manuel Escalante 398ca55247 docs(web): fix Monitor API paths and token and SSL location 2026-11-01 14:05:13 +01:00
Manuel Escalante 4f415c98cf docs(web): fix Monitor install and Change Language drift in Settings 2026-11-01 14:05:12 +01:00
Manuel Escalante 64fa4f8115 fix(web): restore Change Language entry in docs sidebar 2026-10-29 19:54:41 +01:00
Manuel Escalante c26eb49e2c fix(web): render HTML entities in translated text 2026-10-29 09:41:32 +01:00
Manuel Escalante db12972253 fix(web): pass em tag to host-local-disk format steps 2026-10-29 09:41:32 +01:00
Manuel Escalante fac7ac5021 chore(web): drop unused dependencies and apply minor updates and audit fixes 2026-10-29 09:41:32 +01:00
MacRimi bec4606724 Wait for the attached USB/IP port and release USB/IP sharing on uninstall 2026-10-18 17:58:05 +02:00
MacRimi f3be456062 Merge remote-tracking branch 'origin/develop' into HEAD 2026-10-18 17:52:01 +02:00
Jonatan b4c9ffb54b Complete translations for all supported languages 2026-10-16 23:00:17 +02:00
Jonatan 548e237096 Keep SSH fixture keys under a StrictModes-safe directory 2026-10-16 22:07:05 +02:00
Jonatan 440c3df16f Add selected USB/IP device sharing over SSH 2026-10-16 22:04:36 +02:00
525 changed files with 41506 additions and 3783 deletions
+33
View File
@@ -0,0 +1,33 @@
"""Reject foreign ELF files in a native AppDir without executing any binary."""
import argparse
from pathlib import Path
import struct
def check(directory, architecture):
expected = {'x86_64': 62, 'aarch64': 183}[architecture]
checked = 0
for path in Path(directory).rglob('*'):
if path.is_symlink() or not path.is_file():
continue
with path.open('rb') as stream:
header = stream.read(20)
if not header.startswith(b'\x7fELF'):
continue
if len(header) != 20 or header[5] not in (1, 2):
raise ValueError(f'Invalid ELF header: {path}')
machine = struct.unpack('<H' if header[5] == 1 else '>H', header[18:20])[0]
if machine != expected:
raise ValueError(f'Foreign ELF machine {machine} in {architecture} AppDir: {path}')
checked += 1
if not checked:
raise ValueError('No native ELF files found in AppDir')
return checked
if __name__ == '__main__':
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('directory', type=Path)
parser.add_argument('architecture', choices=('x86_64', 'aarch64'))
args = parser.parse_args()
print(f'PASS: {check(args.directory, args.architecture)} native ELF files')
+301
View File
@@ -0,0 +1,301 @@
"""Disposable QEMU-only real-kernel USB/IP regression lab. Never use on a host."""
import contextlib, importlib.util, os, select, socket, subprocess, sys, tempfile, termios, time, tty
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "scripts/devices"))
import usbip_manager as m
from usbip_protocol import Gate
def run(*args):
result = subprocess.run(args, text=True, capture_output=True)
assert result.returncode == 0, (args, result.stdout, result.stderr)
return result.stdout
def put(p, v):
Path(p).write_text(v)
def wait(test):
for _ in range(100):
value = test()
if value:
return value
time.sleep(0.05)
raise AssertionError("condition timed out")
def gadget(name, serial, udc):
g = Path("/sys/kernel/config/usb_gadget") / name
g.mkdir()
for f, v in [("idVendor", "0x1d6b"), ("idProduct", "0x0104")]:
put(g / f, v)
(g / "strings/0x409").mkdir()
for f, v in [
("serialnumber", serial),
("manufacturer", "Regression lab"),
("product", name),
]:
put(g / "strings/0x409" / f, v)
(g / "configs/c.1").mkdir()
(g / "functions/acm.usb0").mkdir()
(g / "configs/c.1/acm.usb0").symlink_to(g / "functions/acm.usb0")
put(g / "UDC", udc)
return g
def find(serial):
return next((d for d in m.inventory() if d["serial"] == serial), None)
def chosen(serial, id):
return dict(wait(lambda: find(serial)), id=id)
def control(port, busid):
import struct
with socket.create_connection(("127.0.0.1", port)) as s:
s.sendall(
struct.pack("!HHI", 0x111, 0x8003, 0) + busid.encode().ljust(32, b"\0")
)
reply = s.recv(8)
assert len(reply) == 8
return struct.unpack("!HHI", reply)[2]
def main():
assert sys.argv[1:] == [
"--disposable-vm"
], "Requires --disposable-vm on a fresh throwaway QEMU VM"
assert (
os.geteuid() == 0 and "QEMU" in Path("/sys/class/dmi/id/sys_vendor").read_text()
)
assert not Path("/sys/kernel/config/usb_gadget").exists() or not list(
Path("/sys/kernel/config/usb_gadget").iterdir()
), "Start with a fresh disposable VM"
run("modprobe", "dummy_hcd", "num=3")
run("modprobe", "libcomposite")
run("modprobe", "usbip-host")
run("modprobe", "vhci-hcd")
udcs = sorted(p.name for p in Path("/sys/class/udc").iterdir())
assert len(udcs) == 3
a_udc = udcs[0]
a = gadget("selected-a", "original-a", udcs[0])
b = gadget("selected-b", "original-b", udcs[1])
time.sleep(0.5)
with tempfile.TemporaryDirectory() as temp:
root = Path(temp)
m.CONFIG_DIR = root / "config"
m.SERVER_RUN_DIR = root / "run"
m.RUN_DIR = root / "client"
selected_a = chosen("original-a", "abcdef123456")
selected_b = chosen("original-b", "fedcba654321")
config = {"server": True, "exports": [selected_a, selected_b], "imports": []}
m.atomic_json(m.CONFIG_DIR / "config.json", config)
owned = {}
leases = {}
daemon = subprocess.Popen(
["usbipd", "-4"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
)
gate = None
proxy = None
try:
assert not (errors := m.reconcile_exports(config, owned, leases)), errors
def claim(name):
for selected in config["exports"]:
id = selected["id"]
lease = leases.get(id)
record = owned.get(id)
if lease and lease.ready and record and record["busid"] == name:
return dict(record, id=id)
gate = Gate(root / "gate.sock", 0, claim)
proxy = subprocess.Popen(
[
"socat",
"TCP-LISTEN:33240,bind=127.0.0.1,reuseaddr,fork",
"UNIX-CONNECT:" + str(root / "gate.sock"),
]
)
time.sleep(0.2)
# A native independent client remains attached throughout A's physical cycle.
print(
run(
"usbip",
"--tcp-port",
"33240",
"attach",
"-r",
"127.0.0.1",
"-b",
selected_b["busid"],
),
flush=True,
)
def serial_transfer(gadget=b, serial="original-b"):
# Gadget B's function tty and remote vhci serial port, not local A's tty.
gadget_tty = (
"/dev/ttyGS"
+ (gadget / "functions/acm.usb0/port_num").read_text().strip()
)
client = wait(
lambda: next(
(
p
for p in Path("/sys/class/tty").glob("ttyACM*")
if "vhci_hcd" in str(p.resolve())
and any(
(q / "serial").exists()
and (q / "serial").read_text().strip() == serial
for q in p.resolve().parents
)
),
None,
)
)
with contextlib.ExitStack() as stack:
fds = [
os.open(path, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
for path in (gadget_tty, "/dev/" + client.name)
]
for fd in fds:
stack.callback(os.close, fd)
tty.setraw(fd)
termios.tcflush(fd, termios.TCIOFLUSH)
payload = b"independent-b-still-transferring\n"
os.write(fds[0], payload)
assert select.select([fds[1]], [], [], 3)[0]
assert os.read(fds[1], len(payload)) == payload
serial_transfer()
for iteration in range(20):
put(a / "UDC", "\n")
time.sleep(0.03)
m.reconcile_exports(config, owned, leases)
assert selected_a["busid"] not in m.MATCH_BUSID.read_text().split()
put(a / "UDC", a_udc)
wait(lambda: find("original-a"))
time.sleep(0.25)
assert not (
errors := m.reconcile_exports(config, owned, leases)
), errors
assert leases[selected_a["id"]].ready
serial_transfer()
print(
"PASS: 20 unplug/replug cycles; stale slot removed and original exported; independent native serial transfer survives",
flush=True,
)
put(a / "UDC", "\n")
time.sleep(0.05)
m.reconcile_exports(config, owned, leases)
a_udc = udcs[2]
put(a / "UDC", a_udc)
wait(lambda: find("original-a"))
time.sleep(0.25)
assert not (errors := m.reconcile_exports(config, owned, leases)), errors
assert owned[selected_a["id"]]["busid"] != selected_a["busid"]
serial_transfer()
print(
"PASS: moving original to another USB port preserves independent serial transfer",
flush=True,
)
# An unselected replacement returns to a local driver and cannot import.
put(a / "UDC", "\n")
time.sleep(0.05)
put(a / "strings/0x409/serialnumber", "unselected-replacement")
put(a / "UDC", a_udc)
replacement = wait(lambda: find("unselected-replacement"))
errors = m.reconcile_exports(config, owned, leases)
assert selected_a["id"] in errors
assert find("unselected-replacement")["driver"] == "usb"
assert control(33240, replacement["busid"]) != 0
# Also bind that unselected replacement in a separate native setup: the
# daemon can see it, but a direct import through our gate must still fail.
run("usbip", "bind", "-b", replacement["busid"])
assert replacement["busid"] in run("usbip", "list", "-r", "127.0.0.1")
assert control(33240, replacement["busid"]) != 0
m.reconcile_exports(config, owned, leases)
assert find("unselected-replacement")["driver"] == "usbip-host"
run("usbip", "unbind", "-b", replacement["busid"])
serial_transfer()
print(
"PASS: same-port replacement stays local, native import rejected, independent serial survives",
flush=True,
)
# Same original then can be selected, imported and exchange native URBs.
put(a / "UDC", "\n")
time.sleep(0.1)
put(a / "strings/0x409/serialnumber", "original-a")
put(a / "UDC", a_udc)
wait(lambda: find("original-a"))
time.sleep(0.25)
assert not (errors := m.reconcile_exports(config, owned, leases)), errors
print(
run(
"usbip",
"--tcp-port",
"33240",
"attach",
"-r",
"127.0.0.1",
"-b",
find("original-a")["busid"],
),
flush=True,
)
wait(lambda: len(m.imported_ports()) == 2)
serial_transfer(a, "original-a")
serial_transfer()
for port in m.imported_ports():
if port["busid"] == find("original-a")["busid"]:
run("usbip", "detach", "-p", str(port["port"]))
# Simulate losing process-owned descriptors before a present-device
# release. The manager must acquire and verify fresh usbfs pins.
leases.pop(selected_a["id"]).close()
config["exports"] = [selected_b]
assert not (errors := m.reconcile_exports(config, owned, leases)), errors
assert find("original-a")["driver"] == "usb"
serial_transfer()
print(
"PASS: original reimport and present-device release restore local driver",
flush=True,
)
finally:
if proxy:
proxy.terminate()
proxy.wait()
if gate:
gate.terminate()
for port in m.imported_ports():
with contextlib.suppress(Exception):
run("usbip", "detach", "-p", str(port["port"]))
config["exports"] = []
print("cleanup", m.reconcile_exports(config, owned, leases), flush=True)
daemon.terminate()
daemon.wait()
for lease in leases.values():
lease.close()
print("PASS: no Oops/BUG in kernel log", flush=True)
for g in (a, b):
if (g / "UDC").read_text().strip():
put(g / "UDC", "\n")
(g / "configs/c.1/acm.usb0").unlink()
(g / "functions/acm.usb0").rmdir()
(g / "configs/c.1").rmdir()
(g / "strings/0x409").rmdir()
g.rmdir()
assert not any(
x in run("dmesg") for x in ["BUG:", "Oops:", "general protection fault"]
)
if __name__ == "__main__":
main()
+153
View File
@@ -0,0 +1,153 @@
"""Opt-in fresh-QEMU lab: actual generated units, restricted SSH and native USB URBs."""
import contextlib, os, select, shutil, sys, termios, time, tty
from pathlib import Path
ROOT = Path(__file__).resolve().parents[2]
sys.path.insert(0, str(ROOT / "scripts/devices"))
from check_usbip_kernel import m, run, put, gadget, find
def wait(test, seconds=30):
end = time.monotonic() + seconds
while time.monotonic() < end:
value = test()
if value:
return value
time.sleep(0.1)
raise AssertionError("timeout")
def transfer(g, serial):
client = wait(
lambda: next(
(
p
for p in Path("/sys/class/tty").glob("ttyACM*")
if "vhci_hcd" in str(p.resolve())
and any(
(q / "serial").exists()
and (q / "serial").read_text().strip() == serial
for q in p.resolve().parents
)
),
None,
)
)
with contextlib.ExitStack() as stack:
fds = [
os.open(path, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
for path in (
"/dev/ttyGS" + (g / "functions/acm.usb0/port_num").read_text().strip(),
"/dev/" + client.name,
)
]
for fd in fds:
stack.callback(os.close, fd)
tty.setraw(fd)
termios.tcflush(fd, termios.TCIOFLUSH)
for src, dst in ((fds[0], fds[1]), (fds[1], fds[0])):
payload = b"actual-systemd-ssh-usbip-serial\n"
os.write(src, payload)
assert select.select([dst], [], [], 5)[0]
assert os.read(dst, len(payload)) == payload
def main():
assert sys.argv[1:] == [
"--disposable-vm"
], "Requires --disposable-vm on a fresh throwaway QEMU VM"
assert not Path("/etc/proxmenux/usbip").exists()
assert "QEMU" in Path("/sys/class/dmi/id/sys_vendor").read_text()
for name in ("usbip_manager.py", "usbip_protocol.py", "usbip_lifetime.py"):
target = Path("/usr/local/share/proxmenux/scripts/devices") / name
target.parent.mkdir(parents=True, exist_ok=True)
shutil.copy(m.SCRIPT.parent / name, target)
run("modprobe", "dummy_hcd", "num=3")
run("modprobe", "libcomposite")
run("modprobe", "usbip-host")
run("modprobe", "vhci-hcd")
udcs = sorted(p.name for p in Path("/sys/class/udc").iterdir())
assert len(udcs) == 3
assert not list(Path("/sys/kernel/config/usb_gadget").iterdir())
a = gadget("service-a", "service-a", udcs[0])
b = gadget("service-b", "service-b", udcs[1])
time.sleep(0.5)
key = Path("/root/service-usbip-key")
run("ssh-keygen", "-q", "-t", "ed25519", "-N", "", "-f", str(key))
m.authorize_key(str(key) + ".pub")
public = Path("/etc/ssh/ssh_host_ed25519_key.pub").read_text().split()
Path("/root/.ssh/known_hosts").write_text(
"127.0.0.1 " + public[0] + " " + public[1] + "\n"
)
imports = []
try:
m.update_server(True)
sa = m.add_export(wait(lambda: find("service-a"))["busid"])
sb = m.add_export(wait(lambda: find("service-b"))["busid"])
wait(lambda: len([e for e in m.catalog() if e["status"] == "exported"]) == 2)
remote = m.validate_remote("127.0.0.1", 22, str(key))
for selected, port in ((sa, 33240), (sb, 33241)):
imports.append(m.add_import(remote, selected["id"], port))
wait(lambda: len(m.imported_ports()) == 2)
transfer(a, "service-a")
transfer(b, "service-b")
print(
"PASS: actual generated server/client systemd units and restricted SSH carry bidirectional native serial on two USBs",
flush=True,
)
for cycle in range(3):
put(a / "UDC", "\n")
time.sleep(0.2)
transfer(b, "service-b")
put(a / "UDC", udcs[0])
wait(lambda: find("service-a"))
time.sleep(0.5)
# An old vhci port may still exist; wait for the new guest driver and verify data.
wait(
lambda: next(
(
e
for e in m.catalog()
if e["id"] == sa["id"] and e["status"] == "exported"
),
None,
)
)
time.sleep(6)
transfer(a, "service-a")
transfer(b, "service-b")
print(
"PASS: three physical reconnects automatically reattach through restricted SSH; second serial connection survives",
flush=True,
)
m.remove_export(sa["id"])
assert find("service-a")["driver"] == "usb"
transfer(b, "service-b")
print(
"PASS: stop-sharing waits for real release and returns local driver while independent client keeps transferring",
flush=True,
)
for item in imports:
m.remove_import(item["id"])
imports = []
m.update_server(False)
assert not m.read_json(m.state_path(), {})
assert find("service-b")["driver"] == "usb"
print(
"PASS: disable stops listeners, removes owned bindings, leaves both local USB drivers restored",
flush=True,
)
finally:
for item in imports:
with contextlib.suppress(Exception):
m.remove_import(item["id"])
with contextlib.suppress(Exception):
m.update_server(False)
print(
run("journalctl", "-u", m.SERVER_UNIT, "--no-pager", "-n", "20"), flush=True
)
if __name__ == "__main__":
main()
+276
View File
@@ -0,0 +1,276 @@
#!/usr/bin/env python3
"""Linux-only integration: real namespaces, socat and SSH; no USB hardware.
Run as root in the disposable CI runner. All keys, configuration, listeners and
child processes belong to a temporary fixture; no systemd units are installed.
"""
import importlib.util
import os
from pathlib import Path
import pwd
import signal
import socket
import stat
import subprocess
import sys
import tempfile
import time
SOURCE = Path(__file__).resolve().parents[2] / "scripts/devices/usbip_manager.py"
def port():
with socket.socket() as sock:
sock.bind(("127.0.0.1", 0))
return sock.getsockname()[1]
def wait_until(test, processes, log, timeout=15):
deadline = time.monotonic() + timeout
while time.monotonic() < deadline:
for process in processes:
if process.poll() is not None:
raise AssertionError(f"Fixture exited ({process.returncode}): {log.read_text()}")
try:
if test():
return
except (ConnectionError, FileNotFoundError, socket.timeout):
pass
time.sleep(0.1)
raise AssertionError(f"Fixture did not become ready: {log.read_text()}")
def echo(sock):
# Exercise the production protocol gate through the real SSH stream. Empty
# fixture selection must produce an empty native DEVLIST, never raw echo.
import struct
sock.settimeout(10)
sock.sendall(struct.pack("!HHI", 0x0111, 0x8005, 0))
received = bytearray()
while len(received) < 12:
chunk = sock.recv(12 - len(received))
if not chunk:
break
received.extend(chunk)
assert bytes(received) == struct.pack("!HHII", 0x0111, 5, 0, 0), received
def main():
assert sys.platform == "linux" and os.geteuid() == 0, "Use the disposable Linux CI runner as root"
spec = importlib.util.spec_from_file_location("usbip_manager", SOURCE)
manager = importlib.util.module_from_spec(spec)
spec.loader.exec_module(manager)
# A mistaken direct launch must never create a listener in this namespace.
try:
manager.require_private_network()
except manager.USBIPError:
pass
else:
raise AssertionError("Expected the host namespace to be rejected")
processes = []
tunnel = None
username = f"pmx-usbip-test-{os.getpid()}"
subprocess.run(["useradd", "--system", "--user-group", "--home-dir", "/nonexistent", "--shell", "/bin/sh", "--password", "*", username], check=True)
account = pwd.getpwnam(username)
manager.TRANSPORT_USER = username
# StrictModes checks every ancestor of AuthorizedKeysFile. A private
# subdirectory of /tmp still fails because /tmp itself is world writable.
# Keep the disposable fixture below root's home without changing its SSH
# configuration, account settings or existing authorized_keys.
with tempfile.TemporaryDirectory(prefix="pmx-usbip-", dir="/var/lib") as directory:
root = Path(directory)
os.chown(root, 0, account.pw_gid)
root.chmod(0o750)
fixture_source = root / "usbip_manager.py"
fixture_source.write_bytes(SOURCE.read_bytes())
fixture_source.chmod(0o644)
for name in ("usbip_protocol.py", "usbip_lifetime.py"):
(root / name).write_bytes((SOURCE.parent / name).read_bytes())
subprocess.run(["usermod", "--home", str(root), username], check=True)
log = root / "transport.log"
with log.open("w") as log_handle:
try:
fake_bin = root / "bin"
fake_bin.mkdir()
# The real daemon requires usbip-host and physical devices.
# Echo stands in only for its TCP endpoint, inside the namespace.
fake_daemon = fake_bin / "usbipd"
fake_daemon.write_text("""#!/usr/bin/python3
import socketserver
class Echo(socketserver.BaseRequestHandler):
def handle(self):
import struct
data = b''
while len(data) < 8:
block = self.request.recv(8 - len(data))
if not block:
return
data += block
if data == struct.pack('!HHI', 0x0111, 0x8005, 0):
self.request.sendall(struct.pack('!HHII', 0x0111, 5, 0, 0))
socketserver.ThreadingTCPServer.allow_reuse_address = True
socketserver.ThreadingTCPServer(('0.0.0.0', 3240), Echo).serve_forever()
""")
fake_daemon.chmod(0o755)
config = root / "config"
manager.atomic_json(config / "config.json", {"server": True, "exports": [], "imports": []})
server_run = root / "server"
runner = root / "server.py"
runner.write_text(f"""import importlib.util
from pathlib import Path
import subprocess
spec = importlib.util.spec_from_file_location('usbip_manager', {str(fixture_source)!r})
m = importlib.util.module_from_spec(spec)
spec.loader.exec_module(m)
m.CONFIG_DIR = Path({str(config)!r})
m.SERVER_RUN_DIR = Path({str(server_run)!r})
m.SYSFS = Path({str(root / 'no-usb-devices')!r})
m.TRANSPORT_USER = {username!r}
m.TRANSPORT_HOME = Path({str(root)!r})
subprocess.run(['ip', 'link', 'set', 'lo', 'up'], check=True)
m.serve()
""")
server = subprocess.Popen(["unshare", "--net", sys.executable, str(runner)],
env={**os.environ, "PATH": f"{fake_bin}:{os.environ['PATH']}"},
stdout=log_handle, stderr=log_handle, start_new_session=True)
processes.append(server)
unix_path = server_run / "usbip.sock"
wait_until(lambda: unix_path.exists(), [server], log)
assert os.readlink(f"/proc/{server.pid}/ns/net") != os.readlink("/proc/self/ns/net")
assert stat.S_IMODE(server_run.stat().st_mode) == 0o750
assert stat.S_IMODE(unix_path.stat().st_mode) == 0o660
# Linux /proc/net reflects the caller's network namespace.
listening = subprocess.check_output(["ss", "-H", "-ltn", "sport", "=", ":3240"], text=True)
assert not listening.strip(), "Raw USB/IP TCP leaked into the host network namespace"
# Wait for both the proxy and its private TCP peer.
def unix_ready():
with socket.socket(socket.AF_UNIX) as connection:
connection.connect(str(unix_path))
echo(connection)
return True
wait_until(unix_ready, [server], log)
for name in ("host", "client", "wrong-client"):
subprocess.run(["ssh-keygen", "-q", "-t", "ed25519", "-N", "", "-f", str(root / name)], check=True)
ssh_dir = root / ".ssh"
ssh_dir.mkdir(mode=0o750)
os.chown(ssh_dir, 0, account.pw_gid)
authorized = ssh_dir / "authorized_keys"
gate = root / "gate.py"
gate.write_text(f"""import importlib.util
from pathlib import Path
spec = importlib.util.spec_from_file_location('usbip_manager', {str(fixture_source)!r})
m = importlib.util.module_from_spec(spec)
spec.loader.exec_module(m)
m.TRANSPORT_USER = {username!r}
m.TRANSPORT_HOME = Path({str(root)!r})
m.SERVER_RUN_DIR = Path({str(server_run)!r})
m.REMOTE_SOCKET = {str(unix_path)!r}
m.transport()
""")
gate.chmod(0o644)
authorized.write_text(f'restrict,command="{sys.executable} {gate}" ' + (root / "client.pub").read_text())
os.chown(authorized, 0, account.pw_gid)
authorized.chmod(0o640)
known = root / "known_hosts"
known.write_text("")
known.chmod(0o600)
ssh_port, local_port = port(), port()
ssh_config = root / "sshd_config"
ssh_config.write_text(f"""Port {ssh_port}
ListenAddress 127.0.0.1
HostKey {root / 'host'}
PidFile {root / 'sshd.pid'}
AuthorizedKeysFile {authorized}
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
UsePAM yes
StrictModes yes
AllowUsers {username}
AllowTcpForwarding local
AllowStreamLocalForwarding local
LogLevel VERBOSE
""")
Path("/run/sshd").mkdir(exist_ok=True, mode=0o755)
sshd = subprocess.Popen(["/usr/sbin/sshd", "-D", "-e", "-f", str(ssh_config)],
stdout=log_handle, stderr=log_handle, start_new_session=True)
processes.append(sshd)
def ssh_ready():
with socket.create_connection(("127.0.0.1", ssh_port), timeout=1):
return True
wait_until(ssh_ready, [server, sshd], log)
remote = manager.validate_remote("127.0.0.1", ssh_port, str(root / "client"))
extra = ["-o", f"UserKnownHostsFile={known}", "-o", "GlobalKnownHostsFile=/dev/null"]
def check_ssh(selected):
args = manager.ssh_args(selected)
args[1:1] = extra
return subprocess.run(args + ["--", selected["host"], "catalog"], capture_output=True, text=True, timeout=15)
unknown = check_ssh(remote)
assert unknown.returncode != 0 and "Host key verification failed" in unknown.stderr, unknown.stderr
host_public = (root / "host.pub").read_text().split()
known.write_text(f"[127.0.0.1]:{ssh_port} {host_public[0]} {host_public[1]}\n")
wrong = check_ssh(remote | {"key": str(root / "wrong-client")})
assert wrong.returncode != 0 and "Permission denied" in wrong.stderr, wrong.stderr
accepted = check_ssh(remote)
assert accepted.returncode == 0, accepted.stderr + "\n" + log.read_text()
forbidden = manager.ssh_args(remote)
forbidden[1:1] = extra
denied = subprocess.run(forbidden + ["--", remote["host"], "id"], capture_output=True, text=True, timeout=15)
assert denied.returncode != 0, "Forced command allowed a shell command"
forwarded = subprocess.run(forbidden + ["-W", "127.0.0.1:22", "--", remote["host"]], capture_output=True, text=True, timeout=15)
assert forwarded.returncode != 0 and "prohibited" in forwarded.stderr, forwarded.stderr
original = manager.ssh_args
def fixture_ssh(selected):
args = original(selected)
args[1:1] = extra
return args
manager.ssh_args = fixture_ssh
tunnel = manager.LoopbackTunnel(remote | {"local_port": local_port})
with socket.socket() as attacker:
try:
attacker.bind(("127.0.0.1", local_port))
except OSError:
pass
else:
raise AssertionError("Another process stole the tunnel port")
def tunnel_ready():
with socket.create_connection(("127.0.0.1", local_port), timeout=1) as connection:
echo(connection)
return True
wait_until(tunnel_ready, processes, log)
listener = subprocess.check_output(["ss", "-H", "-ltn", "sport", "=", f":{local_port}"], text=True)
assert f"127.0.0.1:{local_port}" in listener and f"0.0.0.0:{local_port}" not in listener, listener
print("PASS: private namespace, dedicated-group Unix socket, no host USB/IP listener")
print("PASS: unknown/wrong keys, shell commands and arbitrary forwarding rejected; dedicated key accepted")
print("PASS: native USB/IP DEVLIST across real SSH -> Unix protocol gate -> private TCP")
finally:
if tunnel:
tunnel.terminate()
for process in reversed(processes):
if process.poll() is None:
os.killpg(process.pid, signal.SIGTERM)
for process in reversed(processes):
try:
process.wait(timeout=10)
except subprocess.TimeoutExpired:
os.killpg(process.pid, signal.SIGKILL)
process.wait(timeout=5)
subprocess.run(["pkill", "-KILL", "-u", str(account.pw_uid)], check=False)
# PAM/sshd children need to exit and be reaped before userdel.
for attempt in range(50):
cleanup = subprocess.run(["userdel", username], capture_output=True, text=True)
if cleanup.returncode == 0:
break
if cleanup.returncode != 8:
raise AssertionError(cleanup.stderr)
time.sleep(0.1)
else:
subprocess.run(["ps", "-fu", username], check=False)
raise AssertionError(cleanup.stderr)
return 0
if __name__ == "__main__":
sys.exit(main())
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
# Exercise the extracted launcher and its real native Python environment,
# intercepting only the final server exec so no host-monitoring server starts.
set -eu
appdir="$1"
export PMX_SMOKE_PYTHON
PMX_SMOKE_PYTHON="$(command -v python)"
fixture_bin="$(mktemp -d)"
trap 'rm -rf "$fixture_bin"' EXIT
cat > "$fixture_bin/python3" <<'WRAPPER'
#!/bin/sh
case "$1" in
*/flask_server.py)
exec "$PMX_SMOKE_PYTHON" -c 'import gevent, greenlet, geventwebsocket, zope.interface; from PIL import Image; from gevent import pywsgi; print("PASS: extracted AppRun native runtime")'
;;
*) exec "$PMX_SMOKE_PYTHON" "$@" ;;
esac
WRAPPER
chmod +x "$fixture_bin/python3"
PATH="$fixture_bin:$PATH" bash "$appdir/AppRun"
+188 -2
View File
@@ -5,6 +5,7 @@ and interval the host already has."""
import os
from pathlib import Path
import shutil
import shlex
import subprocess
import tempfile
import unittest
@@ -25,10 +26,176 @@ class KeepOnDiskTests(unittest.TestCase):
(self.log / "journal/abc/system.journal").write_text("entries")
(self.log / "pveproxy").mkdir()
(self.log / "pveproxy/access.log").write_text("GET /")
self.config = self.root / "etc/log2ram.conf"
self.config.parent.mkdir()
self.config.write_text("SIZE=128M\nJOURNALD_AWARE=true\nNOTIFICATION=true\n")
def run_setup(self, edit_failure=False):
# Extract only the shared setup function, never an administrative caller.
body = SETUP.read_text().split("pmx_log2ram_setup() {", 1)[1].split("\n}\n", 1)[0]
body = body.replace("/etc/", str(self.root / "etc") + "/")
for directory in ("cron.d", "tmpfiles.d"):
(self.root / "etc" / directory).mkdir(exist_ok=True)
stubs = r'''
translate() { printf '%s' "$1"; }
msg_info() { :; }
msg_ok() { :; }
pmx_install_pkg() { :; }
_pmx_log2ram_install_release() { :; }
_pmx_log2ram_pbs_logrotate() { :; }
_pmx_log2ram_remove_legacy() { :; }
pmx_edit_file() { local file="$1"; shift; sed -i "$@" "$file"; }
pmx_append_file() { cat >> "$1"; }
pmx_write_file() { cat > "$1"; }
pmx_remove_file() { rm -f "$1"; }
pmx_apply_setting() { :; }
systemctl() { printf '%s\n' "$*" >> "$SYSTEMCTL_TRACE"; }
'''
if edit_failure:
# A failed configuration writer must be handled even by root runners.
stubs += "\npmx_edit_file() { return 1; }\n"
script = (stubs + "\npmx_log2ram_setup() {" + body + "\n}\n"
+ "pmx_log2ram_setup 256 3 false\n")
env = dict(os.environ, SYSTEMCTL_TRACE=str(self.root / "systemctl.trace"),
PMX_L2R_TAG="1.7.2", PMX_L2R_SCRIPTS=str(KEEP.parent),
PMX_L2R_REVERT_UNIT=str(self.root / "etc/revert.service"))
return subprocess.run(["bash", "-c", script], env=env, capture_output=True, text=True, timeout=10)
def test_setup_keeps_journal_aware_syncing_until_boot(self):
self.config.write_text("SIZE=128M\nJOURNALD_AWARE=false\nNOTIFICATION=true\n")
result = self.run_setup()
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn("JOURNALD_AWARE=true\n", self.config.read_text())
self.assertIn("SIZE=256M\n", self.config.read_text())
self.assertFalse((self.log / "journal").is_symlink())
self.assertEqual((self.root / "systemctl.trace").read_text(), "daemon-reload\n")
def test_boot_disables_journal_aware_syncing_after_relocation(self):
self.assertEqual(self.run_setup().returncode, 0)
result = self.run_script()
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(os.readlink(self.log / "journal"), "/var/hdd.journal")
self.assertEqual((self.root / "var/hdd.journal/abc/system.journal").read_text(), "entries")
self.assertIn("JOURNALD_AWARE=false\n", self.config.read_text())
self.assertIn("SIZE=256M\n", self.config.read_text())
# Reapplying the repair to an already-relocated installation is safe.
self.assertEqual(self.run_setup().returncode, 0)
self.assertEqual(self.run_script().returncode, 0)
self.assertIn("JOURNALD_AWARE=false\n", self.config.read_text())
self.assertEqual(sorted(p.name for p in (self.root / "var/hdd.journal").iterdir()), ["abc"])
def test_boot_migration_failure_is_not_ignored_by_startup(self):
self.assertEqual(self.run_setup().returncode, 0)
# A non-directory destination causes a real copy failure, without mounts.
conflict = self.root / "var/hdd.journal"
conflict.write_text("blocked")
unit = self.root / "etc/systemd/system/log2ram.service.d/proxmenux.conf"
command = next(line.split("=", 1)[1] for line in unit.read_text().splitlines()
if line.startswith("ExecStartPre="))
result = subprocess.run(["bash", *shlex.split(command.lstrip("-"))],
env=dict(os.environ, PMX_L2R_ROOT=str(self.root)),
capture_output=True, text=True, timeout=10)
self.assertNotEqual(result.returncode, 0, result.stderr)
self.assertIn("JOURNALD_AWARE=true\n", self.config.read_text())
self.assertFalse(command.startswith("-"), "systemd must not ignore the helper's failure")
conflict.unlink()
self.assertEqual(self.run_script().returncode, 0)
self.assertIn("JOURNALD_AWARE=false\n", self.config.read_text())
def test_setup_adds_journal_aware_setting_when_missing(self):
self.config.write_text("SIZE=128M\n#JOURNALD_AWARE=false\n")
result = self.run_setup()
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn("\nJOURNALD_AWARE=true\n", self.config.read_text())
self.assertEqual(self.run_script().returncode, 0)
self.assertIn("\nJOURNALD_AWARE=false\n", self.config.read_text())
def check_missing_setting_without_final_newline(self, content):
self.config.write_text(content)
result = self.run_setup()
self.assertEqual(result.returncode, 0, result.stderr)
for expected in ("true", "false"):
with self.subTest(journal_aware=expected):
# Read shell semantics in a fresh Bash, not a substring match.
sourced = subprocess.run(
["bash", "--noprofile", "--norc", "-c",
'unset JOURNALD_AWARE NOTIFICATION; source "$1"; '
'printf "%s\\n%s\\n" "${JOURNALD_AWARE-UNSET}" "${NOTIFICATION-UNSET}"',
"fixture", str(self.config)],
capture_output=True, text=True, timeout=10)
self.assertEqual(sourced.returncode, 0, sourced.stderr)
self.assertEqual(sourced.stdout, expected + "\nfalse\n")
if expected == "true":
self.assertFalse((self.log / "journal").is_symlink())
self.assertEqual((self.log / "journal/abc/system.journal").read_text(), "entries")
result = self.run_script()
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(os.readlink(self.log / "journal"), "/var/hdd.journal")
self.assertEqual((self.root / "var/hdd.journal/abc/system.journal").read_text(), "entries")
def test_missing_setting_after_comment_without_final_newline(self):
self.check_missing_setting_without_final_newline(
"SIZE=128M\nNOTIFICATION=false\n#JOURNALD_AWARE=false")
def test_missing_setting_after_assignment_without_final_newline(self):
self.check_missing_setting_without_final_newline("SIZE=128M\nNOTIFICATION=false")
def test_setup_reports_configuration_edit_failure(self):
self.config.write_text("SIZE=128M\nJOURNALD_AWARE=false\nNOTIFICATION=false\n")
result = self.run_setup(edit_failure=True)
self.assertNotEqual(result.returncode, 0, result.stderr)
self.assertIn("JOURNALD_AWARE=false\n", self.config.read_text())
def test_an_existing_link_with_an_unusable_disk_target_fails(self):
self.assertEqual(self.run_script().returncode, 0)
self.config.write_text("JOURNALD_AWARE=true\n")
disk = self.root / "var/hdd.journal"
shutil.rmtree(disk)
disk.write_text("blocked")
result = self.run_script()
self.assertNotEqual(result.returncode, 0, result.stderr)
self.assertEqual(self.config.read_text(), "JOURNALD_AWARE=true\n")
def test_an_unexpected_journal_link_does_not_complete_migration(self):
shutil.rmtree(self.log / "journal")
(self.log / "journal").symlink_to("pveproxy")
result = self.run_script()
self.assertNotEqual(result.returncode, 0, result.stderr)
self.assertEqual(os.readlink(self.log / "journal"), "pveproxy")
self.assertIn("JOURNALD_AWARE=true\n", self.config.read_text())
def test_a_missing_journal_with_an_unusable_disk_target_fails(self):
shutil.rmtree(self.log / "journal")
(self.root / "var/hdd.journal").write_text("blocked")
result = self.run_script()
self.assertNotEqual(result.returncode, 0, result.stderr)
self.assertIn("JOURNALD_AWARE=true\n", self.config.read_text())
self.assertFalse((self.log / "journal").is_symlink())
def test_failed_source_removal_does_not_complete_migration(self):
(self.root / "var/hdd.journal").mkdir()
result = subprocess.run(
["bash", "-c", 'rm() { return 1; }; export -f rm; exec bash "$1"', "fixture", str(KEEP)],
env=dict(os.environ, PMX_L2R_ROOT=str(self.root)), capture_output=True, text=True, timeout=10)
self.assertNotEqual(result.returncode, 0, result.stderr)
self.assertIn("JOURNALD_AWARE=true\n", self.config.read_text())
self.assertTrue((self.log / "journal/abc/system.journal").is_file())
def test_boot_configuration_failure_is_reported_and_can_be_retried(self):
self.config.unlink()
self.config.mkdir()
result = self.run_script()
self.assertNotEqual(result.returncode, 0, result.stderr)
self.assertEqual(os.readlink(self.log / "journal"), "/var/hdd.journal")
self.config.rmdir()
self.config.write_text("JOURNALD_AWARE=true\n")
self.assertEqual(self.run_script().returncode, 0)
self.assertEqual(self.config.read_text(), "JOURNALD_AWARE=false\n")
def run_script(self, revert=False):
env = dict(os.environ, PMX_L2R_ROOT=str(self.root), PMX_L2R_REVERT="1" if revert else "0")
return subprocess.run(["bash", str(KEEP)], env=env, capture_output=True, text=True)
return subprocess.run(["bash", str(KEEP)], env=env, capture_output=True, text=True, timeout=10)
def test_the_journal_moves_to_disk_behind_a_link(self):
self.assertEqual(self.run_script().returncode, 0)
@@ -78,6 +245,7 @@ class KeepOnDiskTests(unittest.TestCase):
def test_removing_log2ram_puts_the_folders_back(self):
(self.log / "proxmox-backup").mkdir()
self.run_script()
self.config.unlink() # Revert must not require or rewrite Log2RAM settings.
self.assertEqual(self.run_script(revert=True).returncode, 0)
for name in ("journal", "proxmox-backup"):
self.assertFalse((self.log / name).is_symlink(), name)
@@ -99,7 +267,7 @@ class KeptSettingsTests(unittest.TestCase):
library = Path(folder) / "setup.sh"
library.write_text(script)
result = subprocess.run(["bash", "-c", f'source "{library}"; {function}'],
capture_output=True, text=True)
capture_output=True, text=True, timeout=10)
return result.stdout.strip()
def test_the_size_comes_from_the_installed_configuration(self):
@@ -114,6 +282,24 @@ class KeptSettingsTests(unittest.TestCase):
cron = "MAILTO=\"\"\n0 */3 * * * root /usr/local/bin/log2ram write >/dev/null 2>&1\n"
self.assertEqual(self.read("pmx_log2ram_current_hours", {"/etc/cron.d/log2ram": cron}), "3")
def test_both_modes_offer_a_repair_to_version_2_0_installs(self):
for filename, function, updater in (
("auto_post_install.sh", "install_log2ram_auto", "_update_existing_log2ram_auto"),
("customizable_post_install.sh", "configure_log2ram", "_update_existing_log2ram_custom"),
):
with self.subTest(mode=filename), tempfile.TemporaryDirectory() as folder:
config = Path(folder) / "log2ram.conf"
config.write_text("JOURNALD_AWARE=false\n")
source = (ROOT / "scripts/post_install" / filename).read_text()
body = source.split(function + "() {", 1)[1].split("\n}\n", 1)[0]
body = body.replace("/etc/log2ram.conf", str(config))
script = ("pmx_journal_context() { :; }\n"
+ updater + "() { printf '%s\\n' \"$1\"; }\n"
+ function + "() {" + body + "\n}\n" + function)
result = subprocess.run(["bash", "-c", script], capture_output=True, text=True, timeout=10)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertEqual(result.stdout.strip(), "2.1")
def test_the_release_is_pinned_to_a_verified_commit(self):
text = SETUP.read_text()
self.assertIn('PMX_L2R_TAG="1.7.2"', text)
@@ -14,15 +14,16 @@ class OciPveVersionGateTests(unittest.TestCase):
@classmethod
def setUpClass(cls):
text = LAUNCHER.read_text(encoding='utf-8')
cls.function = re.search(r'^pve_supports_oci\(\) \{\n.*?^\}\n', text, re.M | re.S).group(0)
cls.function = ''.join(re.search(rf'^{name}\(\) \{{\n.*?^\}}\n', text, re.M | re.S).group(0)
for name in ('pve_manager_version', 'pve_supports_oci'))
cls.text = text
def supported(self, version):
with tempfile.TemporaryDirectory() as folder:
fake = Path(folder, 'pveversion')
# Without Proxmox the command is missing: a stand-in that fails hides the host's own.
fake.write_text('#!/bin/sh\nexit 127\n' if version is None else
f'#!/bin/sh\necho "pve-manager/{version}/b9984c6d90a4bd80 (running kernel: 6.17)"\n')
fake = Path(folder, 'dpkg-query')
# Without Proxmox the package is not installed: dpkg-query fails.
fake.write_text('#!/bin/sh\nexit 1\n' if version is None else
f'#!/bin/sh\nprintf %s "{version}"\n')
fake.chmod(0o755)
result = subprocess.run(['bash', '-c', f'PATH={folder}:/usr/bin:/bin\n{self.function}pve_supports_oci'],
capture_output=True, text=True)
@@ -38,6 +39,9 @@ class OciPveVersionGateTests(unittest.TestCase):
with self.subTest(version=version):
self.assertFalse(self.supported(version))
def test_the_version_is_read_without_the_slow_pveversion(self):
self.assertNotIn('pveversion', self.function)
def test_it_is_checked_before_anything_is_installed(self):
self.assertLess(self.text.index('if ! pve_supports_oci; then'), self.text.index('ensure_oci_dependencies || exit 1'))
+11 -3
View File
@@ -12,7 +12,7 @@ from unittest.mock import Mock, patch
ROOT=Path(__file__).resolve().parents[3]
sys.path[:0]=[str(ROOT/'oci/src'),str(ROOT/'oci/remote')]
from proxmenux_oci import cli, custom, custom_mounts, extra_devices, i18n, installer, ui as native_ui, updates
from proxmenux_oci import catalog_refresh, cli, custom, custom_mounts, extra_devices, i18n, installer, ui as native_ui, updates
from proxmenux_oci.catalog import Catalog
@@ -202,9 +202,17 @@ class InputAndCancellationTests(StorageFixture):
def test_real_menu_error_handler_has_slovak_heading_and_preserves_detail(self):
ui=Mock();ui.choose.side_effect=['custom',None]
with patch.object(cli,'interactive_ui',return_value=ui),patch.object(custom,'explore',side_effect=ValueError('fiction-detail')), \
patch.object(updates,'UpdateCheck') as checker:
with patch.object(cli,'interactive_ui',return_value=ui),patch.object(cli,'_catalog_options',return_value=([],{}, {}, {}, [])), \
patch.object(custom,'explore',side_effect=ValueError('fiction-detail')), \
patch.object(updates,'UpdateCheck') as checker, \
patch.object(catalog_refresh,'CatalogRefresh') as catalog_checker:
# Keep this wording/error-handler test offline and free of writes.
# The real background worker has its own catalog lifecycle tests.
catalog_check=catalog_checker.return_value.__enter__.return_value
catalog_check.active=False;catalog_check.consume.return_value=False
catalog_check.failed=False;catalog_check.label.return_value='Refresh catalog'
check=checker.return_value.__enter__.return_value
check.active=False;check.notice.return_value='';check.status.return_value={'available':[]}
check.label.return_value='Check for updates'
self.assertEqual(cli.interactive(self.catalog),0)
ui.message.assert_called_once_with('Operáciu sa nepodarilo dokončiť:\n\nfiction-detail')
+488
View File
@@ -0,0 +1,488 @@
"""USB/IP ownership, device identity, SSH policy and service regression tests.
No physical USB devices, live systemd units or host configuration are changed.
The optional Linux integration lane exercises actual SSH, socat and namespaces.
"""
import copy
import importlib.util
import json
import os
from pathlib import Path
import shutil
import socket
import subprocess
import sys
import tempfile
import unittest
from types import SimpleNamespace
from unittest.mock import patch
ROOT = Path(__file__).resolve().parents[3]
SOURCE = ROOT / "scripts/devices/usbip_manager.py"
EXPORT = "abcdef123456"
CLIENT = "fedcba654321"
def load():
spec = importlib.util.spec_from_file_location("usbip_manager", SOURCE)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
class USBIPTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
self.root = Path(self.temp.name)
self.m = load()
for attr, path in (("CONFIG_DIR", "config"), ("RUN_DIR", "client-run"),
("SERVER_RUN_DIR", "server-run"), ("UNIT_DIR", "units"), ("SYSFS", "sysfs"),
("NET_SYSFS", "net")):
setattr(self.m, attr, self.root / path)
getattr(self.m, attr).mkdir()
class MatchTable:
# Mirror the kernel contract, not regular-file write semantics:
# del(ALLOC)=REMOV, del(ADDED/REMOV) retains the named slot.
def __init__(self):
self.slots = {}
def write_text(self, value):
action, busid = value.split()
if self.slots.get(busid) == "ALLOC":
self.slots[busid] = "REMOV"
def read_text(self):
return " ".join(self.slots)
self.m.MATCH_BUSID = MatchTable()
self.account = SimpleNamespace(pw_uid=1234, pw_gid=1234)
self.calls = []
self.key = self.root / "id_ed25519"
self.key.write_text("test-key")
self.key.chmod(0o600)
self.remote = {"host": "usb.example.test", "ssh_port": 2222, "key": str(self.key)}
def config(self, exports=None, imports=None, server=True):
value = {"server": server, "exports": exports or [], "imports": imports or []}
self.m.atomic_json(self.m.CONFIG_DIR / "config.json", value)
return value
def test_a_usb_network_adapter_is_not_offered(self):
self.device("1-3", serial="nic-1")
(self.m.NET_SYSFS / "enx001122").mkdir()
(self.m.NET_SYSFS / "enx001122" / "device").symlink_to(self.m.SYSFS / "1-3" / "1-3:1.0")
self.assertEqual(next(d for d in self.m.inventory() if d["busid"] == "1-3")["blocked"],
"USB network adapters cannot be shared")
self.device("1-4", serial="zigbee-9")
self.assertEqual(next(d for d in self.m.inventory() if d["busid"] == "1-4")["blocked"], "")
def device(self, busid="1-2", serial="zigbee-123", device_class="00", interface="03", driver="usb"):
path = self.m.SYSFS / busid
path.mkdir()
values = {"idVendor": "10c4", "idProduct": "ea60", "serial": serial,
"product": "Test Zigbee adapter", "bDeviceClass": device_class}
for key, value in values.items():
(path / key).write_text(value)
child = path / f"{busid}:1.0"
child.mkdir()
(child / "bInterfaceClass").write_text(interface)
self.set_driver(busid, driver)
return next(d for d in self.m.inventory() if d["busid"] == busid)
def set_driver(self, busid, driver):
target = self.root / "drivers" / driver
target.mkdir(parents=True, exist_ok=True)
path = self.m.SYSFS / busid / "driver"
path.unlink(missing_ok=True)
path.symlink_to(target, target_is_directory=True)
def selected(self, device):
return {k: device[k] for k in ("busid", "vendor", "product", "serial", "name")} | {"id": EXPORT}
def usb(self, args, timeout=20):
self.calls.append(args)
if args[:2] == ["usbip", "bind"]:
self.set_driver(args[-1], "usbip-host")
self.m.MATCH_BUSID.slots[args[-1]] = "ALLOC"
elif args[:2] == ["usbip", "unbind"]:
self.set_driver(args[-1], "usb")
self.m.MATCH_BUSID.slots.pop(args[-1], None)
return ""
def test_storage_composite_interfaces_and_hubs_are_never_exported(self):
for index, (base, interface) in enumerate((("08", "06"), ("09", "00"), ("00", "08"), ("", "03"))):
device = self.device(busid=f"1-{index + 1}", device_class=base, interface=interface)
self.assertTrue(device["blocked"])
self.config()
with self.assertRaises(self.m.USBIPError), patch.object(self.m, "run") as command:
self.m.add_export(device["busid"])
command.assert_not_called()
self.assertEqual(self.m.load_config()["exports"], [])
def test_export_intent_is_private_and_bind_is_idempotent(self):
device = self.device()
self.config()
selected = self.m.add_export(device["busid"])
owned = {}
with patch.object(self.m, "run", side_effect=self.usb):
self.assertEqual(self.m.reconcile_exports(self.m.load_config(), owned), {})
self.assertEqual(self.m.reconcile_exports(self.m.load_config(), owned), {})
self.assertEqual(self.calls, [["usbip", "bind", "--busid", "1-2"]])
self.assertEqual(self.m.catalog()[0]["id"], selected["id"])
self.assertEqual(self.m.catalog()[0]["status"], "exported")
for path in (self.m.CONFIG_DIR / "config.json", self.m.state_path()):
self.assertEqual(path.stat().st_mode & 0o777, 0o600)
self.assertNotEqual(self.m.RUN_DIR, self.m.SERVER_RUN_DIR)
def test_port_move_fails_closed_when_kernel_retains_old_slot(self):
selected = self.selected(self.device())
config = self.config([selected])
owned = {}
with patch.object(self.m, "run", side_effect=self.usb):
self.m.reconcile_exports(config, owned)
shutil.rmtree(self.m.SYSFS / "1-2")
self.device(serial="other-device", driver="usbip-host")
self.device(busid="2-4")
errors = self.m.reconcile_exports(config, owned)
self.assertIn("blocked", errors[EXPORT])
self.assertEqual(owned[EXPORT]["busid"], "1-2")
self.assertEqual(self.calls, [["usbip", "bind", "--busid", "1-2"]])
self.assertIsNone(self.m.catalog()[0]["busid"])
def test_retained_slot_is_rejected_before_detaching_reconnected_local_usb(self):
device = self.device()
selected = self.selected(device)
config = self.config([selected])
self.m.MATCH_BUSID.slots[device["busid"]] = "REMOV"
with patch.object(self.m, "run", side_effect=self.usb):
errors = self.m.reconcile_exports(config, {EXPORT: selected}, {})
self.assertIn("local driver", errors[EXPORT])
self.assertEqual(self.calls, [])
self.assertEqual(self.m.inventory()[0]["driver"], "usb")
def test_imported_usb_does_not_shadow_physical_original(self):
device = self.device()
imported = self.m.SYSFS / "2-1"
imported.symlink_to(self.m.SYSFS / "1-2", target_is_directory=True)
target = self.root / "vhci_hcd.0" / "2-1"
target.parent.mkdir()
shutil.copytree(self.m.SYSFS / "1-2", target, symlinks=True)
imported.unlink()
imported.symlink_to(target, target_is_directory=True)
devices = self.m.inventory()
self.assertEqual(len(devices), 1)
self.assertEqual(self.m.resolve_device(device, devices)["busid"], "1-2")
def test_no_serial_requires_same_busid_and_ambiguous_serial_is_rejected(self):
selected = self.selected(self.device(serial=""))
shutil.rmtree(self.m.SYSFS / "1-2")
self.device(busid="2-4", serial="")
with self.assertRaises(self.m.USBIPError):
self.m.resolve_device(selected, self.m.inventory())
self.device(busid="1-3", serial="duplicate")
first = self.device(busid="1-4", serial="duplicate")
with self.assertRaises(self.m.USBIPError):
self.m.resolve_device(first, self.m.inventory())
def test_foreign_exports_are_not_adopted_and_disable_only_releases_owned_devices(self):
own = self.selected(self.device())
foreign = self.device(busid="1-3", serial="foreign", driver="usbip-host")
config = self.config([own, self.selected(foreign) | {"id": CLIENT}])
owned = {}
with patch.object(self.m, "run", side_effect=self.usb):
errors = self.m.reconcile_exports(config, owned)
self.assertIn("outside ProxMenux", errors[CLIENT])
config["server"] = False
self.m.reconcile_exports(config, owned)
self.assertEqual(self.calls, [["usbip", "bind", "--busid", "1-2"], ["usbip", "unbind", "--busid", "1-2"]])
self.assertEqual(owned, {})
self.assertEqual(next(d for d in self.m.inventory() if d["busid"] == "1-3")["driver"], "usbip-host")
def test_recover_bind_intent_and_remove_selected_export(self):
selected = self.selected(self.device(driver="usbip-host"))
self.config([selected])
owned = {EXPORT: selected}
self.m.atomic_json(self.m.state_path(), owned)
with patch.object(self.m, "run", side_effect=self.usb):
self.m.reconcile_exports(self.m.load_config(), owned)
self.assertEqual(self.calls, [])
with patch.object(self.m.time, "sleep", side_effect=lambda _: self.m.reconcile_exports(self.m.load_config(), owned)):
self.m.remove_export(EXPORT)
self.m.reconcile_exports(self.m.load_config(), owned)
self.assertEqual(self.calls, [["usbip", "unbind", "--busid", "1-2"]])
def test_failed_bind_is_reported_and_retains_recoverable_intent(self):
selected = self.selected(self.device())
config = self.config([selected])
owned = {}
with patch.object(self.m, "run", side_effect=self.m.USBIPError("bind failed")):
self.assertEqual(self.m.reconcile_exports(config, owned), {EXPORT: "bind failed"})
self.assertIn(EXPORT, self.m.read_json(self.m.state_path(), {}))
self.assertEqual(self.m.status()["server_status"]["errors"], {EXPORT: "bind failed"})
self.assertEqual(self.m.catalog()[0]["status"], "waiting")
def test_unplugged_kernel_match_is_disarmed_but_not_falsely_forgotten(self):
selected = self.selected(self.device())
config = self.config([selected])
owned = {}
with patch.object(self.m, "run", side_effect=self.usb):
self.m.reconcile_exports(config, owned)
shutil.rmtree(self.m.SYSFS / "1-2")
errors = self.m.reconcile_exports(config, owned)
self.assertEqual(owned[EXPORT]["busid"], "1-2")
self.assertIn("blocked", errors[EXPORT])
self.assertEqual(self.m.MATCH_BUSID.slots["1-2"], "REMOV")
self.assertEqual(len(self.calls), 1)
def test_failed_stale_cleanup_does_not_forget_or_replace_ownership(self):
selected = self.selected(self.device())
config = self.config([selected])
owned = {EXPORT: selected}
shutil.rmtree(self.m.SYSFS / "1-2")
self.device(busid="2-4")
with patch.object(self.m, "disarm_match", side_effect=self.m.USBIPError("disarm failed")), patch.object(self.m, "run") as command:
errors = self.m.reconcile_exports(config, owned)
self.assertIn("disarm", errors[EXPORT])
self.assertEqual(owned[EXPORT]["busid"], "1-2")
command.assert_not_called()
def test_authorized_key_is_restricted_and_policy_stays_root_owned(self):
self.m.TRANSPORT_HOME = self.root / "transport-home"
account = SimpleNamespace(pw_uid=1234, pw_gid=1234, pw_dir=str(self.m.TRANSPORT_HOME))
public = self.root / "client.pub"
public.write_text("ssh-ed25519 AAAA test-client")
with patch.object(self.m.pwd, "getpwnam", side_effect=[KeyError(), account]), patch.object(
self.m, "run"
) as command, patch.object(self.m.os, "chown"), patch.object(self.m.os, "fchown"):
self.m.authorize_key(public)
command.assert_called_once()
self.assertEqual(command.call_args.args[0][0], "useradd")
policy = self.m.TRANSPORT_HOME / ".ssh/authorized_keys"
self.assertEqual(policy.stat().st_mode & 0o777, 0o640)
self.assertEqual(policy.read_text(), 'restrict,command="/usr/bin/python3 ' + self.m.REMOTE_SCRIPT + ' transport" ssh-ed25519 AAAA\n')
with patch.object(self.m.pwd, "getpwnam", return_value=account), patch.object(
self.m.os, "chown"
), patch.object(self.m.os, "fchown"):
self.m.authorize_key(public)
self.assertEqual(len(policy.read_text().splitlines()), 1)
def test_authorize_never_adopts_an_existing_foreign_account(self):
self.m.TRANSPORT_HOME = self.root / "foreign-home"
account = SimpleNamespace(pw_uid=1234, pw_gid=1234, pw_dir=str(self.m.TRANSPORT_HOME))
public = self.root / "client.pub"
public.write_text("ssh-ed25519 AAAA test-client")
with patch.object(self.m.pwd, "getpwnam", return_value=account), patch.object(self.m, "run") as command:
with self.assertRaisesRegex(self.m.USBIPError, "existing"):
self.m.authorize_key(public)
command.assert_not_called()
self.assertFalse(self.m.TRANSPORT_HOME.exists())
def test_forced_command_rejects_shell_and_wrong_identity(self):
for command in ("id", "catalog; id", "", "stream --socket /run/other.sock"):
with patch.object(self.m, "transport_account", return_value=self.account), patch.object(
self.m.os, "geteuid", return_value=1234
), patch.dict(os.environ, {"SSH_ORIGINAL_COMMAND": command}), patch.object(self.m.os, "execvp") as execute:
with self.assertRaisesRegex(self.m.USBIPError, "Only USB/IP"):
self.m.transport()
execute.assert_not_called()
with patch.object(self.m, "transport_account", return_value=self.account), patch.object(self.m.os, "geteuid", return_value=0):
with self.assertRaisesRegex(self.m.USBIPError, "unprivileged"):
self.m.transport()
def test_forced_command_catalog_and_stream_are_fixed(self):
(self.m.SERVER_RUN_DIR / "catalog.json").write_text("[]")
with patch.object(self.m, "transport_account", return_value=self.account), patch.object(self.m.os, "geteuid", return_value=1234):
with patch.dict(os.environ, {"SSH_ORIGINAL_COMMAND": "catalog"}), patch("builtins.print") as output:
self.m.transport()
output.assert_called_once_with("[]")
with patch.dict(os.environ, {"SSH_ORIGINAL_COMMAND": "stream"}), patch.object(self.m.os, "execvp") as execute:
self.m.transport()
execute.assert_called_once_with("socat", ["socat", "STDIO", "UNIX-CONNECT:" + self.m.REMOTE_SOCKET])
def test_loopback_port_is_held_until_tunnel_stops(self):
with socket.socket() as unused:
unused.bind(("127.0.0.1", 0))
port = unused.getsockname()[1]
tunnel = self.m.LoopbackTunnel(self.remote | {"local_port": port})
try:
with socket.socket() as attacker:
with self.assertRaises(OSError):
attacker.bind(("127.0.0.1", port))
with self.assertRaisesRegex(self.m.USBIPError, "in use"):
self.m.LoopbackTunnel(self.remote | {"local_port": port})
finally:
tunnel.terminate()
self.assertEqual(tunnel.poll(), 0)
def test_namespace_guard_fails_before_spawning_a_listener(self):
with patch.object(self.m.os, "readlink", return_value="net:[1]"), patch.object(self.m.subprocess, "Popen") as process:
with self.assertRaisesRegex(self.m.USBIPError, "PrivateNetwork"):
self.m.serve()
process.assert_not_called()
def test_generated_units_are_isolated_quoted_and_owned(self):
self.m.SCRIPT = self.root / 'with space/%and$dollar"quote.py'
with patch("shutil.which", return_value="/usr/sbin/modprobe"):
server = self.m.unit_text("server")
client = self.m.unit_text("client", CLIENT)
self.assertIn("PrivateNetwork=yes", server)
self.assertIn("RuntimeDirectory=proxmenux-usbip-server", server)
self.assertIn("RuntimeDirectoryPreserve=yes", server)
self.assertIn('%%and$$dollar\\"quote.py" serve', server)
self.assertNotIn("PrivateNetwork=yes", client)
self.assertNotIn("RuntimeDirectory=", client)
self.assertIn("vhci-hcd", client)
self.assertIn("Restart=on-failure", client)
unit = self.m.UNIT_DIR / self.m.SERVER_UNIT
unit.write_text("[Unit]\nDescription=Someone else's service\n")
with self.assertRaises(self.m.USBIPError), patch.object(self.m, "run") as command:
self.m.update_server(True)
command.assert_not_called()
self.assertFalse((self.m.CONFIG_DIR / "config.json").exists())
def test_failed_server_start_restores_configuration_and_removes_new_unit(self):
previous = self.config(server=False)
def fail_start(args, timeout=20):
self.calls.append(args)
if args[:3] == ["systemctl", "enable", "--now"]:
raise self.m.USBIPError("start failed")
return ""
with patch.object(self.m, "transport_account", return_value=self.account), patch.object(self.m, "run", side_effect=fail_start), patch("shutil.which", return_value="/sbin/modprobe"):
with self.assertRaisesRegex(self.m.USBIPError, "start failed"):
self.m.update_server(True)
self.assertEqual(self.m.load_config(), previous)
self.assertFalse((self.m.UNIT_DIR / self.m.SERVER_UNIT).exists())
self.assertIn(["systemctl", "disable", "--now", self.m.SERVER_UNIT], self.calls)
def test_ssh_policy_and_argument_boundaries(self):
remote = self.m.validate_remote(self.remote["host"], 2222, str(self.key))
args = self.m.tunnel_args(remote | {"local_port": 33240})
for required in ("BatchMode=yes", "StrictHostKeyChecking=yes", "IdentitiesOnly=yes", "ForwardAgent=no",
"PasswordAuthentication=no", "ExitOnForwardFailure=yes"):
self.assertIn(required, args)
self.assertIn("proxmenux-usbip", args)
self.assertNotIn("root", args)
self.assertNotIn("-L", args)
self.assertNotIn("-N", args)
self.assertNotIn("StrictHostKeyChecking=no", args)
self.assertEqual(args[-3:], ["--", "usb.example.test", "stream"])
for host in ("-oProxyCommand=touch /tmp/no", "root@host", "host;id", "host\nother", "$(id)"):
with self.assertRaises(self.m.USBIPError):
self.m.validate_remote(host, 22, str(self.key))
self.key.chmod(0o644)
with self.assertRaisesRegex(self.m.USBIPError, "permissions"):
self.m.validate_remote("192.0.2.1", 22, str(self.key))
def test_ssh_credential_or_catalog_failure_never_saves_a_connection(self):
for failure in (self.m.USBIPError("Permission denied"), self.m.USBIPError("Connection timed out")):
with patch.object(self.m, "run", side_effect=failure):
with self.assertRaises(self.m.USBIPError):
self.m.add_import(self.remote, EXPORT, 33240)
self.assertFalse((self.m.CONFIG_DIR / "config.json").exists())
with patch.object(self.m, "run", return_value='[{"id":"--bad","busid":"1-2"}]'):
with self.assertRaisesRegex(self.m.USBIPError, "valid"):
self.m.remote_catalog(self.remote)
def test_import_service_failure_rolls_back_and_occupied_port_is_rejected(self):
exports = [{"id": EXPORT, "status": "exported", "busid": "1-2"}]
previous = self.config()
with patch.object(self.m, "remote_catalog", return_value=exports):
with socket.socket() as busy:
busy.bind(("127.0.0.1", 0))
with self.assertRaisesRegex(self.m.USBIPError, "in use"):
self.m.add_import(self.remote, EXPORT, busy.getsockname()[1])
with socket.socket() as unused:
unused.bind(("127.0.0.1", 0))
port = unused.getsockname()[1]
with patch("shutil.which", return_value="/sbin/modprobe"), patch.object(self.m, "enable_unit", side_effect=self.m.USBIPError("failed")):
with self.assertRaises(self.m.USBIPError):
self.m.add_import(self.remote, EXPORT, port)
self.assertEqual(self.m.load_config(), previous)
def port(self, **overrides):
return {"port": 2, "status": "Port in Use", "local_busid": "3-1", "host": "127.0.0.1", "tcp_port": 33240,
"busid": "1-2"} | overrides
def test_real_upstream_port_output_and_unowned_port_cleanup(self):
output = """Imported USB devices
====================
Port 02: <Port in Use> at High Speed(480Mbps)
Test Zigbee adapter (10c4:ea60)
3-1 -> usbip://127.0.0.1:33240/1-2
-> remote bus/dev 001/002
Port 03: <Port Error> at Full Speed(12Mbps)
Another adapter
3-2 -> usbip://192.0.2.1:3240/1-3
"""
ports = self.m.parse_ports(output)
self.assertEqual(ports[0], self.port())
self.assertEqual(ports[1]["status"], "Port Error")
owner = self.m.RUN_DIR / f"client-{CLIENT}.json"
self.m.atomic_json(owner, ports[0])
reused = self.port(local_busid="3-7")
with patch.object(self.m, "imported_ports", return_value=[reused, ports[1]]), patch.object(self.m, "run") as command:
self.m.release_import(owner)
command.assert_not_called()
self.assertFalse(owner.exists())
self.m.atomic_json(owner, ports[0])
with patch.object(self.m, "imported_ports", return_value=ports), patch.object(self.m, "run") as command:
self.m.release_import(owner)
command.assert_called_once_with(["usbip", "detach", "--port", "2"])
def test_attach_reuses_live_port_and_recovers_error_with_new_remote_busid(self):
selected = self.remote | {"id": CLIENT, "local_port": 33240, "export_id": EXPORT}
owner = self.m.RUN_DIR / f"client-{CLIENT}.json"
self.m.atomic_json(owner, self.port())
with patch.object(self.m, "imported_ports", return_value=[self.port()]), patch.object(self.m, "remote_catalog") as remote:
self.assertEqual(self.m.attach_once(selected, owner)["port"], 2)
remote.assert_not_called()
ports = [self.port(status="Port Error")]
def usb(args, timeout=20):
self.calls.append(args)
if "detach" in args:
ports.clear()
elif "attach" in args:
ports.append(self.port(busid="2-4", local_busid="3-5"))
return ""
with patch.object(self.m, "imported_ports", side_effect=lambda: copy.deepcopy(ports)), patch.object(
self.m, "remote_catalog", return_value=[{"id": EXPORT, "status": "exported", "busid": "2-4"}]
), patch.object(self.m, "run", side_effect=usb):
attached = self.m.attach_once(selected, owner)
self.assertEqual(attached["busid"], "2-4")
self.assertEqual(self.calls, [["usbip", "detach", "--port", "2"],
["usbip", "--tcp-port", "33240", "attach", "--remote", "127.0.0.1", "--busid", "2-4"]])
self.assertEqual(self.m.read_json(owner, None), attached)
def test_missing_remote_or_unowned_import_is_never_detached(self):
selected = self.remote | {"id": CLIENT, "local_port": 33240, "export_id": EXPORT}
owner = self.m.RUN_DIR / f"client-{CLIENT}.json"
with patch.object(self.m, "remote_catalog", return_value=[]), patch.object(self.m, "run") as command:
with self.assertRaisesRegex(self.m.USBIPError, "unplugged"):
self.m.attach_once(selected, owner)
command.assert_not_called()
with patch.object(self.m, "remote_catalog", return_value=[{"id": EXPORT, "status": "exported", "busid": "1-2"}]), patch.object(
self.m, "imported_ports", return_value=[self.port()]
), patch.object(self.m, "run") as command:
with self.assertRaisesRegex(self.m.USBIPError, "unowned"):
self.m.attach_once(selected, owner)
command.assert_not_called()
@unittest.skipUnless(sys.platform == "linux" and shutil.which("systemd-analyze"), "systemd verifier requires Linux")
def test_systemd_accepts_both_generated_service_files(self):
with patch("shutil.which", return_value="/bin/true"):
for name, content in ((self.m.SERVER_UNIT, self.m.unit_text("server")),
(self.m.unit_name(CLIENT), self.m.unit_text("client", CLIENT))):
path = self.m.UNIT_DIR / name
path.write_text(content)
result = subprocess.run(["systemd-analyze", "verify", str(path)], capture_output=True, text=True)
self.assertEqual(result.returncode, 0, result.stderr)
def test_menu_and_search_expose_server_and_client_actions(self):
menu = (ROOT / "scripts/menus/hw_grafics_menu.sh").read_text()
self.assertIn('bash "$LOCAL_SCRIPTS/devices/usbip_menu.sh"', menu)
index = json.loads((ROOT / "scripts/menus/search_index.json").read_text())
self.assertTrue(any(i["script"] == "devices/usbip_menu.sh" and "usbip" in i["keywords"] for i in index))
for script in (ROOT / "scripts/devices/usbip_menu.sh", ROOT / "scripts/menus/hw_grafics_menu.sh"):
subprocess.run(["bash", "-n", str(script)], check=True)
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,112 @@
"""Absent-slot recovery must require a verified pin and completed kernel removal."""
import importlib.util
import errno
from pathlib import Path
import socket
import tempfile
import unittest
from unittest.mock import Mock, patch
SOURCE = Path(__file__).resolve().parents[3] / "scripts/devices/usbip_lifetime.py"
spec = importlib.util.spec_from_file_location("usbip_lifetime", SOURCE)
l = importlib.util.module_from_spec(spec)
spec.loader.exec_module(l)
class LifetimeTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory()
self.addCleanup(self.temp.cleanup)
self.root = Path(self.temp.name)
lease = l.Lease.__new__(l.Lease)
lease.path = self.root / "1-2"
lease.devpath = "/devices/test/usb1/1-2"
lease.bus = 1
lease.number = 3
lease.sequence = 100
lease.ready = True
lease.removed = False
lease.fds = []
lease.events = Mock()
lease.events.recvmsg.side_effect = BlockingIOError()
self.lease = lease
self.match = Mock()
self.match.parent = self.root
self.match.read_text.side_effect = lambda: (
"" if (self.root / "rebind").exists() else "1-2"
)
def event(self, **changes):
values = {
"ACTION": "remove",
"DEVTYPE": "usb_device",
"DEVPATH": self.lease.devpath,
"BUSNUM": "001",
"DEVNUM": "003",
"SEQNUM": "101",
} | changes
return b"\0".join(f"{k}={v}".encode() for k, v in values.items()) + b"\0"
def test_no_rebind_without_a_verified_lifetime_pin(self):
self.lease.ready = False
self.lease.removed = True
with self.assertRaises(l.LifetimeError):
self.lease.release(self.match, Mock())
self.assertFalse((self.root / "rebind").exists())
def test_rebind_requires_completed_removal_not_only_missing_sysfs(self):
with patch.object(
self.lease, "validate", side_effect=FileNotFoundError()
), patch.object(l.time, "monotonic", side_effect=[0, 3, 4]):
with self.assertRaisesRegex(l.LifetimeError, "Waiting"):
self.lease.release(self.match, Mock())
self.assertFalse((self.root / "rebind").exists())
def test_unrelated_or_userspace_events_do_not_authorize_slot_recovery(self):
packets = [
(self.event(SEQNUM="99"), [], 0, (0, 1)),
(self.event(DEVNUM="004"), [], 0, (0, 1)),
(self.event(DEVPATH="/devices/other"), [], 0, (0, 1)),
(self.event(), [], 0, (12345, 1)),
(self.event(DEVTYPE="usb_interface"), [], 0, (0, 1)),
BlockingIOError(),
]
self.lease.events.recvmsg.side_effect = packets
self.assertFalse(self.lease.poll_removed())
def test_lost_or_truncated_events_invalidate_recovery(self):
for fault in (
OSError(errno.ENOBUFS, "overflow"),
(self.event(), [], socket.MSG_TRUNC, (0, 1)),
):
self.lease.ready = True
self.lease.events.recvmsg.side_effect = [fault]
with self.assertRaises(l.LifetimeError):
self.lease.poll_removed()
self.assertFalse(self.lease.ready)
self.assertFalse((self.root / "rebind").exists())
def test_pinned_completed_removal_cleans_only_its_slot(self):
self.lease.events.recvmsg.side_effect = [
(self.event(), [], 0, (0, 1)),
BlockingIOError(),
]
unbind = Mock()
self.lease.release(self.match, unbind)
unbind.assert_not_called()
self.assertEqual((self.root / "rebind").read_text(), "1-2")
self.assertFalse(self.lease.ready)
def test_present_device_uses_native_unbind_not_absent_recovery(self):
self.match.read_text.return_value = ""
self.match.read_text.side_effect = None
unbind = Mock()
with patch.object(self.lease, "validate"):
self.lease.release(self.match, unbind)
unbind.assert_called_once_with("1-2")
self.assertFalse((self.root / "rebind").exists())
if __name__ == "__main__":
unittest.main()
@@ -0,0 +1,303 @@
"""Real socket control/URB tests with disposable sysfs-shaped device objects."""
import importlib.util
import os
from pathlib import Path
import socket
import socketserver
import struct
import tempfile
import threading
import time
import unittest
from unittest.mock import patch
ROOT = Path(__file__).resolve().parents[3]
spec = importlib.util.spec_from_file_location(
"usbip_protocol", ROOT / "scripts/devices/usbip_protocol.py"
)
p = importlib.util.module_from_spec(spec)
spec.loader.exec_module(p)
def descriptor(
name="2-1", bus=2, number=3, vendor=0x1D6B, product=0x0104, interfaces=1
):
return p.DEVICE.pack(
b"/sys/devices/disposable",
name.encode(),
bus,
number,
3,
vendor,
product,
0x0100,
0,
0,
0,
1,
1,
interfaces,
)
def exact(connection, count):
result = bytearray()
while len(result) < count:
block = connection.recv(count - len(result))
if not block:
break
result.extend(block)
return bytes(result)
class GateTests(unittest.TestCase):
def setUp(self):
self.temporary = tempfile.TemporaryDirectory(prefix="usbip-gate-")
self.addCleanup(self.temporary.cleanup)
self.root = Path(self.temporary.name)
self.sysfs = self.root / "sysfs"
self.sysfs.mkdir()
self.device("original")
self.selected = {
"2-1": {
"id": "abcdef123456",
"vendor": "1d6b",
"product": "0104",
"serial": "selected-serial",
}
}
self.calls = []
self.reply = descriptor()
self.listed = [
(descriptor(), b"\x02\x02\x01\0"),
(descriptor("3-1", bus=3, number=4), b"\x02\x02\x01\0"),
]
self.hook = lambda: None
self.header_override = None
fixture = self
class Handler(socketserver.BaseRequestHandler):
def handle(self):
try:
header = exact(self.request, 8)
if len(header) != 8:
return
_, code, _ = p.HEADER.unpack(header)
request = header + (
exact(self.request, 32) if code == p.IMPORT else b""
)
fixture.calls.append(request)
fixture.hook()
self.request.sendall(
fixture.header_override
or p.HEADER.pack(p.VERSION, code & 0x7FFF, 0)
)
if code == p.DEVLIST:
self.request.sendall(struct.pack("!I", len(fixture.listed)))
for raw, interfaces in fixture.listed:
self.request.sendall(raw + interfaces)
return
self.request.sendall(fixture.reply)
while True:
block = self.request.recv(65536)
if not block:
self.request.shutdown(socket.SHUT_WR)
return
self.request.sendall(block)
except OSError:
return
class Backend(socketserver.ThreadingMixIn, socketserver.TCPServer):
daemon_threads = True
self.backend = Backend(("127.0.0.1", 0), Handler)
self.backend_thread = threading.Thread(
target=self.backend.serve_forever,
kwargs={"poll_interval": 0.05},
daemon=True,
)
self.backend_thread.start()
self.addCleanup(self.backend.server_close)
self.addCleanup(self.backend.shutdown)
# Production calls this as root; these protocol tests do not alter users.
with patch.object(p.os, "chown"):
self.gate = p.Gate(
self.root / "gate.sock",
os.getgid(),
lambda name: self.selected.get(name),
self.sysfs,
self.backend.server_address,
max_connections=2,
)
self.addCleanup(self.gate.terminate)
def device(self, directory, serial="selected-serial", number=3):
device = self.root / directory
device.mkdir()
for name, value in {
"idVendor": "1d6b",
"idProduct": "0104",
"serial": serial,
"busnum": "2",
"devnum": str(number),
"bDeviceClass": "00",
}.items():
(device / name).write_text(value)
interface = device / "2-1:1.0"
interface.mkdir()
(interface / "bInterfaceClass").write_text("02")
(device / "driver").symlink_to("/sys/bus/usb/drivers/usbip-host")
link = self.sysfs / "2-1"
link.unlink(missing_ok=True)
link.symlink_to(device, target_is_directory=True)
return device
def connect(self):
connection = socket.socket(socket.AF_UNIX)
connection.settimeout(3)
connection.connect(str(self.gate.path))
self.addCleanup(connection.close)
return connection
def request(self, name=b"2-1\0", code=p.IMPORT):
return p.HEADER.pack(p.VERSION, code, 0) + (
name.ljust(32, b"\0") if code == p.IMPORT else b""
)
def reject(self, request):
connection = self.connect()
connection.sendall(request)
result = exact(connection, 8)
self.assertTrue(not result or p.HEADER.unpack(result)[2] != 0, result)
self.assertEqual(connection.recv(1), b"")
return result
def test_fragmented_selected_import_and_large_binary_full_duplex(self):
connection = self.connect()
for value in self.request():
connection.sendall(bytes([value]))
self.assertEqual(
exact(connection, 320), p.HEADER.pack(p.VERSION, 3, 0) + self.reply
)
payload = bytes(range(256)) * 4096
writer = threading.Thread(target=connection.sendall, args=(payload,))
writer.start()
self.assertEqual(exact(connection, len(payload)), payload)
writer.join(3)
self.assertFalse(writer.is_alive())
connection.shutdown(socket.SHUT_WR)
self.assertEqual(connection.recv(1), b"")
def test_foreign_device_is_rejected_before_native_backend_import(self):
self.reject(self.request(b"3-1\0"))
self.assertEqual(self.calls, [])
def test_malformed_busids_never_reach_backend(self):
for value in (b"2-1\0x", b"../../etc\0", b"2-1\xff\0", b"x" * 32):
with self.subTest(value=value):
self.reject(self.request(value))
self.assertEqual(self.calls, [])
def test_unsupported_control_headers_never_reach_backend(self):
for header in (
p.HEADER.pack(0x0110, p.IMPORT, 0),
p.HEADER.pack(p.VERSION, 0x8001, 0),
p.HEADER.pack(p.VERSION, p.IMPORT, 1),
):
self.reject(header)
self.assertEqual(self.calls, [])
def test_devlist_filters_unselected_export_and_preserves_interface_records(self):
connection = self.connect()
connection.sendall(self.request(code=p.DEVLIST))
reply = exact(connection, 12)
self.assertEqual(reply, p.HEADER.pack(p.VERSION, 5, 0) + struct.pack("!I", 1))
self.assertEqual(exact(connection, 316), self.reply + b"\x02\x02\x01\0")
self.assertEqual(connection.recv(1), b"")
def test_changed_selection_during_import_receives_no_success_payload(self):
self.hook = self.selected.clear
self.reject(self.request())
self.assertEqual(len(self.calls), 1)
def test_mutated_callback_dictionary_cannot_rewrite_saved_selection(self):
self.hook = lambda: self.selected["2-1"].update(id="fedcba654321")
self.reject(self.request())
def test_replaced_sysfs_object_cannot_use_identical_reply_metadata(self):
self.hook = lambda: self.device("replacement")
self.reject(self.request())
def test_driver_change_during_import_is_rejected(self):
def replace():
driver = self.root / "original/driver"
driver.unlink()
driver.symlink_to("/sys/bus/usb/drivers/usb")
self.hook = replace
self.reject(self.request())
def test_descriptor_identity_and_devnum_must_match_pinned_object(self):
for reply in (
descriptor(number=4),
descriptor(vendor=0x05AC),
descriptor("3-1"),
descriptor(bus=3),
):
self.reply = reply
self.reject(self.request())
def test_composite_storage_or_hub_device_is_rejected_before_backend(self):
for name in ("bDeviceClass", "2-1:1.0/bInterfaceClass"):
path = self.root / "original" / name
old = path.read_text()
for value in ("08", "09"):
path.write_text(value)
self.reject(self.request())
path.write_text(old)
self.assertEqual(self.calls, [])
def test_unicode_serial_is_valid_without_changing_busid_encoding(self):
serial = "selected-ñ-设备"
(self.root / "original/serial").write_text(serial)
self.selected["2-1"]["serial"] = serial
connection = self.connect()
connection.sendall(self.request())
self.assertEqual(
exact(connection, 320), p.HEADER.pack(p.VERSION, 3, 0) + self.reply
)
def test_backend_response_version_opcode_and_status_are_validated(self):
for header in (
p.HEADER.pack(0x0110, 3, 0),
p.HEADER.pack(p.VERSION, 5, 0),
p.HEADER.pack(p.VERSION, 3, 0xFFFFFFFF),
):
self.header_override = header
self.reject(self.request())
def test_incomplete_header_times_out_but_accepted_idle_stream_does_not(self):
with patch.object(p, "CONTROL_SECONDS", 0.1):
partial = self.connect()
partial.sendall(b"\x01")
self.assertEqual(partial.recv(1), b"")
connection = self.connect()
connection.sendall(self.request())
self.assertEqual(len(exact(connection, 320)), 320)
time.sleep(0.2)
connection.sendall(b"idle-still-works")
self.assertEqual(exact(connection, 16), b"idle-still-works")
def test_stop_closes_idle_backend_and_client_and_removes_listener(self):
connection = self.connect()
connection.sendall(self.request())
self.assertEqual(len(exact(connection, 320)), 320)
self.gate.terminate()
self.assertEqual(connection.recv(1), b"")
self.assertFalse(self.gate.path.exists())
self.assertIsNotNone(self.gate.poll())
if __name__ == "__main__":
unittest.main()
@@ -24,7 +24,10 @@ class VmBackupJobsWiring(TestCase):
source = ROUTES.read_text()
self.assertNotIn('shell=True', source)
self.assertNotIn('os.system', source)
self.assertEqual(source.count('subprocess.run('), 1)
# pvesh, and the transient unit a backup started by hand runs in.
programs = re.findall(r'subprocess\.run\(\s*\[\s*"([a-z-]+)"', source)
self.assertEqual(len(programs), source.count('subprocess.run('))
self.assertEqual(set(programs), {'pvesh', 'systemd-run', 'systemctl'})
self.assertIn('subprocess.run(["pvesh", *args]', source)
def test_the_monitor_ships_and_registers_it(self):
+5
View File
@@ -25,6 +25,11 @@ on:
permissions:
contents: read
# A newer push to the same branch or pull request replaces the run in progress.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
check:
runs-on: ubuntu-latest
@@ -0,0 +1,79 @@
name: Native Monitor AppImage validation
on:
pull_request:
paths:
- '.github/workflows/test-appimage-native.yml'
- 'AppImage/scripts/build_appimage.sh'
- 'AppImage/scripts/appimage_arch.sh'
- 'AppImage/scripts/borg_native_arm.sh'
- '.github/scripts/smoke_native_apprun.sh'
- '.github/scripts/check_appimage_elf.py'
- 'AppImage/scripts/AppRun'
- 'tests/test_appimage_arch.py'
workflow_dispatch:
permissions:
contents: read
concurrency:
group: native-appimage-${{ github.ref }}
cancel-in-progress: true
jobs:
native-build:
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-22.04
arch: x86_64
- runner: ubuntu-22.04-arm
arch: aarch64
runs-on: ${{ matrix.runner }}
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Validate native architecture selection
run: |
test "$(uname -m)" = '${{ matrix.arch }}'
python -B -m unittest discover -s tests -p test_appimage_arch.py -v
- name: Refresh package indexes for bundled monitoring tools
# Third-party runner repositories occasionally fail; the build reports missing tools.
run: sudo apt-get update || true
- name: Build native AppImage without publishing it
run: bash AppImage/scripts/build_appimage.sh
- name: Reject foreign ELF payloads
run: python .github/scripts/check_appimage_elf.py /tmp/proxmenux_build/ProxMenux.AppDir '${{ matrix.arch }}'
- name: Extract native AppImage without FUSE
run: |
mkdir /tmp/proxmenux-native-extract
cd /tmp/proxmenux-native-extract
image=$(find "$GITHUB_WORKSPACE/AppImage/dist" -name '*.AppImage' -type f -print -quit)
test -n "$image"
chmod +x "$image"
"$image" --appimage-extract
test -f squashfs-root/usr/bin/flask_server.py
test -f squashfs-root/usr/bin/appimage_arch.sh
test -f squashfs-root/web/index.html
- name: Import bundled Python 3.11 native WebSocket runtime
env:
PYTHONPATH: /tmp/proxmenux-native-extract/squashfs-root/usr/lib/python3/vendor/cp311:/tmp/proxmenux-native-extract/squashfs-root/usr/lib/python3/dist-packages
run: |
python -c 'import gevent, greenlet, geventwebsocket, zope.interface; from PIL import Image; from gevent import pywsgi; print(gevent.__version__)'
bash .github/scripts/smoke_native_apprun.sh /tmp/proxmenux-native-extract/squashfs-root
- uses: actions/setup-python@v5
with:
python-version: '3.13'
- name: Import bundled Python 3.13 native WebSocket runtime
env:
PYTHONPATH: /tmp/proxmenux-native-extract/squashfs-root/usr/lib/python3/vendor/cp313:/tmp/proxmenux-native-extract/squashfs-root/usr/lib/python3/dist-packages
run: |
python -c 'import gevent, greenlet, geventwebsocket, zope.interface; from PIL import Image; from gevent import pywsgi; print(gevent.__version__)'
bash .github/scripts/smoke_native_apprun.sh /tmp/proxmenux-native-extract/squashfs-root
+85 -2
View File
@@ -7,7 +7,9 @@ on:
- 'AppImage/scripts/notification_manager.py'
- 'AppImage/scripts/notification_templates.py'
- 'AppImage/scripts/ai_context_enrichment.py'
- 'AppImage/scripts/ai_providers/base.py'
- 'AppImage/scripts/ai_providers/**'
- 'AppImage/config/verified_ai_models.json'
- 'AppImage/scripts/tests/test_groq_model_recommendations.py'
- 'AppImage/scripts/tests/test_backup_ai_diagnostics.py'
- 'AppImage/scripts/notification_channels.py'
- 'AppImage/components/apprise-service-help.tsx'
@@ -22,11 +24,19 @@ on:
- 'tests/test_vm_backup_jobs_api.py'
- 'tests/test_backup_storage_retention.cjs'
- 'tests/test_figurine_installation.py'
- 'scripts/gpu_tpu/nvidia_installer.sh'
- 'tests/test_nvidia*.py'
- 'AppImage/scripts/managed_installs.py'
- 'scripts/post_install/customizable_post_install.sh'
- 'AppImage/scripts/post_install_versions.py'
- 'AppImage/scripts/flask_proxmenux_routes.py'
- 'AppImage/scripts/guest_backup_archives.py'
- 'AppImage/scripts/flask_server.py'
- 'AppImage/scripts/ovs_topology.py'
- 'AppImage/scripts/tests/test_ovs_topology.py'
- 'AppImage/components/network-flow.tsx'
- 'AppImage/components/network-metrics.tsx'
- 'AppImage/tests/ovs-network-flow.cjs'
- 'AppImage/scripts/jwt_middleware.py'
- 'AppImage/scripts/build_appimage.sh'
- 'AppImage/components/guest-backup-list.tsx'
@@ -69,7 +79,9 @@ on:
- 'AppImage/scripts/notification_manager.py'
- 'AppImage/scripts/notification_templates.py'
- 'AppImage/scripts/ai_context_enrichment.py'
- 'AppImage/scripts/ai_providers/base.py'
- 'AppImage/scripts/ai_providers/**'
- 'AppImage/config/verified_ai_models.json'
- 'AppImage/scripts/tests/test_groq_model_recommendations.py'
- 'AppImage/scripts/tests/test_backup_ai_diagnostics.py'
- 'AppImage/scripts/notification_channels.py'
- 'AppImage/components/apprise-service-help.tsx'
@@ -86,6 +98,11 @@ on:
- 'AppImage/scripts/flask_proxmenux_routes.py'
- 'AppImage/scripts/guest_backup_archives.py'
- 'AppImage/scripts/flask_server.py'
- 'AppImage/scripts/ovs_topology.py'
- 'AppImage/scripts/tests/test_ovs_topology.py'
- 'AppImage/components/network-flow.tsx'
- 'AppImage/components/network-metrics.tsx'
- 'AppImage/tests/ovs-network-flow.cjs'
- 'AppImage/scripts/jwt_middleware.py'
- 'AppImage/components/guest-backup-list.tsx'
- 'AppImage/components/virtual-machines.tsx'
@@ -101,6 +118,9 @@ on:
- 'AppImage/scripts/tests/test_proxmox_node_name.py'
- 'AppImage/scripts/tests/test_pve_notifications_cfg_writes.py'
- 'tests/test_lvm_disk_read_policy.py'
- 'scripts/gpu_tpu/nvidia_installer.sh'
- 'tests/test_nvidia*.py'
- 'AppImage/scripts/managed_installs.py'
- 'oci/**'
- 'AppImage/scripts/oci_menu_bridge.py'
- 'AppImage/scripts/lxc_apps.py'
@@ -112,6 +132,11 @@ on:
permissions:
contents: read
# A newer push to the same branch or pull request replaces the run in progress.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
apprise-services:
runs-on: ubuntu-latest
@@ -164,6 +189,34 @@ jobs:
NODE_PATH: ${{ github.workspace }}/.github/ci/offline-node/node_modules
run: node tests/test_backup_storage_retention.cjs
nvidia-installer:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Check NVIDIA parser, cache and Secure Boot regressions
run: |
bash -n scripts/gpu_tpu/nvidia_installer.sh
python3 -B -m unittest discover -s tests -p 'test_nvidia*.py' -v
ai-model-availability:
runs-on: ubuntu-latest
timeout-minutes: 3
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Test model ordering and curated availability without network or credentials
run: python -B -m unittest discover -s AppImage/scripts/tests -p test_groq_model_recommendations.py -v
installer-and-release:
runs-on: ubuntu-latest
timeout-minutes: 10
@@ -382,3 +435,33 @@ jobs:
run: |
npm ci --prefix .github/ci/offline-node --legacy-peer-deps --ignore-scripts --no-audit --no-fund
NODE_PATH="$PWD/.github/ci/offline-node/node_modules" node AppImage/tests/pbs-navigation.cjs
native-image-import:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: Exercise private images with isolated mapped Linux readers
run: sudo /usr/bin/python3 -B -m unittest discover -s oci/tests -p test_native_import_access.py -v
network-topology:
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- uses: actions/setup-node@v6
with:
node-version: '22.14.0'
- name: Test read-only OVS discovery and mixed network API
run: python -B -m unittest discover -s AppImage/scripts/tests -p test_ovs_topology.py -v
- name: Test both Network Flow layouts
run: |
npm ci --prefix .github/ci/offline-node --ignore-scripts --no-audit --no-fund
NODE_PATH="$PWD/.github/ci/offline-node/node_modules" node AppImage/tests/ovs-network-flow.cjs
+5
View File
@@ -51,6 +51,11 @@ on:
permissions:
contents: read
# A newer push to the same branch or pull request replaces the run in progress.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
# Preserve this check ID for existing branch protection rules. This suite
# includes menu, download and scheduler regressions as well as i18n tests.
@@ -57,6 +57,11 @@ on:
permissions:
contents: read
# A newer push to the same branch or pull request replaces the run in progress.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
offline-python:
runs-on: ubuntu-latest
+50
View File
@@ -0,0 +1,50 @@
name: USB/IP over SSH tests
on:
pull_request:
paths:
- 'scripts/devices/**'
- 'scripts/menus/hw_grafics_menu.sh'
- 'scripts/menus/main_menu.sh'
- 'scripts/menus/search_index.json'
- '.github/scripts/tests/test_usbip*.py'
- '.github/scripts/check_usbip_transport.py'
- '.github/workflows/test-usbip.yml'
- 'docs/usbip.md'
push:
branches: [main, develop]
paths:
- 'scripts/devices/**'
- '.github/scripts/tests/test_usbip*.py'
- '.github/scripts/check_usbip_transport.py'
- '.github/workflows/test-usbip.yml'
workflow_dispatch:
permissions:
contents: read
jobs:
usbip:
runs-on: ubuntu-latest
timeout-minutes: 8
strategy:
fail-fast: false
matrix:
python: ['3.11', '3.13']
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: Device ownership, reconnect and systemd validation
env:
PYTHONDONTWRITEBYTECODE: '1'
run: python3 -B -m unittest discover -s .github/scripts/tests -p 'test_usbip*.py' -v
- name: Install fixture-only transport dependencies
run: |
sudo apt-get update -o APT::Update::Error-Mode=any
sudo apt-get install -y socat openssh-client openssh-server iproute2 util-linux
- name: Real SSH and private namespace transport, without USB hardware
run: sudo "$(command -v python3)" -B .github/scripts/check_usbip_transport.py
+1
View File
@@ -54,6 +54,7 @@ Thumbs.db
# Cache
.cache
/oci/.catalog-cache/
/web/.cache
# IDE/editor files
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
5e8afe3b297f21b8646e58eed720ba2eeb5f16681a3d2eb89bcac600065167c9 ProxMenux-1.2.7.AppImage
69ed639710aba5804e3b8f33383357f3bcc981b94a5e9b272d214f31e2e87563 ProxMenux-1.2.8.AppImage
+20 -1
View File
@@ -397,19 +397,38 @@ const SELFHST_THEME_LOGOS: Record<string, { lightTheme: string; darkTheme: strin
lightTheme: `${SELFHST_WEBP_BASE}/frigate-dark.webp`,
darkTheme: `${SELFHST_WEBP_BASE}/frigate-light.webp`,
},
"hermes-agent": {
lightTheme: `${SELFHST_WEBP_BASE}/hermes-agent.webp`,
darkTheme: `${SELFHST_WEBP_BASE}/hermes-agent-light.webp`,
},
"llama-cpp": {
lightTheme: `${SELFHST_WEBP_BASE}/llama-cpp.webp`,
darkTheme: `${SELFHST_WEBP_BASE}/llama-cpp-light.webp`,
},
portainer: {
lightTheme: `${SELFHST_WEBP_BASE}/portainer-dark.webp`,
darkTheme: `${SELFHST_WEBP_BASE}/portainer-light.webp`,
},
tailscale: {
lightTheme: `${SELFHST_WEBP_BASE}/tailscale.webp`,
darkTheme: `${SELFHST_WEBP_BASE}/tailscale-light.webp`,
},
vaultwarden: {
lightTheme: `${SELFHST_WEBP_BASE}/vaultwarden.webp`,
darkTheme: `${SELFHST_WEBP_BASE}/vaultwarden-light.webp`,
},
}
// Earlier catalog icons that now have a themed selfhst equivalent.
const THEMED_LOGO_ALIASES: Record<string, string> = {
"https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@main/webp/hermes.webp": "hermes-agent",
}
function selfhstThemeLogos(src: string) {
const alias = THEMED_LOGO_ALIASES[src.toLowerCase()]
if (alias) return SELFHST_THEME_LOGOS[alias]
if (!src.toLowerCase().includes("cdn.jsdelivr.net/gh/selfhst/icons")) return null
const match = src.toLowerCase().match(/\/(frigate|portainer|vaultwarden)(?:-(?:dark|light))?\.webp(?:[?#].*)?$/)
const match = src.toLowerCase().match(/\/(frigate|hermes-agent|llama-cpp|portainer|tailscale|vaultwarden)(?:-(?:dark|light))?\.webp(?:[?#].*)?$/)
return match ? SELFHST_THEME_LOGOS[match[1]] : null
}
+4 -1
View File
@@ -62,7 +62,7 @@ type Bridge = {
type Guest = {
id: string
label: string
kind: "lxc" | "vm" | "host"
kind: "lxc" | "vm" | "host" | "interface"
bridge: string
rx: number
tx: number
@@ -87,6 +87,8 @@ const ICONS: Record<string, string> = {
vm: `<rect width="20" height="8" x="2" y="2" rx="2"/><rect width="20" height="8" x="2" y="14" rx="2"/><path d="M6 6h.01"/><path d="M6 18h.01"/>`,
}
ICONS.interface = ICONS.bridge
const COLORS = {
host: "var(--amber-500, #f59e0b)",
lxc: "var(--cyan-500, #06b6d4)",
@@ -97,6 +99,7 @@ const COLORS = {
// just another NIC.
bond: "var(--orange-500, #f97316)",
bridge: "var(--cyan-500, #06b6d4)",
interface: "var(--cyan-500, #06b6d4)",
gray: "#525252",
}
+12 -4
View File
@@ -101,6 +101,9 @@ interface NetworkInterface {
// Master device resolved from /sys/class/net/<iface>/master — the
// bridge for a guest tap, the bond for a slave NIC.
bridge_owner?: string
network_backend?: "ovs"
ovs_tag?: number | null
ovs_trunks?: number[]
bridge_members?: string[]
bridge_physical_interface?: string
bridge_bond_slaves?: string[]
@@ -568,6 +571,7 @@ export function NetworkMetrics() {
...(networkData.bond_interfaces || []),
...(networkData.bridge_interfaces || []),
...(networkData.vm_lxc_interfaces || []),
...(networkData.interfaces || []).filter((i) => i.network_backend === "ovs" && i.type === "vlan"),
]
const vmLxcInterfaces = (networkData.vm_lxc_interfaces || []).sort((a, b) => {
@@ -867,6 +871,7 @@ export function NetworkMetrics() {
...(networkData.bond_interfaces || []),
...(networkData.bridge_interfaces || []),
...(networkData.vm_lxc_interfaces || []),
...(networkData.interfaces || []).filter((i) => i.network_backend === "ovs" && i.type === "vlan"),
]
const flowData: NetworkFlowData = {
nics: (networkData.physical_interfaces || []).map((p) => ({
@@ -916,7 +921,9 @@ export function NetworkMetrics() {
tx: runningGuests.reduce((a, v) => a + toMBps(v.tx_Bps), 0),
}
})(),
...(networkData.vm_lxc_interfaces || []).map((v) => {
...[...(networkData.vm_lxc_interfaces || []),
...(networkData.interfaces || []).filter((i) => i.network_backend === "ovs" && i.type === "vlan"),
].map((v) => {
// Authoritative bridge from the kernel (read by the
// backend from /sys/class/net/<iface>/master). Fallback
// to bridge_members scan, then first bridge as last
@@ -929,8 +936,8 @@ export function NetworkMetrics() {
(networkData.bridge_interfaces?.[0]?.name || "")
return {
id: v.name,
label: v.vm_name || v.name,
kind: (v.vm_type === "vm" ? "vm" : "lxc") as "vm" | "lxc",
label: v.vm_name || (v.ovs_tag != null ? `${v.name} · VLAN ${v.ovs_tag}` : v.name),
kind: v.type === "vlan" ? "interface" as const : (v.vm_type === "vm" ? "vm" as const : "lxc" as const),
bridge: ownerName,
rx: toMBps(v.rx_Bps),
tx: toMBps(v.tx_Bps),
@@ -1213,6 +1220,7 @@ export function NetworkMetrics() {
...(modalNetworkData.bond_interfaces || []),
...(modalNetworkData.bridge_interfaces || []),
...(modalNetworkData.vm_lxc_interfaces || []),
...(modalNetworkData.interfaces || []).filter((i) => i.network_backend === "ovs" && i.type === "vlan"),
].find((iface) => iface.name === selectedInterface.name)
: selectedInterface
@@ -1298,7 +1306,7 @@ export function NetworkMetrics() {
</div>
<div>
<div className="text-sm text-muted-foreground">MTU</div>
<div className="font-medium">{displayInterface.mtu}</div>
<div className="font-medium">{displayInterface.mtu || t("common.notAvailable")}</div>
</div>
{displayInterface.mac_address && (
<div className="col-span-2">
+13 -20
View File
@@ -804,7 +804,7 @@ export function StorageOverview({ disksOnly = false }: { disksOnly?: boolean } =
</div>
)}
{/* Reallocated only meaningful on rotating disks. */}
{disk.reallocated_sectors !== undefined && (disk.rotation_rate ?? 0) > 0 && (
{disk.reallocated_sectors !== undefined && resolveDiskType(disk.name, disk.rotation_rate) === "HDD" && (
<div className="flex items-baseline justify-between gap-3">
<span className="text-[11px] uppercase tracking-wider text-muted-foreground">
{t("storage.reallocatedShort")}
@@ -860,12 +860,7 @@ export function StorageOverview({ disksOnly = false }: { disksOnly?: boolean } =
// Resolve disk class → threshold pair from the user-configurable
// backend (single source of truth). The semantics: temp BELOW warn
// is green, between warn and hot is amber, hot or above is red.
let cls: keyof DiskTempMap = "HDD"
if (diskName?.startsWith("nvme")) {
cls = "NVMe"
} else if (!rotationRate || rotationRate === 0) {
cls = "SSD"
}
const cls: keyof DiskTempMap = resolveDiskType(diskName ?? "", rotationRate)
const t = dtThresholds[cls]
if (temp >= t.hot) return "text-red-500"
if (temp >= t.warn) return "text-yellow-500"
@@ -896,9 +891,9 @@ export function StorageOverview({ disksOnly = false }: { disksOnly?: boolean } =
return t("storage.duration.daysShort", { days: totalDays })
}
const formatRotationRate = (rpm: number | undefined) => {
if (!rpm || rpm === 0) return "SSD"
return `${rpm.toLocaleString()} RPM`
const formatRotationRate = (diskName: string, rpm: number | undefined) => {
if (getDiskType(diskName, rpm) !== "HDD") return "SSD"
return rpm && rpm > 0 ? `${rpm.toLocaleString()} RPM` : t("common.notAvailable")
}
// Thin wrapper over the shared classifier so the rest of the file
@@ -2626,7 +2621,7 @@ export function StorageOverview({ disksOnly = false }: { disksOnly?: boolean } =
</div>
<div>
<p className="text-sm text-muted-foreground">{t("storage.rotationRate")}</p>
<p className="font-medium">{formatRotationRate(selectedDisk.rotation_rate)}</p>
<p className="font-medium">{formatRotationRate(selectedDisk.name, selectedDisk.rotation_rate)}</p>
</div>
<div>
<p className="text-sm text-muted-foreground">{t("storage.powerCycles")}</p>
@@ -2871,14 +2866,12 @@ function openSmartReport(disk: DiskInfo, testStatus: SmartTestStatus, smartAttri
// Determine disk type (SAS detected via backend flag or connection_type)
const isSasDisk = sd?.is_sas === true || disk.connection_type === 'sas'
let diskType = "HDD"
if (disk.name.startsWith("nvme")) {
diskType = "NVMe"
} else if (isSasDisk) {
let diskType: string = resolveDiskType(disk.name, disk.rotation_rate)
if (diskType !== "NVMe" && isSasDisk) {
diskType = "SAS"
} else if (!disk.rotation_rate || disk.rotation_rate === 0) {
diskType = "SSD"
}
const rpm = disk.rotation_rate && disk.rotation_rate > 0 ? disk.rotation_rate : 0
const known = (value?: string) => (value && value !== "Unknown" ? value : undefined)
// Health status styling
const healthStatus = String(testStatus.smart_status || (testStatus.smart_data?.smart_status) || 'unknown')
@@ -3824,11 +3817,11 @@ function pmxPrint(){
<div class="grid-4">
<div class="card">
<div class="card-label">${tSmart("labels.model")}</div>
<div class="card-value" style="font-size:11px;">${disk.model || sd?.model || t("app.unknown")}</div>
<div class="card-value" style="font-size:11px;">${known(disk.model) || known(sd?.model) || t("app.unknown")}</div>
</div>
<div class="card">
<div class="card-label">${tSmart("labels.serial")}</div>
<div class="card-value" style="font-size:11px;font-family:monospace;">${disk.serial || sd?.serial || t("app.unknown")}</div>
<div class="card-value" style="font-size:11px;font-family:monospace;">${known(disk.serial) || known(sd?.serial) || t("app.unknown")}</div>
</div>
<div class="card">
<div class="card-label">${tSmart("labels.capacity")}</div>
@@ -3836,7 +3829,7 @@ function pmxPrint(){
</div>
<div class="card">
<div class="card-label">${tSmart("labels.type")}</div>
<div class="card-value" style="font-size:11px;">${diskType === 'SAS' ? (disk.rotation_rate ? `SAS ${disk.rotation_rate} RPM` : 'SAS SSD') : diskType === 'HDD' && disk.rotation_rate ? `HDD ${disk.rotation_rate} RPM` : diskType}</div>
<div class="card-value" style="font-size:11px;">${diskType === 'SAS' ? (rpm ? `SAS ${rpm} RPM` : disk.rotation_rate === -1 ? 'SAS HDD' : 'SAS SSD') : diskType === 'HDD' && rpm ? `HDD ${rpm} RPM` : diskType}</div>
</div>
</div>
${(modelFamily || formFactor || sataVersion || ifaceSpeed) ? `
+2 -4
View File
@@ -110,12 +110,10 @@
"openai/gpt-oss-120b",
"meta-llama/llama-3.1-8b-instruct",
"nvidia/nemotron-3-nano-omni-30b-a3b-reasoning:free",
"nvidia/nemotron-3-super-120b-a12b:free",
"google/gemma-4-26b-a4b-it:free",
"poolside/laguna-s-2.1:free"
"google/gemma-4-26b-a4b-it:free"
],
"recommended": "meta-llama/llama-3.3-70b-instruct",
"_note": "Curated manually from the 249+ models OpenRouter serves — the auto-verifier passes ~200 today but only a subset are practical for notification translation. Includes the 11 previously-curated paid models plus 22 new mainstream additions (gpt-5.1, claude-opus-4.8, sonnet-5, grok-4.3/4.20, kimi-k2, deepseek-v3.2, nova, cohere-a, sonar, ...) and 6 `:free` variants re-added manually — the free tier is intentionally supported per user request even though today's rate limits blocked some of them from passing the test. Reviewed 2026-10-26: three `:free` variants no longer served by OpenRouter were dropped."
"_note": "Curated manually from the 249+ models OpenRouter serves — the auto-verifier passes ~200 today but only a subset are practical for notification translation. Includes the 11 previously-curated paid models plus 22 new mainstream additions (gpt-5.1, claude-opus-4.8, sonnet-5, grok-4.3/4.20, kimi-k2, deepseek-v3.2, nova, cohere-a, sonar, ...) and 6 `:free` variants re-added manually — the free tier is intentionally supported per user request even though today's rate limits blocked some of them from passing the test. Reviewed 2026-10-26: three `:free` variants no longer served by OpenRouter were dropped. Availability reviewed 2026-11-04 against the public models endpoint: expired poolside/laguna-s-2.1:free and unlisted nvidia/nemotron-3-super-120b-a12b:free removed. This availability check is not a new inference verification; no untested models were added."
},
"ollama": {
"_note": "Ollama models are local, we don't filter them. User manages their own models.",
+22 -22
View File
@@ -6082,11 +6082,11 @@
},
"nextStep": {
"noJobs": "Vytvor zálohovaciu úlohu na tomto uzle a vyber VM alebo kontajnery s údajmi, ktoré by sa ťažko obnovovali ručne. Vypnutá úloha nezahŕňa do zálohovania žiadne VM ani kontajnery.",
"uncovered": "Rozhodnite sa pre každého z týchto hostí, či má niečo, čo stojí za to udržať. Pridajte tie, ktoré robia prácu; pre tie, ktoré nie, deklarujte, že v politike, takže sa prestanú počítať tu.",
"excludedData": "Otvorte zoznam vylúčených pracovných miest a potvrďte, že vynecháva údaje, ktoré si môžete dovoliť stratiť. Vylúčenie pridané, aby sa práca rýchlejšie chráni nič, čo preskočí.",
"uncoveredExpected": "Politika vyhlasuje, že títo hostia vyžadujú zálohu a žiadna povolená práca si ich vyberie. Buď ich pridajte do práce, alebo zmeňte, čo politika vyhlasuje, takže obaja súhlasia."
"uncovered": "Pre každého z týchto hostí rozhodnite, či obsahuje niečo, čo stojí za to ponechať. Tých, ktorí to obsahujú, pridajte do úlohy; v prípade tých, ktorí to neobsahujú, uveďte to v pravidle, aby sa tu už nezapočítavali.",
"excludedData": "Otvorte zoznam vylúčených položiek každej úlohy a overte si, či sa medzi vylúčenými údajmi nachádzajú len tie, ktorých stratu si môžete dovoliť. Vylúčenie pridané s cieľom urýchliť úlohu nijako nechráni údaje, ktoré sa tým vynechajú.",
"uncoveredExpected": "V rámci tejto politiky sú títo hostia označení ako vyžadujúci zálohovanie, avšak žiadna zapnutá úloha ich nevyberá. Pridajte ich do úlohy alebo upravte nastavenia politiky tak, aby sa tieto dve veci zhodovali."
},
"explanation": "Záloha chráni len to, čo si práca skutočne vyberie. Táto kontrola spáruje hostí na tomto uzle s pracovnými miestami, ktoré tu bežia, takže hosť, ktorý sa nikto neobjaví ako taký, namiesto toho, aby bol považovaný za pokrytý niečím iným."
"explanation": "Záloha chráni len to, čo úloha skutočne vyberie. Táto kontrola spáruje hostí na tomto uzle s úlohami, ktoré sa tu spúšťajú, takže hosť, ktorého nikto nezálohuje, sa zobrazí ako taký, namiesto toho, aby sa predpokladalo, že je zahrnutý v niečom inom."
},
"last_backup_age": {
"title": "Vek uložených záloh",
@@ -6099,11 +6099,11 @@
"evaluationFailed": "Kontrolu sa nepodarilo vyhodnotiť"
},
"nextStep": {
"stale": "Zisti, prečo úloha prestala vytvárať zálohy týchto VM alebo kontajnerov: môže byť vypnutá, nemusí sa spúšťať podľa plánu alebo môže končiť chybou. V prehľade výsledkov skontroluj jej posledné spustenie.",
"noBackups": "Žiadna uložená kópia sa nezhoduje s hosťom v tomto uzle. Ak práce napísať do cieľa, tento uzol nemôže čítať, to sa očakáva, inak sú produkovať nič.",
"attention": "Prezrite si uvedených hostí. Každá z nich nemá žiadnu kópiu alebo je staršia ako vek, ktorý sa používa."
"stale": "Zistite, prečo táto úloha prestala vytvárať kópie pre týchto hostí: mohla byť deaktivovaná, jej plán sa možno nikdy nespustil alebo jej behy zlyhávajú. Kontrola výsledkov behov uvádza, ako sa každá úloha naposledy ukončila.",
"noBackups": "Žiadna uložená kópia nezodpovedá žiadnemu hosťovi na tomto uzle. Ak úlohy zapisujú do cieľového umiestnenia, z ktorého tento uzol nemôže čítať, je to očakávané; inak by totiž nevytvárali žiadne výstupy.",
"attention": "Prezrite si zoznam hostí. Každý z nich buď nemá žiadnu aktuálnu kópiu, alebo má kópiu staršiu, než je požadovaný vek."
},
"explanation": "Práca, ktorá existuje, nie je to isté ako kópia, ktorá existuje. Tento šek číta najnovšie uložené kópie každého hosťa a ako dávno to bolo napísané, čo je, ako ďaleko by ste mali ísť, ak ste museli obnoviť dnes."
"explanation": "Existencia úlohy nie je to isté ako existencia jej kópie. Táto kontrola zisťuje najnovšiu uloženú kópiu každého hosťa a to, kedy bola napísaná – teda ako ďaleko by ste museli siahnuť, keby ste dnes museli vykonať obnovenie."
},
"retention_defined": {
"title": "Retencia záloh",
@@ -6116,11 +6116,11 @@
"evaluationFailed": "Kontrolu sa nepodarilo vyhodnotiť"
},
"nextStep": {
"missing": "Nastavte si držanie na týchto pracovných miestach, alebo na sklade, na ktorý píšu. Proxmox berie nastavenie úlohy ako prvý, potom úložisko je, potom uzol predvolený.",
"notDeclared": "Tieto práce uchovávajú všetky kópie, ktoré robia. To je zámerná voľba pre niektoré destinácie, ale potvrďte, že cieľ má priestor na rast.",
"onServer": "Tieto úlohy ukladajú zálohy na zálohovací server. Ten odstraňuje staré zálohy podľa vlastných pravidiel. Z tohto uzla sa nedá zistiť, ktoré zálohy uchováva; skontroluj ich priamo na zálohovacom serveri."
"missing": "Nastavte dobu uchovávania pre tieto úlohy alebo pre úložisko, do ktorého sa zapisujú. Proxmox uprednostňuje najskôr nastavenie úlohy, potom nastavenie úložiska a nakoniec predvolené nastavenie uzla.",
"notDeclared": "Tieto úlohy uchovávajú každú vytvorenú kópiu. V prípade niektorých cieľových umiestnení ide o zámernú voľbu, avšak je potrebné overiť, či má cieľové umiestnenie dostatok miesta na ďalší rast.",
"onServer": "Tieto úlohy zapisujú údaje na záložný server, ktorý ich odstraňuje podľa vlastných pravidiel. Pravidlá uchovávania sa z tohto uzla nedajú zistiť; skontroluj ich priamo na zálohovacom serveri."
},
"explanation": "O tom, koľko výtlačkov sa uchováva a ako dlho sa uchováva. Bez nej sa cieľ naplní, kým neprestane prijímať nové kópie, a záloha, ktorú nemožno napísať, je tá, o ktorej sa dozviete v deň, keď ju potrebujete."
"explanation": "Doba uchovávania určuje, koľko kópií sa uchováva a ako dlho. Bez nej sa cieľové úložisko zaplní do tej miery, že prestane prijímať nové kópie, a o zálohe, ktorú nie je možné zapísať, sa dozviete práve v deň, keď ju budete potrebovať."
},
"verification_state": {
"title": "Overenie záloh",
@@ -6132,10 +6132,10 @@
"evaluationFailed": "Stav overenia sa nepodarilo prečítať"
},
"nextStep": {
"failed": "Kópiu, ktorá nie je overená, nemožno použiť. Skontrolujte, či skoršia kópia rovnakého hosťa overené, a pozrite sa na skladovanie neúspešné kópie naživo.",
"notVerified": "Nič nepotvrdilo, že tieto kópie sa dajú prečítať späť. Záložný server môže overiť svoj vlastný rozvrh, oddelene od úlohy, ktorá ich napísala."
"failed": "Na kópiu, ktorá neprešla overením, sa nedá spoľahnúť. Skontrolujte, či bola overená skoršia kópia toho istého hosťa, a pozrite sa na úložisko, na ktorom sa nachádzajú neúspešné kópie.",
"notVerified": "Nič nepotvrdilo, že tieto kópie je možné opäť prečítať. Záložný server môže overovať podľa vlastného harmonogramu, nezávisle od úlohy, ktorá ich vytvorila."
},
"explanation": "Overenie číta uložené kópie späť a potvrdzuje, že je neporušený. Je to rozdiel medzi kópiou, ktorá existuje, a kópiou, ktorá môže byť prečítaná, rozdiel, ktorý záleží len na dni, kedy ho potrebujete."
"explanation": "Pri overovaní sa načíta uložená kópia a potvrdí sa, že je neporušená. Ide o rozdiel medzi kópiou, ktorá existuje, a kópiou, ktorú je možné prečítať – toto rozlíšenie má význam až v deň, keď ju budete potrebovať."
},
"job_results": {
"title": "Výsledky zálohovacích behov",
@@ -6147,10 +6147,10 @@
"recovered": "{count} z {total} VM a LXC zlyhalo pri skoršom spustení a odvtedy uspelo"
},
"nextStep": {
"recovered": "Títo hostia zlyhali a odvtedy sa im to podarilo. Predchádzajúca chyba stále stojí za čítanie: zlyhanie, ktoré vyrieši sám často vracia.",
"recovered": "Týmto hosťom sa predchádzajúci pokus nepodaril, ale neskôr uspeli. Stojí za to si prečítať popis tej predchádzajúcej chyby: chyba, ktorá sa sama vyriešila, sa často vráti.",
"someFailed": "Pri týchto behoch si pozrite chybu v zázname úloh. Beh, ktorý skončil chybou, považujte za neúspešný. Skôr než sa na zálohu spoľahnete, overte dostupnú kópiu pre príslušné VM a LXC."
},
"explanation": "Ako sa posledná práca skončila, ako to nahral tento uzol. Práca môže byť nakonfigurovaná dokonale a stále zlyhá každú noc, a to je miesto, kde to ukazuje."
"explanation": "Ako skončilo posledné spustenie každej úlohy, tak ako to zaznamenal tento uzol. Úloha môže byť dokonale nakonfigurovaná a napriek tomu zlyháva každú noc, a práve tu sa to prejaví."
},
"host_recovery": {
"title": "Obnova servera",
@@ -6162,11 +6162,11 @@
"scheduledOnly": "Zálohy nastavení servera sú naplánované cez {count} časovačov, lokálne však nie je uložený žiadny archív"
},
"nextStep": {
"attention": "Prehľadajte uvedené záznamy konfigurácie hostiteľa. Každý má niečo, čo stojí za to pozrieť sa na: beh, ktorý zlyhal, cieľ, ktorý je preč, alebo výtlačok starší ako vek v používaní.",
"scheduledOnly": "Časovač bude produkovať zálohovanie konfigurácie hostiteľa, ale žiadny ešte nie je uložený. Kým prvý beží, uzol vlastné nastavenie nie je chránené.",
"attention": "Prezrite si uvedené konfiguračné záznamy hostiteľov. V každom z nich sa nachádza niečo, čo stojí za pozornosť: neúspešné spustenie, cieľ, ktorý už neexistuje, alebo kópia staršia, než je povolená doba používania.",
"scheduledOnly": "Časovač bude vytvárať zálohy konfigurácie hostiteľa, zatiaľ však nie je uložená žiadna. Pokiaľ sa nespustí prvá záloha, vlastná konfigurácia uzla nie je chránená.",
"noHostBackup": "ProxMenux tu nemá zaznamenanú uloženú zálohu nastavení servera. Ak neexistuje iná záloha, ktorú tento uzol nevidí, pri obnove servera by bolo potrebné úložiská, sieť a používateľské účty nastaviť ručne podľa dostupných poznámok."
},
"explanation": "Zálohovanie hostí neobnoví uzol. Táto kontrola sa pozerá na to, či uzol vlastné konfigurácia"
"explanation": "Zálohovanie hostí nevedie k obnoveniu uzla. Táto kontrola overuje, či je vlastná konfigurácia uzla – jeho definície úložísk, sieťové nastavenia a používatelia – uložená niekde, od čoho závisí samotná obnova hostiteľa."
}
},
"system": {
@@ -6977,8 +6977,8 @@
"withoutLynis": "Spustiť bez Lynisu",
"cancel": "Zrušiť"
},
"noActionNeeded": "Nemám čo robiť. Tento šek našiel to, čo očakáva.",
"couldNotEvaluate": "Tento šek nemohol byť vyhodnotený, takže nič nehlási. Dôkazy zaznamenávajú, čo nebolo možné prečítať."
"noActionNeeded": "Nie je čo robiť. Táto kontrola potvrdila to, čo sa očakávalo.",
"couldNotEvaluate": "Túto kontrolu nebolo možné vyhodnotiť, preto sa v správe neuvádza žiadny výsledok. V zázname je uvedené, čo sa nepodarilo prečítať."
},
"runtime": {
"notifications": {
+4 -1
View File
@@ -6,8 +6,11 @@
# Get the directory where this AppImage is mounted
APPDIR="$(dirname "$(readlink -f "${0}")")"
source "${APPDIR}/usr/bin/appimage_arch.sh" || exit 1
pmx_appimage_arch "$(uname -m)" || exit 1
export PATH="${APPDIR}/usr/bin:${PATH}"
export LD_LIBRARY_PATH="${APPDIR}/usr/lib/x86_64-linux-gnu:${APPDIR}/usr/lib:${APPDIR}/lib/x86_64-linux-gnu:${APPDIR}/lib:${LD_LIBRARY_PATH}"
export LD_LIBRARY_PATH="${APPDIR}/usr/lib/${PMX_APPIMAGE_TRIPLET}:${APPDIR}/usr/lib:${APPDIR}/lib/${PMX_APPIMAGE_TRIPLET}:${APPDIR}/lib:${LD_LIBRARY_PATH}"
# Select the native dependency tree matching the host interpreter. PVE 8
# uses CPython 3.11 and PVE 9 uses CPython 3.13; both runtimes are bundled in
+5 -11
View File
@@ -165,22 +165,16 @@ def get_event_frequency(error_id: str = None, error_key: str = None,
try:
cursor = conn.cursor()
# Try to find the error
if error_id:
# Try to find the error. The errors table keys a row by error_key.
if error_id or error_key:
cursor.execute('''
SELECT first_seen, last_seen, occurrences, category
FROM errors WHERE error_key = ? OR error_id = ?
ORDER BY last_seen DESC LIMIT 1
''', (error_id, error_id))
elif error_key:
cursor.execute('''
SELECT first_seen, last_seen, occurrences, category
SELECT first_seen, last_seen, occurrence_count, category
FROM errors WHERE error_key = ?
ORDER BY last_seen DESC LIMIT 1
''', (error_key,))
''', (error_id or error_key,))
elif category:
cursor.execute('''
SELECT first_seen, last_seen, occurrences, category
SELECT first_seen, last_seen, occurrence_count, category
FROM errors WHERE category = ? AND resolved_at IS NULL
ORDER BY last_seen DESC LIMIT 1
''', (category,))
@@ -21,8 +21,13 @@ class GroqProvider(AIProvider):
# Exclude non-chat models
EXCLUDED_PATTERNS = ['whisper', 'tts', 'guard', 'tool-use']
# Recommended models (in priority order - versatile/large models first)
RECOMMENDED_PREFIXES = ['llama-3.3', 'llama-3.1-70b', 'llama-3.1-8b', 'mixtral', 'gemma']
# Prefer the verified default and current GPT-OSS models. Llama remains
# available for accounts with access; retired Mixtral/Gemma families have
# no recommendation priority. Sorting never adds IDs to the API response.
RECOMMENDED_PREFIXES = [
'openai/gpt-oss-20b', 'openai/gpt-oss-120b', 'qwen/qwen3.8-27b',
'llama-3.3', 'llama-3.1-8b',
]
def list_models(self) -> List[str]:
"""List available Groq models for chat completions.
@@ -24,6 +24,9 @@ class OpenAIProvider(AIProvider):
"""
NAME = "openai"
# The Monitor gives any rewrite 25 s; a local model behind an
# OpenAI-compatible endpoint may need all of it.
REQUEST_TIMEOUT_SECONDS = 25
REQUIRES_API_KEY = True
DEFAULT_API_URL = "https://api.openai.com/v1/chat/completions"
DEFAULT_MODELS_URL = "https://api.openai.com/v1/models"
@@ -226,7 +229,7 @@ class OpenAIProvider(AIProvider):
}
api_url = self._get_api_url()
result = self._make_request(api_url, payload, headers)
result = self._make_request(api_url, payload, headers, timeout=self.REQUEST_TIMEOUT_SECONDS)
try:
return result['choices'][0]['message']['content'].strip()
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
# Shared native build/runtime architecture names. No emulated cross-builds.
pmx_appimage_arch() {
case "$1" in
x86_64|amd64)
PMX_APPIMAGE_ARCH=x86_64
PMX_APPIMAGE_TRIPLET=x86_64-linux-gnu
PMX_APPIMAGE_SUFFIX=""
;;
aarch64|arm64)
PMX_APPIMAGE_ARCH=aarch64
PMX_APPIMAGE_TRIPLET=aarch64-linux-gnu
PMX_APPIMAGE_SUFFIX=-aarch64
;;
*)
echo "Unsupported Monitor AppImage architecture: $1" >&2
return 1
;;
esac
}
+7 -1
View File
@@ -27,6 +27,8 @@ import sys
import time
from typing import Any, Optional
import disk_identity
SCHEMA_VERSION = 2
# Disk entries in a guest configuration: rootfs and mpN for containers,
@@ -630,12 +632,16 @@ def _physical_disks(ctx) -> list[dict[str, Any]]:
size = row.get("SIZE", "")
name = row.get("NAME", "")
health = smart.get(name) or {}
# The Monitor's rotation when it read the disk, so both agree.
rate = health.get("rotation_rate")
if not isinstance(rate, int):
rate = -1 if row.get("ROTA") == "1" else 0
disks.append({
"name": name,
"model": (row.get("MODEL") or "").strip(),
"serial": (row.get("SERIAL") or "").strip(),
"size_bytes": int(size) if size.isdigit() else None,
"rotational": row.get("ROTA") == "1",
"rotational": disk_identity.media_type(name, rate) == "HDD",
"bus": (row.get("TRAN") or "").strip(),
"health": health.get("smart_status"),
"temperature": health.get("temperature"),
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh
# Borg 1.2.8 has no official ARM64 standalone release. Never ship or run
# its AMD64 executable on ARM; use the host's native distro package instead.
if [ -x /usr/bin/borg ]; then
# The distro package must use its own Python modules and shared libraries.
unset PYTHONPATH PYTHONHOME LD_LIBRARY_PATH
exec /usr/bin/borg "$@"
fi
echo 'Native Borg is unavailable. Install the native borgbackup package on this host to use Borg backups.' >&2
exit 127
+39 -16
View File
@@ -8,6 +8,8 @@ set -e
WORK_DIR="/tmp/proxmenux_build"
APP_DIR="$WORK_DIR/ProxMenux.AppDir"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/appimage_arch.sh"
pmx_appimage_arch "$(uname -m)" || exit 1
DIST_DIR="$SCRIPT_DIR/../dist"
APPIMAGE_ROOT="$SCRIPT_DIR/.."
@@ -24,7 +26,7 @@ ZOPE_EVENT_VERSION="6.2"
GEVENT_WEBSOCKET_VERSION="0.10.1"
VERSION=$(node -p "require('$APPIMAGE_ROOT/package.json').version")
APPIMAGE_NAME="ProxMenux-${VERSION}.AppImage"
APPIMAGE_NAME="ProxMenux-${VERSION}${PMX_APPIMAGE_SUFFIX}.AppImage"
echo "🚀 Building ProxMenux Monitor AppImage v${VERSION} with hardware monitoring tools..."
@@ -33,17 +35,18 @@ echo "🚀 Building ProxMenux Monitor AppImage v${VERSION} with hardware monitor
# under the non-root GitHub Actions runner — previously hardcoded to
# /var/cache/, which the CI user can't write to (mkdir Permission
# denied → build aborted before doing any actual work).
APPIMAGETOOL_CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/proxmenux-build/appimagetool"
APPIMAGETOOL_CACHE="${XDG_CACHE_HOME:-$HOME/.cache}/proxmenux-build/appimagetool-${PMX_APPIMAGE_ARCH}"
# Preserve a cached copy of appimagetool across builds. wget -q has bitten
# us repeatedly when GitHub momentarily rate-limits or the runner has no
# network — the result is a 0-byte file that passes the `[ -f ]` check on
# the next run and breaks the build silently.
if [ -f "$WORK_DIR/appimagetool" ] && [ -s "$WORK_DIR/appimagetool" ]; then
mkdir -p "$(dirname "$APPIMAGETOOL_CACHE")"
cp -f "$WORK_DIR/appimagetool" "$APPIMAGETOOL_CACHE"
APPIMAGETOOL_URL="https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-${PMX_APPIMAGE_ARCH}.AppImage"
if [ "$PMX_APPIMAGE_ARCH" = aarch64 ]; then
# The old AppImageKit ARM build does not accept ARCH=aarch64 reliably.
# Use a versioned tool; leave the existing AMD64 tool unchanged.
APPIMAGETOOL_URL="https://github.com/AppImage/appimagetool/releases/download/1.9.1/appimagetool-aarch64.AppImage"
APPIMAGETOOL_CACHE="${APPIMAGETOOL_CACHE}-1.9.1"
fi
# Architecture-specific caches never reuse an executable from a different CPU.
# Clean and create work directory
rm -rf "$WORK_DIR"
mkdir -p "$APP_DIR"
@@ -57,7 +60,7 @@ if [ -s "$APPIMAGETOOL_CACHE" ]; then
fi
if [ ! -s "$WORK_DIR/appimagetool" ]; then
echo "📥 Downloading appimagetool..."
wget --tries=3 --timeout=60 "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" -O "$WORK_DIR/appimagetool" || true
wget --tries=3 --timeout=60 "$APPIMAGETOOL_URL" -O "$WORK_DIR/appimagetool" || true
if [ ! -s "$WORK_DIR/appimagetool" ]; then
echo "❌ Failed to download appimagetool" >&2
exit 1
@@ -67,6 +70,17 @@ if [ ! -s "$WORK_DIR/appimagetool" ]; then
cp -f "$WORK_DIR/appimagetool" "$APPIMAGETOOL_CACHE"
fi
APPIMAGETOOL_ARGS=()
if [ "$PMX_APPIMAGE_ARCH" = aarch64 ]; then
echo "f0837e7448a0c1e4e650a93bb3e85802546e60654ef287576f46c71c126a9158 $WORK_DIR/appimagetool" | sha256sum -c -
# Without --runtime-file, appimagetool 1.9.1 embeds the unpinned
# `continuous` runtime. Use a released runtime checked by its digest.
RUNTIME_URL="https://github.com/AppImage/type2-runtime/releases/download/20251108/runtime-aarch64"
wget --tries=3 --timeout=60 "$RUNTIME_URL" -O "$WORK_DIR/runtime-aarch64"
echo "00cbdfcf917cc6c0ff6d3347d59e0ca1f7f45a6df1a428a0d6d8a78664d87444 $WORK_DIR/runtime-aarch64" | sha256sum -c -
APPIMAGETOOL_ARGS=(--runtime-file "$WORK_DIR/runtime-aarch64")
fi
# Create directory structure
mkdir -p "$APP_DIR/usr/bin"
mkdir -p "$APP_DIR/usr/lib/python3/dist-packages"
@@ -126,6 +140,7 @@ cd "$SCRIPT_DIR"
# Copy Flask server
echo "📋 Copying Flask server..."
cp "$SCRIPT_DIR/flask_server.py" "$APP_DIR/usr/bin/"
cp "$SCRIPT_DIR/ovs_topology.py" "$APP_DIR/usr/bin/"
cp "$SCRIPT_DIR/zram_metrics.py" "$APP_DIR/usr/bin/"
cp "$SCRIPT_DIR/flask_auth_routes.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ flask_auth_routes.py not found"
cp "$SCRIPT_DIR/auth_manager.py" "$APP_DIR/usr/bin/" 2>/dev/null || echo "⚠️ auth_manager.py not found"
@@ -245,6 +260,7 @@ fi
# hb_ensure_borg used to download on demand — kept in lockstep so both
# code paths see the same version semantics. SHA256 is the upstream
# release checksum; bump both together.
if [ "$PMX_APPIMAGE_ARCH" = x86_64 ]; then
BORG_VERSION="1.2.8"
BORG_URL="https://github.com/borgbackup/borg/releases/download/${BORG_VERSION}/borg-linux64"
BORG_SHA256="cfa50fb704a93d3a4fa258120966345fddb394f960dca7c47fcb774d0172f40b"
@@ -280,6 +296,12 @@ else
exit 1
fi
else
echo "⚠️ No official Borg 1.2.8 ARM64 standalone binary; using native-host adapter"
cp "$SCRIPT_DIR/borg_native_arm.sh" "$APP_DIR/usr/bin/borg"
chmod +x "$APP_DIR/usr/bin/borg"
fi
# Copy Next.js build
echo "📋 Copying web dashboard..."
if [ -d "$APPIMAGE_ROOT/out" ]; then
@@ -310,6 +332,7 @@ fi
echo "📋 Copying AppRun script..."
if [ -f "$SCRIPT_DIR/AppRun" ]; then
cp "$SCRIPT_DIR/AppRun" "$APP_DIR/AppRun"
cp "$SCRIPT_DIR/appimage_arch.sh" "$APP_DIR/usr/bin/appimage_arch.sh"
chmod +x "$APP_DIR/AppRun"
echo "✅ AppRun script copied successfully"
else
@@ -379,7 +402,7 @@ pip3 install --target "$APP_DIR/usr/lib/python3/dist-packages" --upgrade \
# Phase 3b: Install the complete gevent/WSS runtime separately for every
# supported host ABI. Keeping each dependency tree isolated avoids mixing
# CPython-specific modules from the build runner with those loaded by PVE.
# The two --platform values allow gevent's manylinux_2_28 wheels and the
# The three --platform values allow gevent's manylinux_2_28 wheels and the
# backwards-compatible manylinux2014 zope.interface wheels to be resolved in
# one deterministic installation.
install_gevent_runtime() {
@@ -394,9 +417,9 @@ install_gevent_runtime() {
--target "$target" \
--upgrade \
--only-binary=:all: \
--platform manylinux_2_28_x86_64 \
--platform manylinux_2_27_x86_64 \
--platform manylinux2014_x86_64 \
--platform "manylinux_2_28_${PMX_APPIMAGE_ARCH}" \
--platform "manylinux_2_27_${PMX_APPIMAGE_ARCH}" \
--platform "manylinux2014_${PMX_APPIMAGE_ARCH}" \
--implementation cp \
--python-version "$python_version" \
--abi "$abi" \
@@ -547,7 +570,7 @@ if [ -d "$APP_DIR/bin" ]; then
fi
echo "🔍 Sanity check (ldd + presence of libfreeipmi)"
export LD_LIBRARY_PATH="$APP_DIR/lib:$APP_DIR/lib/x86_64-linux-gnu:$APP_DIR/usr/lib:$APP_DIR/usr/lib/x86_64-linux-gnu"
export LD_LIBRARY_PATH="$APP_DIR/lib:$APP_DIR/lib/${PMX_APPIMAGE_TRIPLET}:$APP_DIR/usr/lib:$APP_DIR/usr/lib/${PMX_APPIMAGE_TRIPLET}"
if ! find "$APP_DIR/usr/lib" "$APP_DIR/lib" -maxdepth 3 -name 'libfreeipmi.so.17*' | grep -q .; then
echo "❌ libfreeipmi.so.17 not found inside AppDir (ipmitool will fail)"
@@ -608,7 +631,7 @@ echo "🔨 Building unified AppImage v${VERSION}..."
cd "$WORK_DIR"
export NO_CLEANUP=1
export APPIMAGE_EXTRACT_AND_RUN=1
ARCH=x86_64 ./appimagetool --no-appstream --verbose "$APP_DIR" "$APPIMAGE_NAME"
ARCH="$PMX_APPIMAGE_ARCH" ./appimagetool --no-appstream --verbose "${APPIMAGETOOL_ARGS[@]}" "$APP_DIR" "$APPIMAGE_NAME"
# Move to dist directory
mv "$APPIMAGE_NAME" "$DIST_DIR/"
+22
View File
@@ -15,6 +15,7 @@ import subprocess
from typing import Any, Dict, List
_LSBLK_TIMEOUT = 5
_SYS_BLOCK = "/sys/block"
_FIELD_RE = re.compile(r'(\w+)="([^"]*)"')
_SKIP_PREFIXES = ("loop", "zd", "nbd", "ram", "sr")
@@ -69,6 +70,27 @@ def list_physical_disks() -> List[Dict[str, Any]]:
return disks
def rotation_rate(name: str, reported: Any = None) -> int:
"""The rotation every view of a disk shows: the RPM smartctl reported,
0 meaning solid state, or else the kernel's flag, where -1 is a spinning
disk of unknown speed. What smartctl reported wins, because USB-SATA
bridges mark every disk behind them as rotational."""
if isinstance(reported, int) and not isinstance(reported, bool) and reported >= 0:
return reported
try:
with open(f"{_SYS_BLOCK}/{name}/queue/rotational") as flag:
return -1 if flag.read().strip() == "1" else 0
except OSError:
return 0
def media_type(name: str, rate: int) -> str:
"""NVMe, SSD or HDD, from a rotation as ``rotation_rate`` returns it."""
if name.startswith("nvme"):
return "NVMe"
return "HDD" if rate else "SSD"
def names_for_keys(keys) -> set:
"""Current kernel names of the disks whose identity is in ``keys``."""
if not keys:
+72 -32
View File
@@ -52,6 +52,8 @@ import time
import threading
import urllib.parse
import uuid
import disk_identity
import ovs_topology
import hardware_monitor
from health_persistence import health_persistence
import xml.etree.ElementTree as ET
@@ -98,6 +100,7 @@ from flask_notification_routes import notification_bp # noqa: E402
from flask_oci_routes import oci_bp # noqa: E402
from flask_audit_routes import audit_bp # noqa: E402
from flask_vm_backup_routes import vm_backup_bp # noqa: E402
from flask_vm_backup_routes import active_vzdump # noqa: E402
from guest_backup_archives import (BackupArchiveError, delete_guest_backups,
guest_backup_deletion_status) # noqa: E402
from notification_manager import notification_manager, resolve_notification_hostname # noqa: E402
@@ -5263,11 +5266,7 @@ def _smart_identity_payload(disk_name):
base['serial'] = value.strip()
except OSError:
pass
try:
if Path(f'/sys/block/{disk_name}/queue/rotational').read_text().strip() == '1':
base['rotation_rate'] = -1 # HDD, RPM unknown
except OSError:
pass
base['rotation_rate'] = disk_identity.rotation_rate(disk_name)
return base
@@ -5327,7 +5326,8 @@ def get_smart_data(disk_name):
retry_at = _smart_fail_backoff.get(disk_name, 0)
if retry_at > now:
return dict(cached[1]) if cached else _smart_default_payload()
# smartctl keeps failing: show what the host knows of the disk.
return dict(cached[1]) if cached else _smart_identity_payload(disk_name)
result = _get_smart_data_uncached(disk_name)
@@ -5801,6 +5801,11 @@ def _get_smart_data_uncached(disk_name):
# print(f"[v0] Health: CRITICAL (SMART failed)")
pass
# Without an answer from smartctl, the kernel's flag; the temperature
# class below depends on it.
if not smart_data['_rotation_known']:
smart_data['rotation_rate'] = disk_identity.rotation_rate(disk_name)
# Temperature-based health (only if we have a valid temperature)
# Thresholds differ by disk class (HDD/SSD/NVMe/SAS) and are
# user-configurable via health_thresholds; the values below are
@@ -5831,27 +5836,6 @@ def _get_smart_data_uncached(disk_name):
smart_data['health'] = 'critical'
elif temp > warn:
smart_data['health'] = 'warning'
# Fallback: ask the kernel only when smartctl had no opinion.
# USB-SATA enclosures (ASM105x family etc.) advertise
# rotational=1 to the kernel even when there's an SSD behind
# them, so trusting /sys here without first checking what
# smartctl said would flip a correctly-identified SSD back to
# HDD. The previous condition (`rotation_rate == 0`) couldn't
# tell "smartctl confirmed SSD" from "smartctl never spoke",
# which is what bit the OCZ-SOLID2 behind an ASM105x dock on
# the lab host (sdd showed as HDD in the UI while smartctl
# was reporting it as SSD).
if not smart_data['_rotation_known']:
try:
rotational_path = f"/sys/block/{disk_name}/queue/rotational"
if os.path.exists(rotational_path):
with open(rotational_path, 'r') as f:
rotational = int(f.read().strip())
if rotational == 1:
smart_data['rotation_rate'] = -1 # HDD, RPM unknown
except Exception:
pass
except FileNotFoundError:
# print(f"[v0] ERROR: smartctl not found - install smartmontools for disk monitoring.")
pass
@@ -6275,15 +6259,22 @@ def _iface_master(iface_name):
# Chain: veth/tap → fwbr (intermediate) → fwpr (peer) → vmbr (real).
def _resolve_bridge_owner(iface_name):
import re
ovs_owners = ovs_topology.get_topology().get('owners', {})
if iface_name in ovs_owners:
return ovs_owners[iface_name]
master = _iface_master(iface_name)
if not master:
return None
if master.startswith('fwbr'):
fwpr = re.sub(r'^fwbr', 'fwpr', master)
fwpr = re.sub(r'i(\d+)$', r'p\1', fwpr)
# A Linux bridge reaches the firewall bridge through fwprNpM; an OVS
# bridge through its own internal port fwlnNoM.
suffix = master[len('fwbr'):]
links = (re.sub(r'i(\d+)$', r'p\1', 'fwpr' + suffix),
re.sub(r'i(\d+)$', r'o\1', 'fwln' + suffix))
try:
if os.path.exists(f'/sys/class/net/{fwpr}'):
real = _iface_master(fwpr)
for link in links:
if os.path.exists(f'/sys/class/net/{link}'):
real = ovs_owners.get(link) or _iface_master(link)
if real:
return real
except Exception:
@@ -6368,6 +6359,10 @@ def get_interface_type(interface_name):
if interface_name.startswith(('tun', 'vnet', 'docker', 'virbr')):
return 'skip'
ovs_type = ovs_topology.get_topology().get('types', {}).get(interface_name)
if ovs_type:
return ovs_type
# Check if it's a bond — sysfs first (name-agnostic), then the
# "bondN" convention as fallback when /sys isn't readable.
if _is_bond_master(interface_name) or interface_name.startswith('bond'):
@@ -6607,6 +6602,7 @@ def get_network_info():
pass
vm_lxc_map = get_vm_lxc_names()
ovs = ovs_topology.get_topology()
# Get network interfaces
net_if_addrs = psutil.net_if_addrs()
@@ -6741,8 +6737,10 @@ def get_network_info():
# vmbr so a guest behind the Proxmox firewall still lands
# under its true bridge in the Network Flow diagram.
master = _resolve_bridge_owner(interface_name)
master = ovs.get('owners', {}).get(interface_name) or master
if master:
interface_info['bridge_owner'] = master
interface_info.update(ovs.get('ports', {}).get(interface_name, {}))
if interface_type == 'bond':
bond_info = get_bond_info(interface_name)
@@ -6755,6 +6753,12 @@ def get_network_info():
if interface_type == 'bridge':
bridge_info = get_bridge_info(interface_name)
if interface_name in ovs.get('bridges', {}):
bridge_info['members'] = ovs['bridges'][interface_name]
bridge_info['physical_interface'] = next((member for member in bridge_info['members']
if member in ovs.get('bonds', {}) or _is_physical_dev(member)), None)
bridge_info['bond_slaves'] = ovs.get('bonds', {}).get(bridge_info['physical_interface'], {}).get('bond_slaves', [])
interface_info['network_backend'] = 'ovs'
interface_info['bridge_members'] = bridge_info['members']
interface_info['bridge_physical_interface'] = bridge_info['physical_interface']
interface_info['bridge_physical_duplex'] = bridge_info['physical_duplex']
@@ -6775,6 +6779,22 @@ def get_network_info():
if interface_type == 'bond':
network_data['bond_interfaces'].append(interface_info)
# An OVS bond is an OVSDB port, not a kernel network interface.
for name, detail in ovs.get('bonds', {}).items():
slaves = [item for item in network_data['physical_interfaces']
if item['name'] in detail['bond_slaves']]
network_data['bond_interfaces'] = [item for item in network_data['bond_interfaces'] if item['name'] != name]
bond_interface = {
'name': name, 'type': 'bond', 'addresses': [],
'status': 'up' if any(item['status'] == 'up' for item in slaves) else 'down',
# OVSDB membership does not reveal active-backup capacity.
'speed': 0, 'duplex': 'unknown', 'mtu': 0, 'mac_address': None,
'rx_Bps': sum(item.get('rx_Bps', 0) for item in slaves),
'tx_Bps': sum(item.get('tx_Bps', 0) for item in slaves), **detail}
network_data['bond_interfaces'].append(bond_interface)
network_data['interfaces'] = [item for item in network_data['interfaces'] if item['name'] != name]
network_data['interfaces'].append(bond_interface)
network_data['physical_active_count'] = physical_active_count
network_data['physical_total_count'] = physical_total_count
network_data['bridge_active_count'] = bridge_active_count
@@ -6825,6 +6845,11 @@ def get_network_info():
bridges_per_nic.setdefault(slave, []).append(bridge['name'])
else:
bridges_per_nic.setdefault(phys, []).append(bridge['name'])
for name, members in ovs.get('bridges', {}).items():
for member in members:
for nic in ovs.get('bonds', {}).get(member, {}).get('bond_slaves', [member]):
if name not in bridges_per_nic.setdefault(nic, []):
bridges_per_nic[nic].append(name)
for phy in network_data['physical_interfaces']:
if phy['name'] in bridges_per_nic:
phy['used_by_bridges'] = bridges_per_nic[phy['name']]
@@ -11523,7 +11548,7 @@ def api_smart_status(disk_name):
'temperature': temp,
'power_on_hours': poh,
'power_cycles': cycles,
'rotation_rate': data.get('rotation_rate', 0),
'rotation_rate': disk_identity.rotation_rate(disk_name, data.get('rotation_rate')),
'form_factor': form_factor,
'physical_block_size': physical_block_size,
'trim_supported': trim_supported,
@@ -13429,6 +13454,7 @@ def api_create_backup(vmid):
pass
unit = f'proxmenux-vzdump-{vmid}-{uuid.uuid4().hex[:8]}'
out_path = os.path.join(run_dir, f'vzdump-{unit}.out')
since = int(time.time()) - 1
launch = subprocess.run(
['systemd-run', f'--unit={unit}', '--collect', '--quiet',
f'--description=ProxMenux backup of {vm_type.upper()} {vmid}',
@@ -13456,7 +13482,21 @@ def api_create_backup(vmid):
capture_output=True, text=True).stdout.strip()
if state not in ('active', 'activating'):
break
# pvesh prints the UPID only once the backup has ended.
upid = active_vzdump(node, since)
if upid:
break
time.sleep(0.3)
if upid is None:
# A short backup can finish between two reads.
try:
with open(out_path, encoding='utf-8', errors='replace') as handle:
buf = handle.read()
except OSError:
pass
m = upid_re.search(buf)
if m:
upid = m.group(0).rstrip(':')
if upid is None:
tail = buf.strip() or 'pvesh exited without producing a UPID'
return jsonify({
+87 -5
View File
@@ -24,7 +24,10 @@ policy only changes the native storage configuration; it never runs pruning.
import json
import os
import re
import shutil
import subprocess
import time
import uuid
from flask import Blueprint, jsonify, request
@@ -395,6 +398,86 @@ def _run_arguments(job):
return args
# A job of several guests leaves the id of its task empty.
UPID_RE = re.compile(r"UPID:[^:\s]+:[^:\s]+:[^:\s]+:[^:\s]+:vzdump:[^:\s]*:[^:\s]+:")
RUN_DIR = "/run/proxmenux"
def active_vzdump(node, since):
"""The UPID of the first backup task the node started at or after `since`."""
ok, tasks = _pvesh_json(["get", f"/nodes/{node}/tasks", "--source", "active", "--typefilter", "vzdump"])
if not ok or not isinstance(tasks, list):
return None
started = sorted((task for task in tasks if isinstance(task, dict)
and UPID_RE.match(str(task.get("upid") or ""))
and isinstance(task.get("starttime"), int) and task["starttime"] >= since),
key=lambda task: task["starttime"])
return started[0]["upid"].rstrip(":") if started else None
def _start_vzdump(node, arguments, job_id):
"""Start the part of a job that runs on a node and return its task UPID.
pvesh waits for the whole backup and prints the UPID only at the end, and
a child of the Monitor is killed with its service, so vzdump runs in its
own transient unit and its UPID is read from the node's active tasks. The
task then runs to the end on its own. Returns (upid, error)."""
if not shutil.which("systemd-run"):
return None, "systemd-run not found"
run_dir = RUN_DIR
try:
os.makedirs(run_dir, mode=0o700, exist_ok=True)
now = time.time()
for old in os.listdir(run_dir):
old_path = os.path.join(run_dir, old)
if old.startswith("vzdump-") and now - os.path.getmtime(old_path) > 86400:
os.remove(old_path)
except OSError:
pass
unit = f"proxmenux-vzdump-job-{uuid.uuid4().hex[:8]}"
out_path = os.path.join(run_dir, f"vzdump-{unit}.out")
since = int(time.time()) - 1
try:
launch = subprocess.run(
["systemd-run", f"--unit={unit}", "--collect", "--quiet",
f"--description=ProxMenux backup job {job_id}",
f"--property=StandardOutput=file:{out_path}",
"pvesh", "create", f"/nodes/{node}/vzdump", *arguments],
capture_output=True, text=True, timeout=15)
except subprocess.TimeoutExpired:
return None, "systemd-run timed out"
if launch.returncode != 0:
return None, (launch.stderr or launch.stdout).strip()
buf = ""
deadline = time.time() + 10.0
while time.time() < deadline:
try:
with open(out_path, encoding="utf-8", errors="replace") as handle:
buf = handle.read()
except OSError:
buf = ""
found = UPID_RE.search(buf)
if found:
return found.group(0).rstrip(":"), None
state = subprocess.run(["systemctl", "is-active", unit], capture_output=True, text=True).stdout.strip()
if state not in ("active", "activating"):
break
upid = active_vzdump(node, since)
if upid:
return upid, None
time.sleep(0.5)
# A short backup can finish between two reads: its UPID is the last line.
try:
with open(out_path, encoding="utf-8", errors="replace") as handle:
buf = handle.read()
except OSError:
pass
found = UPID_RE.search(buf)
if found:
return found.group(0).rstrip(":"), None
return None, (buf.strip() or "pvesh exited without producing a UPID")[-800:]
@vm_backup_bp.route("/api/vm-backup-jobs/<job_id>/run", methods=["POST"])
@require_admin_scope
def run_job(job_id):
@@ -418,12 +501,11 @@ def run_job(job_id):
for node in nodes:
if not NODE_RE.match(node):
continue
ok, out = _pvesh(["create", f"/nodes/{node}/vzdump", *arguments])
if ok:
found = re.search(r"UPID:[^\s\"']+", out)
tasks.append({"node": node, "upid": found.group(0) if found else ""})
upid, error = _start_vzdump(node, arguments, job_id)
if upid:
tasks.append({"node": node, "upid": upid})
else:
failures.append({"node": node, "error": out})
failures.append({"node": node, "error": error})
if not tasks:
return _err(failures[0]["error"] if failures else "The backup could not be started", 500)
return jsonify({"success": True, "tasks": tasks, "failures": failures})
+36 -64
View File
@@ -1188,21 +1188,15 @@ def _check_oci_app(entry: dict) -> dict:
# ── NVIDIA driver checker ──
#
# Source of truth for what's available upstream:
# `https://download.nvidia.com/XFree86/Linux-x86_64/latest.txt`
# returns the single newest version, e.g. "580.105.08"
# `https://download.nvidia.com/XFree86/Linux-x86_64/`
# HTML directory listing — we scrape it for per-branch latest
# (so a user on 570.x gets 570.x's latest, without an automatic
# cross-branch upgrade).
#
# Cache TTL is 7 days because NVIDIA's release cadence on each branch
# is roughly monthly. The cache is in-memory only; AppImage restarts
# refresh it for free.
# The driver update is the version the NVIDIA installer itself would
# recommend on this host: it filters by the running kernel, NVIDIA's
# maintained branches, the PCI IDs of the host's GPUs and the NVENC patch,
# and keeps the installed branch when it can. Asking the installer means the
# Monitor never announces a version the installer then refuses. The installer
# keeps its own caches of NVIDIA's pages for 24 hours.
_NVIDIA_BASE = "https://download.nvidia.com/XFree86/Linux-x86_64"
_NVIDIA_CACHE_TTL = 7 * 86400
_nvidia_cache: dict[str, Any] = {"versions": [], "fetched_at": 0}
_NVIDIA_INSTALLER = "/usr/local/share/proxmenux/scripts/gpu_tpu/nvidia_installer.sh"
_NVIDIA_CHECK_TIMEOUT = 300
def _version_tuple(v: str) -> tuple:
@@ -1219,64 +1213,46 @@ def _version_tuple(v: str) -> tuple:
return tuple(out[:3])
def _fetch_nvidia_versions(force: bool = False) -> list[str]:
"""Return the cached list of all upstream versions, or fetch fresh."""
now = time.time()
if not force and _nvidia_cache["versions"] and \
now - _nvidia_cache["fetched_at"] < _NVIDIA_CACHE_TTL:
return _nvidia_cache["versions"]
def _nvidia_recommended_version(current: str) -> tuple[Optional[str], Optional[str]]:
"""The version the installer recommends for this host, or an error."""
try:
req = urllib.request.Request(
_NVIDIA_BASE + "/",
headers={"User-Agent": "ProxMenux-Monitor/1.0"},
)
with urllib.request.urlopen(req, timeout=15) as resp:
html = resp.read().decode("utf-8", errors="replace")
except Exception as e:
print(f"[ProxMenux] NVIDIA version fetch failed: {e}")
return _nvidia_cache.get("versions", [])
versions = sorted(
{m.group(1) for m in re.finditer(
r"""href=['"](\d+\.\d+(?:\.\d+)?)/?['"]""", html)},
key=_version_tuple,
reverse=True,
# An older installer would ignore the option and open its menu.
with open(_NVIDIA_INSTALLER, encoding="utf-8", errors="replace") as handle:
if "--recommended-version" not in handle.read():
return None, "the NVIDIA installer on this host is older than ProxMenux Monitor"
done = subprocess.run(
["bash", _NVIDIA_INSTALLER, "--recommended-version", current],
capture_output=True, text=True, timeout=_NVIDIA_CHECK_TIMEOUT,
# The host's curl and Python, not the AppImage's libraries.
env={k: v for k, v in os.environ.items() if k not in ("PYTHONPATH", "LD_LIBRARY_PATH")},
)
except (OSError, subprocess.TimeoutExpired) as e:
return None, f"the NVIDIA installer could not be run: {e}"
versions = [line.strip() for line in done.stdout.splitlines()
if re.fullmatch(r"\d+\.\d+(\.\d+)?", line.strip())]
if versions:
_nvidia_cache["versions"] = versions
_nvidia_cache["fetched_at"] = now
return versions
return versions[-1], None
if done.returncode == 0:
return None, None
return None, "the NVIDIA installer could not read the version list"
def _check_nvidia_xfree86(entry: dict) -> dict:
"""Report same-branch bugfix upgrades for the installed driver."""
"""Report the update the NVIDIA installer would recommend."""
current = entry.get("current_version")
if not current or not re.match(r"^\d+\.\d+(\.\d+)?$", current):
return {"available": False, "latest": None,
"last_check": _now_iso(), "error": "no installed version"}
versions = _fetch_nvidia_versions()
if not versions:
return {"available": False, "latest": None,
"last_check": _now_iso(),
"error": "could not parse upstream version listing"}
current_branch = current.split(".")[0]
same_branch = [v for v in versions if v.split(".")[0] == current_branch]
same_branch_latest = same_branch[0] if same_branch else None
available = False
latest: Optional[str] = None
if same_branch_latest and \
_version_tuple(same_branch_latest) > _version_tuple(current):
latest = same_branch_latest
available = True
recommended, error = _nvidia_recommended_version(current)
available = bool(recommended) and _version_tuple(recommended) > _version_tuple(current)
same_branch = bool(recommended) and recommended.split(".")[0] == current.split(".")[0]
return {
"available": available,
"latest": latest,
"latest": recommended if available else None,
"last_check": _now_iso(),
"error": None,
"_upgrade_kind": "patch" if available else None,
"error": error,
"_upgrade_kind": ("patch" if same_branch else "branch") if available else None,
}
@@ -1842,13 +1818,9 @@ def check_for_updates(force: bool = False) -> list[dict]:
UI reads ``get_active_items()`` to render the inline "update
available" line.
``force`` invalidates the per-source caches (currently only the
NVIDIA versions list — OCI keeps its own internal cache).
``force`` is kept for callers; the NVIDIA installer and OCI keep
their own caches.
"""
if force:
_nvidia_cache["versions"] = []
_nvidia_cache["fetched_at"] = 0
updates_available: list[dict] = []
successful_lxc_checks: list[tuple[int, int]] = []
with _lock:
+4 -1
View File
@@ -3163,7 +3163,10 @@ class NotificationManager:
if not ok:
raise ValueError(f"Invalid ai_ollama_url: {err}")
if short_key == 'ai_openai_base_url' and str(value):
ok, err = validate_external_url(str(value), allow_loopback=False)
# Custom OpenAI-compatible servers can run on the LAN or
# localhost, just like Ollama. Match test-ai/provider-models;
# unsafe schemes, metadata hosts and link-local stay blocked.
ok, err = validate_external_url(str(value), allow_loopback=True)
if not ok:
raise ValueError(f"Invalid ai_openai_base_url: {err}")
+109
View File
@@ -0,0 +1,109 @@
"""Read-only OVSDB topology; Linux bridges continue to use their sysfs path.
OVS does not publish Linux bridge brif/master links, and an OVSBond has
no kernel netdev. Read the three OVSDB tables once per short cache window
instead of guessing from names or changing the host's network config.
"""
import json
import shutil
import subprocess
import threading
import time
_CACHE_SECONDS = 15
_lock = threading.Lock()
_cached_at = 0
_cached = {}
def _value(value):
if isinstance(value, list) and len(value) == 2:
if value[0] in ('uuid', 'named-uuid'):
return value[1]
if value[0] == 'set':
return [_value(item) for item in value[1]]
return value
def _rows(table):
return [{key: _value(value) for key, value in zip(table['headings'], row)}
for row in table['data']]
def _list(value):
return value if isinstance(value, list) else [] if value is None or value == '' else [value]
def parse_topology(bridges, ports, interfaces):
"""Normalize OVSDB UUID references, including singleton sets and bonds."""
iface_by_id = {row['_uuid']: row for row in _rows(interfaces)}
port_by_id = {row['_uuid']: row for row in _rows(ports)}
topology = {'types': {}, 'owners': {}, 'bridges': {}, 'bonds': {}, 'ports': {}}
for bridge in _rows(bridges):
name = bridge['name']
topology['types'][name] = 'bridge'
members = []
for port_id in _list(bridge.get('ports')):
port = port_by_id.get(port_id)
if not port:
continue
port_name = port['name']
ifaces = [iface_by_id[i] for i in _list(port.get('interfaces')) if i in iface_by_id]
# The bridge's own internal port is not a downstream member.
if port_name == name:
continue
members.append(port_name)
detail = {'bridge_owner': name, 'network_backend': 'ovs',
'ovs_tag': next(iter(_list(port.get('tag'))), None),
'ovs_trunks': _list(port.get('trunks'))}
topology['ports'][port_name] = detail
topology['owners'][port_name] = name
is_bond = len(ifaces) > 1
if is_bond:
topology['types'][port_name] = 'bond'
mode = port.get('bond_mode') or 'balance-slb'
topology['bonds'][port_name] = {
'bond_mode': mode, 'bond_slaves': [i['name'] for i in ifaces],
# OVSDB alone does not tell us which slave is active.
'bond_active_slave': None, 'bond_supports_failover': False,
'bond_slave_status': {}, **detail}
for iface in ifaces:
iface_name = iface['name']
topology['owners'][iface_name] = name
topology['ports'][iface_name] = detail
if is_bond:
topology['ports'][iface_name] = {**detail, 'bond_master': port_name,
'bond_role': 'member'}
elif iface.get('type') == 'internal' and not iface_name.startswith(('fwpr', 'fwln')):
topology['types'][iface_name] = 'vlan'
topology['bridges'][name] = members
return topology
def get_topology():
"""Bounded, cached reads; missing OVS or an unavailable daemon is harmless."""
global _cached_at, _cached
with _lock:
now = time.monotonic()
if now - _cached_at < _CACHE_SECONDS:
return _cached
binary = shutil.which('ovs-vsctl')
result = {}
if binary:
try:
tables = []
for table, columns in (
('Bridge', '_uuid,name,ports'),
('Port', '_uuid,name,interfaces,bond_mode,tag,trunks'),
('Interface', '_uuid,name,type'),
):
proc = subprocess.run(
[binary, '--timeout=1', '--format=json', f'--columns={columns}', 'list', table],
capture_output=True, text=True, timeout=2, check=True)
tables.append(json.loads(proc.stdout))
result = parse_topology(*tables)
except (OSError, subprocess.SubprocessError, ValueError, KeyError, TypeError):
# Do not keep stale ownership when OVS disappears or is reconfigured.
result = {}
_cached, _cached_at = result, now
return _cached
@@ -0,0 +1,52 @@
"""Provider model ordering and curated availability, without credentials/network."""
import io
import json
from pathlib import Path
import sys
import unittest
from unittest.mock import patch
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from ai_providers.groq_provider import GroqProvider
class GroqModelRecommendationsTests(unittest.TestCase):
def fetch(self, ids):
response = io.BytesIO(json.dumps({'data': [{'id': model} for model in ids]}).encode())
with patch('ai_providers.groq_provider.urllib.request.urlopen', return_value=response) as request:
models = GroqProvider(api_key='fixture-only').list_models()
self.assertEqual(request.call_args.kwargs['timeout'], 10)
return models
def test_current_verified_models_precede_legacy_and_unknown_families(self):
listed = ['mixtral-fixture', 'allam-2-7b', 'llama-3.3-70b-versatile',
'openai/gpt-oss-120b', 'qwen/qwen3.8-27b', 'openai/gpt-oss-20b']
self.assertEqual(self.fetch(listed)[:3],
['openai/gpt-oss-20b', 'openai/gpt-oss-120b', 'qwen/qwen3.8-27b'])
self.assertCountEqual(self.fetch(listed), listed)
def test_recommendations_never_invent_models_or_remove_arabic_model(self):
self.assertEqual(self.fetch(['allam-2-7b']), ['allam-2-7b'])
self.assertEqual(self.fetch([]), [])
def test_non_chat_models_still_excluded(self):
self.assertEqual(self.fetch(['whisper-large-v3', 'llama-prompt-guard-2-22m',
'openai/gpt-oss-20b']), ['openai/gpt-oss-20b'])
def test_missing_credentials_do_not_fetch_models(self):
with patch('ai_providers.groq_provider.urllib.request.urlopen') as request:
self.assertEqual(GroqProvider().list_models(), [])
request.assert_not_called()
def test_curated_catalog_keeps_verified_default_and_removes_unavailable_free_ids(self):
catalog = json.loads((Path(__file__).resolve().parents[2] / 'config/verified_ai_models.json').read_text())
self.assertEqual(GroqProvider.RECOMMENDED_PREFIXES[0], catalog['groq']['recommended'])
for provider in ('groq', 'openrouter'):
self.assertIn(catalog[provider]['recommended'], catalog[provider]['models'])
self.assertNotIn('poolside/laguna-s-2.1:free', catalog['openrouter']['models'])
self.assertNotIn('nvidia/nemotron-3-super-120b-a12b:free', catalog['openrouter']['models'])
self.assertIn('allam-2-7b', catalog['groq']['models'])
if __name__ == '__main__':
unittest.main()
@@ -20,8 +20,9 @@ class CapturingOpenAIProvider(OpenAIProvider):
super().__init__(*args, **kwargs)
self.captured_payload = None
def _make_request(self, url, payload, headers):
def _make_request(self, url, payload, headers, timeout=15):
self.captured_payload = payload
self.captured_timeout = timeout
return {"choices": [{"message": {"content": "ok"}}]}
@@ -69,6 +70,41 @@ class OpenAICompatibleModelTests(unittest.TestCase):
self.addCleanup(patcher.stop)
return db_path
def test_local_compatible_endpoint_can_be_saved_and_reloaded(self):
db_path = self._temp_db_patch()
# Synthetic addresses cover each RFC1918 range; no network is used.
for url in ('http://10.0.0.10:8080/v1', 'http://172.16.0.10:8080/v1',
'http://192.168.1.10:8080/v1', 'http://localhost:8080/v1',
'http://127.0.0.1:8080/v1'):
with self.subTest(url=url):
manager = self._manager({})
result = manager.save_settings({'ai_openai_base_url': url})
self.assertTrue(result['success'], result)
with sqlite3.connect(db_path) as conn:
saved = conn.execute(
'SELECT setting_value FROM user_settings WHERE setting_key=?',
('notification.ai_openai_base_url',),
).fetchone()
self.assertEqual(saved, (url,))
reloaded = self._manager({})
reloaded._load_config()
self.assertEqual(reloaded._config['ai_openai_base_url'], url)
def test_local_compatible_endpoint_keeps_unsafe_urls_blocked(self):
db_path = self._temp_db_patch()
for url in ('file:///etc/shadow', 'http://169.254.169.254/latest/meta-data/',
'http://metadata.google.internal/', 'http://[fe80::1]/',
'http://0.0.0.0:8080/v1', 'http://224.0.0.1/v1'):
with self.subTest(url=url):
result = self._manager({}).save_settings({'ai_openai_base_url': url})
self.assertFalse(result['success'], result)
with sqlite3.connect(db_path) as conn:
saved = conn.execute(
'SELECT setting_value FROM user_settings WHERE setting_key=?',
('notification.ai_openai_base_url',),
).fetchone()
self.assertIsNone(saved)
def test_custom_openai_endpoint_omits_temperature_for_opaque_alias(self):
provider = CapturingOpenAIProvider(
api_key="token",
@@ -84,6 +120,14 @@ class OpenAICompatibleModelTests(unittest.TestCase):
self.assertNotIn("reasoning_effort", provider.captured_payload)
self.assertNotIn("max_completion_tokens", provider.captured_payload)
def test_a_request_waits_as_long_as_the_monitor_allows_a_rewrite(self):
# A local model behind an OpenAI-compatible endpoint is slow; the
# request must not give up before the Monitor's own limit.
provider = CapturingOpenAIProvider(api_key="token", model="gemma-3-1b-it-Q4_K_M",
base_url="http://192.0.2.22:8080/v1")
provider.generate("system", "user", max_tokens=100)
self.assertEqual(provider.captured_timeout, notification_manager.AI_REWRITE_TIMEOUT_SECONDS)
def test_official_openai_reasoning_model_still_uses_reasoning_contract(self):
provider = CapturingOpenAIProvider(
api_key="token",
+148
View File
@@ -0,0 +1,148 @@
"""OVSDB fixtures exercise live ownership, UUID sets, bonds and API output."""
import ast
import importlib.util
import json
import os
from pathlib import Path
import socket
import subprocess
import types
import unittest
from unittest.mock import patch
SCRIPTS = Path(__file__).resolve().parents[1]
spec = importlib.util.spec_from_file_location('ovs_topology_test', SCRIPTS / 'ovs_topology.py')
ovs = importlib.util.module_from_spec(spec)
spec.loader.exec_module(ovs)
def uuid(name):
return ['uuid', name]
def refs(*names):
return ['set', [uuid(name) for name in names]]
def table(headings, *rows):
return {'headings': headings.split(','), 'data': list(rows)}
def fixture():
# Mixed Linux/OVS host, named bond without a kernel netdev, tagged
# internal port, direct guest and guest behind a Proxmox firewall,
# which on OVS links its fwbr bridge through the internal port fwlnNoM.
return (
table('_uuid,name,ports', ['b1', 'switch0', refs('p0', 'p1', 'p2', 'p3', 'p4', 'p5')]),
table('_uuid,name,interfaces,bond_mode,tag,trunks',
['p0', 'switch0', uuid('i0'), '', ['set', []], ['set', []]],
['p1', 'eno1', uuid('i1'), '', ['set', []], ['set', [10, 20]]],
['p2', 'uplink', refs('i2', 'i3'), 'balance-tcp', ['set', []], ['set', []]],
['p3', 'vlan100', uuid('i4'), '', 100, ['set', []]],
['p4', 'tap103i0', uuid('i5'), '', 100, ['set', []]],
['p5', 'fwln115o0', uuid('i6'), '', 10, ['set', []]]),
table('_uuid,name,type', ['i0', 'switch0', 'internal'], ['i1', 'eno1', ''],
['i2', 'eno2', ''], ['i3', 'eno3', ''], ['i4', 'vlan100', 'internal'],
['i5', 'tap103i0', ''], ['i6', 'fwln115o0', 'internal']))
class OvsTopology(unittest.TestCase):
def setUp(self):
ovs._cached_at = 0
ovs._cached = {}
self.addCleanup(setattr, ovs, '_cached_at', 0)
self.addCleanup(setattr, ovs, '_cached', {})
def test_ovsdb_singletons_bonds_tags_and_internal_ports(self):
data = ovs.parse_topology(*fixture())
self.assertEqual(data['types']['switch0'], 'bridge')
self.assertEqual(data['types']['vlan100'], 'vlan')
self.assertNotIn('switch0', data['bridges']['switch0'])
self.assertEqual(data['owners']['tap103i0'], 'switch0')
self.assertEqual(data['ports']['vlan100']['ovs_tag'], 100)
self.assertEqual(data['ports']['eno1']['ovs_trunks'], [10, 20])
self.assertEqual(data['bonds']['uplink']['bond_slaves'], ['eno2', 'eno3'])
self.assertIsNone(data['bonds']['uplink']['bond_active_slave'])
self.assertEqual(data['ports']['eno2']['bond_master'], 'uplink')
def test_zero_vlan_tag_is_preserved(self):
tables = fixture()
tables[1]['data'][3][4] = 0
self.assertEqual(ovs.parse_topology(*tables)['ports']['vlan100']['ovs_tag'], 0)
def test_no_ovs_does_not_spawn_any_process(self):
with patch.object(ovs.shutil, 'which', return_value=None), patch.object(ovs.subprocess, 'run') as run:
self.assertEqual(ovs.get_topology(), {})
run.assert_not_called()
def test_read_only_queries_cached_and_failure_drops_stale_topology(self):
replies = [types.SimpleNamespace(stdout=json.dumps(t)) for t in fixture()]
with patch.object(ovs.shutil, 'which', return_value='/usr/bin/ovs-vsctl'), \
patch.object(ovs.subprocess, 'run', side_effect=replies) as run:
first = ovs.get_topology()
self.assertEqual(ovs.get_topology(), first)
self.assertEqual(run.call_count, 3)
for call in run.call_args_list:
self.assertEqual(call.args[0][-2], 'list')
self.assertIn('--timeout=1', call.args[0])
ovs._cached_at = 0
with patch.object(ovs.shutil, 'which', return_value='/usr/bin/ovs-vsctl'), \
patch.object(ovs.subprocess, 'run', side_effect=subprocess.TimeoutExpired('ovs-vsctl', 2)):
self.assertEqual(ovs.get_topology(), {})
def test_malformed_or_reconfigured_database_is_harmless(self):
for payload in ('not-json', '{}', '{"headings": [], "data": [[]]}'):
ovs._cached_at = 0
with patch.object(ovs.shutil, 'which', return_value='/usr/bin/ovs-vsctl'), \
patch.object(ovs.subprocess, 'run', return_value=types.SimpleNamespace(stdout=payload)):
self.assertEqual(ovs.get_topology(), {})
def api_namespace(self):
names = {'get_network_info', 'get_interface_type', '_resolve_bridge_owner'}
tree = ast.parse((SCRIPTS / 'flask_server.py').read_text())
nodes = [n for n in tree.body if isinstance(n, ast.FunctionDef) and n.name in names]
data = ovs.parse_topology(*fixture())
names = ['eno1', 'eno2', 'eno3', 'switch0', 'vlan100', 'tap103i0', 'tap115i0', 'vmbr1']
stats = {name: types.SimpleNamespace(isup=True, speed=1000, duplex=2, mtu=1500) for name in names}
counter = types.SimpleNamespace(bytes_sent=1000, bytes_recv=2000, packets_sent=10, packets_recv=20,
errin=0, errout=0, dropin=0, dropout=0)
ns = {'os': os, 'socket': socket,
'ovs_topology': types.SimpleNamespace(get_topology=lambda: data),
'get_proxmox_node_name': lambda: 'pve', 'get_vm_lxc_names': lambda: {},
'psutil': types.SimpleNamespace(net_if_addrs=lambda: dict.fromkeys(names, []),
net_if_stats=lambda: stats,
net_io_counters=lambda **kw: dict.fromkeys(names, counter) if kw else counter),
'_ensure_net_rate_sampler': lambda: None, '_compute_per_nic_rates_live': lambda _: {},
'_is_bond_master': lambda _: False, '_is_physical_dev': lambda name: name.startswith('eno'),
'_ethtool_max_speed': lambda _: 1000,
'_iface_master': lambda name: {'tap115i0': 'fwbr115i0', 'fwln115o0': 'ovs-system'}.get(name),
'extract_vmid_from_interface': lambda name: (103 if '103' in name else 115, 'vm'),
'get_bridge_info': lambda _: {'members': [], 'physical_interface': None,
'physical_duplex': 'unknown', 'bond_slaves': []}}
exec(compile(ast.Module(body=nodes, type_ignores=[]), 'flask_server.py', 'exec'), ns)
return ns
def test_api_preserves_linux_bridge_and_assigns_ovs_guests_and_bond(self):
ns = self.api_namespace()
# OVS creates no fwpr peer for the firewall bridge.
with patch('os.path.exists', side_effect=lambda path: 'fwpr' not in str(path)):
result = ns['get_network_info']()
self.assertNotIn('error', result)
self.assertEqual({i['name'] for i in result['bridge_interfaces']}, {'switch0', 'vmbr1'})
self.assertEqual(result['bond_interfaces'][0]['name'], 'uplink')
self.assertEqual(result['bond_interfaces'][0]['speed'], 0)
self.assertIsNone(result['bond_interfaces'][0]['mac_address'])
self.assertIn('uplink', {i['name'] for i in result['interfaces']})
for guest in result['vm_lxc_interfaces']:
self.assertEqual(guest['bridge_owner'], 'switch0')
self.assertEqual(next(i for i in result['interfaces'] if i['name'] == 'vlan100')['ovs_tag'], 100)
for nic in result['physical_interfaces']:
self.assertIn('switch0', nic['used_by_bridges'])
def test_packaged_module_is_shipped_with_backend(self):
self.assertIn('cp "$SCRIPT_DIR/ovs_topology.py" "$APP_DIR/usr/bin/"',
(SCRIPTS / 'build_appimage.sh').read_text())
if __name__ == '__main__':
unittest.main()
+39
View File
@@ -0,0 +1,39 @@
// Exercise both shipped SVG layouts with OVS internal ports and bond topology.
const assert = require('node:assert/strict')
const fs = require('node:fs')
const path = require('node:path')
const vm = require('node:vm')
const ts = require('typescript')
const source = fs.readFileSync(path.join(__dirname, '../components/network-flow.tsx'), 'utf8')
const code = ts.transpileModule(source, {
compilerOptions: { module: ts.ModuleKind.CommonJS, jsx: ts.JsxEmit.ReactJSX },
}).outputText
const sandbox = { exports: {}, require: () => ({}), console }
vm.runInNewContext(code, sandbox)
const data = {
nics: [
{ id: 'eno1', link: '1 Gb/s', rx: 1, tx: 2, status: 'up' },
{ id: 'eno2', link: '1 Gb/s', rx: 1, tx: 2, status: 'up', bond: 'uplink', role: 'member' },
{ id: 'eno3', link: '1 Gb/s', rx: 1, tx: 2, status: 'up', bond: 'uplink', role: 'member' },
],
bonds: [{ id: 'uplink', mode: 'balance-tcp', rx: 2, tx: 4, status: 'up' }],
bridges: [{ id: 'switch0', parent: 'eno1' }, { id: 'vmbr1' }],
consumers: [
{ id: 'host', kind: 'host', label: 'host', bridge: 'switch0', rx: 1, tx: 2 },
{ id: 'vlan100', kind: 'interface', label: 'vlan100 · VLAN 100', bridge: 'switch0', rx: 0, tx: 0 },
{ id: 'tap103i0', kind: 'vm', label: 'VM 103', bridge: 'switch0', rx: 1, tx: 2 },
{ id: 'veth115i0', kind: 'lxc', label: 'LXC 115', bridge: 'switch0', rx: 1, tx: 2 },
{ id: 'tap104i0', kind: 'vm', label: 'VM 104', bridge: 'vmbr1', rx: 1, tx: 2 },
],
}
const labels = { down: 'Down', active: 'Active', standby: 'Standby' }
for (const render of [sandbox.renderHorizontal, sandbox.renderVertical]) {
const result = render(data, 1500, labels, 'Bytes')
for (const id of ['switch0', 'vmbr1', 'vlan100', 'tap103i0', 'veth115i0', 'tap104i0', 'uplink']) {
assert.ok(result.svg.includes(`data-node-id="${id}"`), `layout must draw ${id}`)
}
assert.ok(result.svg.includes('vlan100 · VLAN 100'))
assert.ok(!result.svg.includes('NaN'))
assert.ok(!result.svg.includes('undefined'))
}
console.log('PASS: both Network Flow layouts render OVS bonds, internal VLAN ports and mixed Linux/OVS guests')
+2
View File
@@ -23,6 +23,7 @@ A special thank you goes to [@Vaso73](https://github.com/Vaso73), [@f3rs3n](http
- **The Ollama entry describes what the image provides** ([PR #566](https://github.com/MacRimi/ProxMenux/pull/566), contributed by [@jcastro](https://github.com/jcastro)): its HTTP API on port 11434, with its link and startup check on `/api/version`.
- **An update clears the snapshot an interrupted backup leaves** ([#565](https://github.com/MacRimi/ProxMenux/issues/565), reported by [@kiosvantra](https://github.com/kiosvantra)). A snapshot made by the user stops the update, because a rebuilt container cannot keep it.
- **A container that ignores the shutdown signal is stopped after 60 seconds**, as `docker stop` does, during an update and when an interrupted operation is recovered.
- **Modify and updates accept every application whose image declares a data path**: SearXNG, Tor, Whoogle and BIND9 keep it in a volume of its own, Kanboard keeps its certificates, and Chrony, Jaeger, PlantUML, UrBackup, GoToSocial, AceStream HTTP Proxy and RomM mark the paths that hold no data. When an installation still keeps such a path in the container, the message names it.
## 🖥️ Monitor — Proxmox updates and pending reboots
@@ -59,6 +60,7 @@ A special thank you goes to [@Vaso73](https://github.com/Vaso73), [@f3rs3n](http
- **Bitwarden recognizes the 2FA field on the Monitor login** ([#570](https://github.com/MacRimi/ProxMenux/issues/570), reported by [@shtefko](https://github.com/shtefko)): the backup code hint keeps its text and place, outside the group of the field.
- **Secure Gateway installs on Proxmox hosts on BTRFS** ([#564](https://github.com/MacRimi/ProxMenux/issues/564), reported by [@78v5](https://github.com/78v5)): the Alpine template goes to an active storage that holds container templates.
- **A disk I/O error from the kernel is recorded on its disk**, with its serial number, also when the error names a partition.
- **Every view of a disk shows the same type**: the Storage page, the disk details, the SMART report and the Audit & Report inventory take it from one source. A hard disk smartctl cannot read keeps its type, model and serial number, and a hard disk that reports no speed shows as HDD.
- **The Monitor installs as an app (PWA) from the browser**: it serves its own web app manifest and service worker, with the 192 and 512 px icons Chrome requires.
- **The Y-axis titles stay inside the overview charts** ([PR #539](https://github.com/MacRimi/ProxMenux/pull/539), contributed by [@f3rs3n](https://github.com/f3rs3n)).
- **The application version-tracking catalog builds from the current Helper-Scripts repositories**.
+37
View File
@@ -0,0 +1,37 @@
# Native Monitor AppImage builds
The builder selects its native architecture using `uname -m`. Supported targets
are x86_64 and aarch64 (ARM64). It selects matching appimagetool executables,
separate download caches, manylinux wheels and GNU library paths. Cross-building
by overriding a target variable is intentionally unsupported: APT packages and
other native Python dependencies must also match the build machine.
Run `bash AppImage/scripts/build_appimage.sh` on a Linux builder with Node.js,
Python/pip, APT and the usual AppImage build dependencies. AMD64 keeps the existing
`ProxMenux-VERSION.AppImage` name; ARM64 produces
`ProxMenux-VERSION-aarch64.AppImage`.
The native validation workflow builds both architectures on GitHub's native
Ubuntu 22.04 runners, extracts each AppImage without FUSE, and imports its bundled
CPython 3.11 and 3.13 WebSocket/image runtimes, including the extracted launcher
with only its final server execution intercepted. It does not upload artifacts,
change release assets, or modify an installed Monitor.
This build lane is a prerequisite for ARM distribution, not a declaration of
PXVIRT or Raspberry Pi hardware compatibility. ARM release/checksum publication,
installer selection and validation on the maintainer's PXVIRT lab remain separate
steps before ARM installations can use a published image. The current release
and installer distribution remain unchanged.
## Borg host backups on ARM64
Borg 1.2.8 publishes an AMD64 standalone executable but no ARM64 equivalent.
ARM64 builds therefore include a small adapter that uses `/usr/bin/borg` from
the host's native `borgbackup` package. Without that package it exits with a
clear error; it never runs the AMD64 binary. The host-backup helper likewise
refuses AMD64 cached/downloaded binaries on non-AMD64 hosts. The existing AMD64
standalone binary and checksum remain unchanged. Operators must install their
native distro package separately; this build does not install it on the host.
ARM64 uses the official versioned appimagetool 1.9.1 with SHA256 verification;
the existing AMD64 packaging tool remains unchanged.
+216
View File
@@ -0,0 +1,216 @@
# USB/IP over SSH
Open **Hardware: GPUs and Coral-TPU → USB/IP over SSH** to share a
selected USB device or connect this Linux machine to a device on another host.
The same menu is available through the main menu search (`usbip`, `zigbee`,
`bluetooth` or `printer`). This implements the host and Linux client setup
requested in [#350](https://github.com/MacRimi/ProxMenux/issues/350).
## Server
1. Enable the USB/IP server. Missing `usbip`, `socat`, `kmod` and `openssh-client`
packages are offered from the existing Debian repositories. Repository and
SSH server settings are preserved.
2. Choose **Share a local USB device** and select a device by its bus ID, product
and serial number. Confirm that it will become unavailable to local programs
and guests using ordinary USB passthrough.
3. Check **View USB/IP status**. The device should show `exported` and a bus ID.
Binding errors are reported separately rather than treated as a successful
export. Inspect the service log for startup errors:
```sh
journalctl -u proxmenux-usbip-server.service
```
The server reloads saved selections every three seconds. It keeps open usbfs
references to each original USB device and its USB ancestors before binding.
After binding it marks the live match REMOV and verifies the original is still
bound. Replacement devices cannot use that match for automatic USB/IP probing.
On physical removal, the worker waits for the original device's completed kernel
remove event, uses the still-pinned original reference to clear that one retained
slot, and verifies disappearance before binding again. Other exports are left
running. Reconnection at the same port, movement to another port and normal
present-device release do not require reloading a shared module.
If the worker is killed, a bind cannot be verified, removal events are lost, or
an older installation left a retained slot, that slot has no proven lifetime
reference. The worker reports an error and refuses to detach a new local device
or attempt absent-slot recovery. Stop sharing while the original remains present;
if that cannot clear the slot, a host reboot is the supported recovery. This
exceptional recovery interrupts the host, so schedule it yourself; the manager
never reboots it or reloads USB modules automatically. Graceful service stop
releases managed bindings before dropping the references.
Without a serial number, the vendor/product and original bus ID must match;
the manager will not guess which identical dongle to bind. Duplicate serial
numbers are rejected as ambiguous. USB hubs and mass-storage devices, including
composite devices with a storage interface, are excluded. So are USB network
adapters: on many mini PCs one is the management link of the host.
**Stop sharing** removes one saved selection and waits for confirmed release.
A cleanup error or timeout is reported instead of claiming that eject succeeded.
**Disable server** stops the service and releases its
managed exports, retaining selections for the next enable. Devices already
bound by another USB/IP setup are not adopted or unbound by this manager.
Native USB/IP unbind reprobes the device so its normal local driver can return.
## Transport and authentication
USB/IP has no built-in authentication or encryption. The generated server unit
uses systemd `PrivateNetwork=yes`: `usbipd --ipv4 --tcp-port 3240` and its
Python protocol gate run in an isolated network namespace. There is **no USB/IP TCP
listener in the host network namespace**, and this feature does not open a
firewall port. Running the manager's `serve` command outside a private network
namespace is rejected before spawning a listener.
The gate exposes `/run/proxmenux-usbip-server/usbip.sock` to the dedicated
`proxmenux-usbip` group (0660), inside a root-owned 0750 directory. For each native
DEVLIST and IMPORT, the gate checks the saved selection,
verified ownership, current USB identity, driver and sysfs incarnation. It checks
again before releasing a successful import reply; an unselected export bound by
another setup cannot bypass selection by requesting its bus ID directly. Control
requests have bounded time, memory and connection counts. Accepted URB streams
retain full-duplex transfer, half-close and backpressure without an idle timeout.
Root alone can read or change the managed device/configuration state.
A separate group-readable
catalog contains only the selected USB device metadata.
Before enabling the server, choose **Authorize a client SSH public key** and
supply the path to a dedicated client's `.pub` file already copied to the server.
This creates a local system account `proxmenux-usbip` with a disabled password,
no administrative group membership, and a root-owned home and `authorized_keys`.
Each managed key uses OpenSSH `restrict` and a fixed forced command. The command
accepts only `catalog` (read selected devices) and `stream` (connect the one USB/IP
Unix socket). Shell commands, PTY, agent/X11 forwarding and TCP/Unix forwarding
are prohibited. This does not use or modify Proxmox's cluster-wide root keys,
root `authorized_keys`, or SSH server settings. A conflicting pre-existing
account/home is rejected rather than adopted. Authorize keys before starting
the server; `useradd` and an existing OpenSSH server are required.
The client holds its loopback TCP listening socket continuously, then launches
an SSH `stream` session for each connection. It does not release a port probe
and later ask SSH to bind the same port. Unknown or changed host keys and wrong
client keys fail closed. Create a dedicated key, not one used for root access.
Anyone with that key can access **all selected USB/IP exports**; it is not a
per-device authorization policy. Local users of the client can also connect to
the loopback port, so use trusted clients. To revoke a client, remove its managed
line from `/var/lib/proxmenux-usbip/.ssh/authorized_keys` and terminate its active
connections; deleting a key does not disconnect an existing SSH session.
Old configurations using root keys do not silently keep root access: clients
now connect only as `proxmenux-usbip`. Authorize a separate key on the server and
replace the saved client connection if it previously referenced a root key.
## Linux VM/client
Run the client **inside the Linux VM that needs the device**. Connecting it to
a Proxmox node alone does not make that device migrate with a VM. A supported
Linux kernel must provide `vhci-hcd`; the server needs `usbip-host`. Proxmox
kernel packages normally provide these modules, but activation fails visibly
if they are missing. No out-of-tree kernel modules are installed.
The client can use the menu when ProxMenux is installed, or the standalone
standard-library Python manager. On a Debian Linux guest, install the packages
and copy `scripts/devices/usbip_manager.py` from the reviewed ProxMenux checkout:
```sh
apt-get install usbip openssh-client kmod
install -D -m 0755 usbip_manager.py /usr/local/share/proxmenux/scripts/devices/usbip_manager.py
```
Generate a dedicated SSH client key (for example `/root/.ssh/id_usbip`) and
authorize its public key through the server menu. Verify the server host-key
fingerprint through a trusted channel and install it in the client's root
`known_hosts` file. Do not attempt an interactive login: the account intentionally
rejects a shell. SSH config aliases and `ProxyJump` settings are not used; enter
the actual address and port.
Then choose **Connect a remote USB device** and provide the server address,
SSH port and absolute path to an existing private key (0400 or 0600). The menu
authenticates and lists the server's configured exports before saving a client.
Choose an unused local port for each device (33240 by default).
Equivalent standalone commands:
```sh
MANAGER=/usr/local/share/proxmenux/scripts/devices/usbip_manager.py
python3 "$MANAGER" remote --host 192.0.2.10 --ssh-port 22 --key /root/.ssh/id_usbip
# Substitute the export ID returned by the server:
python3 "$MANAGER" add-import --host 192.0.2.10 --ssh-port 22 --key /root/.ssh/id_usbip --export-id abcdef123456 --local-port 33240
python3 "$MANAGER" status
```
The client has an enabled systemd service per device. It reconnects the SSH
tunnel and reattaches the device after a network interruption or restart. On
each new attach it resolves the **saved export ID** to the server's current bus
ID; physical port movement is resolved only after confirmed cleanup of the old
slot. The client keeps an ownership
record of the exact imported kernel port, local bus ID and remote endpoint;
cleanup detaches only a matching owned import. Removing a connection disables
its service, releases its device and removes its saved configuration.
Only **one client at a time** can attach a physical USB device. A device already
in use by another client may be listed as exported, but the kernel rejects a
second attach; the client reports the error and waits. Applications must handle
USB disconnect/reconnect themselves. A brief network interruption can still
reset the USB device and interrupt a Zigbee coordinator, printer or Bluetooth
session; this is not transparent USB high availability.
Unprivileged LXC, Home Assistant OS and non-Linux clients require their own
kernel/device permissions or add-on integration. This feature does not change
LXC privileges, edit VM passthrough settings or deploy HAOS add-ons. A standard
addon that expects raw USB/IP TCP also needs the SSH transport configured; it
cannot directly connect to this server's isolated daemon.
## Files and checks
- Root-only configuration: `/etc/proxmenux/usbip/config.json` (0600).
- Owned server unit: `proxmenux-usbip-server.service`.
- Owned client units: `proxmenux-usbip-client-<id>.service`.
- Server ownership/status: `/run/proxmenux-usbip-server/`.
- Client ownership/status: `/run/proxmenux-usbip/`, independent of server cleanup.
- Menu actions and package installations use the ProxMenux journal when present.
Validation includes fake sysfs/USB commands for identity and ownership, service
rollback and quoting, malformed catalogs, credential failures and reconnects.
The Linux CI also verifies generated units and exercises actual namespace
isolation and restricted SSH sessions with native USB/IP control messages.
Protocol socket tests cover binary transfers, malformed requests, selection
changes, foreign exports and replaced device objects. Lifetime tests require a
verified pin and a matching completed kernel removal event before slot recovery.
The kernel regression lab is deliberately opt-in and requires a fresh, disposable
QEMU Linux VM with usbip, socat and the dummy_hcd/libcomposite/usbip-host/vhci-hcd
modules. Never run it on a production host. In that VM, from the checkout:
```sh
sudo unshare --net sh -c 'ip link set lo up; python3 -B .github/scripts/check_usbip_kernel.py --disposable-vm'
```
It creates two virtual ACM gadgets, performs 20 physical unplug/replug cycles,
rejects an unselected same-port replacement, reimports the original and confirms
local-driver restoration. An independent native USB/IP serial transfer must keep
working during the cycles. The lab passed on Debian 13 / Linux 6.12.115; actual
hardware and guest-driver compatibility still depends on the deployment.
The companion service lab must run in a separate fresh disposable QEMU VM:
```sh
sudo python3 -B .github/scripts/check_usbip_services.py --disposable-vm
```
It installs the actual generated server/client units and a dedicated SSH key
inside that VM, transfers native serial data in both directions through restricted
SSH, checks three automatic reconnects with an independent connection alive, and
verifies synchronous stop-sharing and disable cleanup. Destroy the VM afterwards.
The lifetime contract is based on [usbfs open/release references](https://github.com/torvalds/linux/blob/v6.12/drivers/usb/core/devio.c),
[USB/IP match/rebind](https://github.com/torvalds/linux/blob/v6.12/drivers/usb/usbip/stub_main.c)
and [completed stub disconnect](https://github.com/torvalds/linux/blob/v6.12/drivers/usb/usbip/stub_dev.c).
A sysfs pathname alone is never sufficient authority for absent-slot rebind.
Protocol and transport references:
[Linux USB/IP tools](https://github.com/torvalds/linux/tree/master/tools/usb/usbip),
[Debian usbip manual](https://manpages.debian.org/trixie/usbip/usbip.8.en.html),
[OpenSSH authorized_keys restrictions](https://man.openbsd.org/sshd#AUTHORIZED_KEYS_FILE_FORMAT),
[systemd PrivateNetwork](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#PrivateNetwork=).
+96
View File
@@ -184,6 +184,7 @@
"A tunneling daemon by Cloudflare that safely exposes your web servers into the internet.": "Ein Tunnel-Daemon von Cloudflare, der Ihre Webserver sicher im Internet aussetzt.",
"A unified email and collaboration server.": "Ein einheitlicher E-Mail- und Kollaborationsserver.",
"A unified platform for logs, metrics and traces.": "Eine einheitliche Plattform für Logs, Metriken und Traces.",
"A validating, recursive DNS resolver for your private network.": "Ein validierender, rekursiver DNS-Resolver für Ihr privates Netzwerk.",
"A versatile file conversion tool that supports multiple formats.": "Ein vielseitiges Dateikonvertierungstool, das mehrere Formate unterstützt.",
"A visual tool for exploring and documenting database schemas.": "Ein visuelles Werkzeug zum Erkunden und Dokumentieren von Datenbankschemata.",
"A web GUI client of Project V which supports VMess, VLESS, SS, SSR, Trojan, Tuic and Juicity protocols": "Ein Web-GUI-Client von Project V, der die Protokolle VMess, VLESS, SS, SSR, Trojan, Tuic und Juicity unterstützt",
@@ -245,6 +246,7 @@
"Aborted": "Abgebrochen",
"About to restore": "Wird gerade wiederhergestellt",
"Absolute directory path to use as backup target:": "Absoluter Verzeichnispfad zur Verwendung als Sicherungsziel:",
"Absolute path of the client SSH private key:": "Absoluter Pfad des privaten SSH-Schlüssels des Clients:",
"Absolute path to a file or directory you want backed up:": "Absoluter Pfad zu einer Datei oder einem Verzeichnis, die/das Sie sichern möchten:",
"Acceleration": "Beschleunigung",
"Acceleration configuration cancelled": "Beschleunigungskonfiguration abgesagt",
@@ -256,6 +258,7 @@
"Acceleration for llama.cpp": "Beschleunigung für llama.cpp",
"Accept routes from other nodes?": "Routen von anderen Knoten akzeptieren?",
"Accept this host monitoring profile?": "Akzeptieren Sie dieses Host Monitoring Profil?",
"Access Movistar and O2 Cloud from WebDAV clients and backup tools.": "Zugriff auf die Movistar- und O2-Cloud über WebDAV-Clients und Backup-Werkzeuge.",
"Access Scope:": "Zugriffsbereich:",
"Access bridge": "Zugangsbrücke",
"Access bridge for Immich": "Access Bridge für Immich",
@@ -410,6 +413,7 @@
"After the reboot, you will only be able to access the Proxmox host via:": "Nach dem Neustart können Sie nur noch auf den Proxmox-Host zugreifen über:",
"After this LXC → VM switch, reboot the host so the new binding state is applied cleanly.": "Starten Sie nach diesem Wechsel von LXC → VM den Host neu, damit der neue Bindungsstatus sauber angewendet wird.",
"Agentless monitoring and observability platform.": "Agentenlose Plattform für Monitoring und Observability.",
"AirDC++ administrator": "AirDC++-Administrator",
"Airsonic Advanced web interface": "Airsonic Advanced Web-Schnittstelle",
"Airsonic-advanced is a free, web-based media streamer, providing ubiquitious access to your music. Use it to share your music with friends, or to listen to your own music while at work. You can stream to multiple players simultaneously, for instance to one player in your kitchen and another in your living room.": "Airsonic-advanced ist ein kostenloser, webbasierter Medienstreamer, der ubiquitious Zugang zu Ihrer Musik bietet. Verwenden Sie es, um Ihre Musik mit Freunden zu teilen oder Ihre eigene Musik während der Arbeit zu hören. Sie können zu mehreren Spielern gleichzeitig streamen, zum Beispiel zu einem Spieler in Ihrer Küche und einem anderen in Ihrem Wohnzimmer.",
"Aliases added to .bashrc": "Aliase wurden zu .bashrc hinzugefügt",
@@ -598,11 +602,15 @@
"Attention: Removing the subscription banner may cause issues in the web interface after a future update.": "Achtung: Das Entfernen des Abonnementbanners kann nach einem zukünftigen Update zu Problemen in der Weboberfläche führen.",
"Audacity is an easy-to-use, multi-track audio editor and recorder. Developed by a group of volunteers as open source.": "Audacity ist ein einfach zu bedienender, mehrspuriger Audio-Editor und Recorder. Entwickelt von einer Gruppe von Freiwilligen als Open Source.",
"Audio device directory": "Audiogeräteverzeichnis",
"Audio recording and mixing in your browser": "Audioaufnahme und -mischung im Browser",
"Audiobookshelf is a self-hosted audiobook and podcast server.": "Audiobookshelf ist ein selbst gehosteter Hörbuch- und Podcast-Server.",
"Audit completed. Press Enter to continue...": "Prüfung abgeschlossen. Drücken Sie die Eingabetaste, um fortzufahren...",
"Audit socket disabled or not required": "Audit-Socket deaktiviert oder nicht erforderlich",
"Auth key is required.": "Authentifizierungsschlüssel ist erforderlich.",
"Auth:": "Authentifizierung:",
"Authelia Web UI": "Authelia Web-Benutzeroberfläche",
"Authelia administrator": "Authelia-Administrator",
"Authelia session cookie domain for this portal (for example example.com)": "Authelia Sitzungscookie-Domäne für dieses Portal (z. B. example.com)",
"Authentication": "Authentifizierung",
"Authentication & Security": "Authentifizierung und Sicherheit",
"Authentication Error": "Authentifizierungsfehler",
@@ -612,6 +620,8 @@
"Authentication:": "Authentifizierung:",
"Authorization failed": "Die Autorisierung ist fehlgeschlagen",
"Authorization successful": "Autorisierung erfolgreich",
"Authorize a client SSH public key": "Öffentlichen SSH-Schlüssel eines Clients autorisieren",
"Authorize a dedicated client public key on the server first. The restricted USB/IP account cannot run a shell or forward other sockets. Verify the server host key before connecting; unknown keys are rejected.": "Autorisiere zuerst einen eigenen öffentlichen Clientschlüssel auf dem Server. Das eingeschränkte USB/IP-Konto kann keine Shell starten oder andere Sockets weiterleiten. Prüfe vor dem Verbinden den Hostschlüssel des Servers; unbekannte Schlüssel werden abgelehnt.",
"Authorize this key on the server": "Autorisieren Sie diesen Schlüssel auf dem Server",
"Authorize via 'pct exec' (Borg server is an LXC on a PVE host I can SSH into)": "Autorisieren über „pct exec“ (Borg-Server ist ein LXC auf einem PVE-Host, in den ich SSH einbinden kann)",
"Authorized": "Autorisiert",
@@ -642,6 +652,7 @@
"Available PVE Version": "Verfügbare PVE-Version",
"Available Shares:": "Verfügbare Aktien:",
"Available action": "Verfügbare Aktion",
"Available applications: {count}": "Verfügbare Anwendungen: {count}",
"Available archives:": "Verfügbare Archive:",
"Available disks detected.": "Verfügbare Festplatten erkannt.",
"Available host backups:": "Verfügbare Host-Backups:",
@@ -873,6 +884,7 @@
"Cannot write the image archive to {storage}. Check storage access and mount status.": "Das Bildarchiv kann nicht in {storage} geschrieben werden. Überprüfen Sie den Speicherzugriff und den Bereitstellungsstatus.",
"Capabilities cannot be kept and all dropped at the same time": "Fähigkeiten können nicht gehalten werden und alle gleichzeitig fallen gelassen werden",
"Catalog options": "Katalogoptionen",
"Catalog refresh unavailable; using the local catalog.": "Der Katalog konnte nicht aktualisiert werden; der lokale Katalog wird verwendet.",
"Category": "Kategorie",
"Caution: Maximum mode generates more heat.": "Achtung: Im Maximalmodus entsteht mehr Wärme.",
"Central server for file and image backups.": "Zentraler Server für Datei- und Bildsicherungen.",
@@ -1159,6 +1171,7 @@
"Compressing": "Komprimieren",
"Compression": "Komprimierung",
"Compression Tools": "Komprimierungswerkzeuge",
"Computer-aided design and drafting in your browser": "Computergestütztes Konstruieren und technisches Zeichnen im Browser",
"Concise output of logical volumes": "Übersichtliche Ausgabe logischer Volumes",
"Concise output of physical volumes": "Übersichtliche Ausgabe physischer Datenträger",
"Concise output of volume groups": "Übersichtliche Ausgabe von Volumengruppen",
@@ -1289,6 +1302,7 @@
"Conflicting utilities removed": "Widersprüchliche Dienstprogramme entfernt",
"Connect Zigbee devices to MQTT with a browser-based setup interface.": "Verbinde Zigbee-Geräte mit MQTT über eine webbasierte Einrichtungsoberfläche.",
"Connect a Coral Accelerator and try again.": "Schließen Sie einen Coral Accelerator an und versuchen Sie es erneut.",
"Connect a remote USB device": "Entferntes USB-Gerät verbinden",
"Connect it, or remove it from the container in Proxmox (Resources), and run the recovery again.": "Verbinden Sie es oder entfernen Sie es aus dem Container in Proxmox (Ressourcen) und führen Sie die Wiederherstellung erneut aus.",
"Connect your devices and users together in your own secure virtual private network.": "Verbinden Sie Ihre Geräte und Benutzer in Ihrem eigenen sicheren virtuellen privaten Netzwerk.",
"Connect your devices into a secure WireGuard®-based overlay network with SSO, MFA and granular access controls.": "Verbinden Sie Ihre Geräte mit einem sicheren WireGuard®-basierten Overlay-Netzwerk mit SSO, MFA und granularen Zugriffskontrollen.",
@@ -1393,6 +1407,7 @@
"Controller + NVMe": "Controller + NVMe",
"Controller + NVMe assignment will be written now and become active after host reboot.": "Die Controller + NVMe-Zuweisung wird jetzt geschrieben und wird nach dem Neustart des Hosts aktiv.",
"Controller + NVMe passthrough requires machine type q35. Skipping controller assignment.": "Controller + NVMe-Passthrough erfordern Maschinentyp q35. Controller-Zuweisung wird übersprungen.",
"Controller path on the Proxmox host; prefer /dev/serial/by-id/...": "Controller-Pfad auf dem Proxmox-Host;lieber /dev/serial/by-id/...",
"Controller/NVMe Conflict Policy": "Controller-/NVMe-Konfliktrichtlinie",
"Controller/NVMe already present in VM config": "Controller/NVMe bereits in der VM-Konfiguration vorhanden",
"Controller/NVMe already present in VM config (%s)": "Controller/NVMe ist bereits in der VM-Konfiguration vorhanden (%s)",
@@ -1927,6 +1942,7 @@
"Dgraph": "Dgraph",
"Diff: current system vs backup (--- system +++ backup)": "Unterschied: aktuelles System vs. Backup (--- System +++ Backup)",
"Different host. Backup from:": "Anderer Gastgeber. Backup von:",
"Direct Connect file sharing with a web interface": "Direct-Connect-Dateifreigabe mit Weboberfläche",
"Direct conversion completed for container": "Direkte Konvertierung für Container abgeschlossen",
"Directory Exists": "Verzeichnis existiert",
"Directory Not Empty": "Verzeichnis nicht leer",
@@ -1949,12 +1965,14 @@
"Directus administrator": "Directus-Administrator",
"Disable NIC Offloading (Intel e1000e)": "NIC-Offloading deaktivieren (Intel e1000e)",
"Disable Secure Boot in the UEFI firmware and run the installer again. Nothing has been changed.": "Deaktivieren Sie Secure Boot in der UEFI-Firmware und führen Sie das Installationsprogramm erneut aus. Es wurde nichts geändert.",
"Disable USB/IP server": "USB/IP-Server deaktivieren",
"Disable autostart on conflicting VM": "Deaktivieren Sie den Autostart auf in Konflikt stehenden VMs",
"Disable autostart on one VM to avoid startup conflicts.": "Deaktivieren Sie den Autostart auf einer VM, um Startkonflikte zu vermeiden.",
"Disable job": "Job deaktivieren",
"Disable kernel audit messages (optional but recommended):": "Deaktivieren Sie Kernel-Überwachungsmeldungen (optional, aber empfohlen):",
"Disable onboot on affected VM(s)/CT(s)": "Onboot auf betroffenen VM(s)/CT(s) deaktivieren",
"Disable portmapper/rpcbind": "Portmapper/rpcbind deaktivieren",
"Disable the server and release all USB devices managed by ProxMenux? Saved selections are kept for the next enable.": "Den Server deaktivieren und alle von ProxMenux verwalteten USB-Geräte freigeben? Die gespeicherte Auswahl bleibt für die nächste Aktivierung erhalten.",
"Disabled": "Deaktiviert",
"Disabling High Availability services...": "Hochverfügbarkeitsdienste werden deaktiviert...",
"Disabling ZFS autotrim applied by ProxMenux...": "Deaktivieren der von ProxMenux angewendeten ZFS-Autotrim-Funktion ...",
@@ -2187,6 +2205,7 @@
"Enable Remote Desktop (RDP) before disabling the virtual display.": "Aktivieren Sie Remote Desktop (RDP), bevor Sie die virtuelle Anzeige deaktivieren.",
"Enable SSD emulation for this disk?": "SSD-Emulation für diese Festplatte aktivieren?",
"Enable TCP BBR/Fast Open control": "Aktivieren Sie die TCP-BBR/Fast-Open-Steuerung",
"Enable USB/IP server": "USB/IP-Server aktivieren",
"Enable VA-API transcoding and HDR10/Dolby Vision to SDR tone mapping": "Aktivieren von VA-API Transcoding und HDR10/Dolby Vision to SDR Tone Mapping",
"Enable VA-API, hardware encoding and OpenCL tone mapping in Jellyfin": "Aktivieren Sie VA-API, Hardware-Codierung und OpenCL-Tone-Mapping in Jellyfin",
"Enable VFIO IOMMU support": "VFIO IOMMU-Unterstützung aktivieren",
@@ -3200,6 +3219,7 @@
"If pvesm path returned a DEVICE (LVM):": "Wenn pvesm path ein GERÄT (LVM) zurückgegeben hat:",
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Wenn pvesm path ein VERZEICHNIS (ZFS/BTRFS) zurückgegeben hat:",
"If repositories error:": "Bei Repository-Fehler:",
"If the USB/IP service stops unexpectedly, stop sharing while the device is still connected to release it. In rare cases only a host reboot releases it.": "Wenn der USB/IP-Dienst unerwartet stoppt, beenden Sie die Freigabe, solange das Gerät noch angeschlossen ist. In seltenen Fällen ist es erst nach einem Neustart des Hosts wieder verfügbar.",
"If the container had already been changed, its previous native backup is restored. Shared host directories are not reverted. The disks of the failed attempt are removed when the cleanup succeeds.": "Wenn der Container bereits geändert wurde, wird sein vorheriges natives Backup wiederhergestellt. Freigegebene Hostverzeichnisse werden nicht zurückgesetzt. Die Festplatten des fehlgeschlagenen Versuchs werden entfernt, wenn die Bereinigung erfolgreich ist.",
"If the host freezes, remove hostpci entries from": "Wenn der Host einfriert, entfernen Sie die Hostpci-Einträge aus",
"If the image channel has a new version, the CT is stopped, backed up and verified, and replaced with the new image to update the container. If anything fails, the backup is restored.": "Wenn der Image-Kanal eine neue Version hat, wird CT gestoppt, gesichert und überprüft und durch das neue Image ersetzt, um den Container zu aktualisieren. Wenn etwas fehlschlägt, wird das Backup wiederhergestellt.",
@@ -3340,6 +3360,7 @@
"Initial Stirling-PDF account": "Erstes Stirling-PDF-Konto",
"Initial Tandoor administrator": "Initial Tandoor Administrator",
"Initial Umami administrator": "Erster Administrator für Umami",
"Initial Z-Wave JS UI admin password": "Ursprüngliches Z-Wave JS UI-Administratorkennwort",
"Initial administrator created:": "Erster Administrator erstellt:",
"Initial administrator user": "Erster Administrator",
"Initializing Borg repository if needed...": "Initialisierung des Borg-Repositorys bei Bedarf ...",
@@ -3393,6 +3414,7 @@
"Install server packages inside CT:": "Installieren Sie Serverpakete in CT:",
"Install terminal multiplexers": "Installieren Sie Terminal-Multiplexer",
"Install the Edge TPU runtime (libedgetpu1-std)": "Installieren Sie die Edge TPU-Laufzeit (libedgetpu1-std).",
"Install the USB/IP dependencies from the configured Debian repositories?": "USB/IP-Abhängigkeiten aus den konfigurierten Debian-Repositories installieren?",
"Install this image?": "Installieren Sie dieses Bild?",
"Install with Cloud-Init script": "Installation mit Cloud-Init-Skript",
"Install with ISO from UUP Dump": "Mit ISO von UUP Dump installieren",
@@ -3525,6 +3547,7 @@
"Interface MTU": "Schnittstellen-MTU",
"Interface Names (persistent)": "Schnittstellennamen (persistent)",
"Interface Type": "Schnittstellentyp",
"Interface design and prototyping in your browser": "Oberflächendesign und Prototyping im Browser",
"Interface names will return to default systemd behavior.": "Schnittstellennamen kehren zum Standardverhalten von systemd zurück.",
"Interface type:": "Schnittstellentyp:",
"Interfaces configured": "Schnittstellen konfiguriert",
@@ -3582,6 +3605,7 @@
"Invalid check package:": "Ungültiges Kontrollpaket:",
"Invalid configuration path:": "Ungültiger Konfigurationspfad:",
"Invalid consume/export volumes": "Ungültige Verbrauchs-/Ausfuhrmengen",
"Invalid container device GID": "Ungültige Geräte-GID im Container",
"Invalid container path:": "Ungültiger Containerpfad:",
"Invalid credential file path:": "Ungültiger credential-Dateipfad:",
"Invalid declarative entrypoint": "Ungültiger deklarativer Eingangspunkt",
@@ -3740,6 +3764,7 @@
"Jupyter Lab (token only)": "Jupyter Lab (nur Token)",
"JupyterLab": "JupyterLab",
"JupyterLab access token": "Zugriffstoken für JupyterLab",
"KDE's twin-panel file manager in a browser-based desktop.": "Der Twin-Panel-Dateimanager von KDE in einem browserbasierten Desktop.",
"KDF:": "KDF:",
"KROMA": "KROMA",
"KVM MSR options added to /etc/modprobe.d/kvm.conf": "KVM-MSR-Optionen zu /etc/modprobe.d/kvm.conf hinzugefügt",
@@ -3787,12 +3812,14 @@
"KiCad - A Cross Platform and Open Source Electronics Design Automation Suite.": "KiCad - Eine Cross-Plattform und Open Source Electronics Design Automation Suite.",
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "Kimai hat kein Standardkonto. Öffnen Sie eine Shell im Container mit: pct enter {main_vmid}",
"Kimai is a professional grade time-tracking application, free and open-source.": "Kimai ist eine professionelle Time-Tracking-Anwendung, kostenlos und Open-Source.",
"KitchenOwl": "KitchenOwl",
"Kometa is a powerful tool designed to give you complete control over your media libraries. With Kometa, you can take your customization to the next level, with granular control over metadata, collections, overlays, and much more.": "Kometa ist ein leistungsstarkes Tool, das Ihnen die vollständige Kontrolle über Ihre Medienbibliotheken gibt. Mit Kometa können Sie Ihre Anpassung auf die nächste Ebene bringen, mit granularer Kontrolle über Metadaten, Sammlungen, Overlays und vielem mehr.",
"Kometa reads its configuration from /config/config.yml and the container only ships /config/config.yml.template. Copy the template to config.yml, fill in the required Plex and TMDb connections, then restart the container.": "Kometa liest seine Konfiguration aus /config/config.yml und der Container liefert nur /config/config.yml.template. Kopieren Sie die Vorlage auf config.yml, füllen Sie die required Plex und TMDb-Verbindungen aus und starten Sie dann den Container neu.",
"Komga is a media server for your comics, mangas, BDs, magazines and eBooks.": "Komga ist ein Medienserver für Ihre Comics, Mangas, BDs, Magazine und eBooks.",
"Kopia Web UI": "Kopia-Weboberfläche",
"Kopia Web UI login": "Anmeldung an der Kopia-Weboberfläche",
"Krita is a professional FREE and open source painting program. It is made by artists that want to see affordable art tools for everyone.": "Krita ist ein professionelles kostenloses und Open-Source-Malprogramm. Es wird von Künstlern gemacht, die erschwingliche Kunstwerkzeuge für alle sehen wollen.",
"Krusader Web UI": "Krusader Web-Benutzeroberfläche",
"LAN access to the kept containers (stack configuration incomplete):": "LAN-Zugriff auf die aufbewahrten Container (Stack-Konfiguration unvollständig):",
"LAN address applied to the application URLs": "LAN-Adresse für die Anwendungs-URLs",
"LLDAP": "LLDAP",
@@ -3873,9 +3900,11 @@
"Line to paste (single line, including \"command=...\" prefix):": "Einzufügende Zeile (einzelne Zeile, einschließlich „command=…“-Präfix):",
"LinkStack": "LinkStack",
"Linux Installation Options": "Linux-Installationsoptionen",
"Linux guest setup and migration notes": "Hinweise zur Einrichtung und Migration von Linux-Gästen",
"Linux/Mac path:": "Linux/Mac-Pfad:",
"LinuxServer Jellyfin with optional GPU passthrough": "LinuxServer Jellyfin mit optionalem GPU-Passthrough",
"LinuxServer MariaDB requires a user, database and password": "LinuxServer MariaDB requires ein Benutzer, Datenbank und Passwort",
"LinuxServer Nextcloud with MariaDB and Redis": "LinuxServer Nextcloud mit MariaDB und Redis",
"List Available Disks": "Verfügbare Festplatten auflisten",
"List IOMMU group mapping": "IOMMU-Gruppenzuordnung auflisten",
"List NVMe devices": "NVMe-Geräte auflisten",
@@ -4020,6 +4049,7 @@
"Manage OCI stack": "Verwalten des OCI-Stacks",
"Manage PBS encryption keyfile": "PBS-Verschlüsselungsschlüsseldatei verwalten",
"Manage Secure Gateway": "Secure Gateway verwalten",
"Manage a Z-Wave network from a web dashboard and WebSocket gateway.": "Verwalten Sie ein Z-Wave-Netzwerk über ein Web-Dashboard und ein WebSocket-Gateway.",
"Manage and inspect VM disk images": "Verwalten und überprüfen Sie VM-Festplatten-Images",
"Manage custom backup paths": "Benutzerdefinierte Sicherungspfade verwalten",
"Manage custom paths (add / remove your folders)": "Benutzerdefinierte Pfade verwalten (Ordner hinzufügen/entfernen)",
@@ -4029,6 +4059,7 @@
"Manage local backup target": "Lokales Backup-Ziel verwalten",
"Manage private image registries.\nSaved credentials let ProxMenux access your private images.": "Private Bildregister verwalten.\nGespeicherte Anmeldeinformationen ermöglichen ProxMenux den Zugriff auf Ihre privaten Bilder.",
"Manage registry accounts as root on the Proxmox node.": "Registrierungskonten als Root auf dem Proxmox-Knoten verwalten.",
"Manage teams of AI agents from a web dashboard.": "Verwalte Teams von KI-Agenten über ein Web-Dashboard.",
"Managed disks must have backup enabled and a valid size": "Managed Disks müssen Backup aktiviert und eine gültige Größe haben",
"Managed public route include is missing": "Die Konfigurationsdatei für die verwalteten öffentlichen Routen fehlt",
"Managed public route installation failed": "Die verwalteten öffentlichen Routen konnten nicht eingerichtet werden",
@@ -4134,6 +4165,7 @@
"Monitoring": "Überwachung",
"Monitoring & Analytics": "Überwachung und Auswertung",
"Most common cause: the archive is corrupted (interrupted write, partial copy, or storage issue).": "Häufigste Ursache: Das Archiv ist beschädigt (unterbrochener Schreibvorgang, teilweises Kopieren oder Speicherproblem).",
"Motion graphics and compositing in your browser": "Motion-Design und Compositing im Browser",
"Mount Added Successfully:": "Mount erfolgreich hinzugefügt:",
"Mount CIFS share:": "CIFS-Freigabe bereitstellen:",
"Mount Configuration Summary:": "Zusammenfassung der Mount-Konfiguration:",
@@ -4293,6 +4325,7 @@
"NVIDIA (CUDA; official GPU image)": "NVIDIA (CUDA; offizielles GPU-Bild)",
"NVIDIA (NVDEC/CUDA)": "NVIDIA (NVDEC/CUDA)",
"NVIDIA (NVENC/NVDEC)": "NVIDIA (NVENC/NVDEC)",
"NVIDIA (Selkies rendering and NVENC)": "NVIDIA (Selkies-Rendering und NVENC)",
"NVIDIA Actions": "NVIDIA-Aktionen",
"NVIDIA CPU hiding already configured": "NVIDIA-CPU-Ausblendung bereits konfiguriert",
"NVIDIA Container Toolkit": "NVIDIA Container Toolkit",
@@ -4376,6 +4409,7 @@
"Name or part of the option or of the application": "Name oder Teil der Option oder der Anwendung",
"Name:": "Name:",
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Benannte Konten benötigen einen privaten Modus. Stoppen Sie den Container, setzen Sie public: false in /config/config.js, starten Sie ihn erneut und erstellen Sie jeden Benutzer mit: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>",
"Native Borg is unavailable. Install the native borgbackup package on this host to use Borg backups.": "Natives Borg ist nicht verfügbar. Installieren Sie das native Paket borgbackup auf diesem Host, um Borg-Backups zu verwenden.",
"Needed:": "Erforderlich:",
"Needs": "Benötigt",
"Neither /etc/kernel/cmdline nor /etc/default/grub found.": "Weder /etc/kernel/cmdline noch /etc/default/grub gefunden.",
@@ -4434,6 +4468,8 @@
"New Search": "Neue Suche",
"New VM:": "Neue VM:",
"New Virtual Machine": "Neue virtuelle Maschine",
"New applications ({count})": "Neue Anwendungen ({count})",
"New applications since your last visit: {count}": "Neue Anwendungen seit Ihrem letzten Besuch: {count}",
"New backup job": "Neuer Sicherungsauftrag",
"New backups on this host will be unencrypted until a new keyfile is set up.": "Neue Backups auf diesem Host werden unverschlüsselt sein, bis eine neue Schlüsseldatei eingerichtet wird.",
"New image compatible:": "Neues Bild kompatibel:",
@@ -4449,6 +4485,7 @@
"Next Step Required": "Nächster Schritt erforderlich",
"Next Steps:": "Nächste Schritte:",
"Next step: stop that VM first, then run": "Nächster Schritt: Stoppen Sie zuerst die VM und führen Sie sie dann aus",
"Nextcloud Web UI": "Nextcloud-Weboberfläche",
"Nextcloud configuration cancelled": "Nextcloud-Konfiguration gestrichen",
"Nextcloud gives you access to all your files wherever you are.": "Nextcloud bietet Ihnen Zugriff auf alle Ihre Dateien, wo immer Sie sind.",
"Nextcloud volume size in GB": "Nextcloud Volumengröße in GB",
@@ -4623,6 +4660,7 @@
"No duplicate IP addresses": "Keine doppelten IP-Adressen",
"No duplicate repositories found": "Keine doppelten Repositorys gefunden",
"No eligible Controller/NVMe devices remain after SR-IOV filtering. Skipping.": "Nach der SR-IOV-Filterung bleiben keine berechtigten Controller/NVMe-Geräte übrig. Überspringen.",
"No eligible USB devices found. Hubs, mass storage and network adapters are excluded.": "Keine geeigneten USB-Geräte gefunden. Hubs, Massenspeicher und Netzwerkadapter sind ausgeschlossen.",
"No eligible controllers remain after SR-IOV filtering.": "Nach der SR-IOV-Filterung bleiben keine berechtigten Controller übrig.",
"No encryption key is stored on this host. Choose how to set one up:": "Auf diesem Host ist kein Verschlüsselungsschlüssel gespeichert. Wählen Sie aus, wie Sie eines einrichten möchten:",
"No exportable VM disks were found (CD-ROM/cloud-init are excluded).": "Es wurden keine exportierbaren VM-Festplatten gefunden (CD-ROM/Cloud-Init sind ausgeschlossen).",
@@ -4707,6 +4745,7 @@
"No self-test log available for": "Kein Selbsttestprotokoll verfügbar für",
"No server IP or hostname provided.": "Keine Server-IP oder Hostname angegeben.",
"No share access test succeeded with guest authentication.": "Bei der Gastauthentifizierung war kein Freigabezugriffstest erfolgreich.",
"No shared devices are available on this server.": "Auf diesem Server sind keine freigegebenen Geräte verfügbar.",
"No shared media content.": "Keine geteilten Medieninhalte.",
"No shared mount detected. Applying standard local access.": "Kein gemeinsamer Mount erkannt. Anwenden des standardmäßigen lokalen Zugriffs.",
"No shares configured.": "Keine Freigaben konfiguriert.",
@@ -4896,6 +4935,8 @@
"Open the page of an application in the menu": "Die Seite einer Anwendung im Menü öffnen",
"Open the web address and create the first account: the daemon registers by itself and starts the first scan.": "Öffne die Webadresse und erstelle das erste Konto: Der Daemon registriert sich selbst und startet den ersten Scan.",
"Open the web address and create the password of the akadmin user in the first-run setup.": "Öffnen Sie die Webadresse und erstellen Sie im ersten Setup das Passwort des akadmin-Benutzers.",
"Open the web address and follow KitchenOwl’s onboarding to create the first account; no default account is configured.": "Öffnen Sie die Webadresse und befolgen Sie die Onboarding-Anweisungen von KitchenOwl, um das erste Konto zu erstellen. Es ist kein Standardkonto konfiguriert.",
"Open the web dashboard and link your Movistar/O2 account using its SMS flow.": "Öffnen Sie das Web-Dashboard und verknüpfen Sie Ihr Movistar/O2-Konto über die SMS-Bestätigung.",
"Open-source AI-powered coding assistant": "Open-Source AI-powered Coding Assistant",
"Open-source UI for building and debugging multi-agent and RAG applications": "Open-Source-Benutzeroberfläche zum Erstellen und Debuggen von Multi-Agenten- und RAG-Anwendungen",
"Open-source in-memory data store.": "Open-Source-Datenspeicher im Arbeitsspeicher.",
@@ -5018,6 +5059,7 @@
"Packages:": "Pakete:",
"Packaging OVA file...": "OVA-Datei verpacken...",
"Packing installer archive...": "Installationsarchiv packen...",
"Page layout and publishing in your browser": "Seitenlayout und Publizieren im Browser",
"PairDrop is a sublime alternative to AirDrop that works on all platforms. Send images, documents or text via peer to peer connection to devices in the same local network/Wi-Fi or to paired devices.": "PairDrop ist eine großartige Alternative zu AirDrop, die auf allen Plattformen funktioniert. Senden Sie Bilder, Dokumente oder Text per Peer-to-Peer-Verbindung an Geräte im gleichen lokalen Netzwerk / WLAN oder an gekoppelte Geräte.",
"Paperless configuration cancelled": "Papierlose Konfiguration abgesagt",
"Paperless-ngx WebUI": "Paperless-ngx WebUI",
@@ -5036,6 +5078,7 @@
"Pass /dev/video12 to the LXC": "Pass /dev/video12 zum LXC",
"Pass a host device to the LXC": "Übergeben Sie ein Host-Gerät an den LXC",
"Pass the UPS to the LXC": "Übergeben Sie die USV an LXC",
"Pass through a Z-Wave USB or serial controller": "Durchlaufen eines Z-Wave-USB- oder seriellen Controllers",
"Passing NVIDIA does not enable acceleration inside the application. The host needs NVIDIA Container Toolkit and a compatible image. Continue?": "Durch die Übergabe von NVIDIA wird keine Beschleunigung innerhalb der Anwendung aktiviert. Der Host benötigt NVIDIA Container Toolkit und ein kompatibles Image. Weitermachen?",
"Passkey-based identity provider for self-hosted apps.": "Passkey-basierter Identitätsanbieter für selbst gehostete Apps.",
"Passphrase used to unlock the imported keyfile (leave blank if the keyfile is unencrypted / kdf=none):": "Passphrase, die zum Entsperren der importierten Schlüsseldatei verwendet wird (leer lassen, wenn die Schlüsseldatei unverschlüsselt ist / kdf=none):",
@@ -5101,6 +5144,7 @@
"Path of the Compose file": "Pfad der Compose-Datei",
"Path of the oci-compose file": "Pfad der oci-compose-Datei",
"Path removed:": "Pfad entfernt:",
"Path to the client SSH public key on this server:": "Pfad zum öffentlichen SSH-Schlüssel des Clients auf diesem Server:",
"Path:": "Weg:",
"Paths applied:": "Angewandte Pfade:",
"Paths included in backup": "Im Backup enthaltene Pfade",
@@ -5143,6 +5187,8 @@
"Personal finance management application": "Persönliche Finanzverwaltung Anwendung",
"Personal media server for browsing and playing a local video library, with direct play and optional modules.": "Persönlicher Medienserver zum Durchsuchen und Abspielen einer lokalen Videosammlung, mit Direktwiedergabe und optionalen Modulen.",
"Photo and video library with optional GPU transcoding and machine learning": "Foto- und Videobibliothek mit optionaler GPU-Transcodierung und maschinellem Lernen",
"Photo editing in your browser": "Fotobearbeitung im Browser",
"Photo library and RAW development in your browser": "Fotoverwaltung und RAW-Entwicklung im Browser",
"PhotoPrism": "PhotoPrism",
"Photofield": "Photofield",
"Phpmyadmin is a free software tool written in PHP, intended to handle the administration of MySQL over the Web. phpMyAdmin supports a wide range of operations on MySQL and MariaDB.": "Phpmyadmin ist ein in PHP geschriebenes kostenloses Software-Tool, das die Verwaltung von MySQL über das Web übernehmen soll. phpMyAdmin unterstützt eine breite Palette von operationen auf MySQL und MariaDB.",
@@ -5235,6 +5281,7 @@
"Preparing the machine learning container for the new choice...": "Container für maschinelles Lernen wird für die neue Auswahl vorbereitet...",
"Preparing the recreation...": "Vorbereitung der Erholung...",
"Preparing the update...": "Vorbereitung des Updates...",
"Presentations and slide decks in your browser": "Präsentationen und Folien im Browser",
"Preserving logs to /var/log.hdd before unmounting...": "Protokolle werden vor dem Aufheben der Bereitstellung in /var/log.hdd beibehalten ...",
"Press 'q' to exit": "Drücken Sie „q“, um den Vorgang zu beenden",
"Press Ctrl+C to stop the server and return to menu.": "Drücken Sie Strg+C, um den Server zu stoppen und zum Menü zurückzukehren.",
@@ -5340,6 +5387,7 @@
"ProxMenux does not install them. The installation asks how to connect to them.": "ProxMenux installiert sie nicht. Die Installation fragt, wie man sich mit ihnen verbindet.",
"ProxMenux does not validate the contents; any keyfile your PBS accepts is accepted here.": "ProxMenux validiert den Inhalt nicht;Jede von Ihrem PBS akzeptierte Schlüsseldatei wird hier akzeptiert.",
"ProxMenux files:": "ProxMenux-Dateien:",
"ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.": "ProxMenux erzeugt das Administratorpasswort und zeigt es am Ende der Installation an. Ändern Sie es nach der ersten Anmeldung.",
"ProxMenux logo applied": "ProxMenux-Logo angewendet",
"ProxMenux only acts as a launcher — once the script starts, control leaves ProxMenux.": "ProxMenux fungiert nur als Startprogramm – sobald das Skript gestartet wird, verlässt ProxMenux die Steuerung.",
"ProxMenux saved it locally at:": "ProxMenux hat es lokal gespeichert unter:",
@@ -5395,6 +5443,7 @@
"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",
"Proxy address to reach the API (optional)": "Proxy-Adresse zum Erreichen der API (optional)",
"Public HTTPS URL used to open this Authelia portal (for example https://auth.example.com)": "Öffentliche HTTPS-URL, die zum Öffnen dieses Authelia-Portals verwendet wird (zum Beispiel https://auth.example.com)",
"Public UDP port clients connect to": "Öffentliche UDP Port Clients verbinden sich mit",
"Public UDP port peers connect to": "Öffentliche UDP-Port Peers verbinden sich mit",
"Public URL of phpMyAdmin when it is served behind a reverse proxy": "Öffentliche URL von phpMyAdmin, wenn sie hinter einem Reverse-Proxy bereitgestellt wird",
@@ -5455,6 +5504,7 @@
"Re-running pre-check after repairs...": "Nach der Reparatur wird die Vorkontrolle erneut durchgeführt...",
"Reachable": "Erreichbar",
"Read an oci-compose from a file of this host": "Lesen Sie ein oci-compose aus einer Datei dieses Hosts",
"Read and edit PDF documents in your browser": "PDF-Dokumente im Browser lesen und bearbeiten",
"Read its Compose file from a file of this host": "Lesen Sie die Compose-Datei aus einer Datei dieses Hosts",
"Read manga through a self-hosted server and web UI.": "Manga über einen selbst gehosteten Server mit Weboberfläche lesen.",
"Read the link with pct console CTID on the Proxmox host, or from the Console panel of the container in the Proxmox web interface, then open the https://playit.gg/claim/ address it shows in a browser and sign in to playit.gg. Ctrl+a q leaves pct console.": "Lesen Sie den Link mit pct-Konsole CTID auf dem Proxmox-Host oder vom Konsolen-Panel des Containers in der Proxmox-Weboberfläche, öffnen Sie dann die https://playit.gg/claim/Adresse, die in einem Browser angezeigt wird, und melden Sie sich bei playit.gg an. Strg + a q verlässt pct Konsole.",
@@ -5558,8 +5608,10 @@
"Recreation prepared": "Erholung vorbereitet",
"Recursive DNS resolver.": "Rekursiver DNS-Resolver.",
"Recursive and authoritative DNS server.": "Rekursiver und autoritativer DNS-Server.",
"Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.": "Die Dateisperre mit Redis wird automatisch eingerichtet. Vorhandene Nextcloud-Konfigurationsdateien bleiben erhalten.",
"Redmine": "Redmine",
"Refresh APT index and verify repositories:": "APT-Index aktualisieren und Repositorys überprüfen:",
"Refresh catalog": "Katalog aktualisieren",
"Refresh the configured APT repositories and review the PBS package upgrade? Repository files will be preserved.": "Die konfigurierten APT-Repositories aktualisieren und die PBS-Paketaktualisierung prüfen? Repository-Dateien bleiben erhalten.",
"Refresh the index from the image sources": "Den Index aus den Image-Quellen aktualisieren",
"Refresh token of the connector, from the Twingate admin console": "Aktualisierungstoken des Connectors aus der Twingate-Verwaltungskonsole",
@@ -5567,6 +5619,7 @@
"Refresh your browser to see changes (server restart may be required)": "Aktualisieren Sie Ihren Browser, um Änderungen zu sehen (möglicherweise ist ein Neustart des Servers erforderlich).",
"Refreshing apt cache...": "Apt-Cache wird aktualisiert...",
"Refreshing the NVIDIA runtime...": "Erfrischung der NVIDIA Runtime...",
"Refreshing the application catalog...": "Anwendungskatalog wird aktualisiert...",
"Refusing an unexpected rootfs path:": "Ablehnung eines unerwarteten Rootfs-Pfades:",
"Regenerate the catalog templates": "Die Katalogvorlagen neu erstellen",
"Regenerate the template of one application": "Die Vorlage einer Anwendung neu erstellen",
@@ -5639,6 +5692,7 @@
"Remove Proxmox NFS storage:": "Entfernen Sie den Proxmox NFS-Speicher:",
"Remove Proxmox iSCSI storage:": "Entfernen Sie den Proxmox iSCSI-Speicher:",
"Remove Secure Gateway? State will be preserved.": "Secure Gateway entfernen? Der Zustand bleibt erhalten.",
"Remove a remote USB connection": "Entfernte USB-Verbindung entfernen",
"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": "Alle registrierten gasket-DKMS-Versionen entfernen",
@@ -5659,6 +5713,7 @@
"Remove the lock left on a container by an interrupted task": "Die Sperre entfernen, die eine unterbrochene Aufgabe auf einem Container hinterlassen hat",
"Remove the saved credentials for {registry}?\nRunning apps will keep working.": "Die gespeicherten Anmeldeinformationen für {registry} entfernen?\nLaufende Apps funktionieren weiterhin.",
"Remove the unprivileged flag from configuration:": "Entfernen Sie das Unprivileged-Flag aus der Konfiguration:",
"Remove this connection and detach its USB device?": "Diese Verbindung entfernen und das USB-Gerät trennen?",
"Remove unused packages and their config": "Entfernen Sie nicht verwendete Pakete und deren Konfiguration",
"Remove: delete the application and its containers": "Entfernen: Löschen Sie die Anwendung und ihre Container",
"Removed": "ENTFERNT",
@@ -5881,9 +5936,11 @@
"Run mode: Unattended": "Betriebsmodus: Unbeaufsichtigt",
"Run now": "Jetzt ausführen",
"Run security audit now": "Führen Sie jetzt ein Sicherheitsaudit durch",
"Run the client inside the Linux VM that needs the USB device. Install usbip, openssh-client and kmod, then copy usbip_manager.py to the same path as on the server. Configure key authentication and verify the server host key before adding a connection. The client uses the guest kernel and can reconnect after migration while the physical USB device stays on the server. Unprivileged LXC and Home Assistant OS need their own kernel/device or add-on setup. A physical device supports one attached client at a time.": "Führen Sie den Client in der Linux-VM aus, die das USB-Gerät benötigt. Installieren Sie usbip, openssh-client und kmod und kopieren Sie usbip_manager.py an denselben Pfad wie auf dem Server. Richten Sie die Schlüsselauthentifizierung ein und prüfen Sie den Hostschlüssel des Servers, bevor Sie eine Verbindung hinzufügen. Der Client verwendet den Gastkernel und kann sich nach einer Migration erneut verbinden, während das physische USB-Gerät am Server bleibt. Unprivilegierte LXC und Home Assistant OS benötigen eine eigene Kernel-/Geräte- oder Add-on-Einrichtung. Ein physisches Gerät kann jeweils nur mit einem Client verbunden sein.",
"Run the following inside the VM:": "Führen Sie Folgendes in der VM aus:",
"Run the release-channel switch from an SSH session or the Proxmox host console with:": "Führen Sie den Release-Channel-Schalter von einer SSH-Sitzung oder der Proxmox-Hostkonsole aus mit:",
"Run the update from an SSH session or the Proxmox host console with:": "Führen Sie das Update über eine SSH-Sitzung oder die Proxmox-Hostkonsole aus mit:",
"Run this menu as root.": "Führen Sie dieses Menü als root aus.",
"Run this operation as root.": "Führen Sie diesen Vorgang als root aus.",
"Run upgrade checklist script:": "Führen Sie das Upgrade-Checklisten-Skript aus:",
"Running": "Läuft",
@@ -6108,6 +6165,7 @@
"Select a new language for the menu:": "Wählen Sie eine neue Sprache für das Menü:",
"Select a post-installation script:": "Wählen Sie ein Nachinstallationsskript aus:",
"Select a pre-configured Linux VM script to execute:": "Wählen Sie ein vorkonfiguriertes Linux-VM-Skript zur Ausführung aus:",
"Select a saved USB/IP device:": "Gespeichertes USB/IP-Gerät auswählen:",
"Select a script or action:": "Wählen Sie ein Skript oder eine Aktion aus:",
"Select a share to delete:": "Wählen Sie eine Freigabe zum Löschen aus:",
"Select a specific Coral or USB node, not the whole /dev": "Wählen Sie einen bestimmten Coral- oder USB-Knoten, nicht den gesamten /dev",
@@ -6185,6 +6243,7 @@
"Select the Linux distribution to install:": "Wählen Sie die zu installierende Linux-Distribution aus:",
"Select the NAS system to install:": "Wählen Sie das zu installierende NAS-System aus:",
"Select the NVIDIA driver version to install:": "Wählen Sie die zu installierende NVIDIA-Treiberversion aus:",
"Select the USB device to share:": "Freizugebendes USB-Gerät auswählen:",
"Select the VM to add the GPU to:": "Wählen Sie die VM aus, zu der Sie die GPU hinzufügen möchten:",
"Select the VM to which you want to add disks:": "Wählen Sie die VM aus, zu der Sie Festplatten hinzufügen möchten:",
"Select the VM where you want to import the disk image:": "Wählen Sie die VM aus, in die Sie das Disk-Image importieren möchten:",
@@ -6209,6 +6268,7 @@
"Select the parent job to attach to:": "Wählen Sie den übergeordneten Job aus, an den Sie anhängen möchten:",
"Select the paths to restore (one per backup entry):": "Wählen Sie die wiederherzustellenden Pfade aus (einen pro Sicherungseintrag):",
"Select the privileged LXC container to convert:": "Wählen Sie den zu konvertierenden privilegierten LXC-Container aus:",
"Select the remote USB device:": "Entferntes USB-Gerät auswählen:",
"Select the storage that will receive the backups:": "Wählen Sie den Speicher aus, der die Backups erhalten soll:",
"Select the storage volume for disk import:": "Wählen Sie das Speichervolume für den Festplattenimport aus:",
"Select the sync interval (in hours):": "Wählen Sie das Synchronisierungsintervall (in Stunden):",
@@ -6258,6 +6318,7 @@
"Self-hosted file sync and sharing.": "Selbst gehostete Dateisynchronisierung und -freigabe.",
"Self-hosted file toolkit for images, video, audio, PDFs, and files": "Selbst gehostetes Datei-Toolkit für Bilder, Video, Audio, PDFs und Dateien",
"Self-hosted forms and workflows.": "Selbst gehostete Formulare und Arbeitsabläufe.",
"Self-hosted grocery list and recipe manager": "Selbstgehostete Einkaufsliste und Rezeptmanager",
"Self-hosted household plant-care tracker with reminders, photos, and multiple user accounts.": "Selbst gehostete Pflegeverwaltung für Zimmerpflanzen mit Erinnerungen, Fotos und mehreren Benutzerkonten.",
"Self-hosted image-hosting service with authenticated uploads, image processing, public links, and local storage.": "Selbst gehosteter Bildhosting-Dienst mit authentifizierten Uploads, Bildverarbeitung, öffentlichen Links und lokalem Speicher.",
"Self-hosted internet archiving solution": "Selbst gehostete Internet-Archivierungslösung",
@@ -6294,6 +6355,7 @@
"Server IDs to test against, separated by commas (optional)": "Server-IDs zum Testen, durch Kommas getrennt (optional)",
"Server IP/hostname is correct": "Server-IP/Hostname ist korrekt",
"Server IP:": "Server-IP:",
"Server SSH port:": "SSH-Port des Servers:",
"Server is accessible:": "Server ist erreichbar:",
"Server is online": "Server ist online",
"Server is running": "Server läuft",
@@ -6355,6 +6417,7 @@
"Share Access Error": "Fehler beim Freigabezugriff",
"Share Name": "Teilen Sie den Namen",
"Share Options": "Freigabeoptionen",
"Share a local USB device": "Lokales USB-Gerät freigeben",
"Share added successfully.": "Teilen erfolgreich hinzugefügt.",
"Share deleted and Samba service restarted.": "Freigabe gelöscht und Samba-Dienst neu gestartet.",
"Share exists:": "Freigabe existiert:",
@@ -6362,6 +6425,7 @@
"Share name:": "Freigabename:",
"Share not found on server:": "Freigabe nicht auf Server gefunden:",
"Share path:": "Freigabepfad:",
"Share selected USB devices through SSH, or connect this Linux machine to a USB/IP server.": "Geben Sie ausgewählte USB-Geräte über SSH frei oder verbinden Sie diesen Linux-Rechner mit einem USB/IP-Server.",
"Share updated successfully.": "Freigabe erfolgreich aktualisiert.",
"Share:": "Aktie:",
"ShareCoveX panel": "ShareCoveX-Panel",
@@ -6452,6 +6516,7 @@
"Simple and easy to use DDNS": "Einfach und einfach zu bedienen DDNS",
"Simple self-hosted file sharing.": "Einfacher, selbst gehosteter Dateiaustausch.",
"Single GPU Warning": "Warnung vor einer einzelnen GPU",
"Single sign-on and multi-factor authentication": "Single Sign-On und Multi-Faktor-Authentifizierung",
"Single target found — selected automatically:": "Einzelnes Ziel gefunden – automatisch ausgewählt:",
"Single-node log storage and query UI.": "Logspeicher mit Abfrageoberfläche für einen einzelnen Knoten.",
"Single-node observability database for metrics, logs and traces.": "Einzelknoten-Datenbank für Metriken, Protokolle und Traces.",
@@ -6520,7 +6585,9 @@
"Specific subnet (enter manually)": "Spezifisches Subnetz (manuell eingeben)",
"Speedtest Tracker web interface": "Speedtest Tracker Web-Schnittstelle",
"Speedtest-tracker is a self-hosted internet performance tracking application that runs speedtest checks against Ookla's Speedtest service.": "Speedtest-Tracker ist eine selbst gehostete Internet-Performance-Tracking-Anwendung, die Speedtest-Checks gegen den Speedtest-Service von Ookla durchführt.",
"Spoolman web interface": "Spoolman-Weboberfläche",
"Spotube is an open source, cross-platform Spotify client compatible across multiple platforms utilizing Spotify's data API and YouTube, Piped.video or JioSaavn as an audio source, eliminating the need for Spotify Premium": "Spotube ist ein Open-Source-, plattformübergreifender Spotify-Client, der auf mehreren Plattformen mit Spotifys Daten-API und YouTube, Piped, kompatibel ist. Video oder JioSaavn als Audioquelle, wodurch Spotify Premium entfällt",
"Spreadsheets in your browser": "Tabellenkalkulation im Browser",
"Sshwifty": "Sshwifty",
"Sshwifty web access (password only)": "Sshwifty-Webzugriff (nur Passwort)",
"Stable (main branch)": "Stabil (Hauptzweig)",
@@ -6627,6 +6694,8 @@
"Still has issues": "Es gibt immer noch Probleme",
"Stop - shuts the guest down during backup": "Stopp – fährt den Gast während der Sicherung herunter",
"Stop it first and run this option again.": "Stoppen Sie es zuerst und führen Sie diese Option erneut aus.",
"Stop sharing a USB device": "USB-Gerätefreigabe beenden",
"Stop sharing this device? An attached remote client will disconnect.": "Freigabe dieses Geräts beenden? Ein verbundener entfernter Client wird getrennt.",
"Stop that VM, then choose:": "Stoppen Sie VM und wählen Sie dann:",
"Stop the CT, unmount the disk on the HOST, and remount with:": "Stoppen Sie den CT, unmounten Sie die Festplatte auf dem HOST und mounten Sie sie erneut mit:",
"Stop the VM/CT before formatting this disk.": "Stoppen Sie die VM/CT, bevor Sie diese Festplatte formatieren.",
@@ -6982,6 +7051,7 @@
"The container could not be removed automatically:": "Der Container konnte nicht automatisch entfernt werden:",
"The container could not be started:": "Der Container konnte nicht gestartet werden:",
"The container creation does not match the prepared instance": "Die Containererstellung stimmt nicht mit der vorbereiteten Instanz überein",
"The container device settings changed since the last recorded operation": "Die Geräteeinstellungen im Container haben sich seit dem letzten protokollierten Vorgang geändert",
"The container devices do not match the saved record": "Die Containergeräte stimmen nicht mit dem gespeicherten Datensatz überein",
"The container did not stop to update its persistent configuration:": "Der Container hat nicht angehalten, um seine persistente Konfiguration zu aktualisieren:",
"The container did not stop; its disks are not touched": "Der Container hat nicht angehalten; seine Scheiben werden nicht berührt",
@@ -7263,6 +7333,7 @@
"The record no longer belongs to this operation": "Der Datensatz gehört nicht mehr zu dieser operation",
"The record of a member was replaced; the assembly is not resumed": "Die Aufzeichnung eines Mitglieds wurde ersetzt; die Versammlung wird nicht wieder aufgenommen",
"The record or diagnosis could not be completed; no update was run.": "Die Aufzeichnung oder Diagnose konnte nicht abgeschlossen werden; kein Update wurde ausgeführt.",
"The recorded container device GID does not match its configuration": "Die protokollierte Geräte-GID im Container stimmt nicht mit der Konfiguration überein",
"The recovery did not complete. Review the log and choose \"Recover\" again for this container in the OCI management menu.": "Die Rückforderung war nicht abgeschlossen. Überprüfen Sie das Protokoll und wählen Sie erneut \"Wiederherstellen\" für diesen Container im OCI-Verwaltungsmenü.",
"The recovery did not complete. Review the log and choose \"{choice}\" again for this container in the OCI management menu.": "Die Wiederherstellung wurde nicht abgeschlossen. Prüfen Sie das Protokoll und wählen Sie für diesen Container im OCI-Verwaltungsmenü erneut \"{choice}\".",
"The registry authentication file is invalid; it was not changed.": "Die Registrierungsauthentifizierungsdatei ist ungültig; es wurde nicht geändert.",
@@ -7330,6 +7401,7 @@
"The selected Intel GPU has non-FLR reset support and unknown subtype": "Die ausgewählte Intel-GPU verfügt über Nicht-FLR-Reset-Unterstützung und einen unbekannten Subtyp",
"The selected Intel GPU is currently in power state D3cold": "Die ausgewählte Intel-GPU befindet sich derzeit im Energiezustand D3cold",
"The selected Intel render device does not exist:": "Das ausgewählte Intel-Rendergerät existiert nicht:",
"The selected USB device will become unavailable to local applications and guests. Only one remote client can use it at a time. Share this device?": "Das ausgewählte USB-Gerät steht lokalen Anwendungen und Gästen nicht mehr zur Verfügung. Nur ein entfernter Client kann es gleichzeitig verwenden. Dieses Gerät freigeben?",
"The selected VM": "Die ausgewählte VM",
"The selected VM is running.": "Die ausgewählte VM läuft.",
"The selected base folder does not exist and could not be created:": "Der ausgewählte Basisordner existiert nicht und konnte nicht erstellt werden:",
@@ -7417,6 +7489,7 @@
"Then bind-mount to container": "Dann bind-mounten Sie es an den Container",
"Then change the VM display to none (vga: none) when the guest is stable.": "Ändern Sie dann die VM-Anzeige auf „Keine“ (vga: none), wenn der Gast stabil ist.",
"Then change the VM display to none (vga: none) when the system is stable.": "Ändern Sie dann die VM-Anzeige auf „Keine“ (vga: none), wenn das System stabil ist.",
"Then restart the container so the new model appears in the list.": "Starten Sie den Container anschließend neu, damit das neue Modell in der Liste erscheint.",
"Then run this option again:": "Führen Sie dann diese Option erneut aus:",
"Then update /etc/fstab on the host with the same options.": "Aktualisieren Sie dann /etc/fstab auf dem Host mit denselben Optionen.",
"There are extra disks or bind mounts outside the journal; the rootfs is not replaced": "Es gibt zusätzliche Festplatten oder Bindehalterungen außerhalb des Journals; die Rootfs werden nicht ersetzt",
@@ -7464,6 +7537,7 @@
"This container does not have apt-get. NFS client installation only supports Debian/Ubuntu containers.": "Dieser Container verfügt nicht über apt-get. Die NFS-Client-Installation unterstützt nur Debian/Ubuntu-Container.",
"This container does not have apt-get. Samba client installation only supports Debian/Ubuntu containers.": "Dieser Container verfügt nicht über apt-get. Die Samba-Client-Installation unterstützt nur Debian/Ubuntu-Container.",
"This container has no GPU configured. Coral TPU works best alongside hardware video decoding (Quick Sync, VA-API, NVENC) for apps like Frigate.": "Für diesen Container ist keine GPU konfiguriert. Coral TPU funktioniert am besten zusammen mit der Hardware-Videodekodierung (Quick Sync, VA-API, NVENC) für Apps wie Frigate.",
"This container is managed by high availability. Remove ct:{vmid} from HA (Datacenter → HA, or ha-manager remove ct:{vmid}), repeat the operation and add it back to HA with the same settings.": "Dieser Container wird von der Hochverfügbarkeit verwaltet. Entfernen Sie ct:{vmid} aus HA (Rechenzentrum → HA oder ha-manager remove ct:{vmid}), wiederholen Sie den Vorgang und fügen Sie ihn mit denselben Einstellungen wieder zu HA hinzu.",
"This container is not a member of a multi-container application": "Dieser Container ist kein Mitglied einer Multi-Container-Anwendung",
"This container is not a registered OCI instance.": "Dieser Container ist keine registrierte OCI-Instanz.",
"This container was restored or came back from another host after its record on this host was written. Open this menu again to recover it; nothing was changed.": "Dieser Container wurde wiederhergestellt oder kam von einem anderen Host zurück, nachdem sein Datensatz auf diesem Host geschrieben wurde. Öffnen Sie dieses Menü erneut, um ihn zu registrieren; es wurde nichts geändert.",
@@ -7582,6 +7656,7 @@
"Tip: You can install the QEMU Guest Agent inside the VM with:": "Tipp: Sie können den QEMU Guest Agent in der VM installieren mit:",
"Tip: zfs set acltype=posixacl xattr=sa <pool>/<dataset> enables full ACL support.": "Tipp: zfs set acltype=posixacl xattr=sa <pool>/<dataset> aktiviert die vollständige ACL-Unterstützung.",
"Tmpfs size in MiB for": "Tmpfs Größe in MiB für",
"To add a model, open the console of the container in Proxmox and download it into /models, for example:": "Um ein Modell hinzuzufügen, öffnen Sie die Konsole des Containers in Proxmox und laden Sie es nach /models herunter, zum Beispiel:",
"To allow LXC write access, change the NFS export on the server to include:": "Um LXC-Schreibzugriff zu ermöglichen, ändern Sie den NFS-Export auf dem Server so, dass er Folgendes enthält:",
"To apply it to the current shell now, run:": "Um sie jetzt auf die aktuelle Shell anzuwenden, führen Sie Folgendes aus:",
"To assign VFs to VMs or LXCs, edit the configuration manually via the Proxmox web interface. The Physical Function will remain bound to the native driver.": "Um VFs VMs oder LXCs zuzuweisen, bearbeiten Sie die Konfiguration manuell über die Proxmox-Weboberfläche. Die physische Funktion bleibt an den nativen Treiber gebunden.",
@@ -7621,6 +7696,7 @@
"Total routes": "Gesamtrouten",
"Total size:": "Gesamtgröße:",
"Toxiproxy": "Toxiproxy",
"Track 3D printer filament spools and usage.": "Verfolgen Sie die Filamentspulen und den Verbrauch von 3D-Druckern.",
"Track movies, television, anime and games you want to enjoy.": "Behalten Sie Filme, Serien, Anime und Spiele im Blick, die Sie ansehen oder spielen möchten.",
"Track subscriptions and recurring expenses.": "Abonnements und wiederkehrende Ausgaben verwalten.",
"Track your music listening history on your own server.": "Hörverlauf für Musik auf dem eigenen Server erfassen.",
@@ -7665,6 +7741,9 @@
"USB drives mounted now:": "Jetzt gemountete USB-Laufwerke:",
"USB libedgetpu1": "USB libedgetpu1",
"USB or serial device node": "USB- oder serieller Geräteknoten",
"USB/IP configuration updated. Open status to check the connection.": "USB/IP-Konfiguration aktualisiert. Öffnen Sie den Status, um die Verbindung zu prüfen.",
"USB/IP over SSH": "USB/IP über SSH",
"USB/IP server IP address or DNS hostname:": "IP-Adresse oder DNS-Hostname des USB/IP-Servers:",
"UUP Dump script not found.": "UUP-Dump-Skript nicht gefunden.",
"UUp Dump ISO creator Custom": "UUp Dump ISO-Ersteller Benutzerdefiniert",
"Ubooquity is a free, lightweight and easy-to-use home server for your comics and ebooks. Use it to access your files from anywhere, with a tablet, an e-reader, a phone or a computer.": "Ubooquity ist ein kostenloser, leichter und benutzerfreundlicher Heimserver für Ihre Comics und E-Books. Verwenden Sie es, um von überall auf Ihre Dateien zuzugreifen, mit einem Tablet, einem E-Reader, einem Telefon oder einem Computer.",
@@ -7821,6 +7900,7 @@
"Untrusted or modified NVIDIA hook": "Nicht vertrauenswürdiger oder modifizierter NVIDIA-Hook",
"Unused image removed from the cache:": "Nicht verwendetes Bild aus dem Cache entfernt:",
"Unused images removed from the cache:": "Nicht verwendete Bilder aus dem Cache entfernt:",
"Unused local loopback TCP port for this device:": "Freier lokaler Loopback-TCP-Port für dieses Gerät:",
"Update": "Aktualisierung",
"Update Available": "Update verfügbar",
"Update Ceph repository (Only if using Ceph):": "Ceph-Repository aktualisieren (nur bei Verwendung von Ceph):",
@@ -7855,6 +7935,7 @@
"Update the whole stack?": "Aktualisieren Sie den gesamten Stack?",
"Update, modify or recreate one installed OCI instance": "Eine installierte OCI-Instanz aktualisieren, ändern oder neu erstellen",
"Updated": "Aktualisiert",
"Updated recipes since your last visit: {count}": "Aktualisierte Rezepte seit Ihrem letzten Besuch: {count}",
"Updated sharedfiles group to GID: 101000": "Sharedfiles-Gruppe auf GID aktualisiert: 101000",
"Updated stack checked": "Aktualisierter Stapel geprüft",
"Updated:": "Aktualisiert:",
@@ -7918,6 +7999,7 @@
"Use a privileged LXC for NFS server/client workflows.": "Verwenden Sie einen privilegierten LXC für NFS-Server-/Client-Workflows.",
"Use a privileged LXC for Samba client/server workflows.": "Verwenden Sie einen privilegierten LXC für Samba-Client/Server-Workflows.",
"Use a registry hostname, for example ghcr.io or registry.example.com:5000.": "Verwenden Sie einen Registrierungs-Hostnamen, zum Beispiel ghcr.io oder registry.example.com:5000.",
"Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time.": "Verwenden Sie einen HTTPS-Reverse-Proxy mit einem vertrauenswürdigen Zertifikat. Aktualisieren Sie Nextcloud jeweils auf die nächste Hauptversion, ohne eine zu überspringen.",
"Use an existing SSH private key file on this host": "Verwenden Sie eine vorhandene private SSH-Schlüsseldatei auf diesem Host",
"Use an existing keyfile": "Verwenden Sie eine vorhandene Schlüsseldatei",
"Use an image reference, for example ghcr.io/owner/app:latest.": "Verwenden Sie eine Bildreferenz, zum Beispiel ghcr.io/owner/app:latest.",
@@ -7931,6 +8013,7 @@
"Use existing filesystem": "Vorhandenes Dateisystem verwenden",
"Use existing: mount without formatting": "Vorhandenes verwenden: mounten ohne Formatierung",
"Use images only if the directory is on suitable storage.": "Verwenden Sie Bilder nur, wenn sich das Verzeichnis auf einem geeigneten Speicher befindet.",
"Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.": "Verwenden Sie verwalteten Speicher für /config und MariaDB. Für /data können Sie ein Verzeichnis auf dem Host/NAS auswählen, das eine eigene Sicherung benötigt.",
"Use mp1/mp2/... for extra mount points.": "Verwenden Sie mp1/mp2/... für zusätzliche Mount-Punkte.",
"Use only when unprivileged containers cannot meet your needs": "Verwenden Sie es nur, wenn nicht privilegierte Container Ihre Anforderungen nicht erfüllen können",
"Use option 1 to add a local disk (as Proxmox storage and/or as a host mount).": "Verwenden Sie Option 1, um eine lokale Festplatte hinzuzufügen (als Proxmox-Speicher und/oder als Host-Mount).",
@@ -8060,6 +8143,7 @@
"Variables": "Variablen",
"Variables the installation asks for:": "Variablen, die von der Anlage verlangt werden:",
"Vaultwarden Web Vault": "Vaultwarden Web Vault",
"Vector illustration in your browser": "Vektorillustrationen im Browser",
"Vector search engine with a built-in dashboard.": "Vektorsuchmaschine mit integriertem Dashboard.",
"Verbose pool status": "Ausführlicher Poolstatus",
"Verification": "Überprüfung",
@@ -8090,6 +8174,7 @@
"Versions shown belong to maintained NVIDIA branches that list your GPU PCI ID and are new enough to build against the running kernel. DKMS compilation is the final validation. The recommended version keeps the current branch, or uses the NVIDIA Production Branch on a fresh install.": "Die angezeigten Versionen gehören zu gepflegten NVIDIA-Zweigen, die Ihre GPU-PCI-ID auflisten und neu genug sind, um auf dem laufenden Kernel zu erstellen. Die DKMS-Kompilierung ist die endgültige Validierung. Die empfohlene Version behält den aktuellen Zweig bei oder verwendet den NVIDIA Production Branch bei einer Neuinstallation.",
"VictoriaLogs": "VictoriaLogs",
"Video acceleration and object detection are independent choices; the installer does not write camera or detector YAML.": "Videobeschleunigung und Objekterkennung sind unabhängige Entscheidungen; der Installer schreibt keine Kamera oder Detektor YAML.",
"Video editing in your browser": "Videoschnitt im Browser",
"Video transcoding acceleration": "Videotranscodierungsbeschleunigung",
"Video transcoding profile not implemented:": "Videotranskodierungsprofil nicht implementiert:",
"View CIFS Mounts (pvesm + fstab)": "CIFS-Mounts anzeigen (pvesm + fstab)",
@@ -8099,6 +8184,7 @@
"View Disk Storages": "Festplattenspeicher anzeigen",
"View Mount Points": "Mount-Punkte anzeigen",
"View NFS Mounts (pvesm + fstab)": "NFS-Mounts anzeigen (pvesm + fstab)",
"View USB/IP status": "USB/IP-Status anzeigen",
"View backup metadata": "Sicherungsmetadaten anzeigen",
"View current paths": "Aktuelle Pfade anzeigen",
"View existing folders in /mnt": "Vorhandene Ordner in /mnt anzeigen",
@@ -8199,12 +8285,17 @@
"Web access": "Webzugang",
"Web address of the AdGuard Home that receives the settings (e.g. http://192.168.1.3)": "Webadresse des AdGuard Home, der die Einstellungen erhält (z. B. http://192.168.1.3)",
"Web address of the main AdGuard Home, whose settings are copied (e.g. http://192.168.1.2)": "Webadresse des AdGuard Home, dessen Einstellungen kopiert sind (z. B. http://192.168.1.2)",
"Web dashboard": "Web-Dashboard",
"Web dashboard and WebDAV": "Web-Dashboard und WebDAV",
"Web interface": "Weboberfläche",
"Web interface for Borg Backup repositories and jobs.": "Weboberfläche für Borg-Backup-Repositories und -Jobs.",
"Web interface for managing 3D printers.": "Weboberfläche zur Verwaltung von 3D-Druckern.",
"Web interface to manage devices running Tasmota firmware.": "Web-Schnittstelle zur Verwaltung von Geräten mit Tasmota-Firmware.",
"Web reverse proxy with an administration interface.": "Web-Reverse-Proxy mit Administrationsoberfläche.",
"WebCord can be summarized as a pack of security and privacy hardenings, Discord features reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, internal pages and wrapped https://discord.com page, designed to conform with ToS as much as it is possible (or hide the changes that might violate it from Discord's eyes).": "WebCord kann als ein Paket von Sicherheits- und Datenschutz-Härtungen, Discord-Features-Reimplementierungen, Electron / Chromium / Discord-Bugs-Workarounds, Stylesheets, interne Seiten und verpackte https://discord.com-Seite zusammengefasst werden, die so weit wie möglich mit ToS konform sind (oder die Änderungen, die es verletzen könnten, vor Discords Augen verbergen).",
"WebDAV": "WebDAV",
"WebDAV and dashboard password (leave empty to generate)": "Passwort für WebDAV und Dashboard (leer = generiert)",
"WebDAV is available on container port 8080. Account linking is required before cloud file operations.": "WebDAV ist auf Port 8080 des Containers verfügbar. Vor Dateioperationen in der Cloud muss das Konto verknüpft werden.",
"Webgrabplus is a multi-site incremental xmltv epg grabber. It collects tv-program guide data from selected tvguide sites for your favourite channels.": "Webgrabplus ist ein multi-site inkrementeller xmltv epg grabber. Es sammelt tv-programm-guide-daten von ausgewählten tvguide-seiten für ihre lieblingskanäle.",
"Webservers & Proxies": "Webserver und Proxys",
"Website": "Webseite",
@@ -8262,6 +8353,7 @@
"Without a usable reset path, passthrough reliability is poor and VM": "Ohne einen nutzbaren Reset-Pfad ist die Passthrough-Zuverlässigkeit schlecht und VM",
"Wizard cancelled": "Assistent abgebrochen",
"Wolfenstein: Blade of Agony is a story-driven WWII shooter inspired by Wolfenstein and Doom.": "Wolfenstein: Blade of Agony ist ein Story-basierter WWII-Shooter, inspiriert von Wolfenstein und Doom.",
"Word processing in your browser": "Textverarbeitung im Browser",
"Workflow automation tool": "Workflow Automation Tool",
"Working directory:": "Arbeitsverzeichnis:",
"Works with LVM, ZFS, and BTRFS storage types": "Funktioniert mit LVM-, ZFS- und BTRFS-Speichertypen",
@@ -8312,6 +8404,8 @@
"Your machine learning Env work with Jupyter Lab": "Ihre Machine Learning Env arbeitet mit Jupyter Lab",
"Your next YouTube media manager": "Dein nächster YouTube Media Manager",
"Your_spotify is a self-hosted application that tracks what you listen and offers you a dashboard to explore statistics about it! It's composed of a web server which polls the Spotify API every now and then and a web application on which you can explore your statistics.": "Your_spotify ist eine selbst gehostete Anwendung, die verfolgt, was Sie hören und bietet Ihnen ein Dashboard, um Statistiken darüber zu erkunden! Es besteht aus einem Webserver, der hin und wieder die Spotify-API abfragt, und einer Webanwendung, auf der Sie Ihre Statistiken erkunden können.",
"Z-Wave JS UI": "Z-Wave JS UI",
"Z-Wave JS UI admin login": "Z-Wave JS UI Admin-Login",
"ZFS ARC config removed (kernel defaults will apply on reboot)": "ZFS ARC-Konfiguration entfernt (Kernel-Standardeinstellungen gelten beim Neustart)",
"ZFS ARC maximum configured:": "ZFS ARC maximal konfiguriert:",
"ZFS ARC optimization completed": "ZFS ARC-Optimierung abgeschlossen",
@@ -8425,6 +8519,7 @@
"could not be compiled for kernel": "konnte nicht für den Kernel kompiliert werden",
"could not validate NVIDIA; exit code": "konnte NVIDIA nicht validieren; Exit-Code",
"cpuunits must be between 8 and 10000": "cpuunits müssen zwischen 8 und 10000 sein",
"curl -L -o /models/gemma-3-1b-it-Q4_K_M.gguf https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf": "curl -L -o /models/gemma-3-1b-it-Q4_K_M.gguf https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf",
"custom": "Custom",
"custom dependency commands are not yet supported": "Custom Dependency Commands werden noch nicht unterstützt",
"custom path(s) saved.": "Benutzerdefinierte(r) Pfad(e) gespeichert.",
@@ -8631,6 +8726,7 @@
"kexec-tools is not installed or already removed.": "kexec-tools ist nicht installiert oder bereits entfernt.",
"layers": "Schichten",
"legacy .link file(s) to the ProxMenux-managed format": "ältere .link-Dateien in das von ProxMenux verwaltete Format",
"llama.cpp shows every GGUF model saved in /models in its web UI and loads the one you choose.": "llama.cpp zeigt in seiner Weboberfläche alle in /models gespeicherten GGUF-Modelle an und lädt das ausgewählte.",
"log2ram completely removed from system": "log2ram vollständig aus dem System entfernt",
"main container of the application": "Hauptcontainer der Anwendung",
"make cloned mount tree read-only": "geklonten Mount-Baum schreibgeschützt machen",
+96
View File
@@ -183,6 +183,7 @@
"A tunneling daemon by Cloudflare that safely exposes your web servers into the internet.": "Un daemon de túneles de Cloudflare que expone tus servidores web a Internet de forma segura.",
"A unified email and collaboration server.": "Un servidor unificado de correo electrónico y colaboración.",
"A unified platform for logs, metrics and traces.": "Una plataforma unificada para registros, métricas y trazas.",
"A validating, recursive DNS resolver for your private network.": "un solucionador de DNS recursivo y de validación para su red privada.",
"A versatile file conversion tool that supports multiple formats.": "Una herramienta versátil de conversión de archivos compatible con múltiples formatos.",
"A visual tool for exploring and documenting database schemas.": "Una herramienta visual para explorar y documentar esquemas de bases de datos.",
"A web GUI client of Project V which supports VMess, VLESS, SS, SSR, Trojan, Tuic and Juicity protocols": "Un cliente web de Project V compatible con los protocolos VMess, VLESS, SS, SSR, Trojan, Tuic y Juicity",
@@ -244,6 +245,7 @@
"Aborted": "Abortado",
"About to restore": "A punto de restaurar",
"Absolute directory path to use as backup target:": "Ruta absoluta del directorio para usar como destino del backup:",
"Absolute path of the client SSH private key:": "Ruta absoluta de la clave privada SSH del cliente:",
"Absolute path to a file or directory you want backed up:": "Ruta absoluta de un archivo o directorio del que desea hacer backup:",
"Acceleration": "Aceleración",
"Acceleration configuration cancelled": "Configuración de aceleración cancelada",
@@ -255,6 +257,7 @@
"Acceleration for llama.cpp": "Aceleración para llama.cpp",
"Accept routes from other nodes?": "¿Aceptar rutas de otros nodos?",
"Accept this host monitoring profile?": "¿Aceptar este perfil de monitorización del host?",
"Access Movistar and O2 Cloud from WebDAV clients and backup tools.": "Accede a la nube de Movistar y O2 desde clientes WebDAV y herramientas de backup.",
"Access Scope:": "Ámbito de acceso:",
"Access bridge": "Puente de acceso",
"Access bridge for Immich": "Puente de acceso para Immich",
@@ -408,6 +411,7 @@
"After the reboot, you will only be able to access the Proxmox host via:": "Después del reinicio, solo podrá acceder al host Proxmox a través de:",
"After this LXC → VM switch, reboot the host so the new binding state is applied cleanly.": "Después de este cambio LXC → VM, reinicia el host para que el nuevo estado de enlace se aplique limpiamente.",
"Agentless monitoring and observability platform.": "Plataforma de monitorización y observabilidad sin agentes.",
"AirDC++ administrator": "Administrador de AirDC++",
"Airsonic Advanced web interface": "Interfaz web de Airsonic Advanced",
"Airsonic-advanced is a free, web-based media streamer, providing ubiquitious access to your music. Use it to share your music with friends, or to listen to your own music while at work. You can stream to multiple players simultaneously, for instance to one player in your kitchen and another in your living room.": "Airsonic-advanced es un servidor de streaming multimedia gratuito y basado en web que da acceso a tu música desde cualquier lugar. Úsalo para compartir tu música con amigos o para escuchar la tuya en el trabajo. Puede transmitir a varios reproductores a la vez, por ejemplo a uno en la cocina y a otro en el salón.",
"Aliases added to .bashrc": "Alias añadidos a .bashrc",
@@ -595,12 +599,16 @@
"Attention: Removing the subscription banner may cause issues in the web interface after a future update.": "Atención: Eliminar el banner de suscripción puede causar problemas en la interfaz web después de una actualización futura.",
"Audacity is an easy-to-use, multi-track audio editor and recorder. Developed by a group of volunteers as open source.": "Audacity es un editor y grabador de audio multipista fácil de usar, desarrollado como código abierto por un grupo de voluntarios.",
"Audio device directory": "Directorio de dispositivos de audio",
"Audio recording and mixing in your browser": "Grabación y mezcla de audio en el navegador",
"Audio/Video": "Audio/vídeo",
"Audiobookshelf is a self-hosted audiobook and podcast server.": "Audiobookshelf es un servidor autoalojado de audiolibros y podcasts.",
"Audit completed. Press Enter to continue...": "Auditoría completada. Pulsa Intro para continuar...",
"Audit socket disabled or not required": "Socket de auditoría deshabilitado o no requerido",
"Auth key is required.": "Se requiere clave de autenticación.",
"Auth:": "Autenticación:",
"Authelia Web UI": "Authelia Interfaz de usuario web",
"Authelia administrator": "administrador Authelia",
"Authelia session cookie domain for this portal (for example example.com)": "dominio de cookie de sesión Authelia para este portal (por ejemplo, ejemplo.com)",
"Authentication": "Autenticación",
"Authentication & Security": "Authentication & Security",
"Authentication Error": "Error de autenticación",
@@ -610,6 +618,8 @@
"Authentication:": "Autenticación:",
"Authorization failed": "Autorización fallida",
"Authorization successful": "Autorización correcta",
"Authorize a client SSH public key": "Autorizar una clave pública SSH de un cliente",
"Authorize a dedicated client public key on the server first. The restricted USB/IP account cannot run a shell or forward other sockets. Verify the server host key before connecting; unknown keys are rejected.": "Autoriza primero una clave pública dedicada del cliente en el servidor. La cuenta restringida de USB/IP no puede abrir una shell ni redirigir otros sockets. Verifica la clave del servidor antes de conectarte; las claves desconocidas se rechazan.",
"Authorize this key on the server": "Autorizar esta clave en el servidor",
"Authorize via 'pct exec' (Borg server is an LXC on a PVE host I can SSH into)": "Autorizar a través de 'pct exec' (el servidor Borg es un LXC en un host PVE en el que puedo acceder mediante SSH)",
"Authorized": "Autorizado",
@@ -640,6 +650,7 @@
"Available PVE Version": "Versión PVE disponible",
"Available Shares:": "Recursos compartidos disponibles:",
"Available action": "Acción disponible",
"Available applications: {count}": "Aplicaciones disponibles: {count}",
"Available archives:": "Archivos disponibles:",
"Available disks detected.": "Discos disponibles detectados.",
"Available host backups:": "Backups de host disponibles:",
@@ -872,6 +883,7 @@
"Cannot write the image archive to {storage}. Check storage access and mount status.": "No se puede escribir el archivo de la imagen en {storage}. Comprueba el acceso al almacenamiento y que esté montado.",
"Capabilities cannot be kept and all dropped at the same time": "No se pueden mantener las capacidades y todas se disminuyen al mismo tiempo",
"Catalog options": "Opciones del catálogo",
"Catalog refresh unavailable; using the local catalog.": "No se pudo actualizar el catálogo; se está usando la copia local.",
"Category": "Categoría",
"Caution: Maximum mode generates more heat.": "Precaución: el modo máximo genera más calor.",
"Central server for file and image backups.": "Servidor central para copias de seguridad de archivos e imágenes.",
@@ -1159,6 +1171,7 @@
"Compressing": "Comprimiendo",
"Compression": "Compresión",
"Compression Tools": "Herramientas de compresión",
"Computer-aided design and drafting in your browser": "Diseño CAD y dibujo técnico en el navegador",
"Concise output of logical volumes": "Salida concisa de volúmenes lógicos",
"Concise output of physical volumes": "Salida concisa de volúmenes físicos",
"Concise output of volume groups": "Salida concisa de grupos de volúmenes",
@@ -1289,6 +1302,7 @@
"Conflicting utilities removed": "Se eliminaron las utilidades conflictivas",
"Connect Zigbee devices to MQTT with a browser-based setup interface.": "Conecta dispositivos Zigbee a MQTT mediante una interfaz web de configuración.",
"Connect a Coral Accelerator and try again.": "Conecta un Coral Accelerator y vuelve a intentarlo.",
"Connect a remote USB device": "Conectar un dispositivo USB remoto",
"Connect it, or remove it from the container in Proxmox (Resources), and run the recovery again.": "Conéctalo, o elimínalo del contenedor en Proxmox (Recursos), y vuelve a lanzar la recuperación.",
"Connect your devices and users together in your own secure virtual private network.": "Conecta tus dispositivos y usuarios en tu propia red privada virtual segura.",
"Connect your devices into a secure WireGuard®-based overlay network with SSO, MFA and granular access controls.": "Conecta tus dispositivos en una red overlay segura basada en WireGuard®, con SSO, MFA y controles de acceso granulares.",
@@ -1391,6 +1405,7 @@
"Controller + NVMe": "Controlador + NVMe",
"Controller + NVMe assignment will be written now and become active after host reboot.": "La asignación de controlador + NVMe se escribirá ahora y se activará después de reiniciar el host.",
"Controller + NVMe passthrough requires machine type q35. Skipping controller assignment.": "El passthrough de controlador + NVMe requiere el tipo de máquina q35. Se omite la asignación del controlador.",
"Controller path on the Proxmox host; prefer /dev/serial/by-id/...": "Ruta del controlador en el host Proxmox;prefiero /dev/serial/by-id/...",
"Controller/NVMe Conflict Policy": "Política de conflictos entre controlador y NVMe",
"Controller/NVMe already present in VM config": "Controlador/NVMe ya presente en la configuración de VM",
"Controller/NVMe already present in VM config (%s)": "El controlador/NVMe ya está en la configuración de la VM (%s)",
@@ -1925,6 +1940,7 @@
"Dgraph": "Dgraph",
"Diff: current system vs backup (--- system +++ backup)": "Diferencias: sistema actual frente al backup (--- sistema +++ backup)",
"Different host. Backup from:": "Host diferente. Backup procedente de:",
"Direct Connect file sharing with a web interface": "Intercambio de archivos Direct Connect con interfaz web",
"Direct conversion completed for container": "Conversión directa completada para el contenedor",
"Directory Exists": "El directorio existe",
"Directory Not Empty": "Directorio no vacío",
@@ -1947,12 +1963,14 @@
"Directus administrator": "Administrador de Directus",
"Disable NIC Offloading (Intel e1000e)": "Desactivar offloading de NIC (Intel e1000e)",
"Disable Secure Boot in the UEFI firmware and run the installer again. Nothing has been changed.": "Desactiva Secure Boot en el firmware UEFI y vuelve a ejecutar el instalador. No se ha cambiado nada.",
"Disable USB/IP server": "Desactivar el servidor USB/IP",
"Disable autostart on conflicting VM": "Deshabilitar el inicio automático en VM en conflicto",
"Disable autostart on one VM to avoid startup conflicts.": "Desactiva el inicio automático en una VM para evitar conflictos de inicio.",
"Disable job": "Desactivar trabajo",
"Disable kernel audit messages (optional but recommended):": "Desactivar los mensajes de auditoría del kernel (opcional pero recomendado):",
"Disable onboot on affected VM(s)/CT(s)": "Deshabilitar el arranque en las VM/CT afectadas",
"Disable portmapper/rpcbind": "Desactivar portmapper/rpcbind",
"Disable the server and release all USB devices managed by ProxMenux? Saved selections are kept for the next enable.": "¿Desactivar el servidor y liberar todos los dispositivos USB gestionados por ProxMenux? La selección guardada se conserva para la próxima activación.",
"Disabled": "Desactivado",
"Disabling High Availability services...": "Deshabilitando los servicios de alta disponibilidad...",
"Disabling ZFS autotrim applied by ProxMenux...": "Deshabilitando el recorte automático ZFS aplicado por ProxMenux...",
@@ -2185,6 +2203,7 @@
"Enable Remote Desktop (RDP) before disabling the virtual display.": "Activa el Escritorio remoto (RDP) antes de desactivar la pantalla virtual.",
"Enable SSD emulation for this disk?": "¿Habilitar la emulación SSD para este disco?",
"Enable TCP BBR/Fast Open control": "Activar control TCP BBR/Fast Open",
"Enable USB/IP server": "Activar el servidor USB/IP",
"Enable VA-API transcoding and HDR10/Dolby Vision to SDR tone mapping": "Activar la transcodificación VA-API y el mapeo de tonos de HDR10/Dolby Vision a SDR",
"Enable VA-API, hardware encoding and OpenCL tone mapping in Jellyfin": "Activar VA-API, la codificación por hardware y el mapeo de tonos OpenCL en Jellyfin",
"Enable VFIO IOMMU support": "Activar soporte VFIO IOMMU",
@@ -3196,6 +3215,7 @@
"If pvesm path returned a DEVICE (LVM):": "Si pvesm path devolvió un DISPOSITIVO (LVM):",
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Si pvesm path devolvió un DIRECTORIO (ZFS/BTRFS):",
"If repositories error:": "Si hay error en los repositorios:",
"If the USB/IP service stops unexpectedly, stop sharing while the device is still connected to release it. In rare cases only a host reboot releases it.": "Si el servicio USB/IP se detiene de forma inesperada, deja de compartir el dispositivo mientras sigue conectado para liberarlo. En casos excepcionales solo se libera reiniciando el host.",
"If the container had already been changed, its previous native backup is restored. Shared host directories are not reverted. The disks of the failed attempt are removed when the cleanup succeeds.": "Si el contenedor ya se había modificado, se restaura su backup nativo anterior. Los directorios compartidos del host no se revierten. Los discos del intento fallido se eliminan si la limpieza termina bien.",
"If the host freezes, remove hostpci entries from": "Si el host se congela, elimina las entradas hostpci de",
"If the image channel has a new version, the CT is stopped, backed up and verified, and replaced with the new image to update the container. If the update fails after the container was changed, the backup is restored. An update that stops halfway is recovered from the OCI management menu.": "Si el canal de imagen tiene una versión nueva, el CT se detiene, se hace un backup, se verifica y se sustituye por la nueva imagen, actualizando el contenedor. Si la actualización falla después de modificar el contenedor, se restaura el backup. Una actualización que se queda a medias se recupera desde el menú de gestión OCI.",
@@ -3336,6 +3356,7 @@
"Initial Stirling-PDF account": "Cuenta inicial de Stirling-PDF",
"Initial Tandoor administrator": "Administrador inicial de Tandoor",
"Initial Umami administrator": "Administrador inicial de Umami",
"Initial Z-Wave JS UI admin password": "Contraseña de administrador inicial Z-Wave JS UI",
"Initial administrator created:": "Administrador inicial creado:",
"Initial administrator user": "Usuario administrador inicial",
"Initializing Borg repository if needed...": "Inicializando el repositorio de Borg si es necesario...",
@@ -3389,6 +3410,7 @@
"Install server packages inside CT:": "Instalar paquetes de servidor dentro de CT:",
"Install terminal multiplexers": "Instalar multiplexores de terminales",
"Install the Edge TPU runtime (libedgetpu1-std)": "Instalar el tiempo de ejecución de Edge TPU (libedgetpu1-std)",
"Install the USB/IP dependencies from the configured Debian repositories?": "¿Instalar las dependencias de USB/IP desde los repositorios de Debian configurados?",
"Install this image?": "¿Instalar esta imagen?",
"Install with Cloud-Init script": "Instalar con el script Cloud-Init",
"Install with ISO from UUP Dump": "Instalar con ISO desde UUP Dump",
@@ -3521,6 +3543,7 @@
"Interface MTU": "MTU de interfaz",
"Interface Names (persistent)": "Nombres de interfaces persistentes",
"Interface Type": "Tipo de interfaz",
"Interface design and prototyping in your browser": "Diseño de interfaces y prototipos en el navegador",
"Interface names will return to default systemd behavior.": "Los nombres de las interfaces volverán al comportamiento predeterminado de systemd.",
"Interface type:": "Tipo de interfaz:",
"Interfaces configured": "Interfaces configuradas",
@@ -3578,6 +3601,7 @@
"Invalid check package:": "Paquete de comprobación inválido:",
"Invalid configuration path:": "Vía de configuración inválida:",
"Invalid consume/export volumes": "Volumen de consumo/exportación inválidos",
"Invalid container device GID": "El GID del dispositivo del contenedor no es válido",
"Invalid container path:": "Carril de contenedor inválido:",
"Invalid credential file path:": "Ruta de archivo credential no válida:",
"Invalid declarative entrypoint": "Punto de entrada declarativo inválido",
@@ -3736,6 +3760,7 @@
"Jupyter Lab (token only)": "Jupyter Lab (solo token)",
"JupyterLab": "JupyterLab",
"JupyterLab access token": "Token de acceso de JupyterLab",
"KDE's twin-panel file manager in a browser-based desktop.": "administrador de archivos de panel doble de KDE en un escritorio basado en navegador.",
"KDF:": "KDF:",
"KROMA": "KROMA",
"KVM MSR options added to /etc/modprobe.d/kvm.conf": "Opciones de KVM MSR añadidas a /etc/modprobe.d/kvm.conf",
@@ -3783,12 +3808,14 @@
"KiCad - A Cross Platform and Open Source Electronics Design Automation Suite.": "KiCad - Una suite de automatización de diseño electrónico multiplataforma y de código abierto.",
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "Kimai no tiene una cuenta predeterminada. Entra en el contenedor con: pct enter {main_vmid}",
"Kimai is a professional grade time-tracking application, free and open-source.": "Kimai es una aplicación profesional de control de tiempo, gratuita y de código abierto.",
"KitchenOwl": "KitchenOwl",
"Kometa is a powerful tool designed to give you complete control over your media libraries. With Kometa, you can take your customization to the next level, with granular control over metadata, collections, overlays, and much more.": "Kometa es una potente herramienta que te da control total sobre tus bibliotecas multimedia. Con Kometa llevas la personalización al siguiente nivel, con control detallado de metadatos, colecciones, overlays y mucho más.",
"Kometa reads its configuration from /config/config.yml and the container only ships /config/config.yml.template. Copy the template to config.yml, fill in the required Plex and TMDb connections, then restart the container.": "Kometa lee su configuración de /config/config.yml y el contenedor solo incluye /config/config.yml.template. Copia la plantilla a config.yml, rellena las conexiones obligatorias de Plex y TMDb y reinicia el contenedor.",
"Komga is a media server for your comics, mangas, BDs, magazines and eBooks.": "Komga es un servidor multimedia para tus cómics, mangas, BDs, revistas y eBooks.",
"Kopia Web UI": "Interfaz web de Kopia",
"Kopia Web UI login": "Acceso a la interfaz web de Kopia",
"Krita is a professional FREE and open source painting program. It is made by artists that want to see affordable art tools for everyone.": "Krita es un programa de pintura profesional, GRATUITO y de código abierto. Lo hacen artistas que quieren herramientas de arte asequibles para todos.",
"Krusader Web UI": "Krusader Interfaz de usuario web",
"LAN access to the kept containers (stack configuration incomplete):": "Acceso LAN a los contenedores conservados (configuración de la pila incompleta):",
"LAN address applied to the application URLs": "Dirección LAN aplicada a las URL de la aplicación",
"LLDAP": "LLDAP",
@@ -3868,9 +3895,11 @@
"Line to paste (single line, including \"command=...\" prefix):": "Línea para pegar (una sola línea, incluido el prefijo \"comando=...\"):",
"LinkStack": "LinkStack",
"Linux Installation Options": "Opciones de instalación de Linux",
"Linux guest setup and migration notes": "Configuración del invitado Linux y notas sobre migración",
"Linux/Mac path:": "Ruta Linux/Mac:",
"LinuxServer Jellyfin with optional GPU passthrough": "Jellyfin de LinuxServer con passthrough de GPU opcional",
"LinuxServer MariaDB requires a user, database and password": "LinuxServer MariaDB requiere un usuario, base de datos y contraseña",
"LinuxServer Nextcloud with MariaDB and Redis": "Nextcloud de LinuxServer con MariaDB y Redis",
"List Available Disks": "Listar discos disponibles",
"List IOMMU group mapping": "Listar el mapeo del grupo IOMMU",
"List NVMe devices": "Listar dispositivos NVMe",
@@ -4015,6 +4044,7 @@
"Manage OCI stack": "Administrar la pila de OCI",
"Manage PBS encryption keyfile": "Administrar el archivo de claves de cifrado PBS",
"Manage Secure Gateway": "Administrar Secure Gateway",
"Manage a Z-Wave network from a web dashboard and WebSocket gateway.": "administre una red Z-Wave desde un panel web y una puerta de enlace WebSocket.",
"Manage and inspect VM disk images": "Administrar e inspeccionar imágenes de disco de VM",
"Manage custom backup paths": "Configurar rutas de backup personalizadas",
"Manage custom paths (add / remove your folders)": "Configurar rutas personalizadas (añadir/eliminar carpetas)",
@@ -4024,6 +4054,7 @@
"Manage local backup target": "Configurar el destino del backup local",
"Manage private image registries.\nSaved credentials let ProxMenux access your private images.": "Gestiona los registros de imágenes privadas.\nCon las credenciales guardadas, ProxMenux puede acceder a tus imágenes privadas.",
"Manage registry accounts as root on the Proxmox node.": "Gestiona las cuentas de registro como root en el nodo Proxmox.",
"Manage teams of AI agents from a web dashboard.": "Gestiona equipos de agentes de IA desde un panel web.",
"Managed disks must have backup enabled and a valid size": "Los discos gestionados deben tener habilitado backup y un tamaño válido",
"Managed public route include is missing": "Falta el archivo de configuración de las rutas públicas gestionadas",
"Managed public route installation failed": "No se han podido configurar las rutas públicas gestionadas",
@@ -4129,6 +4160,7 @@
"Monitoring": "Monitorización",
"Monitoring & Analytics": "Monitoring & Analytics",
"Most common cause: the archive is corrupted (interrupted write, partial copy, or storage issue).": "Causa más común: el archivo está dañado (escritura interrumpida, copia parcial o problema de almacenamiento).",
"Motion graphics and compositing in your browser": "Animación gráfica y composición en el navegador",
"Mount Added Successfully:": "Montaje añadido correctamente:",
"Mount CIFS share:": "Monta el recurso compartido CIFS:",
"Mount Configuration Summary:": "Resumen de configuración de montaje:",
@@ -4288,6 +4320,7 @@
"NVIDIA (CUDA; official GPU image)": "NVIDIA (CUDA; imagen oficial para GPU)",
"NVIDIA (NVDEC/CUDA)": "NVIDIA (NVDEC/CUDA)",
"NVIDIA (NVENC/NVDEC)": "NVIDIA (NVENC/NVDEC)",
"NVIDIA (Selkies rendering and NVENC)": "NVIDIA (renderizado de Selkies y NVENC)",
"NVIDIA Actions": "Acciones de NVIDIA",
"NVIDIA CPU hiding already configured": "Ocultación de CPU NVIDIA ya configurada",
"NVIDIA Container Toolkit": "Kit de herramientas de contenedor NVIDIA",
@@ -4371,6 +4404,7 @@
"Name or part of the option or of the application": "Nombre o parte de la opción o de la aplicación",
"Name:": "Nombre:",
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Las cuentas con nombre necesitan el modo privado. Detén el contenedor, pon public: false en /config/config.js, vuelve a arrancarlo y crea cada usuario con: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>",
"Native Borg is unavailable. Install the native borgbackup package on this host to use Borg backups.": "Borg nativo no está disponible. Instala el paquete borgbackup nativo en este host para usar los backups de Borg.",
"Needed:": "Necesario:",
"Needs": "Necesita",
"Neither /etc/kernel/cmdline nor /etc/default/grub found.": "No se encontraron /etc/kernel/cmdline ni /etc/default/grub.",
@@ -4429,6 +4463,8 @@
"New Search": "Nueva búsqueda",
"New VM:": "Nueva máquina virtual:",
"New Virtual Machine": "Nueva máquina virtual",
"New applications ({count})": "Aplicaciones nuevas ({count})",
"New applications since your last visit: {count}": "Aplicaciones nuevas desde tu última visita: {count}",
"New backup job": "Nuevo trabajo de backup",
"New backups on this host will be unencrypted until a new keyfile is set up.": "Los nuevos backups de este host no se cifrarán hasta que se configure un nuevo archivo de claves.",
"New image compatible:": "Nueva imagen compatible:",
@@ -4444,6 +4480,7 @@
"Next Step Required": "Se requiere el siguiente paso",
"Next Steps:": "Próximos pasos:",
"Next step: stop that VM first, then run": "Siguiente paso: detén esa VM primero y luego ejecuta",
"Nextcloud Web UI": "Interfaz web de Nextcloud",
"Nextcloud configuration cancelled": "Configuración Nextcloud cancelada",
"Nextcloud gives you access to all your files wherever you are.": "Nextcloud te da acceso a todos tus archivos estés donde estés.",
"Nextcloud volume size in GB": "Tamaño del volumen de Nextcloud en GB",
@@ -4617,6 +4654,7 @@
"No duplicate IP addresses": "Sin direcciones IP duplicadas",
"No duplicate repositories found": "No se encontraron repositorios duplicados",
"No eligible Controller/NVMe devices remain after SR-IOV filtering. Skipping.": "No quedan dispositivos de controlador/NVMe elegibles después del filtrado SR-IOV. Salto a la comba.",
"No eligible USB devices found. Hubs, mass storage and network adapters are excluded.": "No hay dispositivos USB compatibles. Se excluyen los concentradores, el almacenamiento masivo y los adaptadores de red.",
"No eligible controllers remain after SR-IOV filtering.": "No quedan controladores elegibles después del filtrado SR-IOV.",
"No encryption key is stored on this host. Choose how to set one up:": "No se almacena ninguna clave de cifrado en este host. Elige cómo configurar una:",
"No exportable VM disks were found (CD-ROM/cloud-init are excluded).": "No se encontraron discos de VM exportables (se excluyen CD-ROM/cloud-init).",
@@ -4701,6 +4739,7 @@
"No self-test log available for": "No hay ningún log de autoprueba disponible para",
"No server IP or hostname provided.": "No se proporcionó ninguna IP de servidor ni nombre de host.",
"No share access test succeeded with guest authentication.": "Ninguna prueba de acceso a recursos compartidos funcionó con autenticación de invitado.",
"No shared devices are available on this server.": "No hay dispositivos compartidos disponibles en este servidor.",
"No shared media content.": "No hay contenido multimedia compartido.",
"No shared mount detected. Applying standard local access.": "No se detectó ningún montaje compartido. Aplicando acceso local estándar.",
"No shares configured.": "No hay recursos compartidos configurados.",
@@ -4887,6 +4926,8 @@
"Open the page of an application in the menu": "Abrir la página de una aplicación en el menú",
"Open the web address and create the first account: the daemon registers by itself and starts the first scan.": "Abre la dirección web y crea la primera cuenta: el daemon se registra solo y empieza el primer escaneo.",
"Open the web address and create the password of the akadmin user in the first-run setup.": "abra la dirección web y cree la contraseña del usuario akaadmin en la configuración de primera ejecución.",
"Open the web address and follow KitchenOwl’s onboarding to create the first account; no default account is configured.": "abra la dirección web y siga la incorporación de KitchenOwl para crear la primera cuenta;no hay ninguna cuenta predeterminada configurada.",
"Open the web dashboard and link your Movistar/O2 account using its SMS flow.": "Abre el panel web y vincula tu cuenta de Movistar/O2 con su verificación por SMS.",
"Open-source AI-powered coding assistant": "Asistente de programación con IA de código abierto",
"Open-source UI for building and debugging multi-agent and RAG applications": "Interfaz de código abierto para crear y depurar aplicaciones multiagente y RAG",
"Open-source in-memory data store.": "Almacén de datos en memoria de código abierto.",
@@ -5009,6 +5050,7 @@
"Packages:": "Paquetes:",
"Packaging OVA file...": "Embalaje archivo OVA...",
"Packing installer archive...": "Empaquetando el archivo del instalador...",
"Page layout and publishing in your browser": "Maquetación y publicación en el navegador",
"PairDrop is a sublime alternative to AirDrop that works on all platforms. Send images, documents or text via peer to peer connection to devices in the same local network/Wi-Fi or to paired devices.": "PairDrop es una magnífica alternativa a AirDrop que funciona en todas las plataformas. Envía imágenes, documentos o texto mediante una conexión entre pares a dispositivos de la misma red local/Wi-Fi o a dispositivos emparejados.",
"Paperless configuration cancelled": "Configuración de Paperless cancelada",
"Paperless-ngx WebUI": "Paperless-ngx WebUI",
@@ -5027,6 +5069,7 @@
"Pass /dev/video12 to the LXC": "Pasar /dev/video12 al LXC",
"Pass a host device to the LXC": "Pasar un dispositivo del host al LXC",
"Pass the UPS to the LXC": "Pase el UPS al LXC",
"Pass through a Z-Wave USB or serial controller": "pasar a través de un controlador serie o USB Z-Wave",
"Passing NVIDIA does not enable acceleration inside the application. The host needs NVIDIA Container Toolkit and a compatible image. Continue?": "Pasar NVIDIA no habilita la aceleración dentro de la aplicación. El host necesita NVIDIA Container Toolkit y una imagen compatible. ¿Continuar?",
"Passkey-based identity provider for self-hosted apps.": "Proveedor de identidad basado en passkeys para aplicaciones autoalojadas.",
"Passphrase used to unlock the imported keyfile (leave blank if the keyfile is unencrypted / kdf=none):": "Frase de contraseña utilizada para desbloquear el archivo de claves importado (déjalo en blanco si el archivo de claves no está cifrado/kdf=none):",
@@ -5092,6 +5135,7 @@
"Path of the Compose file": "Ruta del archivo Compose",
"Path of the oci-compose file": "Ruta del archivo oci-compose",
"Path removed:": "Ruta eliminada:",
"Path to the client SSH public key on this server:": "Ruta de la clave pública SSH del cliente en este servidor:",
"Path:": "Ruta:",
"Paths applied:": "Rutas aplicadas:",
"Paths included in backup": "Rutas incluidas en el backup",
@@ -5134,6 +5178,8 @@
"Personal finance management application": "Aplicación de gestión de finanzas personales",
"Personal media server for browsing and playing a local video library, with direct play and optional modules.": "Servidor multimedia personal para explorar y reproducir una biblioteca local de vídeos, con reproducción directa y módulos opcionales.",
"Photo and video library with optional GPU transcoding and machine learning": "Biblioteca de fotos y vídeos con transcodificación por GPU y aprendizaje automático opcionales",
"Photo editing in your browser": "Edición de fotos en el navegador",
"Photo library and RAW development in your browser": "Biblioteca de fotos y revelado RAW en el navegador",
"PhotoPrism": "PhotoPrism",
"Photofield": "Photofield",
"Phpmyadmin is a free software tool written in PHP, intended to handle the administration of MySQL over the Web. phpMyAdmin supports a wide range of operations on MySQL and MariaDB.": "Phpmyadmin es una herramienta de software libre escrita en PHP para administrar MySQL por la web. phpMyAdmin admite una amplia gama de operaciones en MySQL y MariaDB.",
@@ -5225,6 +5271,7 @@
"Preparing the changes...": "Preparando los cambios...",
"Preparing the machine learning container for the new choice...": "Preparando el contenedor Machine learning para la nueva opción...",
"Preparing the update...": "Preparando la actualización...",
"Presentations and slide decks in your browser": "Presentaciones y diapositivas en el navegador",
"Preserving logs to /var/log.hdd before unmounting...": "Preservando logs en /var/log.hdd antes de desmontar...",
"Press 'q' to exit": "Pulsa 'q' para salir",
"Press Ctrl+C to stop the server and return to menu.": "Pulsa Ctrl+C para detener el servidor y volver al menú.",
@@ -5330,6 +5377,7 @@
"ProxMenux does not install them. The installation asks how to connect to them.": "ProxMenux no los instala. La instalación pide cómo conectarse a ellos.",
"ProxMenux does not validate the contents; any keyfile your PBS accepts is accepted here.": "ProxMenux no valida los contenidos; cualquier archivo de claves que acepte tu PBS se acepta aquí.",
"ProxMenux files:": "Archivos ProxMenux:",
"ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.": "ProxMenux genera la contraseña del administrador y la muestra al final de la instalación. Cámbiala después del primer inicio de sesión.",
"ProxMenux logo applied": "Logotipo de ProxMenux aplicado",
"ProxMenux only acts as a launcher — once the script starts, control leaves ProxMenux.": "ProxMenux solo actúa como Lanzador del script.",
"ProxMenux saved it locally at:": "ProxMenux lo guardó localmente en:",
@@ -5385,6 +5433,7 @@
"Proxmox web interface: Datacenter > Storage > Add > ZFS": "Interfaz web de Proxmox: Datacenter > Storage > Add > ZFS",
"Proxmox web interface: Datacenter > Storage > Add > iSCSI": "Interfaz web de Proxmox: Datacenter > Storage > Add > iSCSI",
"Proxy address to reach the API (optional)": "Dirección del proxy para llegar a la API (opcional)",
"Public HTTPS URL used to open this Authelia portal (for example https://auth.example.com)": "URL HTTPS pública utilizada para abrir este portal Authelia (por ejemplo, https://auth.example.com)",
"Public UDP port clients connect to": "Puerto UDP público al que se conectan los clientes",
"Public UDP port peers connect to": "Puerto UDP público al que se conectan los peers",
"Public URL of phpMyAdmin when it is served behind a reverse proxy": "URL pública de phpMyAdmin cuando se sirve detrás de un proxy inverso",
@@ -5445,6 +5494,7 @@
"Re-running pre-check after repairs...": "Volviendo a ejecutar la verificación previa después de las reparaciones...",
"Reachable": "Accesible",
"Read an oci-compose from a file of this host": "Leer un oci-compose desde un archivo de este host",
"Read and edit PDF documents in your browser": "Lectura y edición de documentos PDF en el navegador",
"Read its Compose file from a file of this host": "Leer su archivo Compose desde un archivo de este host",
"Read manga through a self-hosted server and web UI.": "Lee manga desde un servidor autoalojado con interfaz web.",
"Read the link with pct console CTID on the Proxmox host, or from the Console panel of the container in the Proxmox web interface, then open the https://playit.gg/claim/ address it shows in a browser and sign in to playit.gg. Ctrl+a q leaves pct console.": "Lee el enlace con pct console CTID en el host Proxmox, o desde el panel Console del contenedor en la interfaz web de Proxmox; después abre en un navegador la dirección https://playit.gg/claim/ que muestra e inicia sesión en playit.gg. Ctrl+a q sale de pct console.",
@@ -5541,8 +5591,10 @@
"Recreating the container:": "Recreando el contenedor:",
"Recursive DNS resolver.": "Resolvedor DNS recursivo.",
"Recursive and authoritative DNS server.": "Servidor DNS recursivo y autoritativo.",
"Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.": "El bloqueo con Redis se configura automáticamente. Se conservan los archivos de configuración existentes de Nextcloud.",
"Redmine": "Redmine",
"Refresh APT index and verify repositories:": "Actualizar el índice APT y verificar los repositorios:",
"Refresh catalog": "Actualizar catálogo",
"Refresh the configured APT repositories and review the PBS package upgrade? Repository files will be preserved.": "¿Actualizar los índices de los repositorios de APT configurados y revisar la actualización de paquetes de PBS? Se conservarán los archivos de los repositorios.",
"Refresh the index from the image sources": "Actualizar el índice desde las fuentes de imágenes",
"Refresh token of the connector, from the Twingate admin console": "Token de renovación del conector, de la consola de administración de Twingate",
@@ -5550,6 +5602,7 @@
"Refresh your browser to see changes (server restart may be required)": "Actualiza tu navegador para ver los cambios (es posible que sea necesario reiniciar el servidor)",
"Refreshing apt cache...": "Actualizando caché de apt...",
"Refreshing the NVIDIA runtime...": "Refrescando el tiempo de ejecución de NVIDIA...",
"Refreshing the application catalog...": "Actualizando el catálogo de aplicaciones...",
"Refusing an unexpected rootfs path:": "Refusing an inesperado rootfs path:",
"Regenerate the catalog templates": "Regenerar las plantillas del catálogo",
"Regenerate the template of one application": "Regenerar la plantilla de una aplicación",
@@ -5622,6 +5675,7 @@
"Remove Proxmox NFS storage:": "Eliminar el almacenamiento Proxmox NFS:",
"Remove Proxmox iSCSI storage:": "Eliminar el almacenamiento iSCSI de Proxmox:",
"Remove Secure Gateway? State will be preserved.": "¿Eliminar Secure Gateway? Se conservará el estado.",
"Remove a remote USB connection": "Eliminar una conexión USB remota",
"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": "Eliminar todas las versiones de gasket registradas en DKMS",
@@ -5642,6 +5696,7 @@
"Remove the lock left on a container by an interrupted task": "Quitar el bloqueo que deja en un contenedor una tarea interrumpida",
"Remove the saved credentials for {registry}?\nRunning apps will keep working.": "¿Eliminar las credenciales guardadas de {registry}?\nLas aplicaciones en marcha seguirán funcionando.",
"Remove the unprivileged flag from configuration:": "Elimina el flag unprivileged de la configuración:",
"Remove this connection and detach its USB device?": "¿Eliminar esta conexión y desconectar su dispositivo USB?",
"Remove unused packages and their config": "Eliminar paquetes no utilizados y su configuración",
"Remove: delete the application and its containers": "Eliminar: la aplicación y sus contenedores",
"Removed": "Remoto",
@@ -5864,9 +5919,11 @@
"Run mode: Unattended": "Modo de ejecución: desatendido",
"Run now": "Ejecutar ahora",
"Run security audit now": "Ejecutar la auditoría de seguridad ahora",
"Run the client inside the Linux VM that needs the USB device. Install usbip, openssh-client and kmod, then copy usbip_manager.py to the same path as on the server. Configure key authentication and verify the server host key before adding a connection. The client uses the guest kernel and can reconnect after migration while the physical USB device stays on the server. Unprivileged LXC and Home Assistant OS need their own kernel/device or add-on setup. A physical device supports one attached client at a time.": "Ejecuta el cliente dentro de la VM Linux que necesita el USB. Instala usbip, openssh-client y kmod y copia usbip_manager.py en la misma ruta que en el servidor. Configura la autenticación por clave y verifica la clave del servidor antes de añadir la conexión. El cliente usa el kernel del invitado y puede reconectarse después de migrarlo mientras el USB físico sigue en el servidor. Los LXC sin privilegios y Home Assistant OS necesitan su propia configuración de kernel, dispositivos o complementos. Solo un cliente puede usar cada dispositivo físico a la vez.",
"Run the following inside the VM:": "Ejecuta lo siguiente dentro de la VM:",
"Run the release-channel switch from an SSH session or the Proxmox host console with:": "Ejecuta el cambio de canal de versiones desde una sesión SSH o la consola del host Proxmox con:",
"Run the update from an SSH session or the Proxmox host console with:": "Ejecuta la actualización desde una sesión SSH o la consola del host Proxmox con:",
"Run this menu as root.": "Ejecuta este menú como root.",
"Run this operation as root.": "Ejecuta esta operación como root.",
"Run upgrade checklist script:": "Ejecuta el script de la lista de verificación de actualización:",
"Running": "En ejecución",
@@ -6091,6 +6148,7 @@
"Select a new language for the menu:": "Selecciona un nuevo idioma para el menú:",
"Select a post-installation script:": "Selecciona un script de post-instalación:",
"Select a pre-configured Linux VM script to execute:": "Selecciona un script de VM Linux preconfigurado para ejecutar:",
"Select a saved USB/IP device:": "Selecciona un dispositivo USB/IP guardado:",
"Select a script or action:": "Selecciona un script o acción:",
"Select a share to delete:": "Selecciona un recurso compartido para eliminar:",
"Select a specific Coral or USB node, not the whole /dev": "Selecciona un Coral específico o nodo USB, no todo /dev",
@@ -6168,6 +6226,7 @@
"Select the Linux distribution to install:": "Selecciona la distribución de Linux para instalar:",
"Select the NAS system to install:": "Selecciona el sistema NAS a instalar:",
"Select the NVIDIA driver version to install:": "Selecciona la versión del controlador NVIDIA para instalar:",
"Select the USB device to share:": "Selecciona el dispositivo USB que quieres compartir:",
"Select the VM to add the GPU to:": "Selecciona la VM a la que añadir la GPU:",
"Select the VM to which you want to add disks:": "Selecciona la VM a la que deseas añadir discos:",
"Select the VM where you want to import the disk image:": "Selecciona la VM donde deseas importar la imagen del disco:",
@@ -6192,6 +6251,7 @@
"Select the parent job to attach to:": "Selecciona el trabajo principal al que adjuntarlo:",
"Select the paths to restore (one per backup entry):": "Selecciona las rutas para restaurar (una por entrada de backup):",
"Select the privileged LXC container to convert:": "Selecciona el contenedor LXC privilegiado para convertir:",
"Select the remote USB device:": "Selecciona el dispositivo USB remoto:",
"Select the storage that will receive the backups:": "Selecciona el almacenamiento que recibirá los backups:",
"Select the storage volume for disk import:": "Selecciona el volumen de almacenamiento para la importación de disco:",
"Select the sync interval (in hours):": "Selecciona el intervalo de sincronización (en horas):",
@@ -6241,6 +6301,7 @@
"Self-hosted file sync and sharing.": "Sincronización y uso compartido de archivos autoalojados.",
"Self-hosted file toolkit for images, video, audio, PDFs, and files": "Kit de herramientas autoalojado para imágenes, vídeo, audio, PDF y archivos",
"Self-hosted forms and workflows.": "Formularios y flujos de trabajo autoalojados.",
"Self-hosted grocery list and recipe manager": "lista de compras y administrador de recetas autohospedado",
"Self-hosted household plant-care tracker with reminders, photos, and multiple user accounts.": "Gestor autoalojado del cuidado de plantas domésticas, con recordatorios, fotos y varias cuentas de usuario.",
"Self-hosted image-hosting service with authenticated uploads, image processing, public links, and local storage.": "Servicio autoalojado para alojar imágenes, con subidas autenticadas, procesamiento de imágenes, enlaces públicos y almacenamiento local.",
"Self-hosted internet archiving solution": "Solución autoalojada de archivado de Internet",
@@ -6277,6 +6338,7 @@
"Server IDs to test against, separated by commas (optional)": "ID de los servidores contra los que probar, separados por comas (opcional)",
"Server IP/hostname is correct": "La IP/nombre de host del servidor es correcta",
"Server IP:": "IP del servidor:",
"Server SSH port:": "Puerto SSH del servidor:",
"Server is accessible:": "El servidor es accesible:",
"Server is online": "El servidor está en línea",
"Server is running": "El servidor está funcionando",
@@ -6338,6 +6400,7 @@
"Share Access Error": "Error de acceso al recurso compartido",
"Share Name": "Nombre compartido",
"Share Options": "Opciones para compartir",
"Share a local USB device": "Compartir un dispositivo USB local",
"Share added successfully.": "Recurso compartido añadido correctamente.",
"Share deleted and Samba service restarted.": "Compartir eliminado y servicio Samba reiniciado.",
"Share exists:": "Compartir existe:",
@@ -6345,6 +6408,7 @@
"Share name:": "Nombre compartido:",
"Share not found on server:": "Compartir no encontrado en el servidor:",
"Share path:": "Compartir ruta:",
"Share selected USB devices through SSH, or connect this Linux machine to a USB/IP server.": "Comparte dispositivos USB mediante SSH o conecta este equipo Linux a un servidor USB/IP.",
"Share updated successfully.": "Compartir actualizado con éxito.",
"Share:": "Compartir:",
"ShareCoveX panel": "Panel de ShareCoveX",
@@ -6435,6 +6499,7 @@
"Simple and easy to use DDNS": "DDNS simple y fácil de usar",
"Simple self-hosted file sharing.": "Servicio sencillo y autoalojado para compartir archivos.",
"Single GPU Warning": "Advertencia de GPU única",
"Single sign-on and multi-factor authentication": "inicio de sesión único y autenticación multifactor",
"Single target found — selected automatically:": "Destino único encontrado: seleccionado automáticamente:",
"Single-node log storage and query UI.": "Almacenamiento de logs para un solo nodo con interfaz de consulta.",
"Single-node observability database for metrics, logs and traces.": "Base de datos de observabilidad de un solo nodo para métricas, registros y trazas.",
@@ -6504,7 +6569,9 @@
"Specific subnet (enter manually)": "Subred específica (introducir manualmente)",
"Speedtest Tracker web interface": "Interfaz web de Speedtest Tracker",
"Speedtest-tracker is a self-hosted internet performance tracking application that runs speedtest checks against Ookla's Speedtest service.": "Speedtest-tracker es una aplicación autoalojada de seguimiento del rendimiento de Internet que ejecuta pruebas de velocidad contra el servicio Speedtest de Ookla.",
"Spoolman web interface": "interfaz web Spoolman",
"Spotube is an open source, cross-platform Spotify client compatible across multiple platforms utilizing Spotify's data API and YouTube, Piped.video or JioSaavn as an audio source, eliminating the need for Spotify Premium": "Spotube es un cliente de Spotify de código abierto y multiplataforma que usa la API de datos de Spotify y YouTube, Piped.video o JioSaavn como fuente de audio, sin necesidad de Spotify Premium",
"Spreadsheets in your browser": "Hojas de cálculo en el navegador",
"Sshwifty": "Sshwifty",
"Sshwifty web access (password only)": "Acceso web a Sshwifty (solo con contraseña)",
"Stable (main branch)": "Estable (rama main)",
@@ -6611,6 +6678,8 @@
"Still has issues": "Todavía tiene problemas",
"Stop - shuts the guest down during backup": "Stop - apaga la VM o CT durante el backup",
"Stop it first and run this option again.": "Detenlo primero y ejecuta esta opción nuevamente.",
"Stop sharing a USB device": "Dejar de compartir un dispositivo USB",
"Stop sharing this device? An attached remote client will disconnect.": "¿Dejar de compartir este dispositivo? Se desconectará el cliente remoto que lo esté usando.",
"Stop that VM, then choose:": "Detén ese VM, luego elige:",
"Stop the CT, unmount the disk on the HOST, and remount with:": "Detén el CT, desmonta el disco en el HOST y vuelve a montarlo con:",
"Stop the VM/CT before formatting this disk.": "Detén el VM/CT antes de formatear este disco.",
@@ -6964,6 +7033,7 @@
"The container could not be removed automatically:": "El contenedor no se puede retirar automáticamente:",
"The container could not be started:": "No se podía iniciar el contenedor:",
"The container creation does not match the prepared instance": "La creación de contenedores no coincide con la instancia preparada",
"The container device settings changed since the last recorded operation": "La configuración del dispositivo del contenedor ha cambiado desde la última operación registrada",
"The container devices do not match the saved record": "Los dispositivos del contenedor no coinciden con el registro guardado",
"The container did not stop to update its persistent configuration:": "El contenedor no se detuvo para actualizar su configuración persistente:",
"The container did not stop; its disks are not touched": "El contenedor no se detuvo; sus discos no se tocan",
@@ -7238,6 +7308,7 @@
"The record no longer belongs to this operation": "El registro ya no pertenece a esta operación",
"The record of a member was replaced; the assembly is not resumed": "El registro de un miembro fue reemplazado; el ensamblado no se reanuda",
"The record or diagnosis could not be completed; no update was run.": "El registro o el diagnóstico no se pudo completar; no se realizó ninguna actualización.",
"The recorded container device GID does not match its configuration": "El GID registrado del dispositivo del contenedor no coincide con su configuración",
"The recovery did not complete. Review the log and choose \"Recover\" again for this container in the OCI management menu.": "La recuperación no terminó. Revisa el log y elige \"Recuperar la instalación anterior\" de nuevo para este contenedor en el menú de gestión OCI.",
"The recovery did not complete. Review the log and choose \"{choice}\" again for this container in the OCI management menu.": "La recuperación no terminó. Revisa el log y elige \"{choice}\" de nuevo para este contenedor en el menú de gestión OCI.",
"The registry authentication file is invalid; it was not changed.": "El fichero de autenticación del registro no es válido; no se ha modificado.",
@@ -7305,6 +7376,7 @@
"The selected Intel GPU has non-FLR reset support and unknown subtype": "La GPU Intel seleccionada tiene soporte de reinicio no FLR y subtipo desconocido",
"The selected Intel GPU is currently in power state D3cold": "La GPU Intel seleccionada se encuentra actualmente en estado de energía D3cold",
"The selected Intel render device does not exist:": "El dispositivo de renderización Intel seleccionado no existe:",
"The selected USB device will become unavailable to local applications and guests. Only one remote client can use it at a time. Share this device?": "El dispositivo USB dejará de estar disponible para las aplicaciones y los invitados locales. Solo puede usarlo un cliente remoto a la vez. ¿Compartirlo?",
"The selected VM": "La máquina virtual seleccionada",
"The selected VM is running.": "La VM seleccionada se está ejecutando.",
"The selected base folder does not exist and could not be created:": "La carpeta base seleccionada no existe y no se pudo crear:",
@@ -7392,6 +7464,7 @@
"Then bind-mount to container": "Luego vincule el montaje al contenedor",
"Then change the VM display to none (vga: none) when the guest is stable.": "Después cambia la pantalla de la VM a none (vga: none) cuando el sistema de la VM sea estable.",
"Then change the VM display to none (vga: none) when the system is stable.": "Luego cambia la visualización de VM a ninguno (vga: ninguno) cuando el sistema esté estable.",
"Then restart the container so the new model appears in the list.": "Después reinicia el contenedor para que el modelo nuevo aparezca en la lista.",
"Then run this option again:": "Luego ejecuta esta opción nuevamente:",
"Then update /etc/fstab on the host with the same options.": "Luego actualiza /etc/fstab en el host con las mismas opciones.",
"There are extra disks or bind mounts outside the journal; the rootfs is not replaced": "Hay discos o bind mounts adicionales fuera del diario de la operación; el rootfs no se reemplaza",
@@ -7438,6 +7511,7 @@
"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.",
"This container is managed by high availability. Remove ct:{vmid} from HA (Datacenter → HA, or ha-manager remove ct:{vmid}), repeat the operation and add it back to HA with the same settings.": "Este contenedor está gestionado por alta disponibilidad. Elimina ct:{vmid} de HA (Centro de datos → HA, o ha-manager remove ct:{vmid}), repite la operación y vuelve a añadirlo a HA con la misma configuración.",
"This container is not a member of a multi-container application": "Este contenedor no forma parte de una aplicación de varios contenedores",
"This container is not a registered OCI instance.": "Este contenedor no es una instancia OCI registrada.",
"This container was restored or came back from another host after its record on this host was written. Open this menu again to recover it; nothing was changed.": "Este contenedor se restauró o volvió de otro host después de que se escribiera su registro en este host. Abre de nuevo este menú para recuperarlo; no se ha cambiado nada.",
@@ -7555,6 +7629,7 @@
"Tip: You can install the QEMU Guest Agent inside the VM with:": "Consejo: Puede instalar el Agente Invitado QEMU dentro de la VM con:",
"Tip: zfs set acltype=posixacl xattr=sa <pool>/<dataset> enables full ACL support.": "Consejo: zfs set acltype=posixacl xattr=sa <pool>/<dataset> habilita la compatibilidad total con ACL.",
"Tmpfs size in MiB for": "Tamaño de tmpfs en MiB para",
"To add a model, open the console of the container in Proxmox and download it into /models, for example:": "Para añadir un modelo, abre la consola del contenedor en Proxmox y descárgalo en /models, por ejemplo:",
"To allow LXC write access, change the NFS export on the server to include:": "Para permitir el acceso de escritura a LXC, cambia la exportación NFS en el servidor para incluir:",
"To apply it to the current shell now, run:": "Para aplicarlo ahora en la sesión actual, ejecuta:",
"To assign VFs to VMs or LXCs, edit the configuration manually via the Proxmox web interface. The Physical Function will remain bound to the native driver.": "Para asignar VF a VM o LXC, edita la configuración manualmente a través de la interfaz web de Proxmox. La Función Física permanecerá ligada al controlador nativo.",
@@ -7594,6 +7669,7 @@
"Total routes": "Rutas totales",
"Total size:": "Tamaño total:",
"Toxiproxy": "Toxiproxy",
"Track 3D printer filament spools and usage.": "realice un seguimiento de los carretes de filamentos de las impresoras 3D y su uso.",
"Track movies, television, anime and games you want to enjoy.": "Lleva un registro de películas, series, anime y videojuegos que quieras disfrutar.",
"Track subscriptions and recurring expenses.": "Seguimiento de suscripciones y gastos recurrentes.",
"Track your music listening history on your own server.": "Registra tu historial de reproducción musical en tu propio servidor.",
@@ -7638,6 +7714,9 @@
"USB drives mounted now:": "Unidades USB montadas ahora:",
"USB libedgetpu1": "USB libedgetpu1",
"USB or serial device node": "Nodo de dispositivo USB o serie",
"USB/IP configuration updated. Open status to check the connection.": "Configuración de USB/IP actualizada. Abre el estado para comprobar la conexión.",
"USB/IP over SSH": "USB/IP mediante SSH",
"USB/IP server IP address or DNS hostname:": "Dirección IP o nombre DNS del servidor USB/IP:",
"UUP Dump script not found.": "No se encontró el script de UUP Dump.",
"UUp Dump ISO creator Custom": "Creador de ISO personalizada con UUP Dump",
"Ubooquity is a free, lightweight and easy-to-use home server for your comics and ebooks. Use it to access your files from anywhere, with a tablet, an e-reader, a phone or a computer.": "Ubooquity es un servidor doméstico gratuito, ligero y fácil de usar para tus cómics y ebooks. Úsalo para acceder a tus archivos desde cualquier lugar, con una tableta, un lector electrónico, un teléfono o un ordenador.",
@@ -7792,6 +7871,7 @@
"Untrusted or modified NVIDIA hook": "Hook NVIDIA sin confianza o modificado",
"Unused image removed from the cache:": "Imagen sin uso eliminada de la caché:",
"Unused images removed from the cache:": "Imágenes sin uso eliminadas de la caché:",
"Unused local loopback TCP port for this device:": "Puerto TCP de loopback local libre para este dispositivo:",
"Update": "Actualización",
"Update Available": "Actualización disponible",
"Update Ceph repository (Only if using Ceph):": "Actualiza el repositorio de Ceph (solo si usas Ceph):",
@@ -7826,6 +7906,7 @@
"Update the whole stack?": "¿Actualizar toda la pila?",
"Update, modify or recreate one installed OCI instance": "Actualizar, modificar o recrear una instancia OCI instalada",
"Updated": "Actualizado",
"Updated recipes since your last visit: {count}": "Recetas actualizadas desde tu última visita: {count}",
"Updated sharedfiles group to GID: 101000": "Grupo de archivos compartidos actualizado a GID: 101000",
"Updated stack checked": "Pila actualizada comprobada",
"Updated:": "Actualizado:",
@@ -7889,6 +7970,7 @@
"Use a privileged LXC for NFS server/client workflows.": "Utiliza un LXC privilegiado para flujos de trabajo de servidor/cliente NFS.",
"Use a privileged LXC for Samba client/server workflows.": "Utiliza un LXC privilegiado para flujos de trabajo de cliente/servidor Samba.",
"Use a registry hostname, for example ghcr.io or registry.example.com:5000.": "Escribe el nombre de un registro, por ejemplo ghcr.io o registry.example.com:5000.",
"Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time.": "Usa un proxy inverso HTTPS con un certificado de confianza. Actualiza Nextcloud de una versión principal a la siguiente, sin saltarte ninguna.",
"Use an existing SSH private key file on this host": "Usar un archivo de clave privada SSH existente en este host",
"Use an existing keyfile": "Usar un archivo de claves existente",
"Use an image reference, for example ghcr.io/owner/app:latest.": "Escribe una referencia de imagen, por ejemplo ghcr.io/owner/app:latest.",
@@ -7902,6 +7984,7 @@
"Use existing filesystem": "Usar el sistema de archivos existente",
"Use existing: mount without formatting": "Usar existente: montar sin formatear",
"Use images only if the directory is on suitable storage.": "Utiliza imágenes solo si el directorio está en un almacenamiento adecuado.",
"Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.": "Usa almacenamiento gestionado para /config y MariaDB. Para /data puedes elegir un directorio del host/NAS, que necesita su propia copia de seguridad.",
"Use mp1/mp2/... for extra mount points.": "Utiliza mp1/mp2/... para puntos de montaje adicionales.",
"Use only when unprivileged containers cannot meet your needs": "Úselo solo cuando los contenedores sin privilegios no puedan satisfacer sus necesidades",
"Use option 1 to add a local disk (as Proxmox storage and/or as a host mount).": "Utiliza la opción 1 para añadir un disco local (como almacenamiento Proxmox y/o como montaje de host).",
@@ -8031,6 +8114,7 @@
"Variables": "Variables",
"Variables the installation asks for:": "Variables que pide la instalación:",
"Vaultwarden Web Vault": "Vaultwarden Web Vault",
"Vector illustration in your browser": "Ilustración vectorial en el navegador",
"Vector search engine with a built-in dashboard.": "Motor de búsqueda vectorial con panel integrado.",
"Vendor Specific": "Específico del proveedor",
"Verbose pool status": "Estado detallado del grupo",
@@ -8063,6 +8147,7 @@
"VictoriaLogs": "VictoriaLogs",
"Video": "Vídeo",
"Video acceleration and object detection are independent choices; the installer does not write camera or detector YAML.": "La aceleración de vídeo y la detección de objetos se eligen por separado; el instalador no escribe el YAML de cámaras ni de detectores.",
"Video editing in your browser": "Edición de vídeo en el navegador",
"Video transcoding acceleration": "Aceleración de transcodificación de vídeo",
"Video transcoding profile not implemented:": "Perfil de transcodificación de vídeo no implementado:",
"View CIFS Mounts (pvesm + fstab)": "Ver montajes CIFS (pvesm + fstab)",
@@ -8072,6 +8157,7 @@
"View Disk Storages": "Ver almacenamientos en disco",
"View Mount Points": "Ver puntos de montaje",
"View NFS Mounts (pvesm + fstab)": "Ver montajes NFS (pvesm + fstab)",
"View USB/IP status": "Ver el estado de USB/IP",
"View backup metadata": "Ver metadatos de backup",
"View current paths": "Ver rutas actuales",
"View existing folders in /mnt": "Ver carpetas existentes en /mnt",
@@ -8172,12 +8258,17 @@
"Web access": "Acceso web",
"Web address of the AdGuard Home that receives the settings (e.g. http://192.168.1.3)": "Dirección web del AdGuard Home que recibe los ajustes (por ejemplo, http://192.168.1.3)",
"Web address of the main AdGuard Home, whose settings are copied (e.g. http://192.168.1.2)": "Dirección web del AdGuard Home principal, cuyos ajustes se copian (por ejemplo, http://192.168.1.2)",
"Web dashboard": "Panel web",
"Web dashboard and WebDAV": "Panel web y WebDAV",
"Web interface": "interfaz web",
"Web interface for Borg Backup repositories and jobs.": "Interfaz web para gestionar repositorios y tareas de Borg Backup.",
"Web interface for managing 3D printers.": "Interfaz web para gestionar impresoras 3D.",
"Web interface to manage devices running Tasmota firmware.": "Interfaz web para gestionar dispositivos con firmware Tasmota.",
"Web reverse proxy with an administration interface.": "Proxy inverso web con interfaz de administración.",
"WebCord can be summarized as a pack of security and privacy hardenings, Discord features reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, internal pages and wrapped https://discord.com page, designed to conform with ToS as much as it is possible (or hide the changes that might violate it from Discord's eyes).": "WebCord puede resumirse como un conjunto de medidas de hardening de seguridad y privacidad, reimplementaciones de funciones de Discord, soluciones a fallos de Electron / Chromium / Discord, hojas de estilo, páginas internas y la página https://discord.com encapsulada, diseñado para cumplir los ToS en lo posible (u ocultar a Discord los cambios que podrían incumplirlos).",
"WebDAV": "WebDAV",
"WebDAV and dashboard password (leave empty to generate)": "Contraseña de WebDAV y del panel (vacío = generada)",
"WebDAV is available on container port 8080. Account linking is required before cloud file operations.": "WebDAV está disponible en el puerto 8080 del contenedor. Hay que vincular la cuenta antes de trabajar con los archivos de la nube.",
"Webgrabplus is a multi-site incremental xmltv epg grabber. It collects tv-program guide data from selected tvguide sites for your favourite channels.": "Webgrabplus es un capturador incremental de EPG xmltv para múltiples sitios. Recoge los datos de la guía de programación de los sitios de guías de TV seleccionados para tus canales favoritos.",
"Webservers & Proxies": "Webservers & Proxies",
"Website": "Sitio web",
@@ -8234,6 +8325,7 @@
"Without a usable reset path, passthrough reliability is poor and VM": "Sin una ruta de reset utilizable, la fiabilidad del passthrough es baja y la VM",
"Wizard cancelled": "Asistente cancelado",
"Wolfenstein: Blade of Agony is a story-driven WWII shooter inspired by Wolfenstein and Doom.": "Wolfenstein: Blade of Agony es un shooter de la Segunda Guerra Mundial con historia, inspirado en Wolfenstein y Doom.",
"Word processing in your browser": "Procesador de textos en el navegador",
"Workflow automation tool": "Herramienta de automatización de flujos de trabajo",
"Working directory:": "Directorio de trabajo:",
"Works with LVM, ZFS, and BTRFS storage types": "Funciona con tipos de almacenamiento LVM, ZFS y BTRFS",
@@ -8284,6 +8376,8 @@
"Your machine learning Env work with Jupyter Lab": "Tu entorno de machine learning con Jupyter Lab",
"Your next YouTube media manager": "Tu próximo gestor multimedia de YouTube",
"Your_spotify is a self-hosted application that tracks what you listen and offers you a dashboard to explore statistics about it! It's composed of a web server which polls the Spotify API every now and then and a web application on which you can explore your statistics.": "¡Your_spotify es una aplicación autoalojada que registra lo que escuchas y te ofrece un panel para explorar tus estadísticas! Consta de un servidor web que consulta la API de Spotify cada cierto tiempo y una aplicación web donde explorar tus estadísticas.",
"Z-Wave JS UI": "Z-Wave JS UI",
"Z-Wave JS UI admin login": "Z-Wave JS UI inicio de sesión de administrador",
"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",
@@ -8397,6 +8491,7 @@
"could not be compiled for kernel": "no se pudo compilar para el kernel",
"could not validate NVIDIA; exit code": "no puede validar NVIDIA; código de salida",
"cpuunits must be between 8 and 10000": "cpuunits debe ser entre 8 y 10000",
"curl -L -o /models/gemma-3-1b-it-Q4_K_M.gguf https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf": "curl -L -o /models/gemma-3-1b-it-Q4_K_M.gguf https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf",
"custom": "personalizado",
"custom dependency commands are not yet supported": "los comandos de dependencia personalizados todavía no son compatibles",
"custom path(s) saved.": "rutas personalizadas guardadas.",
@@ -8602,6 +8697,7 @@
"kexec-tools is not installed or already removed.": "kexec-tools no está instalado o ya se ha eliminado.",
"layers": "capas",
"legacy .link file(s) to the ProxMenux-managed format": "archivo(s) .link antiguos al formato gestionado por ProxMenux",
"llama.cpp shows every GGUF model saved in /models in its web UI and loads the one you choose.": "llama.cpp muestra en su interfaz web todos los modelos GGUF guardados en /models y carga el que elijas.",
"log2ram completely removed from system": "log2ram completamente eliminado del sistema",
"main container of the application": "contenedor principal de la aplicación",
"make cloned mount tree read-only": "hacer de solo lectura el árbol de montaje clonado",
+96
View File
@@ -184,6 +184,7 @@
"A tunneling daemon by Cloudflare that safely exposes your web servers into the internet.": "Un démon de tunnel par Cloudflare qui expose en toute sécurité vos serveurs web dans Internet.",
"A unified email and collaboration server.": "Un serveur unifié de messagerie et de collaboration.",
"A unified platform for logs, metrics and traces.": "Une plateforme unifiée pour les journaux, les métriques et les traces.",
"A validating, recursive DNS resolver for your private network.": "Un résolveur DNS récursif de validation pour votre réseau privé.",
"A versatile file conversion tool that supports multiple formats.": "Un outil de conversion de fichiers polyvalent qui prend en charge plusieurs formats.",
"A visual tool for exploring and documenting database schemas.": "Un outil visuel pour explorer et documenter les schémas de bases de données.",
"A web GUI client of Project V which supports VMess, VLESS, SS, SSR, Trojan, Tuic and Juicity protocols": "Un client web GUI du Projet V qui prend en charge les protocoles VMess, VLESS, SS, SSR, Trojan, Tuic et Juicity",
@@ -245,6 +246,7 @@
"Aborted": "Avorté",
"About to restore": "Sur le point de restaurer",
"Absolute directory path to use as backup target:": "Chemin du répertoire absolu à utiliser comme cible de sauvegarde :",
"Absolute path of the client SSH private key:": "Chemin absolu de la clé privée SSH du client :",
"Absolute path to a file or directory you want backed up:": "Chemin absolu vers un fichier ou un répertoire que vous souhaitez sauvegarder :",
"Acceleration": "Accélération",
"Acceleration configuration cancelled": "Configuration d'accélération annulée",
@@ -256,6 +258,7 @@
"Acceleration for llama.cpp": "Accélération pour llama.cpp",
"Accept routes from other nodes?": "Accepter les routes d'autres nœuds ?",
"Accept this host monitoring profile?": "Accepter ce profil de surveillance de l'hôte?",
"Access Movistar and O2 Cloud from WebDAV clients and backup tools.": "Accédez au cloud Movistar et O2 depuis des clients WebDAV et des outils de sauvegarde.",
"Access Scope:": "Portée d'accès :",
"Access bridge": "Pont d'accès",
"Access bridge for Immich": "Pont d'accès pour Immich",
@@ -410,6 +413,7 @@
"After the reboot, you will only be able to access the Proxmox host via:": "Après le redémarrage, vous ne pourrez accéder à l'hôte Proxmox que via :",
"After this LXC → VM switch, reboot the host so the new binding state is applied cleanly.": "Après ce commutateur LXC → VM, redémarrez l'hôte afin que le nouvel état de liaison soit appliqué proprement.",
"Agentless monitoring and observability platform.": "Plateforme de supervision et d’observabilité sans agent.",
"AirDC++ administrator": "Administrateur AirDC++",
"Airsonic Advanced web interface": "Interface web Airsonic Advanced",
"Airsonic-advanced is a free, web-based media streamer, providing ubiquitious access to your music. Use it to share your music with friends, or to listen to your own music while at work. You can stream to multiple players simultaneously, for instance to one player in your kitchen and another in your living room.": "Airsonic-Advanced est un flux multimédia gratuit, basé sur le web, offrant un accès ubiquitious à votre musique. Utilisez-le pour partager votre musique avec des amis, ou pour écouter votre propre musique au travail. Vous pouvez diffuser simultanément vers plusieurs joueurs, par exemple vers un joueur dans votre cuisine et un autre dans votre salon.",
"Aliases added to .bashrc": "Alias ajoutés à .bashrc",
@@ -598,11 +602,15 @@
"Attention: Removing the subscription banner may cause issues in the web interface after a future update.": "Attention : La suppression de la bannière d'abonnement peut entraîner des problèmes dans l'interface Web après une future mise à jour.",
"Audacity is an easy-to-use, multi-track audio editor and recorder. Developed by a group of volunteers as open source.": "Audacity est un éditeur et un enregistreur audio facile à utiliser. Développé par un groupe de volontaires comme source ouverte.",
"Audio device directory": "Répertoire des périphériques audio",
"Audio recording and mixing in your browser": "Enregistrement et mixage audio dans le navigateur",
"Audiobookshelf is a self-hosted audiobook and podcast server.": "Audiobookshelf est un livre audio et un serveur podcast auto-organisé.",
"Audit completed. Press Enter to continue...": "Vérification terminée. Appuyez sur Entrée pour continuer...",
"Audit socket disabled or not required": "Socket d'audit désactivé ou non requis",
"Auth key is required.": "La clé d'authentification est requise.",
"Auth:": "Authentification :",
"Authelia Web UI": "interface utilisateur Web Authelia",
"Authelia administrator": "Administrateur Authelia",
"Authelia session cookie domain for this portal (for example example.com)": "domaine de cookie de session Authelia pour ce portail (par exemple exemple.com)",
"Authentication": "Authentification",
"Authentication & Security": "Authentification et sécurité",
"Authentication Error": "Erreur d'authentification",
@@ -612,6 +620,8 @@
"Authentication:": "Authentification:",
"Authorization failed": "L'autorisation a échoué",
"Authorization successful": "Autorisation réussie",
"Authorize a client SSH public key": "Autoriser la clé publique SSH d’un client",
"Authorize a dedicated client public key on the server first. The restricted USB/IP account cannot run a shell or forward other sockets. Verify the server host key before connecting; unknown keys are rejected.": "Autorisez d’abord une clé publique dédiée au client sur le serveur. Le compte USB/IP restreint ne peut ni ouvrir de shell ni rediriger d’autres sockets. Vérifiez la clé d’hôte du serveur avant la connexion ; les clés inconnues sont refusées.",
"Authorize this key on the server": "Autoriser cette clé sur le serveur",
"Authorize via 'pct exec' (Borg server is an LXC on a PVE host I can SSH into)": "Autoriser via 'pct exec' (le serveur Borg est un LXC sur un hôte PVE sur lequel je peux me connecter en SSH)",
"Authorized": "Autorisé",
@@ -642,6 +652,7 @@
"Available PVE Version": "Version PVE disponible",
"Available Shares:": "Actions disponibles :",
"Available action": "Action disponible",
"Available applications: {count}": "Applications disponibles : {count}",
"Available archives:": "Archives disponibles :",
"Available disks detected.": "Disques disponibles détectés.",
"Available host backups:": "Sauvegardes d'hôte disponibles :",
@@ -873,6 +884,7 @@
"Cannot write the image archive to {storage}. Check storage access and mount status.": "Impossible d'écrire l'archive d'images sur {storage}. Vérifiez l'accès au stockage et l'état du montage.",
"Capabilities cannot be kept and all dropped at the same time": "Les capacités ne peuvent être conservées et toutes abandonnées en même temps",
"Catalog options": "Options du catalogue",
"Catalog refresh unavailable; using the local catalog.": "Impossible de mettre à jour le catalogue ; le catalogue local est utilisé.",
"Category": "Catégorie",
"Caution: Maximum mode generates more heat.": "Attention : le mode maximum génère plus de chaleur.",
"Central server for file and image backups.": "Serveur central pour les sauvegardes de fichiers et d’images.",
@@ -1159,6 +1171,7 @@
"Compressing": "Compression",
"Compression": "Compression",
"Compression Tools": "Outils de compression",
"Computer-aided design and drafting in your browser": "Conception assistée par ordinateur et dessin technique dans le navigateur",
"Concise output of logical volumes": "Sortie concise des volumes logiques",
"Concise output of physical volumes": "Sortie concise des volumes physiques",
"Concise output of volume groups": "Sortie concise des groupes de volumes",
@@ -1289,6 +1302,7 @@
"Conflicting utilities removed": "Utilitaires en conflit supprimés",
"Connect Zigbee devices to MQTT with a browser-based setup interface.": "Connectez les appareils Zigbee à MQTT via une interface web de configuration.",
"Connect a Coral Accelerator and try again.": "Connectez un accélérateur Coral et réessayez.",
"Connect a remote USB device": "Connecter un périphérique USB distant",
"Connect it, or remove it from the container in Proxmox (Resources), and run the recovery again.": "Connectez-le ou supprimez-le du conteneur dans Proxmox (Ressources) et réexécutez la récupération.",
"Connect your devices and users together in your own secure virtual private network.": "Connectez vos appareils et utilisateurs ensemble dans votre propre réseau privé virtuel sécurisé.",
"Connect your devices into a secure WireGuard®-based overlay network with SSO, MFA and granular access controls.": "Connectez vos appareils à un réseau de superposition sécurisé basé sur WireGuard® avec des contrôles d'accès SSO, MFA et granulaires.",
@@ -1393,6 +1407,7 @@
"Controller + NVMe": "Contrôleur + NVMe",
"Controller + NVMe assignment will be written now and become active after host reboot.": "L'affectation Contrôleur + NVMe sera écrite maintenant et deviendra active après le redémarrage de l'hôte.",
"Controller + NVMe passthrough requires machine type q35. Skipping controller assignment.": "Le contrôleur + le relais NVMe nécessite une machine de type q35. Ignorer l'affectation du contrôleur.",
"Controller path on the Proxmox host; prefer /dev/serial/by-id/...": "Chemin du contrôleur sur l’hôte Proxmox ;préférez /dev/serial/by-id/...",
"Controller/NVMe Conflict Policy": "Politique de conflit contrôleur/NVMe",
"Controller/NVMe already present in VM config": "Contrôleur/NVMe déjà présent dans la configuration de la VM",
"Controller/NVMe already present in VM config (%s)": "Contrôleur/NVMe déjà présent dans la configuration de la VM (%s)",
@@ -1927,6 +1942,7 @@
"Dgraph": "Dgraph",
"Diff: current system vs backup (--- system +++ backup)": "Diff : système actuel vs sauvegarde (--- système +++ sauvegarde)",
"Different host. Backup from:": "Hôte différent. Sauvegarde depuis :",
"Direct Connect file sharing with a web interface": "Partage de fichiers Direct Connect avec une interface web",
"Direct conversion completed for container": "Conversion directe terminée pour le conteneur",
"Directory Exists": "Le répertoire existe",
"Directory Not Empty": "Répertoire non vide",
@@ -1949,12 +1965,14 @@
"Directus administrator": "Administrateur Directus",
"Disable NIC Offloading (Intel e1000e)": "Désactiver le déchargement de la carte réseau (Intel e1000e)",
"Disable Secure Boot in the UEFI firmware and run the installer again. Nothing has been changed.": "Désactivez Secure Boot dans le firmware UEFI et relancez le programme d'installation. Rien n'a été modifié.",
"Disable USB/IP server": "Désactiver le serveur USB/IP",
"Disable autostart on conflicting VM": "Désactiver le démarrage automatique sur la VM en conflit",
"Disable autostart on one VM to avoid startup conflicts.": "Désactivez le démarrage automatique sur une VM pour éviter les conflits de démarrage.",
"Disable job": "Désactiver le travail",
"Disable kernel audit messages (optional but recommended):": "Désactivez les messages d'audit du noyau (facultatif mais recommandé) :",
"Disable onboot on affected VM(s)/CT(s)": "Désactiver le démarrage sur les VM/CT concernés",
"Disable portmapper/rpcbind": "Désactiver portmapper/rpcbind",
"Disable the server and release all USB devices managed by ProxMenux? Saved selections are kept for the next enable.": "Désactiver le serveur et libérer tous les périphériques USB gérés par ProxMenux ? Les sélections enregistrées seront conservées pour la prochaine activation.",
"Disabled": "Désactivé",
"Disabling High Availability services...": "Désactivation des services haute disponibilité...",
"Disabling ZFS autotrim applied by ProxMenux...": "Désactivation du découpage automatique ZFS appliqué par ProxMenux...",
@@ -2187,6 +2205,7 @@
"Enable Remote Desktop (RDP) before disabling the virtual display.": "Activez le Bureau à distance (RDP) avant de désactiver l'affichage virtuel.",
"Enable SSD emulation for this disk?": "Activer l'émulation SSD pour ce disque ?",
"Enable TCP BBR/Fast Open control": "Activer le contrôle TCP BBR/Fast Open",
"Enable USB/IP server": "Activer le serveur USB/IP",
"Enable VA-API transcoding and HDR10/Dolby Vision to SDR tone mapping": "Activer le transcodage VA-API et HDR10/Dolby Vision pour la cartographie des tons SDR",
"Enable VA-API, hardware encoding and OpenCL tone mapping in Jellyfin": "Activer le VA-API, l'encodage matériel et la cartographie des tons OpenCL dans Jellyfin",
"Enable VFIO IOMMU support": "Activer la prise en charge de VFIO IOMMU",
@@ -3200,6 +3219,7 @@
"If pvesm path returned a DEVICE (LVM):": "Si pvesm path a renvoyé un PÉRIPHÉRIQUE (LVM) :",
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Si pvesm path a renvoyé un RÉPERTOIRE (ZFS/BTRFS) :",
"If repositories error:": "Si erreur de référentiels :",
"If the USB/IP service stops unexpectedly, stop sharing while the device is still connected to release it. In rare cases only a host reboot releases it.": "Si le service USB/IP s'arrête de manière inattendue, arrêtez le partage tant que le périphérique est encore branché pour le libérer. Dans de rares cas, seul un redémarrage de l'hôte le libère.",
"If the container had already been changed, its previous native backup is restored. Shared host directories are not reverted. The disks of the failed attempt are removed when the cleanup succeeds.": "Si le conteneur a déjà été modifié, sa sauvegarde native précédente est restaurée. Les répertoires hôtes partagés ne sont pas rétablis. Les disques de la tentative ayant échoué sont supprimés une fois le nettoyage réussi.",
"If the host freezes, remove hostpci entries from": "Si l'hôte se bloque, supprimez les entrées hostpci de",
"If the image channel has a new version, the CT is stopped, backed up and verified, and replaced with the new image to update the container. If anything fails, the backup is restored.": "Si le canal d'image a une nouvelle version, le CT est arrêté, sauvegardé et vérifié, puis remplacé par la nouvelle image pour mettre à jour le conteneur. Si quelque chose échoue, la sauvegarde est restaurée.",
@@ -3340,6 +3360,7 @@
"Initial Stirling-PDF account": "Compte initial Stirling-PDF",
"Initial Tandoor administrator": "Administrateur Tandoor initial",
"Initial Umami administrator": "Administrateur initial d’Umami",
"Initial Z-Wave JS UI admin password": "Mot de passe administrateur initial Z-Wave JS UI",
"Initial administrator created:": "Administrateur initial créé :",
"Initial administrator user": "Administrateur initial",
"Initializing Borg repository if needed...": "Initialisation du référentiel Borg si nécessaire...",
@@ -3393,6 +3414,7 @@
"Install server packages inside CT:": "Installez les packages de serveur dans CT :",
"Install terminal multiplexers": "Installer des multiplexeurs de terminaux",
"Install the Edge TPU runtime (libedgetpu1-std)": "Installez le runtime Edge TPU (libedgetpu1-std)",
"Install the USB/IP dependencies from the configured Debian repositories?": "Installer les dépendances USB/IP depuis les dépôts Debian configurés ?",
"Install this image?": "Installer cette image ?",
"Install with Cloud-Init script": "Installer avec le script Cloud-Init",
"Install with ISO from UUP Dump": "Installer avec ISO à partir de UUP Dump",
@@ -3525,6 +3547,7 @@
"Interface MTU": "MTU de l'interface",
"Interface Names (persistent)": "noms d'interface (persistants)",
"Interface Type": "Type d'interface",
"Interface design and prototyping in your browser": "Conception d’interfaces et prototypage dans le navigateur",
"Interface names will return to default systemd behavior.": "Les noms d’interface reviendront au comportement systemd par défaut.",
"Interface type:": "Type d'interface :",
"Interfaces configured": "Interfaces configurées",
@@ -3582,6 +3605,7 @@
"Invalid check package:": "Dossier de contrôle non valide:",
"Invalid configuration path:": "Chemin de configuration non valide & #160;:",
"Invalid consume/export volumes": "Volumes de consommation/d'exportation non valides",
"Invalid container device GID": "GID de périphérique du conteneur invalide",
"Invalid container path:": "Voie du conteneur non valide:",
"Invalid credential file path:": "Chemin de fichier credential incorrect :",
"Invalid declarative entrypoint": "Point de déclaration non valide",
@@ -3740,6 +3764,7 @@
"Jupyter Lab (token only)": "Jupyter Lab (jeton seulement)",
"JupyterLab": "JupyterLab",
"JupyterLab access token": "Jeton d’accès JupyterLab",
"KDE's twin-panel file manager in a browser-based desktop.": "le gestionnaire de fichiers à deux panneaux de KDE dans un bureau basé sur un navigateur.",
"KDF:": "KDF :",
"KROMA": "KROMA",
"KVM MSR options added to /etc/modprobe.d/kvm.conf": "Options KVM MSR ajoutées à /etc/modprobe.d/kvm.conf",
@@ -3787,12 +3812,14 @@
"KiCad - A Cross Platform and Open Source Electronics Design Automation Suite.": "KiCad - Une plateforme croisée et une suite d'automatisation de conception électronique ouverte.",
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "Kimai n’a pas de compte par défaut. Ouvrez un shell dans le conteneur avec : pct enter {main_vmid}",
"Kimai is a professional grade time-tracking application, free and open-source.": "Kimai est une application professionnelle de suivi du temps, libre et open-source.",
"KitchenOwl": "KitchenOwl",
"Kometa is a powerful tool designed to give you complete control over your media libraries. With Kometa, you can take your customization to the next level, with granular control over metadata, collections, overlays, and much more.": "Kometa est un outil puissant conçu pour vous donner un contrôle complet sur vos bibliothèques multimédias. Avec Kometa, vous pouvez porter votre personnalisation au niveau suivant, avec un contrôle granulaire sur les métadonnées, les collections, les superpositions et bien plus encore.",
"Kometa reads its configuration from /config/config.yml and the container only ships /config/config.yml.template. Copy the template to config.yml, fill in the required Plex and TMDb connections, then restart the container.": "Kometa lit sa configuration à partir de /config/config.yml et le conteneur ne livre que /config/config.yml.template. Copiez le modèle pour config.yml, remplissez les connexions required Plex et TMDb, puis redémarrez le conteneur.",
"Komga is a media server for your comics, mangas, BDs, magazines and eBooks.": "Komga est un serveur multimédia pour vos BD, mangas, BD, magazines et eBooks.",
"Kopia Web UI": "Interface web de Kopia",
"Kopia Web UI login": "Connexion à l’interface web de Kopia",
"Krita is a professional FREE and open source painting program. It is made by artists that want to see affordable art tools for everyone.": "Krita est un programme professionnel de peinture libre et GRATUIT. Il est fait par des artistes qui veulent voir des outils d'art abordables pour tout le monde.",
"Krusader Web UI": "interface utilisateur Web Krusader",
"LAN access to the kept containers (stack configuration incomplete):": "Accès au réseau local des conteneurs gardés (configuration incomplète):",
"LAN address applied to the application URLs": "Adresse LAN appliquée aux URL de l'application",
"LLDAP": "LLDAP",
@@ -3873,9 +3900,11 @@
"Line to paste (single line, including \"command=...\" prefix):": "Ligne à coller (une seule ligne, incluant le préfixe \"command=...\") :",
"LinkStack": "LinkStack",
"Linux Installation Options": "Options d'installation Linux",
"Linux guest setup and migration notes": "Configuration des invités Linux et notes de migration",
"Linux/Mac path:": "Chemin Linux/Mac :",
"LinuxServer Jellyfin with optional GPU passthrough": "LinuxServer Jellyfin avec passage GPU optionnel",
"LinuxServer MariaDB requires a user, database and password": "LinuxServer MariaDB requires un utilisateur, une base de données et un mot de passe",
"LinuxServer Nextcloud with MariaDB and Redis": "Nextcloud de LinuxServer avec MariaDB et Redis",
"List Available Disks": "Liste des disques disponibles",
"List IOMMU group mapping": "Répertorier le mappage de groupe IOMMU",
"List NVMe devices": "Répertorier les appareils NVMe",
@@ -4020,6 +4049,7 @@
"Manage OCI stack": "Gérer la pile OCI",
"Manage PBS encryption keyfile": "Gérer le fichier de clés de chiffrement PBS",
"Manage Secure Gateway": "Gérer Secure Gateway",
"Manage a Z-Wave network from a web dashboard and WebSocket gateway.": "Gérez un réseau Z-Wave à partir d'un tableau de bord Web et d'une passerelle WebSocket.",
"Manage and inspect VM disk images": "Gérer et inspecter les images de disque de VM",
"Manage custom backup paths": "Gérer les chemins de sauvegarde personnalisés",
"Manage custom paths (add / remove your folders)": "Gérer les chemins personnalisés (ajouter/supprimer vos dossiers)",
@@ -4029,6 +4059,7 @@
"Manage local backup target": "Gérer la cible de sauvegarde locale",
"Manage private image registries.\nSaved credentials let ProxMenux access your private images.": "Gérer les registres d’images privés.\nLes informations d'identification enregistrées permettent à ProxMenux d'accéder à vos images privées.",
"Manage registry accounts as root on the Proxmox node.": "Gérez les comptes de registre en tant que root sur le nœud Proxmox.",
"Manage teams of AI agents from a web dashboard.": "Gérez des équipes d’agents IA depuis un tableau de bord web.",
"Managed disks must have backup enabled and a valid size": "Les disques gérés doivent avoir une sauvegarde activée et une taille valide",
"Managed public route include is missing": "Le fichier de configuration des routes publiques gérées est manquant",
"Managed public route installation failed": "Impossible de configurer les routes publiques gérées",
@@ -4134,6 +4165,7 @@
"Monitoring": "Surveillance",
"Monitoring & Analytics": "Surveillance et analyse",
"Most common cause: the archive is corrupted (interrupted write, partial copy, or storage issue).": "Cause la plus courante : l'archive est corrompue (écriture interrompue, copie partielle ou problème de stockage).",
"Motion graphics and compositing in your browser": "Animation graphique et compositing dans le navigateur",
"Mount Added Successfully:": "Montage ajouté avec succès :",
"Mount CIFS share:": "Montez le partage CIFS :",
"Mount Configuration Summary:": "Résumé de la configuration du montage :",
@@ -4293,6 +4325,7 @@
"NVIDIA (CUDA; official GPU image)": "NVIDIA (CUDA; image officielle du GPU)",
"NVIDIA (NVDEC/CUDA)": "NVIDIA (NVDEC/CUDA)",
"NVIDIA (NVENC/NVDEC)": "NVIDIA (NVENC/NVDEC)",
"NVIDIA (Selkies rendering and NVENC)": "NVIDIA (rendu Selkies et NVENC)",
"NVIDIA Actions": "Actions NVIDIA",
"NVIDIA CPU hiding already configured": "Le masquage du processeur NVIDIA est déjà configuré",
"NVIDIA Container Toolkit": "Boîte à outils de conteneur NVIDIA",
@@ -4376,6 +4409,7 @@
"Name or part of the option or of the application": "Nom ou partie de l'option ou de l'application",
"Name:": "Nom:",
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Les comptes nommés nécessitent un mode privé. Arrêter le conteneur, définir public: false in /config/config.js, recommencer et créer chaque utilisateur avec: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge ajouter <user>",
"Native Borg is unavailable. Install the native borgbackup package on this host to use Borg backups.": "La version native de Borg n’est pas disponible. Installez le paquet natif borgbackup sur cet hôte pour utiliser les sauvegardes Borg.",
"Needed:": "Nécessaire :",
"Needs": "Nécessite",
"Neither /etc/kernel/cmdline nor /etc/default/grub found.": "Ni /etc/kernel/cmdline ni /etc/default/grub n'ont été trouvés.",
@@ -4434,6 +4468,8 @@
"New Search": "Nouvelle recherche",
"New VM:": "Nouvelle VM :",
"New Virtual Machine": "Nouvelle machine virtuelle",
"New applications ({count})": "Nouvelles applications ({count})",
"New applications since your last visit: {count}": "Nouvelles applications depuis votre dernière visite : {count}",
"New backup job": "Nouveau travail de sauvegarde",
"New backups on this host will be unencrypted until a new keyfile is set up.": "Les nouvelles sauvegardes sur cet hôte ne seront pas chiffrées jusqu'à ce qu'un nouveau fichier de clés soit configuré.",
"New image compatible:": "Nouvelle image compatible & #160;:",
@@ -4449,6 +4485,7 @@
"Next Step Required": "Prochaine étape requise",
"Next Steps:": "Prochaines étapes :",
"Next step: stop that VM first, then run": "Étape suivante : arrêtez d'abord cette VM, puis exécutez",
"Nextcloud Web UI": "Interface web de Nextcloud",
"Nextcloud configuration cancelled": "Configuration Nextcloud annulée",
"Nextcloud gives you access to all your files wherever you are.": "Nextcloud vous donne accès à tous vos fichiers où que vous soyez.",
"Nextcloud volume size in GB": "Taille du volume Nextcloud en GB",
@@ -4623,6 +4660,7 @@
"No duplicate IP addresses": "Pas d'adresses IP en double",
"No duplicate repositories found": "Aucun référentiel en double trouvé",
"No eligible Controller/NVMe devices remain after SR-IOV filtering. Skipping.": "Il ne reste aucun périphérique contrôleur/NVMe éligible après le filtrage SR-IOV. Saut.",
"No eligible USB devices found. Hubs, mass storage and network adapters are excluded.": "Aucun périphérique USB éligible trouvé. Les concentrateurs, les périphériques de stockage de masse et les adaptateurs réseau sont exclus.",
"No eligible controllers remain after SR-IOV filtering.": "Il ne reste aucun contrôleur éligible après le filtrage SR-IOV.",
"No encryption key is stored on this host. Choose how to set one up:": "Aucune clé de cryptage n’est stockée sur cet hôte. Choisissez comment en configurer un :",
"No exportable VM disks were found (CD-ROM/cloud-init are excluded).": "Aucun disque de VM exportable n'a été trouvé (les CD-ROM/cloud-init sont exclus).",
@@ -4707,6 +4745,7 @@
"No self-test log available for": "Aucun journal d'autotest disponible pour",
"No server IP or hostname provided.": "Aucune adresse IP de serveur ou nom d'hôte fourni.",
"No share access test succeeded with guest authentication.": "Aucun test d'accès au partage n'a réussi avec l'authentification des invités.",
"No shared devices are available on this server.": "Aucun périphérique partagé n'est disponible sur ce serveur.",
"No shared media content.": "Pas de contenu multimédia partagé.",
"No shared mount detected. Applying standard local access.": "Aucun montage partagé détecté. Application d'un accès local standard.",
"No shares configured.": "Aucun partage configuré.",
@@ -4896,6 +4935,8 @@
"Open the page of an application in the menu": "Ouvrir la page d'une application dans le menu",
"Open the web address and create the first account: the daemon registers by itself and starts the first scan.": "Ouvrez l'adresse web et créez le premier compte : le daemon s'enregistre tout seul et lance la première analyse.",
"Open the web address and create the password of the akadmin user in the first-run setup.": "ouvrez l'adresse Web et créez le mot de passe de l'utilisateur akadmin lors de la configuration de première exécution.",
"Open the web address and follow KitchenOwl’s onboarding to create the first account; no default account is configured.": "ouvrez l'adresse Web et suivez l'intégration de KitchenOwl pour créer le premier compte ;aucun compte par défaut n'est configuré.",
"Open the web dashboard and link your Movistar/O2 account using its SMS flow.": "Ouvrez le tableau de bord web et liez votre compte Movistar/O2 avec sa vérification par SMS.",
"Open-source AI-powered coding assistant": "Assistant de codage à source ouverte",
"Open-source UI for building and debugging multi-agent and RAG applications": "UI open-source pour la construction et le débogage d'applications multi-agents et RAG",
"Open-source in-memory data store.": "Magasin de données en mémoire libre.",
@@ -5018,6 +5059,7 @@
"Packages:": "Forfaits :",
"Packaging OVA file...": "Emballage du fichier OVA...",
"Packing installer archive...": "Archive du programme d'installation de l'emballage...",
"Page layout and publishing in your browser": "Mise en page et publication dans le navigateur",
"PairDrop is a sublime alternative to AirDrop that works on all platforms. Send images, documents or text via peer to peer connection to devices in the same local network/Wi-Fi or to paired devices.": "PairDrop est une sublime alternative à AirDrop qui fonctionne sur toutes les plateformes. Envoyez des images, des documents ou du texte via une connexion pair à des appareils du même réseau local/Wi-Fi ou à des appareils appariés.",
"Paperless configuration cancelled": "Configuration sans papier annulée",
"Paperless-ngx WebUI": "Paperless-ngx WebUI",
@@ -5036,6 +5078,7 @@
"Pass /dev/video12 to the LXC": "Passer /dev/video12 au LXC",
"Pass a host device to the LXC": "Passer un appareil hôte au LXC",
"Pass the UPS to the LXC": "Passer l'UPS au LXC",
"Pass through a Z-Wave USB or serial controller": "Passer par un contrôleur USB ou série Z-Wave",
"Passing NVIDIA does not enable acceleration inside the application. The host needs NVIDIA Container Toolkit and a compatible image. Continue?": "Passer NVIDIA n’active pas l’accélération dans l’application. L'hôte a besoin du NVIDIA Container Toolkit et d'une image compatible. Continuer?",
"Passkey-based identity provider for self-hosted apps.": "Fournisseur d’identité utilisant des passkeys pour les applications auto-hébergées.",
"Passphrase used to unlock the imported keyfile (leave blank if the keyfile is unencrypted / kdf=none):": "Phrase secrète utilisée pour déverrouiller le fichier de clés importé (laisser vide si le fichier de clés n'est pas chiffré / kdf=aucun) :",
@@ -5101,6 +5144,7 @@
"Path of the Compose file": "Chemin du fichier Composer",
"Path of the oci-compose file": "Chemin du fichier oci-compose",
"Path removed:": "Chemin supprimé :",
"Path to the client SSH public key on this server:": "Chemin de la clé publique SSH du client sur ce serveur :",
"Path:": "Chemin:",
"Paths applied:": "Chemins appliqués :",
"Paths included in backup": "Chemins inclus dans la sauvegarde",
@@ -5143,6 +5187,8 @@
"Personal finance management application": "Demande de gestion des finances personnelles",
"Personal media server for browsing and playing a local video library, with direct play and optional modules.": "Serveur multimédia personnel pour parcourir et lire une vidéothèque locale, avec lecture directe et modules facultatifs.",
"Photo and video library with optional GPU transcoding and machine learning": "Photothèque et vidéothèque avec transcodage GPU optionnel et apprentissage automatique",
"Photo editing in your browser": "Retouche photo dans le navigateur",
"Photo library and RAW development in your browser": "Photothèque et développement RAW dans le navigateur",
"PhotoPrism": "PhotoPrism",
"Photofield": "Photofield",
"Phpmyadmin is a free software tool written in PHP, intended to handle the administration of MySQL over the Web. phpMyAdmin supports a wide range of operations on MySQL and MariaDB.": "Phpmyadmin est un logiciel libre écrit en PHP, destiné à gérer l'administration de MySQL sur le Web. phpMyAdmin prend en charge une large gamme de operations sur MySQL et MariaDB.",
@@ -5235,6 +5281,7 @@
"Preparing the machine learning container for the new choice...": "Préparation du conteneur d'apprentissage automatique pour le nouveau choix...",
"Preparing the recreation...": "Préparer les loisirs...",
"Preparing the update...": "Préparation de la mise à jour...",
"Presentations and slide decks in your browser": "Présentations et diaporamas dans le navigateur",
"Preserving logs to /var/log.hdd before unmounting...": "Conserver les journaux dans /var/log.hdd avant de démonter...",
"Press 'q' to exit": "Appuyez sur « q » pour quitter",
"Press Ctrl+C to stop the server and return to menu.": "Appuyez sur Ctrl+C pour arrêter le serveur et revenir au menu.",
@@ -5340,6 +5387,7 @@
"ProxMenux does not install them. The installation asks how to connect to them.": "ProxMenux ne les installe pas. L'installation demande comment s'y connecter.",
"ProxMenux does not validate the contents; any keyfile your PBS accepts is accepted here.": "ProxMenux ne valide pas le contenu ;tout fichier clé accepté par votre PBS est accepté ici.",
"ProxMenux files:": "Fichiers ProxMenux :",
"ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.": "ProxMenux génère le mot de passe de l'administrateur et l'affiche à la fin de l'installation. Modifiez-le après la première connexion.",
"ProxMenux logo applied": "Logo ProxMenux appliqué",
"ProxMenux only acts as a launcher — once the script starts, control leaves ProxMenux.": "ProxMenux agit uniquement comme un lanceur : une fois le script démarré, le contrôle quitte ProxMenux.",
"ProxMenux saved it locally at:": "ProxMenux l'a enregistré localement à :",
@@ -5395,6 +5443,7 @@
"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",
"Proxy address to reach the API (optional)": "Adresse proxy pour accéder à l'API (facultatif)",
"Public HTTPS URL used to open this Authelia portal (for example https://auth.example.com)": "URL HTTPS publique utilisée pour ouvrir ce portail Authelia (par exemple https://auth.example.com)",
"Public UDP port clients connect to": "Les clients du port UDP public se connectent à",
"Public UDP port peers connect to": "Les pairs du port UDP public se connectent à",
"Public URL of phpMyAdmin when it is served behind a reverse proxy": "URL publique de phpMyAdmin quand elle est servie derrière un proxy inversé",
@@ -5455,6 +5504,7 @@
"Re-running pre-check after repairs...": "Nouvelle vérification préalable après réparation...",
"Reachable": "Accessible",
"Read an oci-compose from a file of this host": "Lire un oci-compose à partir d'un fichier de cet hôte",
"Read and edit PDF documents in your browser": "Lire et modifier des documents PDF dans le navigateur",
"Read its Compose file from a file of this host": "Lire son fichier Composer à partir d'un fichier de cet hôte",
"Read manga through a self-hosted server and web UI.": "Lire des mangas via un serveur auto-hébergé et son interface web.",
"Read the link with pct console CTID on the Proxmox host, or from the Console panel of the container in the Proxmox web interface, then open the https://playit.gg/claim/ address it shows in a browser and sign in to playit.gg. Ctrl+a q leaves pct console.": "Lisez le lien avec la console pct CTID sur l'hôte Proxmox, ou depuis le panneau Console du conteneur dans l'interface web Proxmox, puis ouvrez l'adresse https://playit.gg/claim/ qu'elle affiche dans un navigateur et connectez-vous à playit.gg. Ctrl+a q quitte la console pct.",
@@ -5558,8 +5608,10 @@
"Recreation prepared": "Loisirs préparés",
"Recursive DNS resolver.": "Résolveur DNS récursif.",
"Recursive and authoritative DNS server.": "Serveur DNS récursif et faisant autorité.",
"Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.": "Le verrouillage avec Redis est configuré automatiquement. Les fichiers de configuration existants de Nextcloud sont conservés.",
"Redmine": "Redmine",
"Refresh APT index and verify repositories:": "Actualisez l'index APT et vérifiez les référentiels :",
"Refresh catalog": "Actualiser le catalogue",
"Refresh the configured APT repositories and review the PBS package upgrade? Repository files will be preserved.": "Actualiser les dépôts APT configurés et examiner la mise à niveau des paquets PBS ? Les fichiers des dépôts seront conservés.",
"Refresh the index from the image sources": "Actualiser l'index à partir des sources d'images",
"Refresh token of the connector, from the Twingate admin console": "Jeton d'actualisation du connecteur, depuis la console d'administration Twingate",
@@ -5567,6 +5619,7 @@
"Refresh your browser to see changes (server restart may be required)": "Actualisez votre navigateur pour voir les modifications (un redémarrage du serveur peut être nécessaire)",
"Refreshing apt cache...": "Actualisation du cache apt...",
"Refreshing the NVIDIA runtime...": "Rafraîchir l'exécution NVIDIA...",
"Refreshing the application catalog...": "Mise à jour du catalogue des applications...",
"Refusing an unexpected rootfs path:": "Refuser un chemin inattendu de roofs :",
"Regenerate the catalog templates": "Régénérer les modèles du catalogue",
"Regenerate the template of one application": "Régénérer le modèle d'une application",
@@ -5639,6 +5692,7 @@
"Remove Proxmox NFS storage:": "Supprimez le stockage Proxmox NFS :",
"Remove Proxmox iSCSI storage:": "Supprimez le stockage iSCSI Proxmox :",
"Remove Secure Gateway? State will be preserved.": "Supprimer Secure Gateway ? L'État sera préservé.",
"Remove a remote USB connection": "Supprimer une connexion USB distante",
"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 toutes les versions DKMS de gasket enregistrées",
@@ -5659,6 +5713,7 @@
"Remove the lock left on a container by an interrupted task": "Supprimer le verrou laissé sur un conteneur par une tâche interrompue",
"Remove the saved credentials for {registry}?\nRunning apps will keep working.": "Supprimer les informations d'identification enregistrées pour {registry} ?\nLes applications en cours d’exécution continueront de fonctionner.",
"Remove the unprivileged flag from configuration:": "Supprimez l'indicateur sans privilèges de la configuration :",
"Remove this connection and detach its USB device?": "Supprimer cette connexion et détacher son périphérique USB ?",
"Remove unused packages and their config": "Supprimer les packages inutilisés et leur configuration",
"Remove: delete the application and its containers": "Supprimer: supprimer l'application et ses conteneurs",
"Removed": "Supprimé",
@@ -5881,9 +5936,11 @@
"Run mode: Unattended": "Mode d'exécution : sans surveillance",
"Run now": "Exécuter maintenant",
"Run security audit now": "Exécutez un audit de sécurité maintenant",
"Run the client inside the Linux VM that needs the USB device. Install usbip, openssh-client and kmod, then copy usbip_manager.py to the same path as on the server. Configure key authentication and verify the server host key before adding a connection. The client uses the guest kernel and can reconnect after migration while the physical USB device stays on the server. Unprivileged LXC and Home Assistant OS need their own kernel/device or add-on setup. A physical device supports one attached client at a time.": "Exécutez le client dans la VM Linux qui a besoin du périphérique USB. Installez usbip, openssh-client et kmod, puis copiez usbip_manager.py au même chemin que sur le serveur. Configurez l'authentification par clé et vérifiez la clé d'hôte du serveur avant d'ajouter une connexion. Le client utilise le noyau de l'invité et peut se reconnecter après une migration tandis que le périphérique USB physique reste sur le serveur. Les LXC non privilégiés et Home Assistant OS nécessitent une configuration spécifique du noyau, des périphériques ou des modules complémentaires. Un périphérique physique ne peut être attaché qu'à un seul client à la fois.",
"Run the following inside the VM:": "Exécutez la commande suivante dans la VM :",
"Run the release-channel switch from an SSH session or the Proxmox host console with:": "Exécutez le commutateur de canal de version à partir d'une session SSH ou de la console hôte Proxmox avec :",
"Run the update from an SSH session or the Proxmox host console with:": "Exécutez la mise à jour depuis une session SSH ou la console hôte Proxmox avec :",
"Run this menu as root.": "Exécutez ce menu en tant que root.",
"Run this operation as root.": "Exécutez cette opération en tant que root.",
"Run upgrade checklist script:": "Exécutez le script de liste de contrôle de mise à niveau :",
"Running": "En cours d'exécution",
@@ -6108,6 +6165,7 @@
"Select a new language for the menu:": "Sélectionnez une nouvelle langue pour le menu :",
"Select a post-installation script:": "Sélectionnez un script de post-installation :",
"Select a pre-configured Linux VM script to execute:": "Sélectionnez un script de machine virtuelle Linux préconfiguré à exécuter :",
"Select a saved USB/IP device:": "Sélectionnez un périphérique USB/IP enregistré :",
"Select a script or action:": "Sélectionnez un script ou une action :",
"Select a share to delete:": "Sélectionnez un partage à supprimer :",
"Select a specific Coral or USB node, not the whole /dev": "Sélectionnez un noeud spécifique Coral ou USB, pas l'ensemble /dev",
@@ -6185,6 +6243,7 @@
"Select the Linux distribution to install:": "Sélectionnez la distribution Linux à installer :",
"Select the NAS system to install:": "Sélectionnez le système NAS à installer :",
"Select the NVIDIA driver version to install:": "Sélectionnez la version du pilote NVIDIA à installer :",
"Select the USB device to share:": "Sélectionnez le périphérique USB à partager :",
"Select the VM to add the GPU to:": "Sélectionnez la VM à laquelle ajouter le GPU :",
"Select the VM to which you want to add disks:": "Sélectionnez la VM à laquelle vous souhaitez ajouter des disques :",
"Select the VM where you want to import the disk image:": "Sélectionnez la VM sur laquelle vous souhaitez importer l'image disque :",
@@ -6209,6 +6268,7 @@
"Select the parent job to attach to:": "sélectionnez la tâche parent à attacher :",
"Select the paths to restore (one per backup entry):": "Sélectionnez les chemins à restaurer (un par entrée de sauvegarde) :",
"Select the privileged LXC container to convert:": "Sélectionnez le conteneur LXC privilégié à convertir :",
"Select the remote USB device:": "Sélectionnez le périphérique USB distant :",
"Select the storage that will receive the backups:": "Sélectionnez le stockage qui recevra les sauvegardes :",
"Select the storage volume for disk import:": "Sélectionnez le volume de stockage pour l'importation de disque :",
"Select the sync interval (in hours):": "Sélectionnez l'intervalle de synchronisation (en heures) :",
@@ -6258,6 +6318,7 @@
"Self-hosted file sync and sharing.": "Service auto-hébergé de synchronisation et de partage de fichiers.",
"Self-hosted file toolkit for images, video, audio, PDFs, and files": "Boîte à outils de fichiers auto-organisé pour les images, vidéo, audio, PDF et fichiers",
"Self-hosted forms and workflows.": "Formulaires et workflows auto-hébergés.",
"Self-hosted grocery list and recipe manager": "Liste d'épicerie et gestionnaire de recettes auto-hébergés",
"Self-hosted household plant-care tracker with reminders, photos, and multiple user accounts.": "Suivi auto-hébergé de l'entretien des plantes à la maison, avec rappels, photos et plusieurs comptes utilisateur.",
"Self-hosted image-hosting service with authenticated uploads, image processing, public links, and local storage.": "Service auto-hébergé d'hébergement d'images avec téléversements authentifiés, traitement des images, liens publics et stockage local.",
"Self-hosted internet archiving solution": "Solution d'archivage internet auto-organisé",
@@ -6294,6 +6355,7 @@
"Server IDs to test against, separated by commas (optional)": "ID de serveur à tester, séparés par des virgules (facultatif)",
"Server IP/hostname is correct": "L'adresse IP/le nom d'hôte du serveur est correct",
"Server IP:": "IP du serveur :",
"Server SSH port:": "Port SSH du serveur :",
"Server is accessible:": "Le serveur est accessible :",
"Server is online": "Le serveur est en ligne",
"Server is running": "Le serveur est en cours d'exécution",
@@ -6355,6 +6417,7 @@
"Share Access Error": "Erreur d'accès au partage",
"Share Name": "Partager le nom",
"Share Options": "Options de partage",
"Share a local USB device": "Partager un périphérique USB local",
"Share added successfully.": "Partage ajouté avec succès.",
"Share deleted and Samba service restarted.": "Partage supprimé et service Samba redémarré.",
"Share exists:": "Le partage existe :",
@@ -6362,6 +6425,7 @@
"Share name:": "Nom du partage :",
"Share not found on server:": "Partage introuvable sur le serveur :",
"Share path:": "Chemin de partage :",
"Share selected USB devices through SSH, or connect this Linux machine to a USB/IP server.": "Partagez les périphériques USB sélectionnés via SSH ou connectez cette machine Linux à un serveur USB/IP.",
"Share updated successfully.": "Partage mis à jour avec succès.",
"Share:": "Partager:",
"ShareCoveX panel": "Panneau ShareCoveX",
@@ -6452,6 +6516,7 @@
"Simple and easy to use DDNS": "Simple et facile à utiliser DDNS",
"Simple self-hosted file sharing.": "Service simple et auto-hébergé de partage de fichiers.",
"Single GPU Warning": "Avertissement sur un seul GPU",
"Single sign-on and multi-factor authentication": "authentification unique et authentification multifacteur",
"Single target found — selected automatically:": "Cible unique trouvée — sélectionnée automatiquement :",
"Single-node log storage and query UI.": "Stockage de journaux sur un nœud unique avec interface de requête.",
"Single-node observability database for metrics, logs and traces.": "Base de données d’observabilité à nœud unique pour les métriques, les journaux et les traces.",
@@ -6520,7 +6585,9 @@
"Specific subnet (enter manually)": "Sous-réseau spécifique (saisir manuellement)",
"Speedtest Tracker web interface": "Interface web Speedtest Tracker",
"Speedtest-tracker is a self-hosted internet performance tracking application that runs speedtest checks against Ookla's Speedtest service.": "Speedtest-tracker est une application de suivi de performance internet auto-organisé qui effectue des contrôles de test de vitesse contre le service Speedtest d'Ookla.",
"Spoolman web interface": "interface Web Spoolman",
"Spotube is an open source, cross-platform Spotify client compatible across multiple platforms utilizing Spotify's data API and YouTube, Piped.video or JioSaavn as an audio source, eliminating the need for Spotify Premium": "Spotube est un client Spotify ouvert et multiplateforme compatible avec plusieurs plateformes utilisant l'API de données de Spotify et YouTube, Piped. vidéo ou JioSaavn comme source audio, éliminant le besoin de Spotify Premium",
"Spreadsheets in your browser": "Tableur dans le navigateur",
"Sshwifty": "Sshwifty",
"Sshwifty web access (password only)": "Accès web à Sshwifty (mot de passe uniquement)",
"Stable (main branch)": "Stable (branche principale)",
@@ -6627,6 +6694,8 @@
"Still has issues": "A encore des problèmes",
"Stop - shuts the guest down during backup": "Arrêter - arrête l'invité pendant la sauvegarde",
"Stop it first and run this option again.": "Arrêtez-le d'abord et réexécutez cette option.",
"Stop sharing a USB device": "Arrêter le partage d'un périphérique USB",
"Stop sharing this device? An attached remote client will disconnect.": "Arrêter le partage de ce périphérique ? Tout client distant attaché sera déconnecté.",
"Stop that VM, then choose:": "Arrêtez ce VM, puis choisissez :",
"Stop the CT, unmount the disk on the HOST, and remount with:": "Arrêtez le CT, démontez le disque sur le HOST et remontez avec :",
"Stop the VM/CT before formatting this disk.": "Arrêtez la VM/CT avant de formater ce disque.",
@@ -6981,6 +7050,7 @@
"The container could not be removed automatically:": "Le conteneur n'a pas pu être enlevé automatiquement:",
"The container could not be started:": "Le conteneur n'a pas pu être démarré:",
"The container creation does not match the prepared instance": "La création du conteneur ne correspond pas à l'instance préparée",
"The container device settings changed since the last recorded operation": "La configuration du périphérique du conteneur a changé depuis la dernière opération enregistrée",
"The container devices do not match the saved record": "Les périphériques de conteneur ne correspondent pas à l'enregistrement enregistré",
"The container did not stop to update its persistent configuration:": "Le conteneur ne s'est pas arrêté pour mettre à jour sa configuration persistante:",
"The container did not stop; its disks are not touched": "Le conteneur ne s'est pas arrêté; ses disques ne sont pas touchés",
@@ -7262,6 +7332,7 @@
"The record no longer belongs to this operation": "Le record n'appartient plus à cette operation",
"The record of a member was replaced; the assembly is not resumed": "Le procès-verbal d'un membre a été remplacé; l'assemblée n'est pas reprise",
"The record or diagnosis could not be completed; no update was run.": "Le dossier ou le diagnostic n'a pu être complété; aucune mise à jour n'a été effectuée.",
"The recorded container device GID does not match its configuration": "Le GID enregistré du périphérique du conteneur ne correspond pas à sa configuration",
"The recovery did not complete. Review the log and choose \"Recover\" again for this container in the OCI management menu.": "La récupération n'est pas terminée. Passez en revue le journal et choisissez « Recover » pour ce conteneur dans le menu de gestion OCI.",
"The recovery did not complete. Review the log and choose \"{choice}\" again for this container in the OCI management menu.": "La restauration ne s'est pas terminée. Consultez le journal et choisissez de nouveau « {choice} » pour ce conteneur dans le menu de gestion OCI.",
"The registry authentication file is invalid; it was not changed.": "Le fichier d'authentification du registre n'est pas valide ; cela n'a pas été changé.",
@@ -7329,6 +7400,7 @@
"The selected Intel GPU has non-FLR reset support and unknown subtype": "Le GPU Intel sélectionné prend en charge la réinitialisation non FLR et sous-type inconnu",
"The selected Intel GPU is currently in power state D3cold": "Le GPU Intel sélectionné est actuellement en état d'alimentation D3cold",
"The selected Intel render device does not exist:": "Le périphérique de rendu Intel sélectionné n'existe pas :",
"The selected USB device will become unavailable to local applications and guests. Only one remote client can use it at a time. Share this device?": "Le périphérique USB sélectionné ne sera plus disponible pour les applications et les invités locaux. Un seul client distant peut l'utiliser à la fois. Partager ce périphérique ?",
"The selected VM": "La VM sélectionnée",
"The selected VM is running.": "La VM sélectionnée est en cours d'exécution.",
"The selected base folder does not exist and could not be created:": "Le dossier de base sélectionné n'existe pas et n'a pas pu être créé :",
@@ -7416,6 +7488,7 @@
"Then bind-mount to container": "Puis liez le montage au conteneur",
"Then change the VM display to none (vga: none) when the guest is stable.": "Modifiez ensuite l'affichage de la VM sur aucun (vga : aucun) lorsque l'invité est stable.",
"Then change the VM display to none (vga: none) when the system is stable.": "Modifiez ensuite l'affichage de la VM sur aucun (vga : aucun) lorsque le système est stable.",
"Then restart the container so the new model appears in the list.": "Redémarrez ensuite le conteneur pour que le nouveau modèle apparaisse dans la liste.",
"Then run this option again:": "Ensuite, réexécutez cette option :",
"Then update /etc/fstab on the host with the same options.": "Mettez ensuite à jour /etc/fstab sur l'hôte avec les mêmes options.",
"There are extra disks or bind mounts outside the journal; the rootfs is not replaced": "Il y a des disques supplémentaires ou des fixations en dehors du journal; les rootfs ne sont pas remplacés",
@@ -7463,6 +7536,7 @@
"This container does not have apt-get. NFS client installation only supports Debian/Ubuntu containers.": "Ce conteneur n'a pas apt-get. L'installation du client NFS prend uniquement en charge les conteneurs Debian/Ubuntu.",
"This container does not have apt-get. Samba client installation only supports Debian/Ubuntu containers.": "Ce conteneur n'a pas apt-get. L'installation du client Samba prend uniquement en charge les conteneurs 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.": "Ce conteneur n'a aucun GPU configuré. Coral TPU fonctionne mieux avec le décodage vidéo matériel (Quick Sync, VA-API, NVENC) pour des applications comme Frigate.",
"This container is managed by high availability. Remove ct:{vmid} from HA (Datacenter → HA, or ha-manager remove ct:{vmid}), repeat the operation and add it back to HA with the same settings.": "Ce conteneur est géré par la haute disponibilité. Retirez ct:{vmid} de HA (Centre de données → HA, ou ha-manager remove ct:{vmid}), relancez l'opération et rajoutez-le à HA avec les mêmes paramètres.",
"This container is not a member of a multi-container application": "Ce conteneur n'est pas membre d'une application multi-conteneurs",
"This container is not a registered OCI instance.": "Ce conteneur n'est pas une instance OCI enregistrée.",
"This container was restored or came back from another host after its record on this host was written. Open this menu again to recover it; nothing was changed.": "Ce conteneur a été restauré ou est revenu d'un autre hôte après l'écriture de son enregistrement sur cet hôte. Ouvrez à nouveau ce menu pour le récupérer ; rien n'a été changé.",
@@ -7581,6 +7655,7 @@
"Tip: You can install the QEMU Guest Agent inside the VM with:": "Astuce : Vous pouvez installer l'agent invité QEMU dans la VM avec :",
"Tip: zfs set acltype=posixacl xattr=sa <pool>/<dataset> enables full ACL support.": "Astuce : zfs set acltype=posixacl xattr=sa <pool>/<dataset> active la prise en charge complète des ACL.",
"Tmpfs size in MiB for": "Taille Tmpfs en MiB pour",
"To add a model, open the console of the container in Proxmox and download it into /models, for example:": "Pour ajouter un modèle, ouvrez la console du conteneur dans Proxmox et téléchargez-le dans /models, par exemple :",
"To allow LXC write access, change the NFS export on the server to include:": "Pour autoriser l'accès en écriture LXC, modifiez l'exportation NFS sur le serveur pour inclure :",
"To apply it to the current shell now, run:": "Pour l’appliquer maintenant à la session shell actuelle, exécutez :",
"To assign VFs to VMs or LXCs, edit the configuration manually via the Proxmox web interface. The Physical Function will remain bound to the native driver.": "Pour attribuer des VF aux VM ou LXC, modifiez la configuration manuellement via l'interface Web Proxmox. La fonction physique restera liée au pilote natif.",
@@ -7620,6 +7695,7 @@
"Total routes": "Total des itinéraires",
"Total size:": "Taille totale :",
"Toxiproxy": "Toxiproxy",
"Track 3D printer filament spools and usage.": "Suivez les bobines de filament d’imprimante 3D et leur utilisation.",
"Track movies, television, anime and games you want to enjoy.": "Suivez les films, séries, animés et jeux vidéo que vous souhaitez découvrir.",
"Track subscriptions and recurring expenses.": "Suivi des abonnements et des dépenses récurrentes.",
"Track your music listening history on your own server.": "Historique d’écoute musicale hébergé sur votre propre serveur.",
@@ -7664,6 +7740,9 @@
"USB drives mounted now:": "Clés USB montées maintenant :",
"USB libedgetpu1": "USB libedgetpu1",
"USB or serial device node": "nœud de périphérique USB ou série",
"USB/IP configuration updated. Open status to check the connection.": "Configuration USB/IP mise à jour. Ouvrez l'état pour vérifier la connexion.",
"USB/IP over SSH": "USB/IP via SSH",
"USB/IP server IP address or DNS hostname:": "Adresse IP ou nom d'hôte DNS du serveur USB/IP :",
"UUP Dump script not found.": "Script de vidage UUP introuvable.",
"UUp Dump ISO creator Custom": "UUp Dump Créateur ISO Personnalisé",
"Ubooquity is a free, lightweight and easy-to-use home server for your comics and ebooks. Use it to access your files from anywhere, with a tablet, an e-reader, a phone or a computer.": "Ubooquity est un serveur à domicile gratuit, léger et facile à utiliser pour vos BD et ebooks. Utilisez-le pour accéder à vos fichiers de n'importe où, avec une tablette, un lecteur électronique, un téléphone ou un ordinateur.",
@@ -7820,6 +7899,7 @@
"Untrusted or modified NVIDIA hook": "Crochet NVIDIA non fiable ou modifié",
"Unused image removed from the cache:": "Image non utilisée retirée du cache :",
"Unused images removed from the cache:": "Images inutilisées supprimées du cache :",
"Unused local loopback TCP port for this device:": "Port TCP local de bouclage inutilisé pour ce périphérique :",
"Update": "Mise à jour",
"Update Available": "mise à jour disponible",
"Update Ceph repository (Only if using Ceph):": "Mettre à jour le référentiel Ceph (uniquement si vous utilisez Ceph) :",
@@ -7854,6 +7934,7 @@
"Update the whole stack?": "Mettre à jour toute la pile ?",
"Update, modify or recreate one installed OCI instance": "Mettre à jour, modifier ou recréer une instance OCI installée",
"Updated": "Mis à jour",
"Updated recipes since your last visit: {count}": "Recettes mises à jour depuis votre dernière visite : {count}",
"Updated sharedfiles group to GID: 101000": "Groupe de fichiers partagés mis à jour vers GID : 101000",
"Updated stack checked": "Correction de la pile",
"Updated:": "Mise à jour :",
@@ -7917,6 +7998,7 @@
"Use a privileged LXC for NFS server/client workflows.": "Utilisez un LXC privilégié pour les workflows serveur/client NFS.",
"Use a privileged LXC for Samba client/server workflows.": "Utilisez un LXC privilégié pour les workflows client/serveur Samba.",
"Use a registry hostname, for example ghcr.io or registry.example.com:5000.": "Utilisez un nom d'hôte de registre, par exemple ghcr.io ou registry.example.com:5000.",
"Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time.": "Utilisez un proxy inverse HTTPS avec un certificat de confiance. Mettez Nextcloud à niveau vers la version majeure suivante, sans en sauter.",
"Use an existing SSH private key file on this host": "Utiliser un fichier de clé privée SSH existant sur cet hôte",
"Use an existing keyfile": "utiliser un fichier de clés existant",
"Use an image reference, for example ghcr.io/owner/app:latest.": "Utilisez une référence d'image, par exemple ghcr.io/owner/app:latest.",
@@ -7930,6 +8012,7 @@
"Use existing filesystem": "Utiliser le système de fichiers existant",
"Use existing: mount without formatting": "Utiliser existant : monter sans formatage",
"Use images only if the directory is on suitable storage.": "Utilisez des images uniquement si le répertoire se trouve sur un stockage approprié.",
"Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.": "Utilisez un stockage géré pour /config et MariaDB. Pour /data, vous pouvez choisir un répertoire de l’hôte/NAS, qui nécessite sa propre sauvegarde.",
"Use mp1/mp2/... for extra mount points.": "Utilisez mp1/mp2/... pour des points de montage supplémentaires.",
"Use only when unprivileged containers cannot meet your needs": "À utiliser uniquement lorsque les conteneurs non privilégiés ne peuvent pas répondre à vos besoins",
"Use option 1 to add a local disk (as Proxmox storage and/or as a host mount).": "Utilisez l'option 1 pour ajouter un disque local (comme stockage Proxmox et/ou comme montage hôte).",
@@ -8059,6 +8142,7 @@
"Variables": "Variables",
"Variables the installation asks for:": "Variables que l'installation demande:",
"Vaultwarden Web Vault": "Vaultwarden Web Vault",
"Vector illustration in your browser": "Illustration vectorielle dans le navigateur",
"Vector search engine with a built-in dashboard.": "Moteur de recherche vectorielle avec tableau de bord intégré.",
"Verbose pool status": "État du pool détaillé",
"Verification": "Vérification",
@@ -8089,6 +8173,7 @@
"Versions shown belong to maintained NVIDIA branches that list your GPU PCI ID and are new enough to build against the running kernel. DKMS compilation is the final validation. The recommended version keeps the current branch, or uses the NVIDIA Production Branch on a fresh install.": "Les versions affichées appartiennent aux branches NVIDIA maintenues qui répertorient votre ID PCI GPU et sont suffisamment récentes pour être construites sur le noyau en cours d'exécution. La compilation DKMS est la validation finale. La version recommandée conserve la branche actuelle ou utilise la branche de production NVIDIA sur une nouvelle installation.",
"VictoriaLogs": "VictoriaLogs",
"Video acceleration and object detection are independent choices; the installer does not write camera or detector YAML.": "L'accélération vidéo et la détection d'objets sont des choix indépendants; l'installateur n'écrit pas la caméra ou le détecteur YAML.",
"Video editing in your browser": "Montage vidéo dans le navigateur",
"Video transcoding acceleration": "Accélération du transcodage vidéo",
"Video transcoding profile not implemented:": "Profil de transcodage vidéo non implémenté :",
"View CIFS Mounts (pvesm + fstab)": "Afficher les montages CIFS (pvesm + fstab)",
@@ -8098,6 +8183,7 @@
"View Disk Storages": "Afficher les stockages sur disque",
"View Mount Points": "Afficher les points de montage",
"View NFS Mounts (pvesm + fstab)": "Afficher les montages NFS (pvesm + fstab)",
"View USB/IP status": "Afficher l'état USB/IP",
"View backup metadata": "Afficher les métadonnées de sauvegarde",
"View current paths": "afficher les chemins actuels",
"View existing folders in /mnt": "Afficher les dossiers existants dans /mnt",
@@ -8198,12 +8284,17 @@
"Web access": "Accès au Web",
"Web address of the AdGuard Home that receives the settings (e.g. http://192.168.1.3)": "Adresse Web du AdGuard Home qui reçoit les paramètres (p. ex. http://192.168.1.3)",
"Web address of the main AdGuard Home, whose settings are copied (e.g. http://192.168.1.2)": "Adresse Web du principal AdGuard Home, dont les paramètres sont copiés (par exemple http://192.168.1.2)",
"Web dashboard": "Tableau de bord web",
"Web dashboard and WebDAV": "Tableau de bord web et WebDAV",
"Web interface": "interface Web",
"Web interface for Borg Backup repositories and jobs.": "Interface web pour les dépôts et tâches Borg Backup.",
"Web interface for managing 3D printers.": "Interface web de gestion des imprimantes 3D.",
"Web interface to manage devices running Tasmota firmware.": "Interface Web pour gérer les appareils utilisant le firmware Tasmota.",
"Web reverse proxy with an administration interface.": "Proxy inverse web doté d’une interface d’administration.",
"WebCord can be summarized as a pack of security and privacy hardenings, Discord features reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, internal pages and wrapped https://discord.com page, designed to conform with ToS as much as it is possible (or hide the changes that might violate it from Discord's eyes).": "WebCord peut être résumé comme un paquet de durcissements de sécurité et de confidentialité, les fonctionnalités Discord réimplémentations, Electron / Chromium / Discord bugs workarounds, les feuilles de style, les pages internes et la page https://discord.com enveloppée, conçue pour se conformer à ToS autant qu'il est possible (ou cacher les changements qui pourraient la violer des yeux de Discord).",
"WebDAV": "WebDAV",
"WebDAV and dashboard password (leave empty to generate)": "Mot de passe WebDAV et du tableau de bord (vide = généré)",
"WebDAV is available on container port 8080. Account linking is required before cloud file operations.": "WebDAV est disponible sur le port 8080 du conteneur. Le compte doit être lié avant toute opération sur les fichiers du cloud.",
"Webgrabplus is a multi-site incremental xmltv epg grabber. It collects tv-program guide data from selected tvguide sites for your favourite channels.": "Webgrabplus est un accrocheur différentiel multisite xmltv egg. Il recueille les données du guide TV-programme à partir de sites sélectionnés pour vos chaînes préférées.",
"Webservers & Proxies": "Serveurs web et proxys",
"Website": "Site web",
@@ -8261,6 +8352,7 @@
"Without a usable reset path, passthrough reliability is poor and VM": "Sans chemin de réinitialisation utilisable, la fiabilité du relais est médiocre et la VM",
"Wizard cancelled": "Assistant annulé",
"Wolfenstein: Blade of Agony is a story-driven WWII shooter inspired by Wolfenstein and Doom.": "Wolfenstein: Blade of Agony est un jeu de tir inspiré par Wolfenstein et Doom.",
"Word processing in your browser": "Traitement de texte dans le navigateur",
"Workflow automation tool": "Outil d'automatisation du flux de travail",
"Working directory:": "Répertoire de travail :",
"Works with LVM, ZFS, and BTRFS storage types": "Fonctionne avec les types de stockage LVM, ZFS et BTRFS",
@@ -8311,6 +8403,8 @@
"Your machine learning Env work with Jupyter Lab": "Votre machine learning Env travaille avec Jupyter Lab",
"Your next YouTube media manager": "Votre prochain gestionnaire de médias YouTube",
"Your_spotify is a self-hosted application that tracks what you listen and offers you a dashboard to explore statistics about it! It's composed of a web server which polls the Spotify API every now and then and a web application on which you can explore your statistics.": "Your_spotify est une application auto-hôte qui suit ce que vous écoutez et vous offre un tableau de bord pour explorer les statistiques à ce sujet! Il est composé d'un serveur web qui interroge l'API Spotify de temps en temps et d'une application web sur laquelle vous pouvez explorer vos statistiques.",
"Z-Wave JS UI": "Z-Wave JS UI",
"Z-Wave JS UI admin login": "connexion administrateur Z-Wave JS UI",
"ZFS ARC config removed (kernel defaults will apply on reboot)": "Configuration ZFS ARC supprimée (les valeurs par défaut du noyau s'appliqueront au redémarrage)",
"ZFS ARC maximum configured:": "ZFS ARC maximum configuré :",
"ZFS ARC optimization completed": "Optimisation ZFS ARC terminée",
@@ -8424,6 +8518,7 @@
"could not be compiled for kernel": "n'a pas pu être compilé pour le noyau",
"could not validate NVIDIA; exit code": "n'a pas pu valider NVIDIA; code de sortie",
"cpuunits must be between 8 and 10000": "cpuunits doivent être compris entre 8 et 10000",
"curl -L -o /models/gemma-3-1b-it-Q4_K_M.gguf https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf": "curl -L -o /models/gemma-3-1b-it-Q4_K_M.gguf https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf",
"custom": "personnalisé",
"custom dependency commands are not yet supported": "commandes de dépendance personnalisées ne sont pas encore prises en charge",
"custom path(s) saved.": "chemin(s) personnalisé(s) enregistré(s).",
@@ -8630,6 +8725,7 @@
"kexec-tools is not installed or already removed.": "kexec-tools n'est pas installé ou déjà supprimé.",
"layers": "couches",
"legacy .link file(s) to the ProxMenux-managed format": "les anciens fichiers .link au format géré par ProxMenux",
"llama.cpp shows every GGUF model saved in /models in its web UI and loads the one you choose.": "llama.cpp affiche dans son interface web tous les modèles GGUF enregistrés dans /models et charge celui que vous choisissez.",
"log2ram completely removed from system": "log2ram complètement supprimé du système",
"main container of the application": "conteneur principal de l'application",
"make cloned mount tree read-only": "rendre l'arborescence de montage clonée en lecture seule",
+96
View File
@@ -184,6 +184,7 @@
"A tunneling daemon by Cloudflare that safely exposes your web servers into the internet.": "Un servizio di tunneling di Cloudflare che espone in modo sicuro i tuoi server web su Internet.",
"A unified email and collaboration server.": "Un server unificato per email e collaborazione.",
"A unified platform for logs, metrics and traces.": "Una piattaforma unificata per log, metriche e tracce.",
"A validating, recursive DNS resolver for your private network.": "un risolutore DNS ricorsivo e di convalida per la tua rete privata.",
"A versatile file conversion tool that supports multiple formats.": "Uno strumento versatile per convertire file in diversi formati.",
"A visual tool for exploring and documenting database schemas.": "Uno strumento visivo per esplorare e documentare gli schemi dei database.",
"A web GUI client of Project V which supports VMess, VLESS, SS, SSR, Trojan, Tuic and Juicity protocols": "Un client web di Project V che supporta i protocolli VMess, VLESS, SS, SSR, Trojan, Tuic e Juicity",
@@ -245,6 +246,7 @@
"Aborted": "Interrotto",
"About to restore": "Ripristino imminente di",
"Absolute directory path to use as backup target:": "Percorso assoluto della directory di destinazione del backup:",
"Absolute path of the client SSH private key:": "Percorso assoluto della chiave privata SSH del client:",
"Absolute path to a file or directory you want backed up:": "Percorso assoluto del file o della directory da includere nel backup:",
"Acceleration": "Accelerazione",
"Acceleration configuration cancelled": "Configurazione accelerazione annullata",
@@ -256,6 +258,7 @@
"Acceleration for llama.cpp": "Accelerazione per llama.cpp",
"Accept routes from other nodes?": "Accettare rotte da altri nodi?",
"Accept this host monitoring profile?": "Accettare questo profilo di monitoraggio host?",
"Access Movistar and O2 Cloud from WebDAV clients and backup tools.": "Accedi al cloud di Movistar e O2 da client WebDAV e strumenti di backup.",
"Access Scope:": "Ambito di accesso:",
"Access bridge": "Bridge di accesso",
"Access bridge for Immich": "Bridge di accesso per Immich",
@@ -410,6 +413,7 @@
"After the reboot, you will only be able to access the Proxmox host via:": "Dopo il riavvio, potrai accedere all'host Proxmox solo tramite:",
"After this LXC → VM switch, reboot the host so the new binding state is applied cleanly.": "Dopo questo passaggio LXC → VM, riavviare l’host in modo che il nuovo stato di associazione venga applicato correttamente.",
"Agentless monitoring and observability platform.": "Piattaforma di monitoraggio e osservabilità senza agent.",
"AirDC++ administrator": "Amministratore AirDC++",
"Airsonic Advanced web interface": "Interfaccia web Airsonic Advanced",
"Airsonic-advanced is a free, web-based media streamer, providing ubiquitious access to your music. Use it to share your music with friends, or to listen to your own music while at work. You can stream to multiple players simultaneously, for instance to one player in your kitchen and another in your living room.": "Airsonic-advanced è un servizio gratuito di streaming multimediale via web che permette di accedere alla propria musica ovunque. Puoi condividerla con gli amici o ascoltarla mentre lavori. Puoi riprodurla contemporaneamente su più dispositivi, per esempio in cucina e in soggiorno.",
"Aliases added to .bashrc": "Alias aggiunti a .bashrc",
@@ -598,11 +602,15 @@
"Attention: Removing the subscription banner may cause issues in the web interface after a future update.": "Attenzione: la rimozione del banner di abbonamento potrebbe causare problemi nell'interfaccia web dopo un futuro aggiornamento.",
"Audacity is an easy-to-use, multi-track audio editor and recorder. Developed by a group of volunteers as open source.": "Audacity è un editor e registratore audio multitraccia facile da usare, sviluppato come software open source da un gruppo di volontari.",
"Audio device directory": "Directory del dispositivo audio",
"Audio recording and mixing in your browser": "Registrazione e missaggio audio nel browser",
"Audiobookshelf is a self-hosted audiobook and podcast server.": "Audiobookshelf è un server self-hosted per audiolibri e podcast.",
"Audit completed. Press Enter to continue...": "Audit completato. Premi Invio per continuare...",
"Audit socket disabled or not required": "Socket di audit disabilitato o non richiesto",
"Auth key is required.": "È richiesta la chiave di autenticazione.",
"Auth:": "Autenticazione:",
"Authelia Web UI": "interfaccia utente Web Authelia",
"Authelia administrator": "amministratore Authelia",
"Authelia session cookie domain for this portal (for example example.com)": "dominio del cookie di sessione Authelia per questo portale (ad esempio example.com)",
"Authentication": "Autenticazione",
"Authentication & Security": "Autenticazione e sicurezza",
"Authentication Error": "Errore di autenticazione",
@@ -612,6 +620,8 @@
"Authentication:": "Autenticazione:",
"Authorization failed": "Autorizzazione fallita",
"Authorization successful": "Autorizzazione riuscita",
"Authorize a client SSH public key": "Autorizza la chiave pubblica SSH di un client",
"Authorize a dedicated client public key on the server first. The restricted USB/IP account cannot run a shell or forward other sockets. Verify the server host key before connecting; unknown keys are rejected.": "Autorizza prima una chiave pubblica dedicata del client sul server. L’account USB/IP con accesso limitato non può avviare una shell né inoltrare altri socket. Verifica la chiave host del server prima di connetterti; le chiavi sconosciute vengono rifiutate.",
"Authorize this key on the server": "Autorizzare questa chiave sul server",
"Authorize via 'pct exec' (Borg server is an LXC on a PVE host I can SSH into)": "Autorizza tramite 'pct exec' (il server Borg è un LXC su un host PVE a cui posso accedere tramite SSH)",
"Authorized": "Autorizzato",
@@ -642,6 +652,7 @@
"Available PVE Version": "Versione PVE disponibile",
"Available Shares:": "Condivisioni disponibili:",
"Available action": "Azione disponibile",
"Available applications: {count}": "Applicazioni disponibili: {count}",
"Available archives:": "Archivi disponibili:",
"Available disks detected.": "Rilevati dischi disponibili.",
"Available host backups:": "Backup host disponibili:",
@@ -873,6 +884,7 @@
"Cannot write the image archive to {storage}. Check storage access and mount status.": "Impossibile scrivere l'archivio dell'immagine su {storage}. Controlla l'accesso allo storage e lo stato di montaggio.",
"Capabilities cannot be kept and all dropped at the same time": "Non è possibile conservare alcune capability e rimuoverle tutte contemporaneamente",
"Catalog options": "Opzioni del catalogo",
"Catalog refresh unavailable; using the local catalog.": "Impossibile aggiornare il catalogo; viene usata la copia locale.",
"Category": "Categoria",
"Caution: Maximum mode generates more heat.": "Attenzione: la modalità massima genera più calore.",
"Central server for file and image backups.": "Server centrale per il backup di file e immagini.",
@@ -1159,6 +1171,7 @@
"Compressing": "Compressione",
"Compression": "Compressione",
"Compression Tools": "Strumenti di compressione",
"Computer-aided design and drafting in your browser": "Progettazione CAD e disegno tecnico nel browser",
"Concise output of logical volumes": "Output conciso di volumi logici",
"Concise output of physical volumes": "Output conciso di volumi fisici",
"Concise output of volume groups": "Output conciso dei gruppi di volumi",
@@ -1289,6 +1302,7 @@
"Conflicting utilities removed": "Utilità in conflitto rimosse",
"Connect Zigbee devices to MQTT with a browser-based setup interface.": "Collega i dispositivi Zigbee a MQTT tramite un’interfaccia web di configurazione.",
"Connect a Coral Accelerator and try again.": "Collega un Coral Accelerator e riprova.",
"Connect a remote USB device": "Collega un dispositivo USB remoto",
"Connect it, or remove it from the container in Proxmox (Resources), and run the recovery again.": "Collegalo o rimuovilo dal container in Proxmox (Risorse), poi ripeti il recupero.",
"Connect your devices and users together in your own secure virtual private network.": "Collega dispositivi e utenti nella tua rete privata virtuale sicura.",
"Connect your devices into a secure WireGuard®-based overlay network with SSO, MFA and granular access controls.": "Collega i tuoi dispositivi in una rete overlay sicura basata su WireGuard®, con SSO, MFA e controlli granulari degli accessi.",
@@ -1393,6 +1407,7 @@
"Controller + NVMe": "Controller + NVMe",
"Controller + NVMe assignment will be written now and become active after host reboot.": "L'assegnazione Controller + NVMe verrà scritta ora e diventerà attiva dopo il riavvio dell'host.",
"Controller + NVMe passthrough requires machine type q35. Skipping controller assignment.": "Il passthrough di controller + NVMe richiede il tipo di macchina q35. Assegnazione del controller saltata.",
"Controller path on the Proxmox host; prefer /dev/serial/by-id/...": "percorso del controller sull'host Proxmox;preferisco /dev/serial/by-id/...",
"Controller/NVMe Conflict Policy": "Policy conflitti controller/NVMe",
"Controller/NVMe already present in VM config": "Controller/NVMe già presente nella configurazione VM",
"Controller/NVMe already present in VM config (%s)": "Controller/NVMe già presente nella configurazione della VM (%s)",
@@ -1927,6 +1942,7 @@
"Dgraph": "Dgraph",
"Diff: current system vs backup (--- system +++ backup)": "Differenza: sistema attuale vs backup (--- sistema +++ backup)",
"Different host. Backup from:": "Host diverso. Backup da:",
"Direct Connect file sharing with a web interface": "Condivisione di file Direct Connect con interfaccia web",
"Direct conversion completed for container": "Conversione diretta completata per il container",
"Directory Exists": "Directory esistente",
"Directory Not Empty": "Directory non vuota",
@@ -1949,12 +1965,14 @@
"Directus administrator": "Amministratore Directus",
"Disable NIC Offloading (Intel e1000e)": "Disabilita offload NIC (Intel e1000e)",
"Disable Secure Boot in the UEFI firmware and run the installer again. Nothing has been changed.": "Disattiva Secure Boot nel firmware UEFI ed esegui di nuovo il programma di installazione. Non è stato modificato nulla.",
"Disable USB/IP server": "Disabilita il server USB/IP",
"Disable autostart on conflicting VM": "Disabilita l'avvio automatico sulla VM in conflitto",
"Disable autostart on one VM to avoid startup conflicts.": "Disabilita l'avvio automatico su una VM per evitare conflitti di avvio.",
"Disable job": "Disabilita job",
"Disable kernel audit messages (optional but recommended):": "Disabilita i messaggi di audit del kernel (facoltativo ma consigliato):",
"Disable onboot on affected VM(s)/CT(s)": "Disabilita onboot sulle VM/CT interessati",
"Disable portmapper/rpcbind": "Disabilita portmapper/rpcbind",
"Disable the server and release all USB devices managed by ProxMenux? Saved selections are kept for the next enable.": "Disabilitare il server e liberare tutti i dispositivi USB gestiti da ProxMenux? Le selezioni salvate verranno mantenute per la prossima attivazione.",
"Disabled": "Disabilitato",
"Disabling High Availability services...": "Disabilitazione dei servizi ad alta disponibilità...",
"Disabling ZFS autotrim applied by ProxMenux...": "Disattivazione di autotrim ZFS applicato da ProxMenux...",
@@ -2187,6 +2205,7 @@
"Enable Remote Desktop (RDP) before disabling the virtual display.": "Abilita Desktop remoto (RDP) prima di disabilitare il display virtuale.",
"Enable SSD emulation for this disk?": "Abilitare l'emulazione SSD per questo disco?",
"Enable TCP BBR/Fast Open control": "Abilita controllo TCP BBR/Fast Open",
"Enable USB/IP server": "Abilita il server USB/IP",
"Enable VA-API transcoding and HDR10/Dolby Vision to SDR tone mapping": "Abilita la transcodifica VA-API e la conversione dei toni da HDR10/Dolby Vision a SDR",
"Enable VA-API, hardware encoding and OpenCL tone mapping in Jellyfin": "Abilita VA-API, la codifica hardware e la mappatura dei toni OpenCL in Jellyfin",
"Enable VFIO IOMMU support": "Abilita supporto VFIO IOMMU",
@@ -3200,6 +3219,7 @@
"If pvesm path returned a DEVICE (LVM):": "Se pvesm path ha restituito un DISPOSITIVO (LVM):",
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Se pvesm path ha restituito una DIRECTORY (ZFS/BTRFS):",
"If repositories error:": "Se si verificano errori nei repository:",
"If the USB/IP service stops unexpectedly, stop sharing while the device is still connected to release it. In rare cases only a host reboot releases it.": "Se il servizio USB/IP si arresta in modo imprevisto, interrompi la condivisione mentre il dispositivo è ancora collegato per liberarlo. In rari casi solo un riavvio dell'host lo libera.",
"If the container had already been changed, its previous native backup is restored. Shared host directories are not reverted. The disks of the failed attempt are removed when the cleanup succeeds.": "Se il container era già stato modificato, viene ripristinato il suo backup nativo precedente. Le directory condivise dell'host non vengono ripristinate. I dischi del tentativo fallito vengono rimossi se la pulizia riesce.",
"If the host freezes, remove hostpci entries from": "Se l'host si blocca, rimuovi le voci hostpci da",
"If the image channel has a new version, the CT is stopped, backed up and verified, and replaced with the new image to update the container. If anything fails, the backup is restored.": "Se il canale immagine ha una nuova versione, CT viene arrestato, sottoposto a backup, verificato e sostituito con la nuova immagine per aggiornare il contenitore. Se qualcosa fallisce, il backup viene ripristinato.",
@@ -3340,6 +3360,7 @@
"Initial Stirling-PDF account": "Account iniziale di Stirling-PDF",
"Initial Tandoor administrator": "Amministratore iniziale Tandoor",
"Initial Umami administrator": "Amministratore iniziale di Umami",
"Initial Z-Wave JS UI admin password": "password amministratore iniziale Z-Wave JS UI",
"Initial administrator created:": "Amministratore iniziale creato:",
"Initial administrator user": "Utente amministratore iniziale",
"Initializing Borg repository if needed...": "Inizializzazione del repository Borg, se necessario...",
@@ -3393,6 +3414,7 @@
"Install server packages inside CT:": "Installa i pacchetti server nel CT:",
"Install terminal multiplexers": "Installa multiplexer di terminale",
"Install the Edge TPU runtime (libedgetpu1-std)": "Installa il runtime Edge TPU (libedgetpu1-std)",
"Install the USB/IP dependencies from the configured Debian repositories?": "Installare le dipendenze USB/IP dai repository Debian configurati?",
"Install this image?": "Installare questa immagine?",
"Install with Cloud-Init script": "Installa con lo script Cloud-Init",
"Install with ISO from UUP Dump": "Installa con ISO da UUP Dump",
@@ -3525,6 +3547,7 @@
"Interface MTU": "MTU interfaccia",
"Interface Names (persistent)": "Nomi interfacce (persistenti)",
"Interface Type": "Tipo interfaccia",
"Interface design and prototyping in your browser": "Progettazione di interfacce e prototipi nel browser",
"Interface names will return to default systemd behavior.": "I nomi delle interfacce torneranno al comportamento systemd predefinito.",
"Interface type:": "Tipo interfaccia:",
"Interfaces configured": "Interfacce configurate",
@@ -3582,6 +3605,7 @@
"Invalid check package:": "Pacchetto controllo non valido:",
"Invalid configuration path:": "Percorso configurazione non valido:",
"Invalid consume/export volumes": "Volumi di acquisizione/esportazione non validi",
"Invalid container device GID": "GID del dispositivo del container non valido",
"Invalid container path:": "Percorso nel container non valido:",
"Invalid credential file path:": "Percorso file credenziali non valido:",
"Invalid declarative entrypoint": "Entrypoint dichiarativo non valido",
@@ -3740,6 +3764,7 @@
"Jupyter Lab (token only)": "Jupyter Lab (solo token)",
"JupyterLab": "JupyterLab",
"JupyterLab access token": "Token di accesso JupyterLab",
"KDE's twin-panel file manager in a browser-based desktop.": "il file manager a doppio pannello di KDE in un desktop basato su browser.",
"KDF:": "KDF:",
"KROMA": "KROMA",
"KVM MSR options added to /etc/modprobe.d/kvm.conf": "Opzioni KVM MSR aggiunte a /etc/modprobe.d/kvm.conf",
@@ -3787,12 +3812,14 @@
"KiCad - A Cross Platform and Open Source Electronics Design Automation Suite.": "KiCad: una suite multipiattaforma e open source per la progettazione elettronica.",
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "Kimai non ha un account predefinito. Accedi al container con: pct enter {main_vmid}",
"Kimai is a professional grade time-tracking application, free and open-source.": "Kimai è un'applicazione professionale, gratuita e open source per il monitoraggio del tempo.",
"KitchenOwl": "KitchenOwl",
"Kometa is a powerful tool designed to give you complete control over your media libraries. With Kometa, you can take your customization to the next level, with granular control over metadata, collections, overlays, and much more.": "Kometa è uno strumento che ti offre un controllo completo sulle tue librerie multimediali. Permette di personalizzare nel dettaglio metadati, raccolte, sovrimpressioni e molto altro.",
"Kometa reads its configuration from /config/config.yml and the container only ships /config/config.yml.template. Copy the template to config.yml, fill in the required Plex and TMDb connections, then restart the container.": "Kometa legge la configurazione da /config/config.yml, ma il container include solo /config/config.yml.template. Copia il modello in config.yml, configura le connessioni necessarie a Plex e TMDb, quindi riavvia il container.",
"Komga is a media server for your comics, mangas, BDs, magazines and eBooks.": "Komga è un server multimediale per fumetti, manga, bande dessinée, riviste ed e-book.",
"Kopia Web UI": "Interfaccia web di Kopia",
"Kopia Web UI login": "Accesso all’interfaccia web di Kopia",
"Krita is a professional FREE and open source painting program. It is made by artists that want to see affordable art tools for everyone.": "Krita è un programma professionale, gratuito e open source per dipingere. È creato da artisti che vogliono rendere gli strumenti artistici accessibili a tutti.",
"Krusader Web UI": "interfaccia utente Web Krusader",
"LAN access to the kept containers (stack configuration incomplete):": "Accesso LAN ai container conservati (configurazione stack incompleta):",
"LAN address applied to the application URLs": "Indirizzo LAN applicato agli URL dell'applicazione",
"LLDAP": "LLDAP",
@@ -3873,9 +3900,11 @@
"Line to paste (single line, including \"command=...\" prefix):": "Riga da incollare (una sola riga, incluso il prefisso \"command=...\"):",
"LinkStack": "LinkStack",
"Linux Installation Options": "Opzioni installazione Linux",
"Linux guest setup and migration notes": "Configurazione degli ospiti Linux e note sulla migrazione",
"Linux/Mac path:": "Percorso Linux/Mac:",
"LinuxServer Jellyfin with optional GPU passthrough": "LinuxServer Jellyfin con passthrough GPU opzionale",
"LinuxServer MariaDB requires a user, database and password": "LinuxServer MariaDB richiede un utente, un database e una password",
"LinuxServer Nextcloud with MariaDB and Redis": "Nextcloud di LinuxServer con MariaDB e Redis",
"List Available Disks": "Elenca i dischi disponibili",
"List IOMMU group mapping": "Elenca la mappatura dei gruppi IOMMU",
"List NVMe devices": "Elenca i dispositivi NVMe",
@@ -4020,6 +4049,7 @@
"Manage OCI stack": "Gestisci stack OCI",
"Manage PBS encryption keyfile": "Gestisci il file di chiavi di crittografia PBS",
"Manage Secure Gateway": "Gestisci Secure Gateway",
"Manage a Z-Wave network from a web dashboard and WebSocket gateway.": "gestisci una rete Z-Wave da una dashboard Web e da un gateway WebSocket.",
"Manage and inspect VM disk images": "Gestisci e ispeziona le immagini disco delle VM",
"Manage custom backup paths": "Gestisci percorsi di backup personalizzati",
"Manage custom paths (add / remove your folders)": "Gestisci percorsi personalizzati (aggiungi/rimuovi le tue cartelle)",
@@ -4029,6 +4059,7 @@
"Manage local backup target": "Gestisci la destinazione di backup locale",
"Manage private image registries.\nSaved credentials let ProxMenux access your private images.": "Gestisci i registri di immagini private.\nLe credenziali salvate consentono a ProxMenux di accedere alle tue immagini private.",
"Manage registry accounts as root on the Proxmox node.": "Gestisci gli account del registro come root sul nodo Proxmox.",
"Manage teams of AI agents from a web dashboard.": "Gestisci team di agenti IA da una dashboard web.",
"Managed disks must have backup enabled and a valid size": "I dischi gestiti devono avere il backup abilitato e una dimensione valida",
"Managed public route include is missing": "Manca la direttiva di inclusione per le rotte pubbliche gestite",
"Managed public route installation failed": "Impossibile configurare le rotte pubbliche gestite",
@@ -4134,6 +4165,7 @@
"Monitoring": "Monitoraggio",
"Monitoring & Analytics": "Monitoraggio e analisi",
"Most common cause: the archive is corrupted (interrupted write, partial copy, or storage issue).": "Causa più comune: l'archivio è danneggiato (scrittura interrotta, copia parziale o problema di archiviazione).",
"Motion graphics and compositing in your browser": "Grafica animata e compositing nel browser",
"Mount Added Successfully:": "Montaggio aggiunto con successo:",
"Mount CIFS share:": "Monta la condivisione CIFS:",
"Mount Configuration Summary:": "Riepilogo configurazione montaggio:",
@@ -4293,6 +4325,7 @@
"NVIDIA (CUDA; official GPU image)": "NVIDIA (CUDA; immagine GPU ufficiale)",
"NVIDIA (NVDEC/CUDA)": "NVIDIA (NVDEC/CUDA)",
"NVIDIA (NVENC/NVDEC)": "NVIDIA (NVENC/NVDEC)",
"NVIDIA (Selkies rendering and NVENC)": "NVIDIA (rendering Selkies e NVENC)",
"NVIDIA Actions": "Azioni NVIDIA",
"NVIDIA CPU hiding already configured": "Occultamento CPU per NVIDIA già configurato",
"NVIDIA Container Toolkit": "NVIDIA Container Toolkit",
@@ -4376,6 +4409,7 @@
"Name or part of the option or of the application": "Nome dell'opzione o dell'applicazione, anche parziale",
"Name:": "Nome:",
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Gli account nominativi richiedono la modalità privata. Arresta il container, imposta public: false in /config/config.js, riavvialo e crea ogni utente con: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>",
"Native Borg is unavailable. Install the native borgbackup package on this host to use Borg backups.": "La versione nativa di Borg non è disponibile. Installa il pacchetto borgbackup nativo su questo host per utilizzare i backup Borg.",
"Needed:": "Spazio richiesto:",
"Needs": "Richiede",
"Neither /etc/kernel/cmdline nor /etc/default/grub found.": "Non sono stati trovati né /etc/kernel/cmdline né /etc/default/grub.",
@@ -4434,6 +4468,8 @@
"New Search": "Nuova ricerca",
"New VM:": "Nuova VM:",
"New Virtual Machine": "Nuova VM",
"New applications ({count})": "Nuove applicazioni ({count})",
"New applications since your last visit: {count}": "Nuove applicazioni dalla tua ultima visita: {count}",
"New backup job": "Nuova attività di backup",
"New backups on this host will be unencrypted until a new keyfile is set up.": "I nuovi backup su questo host non saranno crittografati finché non verrà impostato un nuovo file di chiavi.",
"New image compatible:": "Nuova immagine compatibile:",
@@ -4449,6 +4485,7 @@
"Next Step Required": "Passaggio successivo obbligatorio",
"Next Steps:": "Passaggi successivi:",
"Next step: stop that VM first, then run": "Passaggio successivo: arresta prima la VM, quindi esegui",
"Nextcloud Web UI": "Interfaccia web di Nextcloud",
"Nextcloud configuration cancelled": "Configurazione di Nextcloud annullata",
"Nextcloud gives you access to all your files wherever you are.": "Nextcloud ti dà accesso a tutti i tuoi file, ovunque ti trovi.",
"Nextcloud volume size in GB": "Dimensione volume Nextcloud in GB",
@@ -4623,6 +4660,7 @@
"No duplicate IP addresses": "Nessun indirizzo IP duplicato",
"No duplicate repositories found": "Nessun repository duplicato trovato",
"No eligible Controller/NVMe devices remain after SR-IOV filtering. Skipping.": "Dopo il filtraggio SR-IOV non rimane alcun dispositivo controller/NVMe idoneo. Operazione saltata.",
"No eligible USB devices found. Hubs, mass storage and network adapters are excluded.": "Nessun dispositivo USB idoneo trovato. Gli hub, i dispositivi di archiviazione di massa e gli adattatori di rete sono esclusi.",
"No eligible controllers remain after SR-IOV filtering.": "Dopo il filtraggio SR-IOV non rimane alcun controller idoneo.",
"No encryption key is stored on this host. Choose how to set one up:": "Nessuna chiave di crittografia archiviata su questo host. Scegli come configurarne una:",
"No exportable VM disks were found (CD-ROM/cloud-init are excluded).": "Nessun disco VM esportabile trovato (CD-ROM/cloud-init esclusi).",
@@ -4707,6 +4745,7 @@
"No self-test log available for": "Nessun registro di autotest disponibile per",
"No server IP or hostname provided.": "Nessun IP del server o nome host fornito.",
"No share access test succeeded with guest authentication.": "Nessun test di accesso alle condivisioni è riuscito con l'autenticazione guest.",
"No shared devices are available on this server.": "Nessun dispositivo condiviso disponibile su questo server.",
"No shared media content.": "Nessun contenuto multimediale condiviso.",
"No shared mount detected. Applying standard local access.": "Nessun montaggio condiviso rilevato. Applicazione dell'accesso locale standard.",
"No shares configured.": "Nessuna condivisione configurata.",
@@ -4896,6 +4935,8 @@
"Open the page of an application in the menu": "Apri la pagina di un'applicazione nel menu",
"Open the web address and create the first account: the daemon registers by itself and starts the first scan.": "Apri l'indirizzo web e crea il primo account: il daemon si registra da solo e avvia la prima scansione.",
"Open the web address and create the password of the akadmin user in the first-run setup.": "Apri l'indirizzo web e imposta la password dell'utente akadmin durante la configurazione iniziale.",
"Open the web address and follow KitchenOwl’s onboarding to create the first account; no default account is configured.": "apri l'indirizzo web e segui l'onboarding di KitchenOwl per creare il primo account;non è configurato alcun account predefinito.",
"Open the web dashboard and link your Movistar/O2 account using its SMS flow.": "Apri la dashboard web e collega il tuo account Movistar/O2 con la verifica tramite SMS.",
"Open-source AI-powered coding assistant": "Assistente open source per la programmazione basato sull'IA",
"Open-source UI for building and debugging multi-agent and RAG applications": "Interfaccia open source per creare ed eseguire il debug di applicazioni multiagente e RAG",
"Open-source in-memory data store.": "Archivio dati in memoria open source.",
@@ -5018,6 +5059,7 @@
"Packages:": "Pacchetti:",
"Packaging OVA file...": "Creazione del file OVA...",
"Packing installer archive...": "Compressione dell'archivio del programma di installazione...",
"Page layout and publishing in your browser": "Impaginazione e pubblicazione nel browser",
"PairDrop is a sublime alternative to AirDrop that works on all platforms. Send images, documents or text via peer to peer connection to devices in the same local network/Wi-Fi or to paired devices.": "PairDrop è un'ottima alternativa ad AirDrop che funziona su tutte le piattaforme. Invia immagini, documenti o testo con una connessione peer-to-peer a dispositivi sulla stessa rete locale/Wi-Fi o a dispositivi associati.",
"Paperless configuration cancelled": "Configurazione di Paperless annullata",
"Paperless-ngx WebUI": "Paperless-ngx WebUI",
@@ -5036,6 +5078,7 @@
"Pass /dev/video12 to the LXC": "Collega /dev/video12 al container LXC",
"Pass a host device to the LXC": "Collega un dispositivo dell’host al container LXC",
"Pass the UPS to the LXC": "Passa l'UPS al container LXC",
"Pass through a Z-Wave USB or serial controller": "passa attraverso un controller USB o seriale Z-Wave",
"Passing NVIDIA does not enable acceleration inside the application. The host needs NVIDIA Container Toolkit and a compatible image. Continue?": "il passaggio di NVIDIA non abilita l'accelerazione all'interno dell'applicazione. L'host necessita di NVIDIA Container Toolkit e di un'immagine compatibile. Continuare?",
"Passkey-based identity provider for self-hosted apps.": "Provider di identità basato su passkey per app self-hosted.",
"Passphrase used to unlock the imported keyfile (leave blank if the keyfile is unencrypted / kdf=none):": "Passphrase per sbloccare il file di chiavi importato (lascia vuoto se non è crittografato / kdf=none):",
@@ -5101,6 +5144,7 @@
"Path of the Compose file": "Percorso del file Compose",
"Path of the oci-compose file": "Percorso del file oci-compose",
"Path removed:": "Percorso rimosso:",
"Path to the client SSH public key on this server:": "Percorso della chiave pubblica SSH del client su questo server:",
"Path:": "Percorso:",
"Paths applied:": "Percorsi applicati:",
"Paths included in backup": "Percorsi inclusi nel backup",
@@ -5143,6 +5187,8 @@
"Personal finance management application": "Applicazione per la gestione delle finanze personali",
"Personal media server for browsing and playing a local video library, with direct play and optional modules.": "Server multimediale personale per sfogliare e riprodurre una raccolta video locale, con riproduzione diretta e moduli opzionali.",
"Photo and video library with optional GPU transcoding and machine learning": "Libreria di foto e video con transcodifica GPU e apprendimento automatico opzionali",
"Photo editing in your browser": "Fotoritocco nel browser",
"Photo library and RAW development in your browser": "Libreria fotografica e sviluppo RAW nel browser",
"PhotoPrism": "PhotoPrism",
"Photofield": "Photofield",
"Phpmyadmin is a free software tool written in PHP, intended to handle the administration of MySQL over the Web. phpMyAdmin supports a wide range of operations on MySQL and MariaDB.": "phpMyAdmin è uno strumento software libero scritto in PHP per amministrare MySQL via web. Supporta numerose operazioni su MySQL e MariaDB.",
@@ -5235,6 +5281,7 @@
"Preparing the machine learning container for the new choice...": "Preparazione del container per machine learning con la nuova scelta...",
"Preparing the recreation...": "Preparazione ricreazione...",
"Preparing the update...": "Preparazione dell'aggiornamento...",
"Presentations and slide decks in your browser": "Presentazioni e diapositive nel browser",
"Preserving logs to /var/log.hdd before unmounting...": "Conservazione dei log su /var/log.hdd prima dello smontaggio...",
"Press 'q' to exit": "Premi 'q' per uscire",
"Press Ctrl+C to stop the server and return to menu.": "Premi Ctrl+C per arrestare il server e tornare al menu.",
@@ -5340,6 +5387,7 @@
"ProxMenux does not install them. The installation asks how to connect to them.": "ProxMenux non li installa. Durante l'installazione ti verranno chiesti i dati di connessione.",
"ProxMenux does not validate the contents; any keyfile your PBS accepts is accepted here.": "ProxMenux non convalida i contenuti; qualsiasi file di chiavi accettato dal PBS viene accettato qui.",
"ProxMenux files:": "File ProxMenux:",
"ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.": "ProxMenux genera la password dell'amministratore e la mostra alla fine dell'installazione. Cambiala dopo il primo accesso.",
"ProxMenux logo applied": "Logo ProxMenux applicato",
"ProxMenux only acts as a launcher — once the script starts, control leaves ProxMenux.": "ProxMenux funge solo da launcher: una volta avviato lo script, il controllo lascia ProxMenux.",
"ProxMenux saved it locally at:": "ProxMenux lo ha salvato localmente in:",
@@ -5395,6 +5443,7 @@
"Proxmox web interface: Datacenter > Storage > Add > ZFS": "Interfaccia web Proxmox: Datacenter > Storage > Aggiungi > ZFS",
"Proxmox web interface: Datacenter > Storage > Add > iSCSI": "Interfaccia web Proxmox: Datacenter > Storage > Aggiungi > iSCSI",
"Proxy address to reach the API (optional)": "Indirizzo proxy per raggiungere l'API (facoltativo)",
"Public HTTPS URL used to open this Authelia portal (for example https://auth.example.com)": "URL HTTPS pubblico utilizzato per aprire questo portale Authelia (ad esempio https://auth.example.com)",
"Public UDP port clients connect to": "Porta UDP pubblica a cui si connettono i client",
"Public UDP port peers connect to": "Porta UDP pubblica a cui si connettono i peer",
"Public URL of phpMyAdmin when it is served behind a reverse proxy": "URL pubblico di phpMyAdmin quando viene servito dietro un proxy inverso",
@@ -5455,6 +5504,7 @@
"Re-running pre-check after repairs...": "Nuova esecuzione del controllo preliminare dopo la riparazione...",
"Reachable": "Raggiungibile",
"Read an oci-compose from a file of this host": "Leggi un oci-compose da un file dell’host",
"Read and edit PDF documents in your browser": "Lettura e modifica di documenti PDF nel browser",
"Read its Compose file from a file of this host": "Leggi il file Compose da un file dell’host",
"Read manga through a self-hosted server and web UI.": "Lettura di manga tramite un server self-hosted e un’interfaccia web.",
"Read the link with pct console CTID on the Proxmox host, or from the Console panel of the container in the Proxmox web interface, then open the https://playit.gg/claim/ address it shows in a browser and sign in to playit.gg. Ctrl+a q leaves pct console.": "Leggi il link con pct console CTID sull'host Proxmox oppure nel pannello Console del container nell'interfaccia web Proxmox. Apri nel browser l'indirizzo https://playit.gg/claim/ mostrato e accedi a playit.gg. Ctrl+a q chiude pct console.",
@@ -5558,8 +5608,10 @@
"Recreation prepared": "Ricreazione preparata",
"Recursive DNS resolver.": "Resolver DNS ricorsivo.",
"Recursive and authoritative DNS server.": "Server DNS ricorsivo e autorevole.",
"Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.": "Il blocco dei file con Redis viene configurato automaticamente. I file di configurazione esistenti di Nextcloud vengono conservati.",
"Redmine": "Redmine",
"Refresh APT index and verify repositories:": "Aggiorna l'indice APT e verifica i repository:",
"Refresh catalog": "Aggiorna catalogo",
"Refresh the configured APT repositories and review the PBS package upgrade? Repository files will be preserved.": "Aggiornare gli indici dei repository APT configurati ed esaminare l'aggiornamento dei pacchetti PBS? I file dei repository verranno conservati.",
"Refresh the index from the image sources": "Aggiorna l'indice dalle sorgenti delle immagini",
"Refresh token of the connector, from the Twingate admin console": "Token di refresh del connettore, dalla console di amministrazione Twingate",
@@ -5567,6 +5619,7 @@
"Refresh your browser to see changes (server restart may be required)": "Aggiorna il browser per vedere le modifiche (potrebbe essere necessario il riavvio del server)",
"Refreshing apt cache...": "Aggiornamento cache apt...",
"Refreshing the NVIDIA runtime...": "Aggiornamento del runtime NVIDIA...",
"Refreshing the application catalog...": "Aggiornamento del catalogo delle applicazioni...",
"Refusing an unexpected rootfs path:": "Rifiutato un percorso rootfs inatteso:",
"Regenerate the catalog templates": "Rigenera i modelli del catalogo",
"Regenerate the template of one application": "Rigenera il modello di un'applicazione",
@@ -5639,6 +5692,7 @@
"Remove Proxmox NFS storage:": "Rimuovi storage NFS Proxmox:",
"Remove Proxmox iSCSI storage:": "Rimuovi storage iSCSI Proxmox:",
"Remove Secure Gateway? State will be preserved.": "Rimuovere Secure Gateway? Lo stato sarà preservato.",
"Remove a remote USB connection": "Rimuovi una connessione USB remota",
"Remove custom paths": "Rimuovi percorsi personalizzati",
"Remove disk references from affected VM(s)/CT(s) config": "Rimuovi i riferimenti al disco dalle configurazioni VM/CT interessate",
"Remove every registered gasket DKMS version": "Rimuovi ogni versione DKMS di gasket registrata",
@@ -5659,6 +5713,7 @@
"Remove the lock left on a container by an interrupted task": "Rimuovere il blocco lasciato su un container da un’attività interrotta",
"Remove the saved credentials for {registry}?\nRunning apps will keep working.": "Rimuovere le credenziali salvate per {registry}?\nLe app in esecuzione continueranno a funzionare.",
"Remove the unprivileged flag from configuration:": "Rimuovi il flag unprivileged dalla configurazione:",
"Remove this connection and detach its USB device?": "Rimuovere questa connessione e scollegare il relativo dispositivo USB?",
"Remove unused packages and their config": "Rimuovi i pacchetti non utilizzati e la loro configurazione",
"Remove: delete the application and its containers": "Rimuovi: elimina l'applicazione e i suoi container",
"Removed": "RIMOSSO",
@@ -5881,9 +5936,11 @@
"Run mode: Unattended": "Modalità di esecuzione: non presidiata",
"Run now": "Esegui ora",
"Run security audit now": "Esegui subito il controllo di sicurezza",
"Run the client inside the Linux VM that needs the USB device. Install usbip, openssh-client and kmod, then copy usbip_manager.py to the same path as on the server. Configure key authentication and verify the server host key before adding a connection. The client uses the guest kernel and can reconnect after migration while the physical USB device stays on the server. Unprivileged LXC and Home Assistant OS need their own kernel/device or add-on setup. A physical device supports one attached client at a time.": "Esegui il client nella VM Linux che necessita del dispositivo USB. Installa usbip, openssh-client e kmod, poi copia usbip_manager.py nello stesso percorso usato sul server. Configura l'autenticazione tramite chiave e verifica la chiave host del server prima di aggiungere una connessione. Il client usa il kernel dell'ospite e può riconnettersi dopo una migrazione mentre il dispositivo USB fisico rimane sul server. Gli LXC non privilegiati e Home Assistant OS richiedono una configurazione specifica del kernel, dei dispositivi o dei componenti aggiuntivi. Un dispositivo fisico può essere collegato a un solo client alla volta.",
"Run the following inside the VM:": "Esegui quanto segue nella VM:",
"Run the release-channel switch from an SSH session or the Proxmox host console with:": "Esegui il cambio del canale di rilascio da una sessione SSH o dalla console dell’host Proxmox con:",
"Run the update from an SSH session or the Proxmox host console with:": "Esegui l’aggiornamento da una sessione SSH o dalla console dell’host Proxmox con:",
"Run this menu as root.": "Esegui questo menu come root.",
"Run this operation as root.": "Esegui questa operazione come root.",
"Run upgrade checklist script:": "Esegui lo script di controllo dell’aggiornamento:",
"Running": "In esecuzione",
@@ -6108,6 +6165,7 @@
"Select a new language for the menu:": "Seleziona una nuova lingua per il menu:",
"Select a post-installation script:": "Seleziona uno script post-installazione:",
"Select a pre-configured Linux VM script to execute:": "Seleziona uno script VM Linux preconfigurato da eseguire:",
"Select a saved USB/IP device:": "Seleziona un dispositivo USB/IP salvato:",
"Select a script or action:": "Seleziona uno script o un'azione:",
"Select a share to delete:": "Seleziona una condivisione da eliminare:",
"Select a specific Coral or USB node, not the whole /dev": "Seleziona un nodo Coral o USB specifico, non l’intera directory /dev",
@@ -6185,6 +6243,7 @@
"Select the Linux distribution to install:": "Seleziona la distribuzione Linux da installare:",
"Select the NAS system to install:": "Seleziona il sistema NAS da installare:",
"Select the NVIDIA driver version to install:": "Seleziona la versione del driver NVIDIA da installare:",
"Select the USB device to share:": "Seleziona il dispositivo USB da condividere:",
"Select the VM to add the GPU to:": "Seleziona la VM a cui aggiungere la GPU:",
"Select the VM to which you want to add disks:": "Seleziona la VM a cui aggiungere i dischi:",
"Select the VM where you want to import the disk image:": "Seleziona la VM in cui importare l’immagine disco:",
@@ -6209,6 +6268,7 @@
"Select the parent job to attach to:": "Seleziona l’attività principale a cui collegarsi:",
"Select the paths to restore (one per backup entry):": "Seleziona i percorsi da ripristinare (uno per voce di backup):",
"Select the privileged LXC container to convert:": "Seleziona il container LXC privilegiato da convertire:",
"Select the remote USB device:": "Seleziona il dispositivo USB remoto:",
"Select the storage that will receive the backups:": "Seleziona lo storage di destinazione dei backup:",
"Select the storage volume for disk import:": "Seleziona il volume storage per importare il disco:",
"Select the sync interval (in hours):": "Seleziona l'intervallo di sincronizzazione (in ore):",
@@ -6258,6 +6318,7 @@
"Self-hosted file sync and sharing.": "Servizio self-hosted per sincronizzare e condividere file.",
"Self-hosted file toolkit for images, video, audio, PDFs, and files": "Set di strumenti self-hosted per immagini, video, audio, PDF e altri file",
"Self-hosted forms and workflows.": "Moduli e flussi di lavoro auto-ospitati.",
"Self-hosted grocery list and recipe manager": "lista della spesa e gestore di ricette self-hosted",
"Self-hosted household plant-care tracker with reminders, photos, and multiple user accounts.": "Strumento per la cura delle piante domestiche da ospitare sul proprio server, con promemoria, foto e più account utente.",
"Self-hosted image-hosting service with authenticated uploads, image processing, public links, and local storage.": "Servizio per ospitare immagini sul proprio server, con caricamenti autenticati, elaborazione delle immagini, link pubblici e archiviazione locale.",
"Self-hosted internet archiving solution": "Soluzione self-hosted per archiviare contenuti Internet",
@@ -6294,6 +6355,7 @@
"Server IDs to test against, separated by commas (optional)": "ID dei server da usare per i test, separati da virgole (facoltativi)",
"Server IP/hostname is correct": "L'IP/nome host del server è corretto",
"Server IP:": "IP del server:",
"Server SSH port:": "Porta SSH del server:",
"Server is accessible:": "Il server è accessibile:",
"Server is online": "Il server è in linea",
"Server is running": "Il server è in esecuzione",
@@ -6355,6 +6417,7 @@
"Share Access Error": "Errore di accesso alla condivisione",
"Share Name": "Nome condivisione",
"Share Options": "Opzioni di condivisione",
"Share a local USB device": "Condividi un dispositivo USB locale",
"Share added successfully.": "Condivisione aggiunta con successo.",
"Share deleted and Samba service restarted.": "Condivisione eliminata e servizio Samba riavviato.",
"Share exists:": "La condivisione esiste:",
@@ -6362,6 +6425,7 @@
"Share name:": "Nome condivisione:",
"Share not found on server:": "Condivisione non trovata sul server:",
"Share path:": "Percorso condivisione:",
"Share selected USB devices through SSH, or connect this Linux machine to a USB/IP server.": "Condividi i dispositivi USB selezionati tramite SSH oppure collega questa macchina Linux a un server USB/IP.",
"Share updated successfully.": "Condivisione aggiornata con successo.",
"Share:": "Condivisione:",
"ShareCoveX panel": "Pannello ShareCoveX",
@@ -6452,6 +6516,7 @@
"Simple and easy to use DDNS": "DDNS semplice e facile da usare",
"Simple self-hosted file sharing.": "Servizio semplice e self-hosted per condividere file.",
"Single GPU Warning": "Avviso GPU singola",
"Single sign-on and multi-factor authentication": "Single Sign-On e autenticazione a più fattori",
"Single target found — selected automatically:": "Unica destinazione trovata - selezionata automaticamente:",
"Single-node log storage and query UI.": "Archiviazione dei log su un singolo nodo e interfaccia di interrogazione.",
"Single-node observability database for metrics, logs and traces.": "Database di osservabilità a nodo singolo per metriche, log e tracce.",
@@ -6520,7 +6585,9 @@
"Specific subnet (enter manually)": "Sottorete specifica (immettere manualmente)",
"Speedtest Tracker web interface": "Interfaccia web Speedtest Tracker",
"Speedtest-tracker is a self-hosted internet performance tracking application that runs speedtest checks against Ookla's Speedtest service.": "Speedtest-tracker è un'applicazione self-hosted per monitorare le prestazioni della connessione Internet eseguendo test tramite il servizio Speedtest di Ookla.",
"Spoolman web interface": "interfaccia web Spoolman",
"Spotube is an open source, cross-platform Spotify client compatible across multiple platforms utilizing Spotify's data API and YouTube, Piped.video or JioSaavn as an audio source, eliminating the need for Spotify Premium": "Spotube è un client Spotify open source e multipiattaforma che usa l'API dati di Spotify e YouTube, Piped.video o JioSaavn come sorgenti audio, eliminando la necessità di Spotify Premium",
"Spreadsheets in your browser": "Fogli di calcolo nel browser",
"Sshwifty": "Sshwifty",
"Sshwifty web access (password only)": "Accesso web a Sshwifty (solo password)",
"Stable (main branch)": "Stabile (ramo main)",
@@ -6627,6 +6694,8 @@
"Still has issues": "Ha ancora problemi",
"Stop - shuts the guest down during backup": "Stop - arresta il guest durante il backup",
"Stop it first and run this option again.": "Interrompilo prima ed esegui nuovamente questa opzione.",
"Stop sharing a USB device": "Interrompi la condivisione di un dispositivo USB",
"Stop sharing this device? An attached remote client will disconnect.": "Interrompere la condivisione di questo dispositivo? Il client remoto collegato verrà disconnesso.",
"Stop that VM, then choose:": "Arresta quella VM, quindi scegli:",
"Stop the CT, unmount the disk on the HOST, and remount with:": "Arresta il CT, smonta il disco sull’HOST e rimontalo con:",
"Stop the VM/CT before formatting this disk.": "Arresta la VM o il CT prima di formattare questo disco.",
@@ -6982,6 +7051,7 @@
"The container could not be removed automatically:": "Impossibile rimuovere automaticamente il container:",
"The container could not be started:": "Impossibile avviare il container:",
"The container creation does not match the prepared instance": "La creazione del container non corrisponde all'istanza preparata",
"The container device settings changed since the last recorded operation": "Le impostazioni del dispositivo del container sono cambiate dall’ultima operazione registrata",
"The container devices do not match the saved record": "I dispositivi del container non corrispondono al record salvato",
"The container did not stop to update its persistent configuration:": "Il container non si è arrestato per aggiornare la configurazione persistente:",
"The container did not stop; its disks are not touched": "Il container non si è arrestato; i suoi dischi non vengono toccati",
@@ -7263,6 +7333,7 @@
"The record no longer belongs to this operation": "Il record non appartiene più a questa operazione",
"The record of a member was replaced; the assembly is not resumed": "Il record di un componente è stato sostituito; la composizione dello stack non riprende",
"The record or diagnosis could not be completed; no update was run.": "Non è stato possibile completare la registrazione o la diagnosi; non è stato eseguito alcun aggiornamento.",
"The recorded container device GID does not match its configuration": "Il GID registrato del dispositivo del container non corrisponde alla sua configurazione",
"The recovery did not complete. Review the log and choose \"Recover\" again for this container in the OCI management menu.": "Il recupero non è completo. Rivedere il registro e scegliere \"Recuperare\" di nuovo per questo contenitore nel menu di gestione OCI.",
"The recovery did not complete. Review the log and choose \"{choice}\" again for this container in the OCI management menu.": "Il ripristino non è stato completato. Controllare il log e scegliere di nuovo \"{choice}\" per questo container nel menu di gestione OCI.",
"The registry authentication file is invalid; it was not changed.": "Il file di autenticazione del registro non è valido; non è stato modificato.",
@@ -7330,6 +7401,7 @@
"The selected Intel GPU has non-FLR reset support and unknown subtype": "La GPU Intel selezionata ha il supporto per il ripristino non FLR e un sottotipo sconosciuto",
"The selected Intel GPU is currently in power state D3cold": "La GPU Intel selezionata è nello stato di alimentazione D3cold",
"The selected Intel render device does not exist:": "Il dispositivo di rendering Intel selezionato non esiste:",
"The selected USB device will become unavailable to local applications and guests. Only one remote client can use it at a time. Share this device?": "Il dispositivo USB selezionato non sarà più disponibile per le applicazioni e gli ospiti locali. Può usarlo un solo client remoto alla volta. Condividere questo dispositivo?",
"The selected VM": "La VM selezionata",
"The selected VM is running.": "La VM selezionata è in esecuzione.",
"The selected base folder does not exist and could not be created:": "La cartella di base selezionata non esiste e non è stato possibile crearla:",
@@ -7417,6 +7489,7 @@
"Then bind-mount to container": "Quindi eseguire un bind mount nel container",
"Then change the VM display to none (vga: none) when the guest is stable.": "Quindi impostare il display VM su none (vga: none) quando il guest è stabile.",
"Then change the VM display to none (vga: none) when the system is stable.": "Quindi impostare il display VM su none (vga: none) quando il sistema è stabile.",
"Then restart the container so the new model appears in the list.": "Poi riavvia il container perché il nuovo modello compaia nell'elenco.",
"Then run this option again:": "Quindi eseguire di nuovo questa opzione:",
"Then update /etc/fstab on the host with the same options.": "Quindi aggiornare /etc/fstab sull’host con le stesse opzioni.",
"There are extra disks or bind mounts outside the journal; the rootfs is not replaced": "Ci sono dischi aggiuntivi o bind mount non registrati nel journal; la rootfs non viene sostituita",
@@ -7464,6 +7537,7 @@
"This container does not have apt-get. NFS client installation only supports Debian/Ubuntu containers.": "Questo container non ha apt-get. L'installazione del client NFS supporta solo i container Debian/Ubuntu.",
"This container does not have apt-get. Samba client installation only supports Debian/Ubuntu containers.": "Questo container non ha apt-get. L'installazione del client Samba supporta solo i container 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.": "Questo container non ha una GPU configurata. Coral TPU funziona meglio insieme alla decodifica video hardware (Quick Sync, VA-API, NVENC) per app come Frigate.",
"This container is managed by high availability. Remove ct:{vmid} from HA (Datacenter → HA, or ha-manager remove ct:{vmid}), repeat the operation and add it back to HA with the same settings.": "Questo container è gestito dall'alta disponibilità. Rimuovi ct:{vmid} da HA (Datacenter → HA, oppure ha-manager remove ct:{vmid}), ripeti l'operazione e aggiungilo di nuovo a HA con le stesse impostazioni.",
"This container is not a member of a multi-container application": "Questo container non fa parte di un’applicazione con più container",
"This container is not a registered OCI instance.": "Questo container non è un’istanza OCI registrata.",
"This container was restored or came back from another host after its record on this host was written. Open this menu again to recover it; nothing was changed.": "Questo contenitore è stato ripristinato o è tornato da un altro host dopo la scrittura del suo record su questo host. Apri nuovamente questo menu per recuperarlo; non è stato modificato nulla.",
@@ -7582,6 +7656,7 @@
"Tip: You can install the QEMU Guest Agent inside the VM with:": "Suggerimento: è possibile installare QEMU Guest Agent nella VM con:",
"Tip: zfs set acltype=posixacl xattr=sa <pool>/<dataset> enables full ACL support.": "Suggerimento: zfs set acltype=posixacl xattr=sa <pool>/<dataset> abilita il supporto ACL completo.",
"Tmpfs size in MiB for": "Dimensione tmpfs in MiB per",
"To add a model, open the console of the container in Proxmox and download it into /models, for example:": "Per aggiungere un modello, apri la console del container in Proxmox e scaricalo in /models, ad esempio:",
"To allow LXC write access, change the NFS export on the server to include:": "Per consentire l'accesso in scrittura LXC, modificare l'esportazione NFS sul server per includere:",
"To apply it to the current shell now, run:": "Per applicarlo ora alla shell corrente, eseguire:",
"To assign VFs to VMs or LXCs, edit the configuration manually via the Proxmox web interface. The Physical Function will remain bound to the native driver.": "Per assegnare VF a VM o LXC, modificare manualmente la configurazione tramite l'interfaccia web Proxmox. La funzione fisica resterà associata al driver nativo.",
@@ -7621,6 +7696,7 @@
"Total routes": "Rotte totali",
"Total size:": "Dimensione totale:",
"Toxiproxy": "Toxiproxy",
"Track 3D printer filament spools and usage.": "monitora le bobine e l'utilizzo dei filamenti della stampante 3D.",
"Track movies, television, anime and games you want to enjoy.": "Tieni traccia di film, serie TV, anime e videogiochi che vuoi guardare o provare.",
"Track subscriptions and recurring expenses.": "Tieni traccia degli abbonamenti e delle spese ricorrenti.",
"Track your music listening history on your own server.": "Tieni traccia della cronologia di ascolto musicale sul tuo server.",
@@ -7665,6 +7741,9 @@
"USB drives mounted now:": "Unità USB montate ora:",
"USB libedgetpu1": "USB libedgetpu1",
"USB or serial device node": "Nodo dispositivo USB o seriale",
"USB/IP configuration updated. Open status to check the connection.": "Configurazione USB/IP aggiornata. Apri lo stato per verificare la connessione.",
"USB/IP over SSH": "USB/IP tramite SSH",
"USB/IP server IP address or DNS hostname:": "Indirizzo IP o nome host DNS del server USB/IP:",
"UUP Dump script not found.": "Script UUP Dump non trovato.",
"UUp Dump ISO creator Custom": "UUp Dump - Creazione ISO personalizzate",
"Ubooquity is a free, lightweight and easy-to-use home server for your comics and ebooks. Use it to access your files from anywhere, with a tablet, an e-reader, a phone or a computer.": "Ubooquity è un server domestico gratuito, leggero e facile da usare per fumetti ed ebook. Consente l’accesso ai file ovunque, da tablet, e-reader, telefono o computer.",
@@ -7821,6 +7900,7 @@
"Untrusted or modified NVIDIA hook": "Hook NVIDIA non attendibile o modificato",
"Unused image removed from the cache:": "Immagine inutilizzata rimossa dalla cache:",
"Unused images removed from the cache:": "Immagini non utilizzate rimosse dalla cache:",
"Unused local loopback TCP port for this device:": "Porta TCP locale di loopback inutilizzata per questo dispositivo:",
"Update": "Aggiornamento",
"Update Available": "Aggiornamento disponibile",
"Update Ceph repository (Only if using Ceph):": "Aggiorna repository Ceph (solo se si utilizza Ceph):",
@@ -7855,6 +7935,7 @@
"Update the whole stack?": "Aggiornare l’intero stack?",
"Update, modify or recreate one installed OCI instance": "Aggiorna, modifica o ricrea un'istanza OCI installata",
"Updated": "Aggiornato",
"Updated recipes since your last visit: {count}": "Ricette aggiornate dalla tua ultima visita: {count}",
"Updated sharedfiles group to GID: 101000": "Gruppo sharedfiles aggiornato a GID: 101000",
"Updated stack checked": "Stack aggiornato verificato",
"Updated:": "Aggiornato:",
@@ -7918,6 +7999,7 @@
"Use a privileged LXC for NFS server/client workflows.": "Usare un LXC privilegiato per le operazioni server/client NFS.",
"Use a privileged LXC for Samba client/server workflows.": "Usare un LXC privilegiato per le operazioni client/server Samba.",
"Use a registry hostname, for example ghcr.io or registry.example.com:5000.": "Utilizza un nome host del registro, ad esempio ghcr.io o registry.example.com:5000.",
"Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time.": "Usa un proxy inverso HTTPS con un certificato attendibile. Aggiorna Nextcloud alla versione principale successiva, senza saltarne nessuna.",
"Use an existing SSH private key file on this host": "Usa un file di chiave privata SSH esistente su questo host",
"Use an existing keyfile": "Usa file di chiavi esistente",
"Use an image reference, for example ghcr.io/owner/app:latest.": "Utilizza un riferimento a un'immagine, ad esempio ghcr.io/owner/app:latest.",
@@ -7931,6 +8013,7 @@
"Use existing filesystem": "Usa file system esistente",
"Use existing: mount without formatting": "Usa esistente: monta senza formattare",
"Use images only if the directory is on suitable storage.": "Usare images solo se la directory è su uno storage adatto.",
"Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.": "Usa lo storage gestito per /config e MariaDB. Per /data puoi scegliere una directory dell’host/NAS, che richiede un backup separato.",
"Use mp1/mp2/... for extra mount points.": "Usare mp1/mp2/... per mount aggiuntivi.",
"Use only when unprivileged containers cannot meet your needs": "Usare solo se i container non privilegiati non soddisfano le esigenze",
"Use option 1 to add a local disk (as Proxmox storage and/or as a host mount).": "Usare l’opzione 1 per aggiungere un disco locale (come storage Proxmox e/o mount host).",
@@ -8060,6 +8143,7 @@
"Variables": "Variabili",
"Variables the installation asks for:": "Variabili richieste durante l’installazione:",
"Vaultwarden Web Vault": "Vaultwarden Web Vault",
"Vector illustration in your browser": "Illustrazione vettoriale nel browser",
"Vector search engine with a built-in dashboard.": "Motore di ricerca vettoriale con dashboard integrata.",
"Verbose pool status": "Stato pool dettagliato",
"Verification": "Verifica",
@@ -8090,6 +8174,7 @@
"Versions shown belong to maintained NVIDIA branches that list your GPU PCI ID and are new enough to build against the running kernel. DKMS compilation is the final validation. The recommended version keeps the current branch, or uses the NVIDIA Production Branch on a fresh install.": "Le versioni mostrate appartengono a rami NVIDIA mantenuti che elencano l’ID PCI della tua GPU e sono abbastanza recenti da poter essere compilate per il kernel in esecuzione. La compilazione DKMS costituisce la verifica finale. La versione consigliata mantiene il ramo corrente oppure, per una nuova installazione, utilizza NVIDIA Production Branch.",
"VictoriaLogs": "VictoriaLogs",
"Video acceleration and object detection are independent choices; the installer does not write camera or detector YAML.": "L'accelerazione video e il rilevamento degli oggetti sono scelte indipendenti; l'installer non scrive la configurazione YAML delle telecamere o dei rilevatori.",
"Video editing in your browser": "Montaggio video nel browser",
"Video transcoding acceleration": "Accelerazione transcodifica video",
"Video transcoding profile not implemented:": "Profilo transcodifica video non implementato:",
"View CIFS Mounts (pvesm + fstab)": "Visualizza montaggi CIFS (pvesm + fstab)",
@@ -8099,6 +8184,7 @@
"View Disk Storages": "Visualizza storage su disco",
"View Mount Points": "Visualizza punti di montaggio",
"View NFS Mounts (pvesm + fstab)": "Visualizza montaggi NFS (pvesm + fstab)",
"View USB/IP status": "Visualizza lo stato USB/IP",
"View backup metadata": "Visualizza metadati backup",
"View current paths": "Visualizza percorsi correnti",
"View existing folders in /mnt": "Visualizza cartelle esistenti in /mnt",
@@ -8199,12 +8285,17 @@
"Web access": "Accesso web",
"Web address of the AdGuard Home that receives the settings (e.g. http://192.168.1.3)": "Indirizzo web dell'istanza AdGuard Home che riceve le impostazioni (ad es. http://192.168.1.3)",
"Web address of the main AdGuard Home, whose settings are copied (e.g. http://192.168.1.2)": "Indirizzo web dell'istanza AdGuard Home principale, da cui vengono copiate le impostazioni (ad es. http://192.168.1.2)",
"Web dashboard": "Dashboard web",
"Web dashboard and WebDAV": "Dashboard web e WebDAV",
"Web interface": "Interfaccia web",
"Web interface for Borg Backup repositories and jobs.": "Interfaccia web per repository e job di Borg Backup.",
"Web interface for managing 3D printers.": "Interfaccia web per gestire stampanti 3D.",
"Web interface to manage devices running Tasmota firmware.": "Interfaccia web per gestire dispositivi con firmware Tasmota.",
"Web reverse proxy with an administration interface.": "Proxy inverso web con interfaccia di amministrazione.",
"WebCord can be summarized as a pack of security and privacy hardenings, Discord features reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, internal pages and wrapped https://discord.com page, designed to conform with ToS as much as it is possible (or hide the changes that might violate it from Discord's eyes).": "WebCord comprende miglioramenti alla sicurezza e alla privacy, reimplementazioni di funzioni di Discord, soluzioni alternative ai bug di Electron, Chromium e Discord, fogli di stile, pagine interne e la pagina https://discord.com incapsulata. È progettato per rispettare i termini di servizio per quanto possibile (o nascondere a Discord le modifiche che potrebbero violarli).",
"WebDAV": "WebDAV",
"WebDAV and dashboard password (leave empty to generate)": "Password di WebDAV e della dashboard (campo vuoto = generata)",
"WebDAV is available on container port 8080. Account linking is required before cloud file operations.": "WebDAV è disponibile sulla porta 8080 del container. Prima di operare sui file del cloud bisogna collegare l'account.",
"Webgrabplus is a multi-site incremental xmltv epg grabber. It collects tv-program guide data from selected tvguide sites for your favourite channels.": "Webgrabplus acquisisce dati EPG XMLTV incrementalmente da più siti. Raccoglie le guide TV dai siti selezionati per i canali preferiti.",
"Webservers & Proxies": "Server web e proxy",
"Website": "Sito web",
@@ -8262,6 +8353,7 @@
"Without a usable reset path, passthrough reliability is poor and VM": "Senza un metodo di reset utilizzabile, l'affidabilità del passthrough è scarsa e per le VM",
"Wizard cancelled": "Procedura guidata annullata",
"Wolfenstein: Blade of Agony is a story-driven WWII shooter inspired by Wolfenstein and Doom.": "Wolfenstein: Blade of Agony è uno sparatutto ambientato nella seconda guerra mondiale e incentrato sulla storia, ispirato a Wolfenstein e Doom.",
"Word processing in your browser": "Elaborazione di testi nel browser",
"Workflow automation tool": "Strumento automazione flussi di lavoro",
"Working directory:": "Directory di lavoro:",
"Works with LVM, ZFS, and BTRFS storage types": "Funziona con storage LVM, ZFS e BTRFS",
@@ -8312,6 +8404,8 @@
"Your machine learning Env work with Jupyter Lab": "Ambiente machine learning con Jupyter Lab",
"Your next YouTube media manager": "Il tuo prossimo gestore di video YouTube",
"Your_spotify is a self-hosted application that tracks what you listen and offers you a dashboard to explore statistics about it! It's composed of a web server which polls the Spotify API every now and then and a web application on which you can explore your statistics.": "Your_spotify è un’applicazione self-hosted che traccia gli ascolti e offre una dashboard per consultarne le statistiche. Comprende un server web che interroga periodicamente l’API Spotify e un’applicazione web per esplorare le statistiche.",
"Z-Wave JS UI": "Z-Wave JS UI",
"Z-Wave JS UI admin login": "accesso amministratore Z-Wave JS UI",
"ZFS ARC config removed (kernel defaults will apply on reboot)": "Configurazione ZFS ARC rimossa (valori predefiniti del kernel applicati al riavvio)",
"ZFS ARC maximum configured:": "Limite massimo ZFS ARC configurato:",
"ZFS ARC optimization completed": "Ottimizzazione ZFS ARC completata",
@@ -8425,6 +8519,7 @@
"could not be compiled for kernel": "non è stato possibile compilarlo per il kernel",
"could not validate NVIDIA; exit code": "impossibile convalidare NVIDIA; codice di uscita",
"cpuunits must be between 8 and 10000": "cpuunits deve essere compreso tra 8 e 10000",
"curl -L -o /models/gemma-3-1b-it-Q4_K_M.gguf https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf": "curl -L -o /models/gemma-3-1b-it-Q4_K_M.gguf https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf",
"custom": "personalizzato",
"custom dependency commands are not yet supported": "i comandi di dipendenza personalizzati non sono ancora supportati",
"custom path(s) saved.": "percorsi personalizzati salvati.",
@@ -8631,6 +8726,7 @@
"kexec-tools is not installed or already removed.": "kexec-tools non è installato o è già stato rimosso.",
"layers": "layer",
"legacy .link file(s) to the ProxMenux-managed format": "file .link legacy nel formato gestito da ProxMenux",
"llama.cpp shows every GGUF model saved in /models in its web UI and loads the one you choose.": "llama.cpp mostra nella sua interfaccia web tutti i modelli GGUF salvati in /models e carica quello scelto.",
"log2ram completely removed from system": "log2ram completamente rimosso dal sistema",
"main container of the application": "container principale dell'applicazione",
"make cloned mount tree read-only": "impostazione in sola lettura dell'albero di mount clonato",
+96
View File
@@ -184,6 +184,7 @@
"A tunneling daemon by Cloudflare that safely exposes your web servers into the internet.": "Um daemon de túneis pela Cloudflare que expõe com segurança seus servidores web na internet.",
"A unified email and collaboration server.": "Um servidor unificado de e-mail e colaboração.",
"A unified platform for logs, metrics and traces.": "Uma plataforma unificada para logs, métricas e traces.",
"A validating, recursive DNS resolver for your private network.": "um resolvedor DNS recursivo e validador para sua rede privada.",
"A versatile file conversion tool that supports multiple formats.": "Uma ferramenta versátil de conversão de arquivos que suporta vários formatos.",
"A visual tool for exploring and documenting database schemas.": "Uma ferramenta visual para explorar e documentar esquemas de bases de dados.",
"A web GUI client of Project V which supports VMess, VLESS, SS, SSR, Trojan, Tuic and Juicity protocols": "Um cliente web GUI do Projeto V que suporta protocolos VMess, VLESS, SS, SS, SSR, Trojan, Tuic e Juicity",
@@ -245,6 +246,7 @@
"Aborted": "Abortado",
"About to restore": "Prestes a restaurar",
"Absolute directory path to use as backup target:": "caminho absoluto do diretório para usar como destino de backup:",
"Absolute path of the client SSH private key:": "Caminho absoluto da chave privada SSH do cliente:",
"Absolute path to a file or directory you want backed up:": "Caminho absoluto para um arquivo ou diretório do qual deseja fazer backup:",
"Acceleration": "Aceleração",
"Acceleration configuration cancelled": "Configuração da aceleração cancelada",
@@ -256,6 +258,7 @@
"Acceleration for llama.cpp": "Aceleração para llama.cpp",
"Accept routes from other nodes?": "Aceita rotas de outros nós?",
"Accept this host monitoring profile?": "Aceita este perfil de monitorização da máquina?",
"Access Movistar and O2 Cloud from WebDAV clients and backup tools.": "Acesse a nuvem da Movistar e da O2 a partir de clientes WebDAV e ferramentas de backup.",
"Access Scope:": "Escopo de acesso:",
"Access bridge": "Ponte de acesso",
"Access bridge for Immich": "Ponte de acesso para Immich",
@@ -410,6 +413,7 @@
"After the reboot, you will only be able to access the Proxmox host via:": "Após a reinicialização, você só poderá acessar o host Proxmox via:",
"After this LXC → VM switch, reboot the host so the new binding state is applied cleanly.": "Após esta opção LXC → VM, reinicialize o host para que o novo estado de ligação seja aplicado de forma limpa.",
"Agentless monitoring and observability platform.": "Plataforma de monitoramento e observabilidade sem agentes.",
"AirDC++ administrator": "Administrador do AirDC++",
"Airsonic Advanced web interface": "Interface Web Airsonic Advanced",
"Airsonic-advanced is a free, web-based media streamer, providing ubiquitious access to your music. Use it to share your music with friends, or to listen to your own music while at work. You can stream to multiple players simultaneously, for instance to one player in your kitchen and another in your living room.": "Airsonic-avanced é uma transmissão de mídia gratuita, baseada na web, proporcionando ubiquitious acesso à sua música. Use-o para compartilhar sua música com amigos, ou para ouvir sua própria música durante o trabalho. Você pode transmitir para vários jogadores simultaneamente, por exemplo para um jogador na sua cozinha e outro na sua sala de estar.",
"Aliases added to .bashrc": "Aliases adicionados a .bashrc",
@@ -598,11 +602,15 @@
"Attention: Removing the subscription banner may cause issues in the web interface after a future update.": "Atenção: A remoção do banner de assinatura pode causar problemas na interface web após uma atualização futura.",
"Audacity is an easy-to-use, multi-track audio editor and recorder. Developed by a group of volunteers as open source.": "Audacity é um editor e gravador de áudio de várias faixas fácil de usar. Desenvolvido por um grupo de voluntários como código aberto.",
"Audio device directory": "Directório do dispositivo de áudio",
"Audio recording and mixing in your browser": "Gravação e mixagem de áudio no navegador",
"Audiobookshelf is a self-hosted audiobook and podcast server.": "Audiobookshelf é um servidor de áudio e podcast self-hosted.",
"Audit completed. Press Enter to continue...": "Auditoria concluída. Pressione Enter para continuar...",
"Audit socket disabled or not required": "soquete de auditoria desabilitado ou não necessário",
"Auth key is required.": "A chave de autenticação é obrigatória.",
"Auth:": "Autenticação:",
"Authelia Web UI": "UI da Web Authelia",
"Authelia administrator": "administrador Authelia",
"Authelia session cookie domain for this portal (for example example.com)": "domínio de cookie de sessão Authelia para este portal (por exemplo example.com)",
"Authentication": "Autenticação",
"Authentication & Security": "Autenticação e segurança",
"Authentication Error": "Erro de autenticação",
@@ -612,6 +620,8 @@
"Authentication:": "Autenticação:",
"Authorization failed": "Falha na autorização",
"Authorization successful": "Autorização bem-sucedida",
"Authorize a client SSH public key": "Autorizar a chave pública SSH de um cliente",
"Authorize a dedicated client public key on the server first. The restricted USB/IP account cannot run a shell or forward other sockets. Verify the server host key before connecting; unknown keys are rejected.": "Autorize primeiro uma chave pública dedicada do cliente no servidor. A conta USB/IP restrita não pode abrir uma shell nem encaminhar outros sockets. Verifique a chave do servidor antes de ligar; as chaves desconhecidas são rejeitadas.",
"Authorize this key on the server": "Autorize esta chave no servidor",
"Authorize via 'pct exec' (Borg server is an LXC on a PVE host I can SSH into)": "Autorizar via 'pct exec' (o servidor Borg é um LXC em um host PVE no qual posso usar SSH)",
"Authorized": "Autorizado",
@@ -642,6 +652,7 @@
"Available PVE Version": "Versão PVE disponível",
"Available Shares:": "Ações disponíveis:",
"Available action": "Ação disponível",
"Available applications: {count}": "Aplicações disponíveis: {count}",
"Available archives:": "Arquivos disponíveis:",
"Available disks detected.": "Discos disponíveis detectados.",
"Available host backups:": "Backups de host disponíveis:",
@@ -873,6 +884,7 @@
"Cannot write the image archive to {storage}. Check storage access and mount status.": "Não é possível gravar o arquivo de imagem em {storage}. Verifique o acesso ao armazenamento e o status de montagem.",
"Capabilities cannot be kept and all dropped at the same time": "Capacidades não podem ser mantidas e todas retiradas ao mesmo tempo",
"Catalog options": "Opções do catálogo",
"Catalog refresh unavailable; using the local catalog.": "Não foi possível atualizar o catálogo; está a ser usada a cópia local.",
"Category": "Categoria",
"Caution: Maximum mode generates more heat.": "Cuidado: O modo máximo gera mais calor.",
"Central server for file and image backups.": "Servidor central para backups de arquivos e imagens.",
@@ -1159,6 +1171,7 @@
"Compressing": "Comprimindo",
"Compression": "Compressão",
"Compression Tools": "Ferramentas de compressão",
"Computer-aided design and drafting in your browser": "Projeto CAD e desenho técnico no navegador",
"Concise output of logical volumes": "Saída concisa de volumes lógicos",
"Concise output of physical volumes": "Saída concisa de volumes físicos",
"Concise output of volume groups": "Saída concisa de grupos de volumes",
@@ -1289,6 +1302,7 @@
"Conflicting utilities removed": "Utilitários conflitantes removidos",
"Connect Zigbee devices to MQTT with a browser-based setup interface.": "Conecte dispositivos Zigbee ao MQTT por meio de uma interface web de configuração.",
"Connect a Coral Accelerator and try again.": "Conecte um Coral Accelerator e tente novamente.",
"Connect a remote USB device": "Ligar um dispositivo USB remoto",
"Connect it, or remove it from the container in Proxmox (Resources), and run the recovery again.": "Conecte-o ou remova-o do contêiner em Proxmox (Recursos) e execute a recuperação novamente.",
"Connect your devices and users together in your own secure virtual private network.": "Conecte seus dispositivos e usuários em sua própria rede privada virtual segura.",
"Connect your devices into a secure WireGuard®-based overlay network with SSO, MFA and granular access controls.": "Conecte seus dispositivos a uma rede segura de sobreposição WireGuard® com controles de acesso SSO, MFA e granular.",
@@ -1393,6 +1407,7 @@
"Controller + NVMe": "Controlador + NVMe",
"Controller + NVMe assignment will be written now and become active after host reboot.": "A atribuição de controlador + NVMe será gravada agora e se tornará ativa após a reinicialização do host.",
"Controller + NVMe passthrough requires machine type q35. Skipping controller assignment.": "A passagem Controlador + NVMe requer tipo de máquina q35. Ignorando atribuição do controlador.",
"Controller path on the Proxmox host; prefer /dev/serial/by-id/...": "caminho do controlador no host Proxmox;prefira /dev/serial/by-id/...",
"Controller/NVMe Conflict Policy": "Política de Conflito Controlador/NVMe",
"Controller/NVMe already present in VM config": "Controlador/NVMe já presente na configuração da VM",
"Controller/NVMe already present in VM config (%s)": "Controlador/NVMe já presente na configuração da VM (%s)",
@@ -1927,6 +1942,7 @@
"Dgraph": "Dgraph",
"Diff: current system vs backup (--- system +++ backup)": "Diferença: sistema atual vs backup (--- backup do sistema +++)",
"Different host. Backup from:": "Anfitrião diferente. Backup de:",
"Direct Connect file sharing with a web interface": "Partilha de ficheiros Direct Connect com interface web",
"Direct conversion completed for container": "Conversão direta concluída para contêiner",
"Directory Exists": "O diretório existe",
"Directory Not Empty": "Diretório não vazio",
@@ -1949,12 +1965,14 @@
"Directus administrator": "Administrador do Directus",
"Disable NIC Offloading (Intel e1000e)": "Desativar descarregamento de NIC (Intel e1000e)",
"Disable Secure Boot in the UEFI firmware and run the installer again. Nothing has been changed.": "Desative o Secure Boot no firmware UEFI e execute o instalador novamente. Nada foi alterado.",
"Disable USB/IP server": "Desativar o servidor USB/IP",
"Disable autostart on conflicting VM": "Desative a inicialização automática em VM conflitante",
"Disable autostart on one VM to avoid startup conflicts.": "Desative a inicialização automática em uma VM para evitar conflitos de inicialização.",
"Disable job": "Desativar trabalho",
"Disable kernel audit messages (optional but recommended):": "Desative as mensagens de auditoria do kernel (opcional, mas recomendado):",
"Disable onboot on affected VM(s)/CT(s)": "Desativar inicialização em VM(s)/CT(s) afetados",
"Disable portmapper/rpcbind": "Desativar portmapper/rpcbind",
"Disable the server and release all USB devices managed by ProxMenux? Saved selections are kept for the next enable.": "Desativar o servidor e libertar todos os dispositivos USB geridos pelo ProxMenux? As seleções guardadas serão mantidas para a próxima ativação.",
"Disabled": "Desabilitado",
"Disabling High Availability services...": "Desativando serviços de alta disponibilidade...",
"Disabling ZFS autotrim applied by ProxMenux...": "Desativando o ajuste automático do ZFS aplicado pelo ProxMenux...",
@@ -2187,6 +2205,7 @@
"Enable Remote Desktop (RDP) before disabling the virtual display.": "Habilite a Área de Trabalho Remota (RDP) antes de desabilitar a exibição virtual.",
"Enable SSD emulation for this disk?": "Ativar emulação SSD para este disco?",
"Enable TCP BBR/Fast Open control": "Habilitar controle TCP BBR/Fast Open",
"Enable USB/IP server": "Ativar o servidor USB/IP",
"Enable VA-API transcoding and HDR10/Dolby Vision to SDR tone mapping": "Habilitar transcodificação VA-API e HDR10/Dolby Vision para mapeamento de tom SDR",
"Enable VA-API, hardware encoding and OpenCL tone mapping in Jellyfin": "Habilitar VA-API, codificação de hardware e mapeamento de tom OpenCL em Jellyfin",
"Enable VFIO IOMMU support": "Habilitar suporte VFIO IOMMU",
@@ -3200,6 +3219,7 @@
"If pvesm path returned a DEVICE (LVM):": "Se pvesm path devolveu um DISPOSITIVO (LVM):",
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Se pvesm path devolveu um DIRETÓRIO (ZFS/BTRFS):",
"If repositories error:": "Se houver erro nos repositórios:",
"If the USB/IP service stops unexpectedly, stop sharing while the device is still connected to release it. In rare cases only a host reboot releases it.": "Se o serviço USB/IP parar inesperadamente, deixe de partilhar o dispositivo enquanto ainda estiver ligado para o libertar. Em casos raros, só um reinício do host o liberta.",
"If the container had already been changed, its previous native backup is restored. Shared host directories are not reverted. The disks of the failed attempt are removed when the cleanup succeeds.": "Se o contêiner já tiver sido alterado, seu backup nativo anterior será restaurado. Os diretórios de host compartilhados não são revertidos. Os discos da tentativa fracassada serão removidos quando a limpeza for bem-sucedida.",
"If the host freezes, remove hostpci entries from": "Se o host congelar, remova as entradas hostpci de",
"If the image channel has a new version, the CT is stopped, backed up and verified, and replaced with the new image to update the container. If anything fails, the backup is restored.": "Se o canal de imagem tiver uma nova versão, o CT é interrompido, feito backup e verificado e substituído pela nova imagem para atualizar o contêiner. Se algo falhar, o backup será restaurado.",
@@ -3340,6 +3360,7 @@
"Initial Stirling-PDF account": "Conta inicial do Stirling-PDF",
"Initial Tandoor administrator": "Administrador inicial Tandoor",
"Initial Umami administrator": "Administrador inicial do Umami",
"Initial Z-Wave JS UI admin password": "Senha de administrador inicial do Z-Wave JS UI",
"Initial administrator created:": "Administrador inicial criado:",
"Initial administrator user": "Utilizador de administrador inicial",
"Initializing Borg repository if needed...": "Inicializando o repositório Borg, se necessário...",
@@ -3393,6 +3414,7 @@
"Install server packages inside CT:": "Instale pacotes de servidores dentro do CT:",
"Install terminal multiplexers": "Instale multiplexadores de terminal",
"Install the Edge TPU runtime (libedgetpu1-std)": "Instale o tempo de execução do Edge TPU (libedgetpu1-std)",
"Install the USB/IP dependencies from the configured Debian repositories?": "Instalar as dependências USB/IP a partir dos repositórios Debian configurados?",
"Install this image?": "Instalar esta imagem?",
"Install with Cloud-Init script": "Instalar com script Cloud-Init",
"Install with ISO from UUP Dump": "Instalar com ISO do UUP Dump",
@@ -3525,6 +3547,7 @@
"Interface MTU": "Interface MTU",
"Interface Names (persistent)": "Nomes de Interface (persistente)",
"Interface Type": "Tipo de interface",
"Interface design and prototyping in your browser": "Design de interfaces e protótipos no navegador",
"Interface names will return to default systemd behavior.": "Os nomes das interfaces retornarão ao comportamento padrão do systemd.",
"Interface type:": "Tipo de interface:",
"Interfaces configured": "Interfaces configuradas",
@@ -3582,6 +3605,7 @@
"Invalid check package:": "Pacote de verificação inválido:",
"Invalid configuration path:": "Caminho de configuração inválido:",
"Invalid consume/export volumes": "Volumes de consumo/exportação inválidos",
"Invalid container device GID": "GID do dispositivo do contentor inválido",
"Invalid container path:": "Localização do contentor inválida:",
"Invalid credential file path:": "Caminho do arquivo credential inválido:",
"Invalid declarative entrypoint": "Ponto de entrada declarativo inválido",
@@ -3740,6 +3764,7 @@
"Jupyter Lab (token only)": "Laboratório Jupyter (apenas por token)",
"JupyterLab": "JupyterLab",
"JupyterLab access token": "Token de acesso do JupyterLab",
"KDE's twin-panel file manager in a browser-based desktop.": "Gerenciador de arquivos de painel duplo do KDE em uma área de trabalho baseada em navegador.",
"KDF:": "KDF:",
"KROMA": "KROMA",
"KVM MSR options added to /etc/modprobe.d/kvm.conf": "Opções KVM MSR adicionadas a /etc/modprobe.d/kvm.conf",
@@ -3787,12 +3812,14 @@
"KiCad - A Cross Platform and Open Source Electronics Design Automation Suite.": "KiCad - Uma plataforma cruzada e Open Source Electronics Design Automation Suite.",
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "O Kimai não tem uma conta predefinida. Aceda ao contentor com: pct enter {main_vmid}",
"Kimai is a professional grade time-tracking application, free and open-source.": "Kimai é um aplicativo de rastreamento de tempo profissional, gratuito e de código aberto.",
"KitchenOwl": "KitchenOwl",
"Kometa is a powerful tool designed to give you complete control over your media libraries. With Kometa, you can take your customization to the next level, with granular control over metadata, collections, overlays, and much more.": "Kometa é uma ferramenta poderosa projetada para lhe dar controle completo sobre suas bibliotecas de mídia. Com o Kometa, você pode levar sua personalização para o próximo nível, com controle granular sobre metadados, coleções, sobreposições e muito mais.",
"Kometa reads its configuration from /config/config.yml and the container only ships /config/config.yml.template. Copy the template to config.yml, fill in the required Plex and TMDb connections, then restart the container.": "Kometa lê a sua configuração a partir de /config/config.yml e o recipiente apenas navios /config/config.yml.template. Copie o modelo para config.yml, preencha o requi vermelho Plex e conexões TMDb, em seguida, reinicie o recipiente.",
"Komga is a media server for your comics, mangas, BDs, magazines and eBooks.": "Komga é um servidor de mídia para seus quadrinhos, mangás, BDs, revistas e eBooks.",
"Kopia Web UI": "Interface web do Kopia",
"Kopia Web UI login": "Acesso à interface web do Kopia",
"Krita is a professional FREE and open source painting program. It is made by artists that want to see affordable art tools for everyone.": "Krita é um programa de pintura livre e livre profissional. É feito por artistas que querem ver ferramentas de arte acessíveis para todos.",
"Krusader Web UI": "UI da Web Krusader",
"LAN access to the kept containers (stack configuration incomplete):": "Acesso LAN aos recipientes mantidos (configuração incompleta):",
"LAN address applied to the application URLs": "Endereço LAN aplicado aos URLs da aplicação",
"LLDAP": "LLDAP",
@@ -3873,9 +3900,11 @@
"Line to paste (single line, including \"command=...\" prefix):": "Linha a ser colada (linha única, incluindo o prefixo \"command=...\"):",
"LinkStack": "LinkStack",
"Linux Installation Options": "Opções de instalação do Linux",
"Linux guest setup and migration notes": "Configuração de convidados Linux e notas de migração",
"Linux/Mac path:": "Caminho Linux/Mac:",
"LinuxServer Jellyfin with optional GPU passthrough": "LinuxServer Jellyfin com passagem opcional de GPU",
"LinuxServer MariaDB requires a user, database and password": "LinuxServer MariaDB requires um usuário, banco de dados e senha",
"LinuxServer Nextcloud with MariaDB and Redis": "Nextcloud da LinuxServer com MariaDB e Redis",
"List Available Disks": "Listar discos disponíveis",
"List IOMMU group mapping": "Listar mapeamento de grupo IOMMU",
"List NVMe devices": "Listar dispositivos NVMe",
@@ -4020,6 +4049,7 @@
"Manage OCI stack": "Gerenciar a pilha OCI",
"Manage PBS encryption keyfile": "Gerenciar arquivo de chave de criptografia PBS",
"Manage Secure Gateway": "Gerenciar Secure Gateway",
"Manage a Z-Wave network from a web dashboard and WebSocket gateway.": "gerencie uma rede Z-Wave a partir de um painel da web e gateway WebSocket.",
"Manage and inspect VM disk images": "Gerenciar e inspecionar imagens de disco de VM",
"Manage custom backup paths": "Gerencie caminhos de backup personalizados",
"Manage custom paths (add / remove your folders)": "Gerencie caminhos personalizados (adicione/remova suas pastas)",
@@ -4029,6 +4059,7 @@
"Manage local backup target": "Gerenciar destino de backup local",
"Manage private image registries.\nSaved credentials let ProxMenux access your private images.": "Gerencie registros de imagens privadas.\nAs credenciais salvas permitem que ProxMenux acesse suas imagens privadas.",
"Manage registry accounts as root on the Proxmox node.": "Gerencie contas de registro como root no nó Proxmox.",
"Manage teams of AI agents from a web dashboard.": "Gerencie equipes de agentes de IA a partir de um painel web.",
"Managed disks must have backup enabled and a valid size": "Os discos gerenciados devem ter backup ativado e um tamanho válido",
"Managed public route include is missing": "Falta o ficheiro de configuração das rotas públicas geridas",
"Managed public route installation failed": "Não foi possível configurar as rotas públicas geridas",
@@ -4134,6 +4165,7 @@
"Monitoring": "Monitoramento",
"Monitoring & Analytics": "Monitorização e análise",
"Most common cause: the archive is corrupted (interrupted write, partial copy, or storage issue).": "Causa mais comum: o arquivo está corrompido (gravação interrompida, cópia parcial ou problema de armazenamento).",
"Motion graphics and compositing in your browser": "Animação gráfica e composição no navegador",
"Mount Added Successfully:": "Montagem adicionada com sucesso:",
"Mount CIFS share:": "Monte o compartilhamento CIFS:",
"Mount Configuration Summary:": "Resumo da configuração de montagem:",
@@ -4293,6 +4325,7 @@
"NVIDIA (CUDA; official GPU image)": "NVIDIA (CUDA; imagem oficial da GPU)",
"NVIDIA (NVDEC/CUDA)": "NVIDIA (NVDEC/CUDA)",
"NVIDIA (NVENC/NVDEC)": "NVIDIA (NVENC/NVDEC)",
"NVIDIA (Selkies rendering and NVENC)": "NVIDIA (renderização Selkies e NVENC)",
"NVIDIA Actions": "Ações NVIDIA",
"NVIDIA CPU hiding already configured": "Ocultação de CPU NVIDIA já configurada",
"NVIDIA Container Toolkit": "NVIDIA Container Toolkit",
@@ -4376,6 +4409,7 @@
"Name or part of the option or of the application": "Nome ou parte da opção ou do aplicativo",
"Name:": "Nome:",
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Contas nomeadas precisam de modo privado. Pare o contêiner, defina público: false in /config/config.js, inicie-o novamente e crie cada usuário com: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>",
"Native Borg is unavailable. Install the native borgbackup package on this host to use Borg backups.": "A versão nativa do Borg não está disponível. Instale o pacote borgbackup nativo neste host para utilizar as cópias de segurança do Borg.",
"Needed:": "Necessário:",
"Needs": "Requer",
"Neither /etc/kernel/cmdline nor /etc/default/grub found.": "Nem /etc/kernel/cmdline nem /etc/default/grub foram encontrados.",
@@ -4434,6 +4468,8 @@
"New Search": "Nova pesquisa",
"New VM:": "Nova VM:",
"New Virtual Machine": "Nova máquina virtual",
"New applications ({count})": "Novas aplicações ({count})",
"New applications since your last visit: {count}": "Novas aplicações desde a sua última visita: {count}",
"New backup job": "Nova tarefa de backup",
"New backups on this host will be unencrypted until a new keyfile is set up.": "Novos backups neste host serão descriptografados até que um novo arquivo-chave seja configurado.",
"New image compatible:": "Nova imagem compatível:",
@@ -4449,6 +4485,7 @@
"Next Step Required": "Próxima etapa obrigatória",
"Next Steps:": "Próximas etapas:",
"Next step: stop that VM first, then run": "Próxima etapa: pare a VM primeiro e depois execute",
"Nextcloud Web UI": "Interface web do Nextcloud",
"Nextcloud configuration cancelled": "Configuração do Nextcloud cancelada",
"Nextcloud gives you access to all your files wherever you are.": "O Nextcloud dá-lhe acesso a todos os seus ficheiros onde quer que esteja.",
"Nextcloud volume size in GB": "Tamanho do volume Nextcloud em GB",
@@ -4623,6 +4660,7 @@
"No duplicate IP addresses": "Nenhum endereço IP duplicado",
"No duplicate repositories found": "Nenhum repositório duplicado encontrado",
"No eligible Controller/NVMe devices remain after SR-IOV filtering. Skipping.": "Nenhum dispositivo Controlador/NVMe qualificado permanece após a filtragem SR-IOV. Pulando.",
"No eligible USB devices found. Hubs, mass storage and network adapters are excluded.": "Não foram encontrados dispositivos USB elegíveis. Os hubs, os dispositivos de armazenamento em massa e os adaptadores de rede estão excluídos.",
"No eligible controllers remain after SR-IOV filtering.": "Nenhum controlador elegível permanece após a filtragem SR-IOV.",
"No encryption key is stored on this host. Choose how to set one up:": "Nenhuma chave de criptografia é armazenada neste host. Escolha como configurar um:",
"No exportable VM disks were found (CD-ROM/cloud-init are excluded).": "Nenhum disco VM exportável foi encontrado (CD-ROM/cloud-init foram excluídos).",
@@ -4707,6 +4745,7 @@
"No self-test log available for": "Nenhum registro de autoteste disponível para",
"No server IP or hostname provided.": "Nenhum IP do servidor ou nome de host fornecido.",
"No share access test succeeded with guest authentication.": "Nenhum teste de acesso de compartilhamento foi bem-sucedido com a autenticação de convidado.",
"No shared devices are available on this server.": "Não há dispositivos partilhados disponíveis neste servidor.",
"No shared media content.": "Sem conteúdo de mídia compartilhado.",
"No shared mount detected. Applying standard local access.": "Nenhuma montagem compartilhada detectada. Aplicando acesso local padrão.",
"No shares configured.": "Nenhum compartilhamento configurado.",
@@ -4896,6 +4935,8 @@
"Open the page of an application in the menu": "Abrir a página de uma aplicação no menu",
"Open the web address and create the first account: the daemon registers by itself and starts the first scan.": "Abra o endereço web e crie a primeira conta: o daemon regista-se sozinho e inicia a primeira análise.",
"Open the web address and create the password of the akadmin user in the first-run setup.": "Abra o endereço da web e crie a senha do usuário akadmin na configuração inicial.",
"Open the web address and follow KitchenOwl’s onboarding to create the first account; no default account is configured.": "Abra o endereço web e siga o onboarding do KitchenOwl para criar a primeira conta;nenhuma conta padrão está configurada.",
"Open the web dashboard and link your Movistar/O2 account using its SMS flow.": "Abra o painel web e vincule sua conta Movistar/O2 com a verificação por SMS.",
"Open-source AI-powered coding assistant": "Assistente de codificação com código aberto",
"Open-source UI for building and debugging multi-agent and RAG applications": "UI de código aberto para a construção e depuração de aplicações multi-agente e RAG",
"Open-source in-memory data store.": "Armazenamento de dados em memória de código aberto.",
@@ -5018,6 +5059,7 @@
"Packages:": "Pacotes:",
"Packaging OVA file...": "Empacotando arquivo OVA...",
"Packing installer archive...": "Empacotando o arquivo do instalador...",
"Page layout and publishing in your browser": "Diagramação e publicação no navegador",
"PairDrop is a sublime alternative to AirDrop that works on all platforms. Send images, documents or text via peer to peer connection to devices in the same local network/Wi-Fi or to paired devices.": "PairDrop é uma alternativa sublime para AirDrop que funciona em todas as plataformas. Envie imagens, documentos ou texto via peer para conexão por pares a dispositivos na mesma rede local/Wi-Fi ou para dispositivos pareados.",
"Paperless configuration cancelled": "Configuração sem papel cancelada",
"Paperless-ngx WebUI": "Paperless-ngx WebUI",
@@ -5036,6 +5078,7 @@
"Pass /dev/video12 to the LXC": "Passe /dev/video12 para o LXC",
"Pass a host device to the LXC": "Passe um dispositivo da máquina para o LXC",
"Pass the UPS to the LXC": "Passe o UPS para o LXC",
"Pass through a Z-Wave USB or serial controller": "passe por um controlador serial ou USB Z-Wave",
"Passing NVIDIA does not enable acceleration inside the application. The host needs NVIDIA Container Toolkit and a compatible image. Continue?": "Passar NVIDIA não habilita a aceleração dentro do aplicativo. O host precisa do NVIDIA Container Toolkit e de uma imagem compatível. Continuar?",
"Passkey-based identity provider for self-hosted apps.": "Fornecedor de identidade baseado em passkeys para aplicações autoalojadas.",
"Passphrase used to unlock the imported keyfile (leave blank if the keyfile is unencrypted / kdf=none):": "Senha usada para desbloquear o arquivo-chave importado (deixe em branco se o arquivo-chave não estiver criptografado / kdf=none):",
@@ -5101,6 +5144,7 @@
"Path of the Compose file": "Localização do ficheiro Compor",
"Path of the oci-compose file": "Caminho do arquivo oci-compose",
"Path removed:": "Caminho removido:",
"Path to the client SSH public key on this server:": "Caminho da chave pública SSH do cliente neste servidor:",
"Path:": "Caminho:",
"Paths applied:": "Caminhos aplicados:",
"Paths included in backup": "Caminhos incluídos no backup",
@@ -5143,6 +5187,8 @@
"Personal finance management application": "Aplicação de gestão de finanças pessoais",
"Personal media server for browsing and playing a local video library, with direct play and optional modules.": "Servidor multimídia pessoal para navegar e reproduzir uma biblioteca local de vídeos, com reprodução direta e módulos opcionais.",
"Photo and video library with optional GPU transcoding and machine learning": "Biblioteca de fotos e vídeos com transcodificação GPU opcional e aprendizado de máquina",
"Photo editing in your browser": "Edição de fotos no navegador",
"Photo library and RAW development in your browser": "Biblioteca de fotos e revelação RAW no navegador",
"PhotoPrism": "PhotoPrism",
"Photofield": "Photofield",
"Phpmyadmin is a free software tool written in PHP, intended to handle the administration of MySQL over the Web. phpMyAdmin supports a wide range of operations on MySQL and MariaDB.": "Phpmyadmin é uma ferramenta de software livre escrita em PHP, destinada a lidar com a administração do MySQL através da Web. phpMyAdmin suporta uma ampla gama de operations no MySQL e MariaDB.",
@@ -5235,6 +5281,7 @@
"Preparing the machine learning container for the new choice...": "Preparando o contêiner de aprendizado de máquina para a nova escolha...",
"Preparing the recreation...": "Preparando a recreação...",
"Preparing the update...": "Preparando a atualização...",
"Presentations and slide decks in your browser": "Apresentações e slides no navegador",
"Preserving logs to /var/log.hdd before unmounting...": "Preservando logs em /var/log.hdd antes de desmontar...",
"Press 'q' to exit": "Pressione 'q' para sair",
"Press Ctrl+C to stop the server and return to menu.": "Pressione Ctrl+C para parar o servidor e retornar ao menu.",
@@ -5340,6 +5387,7 @@
"ProxMenux does not install them. The installation asks how to connect to them.": "ProxMenux não os instala. A instalação pergunta como se conectar a eles.",
"ProxMenux does not validate the contents; any keyfile your PBS accepts is accepted here.": "ProxMenux não valida o conteúdo;qualquer arquivo-chave que seu PBS aceita é aceito aqui.",
"ProxMenux files:": "Arquivos ProxMenux:",
"ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.": "O ProxMenux gera a senha do administrador e mostra-a no fim da instalação. Altere-a após o primeiro login.",
"ProxMenux logo applied": "Logotipo ProxMenux aplicado",
"ProxMenux only acts as a launcher — once the script starts, control leaves ProxMenux.": "ProxMenux atua apenas como um iniciador – assim que o script é iniciado, o controle sai do ProxMenux.",
"ProxMenux saved it locally at:": "ProxMenux salvou localmente em:",
@@ -5395,6 +5443,7 @@
"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",
"Proxy address to reach the API (optional)": "Endereço proxy para acessar a API (opcional)",
"Public HTTPS URL used to open this Authelia portal (for example https://auth.example.com)": "URL HTTPS público usado para abrir este portal Authelia (por exemplo https://auth.example.com)",
"Public UDP port clients connect to": "Clientes públicos de porta UDP se conectam",
"Public UDP port peers connect to": "Os pares públicos de portas UDP se conectam",
"Public URL of phpMyAdmin when it is served behind a reverse proxy": "URL público do phpMyAdmin quando é servido por trás de um proxy reverso",
@@ -5455,6 +5504,7 @@
"Re-running pre-check after repairs...": "Executando novamente a pré-verificação após os reparos...",
"Reachable": "Acessível",
"Read an oci-compose from a file of this host": "Leia um oci-compose de um arquivo deste host",
"Read and edit PDF documents in your browser": "Leitura e edição de documentos PDF no navegador",
"Read its Compose file from a file of this host": "Leia seu arquivo Compor de um arquivo desta máquina",
"Read manga through a self-hosted server and web UI.": "Leia mangás em um servidor self-hosted com interface web.",
"Read the link with pct console CTID on the Proxmox host, or from the Console panel of the container in the Proxmox web interface, then open the https://playit.gg/claim/ address it shows in a browser and sign in to playit.gg. Ctrl+a q leaves pct console.": "Leia o link com o PCT console CTID no host Proxmox, ou a partir do painel Console do recipiente na interface web Proxmox, em seguida, abra o https://playit.gg/claim/ endereço que ele mostra em um navegador e entre para playit.gg. Ctrl+a q deixa o console pct.",
@@ -5558,8 +5608,10 @@
"Recreation prepared": "Recreação preparada",
"Recursive DNS resolver.": "Resolvedor DNS recursivo.",
"Recursive and authoritative DNS server.": "Servidor DNS recursivo e autoritativo.",
"Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.": "O bloqueio de ficheiros com Redis é configurado automaticamente. Os ficheiros de configuração existentes do Nextcloud são preservados.",
"Redmine": "Redmine",
"Refresh APT index and verify repositories:": "Atualize o índice APT e verifique os repositórios:",
"Refresh catalog": "Atualizar catálogo",
"Refresh the configured APT repositories and review the PBS package upgrade? Repository files will be preserved.": "Atualizar os índices dos repositórios APT configurados e rever a atualização de pacotes PBS? Os ficheiros dos repositórios serão preservados.",
"Refresh the index from the image sources": "Atualizar o índice a partir das origens de imagens",
"Refresh token of the connector, from the Twingate admin console": "Token de atualização do conector, no console administrativo Twingate",
@@ -5567,6 +5619,7 @@
"Refresh your browser to see changes (server restart may be required)": "Atualize seu navegador para ver as alterações (pode ser necessário reiniciar o servidor)",
"Refreshing apt cache...": "Atualizando o cache do apt...",
"Refreshing the NVIDIA runtime...": "Atualizando o tempo de execução NVIDIA...",
"Refreshing the application catalog...": "A atualizar o catálogo de aplicações...",
"Refusing an unexpected rootfs path:": "Recusando um caminho inesperado do rootfs:",
"Regenerate the catalog templates": "Regenerar os modelos do catálogo",
"Regenerate the template of one application": "Regenerar o modelo de uma aplicação",
@@ -5639,6 +5692,7 @@
"Remove Proxmox NFS storage:": "Remova o armazenamento Proxmox NFS:",
"Remove Proxmox iSCSI storage:": "Remova o armazenamento iSCSI Proxmox:",
"Remove Secure Gateway? State will be preserved.": "Remover Secure Gateway? O estado será preservado.",
"Remove a remote USB connection": "Remover uma ligação USB remota",
"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": "Remover todas as versões DKMS de gasket registadas",
@@ -5659,6 +5713,7 @@
"Remove the lock left on a container by an interrupted task": "Remover o bloqueio deixado num contentor por uma tarefa interrompida",
"Remove the saved credentials for {registry}?\nRunning apps will keep working.": "Remover as credenciais salvas para {registry}?\nOs aplicativos em execução continuarão funcionando.",
"Remove the unprivileged flag from configuration:": "Remova o sinalizador sem privilégios da configuração:",
"Remove this connection and detach its USB device?": "Remover esta ligação e desligar o respetivo dispositivo USB?",
"Remove unused packages and their config": "Remova pacotes não utilizados e suas configurações",
"Remove: delete the application and its containers": "Remover: apagar o aplicativo e seus recipientes",
"Removed": "Removido",
@@ -5881,9 +5936,11 @@
"Run mode: Unattended": "Modo de execução: Autônomo",
"Run now": "Executar agora",
"Run security audit now": "Execute a auditoria de segurança agora",
"Run the client inside the Linux VM that needs the USB device. Install usbip, openssh-client and kmod, then copy usbip_manager.py to the same path as on the server. Configure key authentication and verify the server host key before adding a connection. The client uses the guest kernel and can reconnect after migration while the physical USB device stays on the server. Unprivileged LXC and Home Assistant OS need their own kernel/device or add-on setup. A physical device supports one attached client at a time.": "Execute o cliente na VM Linux que precisa do dispositivo USB. Instale usbip, openssh-client e kmod e copie usbip_manager.py para o mesmo caminho usado no servidor. Configure a autenticação por chave e verifique a chave de anfitrião do servidor antes de adicionar uma ligação. O cliente usa o kernel do convidado e pode voltar a ligar-se após uma migração enquanto o dispositivo USB físico permanece no servidor. Os LXC sem privilégios e o Home Assistant OS precisam de uma configuração própria do kernel, dos dispositivos ou dos complementos. Um dispositivo físico só pode estar ligado a um cliente de cada vez.",
"Run the following inside the VM:": "Execute o seguinte dentro da VM:",
"Run the release-channel switch from an SSH session or the Proxmox host console with:": "execute a opção de canal de lançamento a partir de uma sessão SSH ou do console do host Proxmox com:",
"Run the update from an SSH session or the Proxmox host console with:": "execute a atualização a partir de uma sessão SSH ou do console do host Proxmox com:",
"Run this menu as root.": "Execute este menu como root.",
"Run this operation as root.": "Execute esta operação como root.",
"Run upgrade checklist script:": "Execute o script da lista de verificação de atualização:",
"Running": "Correndo",
@@ -6108,6 +6165,7 @@
"Select a new language for the menu:": "Selecione um novo idioma para o menu:",
"Select a post-installation script:": "Selecione um script pós-instalação:",
"Select a pre-configured Linux VM script to execute:": "Selecione um script de VM Linux pré-configurado para executar:",
"Select a saved USB/IP device:": "Selecione um dispositivo USB/IP guardado:",
"Select a script or action:": "Selecione um script ou ação:",
"Select a share to delete:": "Selecione um compartilhamento para excluir:",
"Select a specific Coral or USB node, not the whole /dev": "Selecione um nó Coral ou USB específico, não o /dev inteiro",
@@ -6185,6 +6243,7 @@
"Select the Linux distribution to install:": "Selecione a distribuição Linux para instalar:",
"Select the NAS system to install:": "Selecione o sistema NAS para instalar:",
"Select the NVIDIA driver version to install:": "Selecione a versão do driver NVIDIA para instalar:",
"Select the USB device to share:": "Selecione o dispositivo USB a partilhar:",
"Select the VM to add the GPU to:": "Selecione a VM à qual adicionar a GPU:",
"Select the VM to which you want to add disks:": "Selecione a VM à qual você deseja adicionar discos:",
"Select the VM where you want to import the disk image:": "Selecione a VM para a qual deseja importar a imagem de disco:",
@@ -6209,6 +6268,7 @@
"Select the parent job to attach to:": "Selecione o trabalho pai ao qual deseja anexar:",
"Select the paths to restore (one per backup entry):": "Selecione os caminhos para restaurar (um por entrada de backup):",
"Select the privileged LXC container to convert:": "Selecione o contêiner LXC privilegiado para converter:",
"Select the remote USB device:": "Selecione o dispositivo USB remoto:",
"Select the storage that will receive the backups:": "Selecione o armazenamento que receberá os backups:",
"Select the storage volume for disk import:": "Selecione o volume de armazenamento para importação de disco:",
"Select the sync interval (in hours):": "Selecione o intervalo de sincronização (em horas):",
@@ -6258,6 +6318,7 @@
"Self-hosted file sync and sharing.": "Sincronização e compartilhamento de arquivos self-hosted.",
"Self-hosted file toolkit for images, video, audio, PDFs, and files": "Kit de ferramentas de arquivo auto hospedado para imagens, vídeo, áudio, PDFs e arquivos",
"Self-hosted forms and workflows.": "Formulários e fluxos de trabalho autoalojados.",
"Self-hosted grocery list and recipe manager": "lista de compras auto-hospedada e gerenciador de receitas",
"Self-hosted household plant-care tracker with reminders, photos, and multiple user accounts.": "Gerenciador auto-hospedado de cuidados com plantas domésticas, com lembretes, fotos e várias contas de usuário.",
"Self-hosted image-hosting service with authenticated uploads, image processing, public links, and local storage.": "Serviço auto-hospedado de hospedagem de imagens, com uploads autenticados, processamento de imagens, links públicos e armazenamento local.",
"Self-hosted internet archiving solution": "Solução de arquivamento de internet self-hosted",
@@ -6294,6 +6355,7 @@
"Server IDs to test against, separated by commas (optional)": "IDs de servidor para testar, separados por vírgulas (opcional)",
"Server IP/hostname is correct": "O IP/nome do host do servidor está correto",
"Server IP:": "IP do servidor:",
"Server SSH port:": "Porta SSH do servidor:",
"Server is accessible:": "O servidor está acessível:",
"Server is online": "O servidor está on-line",
"Server is running": "O servidor está em execução",
@@ -6355,6 +6417,7 @@
"Share Access Error": "Erro de acesso ao compartilhamento",
"Share Name": "Compartilhar nome",
"Share Options": "Opções de compartilhamento",
"Share a local USB device": "Partilhar um dispositivo USB local",
"Share added successfully.": "Compartilhamento adicionado com sucesso.",
"Share deleted and Samba service restarted.": "Compartilhamento excluído e serviço Samba reiniciado.",
"Share exists:": "Existe compartilhamento:",
@@ -6362,6 +6425,7 @@
"Share name:": "Nome do compartilhamento:",
"Share not found on server:": "Compartilhamento não encontrado no servidor:",
"Share path:": "Compartilhar caminho:",
"Share selected USB devices through SSH, or connect this Linux machine to a USB/IP server.": "Partilhe os dispositivos USB selecionados através de SSH ou ligue esta máquina Linux a um servidor USB/IP.",
"Share updated successfully.": "Compartilhamento atualizado com sucesso.",
"Share:": "Compartilhar:",
"ShareCoveX panel": "Painel ShareCoveX",
@@ -6452,6 +6516,7 @@
"Simple and easy to use DDNS": "Simples e fácil de usar DDNS",
"Simple self-hosted file sharing.": "Serviço simples e autoalojado para partilha de ficheiros.",
"Single GPU Warning": "Aviso de GPU única",
"Single sign-on and multi-factor authentication": "login único e autenticação multifator",
"Single target found — selected automatically:": "Único alvo encontrado — selecionado automaticamente:",
"Single-node log storage and query UI.": "Armazenamento de logs para um único nó com interface de consulta.",
"Single-node observability database for metrics, logs and traces.": "Banco de dados de observabilidade de nó único para métricas, logs e traces.",
@@ -6520,7 +6585,9 @@
"Specific subnet (enter manually)": "Sub-rede específica (inserir manualmente)",
"Speedtest Tracker web interface": "Interface Web Speedtest Tracker",
"Speedtest-tracker is a self-hosted internet performance tracking application that runs speedtest checks against Ookla's Speedtest service.": "Speedtest-tracker é um aplicativo de rastreamento de desempenho da internet que executa verificações de velocidade contra o serviço Speedtest da Ookla.",
"Spoolman web interface": "interface web Spoolman",
"Spotube is an open source, cross-platform Spotify client compatible across multiple platforms utilizing Spotify's data API and YouTube, Piped.video or JioSaavn as an audio source, eliminating the need for Spotify Premium": "Spotube é um cliente Spotify de código aberto, multi-plataforma compatível em várias plataformas utilizando a API de dados do Spotify e YouTube, Piped. vídeo ou JioSaavn como uma fonte de áudio, eliminando a necessidade de Spotify Premium",
"Spreadsheets in your browser": "Planilhas no navegador",
"Sshwifty": "Sshwifty",
"Sshwifty web access (password only)": "Acesso web ao Sshwifty (somente com senha)",
"Stable (main branch)": "Estável (ramo principal)",
@@ -6627,6 +6694,8 @@
"Still has issues": "Ainda tem problemas",
"Stop - shuts the guest down during backup": "Parar - desliga o convidado durante o backup",
"Stop it first and run this option again.": "Pare primeiro e execute esta opção novamente.",
"Stop sharing a USB device": "Parar a partilha de um dispositivo USB",
"Stop sharing this device? An attached remote client will disconnect.": "Parar a partilha deste dispositivo? O cliente remoto ligado será desligado.",
"Stop that VM, then choose:": "Pare esse VM e escolha:",
"Stop the CT, unmount the disk on the HOST, and remount with:": "Pare o CT, desmonte o disco no HOST e remonte com:",
"Stop the VM/CT before formatting this disk.": "Pare a VM/CT antes de formatar este disco.",
@@ -6982,6 +7051,7 @@
"The container could not be removed automatically:": "O recipiente não pôde ser removido automaticamente:",
"The container could not be started:": "Não foi possível iniciar o recipiente:",
"The container creation does not match the prepared instance": "A criação do recipiente não corresponde à instância preparada",
"The container device settings changed since the last recorded operation": "As definições do dispositivo do contentor mudaram desde a última operação registada",
"The container devices do not match the saved record": "Os dispositivos do contentor não correspondem ao registo gravado",
"The container did not stop to update its persistent configuration:": "O recipiente não parou para atualizar sua configuração persistente:",
"The container did not stop; its disks are not touched": "O recipiente não parou; os seus discos não são tocados",
@@ -7263,6 +7333,7 @@
"The record no longer belongs to this operation": "O registro já não pertence a esta operation",
"The record of a member was replaced; the assembly is not resumed": "O registro de um membro foi substituído; a assembléia não é retomada",
"The record or diagnosis could not be completed; no update was run.": "O registro ou diagnóstico não pôde ser concluído; nenhuma atualização foi realizada.",
"The recorded container device GID does not match its configuration": "O GID registado do dispositivo do contentor não corresponde à configuração",
"The recovery did not complete. Review the log and choose \"Recover\" again for this container in the OCI management menu.": "A recuperação não terminou. Reveja o log e escolha \"Recover\" novamente para este recipiente no menu de gerenciamento OCI.",
"The recovery did not complete. Review the log and choose \"{choice}\" again for this container in the OCI management menu.": "A recuperação não foi concluída. Revise o log e escolha \"{choice}\" novamente para este contêiner no menu de gerenciamento OCI.",
"The registry authentication file is invalid; it was not changed.": "O arquivo de autenticação do registro é inválido;não foi alterado.",
@@ -7330,6 +7401,7 @@
"The selected Intel GPU has non-FLR reset support and unknown subtype": "A GPU Intel selecionada tem suporte para redefinição não FLR e subtipo desconhecido",
"The selected Intel GPU is currently in power state D3cold": "A GPU Intel selecionada está atualmente no estado de energia D3cold",
"The selected Intel render device does not exist:": "O dispositivo de renderização Intel selecionado não existe:",
"The selected USB device will become unavailable to local applications and guests. Only one remote client can use it at a time. Share this device?": "O dispositivo USB selecionado ficará indisponível para aplicações e convidados locais. Só um cliente remoto o pode usar de cada vez. Partilhar este dispositivo?",
"The selected VM": "A VM selecionada",
"The selected VM is running.": "A VM selecionada está em execução.",
"The selected base folder does not exist and could not be created:": "A pasta base selecionada não existe e não pôde ser criada:",
@@ -7417,6 +7489,7 @@
"Then bind-mount to container": "Em seguida, ligue a montagem ao contêiner",
"Then change the VM display to none (vga: none) when the guest is stable.": "Em seguida, altere a exibição da VM para nenhum (vga: nenhum) quando o convidado estiver estável.",
"Then change the VM display to none (vga: none) when the system is stable.": "Em seguida, altere a exibição da VM para nenhum (vga: nenhum) quando o sistema estiver estável.",
"Then restart the container so the new model appears in the list.": "Depois reinicie o contêiner para que o novo modelo apareça na lista.",
"Then run this option again:": "Em seguida, execute esta opção novamente:",
"Then update /etc/fstab on the host with the same options.": "Em seguida, atualize /etc/fstab no host com as mesmas opções.",
"There are extra disks or bind mounts outside the journal; the rootfs is not replaced": "Existem discos extras ou montagens de ligação fora do diário; o rootfs não é substituído",
@@ -7464,6 +7537,7 @@
"This container does not have apt-get. NFS client installation only supports Debian/Ubuntu containers.": "Este contêiner não possui o apt-get. A instalação do cliente NFS suporta apenas contêineres Debian/Ubuntu.",
"This container does not have apt-get. Samba client installation only supports Debian/Ubuntu containers.": "Este contêiner não possui o apt-get. A instalação do cliente Samba suporta apenas contêineres 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 contêiner não tem GPU configurada. Coral TPU funciona melhor com decodificação de vídeo de hardware (Quick Sync, VA-API, NVENC) para aplicativos como Frigate.",
"This container is managed by high availability. Remove ct:{vmid} from HA (Datacenter → HA, or ha-manager remove ct:{vmid}), repeat the operation and add it back to HA with the same settings.": "Este contentor é gerido pela alta disponibilidade. Remova ct:{vmid} da HA (Datacenter → HA, ou ha-manager remove ct:{vmid}), repita a operação e volte a adicioná-lo à HA com as mesmas definições.",
"This container is not a member of a multi-container application": "Este contêiner não é membro de um aplicativo de vários contêineres",
"This container is not a registered OCI instance.": "Este contêiner não é uma instância OCI registrada.",
"This container was restored or came back from another host after its record on this host was written. Open this menu again to recover it; nothing was changed.": "Este contêiner foi restaurado ou voltou de outro host depois que seu registro neste host foi gravado. Abra este menu novamente para recuperá-lo; nada foi alterado.",
@@ -7582,6 +7656,7 @@
"Tip: You can install the QEMU Guest Agent inside the VM with:": "Dica: você pode instalar o agente convidado QEMU dentro da VM com:",
"Tip: zfs set acltype=posixacl xattr=sa <pool>/<dataset> enables full ACL support.": "Dica: zfs set acltype=posixacl xattr=sa <pool>/<dataset> permite suporte completo a ACL.",
"Tmpfs size in MiB for": "Tamanho do Tmpfs em MiB para",
"To add a model, open the console of the container in Proxmox and download it into /models, for example:": "Para adicionar um modelo, abra o console do contêiner no Proxmox e baixe-o em /models, por exemplo:",
"To allow LXC write access, change the NFS export on the server to include:": "Para permitir o acesso de gravação LXC, altere a exportação NFS no servidor para incluir:",
"To apply it to the current shell now, run:": "Para aplicá-lo agora à sessão shell atual, execute:",
"To assign VFs to VMs or LXCs, edit the configuration manually via the Proxmox web interface. The Physical Function will remain bound to the native driver.": "Para atribuir VFs a VMs ou LXCs, edite a configuração manualmente por meio da interface web do Proxmox. A Função Física permanecerá vinculada ao driver nativo.",
@@ -7621,6 +7696,7 @@
"Total routes": "Rotas totais",
"Total size:": "Tamanho total:",
"Toxiproxy": "Toxiproxy",
"Track 3D printer filament spools and usage.": "rastreie os carretéis e o uso do filamento da impressora 3D.",
"Track movies, television, anime and games you want to enjoy.": "Acompanhe os filmes, séries, anime e videojogos que quer ver ou jogar.",
"Track subscriptions and recurring expenses.": "Acompanhe subscrições e despesas recorrentes.",
"Track your music listening history on your own server.": "Acompanhe seu histórico de músicas ouvidas no seu próprio servidor.",
@@ -7665,6 +7741,9 @@
"USB drives mounted now:": "unidades USB montadas agora:",
"USB libedgetpu1": "USB libedgetpu1",
"USB or serial device node": "nó de dispositivo USB ou serial",
"USB/IP configuration updated. Open status to check the connection.": "Configuração USB/IP atualizada. Abra o estado para verificar a ligação.",
"USB/IP over SSH": "USB/IP através de SSH",
"USB/IP server IP address or DNS hostname:": "Endereço IP ou nome de anfitrião DNS do servidor USB/IP:",
"UUP Dump script not found.": "Script de despejo UUP não encontrado.",
"UUp Dump ISO creator Custom": "Criador UUp Dump ISO personalizado",
"Ubooquity is a free, lightweight and easy-to-use home server for your comics and ebooks. Use it to access your files from anywhere, with a tablet, an e-reader, a phone or a computer.": "Ubooquity é um servidor doméstico gratuito, leve e fácil de usar para seus quadrinhos e ebooks. Use-o para acessar seus arquivos de qualquer lugar, com um tablet, um e-leitor, um telefone ou um computador.",
@@ -7821,6 +7900,7 @@
"Untrusted or modified NVIDIA hook": "Gancho NVIDIA não confiável ou modificado",
"Unused image removed from the cache:": "Imagem não usada removida da cache:",
"Unused images removed from the cache:": "Imagens não usadas removidas da cache:",
"Unused local loopback TCP port for this device:": "Porta TCP local de loopback livre para este dispositivo:",
"Update": "Atualizar",
"Update Available": "atualização disponível",
"Update Ceph repository (Only if using Ceph):": "Atualize o repositório do Ceph (somente se estiver usando o Ceph):",
@@ -7855,6 +7935,7 @@
"Update the whole stack?": "Atualizar toda a pilha?",
"Update, modify or recreate one installed OCI instance": "Atualizar, modificar ou recriar uma instância OCI instalada",
"Updated": "Atualizado",
"Updated recipes since your last visit: {count}": "Receitas atualizadas desde a sua última visita: {count}",
"Updated sharedfiles group to GID: 101000": "Grupo de arquivos compartilhados atualizado para GID: 101000",
"Updated stack checked": "Stack atualizado verificado",
"Updated:": "Actualizado:",
@@ -7918,6 +7999,7 @@
"Use a privileged LXC for NFS server/client workflows.": "Use um LXC privilegiado para fluxos de trabalho de servidor/cliente NFS.",
"Use a privileged LXC for Samba client/server workflows.": "Use um LXC privilegiado para fluxos de trabalho cliente/servidor Samba.",
"Use a registry hostname, for example ghcr.io or registry.example.com:5000.": "Use um nome de host de registro, por exemplo ghcr.io ou registry.example.com:5000.",
"Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time.": "Use um proxy inverso HTTPS com um certificado de confiança. Atualize o Nextcloud para a versão principal seguinte, sem saltar nenhuma.",
"Use an existing SSH private key file on this host": "Use um arquivo de chave privada SSH existente neste host",
"Use an existing keyfile": "Use um arquivo-chave existente",
"Use an image reference, for example ghcr.io/owner/app:latest.": "Use uma referência de imagem, por exemplo ghcr.io/owner/app:latest.",
@@ -7931,6 +8013,7 @@
"Use existing filesystem": "Use o sistema de arquivos existente",
"Use existing: mount without formatting": "Use existente: monte sem formatação",
"Use images only if the directory is on suitable storage.": "Use imagens somente se o diretório estiver em um armazenamento adequado.",
"Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.": "Use armazenamento gerido para /config e MariaDB. Para /data pode escolher um diretório do host/NAS, que precisa de uma cópia de segurança separada.",
"Use mp1/mp2/... for extra mount points.": "Use mp1/mp2/... para pontos de montagem extras.",
"Use only when unprivileged containers cannot meet your needs": "Use somente quando contêineres sem privilégios não atenderem às suas necessidades",
"Use option 1 to add a local disk (as Proxmox storage and/or as a host mount).": "Use a opção 1 para adicionar um disco local (como armazenamento Proxmox e/ou como montagem de host).",
@@ -8060,6 +8143,7 @@
"Variables": "Variáveis",
"Variables the installation asks for:": "Variáveis que a instalação solicita:",
"Vaultwarden Web Vault": "Vaultwarden Web Vault",
"Vector illustration in your browser": "Ilustração vetorial no navegador",
"Vector search engine with a built-in dashboard.": "Mecanismo de busca vetorial com painel integrado.",
"Verbose pool status": "Status detalhado do pool",
"Verification": "Verificação",
@@ -8090,6 +8174,7 @@
"Versions shown belong to maintained NVIDIA branches that list your GPU PCI ID and are new enough to build against the running kernel. DKMS compilation is the final validation. The recommended version keeps the current branch, or uses the NVIDIA Production Branch on a fresh install.": "As versões mostradas pertencem a ramificações NVIDIA mantidas que listam seu ID PCI da GPU e são novas o suficiente para serem construídas no kernel em execução. A compilação DKMS é a validação final. A versão recomendada mantém a ramificação atual ou usa a ramificação de produção NVIDIA em uma nova instalação.",
"VictoriaLogs": "VictoriaLogs",
"Video acceleration and object detection are independent choices; the installer does not write camera or detector YAML.": "Aceleração de vídeo e detecção de objetos são escolhas independentes; o instalador não grava câmera ou detector YAML.",
"Video editing in your browser": "Edição de vídeo no navegador",
"Video transcoding acceleration": "Aceleração da transcodificação de vídeo",
"Video transcoding profile not implemented:": "Perfil de transcodificação de vídeo não implementado:",
"View CIFS Mounts (pvesm + fstab)": "Ver montagens CIFS (pvesm + fstab)",
@@ -8099,6 +8184,7 @@
"View Disk Storages": "Ver armazenamentos em disco",
"View Mount Points": "Ver pontos de montagem",
"View NFS Mounts (pvesm + fstab)": "Ver montagens NFS (pvesm + fstab)",
"View USB/IP status": "Ver estado USB/IP",
"View backup metadata": "Ver metadados de backup",
"View current paths": "Ver caminhos atuais",
"View existing folders in /mnt": "Veja as pastas existentes em /mnt",
@@ -8199,12 +8285,17 @@
"Web access": "Acesso à Internet",
"Web address of the AdGuard Home that receives the settings (e.g. http://192.168.1.3)": "Endereço Web do AdGuard Home que recebe as definições (por exemplo, http://192.168.1.3)",
"Web address of the main AdGuard Home, whose settings are copied (e.g. http://192.168.1.2)": "Endereço Web do AdGuard Home principal, cujas configurações são copiadas (por exemplo, http://192.168.1.2)",
"Web dashboard": "Painel web",
"Web dashboard and WebDAV": "Painel web e WebDAV",
"Web interface": "Interface da Web",
"Web interface for Borg Backup repositories and jobs.": "Interface web para gerenciar repositórios e tarefas do Borg Backup.",
"Web interface for managing 3D printers.": "Interface web para gerenciar impressoras 3D.",
"Web interface to manage devices running Tasmota firmware.": "Interface Web para gerenciar dispositivos rodando firmware Tasmota.",
"Web reverse proxy with an administration interface.": "Proxy reverso web com interface de administração.",
"WebCord can be summarized as a pack of security and privacy hardenings, Discord features reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, internal pages and wrapped https://discord.com page, designed to conform with ToS as much as it is possible (or hide the changes that might violate it from Discord's eyes).": "WebCord pode ser resumido como um pacote de endurecimentos de segurança e privacidade, recursos de discórdia reimplementações, Electron / Chromium / Erros de discórdia workarounds, stylesheets, páginas internas e página envolto https://discord.com, projetado para se conformar com ToS tanto quanto possível (ou ocultar as alterações que podem violá-lo dos olhos da Discord).",
"WebDAV": "WebDAV",
"WebDAV and dashboard password (leave empty to generate)": "Senha do WebDAV e do painel (vazio = gerada)",
"WebDAV is available on container port 8080. Account linking is required before cloud file operations.": "O WebDAV está disponível na porta 8080 do contêiner. É preciso vincular a conta antes de operar com os arquivos da nuvem.",
"Webgrabplus is a multi-site incremental xmltv epg grabber. It collects tv-program guide data from selected tvguide sites for your favourite channels.": "Webgrabplus é um multi-site incremental xmltv epg grabber. Ele coleta dados de guias de tv-programa de sites selecionados para seus canais favoritos.",
"Webservers & Proxies": "Servidores web e proxies",
"Website": "Site",
@@ -8262,6 +8353,7 @@
"Without a usable reset path, passthrough reliability is poor and VM": "Sem um caminho de redefinição utilizável, a confiabilidade da passagem é baixa e a VM",
"Wizard cancelled": "Assistente cancelado",
"Wolfenstein: Blade of Agony is a story-driven WWII shooter inspired by Wolfenstein and Doom.": "Wolfenstein: Blade of Agony é um atirador inspirado em Wolfenstein e Doom.",
"Word processing in your browser": "Processamento de texto no navegador",
"Workflow automation tool": "Ferramenta de automação de fluxo de trabalho",
"Working directory:": "Diretório de trabalho:",
"Works with LVM, ZFS, and BTRFS storage types": "Funciona com tipos de armazenamento LVM, ZFS e BTRFS",
@@ -8312,6 +8404,8 @@
"Your machine learning Env work with Jupyter Lab": "O seu Env de aprendizagem de máquina trabalha com o Jupyter Lab",
"Your next YouTube media manager": "Seu próximo gerenciador de mídia do YouTube",
"Your_spotify is a self-hosted application that tracks what you listen and offers you a dashboard to explore statistics about it! It's composed of a web server which polls the Spotify API every now and then and a web application on which you can explore your statistics.": "Your_spotify é uma aplicação auto-anfitriã que rastreia o que você ouve e oferece um painel para explorar estatísticas sobre isso! É composto por um servidor web que pesquisa a API do Spotify de vez em quando e uma aplicação web na qual você pode explorar suas estatísticas.",
"Z-Wave JS UI": "Z-Wave JS UI",
"Z-Wave JS UI admin login": "login de administrador Z-Wave JS UI",
"ZFS ARC config removed (kernel defaults will apply on reboot)": "Configuração do ZFS ARC removida (os padrões do kernel serão aplicados na reinicialização)",
"ZFS ARC maximum configured:": "máximo do ZFS ARC configurado:",
"ZFS ARC optimization completed": "Otimização ZFS ARC concluída",
@@ -8425,6 +8519,7 @@
"could not be compiled for kernel": "não foi possível compilar para o kernel",
"could not validate NVIDIA; exit code": "não foi possível validar o NVIDIA; código de saída",
"cpuunits must be between 8 and 10000": "cpuunidades devem estar entre 8 e 10000",
"curl -L -o /models/gemma-3-1b-it-Q4_K_M.gguf https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf": "curl -L -o /models/gemma-3-1b-it-Q4_K_M.gguf https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf",
"custom": "personalizado",
"custom dependency commands are not yet supported": "comandos de dependência personalizados ainda não são suportados",
"custom path(s) saved.": "caminhos personalizados salvos.",
@@ -8631,6 +8726,7 @@
"kexec-tools is not installed or already removed.": "kexec-tools não está instalado ou já foi removido.",
"layers": "camadas",
"legacy .link file(s) to the ProxMenux-managed format": "arquivo(s) .link herdado(s) para o formato gerenciado pelo ProxMenux",
"llama.cpp shows every GGUF model saved in /models in its web UI and loads the one you choose.": "O llama.cpp mostra na sua interface web todos os modelos GGUF salvos em /models e carrega o que você escolher.",
"log2ram completely removed from system": "log2ram completamente removido do sistema",
"main container of the application": "contentor principal da aplicação",
"make cloned mount tree read-only": "tornar só de leitura a árvore de montagem clonada",
+96
View File
@@ -184,6 +184,7 @@
"A tunneling daemon by Cloudflare that safely exposes your web servers into the internet.": "Tunelový démon Cloudflare, ktorý bezpečne vystavuje vaše webové servery na internet.",
"A unified email and collaboration server.": "Jednotný server na e-mail a spoluprácu.",
"A unified platform for logs, metrics and traces.": "Jednotná platforma pre logy, metriky a trasovanie.",
"A validating, recursive DNS resolver for your private network.": "Validujúci rekurzívny DNS resolver pre vašu súkromnú sieť.",
"A versatile file conversion tool that supports multiple formats.": "Univerzálny nástroj na konverziu súborov, ktorý podporuje viacero formátov.",
"A visual tool for exploring and documenting database schemas.": "Vizuálny nástroj na skúmanie a dokumentovanie schém databáz.",
"A web GUI client of Project V which supports VMess, VLESS, SS, SSR, Trojan, Tuic and Juicity protocols": "Webový GUI klient projektu V, ktorý podporuje protokoly VMess, VLESS, SS, SSR, Trojan, Tuic a Juicity",
@@ -245,6 +246,7 @@
"Aborted": "Zrušené",
"About to restore": "Chystá sa obnova",
"Absolute directory path to use as backup target:": "Absolútna cesta k priečinku, ktorý sa má použiť ako cieľ záloh:",
"Absolute path of the client SSH private key:": "Absolútna cesta k súkromnému SSH kľúču klienta:",
"Absolute path to a file or directory you want backed up:": "Absolútna cesta k súboru alebo priečinku, ktorý chcete zálohovať:",
"Acceleration": "Zrýchlenie",
"Acceleration configuration cancelled": "Konfigurácia zrýchlenia zrušená",
@@ -256,6 +258,7 @@
"Acceleration for llama.cpp": "Zrýchlenie pre llama.cpp",
"Accept routes from other nodes?": "Prijímať trasy z iných uzlov?",
"Accept this host monitoring profile?": "Prijať tento profil monitorovania hostiteľa?",
"Access Movistar and O2 Cloud from WebDAV clients and backup tools.": "Prístup ku cloudu Movistar a O2 z klientov WebDAV a nástrojov na zálohovanie.",
"Access Scope:": "Rozsah prístupu:",
"Access bridge": "Sieťový most (bridge)",
"Access bridge for Immich": "Sieťový most (bridge) pre Immich",
@@ -410,6 +413,7 @@
"After the reboot, you will only be able to access the Proxmox host via:": "Po reštarte sa k Proxmox hostovi dostanete iba cez:",
"After this LXC → VM switch, reboot the host so the new binding state is applied cleanly.": "Po tomto prepnutí LXC → VM reštartujte host, aby sa nové naviazanie použilo čisto.",
"Agentless monitoring and observability platform.": "Platforma na monitorovanie a observabilitu bez klientskych agentov.",
"AirDC++ administrator": "Správca AirDC++",
"Airsonic Advanced web interface": "Webové rozhranie Airsonic Advanced",
"Airsonic-advanced is a free, web-based media streamer, providing ubiquitious access to your music. Use it to share your music with friends, or to listen to your own music while at work. You can stream to multiple players simultaneously, for instance to one player in your kitchen and another in your living room.": "Airsonic-advanced je bezplatný webový server na streamovanie hudby. Umožňuje zdieľať hudbu s priateľmi alebo počúvať vlastnú zbierku aj v práci. Podporuje súčasné prehrávanie na viacerých zariadeniach, napríklad v kuchyni a obývačke.",
"Aliases added to .bashrc": "Aliasy boli pridané do .bashrc",
@@ -598,11 +602,15 @@
"Attention: Removing the subscription banner may cause issues in the web interface after a future update.": "Upozornenie: odstránenie hlásenia o predplatnom môže po budúcej aktualizácii spôsobiť problém vo webovom rozhraní.",
"Audacity is an easy-to-use, multi-track audio editor and recorder. Developed by a group of volunteers as open source.": "Audacity je jednoduchý viacstopový zvukový editor a rekordér, ktorý dobrovoľníci vyvíjajú ako softvér s otvoreným zdrojovým kódom.",
"Audio device directory": "Adresár zvukových zariadení",
"Audio recording and mixing in your browser": "Nahrávanie a mixovanie zvuku v prehliadači",
"Audiobookshelf is a self-hosted audiobook and podcast server.": "Audiobookshelf je server na audioknihy a podcasty, ktorý prevádzkujete sami.",
"Audit completed. Press Enter to continue...": "Audit dokončený. Pokračujte stlačením Enter...",
"Audit socket disabled or not required": "Zásuvka auditu je zakázaná alebo sa nevyžaduje",
"Auth key is required.": "Auth key je povinný.",
"Auth:": "Prihlásenie:",
"Authelia Web UI": "Webové rozhranie Authelia",
"Authelia administrator": "Správca Authelia",
"Authelia session cookie domain for this portal (for example example.com)": "Doména súboru cookie relácie Authelia pre tento portál (napríklad example.com)",
"Authentication": "Prihlásenie",
"Authentication & Security": "Overovanie a zabezpečenie",
"Authentication Error": "Chyba prihlásenia",
@@ -612,6 +620,8 @@
"Authentication:": "Prihlásenie:",
"Authorization failed": "Autorizácia zlyhala",
"Authorization successful": "Autorizácia úspešná",
"Authorize a client SSH public key": "Povoliť verejný SSH kľúč klienta",
"Authorize a dedicated client public key on the server first. The restricted USB/IP account cannot run a shell or forward other sockets. Verify the server host key before connecting; unknown keys are rejected.": "Najprv na serveri povoľte samostatný verejný kľúč klienta. Obmedzený účet USB/IP nemôže spustiť shell ani presmerovať iné sockety. Pred pripojením overte hostiteľský kľúč servera; neznáme kľúče sa odmietnu.",
"Authorize this key on the server": "Autorizovať tento kľúč na serveri",
"Authorize via 'pct exec' (Borg server is an LXC on a PVE host I can SSH into)": "Autorizovať cez 'pct exec' (Borg server je LXC na PVE hostovi, kam sa viem pripojiť cez SSH)",
"Authorized": "Autorizované",
@@ -642,6 +652,7 @@
"Available PVE Version": "Dostupná verzia PVE",
"Available Shares:": "Dostupné zdieľania:",
"Available action": "Dostupná akcia",
"Available applications: {count}": "Dostupné aplikácie: {count}",
"Available archives:": "Dostupné archívy:",
"Available disks detected.": "Dostupné disky boli nájdené.",
"Available host backups:": "Dostupné zálohy hosta:",
@@ -873,6 +884,7 @@
"Cannot write the image archive to {storage}. Check storage access and mount status.": "Archív obrazu sa nedá zapísať do úložiska {storage}. Skontrolujte prístup k úložisku a stav jeho pripojenia.",
"Capabilities cannot be kept and all dropped at the same time": "Oprávnenia capabilities nemožno súčasne ponechať aj všetky odobrať",
"Catalog options": "Možnosti katalógu",
"Catalog refresh unavailable; using the local catalog.": "Katalóg sa nepodarilo aktualizovať; používa sa miestna kópia.",
"Category": "Kategória",
"Caution: Maximum mode generates more heat.": "Pozor: maximálny režim vytvára viac tepla.",
"Central server for file and image backups.": "Centrálny server na zálohovanie súborov a obrazov.",
@@ -1159,6 +1171,7 @@
"Compressing": "Komprimujem",
"Compression": "Kompresia",
"Compression Tools": "Kompresné nástroje",
"Computer-aided design and drafting in your browser": "Počítačom podporované navrhovanie a technické kreslenie v prehliadači",
"Concise output of logical volumes": "Stručný výpis logických zväzkov",
"Concise output of physical volumes": "Stručný výpis fyzických zväzkov",
"Concise output of volume groups": "Stručný výpis skupín zväzkov",
@@ -1289,6 +1302,7 @@
"Conflicting utilities removed": "Konfliktné nástroje odstránené",
"Connect Zigbee devices to MQTT with a browser-based setup interface.": "Pripojte zariadenia Zigbee k MQTT prostredníctvom webového rozhrania na nastavenie.",
"Connect a Coral Accelerator and try again.": "Pripojte Coral Accelerator a skúste to znova.",
"Connect a remote USB device": "Pripojiť vzdialené USB zariadenie",
"Connect it, or remove it from the container in Proxmox (Resources), and run the recovery again.": "Pripojte zariadenie alebo ho odstráňte z konfigurácie kontajnera v Proxmoxe (Zdroje) a registráciu zopakujte.",
"Connect your devices and users together in your own secure virtual private network.": "Spojte svoje zariadenia a užívateľov vo vlastnej zabezpečenej virtuálnej súkromnej sieti.",
"Connect your devices into a secure WireGuard®-based overlay network with SSO, MFA and granular access controls.": "Pripojte svoje zariadenia do zabezpečenej prekryvnej siete založenej na WireGuard® s ovládacími prvkami SSO, MFA a granulovaného prístupu.",
@@ -1393,6 +1407,7 @@
"Controller + NVMe": "Controller + NVMe",
"Controller + NVMe assignment will be written now and become active after host reboot.": "Priradenie Controller + NVMe sa teraz zapíše a aktivuje sa po reštarte servera.",
"Controller + NVMe passthrough requires machine type q35. Skipping controller assignment.": "Priame priradenie Controller + NVMe vyžaduje typ stroja q35. Priradenie controllera sa preskočí.",
"Controller path on the Proxmox host; prefer /dev/serial/by-id/...": "Cesta ku kontroléru na hostiteľovi Proxmox; uprednostnite /dev/serial/by-id/...",
"Controller/NVMe Conflict Policy": "Riešenie konfliktu Controller/NVMe",
"Controller/NVMe already present in VM config": "Controller/NVMe už je v nastavení VM",
"Controller/NVMe already present in VM config (%s)": "Radič/NVMe už je v nastaveniach VM (%s)",
@@ -1927,6 +1942,7 @@
"Dgraph": "Dgraph",
"Diff: current system vs backup (--- system +++ backup)": "Rozdiel: aktuálny systém vs záloha (--- systém +++ záloha)",
"Different host. Backup from:": "Iný host. Záloha z:",
"Direct Connect file sharing with a web interface": "Zdieľanie súborov cez Direct Connect s webovým rozhraním",
"Direct conversion completed for container": "Priama konverzia bola dokončená pre kontajner",
"Directory Exists": "Priečinok už existuje",
"Directory Not Empty": "Priečinok nie je prázdny",
@@ -1949,12 +1965,14 @@
"Directus administrator": "Správca Directus",
"Disable NIC Offloading (Intel e1000e)": "Vypnúť NIC offloading (Intel e1000e)",
"Disable Secure Boot in the UEFI firmware and run the installer again. Nothing has been changed.": "Vypnite Secure Boot vo firmvéri UEFI a spustite inštalátor znova. Nič sa nezmenilo.",
"Disable USB/IP server": "Zakázať server USB/IP",
"Disable autostart on conflicting VM": "Vypnúť automatický štart na konfliktnej VM",
"Disable autostart on one VM to avoid startup conflicts.": "Na jednej VM vypnite automatický štart, aby nevznikol konflikt pri spúšťaní.",
"Disable job": "Zakázať úlohu",
"Disable kernel audit messages (optional but recommended):": "Vypnite audit správy kernelu (voliteľné, ale odporúčané):",
"Disable onboot on affected VM(s)/CT(s)": "Vypnúť onboot na dotknutých VM/CT",
"Disable portmapper/rpcbind": "Vypnúť portmapper/rpcbind",
"Disable the server and release all USB devices managed by ProxMenux? Saved selections are kept for the next enable.": "Zakázať server a uvoľniť všetky USB zariadenia spravované ProxMenuxom? Uložený výber sa zachová pre ďalšie povolenie.",
"Disabled": "Vypnuté",
"Disabling High Availability services...": "Vypínam služby High Availability...",
"Disabling ZFS autotrim applied by ProxMenux...": "Vypínam ZFS autotrim, ktorý nastavil ProxMenux...",
@@ -2187,6 +2205,7 @@
"Enable Remote Desktop (RDP) before disabling the virtual display.": "Pred vypnutím virtuálneho zobrazenia zapnite Vzdialenú plochu (RDP).",
"Enable SSD emulation for this disk?": "Zapnúť pre tento disk emuláciu SSD?",
"Enable TCP BBR/Fast Open control": "Zapnúť TCP BBR/Fast Open",
"Enable USB/IP server": "Povoliť server USB/IP",
"Enable VA-API transcoding and HDR10/Dolby Vision to SDR tone mapping": "Povoliť prevod videa cez VA-API a mapovanie tónov HDR10/Dolby Vision na SDR",
"Enable VA-API, hardware encoding and OpenCL tone mapping in Jellyfin": "Povoliť VA-API, hardvérové kódovanie a mapovanie tónov pomocou OpenCL v Jellyfine",
"Enable VFIO IOMMU support": "Zapnúť podporu VFIO/IOMMU",
@@ -3199,6 +3218,7 @@
"If pvesm path returned a DEVICE (LVM):": "Ak pvesm path vrátil ZARIADENIE (LVM):",
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Ak pvesm path vrátil PRIEČINOK (ZFS/BTRFS):",
"If repositories error:": "Ak zlyhajú repozitáre:",
"If the USB/IP service stops unexpectedly, stop sharing while the device is still connected to release it. In rare cases only a host reboot releases it.": "Ak sa služba USB/IP neočakávane zastaví, ukončite zdieľanie, kým je zariadenie ešte pripojené, aby sa uvoľnilo. V zriedkavých prípadoch ho uvoľní iba reštart hosta.",
"If the container had already been changed, its previous native backup is restored. Shared host directories are not reverted. The disks of the failed attempt are removed when the cleanup succeeds.": "Ak už bol kontajner zmenený, obnoví sa jeho predchádzajúca natívna záloha. Zdieľané hostiteľské adresáre sa nevrátia späť. Disky neúspešného pokusu sa po úspešnom vyčistení odstránia.",
"If the host freezes, remove hostpci entries from": "Ak server zamrzne, odstráňte položky hostpci z",
"If the image channel has a new version, the CT is stopped, backed up and verified, and replaced with the new image to update the container. If anything fails, the backup is restored.": "Ak má kanál obrázkov novú verziu, CT sa zastaví, zálohuje a overí a nahradí sa novým obrázkom, aby sa aktualizoval kontajner. Ak niečo zlyhá, záloha sa obnoví.",
@@ -3339,6 +3359,7 @@
"Initial Stirling-PDF account": "Počiatočný účet Stirling-PDF",
"Initial Tandoor administrator": "Počiatočný správca Tandoor",
"Initial Umami administrator": "Počiatočný správca Umami",
"Initial Z-Wave JS UI admin password": "Počiatočné heslo správcu Z-Wave JS UI",
"Initial administrator account": "Úvodný účet správcu",
"Initial administrator created:": "Pôvodný správca vytvorený:",
"Initial administrator user": "Počiatočné používateľské meno správcu",
@@ -3393,6 +3414,7 @@
"Install server packages inside CT:": "Nainštalovať serverové balíky vo vnútri CT:",
"Install terminal multiplexers": "Nainštalovať terminálové multiplexery",
"Install the Edge TPU runtime (libedgetpu1-std)": "Nainštaluje Edge TPU runtime (libedgetpu1-std)",
"Install the USB/IP dependencies from the configured Debian repositories?": "Nainštalovať závislosti USB/IP z nakonfigurovaných repozitárov Debianu?",
"Install this image?": "Nainštalovať tento obraz?",
"Install with Cloud-Init script": "Inštalovať cez Cloud-Init skript",
"Install with ISO from UUP Dump": "Inštalovať z ISO cez UUP Dump",
@@ -3525,6 +3547,7 @@
"Interface MTU": "MTU rozhrania",
"Interface Names (persistent)": "Trvalé názvy rozhraní",
"Interface Type": "Typ rozhrania",
"Interface design and prototyping in your browser": "Návrh rozhraní a prototypov v prehliadači",
"Interface names will return to default systemd behavior.": "Názvy rozhraní sa vrátia k predvolenému správaniu systemd.",
"Interface type:": "Typ rozhrania:",
"Interfaces configured": "Nastavené rozhrania",
@@ -3582,6 +3605,7 @@
"Invalid check package:": "Neplatný kontrolný balík:",
"Invalid configuration path:": "Neplatná konfiguračná dráha:",
"Invalid consume/export volumes": "Neplatné dátové zväzky consume a export",
"Invalid container device GID": "Neplatné GID zariadenia v kontajneri",
"Invalid container path:": "Neplatná trasa kontajnera:",
"Invalid credential file path:": "Neplatná cesta súboru s prihlasovacími údajmi:",
"Invalid declarative entrypoint": "Neplatný deklaratívny vstupný bod",
@@ -3740,6 +3764,7 @@
"Jupyter Lab (token only)": "Jupyter Lab (iba token)",
"JupyterLab": "JupyterLab",
"JupyterLab access token": "Prístupový token JupyterLab",
"KDE's twin-panel file manager in a browser-based desktop.": "Dvojpanelový správca súborov KDE v pracovnej ploche dostupnej cez webový prehliadač.",
"KDF:": "KDF:",
"KROMA": "KROMA",
"KVM MSR options added to /etc/modprobe.d/kvm.conf": "Možnosti KVM MSR boli pridané do /etc/modprobe.d/kvm.conf",
@@ -3787,12 +3812,14 @@
"KiCad - A Cross Platform and Open Source Electronics Design Automation Suite.": "KiCad – multiplatformový balík s otvoreným zdrojovým kódom na návrh elektroniky.",
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "Kimai nemá predvolený účet. Do kontajnera vstúpite príkazom: pct enter {main_vmid}",
"Kimai is a professional grade time-tracking application, free and open-source.": "Kimai je profesionálna bezplatná aplikácia na sledovanie pracovného času s otvoreným zdrojovým kódom.",
"KitchenOwl": "KitchenOwl",
"Kometa is a powerful tool designed to give you complete control over your media libraries. With Kometa, you can take your customization to the next level, with granular control over metadata, collections, overlays, and much more.": "Kometa poskytuje podrobnú kontrolu nad mediálnymi knižnicami. Umožňuje prispôsobiť metadáta, kolekcie, grafické prekrytia a ďalšie prvky.",
"Kometa reads its configuration from /config/config.yml and the container only ships /config/config.yml.template. Copy the template to config.yml, fill in the required Plex and TMDb connections, then restart the container.": "Kometa číta nastavenia z /config/config.yml, kontajner však obsahuje iba /config/config.yml.template. Skopírujte šablónu do config.yml, vyplňte požadované pripojenia Plex a TMDb a kontajner reštartujte.",
"Komga is a media server for your comics, mangas, BDs, magazines and eBooks.": "Komga je mediálny server na komiksy, mangu, grafické romány, časopisy a elektronické knihy.",
"Kopia Web UI": "Webové rozhranie Kopia",
"Kopia Web UI login": "Prihlásenie do webového rozhrania Kopia",
"Krita is a professional FREE and open source painting program. It is made by artists that want to see affordable art tools for everyone.": "Krita je profesionálny bezplatný maliarsky program s otvoreným zdrojovým kódom. Vytvárajú ho umelci, ktorí chcú sprístupniť umelecké nástroje každému.",
"Krusader Web UI": "Webové rozhranie Krusaderu",
"LAN access to the kept containers (stack configuration incomplete):": "Prístup z LAN k ponechaným kontajnerom (nastavenie zostavy nie je dokončené):",
"LAN address applied to the application URLs": "LAN adresa použitá na URL aplikácie",
"LLDAP": "LLDAP",
@@ -3873,9 +3900,11 @@
"Line to paste (single line, including \"command=...\" prefix):": "Riadok na vloženie (jeden riadok vrátane predpony \"command=...\"):",
"LinkStack": "LinkStack",
"Linux Installation Options": "Možnosti inštalácie Linuxu",
"Linux guest setup and migration notes": "Nastavenie hostí Linux a poznámky k migrácii",
"Linux/Mac path:": "Cesta pre Linux/Mac:",
"LinuxServer Jellyfin with optional GPU passthrough": "LinuxServer Jellyfin s voliteľným GPU priechodom",
"LinuxServer MariaDB requires a user, database and password": "LinuxServer MariaDB vyžaduje používateľa, databázu a heslo",
"LinuxServer Nextcloud with MariaDB and Redis": "Nextcloud od LinuxServer s MariaDB a Redis",
"List Available Disks": "Zobraziť dostupné disky",
"List IOMMU group mapping": "Zobraziť mapovanie IOMMU skupín",
"List NVMe devices": "Zobraziť NVMe zariadenia",
@@ -4020,6 +4049,7 @@
"Manage OCI stack": "Spravovať aplikáciu s viacerými kontajnermi",
"Manage PBS encryption keyfile": "Spravovať šifrovací keyfile pre PBS",
"Manage Secure Gateway": "Spravovať Secure Gateway",
"Manage a Z-Wave network from a web dashboard and WebSocket gateway.": "Spravujte sieť Z-Wave cez webový panel a bránu WebSocket.",
"Manage and inspect VM disk images": "Spravovať a kontrolovať diskové obrazy VM",
"Manage custom backup paths": "Spravovať vlastné cesty zálohy",
"Manage custom paths (add / remove your folders)": "Spravovať vlastné cesty (pridať / odstrániť priečinky)",
@@ -4029,6 +4059,7 @@
"Manage local backup target": "Spravovať lokálny cieľ záloh",
"Manage private image registries.\nSaved credentials let ProxMenux access your private images.": "Správa súkromných registrov obrazov.\nUložené prihlasovacie údaje umožňujú ProxMenuxu pristupovať k vašim súkromným obrazom.",
"Manage registry accounts as root on the Proxmox node.": "Spravujte účty registra ako root na uzle Proxmox.",
"Manage teams of AI agents from a web dashboard.": "Spravujte tímy AI agentov z webového panela.",
"Managed disks must have backup enabled and a valid size": "Spravované disky musia mať zapnuté zálohovanie a platnú veľkosť",
"Managed public route include is missing": "Chýba konfiguračný súbor spravovaných verejných trás",
"Managed public route installation failed": "Nepodarilo sa nastaviť spravované verejné trasy",
@@ -4134,6 +4165,7 @@
"Monitoring": "Monitorovanie",
"Monitoring & Analytics": "Monitorovanie a analýza",
"Most common cause: the archive is corrupted (interrupted write, partial copy, or storage issue).": "Najčastejšia príčina: archív je poškodený (prerušený zápis, neúplná kópia alebo problém s úložiskom).",
"Motion graphics and compositing in your browser": "Animovaná grafika a kompoziting v prehliadači",
"Mount Added Successfully:": "Mount bol úspešne pridaný:",
"Mount CIFS share:": "Pripojiť CIFS zdieľanie:",
"Mount Configuration Summary:": "Zhrnutie nastavenia mountu:",
@@ -4293,6 +4325,7 @@
"NVIDIA (CUDA; official GPU image)": "NVIDIA (CUDA; oficiálny obraz GPU)",
"NVIDIA (NVDEC/CUDA)": "NVIDIA (NVDEC/CUDA)",
"NVIDIA (NVENC/NVDEC)": "NVIDIA (NVENC/NVDEC)",
"NVIDIA (Selkies rendering and NVENC)": "NVIDIA (vykresľovanie Selkies a NVENC)",
"NVIDIA Actions": "Akcie pre NVIDIA",
"NVIDIA CPU hiding already configured": "NVIDIA CPU skrytie už je nastavené",
"NVIDIA Container Toolkit": "NVIDIA Container Toolkit",
@@ -4376,6 +4409,7 @@
"Name or part of the option or of the application": "Názov alebo časť možnosti alebo aplikácie",
"Name:": "Názov:",
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Používateľské účty vyžadujú súkromný režim. Zastavte kontajner, v /config/config.js nastavte public: false, znova ho spustite a každého používateľa vytvorte príkazom: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>",
"Native Borg is unavailable. Install the native borgbackup package on this host to use Borg backups.": "Natívna verzia Borg nie je dostupná. Ak chcete používať zálohy Borg, nainštalujte na tento hostiteľ natívny balík borgbackup.",
"Needed:": "Potrebné:",
"Needs": "Vyžaduje",
"Neither /etc/kernel/cmdline nor /etc/default/grub found.": "Nenašiel sa /etc/kernel/cmdline ani /etc/default/grub.",
@@ -4434,6 +4468,8 @@
"New Search": "Nové hľadanie",
"New VM:": "Nová VM:",
"New Virtual Machine": "Nová virtuálna mašina",
"New applications ({count})": "Nové aplikácie ({count})",
"New applications since your last visit: {count}": "Nové aplikácie od vašej poslednej návštevy: {count}",
"New backup job": "Nová úloha zálohy",
"New backups on this host will be unencrypted until a new keyfile is set up.": "Nové zálohy na tomto hostovi budú nešifrované, kým nenastavíte nový keyfile.",
"New image compatible:": "Nový obraz je kompatibilný:",
@@ -4449,6 +4485,7 @@
"Next Step Required": "Je potrebný ďalší krok",
"Next Steps:": "Ďalšie kroky:",
"Next step: stop that VM first, then run": "Ďalší krok: najprv zastavte tú VM, potom spustite",
"Nextcloud Web UI": "Webové rozhranie Nextcloud",
"Nextcloud configuration cancelled": "Konfigurácia Nextcloud zrušená",
"Nextcloud gives you access to all your files wherever you are.": "Nextcloud vám umožní prístup ku všetkým súborom kdekoľvek ste.",
"Nextcloud volume size in GB": "Veľkosť dátového zväzku Nextcloud v GB",
@@ -4623,6 +4660,7 @@
"No duplicate IP addresses": "Nenašli sa duplicitné IP adresy",
"No duplicate repositories found": "Nenašli sa žiadne duplicitné repozitáre",
"No eligible Controller/NVMe devices remain after SR-IOV filtering. Skipping.": "Po odfiltrovaní SR-IOV nezostali žiadne vhodné Controller/NVMe zariadenia. Preskakuje sa.",
"No eligible USB devices found. Hubs, mass storage and network adapters are excluded.": "Nenašli sa žiadne vhodné USB zariadenia. Rozbočovače, veľkokapacitné úložiská a sieťové adaptéry sú vylúčené.",
"No eligible controllers remain after SR-IOV filtering.": "Po odfiltrovaní SR-IOV nezostali žiadne vhodné controllery.",
"No encryption key is stored on this host. Choose how to set one up:": "Na tomto hostovi nie je uložený žiadny šifrovací kľúč. Vyberte, ako ho nastaviť:",
"No exportable VM disks were found (CD-ROM/cloud-init are excluded).": "Nenašli sa žiadne exportovateľné VM disky (CD-ROM/cloud-init sú vylúčené).",
@@ -4707,6 +4745,7 @@
"No self-test log available for": "Nie je dostupný log samo-testu pre",
"No server IP or hostname provided.": "Nebola zadaná IP adresa ani názov servera.",
"No share access test succeeded with guest authentication.": "S overením hosťa nebol úspešný žiadny test prístupu k zdieľaniu.",
"No shared devices are available on this server.": "Na tomto serveri nie sú k dispozícii žiadne zdieľané zariadenia.",
"No shared media content.": "Žiadny spoločný mediálny obsah.",
"No shared mount detected. Applying standard local access.": "Nenašlo sa zdieľané pripojenie. Nastavujem bežný lokálny prístup.",
"No shares configured.": "Nie sú nastavené žiadne zdieľania.",
@@ -4898,6 +4937,8 @@
"Open the page of an application in the menu": "Otvoriť stránku aplikácie v ponuke",
"Open the web address and create the first account: the daemon registers by itself and starts the first scan.": "Otvorte webovú adresu a vytvorte prvé konto: daemon sa zaregistruje sám a spustí prvé skenovanie.",
"Open the web address and create the password of the akadmin user in the first-run setup.": "Otvorte webovú adresu a v prvotnom nastavení vytvorte heslo používateľa akadmin.",
"Open the web address and follow KitchenOwl’s onboarding to create the first account; no default account is configured.": "Otvorte webovú adresu a podľa pokynov KitchenOwl vytvorte prvý účet; predvolený účet nie je nastavený.",
"Open the web dashboard and link your Movistar/O2 account using its SMS flow.": "Otvorte webový panel a prepojte svoj účet Movistar/O2 pomocou overenia cez SMS.",
"Open-source AI-powered coding assistant": "Programátorský asistent využívajúci AI s otvoreným zdrojovým kódom",
"Open-source UI for building and debugging multi-agent and RAG applications": "Rozhranie s otvoreným zdrojovým kódom na tvorbu a ladenie aplikácií s viacerými agentmi a RAG",
"Open-source in-memory data store.": "Úložisko údajov v pamäti s otvoreným zdrojovým kódom.",
@@ -5020,6 +5061,7 @@
"Packages:": "Balíky:",
"Packaging OVA file...": "Balím OVA súbor...",
"Packing installer archive...": "Balím archív inštalátora...",
"Page layout and publishing in your browser": "Zalomenie strán a publikovanie v prehliadači",
"PairDrop is a sublime alternative to AirDrop that works on all platforms. Send images, documents or text via peer to peer connection to devices in the same local network/Wi-Fi or to paired devices.": "PairDrop je skvelá alternatíva k AirDrop, ktorá pracuje na všetkých platformách. Poslať obrázky, dokumenty alebo text prostredníctvom peer-to-peer pripojenie k zariadeniam v rovnakej miestnej sieti/Wi-Fi alebo spárované zariadenia.",
"Paperless configuration cancelled": "Nastavenie Paperless bolo zrušené",
"Paperless-ngx WebUI": "Paperless-ngx WebUI",
@@ -5038,6 +5080,7 @@
"Pass /dev/video12 to the LXC": "Sprístupniť /dev/video12 kontajneru LXC",
"Pass a host device to the LXC": "Sprístupniť zariadenie hostiteľa kontajneru LXC",
"Pass the UPS to the LXC": "Sprístupniť UPS kontajneru LXC",
"Pass through a Z-Wave USB or serial controller": "Pripojiť USB alebo sériový radič Z-Wave",
"Passing NVIDIA does not enable acceleration inside the application. The host needs NVIDIA Container Toolkit and a compatible image. Continue?": "Prejdenie NVIDIA neumožní zrýchlenie v aplikácii. Hostiteľ potrebuje NVIDIA Container Toolkit a kompatibilný obrázok. Pokračovať?",
"Passkey-based identity provider for self-hosted apps.": "Poskytovateľ identity založený na passkeys pre samohostované aplikácie.",
"Passphrase used to unlock the imported keyfile (leave blank if the keyfile is unencrypted / kdf=none):": "Fráza na odomknutie importovaného keyfile (nechajte prázdne, ak keyfile nie je šifrovaný / kdf=none):",
@@ -5103,6 +5146,7 @@
"Path of the Compose file": "Cesta k súboru Compose",
"Path of the oci-compose file": "Cesta k súboru oci-compose",
"Path removed:": "Cesta bola odstránená:",
"Path to the client SSH public key on this server:": "Cesta k verejnému SSH kľúču klienta na tomto serveri:",
"Path:": "Cesta:",
"Paths applied:": "Použité cesty:",
"Paths included in backup": "Cesty zahrnuté v zálohe",
@@ -5145,6 +5189,8 @@
"Personal finance management application": "Aplikácia na správu osobných financií",
"Personal media server for browsing and playing a local video library, with direct play and optional modules.": "Osobný mediálny server na prehliadanie a prehrávanie miestnej videoknižnice s priamym prehrávaním a voliteľnými modulmi.",
"Photo and video library with optional GPU transcoding and machine learning": "Knižnica fotografií a videí s voliteľným prevodom videa pomocou GPU a strojovým učením",
"Photo editing in your browser": "Úprava fotografií v prehliadači",
"Photo library and RAW development in your browser": "Fotoknižnica a vyvolávanie RAW v prehliadači",
"PhotoPrism": "PhotoPrism",
"Photofield": "Photofield",
"Phpmyadmin is a free software tool written in PHP, intended to handle the administration of MySQL over the Web. phpMyAdmin supports a wide range of operations on MySQL and MariaDB.": "phpMyAdmin je bezplatný nástroj napísaný v PHP na správu MySQL cez web. Podporuje širokú škálu operácií nad MySQL a MariaDB.",
@@ -5237,6 +5283,7 @@
"Preparing the machine learning container for the new choice...": "Príprava kontajnera strojového učenia pre novú voľbu...",
"Preparing the recreation...": "Príprava rekreácie...",
"Preparing the update...": "Príprava aktualizácie...",
"Presentations and slide decks in your browser": "Prezentácie a snímky v prehliadači",
"Preserving logs to /var/log.hdd before unmounting...": "Pred odpojením zachovávam logy do /var/log.hdd...",
"Press 'q' to exit": "Stlačte 'q' na ukončenie",
"Press Ctrl+C to stop the server and return to menu.": "Server zastavíte stlačením Ctrl+C a vrátite sa do menu.",
@@ -5342,6 +5389,7 @@
"ProxMenux does not install them. The installation asks how to connect to them.": "ProxMenux ich neinštaluje. Inštalácia sa pýta, ako sa k nim pripojiť.",
"ProxMenux does not validate the contents; any keyfile your PBS accepts is accepted here.": "ProxMenux nekontroluje obsah; prijme sa každý keyfile, ktorý prijme vaše PBS.",
"ProxMenux files:": "Súbory ProxMenux:",
"ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.": "ProxMenux vygeneruje heslo správcu a zobrazí ho na konci inštalácie. Po prvom prihlásení ho zmeňte.",
"ProxMenux logo applied": "Logo ProxMenux bolo použité",
"ProxMenux only acts as a launcher — once the script starts, control leaves ProxMenux.": "ProxMenux tu slúži iba ako spúšťač - po spustení skriptu už riadenie neprebieha cez ProxMenux.",
"ProxMenux saved it locally at:": "ProxMenux ju uložil lokálne v:",
@@ -5397,6 +5445,7 @@
"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",
"Proxy address to reach the API (optional)": "Adresa proxy na prístup k API (voliteľné)",
"Public HTTPS URL used to open this Authelia portal (for example https://auth.example.com)": "Verejná adresa HTTPS na otvorenie tohto portálu Authelia (napríklad https://auth.example.com)",
"Public UDP port clients connect to": "Verejný port UDP na pripojenie klientov",
"Public UDP port peers connect to": "Verejný port UDP na pripojenie účastníkov",
"Public URL of phpMyAdmin when it is served behind a reverse proxy": "Verejné URL phpMyAdmin, keď sa podáva za reverzným proxy",
@@ -5457,6 +5506,7 @@
"Re-running pre-check after repairs...": "Spúšťam predbežnú kontrolu znova po opravách...",
"Reachable": "Dostupné",
"Read an oci-compose from a file of this host": "Načítať oci-compose zo súboru tohto hostiteľa",
"Read and edit PDF documents in your browser": "Čítanie a úprava dokumentov PDF v prehliadači",
"Read its Compose file from a file of this host": "Načítať súbor Compose z tohto hostiteľa",
"Read manga through a self-hosted server and web UI.": "Čítajte mangu cez vlastný server a webové rozhranie.",
"Read the link with pct console CTID on the Proxmox host, or from the Console panel of the container in the Proxmox web interface, then open the https://playit.gg/claim/ address it shows in a browser and sign in to playit.gg. Ctrl+a q leaves pct console.": "Odkaz zobrazíte na hostiteľovi Proxmox príkazom pct console CTID alebo v paneli Console kontajnera vo webovom rozhraní Proxmox. Zobrazenú adresu https://playit.gg/claim/ otvorte v prehliadači a prihláste sa do playit.gg. Konzolu pct console ukončíte pomocou Ctrl+a q.",
@@ -5560,8 +5610,10 @@
"Recreation prepared": "Pripravené rekreácie",
"Recursive DNS resolver.": "Rekurzívny DNS resolver.",
"Recursive and authoritative DNS server.": "Rekurzívny a autoritatívny DNS server.",
"Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.": "Zamykanie súborov pomocou Redis sa nastaví automaticky. Existujúce konfiguračné súbory Nextcloud sa zachovajú.",
"Redmine": "Redmine",
"Refresh APT index and verify repositories:": "Obnovte APT index a overte repozitáre:",
"Refresh catalog": "Aktualizovať katalóg",
"Refresh the configured APT repositories and review the PBS package upgrade? Repository files will be preserved.": "Obnoviť indexy nakonfigurovaných repozitárov APT a skontrolovať aktualizáciu balíkov PBS? Súbory repozitárov sa zachovajú.",
"Refresh the index from the image sources": "Obnoviť index zo zdrojov obrazov",
"Refresh token of the connector, from the Twingate admin console": "Obnovovací token konektora z administrátorskej konzoly Twingate",
@@ -5569,6 +5621,7 @@
"Refresh your browser to see changes (server restart may be required)": "Obnovte stránku v prehliadači, aby ste videli zmeny (môže byť potrebný reštart servera)",
"Refreshing apt cache...": "Obnovujem apt cache...",
"Refreshing the NVIDIA runtime...": "Obnovenie prevádzky NVIDIA...",
"Refreshing the application catalog...": "Aktualizuje sa katalóg aplikácií...",
"Refusing an unexpected rootfs path:": "Odmietnutá neočakávaná cesta koreňového súborového systému:",
"Regenerate the catalog templates": "Znova vygenerovať šablóny katalógu",
"Regenerate the template of one application": "Znova vygenerovať šablónu jednej aplikácie",
@@ -5641,6 +5694,7 @@
"Remove Proxmox NFS storage:": "Odstrániť NFS úložisko z Proxmoxu:",
"Remove Proxmox iSCSI storage:": "Odstrániť iSCSI úložisko z Proxmoxu:",
"Remove Secure Gateway? State will be preserved.": "Odstrániť Secure Gateway? Stav bude zachovaný.",
"Remove a remote USB connection": "Odstrániť vzdialené USB pripojenie",
"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ániť všetky registrované verzie gasket DKMS",
@@ -5661,6 +5715,7 @@
"Remove the lock left on a container by an interrupted task": "Odstrániť zámok, ktorý na kontajneri zanechala prerušená úloha",
"Remove the saved credentials for {registry}?\nRunning apps will keep working.": "Odstrániť uložené prihlasovacie údaje pre {registry}?\nSpustené aplikácie budú naďalej fungovať.",
"Remove the unprivileged flag from configuration:": "Odstrániť príznak neprivilegovaného kontajnera z nastavenia:",
"Remove this connection and detach its USB device?": "Odstrániť toto pripojenie a odpojiť jeho USB zariadenie?",
"Remove unused packages and their config": "Odstrániť nepoužívané balíky aj ich nastavenia",
"Remove: delete the application and its containers": "Odstrániť: zmazať aplikáciu a jej kontajnery",
"Removed": "Odstránené",
@@ -5883,9 +5938,11 @@
"Run mode: Unattended": "Režim spustenia: bez zásahu",
"Run now": "Bež teraz",
"Run security audit now": "Spustiť bezpečnostný audit teraz",
"Run the client inside the Linux VM that needs the USB device. Install usbip, openssh-client and kmod, then copy usbip_manager.py to the same path as on the server. Configure key authentication and verify the server host key before adding a connection. The client uses the guest kernel and can reconnect after migration while the physical USB device stays on the server. Unprivileged LXC and Home Assistant OS need their own kernel/device or add-on setup. A physical device supports one attached client at a time.": "Klienta spustite vo virtuálnom stroji Linux, ktorý potrebuje USB zariadenie. Nainštalujte usbip, openssh-client a kmod a potom skopírujte usbip_manager.py na rovnakú cestu ako na serveri. Pred pridaním pripojenia nastavte overovanie kľúčom a overte hostiteľský kľúč servera. Klient používa jadro hosťa a po migrácii sa môže znova pripojiť, zatiaľ čo fyzické USB zariadenie zostáva na serveri. Neprivilegované LXC a Home Assistant OS vyžadujú vlastné nastavenie jadra, zariadení alebo doplnkov. Fyzické zariadenie môže byť pripojené iba k jednému klientovi naraz.",
"Run the following inside the VM:": "Vo vnútri VM spustite:",
"Run the release-channel switch from an SSH session or the Proxmox host console with:": "Prepnutie vetvy vydania spustite cez SSH alebo priamo z konzoly Proxmox servera pomocou:",
"Run the update from an SSH session or the Proxmox host console with:": "Spustite aktualizáciu zo SSH relácie alebo z konzoly Proxmox hosta pomocou:",
"Run this menu as root.": "Túto ponuku spustite ako root.",
"Run this operation as root.": "Túto operáciu spustite ako root.",
"Run upgrade checklist script:": "Spustite kontrolný skript aktualizácie:",
"Running": "Beží",
@@ -6110,6 +6167,7 @@
"Select a new language for the menu:": "Vyberte nový jazyk menu:",
"Select a post-installation script:": "Vyberte skript po inštalácii:",
"Select a pre-configured Linux VM script to execute:": "Vyberte pripravený skript pre Linux VM, ktorý sa má spustiť:",
"Select a saved USB/IP device:": "Vyberte uložené zariadenie USB/IP:",
"Select a script or action:": "Vyberte skript alebo akciu:",
"Select a share to delete:": "Vyberte zdieľanie na vymazanie:",
"Select a specific Coral or USB node, not the whole /dev": "Vyberte špecifický Coral alebo USB uzol, nie celý /dev",
@@ -6187,6 +6245,7 @@
"Select the Linux distribution to install:": "Vyberte Linux distribúciu na inštaláciu:",
"Select the NAS system to install:": "Vyberte NAS systém na inštaláciu:",
"Select the NVIDIA driver version to install:": "Vyberte verziu ovládača NVIDIA na inštaláciu:",
"Select the USB device to share:": "Vyberte USB zariadenie na zdieľanie:",
"Select the VM to add the GPU to:": "Vyberte VM, do ktorej sa má GPU pridať:",
"Select the VM to which you want to add disks:": "Vyberte VM, do ktorej chcete pridať disky:",
"Select the VM where you want to import the disk image:": "Vyberte VM, do ktorej chcete importovať diskový obraz:",
@@ -6211,6 +6270,7 @@
"Select the parent job to attach to:": "Vyberte nadradenú úlohu, ku ktorej sa má pripojiť:",
"Select the paths to restore (one per backup entry):": "Vyberte cesty na obnovu (jedna za každú položku zálohy):",
"Select the privileged LXC container to convert:": "Vyberte privilegovaný LXC kontajner na prevod:",
"Select the remote USB device:": "Vyberte vzdialené USB zariadenie:",
"Select the storage that will receive the backups:": "Vyberte úložisko, ktoré bude prijímať zálohy:",
"Select the storage volume for disk import:": "Vyberte úložisko pre import disku:",
"Select the sync interval (in hours):": "Vyberte interval synchronizácie (v hodinách):",
@@ -6260,6 +6320,7 @@
"Self-hosted file sync and sharing.": "Vlastná služba na synchronizáciu a zdieľanie súborov.",
"Self-hosted file toolkit for images, video, audio, PDFs, and files": "Súprava nástrojov na vlastnom serveri na prácu s obrázkami, videom, zvukom, PDF a ďalšími súbormi",
"Self-hosted forms and workflows.": "Formuláre a pracovné postupy prevádzkované na vlastnom serveri.",
"Self-hosted grocery list and recipe manager": "Správca nákupných zoznamov a receptov, ktorý si môžete prevádzkovať sami.",
"Self-hosted household plant-care tracker with reminders, photos, and multiple user accounts.": "Prehľad starostlivosti o izbové rastliny prevádzkovaný na vlastnom serveri s pripomienkami, fotografiami a viacerými používateľskými účtami.",
"Self-hosted image-hosting service with authenticated uploads, image processing, public links, and local storage.": "Služba na ukladanie a zdieľanie obrázkov na vlastnom serveri s nahrávaním pre overených používateľov, spracovaním obrázkov, verejnými odkazmi a lokálnym úložiskom.",
"Self-hosted internet archiving solution": "Riešenie na archiváciu internetového obsahu na vlastnom serveri",
@@ -6296,6 +6357,7 @@
"Server IDs to test against, separated by commas (optional)": "ID serverov, proti ktorým sa majú spustiť testy (voliteľné)",
"Server IP/hostname is correct": "IP/hostname servera je správny",
"Server IP:": "IP servera:",
"Server SSH port:": "SSH port servera:",
"Server is accessible:": "Server je dostupný:",
"Server is online": "Server je online",
"Server is running": "Server beží",
@@ -6357,6 +6419,7 @@
"Share Access Error": "Chyba prístupu k zdieľaniu",
"Share Name": "Názov zdieľania",
"Share Options": "Možnosti zdieľania",
"Share a local USB device": "Zdieľať miestne USB zariadenie",
"Share added successfully.": "Zdieľanie bolo úspešne pridané.",
"Share deleted and Samba service restarted.": "Zdieľanie bolo vymazané a služba Samba reštartovaná.",
"Share exists:": "Zdieľanie existuje:",
@@ -6364,6 +6427,7 @@
"Share name:": "Názov zdieľania:",
"Share not found on server:": "Zdieľanie sa na serveri nenašlo:",
"Share path:": "Cesta zdieľania:",
"Share selected USB devices through SSH, or connect this Linux machine to a USB/IP server.": "Zdieľajte vybrané USB zariadenia cez SSH alebo pripojte tento počítač Linux k serveru USB/IP.",
"Share updated successfully.": "Zdieľanie bolo úspešne aktualizované.",
"Share:": "Zdieľanie:",
"ShareCoveX panel": "Panel ShareCoveX",
@@ -6454,6 +6518,7 @@
"Simple and easy to use DDNS": "Jednoducho použiteľné dynamické DNS (DDNS)",
"Simple self-hosted file sharing.": "Jednoduchá samohostovaná služba na zdieľanie súborov.",
"Single GPU Warning": "Upozornenie na jednu GPU",
"Single sign-on and multi-factor authentication": "Jednotné prihlásenie a viacfaktorové overovanie",
"Single target found — selected automatically:": "Našiel sa jeden target - vybraný automaticky:",
"Single-node log storage and query UI.": "Úložisko logov a vyhľadávacie rozhranie pre jeden uzol.",
"Single-node observability database for metrics, logs and traces.": "Databáza na jednom uzle na ukladanie metrík, logov a záznamov o priebehu požiadaviek.",
@@ -6522,7 +6587,9 @@
"Specific subnet (enter manually)": "Konkrétna podsieť (zadať ručne)",
"Speedtest Tracker web interface": "Webové rozhranie Speedtest Tracker",
"Speedtest-tracker is a self-hosted internet performance tracking application that runs speedtest checks against Ookla's Speedtest service.": "Speedtest Tracker je aplikácia na vlastnom serveri na sledovanie výkonu internetového pripojenia pomocou meraní služby Ookla Speedtest.",
"Spoolman web interface": "Webové rozhranie Spoolmanu",
"Spotube is an open source, cross-platform Spotify client compatible across multiple platforms utilizing Spotify's data API and YouTube, Piped.video or JioSaavn as an audio source, eliminating the need for Spotify Premium": "Spotube je multiplatformový klient Spotify s otvoreným zdrojovým kódom. Využíva dátové API Spotify a zvuk získava z YouTube, Piped.video alebo JioSaavn, takže nevyžaduje Spotify Premium.",
"Spreadsheets in your browser": "Tabuľkový procesor v prehliadači",
"Sshwifty": "Sshwifty",
"Sshwifty web access (password only)": "Webový prístup do Sshwifty (iba heslom)",
"Stable (main branch)": "Stabilná verzia (vetva main)",
@@ -6629,6 +6696,8 @@
"Still has issues": "Stále má problémy",
"Stop - shuts the guest down during backup": "Stop – vypne hosťa počas zálohovania",
"Stop it first and run this option again.": "Najprv ju zastavte a potom túto možnosť spustite znova.",
"Stop sharing a USB device": "Ukončiť zdieľanie USB zariadenia",
"Stop sharing this device? An attached remote client will disconnect.": "Ukončiť zdieľanie tohto zariadenia? Pripojený vzdialený klient bude odpojený.",
"Stop that VM, then choose:": "Zastavte VM a potom vyberte:",
"Stop the CT, unmount the disk on the HOST, and remount with:": "Zastavte CT, odpojte disk na HOSTE a pripojte ho znova pomocou:",
"Stop the VM/CT before formatting this disk.": "Pred formátovaním tohto disku zastavte VM/CT.",
@@ -6983,6 +7052,7 @@
"The container could not be removed automatically:": "Kontajner sa nepodarilo automaticky odstrániť:",
"The container could not be started:": "Kontajner sa nepodarilo spustiť:",
"The container creation does not match the prepared instance": "Vytvorenie kontajnera nezodpovedá pripravenej inštancii",
"The container device settings changed since the last recorded operation": "Nastavenia zariadenia v kontajneri sa od poslednej zaznamenanej operácie zmenili",
"The container devices do not match the saved record": "Zariadenie kontajnera nezodpovedá uloženému záznamu",
"The container did not stop to update its persistent configuration:": "Kontajner sa nezastavil na aktualizáciu svojich trvalých nastavení:",
"The container did not stop; its disks are not touched": "Kontajner sa nezastavil; jeho disky nie sú dotknuté",
@@ -7264,6 +7334,7 @@
"The record no longer belongs to this operation": "Záznam už nepatrí tejto operácii",
"The record of a member was replaced; the assembly is not resumed": "Záznam kontajnera bol nahradený; zostavovanie nebude pokračovať",
"The record or diagnosis could not be completed; no update was run.": "Záznam alebo diagnóza nemohla byť dokončená; žiadna aktualizácia nebola spustená.",
"The recorded container device GID does not match its configuration": "Zaznamenané GID zariadenia v kontajneri sa nezhoduje s jeho konfiguráciou",
"The recovery did not complete. Review the log and choose \"Recover\" again for this container in the OCI management menu.": "Obnova sa nedokončila. Skontrolujte záznam a v ponuke Správca OCI aplikácií pri tomto kontajneri znova vyberte \"Obnoviť\".",
"The recovery did not complete. Review the log and choose \"{choice}\" again for this container in the OCI management menu.": "Obnova sa nedokončila. Skontrolujte záznam a v ponuke Správca OCI aplikácií pri tomto kontajneri znova vyberte \"{choice}\".",
"The registry authentication file is invalid; it was not changed.": "Súbor s prihlasovacími údajmi registrov je neplatný; nebol zmenený.",
@@ -7331,6 +7402,7 @@
"The selected Intel GPU has non-FLR reset support and unknown subtype": "Vybraná Intel GPU má reset podporu mimo FLR a neznámy podtyp",
"The selected Intel GPU is currently in power state D3cold": "Vybraná Intel GPU je aktuálne v napájacom stave D3cold",
"The selected Intel render device does not exist:": "Vybrané zariadenie Intel render neexistuje:",
"The selected USB device will become unavailable to local applications and guests. Only one remote client can use it at a time. Share this device?": "Vybrané USB zariadenie prestane byť dostupné miestnym aplikáciám a hosťom. Naraz ho môže používať iba jeden vzdialený klient. Zdieľať toto zariadenie?",
"The selected VM": "Vybraná VM",
"The selected VM is running.": "Vybraná VM beží.",
"The selected base folder does not exist and could not be created:": "Vybraný základný priečinok neexistuje a nepodarilo sa ho vytvoriť:",
@@ -7418,6 +7490,7 @@
"Then bind-mount to container": "Potom pripojiť do kontajnera cez bind mount",
"Then change the VM display to none (vga: none) when the guest is stable.": "Keď bude VM stabilná, zmeňte jej display na none (vga: none).",
"Then change the VM display to none (vga: none) when the system is stable.": "Keď bude systém stabilný, zmeňte display VM na none (vga: none).",
"Then restart the container so the new model appears in the list.": "Potom kontajner reštartujte, aby sa nový model zobrazil v zozname.",
"Then run this option again:": "Potom túto možnosť spustite znova:",
"Then update /etc/fstab on the host with the same options.": "Potom aktualizujte /etc/fstab na hoste s rovnakými možnosťami.",
"There are extra disks or bind mounts outside the journal; the rootfs is not replaced": "Ďalšie disky alebo pripojené adresáre nie sú uvedené v zázname operácie; rootfs sa nenahradí",
@@ -7465,6 +7538,7 @@
"This container does not have apt-get. NFS client installation only supports Debian/Ubuntu containers.": "Tento kontajner nemá apt-get. Inštalácia NFS klienta je podporovaná iba v Debian/Ubuntu kontajneroch.",
"This container does not have apt-get. Samba client installation only supports Debian/Ubuntu containers.": "Tento kontajner nemá apt-get. Inštalácia Samba klienta je podporovaná iba v Debian/Ubuntu kontajneroch.",
"This container has no GPU configured. Coral TPU works best alongside hardware video decoding (Quick Sync, VA-API, NVENC) for apps like Frigate.": "Tento kontajner nemá nastavenú GPU. Coral TPU funguje najlepšie spolu s hardvérovým dekódovaním videa (Quick Sync, VA-API, NVENC) v aplikáciách ako Frigate.",
"This container is managed by high availability. Remove ct:{vmid} from HA (Datacenter → HA, or ha-manager remove ct:{vmid}), repeat the operation and add it back to HA with the same settings.": "Tento kontajner spravuje vysoká dostupnosť. Odstráňte ct:{vmid} z HA (Dátové centrum → HA alebo ha-manager remove ct:{vmid}), zopakujte operáciu a potom ho znova pridajte do HA s rovnakými nastaveniami.",
"This container is not a member of a multi-container application": "Tento kontajner nie je členom aplikácie s viacerými kontajnermi",
"This container is not a registered OCI instance.": "Tento kontajner nie je registrovanou inštanciou OCI.",
"This container was restored or came back from another host after its record on this host was written. Open this menu again to recover it; nothing was changed.": "Tento kontajner bol obnovený alebo sa vrátil z iného hostiteľa po napísaní jeho záznamu na tomto hostiteľovi. Znova otvorte túto ponuku a obnovte ju; nič sa nezmenilo.",
@@ -7582,6 +7656,7 @@
"Tip: You can install the QEMU Guest Agent inside the VM with:": "Tip: QEMU Guest Agent môžete vo VM nainštalovať pomocou:",
"Tip: zfs set acltype=posixacl xattr=sa <pool>/<dataset> enables full ACL support.": "Tip: zfs set acltype=posixacl xattr=sa <pool>/<dataset> zapne plnú podporu ACL.",
"Tmpfs size in MiB for": "Veľkosť Tmpfs v MiB pre",
"To add a model, open the console of the container in Proxmox and download it into /models, for example:": "Ak chcete pridať model, otvorte konzolu kontajnera v Proxmoxe a stiahnite ho do /models, napríklad:",
"To allow LXC write access, change the NFS export on the server to include:": "Aby LXC mohol zapisovať, upravte NFS export na serveri tak, aby obsahoval:",
"To apply it to the current shell now, run:": "Ak ho chcete použiť v aktuálnej relácii shellu, spustite:",
"To assign VFs to VMs or LXCs, edit the configuration manually via the Proxmox web interface. The Physical Function will remain bound to the native driver.": "Ak chcete priradiť VF do VM alebo LXC, upravte nastavenie ručne cez webové rozhranie Proxmoxu. Physical Function zostane naviazaná na natívny ovládač.",
@@ -7621,6 +7696,7 @@
"Total routes": "Počet trás",
"Total size:": "Celková veľkosť:",
"Toxiproxy": "Toxiproxy",
"Track 3D printer filament spools and usage.": "Sledujte cievky filamentu pre 3D tlačiareň a ich spotrebu.",
"Track movies, television, anime and games you want to enjoy.": "Sledujte filmy, seriály, anime a hry, ktoré si chcete pozrieť alebo zahrať.",
"Track subscriptions and recurring expenses.": "Sledovanie predplatných a opakovaných výdavkov.",
"Track your music listening history on your own server.": "Sledujte históriu počúvania hudby na vlastnom serveri.",
@@ -7665,6 +7741,9 @@
"USB drives mounted now:": "Aktuálne pripojené USB disky:",
"USB libedgetpu1": "USB libedgetpu1",
"USB or serial device node": "Uzol USB alebo sériového zariadenia",
"USB/IP configuration updated. Open status to check the connection.": "Konfigurácia USB/IP bola aktualizovaná. Otvorte stav a skontrolujte pripojenie.",
"USB/IP over SSH": "USB/IP cez SSH",
"USB/IP server IP address or DNS hostname:": "IP adresa alebo DNS názov hostiteľa servera USB/IP:",
"UUP Dump script not found.": "Skript UUP Dump sa nenašiel.",
"UUp Dump ISO creator Custom": "Vlastný tvorca ISO cez UUP Dump",
"Ubooquity is a free, lightweight and easy-to-use home server for your comics and ebooks. Use it to access your files from anywhere, with a tablet, an e-reader, a phone or a computer.": "Ubooquity je bezplatný, ľahký a ľahko použiteľný domáci server pre vaše komiksy a ebooky. Použite ho na prístup k súborom odkiaľkoľvek, s tabletom, e-čítačkou, telefónom alebo počítačom.",
@@ -7821,6 +7900,7 @@
"Untrusted or modified NVIDIA hook": "Nedôveryhodný alebo zmenený spúšťací skript NVIDIA",
"Unused image removed from the cache:": "Nepoužívaný obraz odstránený z vyrovnávacej pamäte:",
"Unused images removed from the cache:": "Nepoužívané obrazy odstránené z vyrovnávacej pamäte:",
"Unused local loopback TCP port for this device:": "Voľný miestny TCP port spätnej slučky pre toto zariadenie:",
"Update": "Aktualizácia",
"Update Available": "Dostupná aktualizácia",
"Update Ceph repository (Only if using Ceph):": "Aktualizujte Ceph repozitár (iba ak používate Ceph):",
@@ -7855,6 +7935,7 @@
"Update the whole stack?": "Aktualizovať celú aplikáciu?",
"Update, modify or recreate one installed OCI instance": "Aktualizovať, upraviť alebo znova vytvoriť jednu nainštalovanú inštanciu OCI",
"Updated": "Aktualizované",
"Updated recipes since your last visit: {count}": "Aktualizované recepty od vašej poslednej návštevy: {count}",
"Updated sharedfiles group to GID: 101000": "Skupina sharedfiles bola aktualizovaná na GID: 101000",
"Updated stack checked": "Aktualizovaná aplikácia je skontrolovaná",
"Updated:": "Aktualizované:",
@@ -7918,6 +7999,7 @@
"Use a privileged LXC for NFS server/client workflows.": "Pre NFS server/klient používajte privilegovaný LXC.",
"Use a privileged LXC for Samba client/server workflows.": "Pre Samba klient/server používajte privilegovaný LXC.",
"Use a registry hostname, for example ghcr.io or registry.example.com:5000.": "Použite názov hostiteľa registra, napríklad ghcr.io alebo registry.example.com:5000.",
"Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time.": "Použite reverzný proxy server HTTPS s dôveryhodným certifikátom. Nextcloud aktualizujte vždy na nasledujúcu hlavnú verziu, žiadnu nepreskakujte.",
"Use an existing SSH private key file on this host": "Použiť existujúci súbor súkromného SSH kľúča na tomto hostovi",
"Use an existing keyfile": "Použiť existujúci keyfile",
"Use an image reference, for example ghcr.io/owner/app:latest.": "Použite odkaz na obraz, napríklad ghcr.io/owner/app:latest.",
@@ -7931,6 +8013,7 @@
"Use existing filesystem": "Použiť existujúci súborový systém",
"Use existing: mount without formatting": "Použiť existujúci: pripojiť bez formátovania",
"Use images only if the directory is on suitable storage.": "Typ images používajte iba vtedy, ak je priečinok na vhodnom úložisku.",
"Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.": "Pre /config a MariaDB použite spravované úložisko. Pre /data môžete vybrať adresár hostiteľa/NAS, ktorý vyžaduje samostatné zálohovanie.",
"Use mp1/mp2/... for extra mount points.": "Pre ďalšie mount pointy použite mp1/mp2/...",
"Use only when unprivileged containers cannot meet your needs": "Použite iba vtedy, keď neprivilegované kontajnery nestačia vašim potrebám",
"Use option 1 to add a local disk (as Proxmox storage and/or as a host mount).": "Použite možnosť 1 na pridanie lokálneho disku (ako úložisko Proxmoxu a/alebo ako mount na hostovi).",
@@ -8060,6 +8143,7 @@
"Variables": "Premenné",
"Variables the installation asks for:": "Premenné, ktoré požaduje inštalácia:",
"Vaultwarden Web Vault": "Vaultwarden Web Vault",
"Vector illustration in your browser": "Vektorová ilustrácia v prehliadači",
"Vector search engine with a built-in dashboard.": "Vektorový vyhľadávač so vstavaným panelom.",
"Verbose pool status": "Podrobný stav poolu",
"Verification": "Overenie",
@@ -8090,6 +8174,7 @@
"Versions shown belong to maintained NVIDIA branches that list your GPU PCI ID and are new enough to build against the running kernel. DKMS compilation is the final validation. The recommended version keeps the current branch, or uses the NVIDIA Production Branch on a fresh install.": "Zobrazené verzie patria do udržiavaných pobočiek NVIDIA, ktoré uvádzajú vaše ID PCI GPU a sú dostatočne nové na to, aby sa dali postaviť proti bežiacemu jadru. Kompilácia DKMS je konečným overením. Odporúčaná verzia ponecháva aktuálnu vetvu alebo používa NVIDIA Production Branch pri novej inštalácii.",
"VictoriaLogs": "VictoriaLogs",
"Video acceleration and object detection are independent choices; the installer does not write camera or detector YAML.": "Zrýchlenie videa a detekcia objektov sú nezávislé voľby. Inštalačný sprievodca nezapisuje nastavenia kamier ani detektorov do YAML.",
"Video editing in your browser": "Strih videa v prehliadači",
"Video transcoding acceleration": "Zrýchlenie priepustnosti videa",
"Video transcoding profile not implemented:": "Profil transkódovania videa nie je implementovaný:",
"View CIFS Mounts (pvesm + fstab)": "Zobraziť CIFS mounty (pvesm + fstab)",
@@ -8099,6 +8184,7 @@
"View Disk Storages": "Zobraziť diskové úložiská",
"View Mount Points": "Zobraziť mount pointy",
"View NFS Mounts (pvesm + fstab)": "Zobraziť NFS mounty (pvesm + fstab)",
"View USB/IP status": "Zobraziť stav USB/IP",
"View backup metadata": "Zobraziť metadáta zálohy",
"View current paths": "Zobraziť aktuálne cesty",
"View existing folders in /mnt": "Zobraziť existujúce priečinky v /mnt",
@@ -8199,12 +8285,17 @@
"Web access": "Adresa webového rozhrania",
"Web address of the AdGuard Home that receives the settings (e.g. http://192.168.1.3)": "Webová adresa AdGuard Home, ktorá prijíma nastavenia (napr. http://192.168.1.3)",
"Web address of the main AdGuard Home, whose settings are copied (e.g. http://192.168.1.2)": "Webová adresa hlavného AdGuard Home, ktorého nastavenia sú kopírované (napr. http://192.168.1.2)",
"Web dashboard": "Webový panel",
"Web dashboard and WebDAV": "Webový panel a WebDAV",
"Web interface": "Webové rozhranie",
"Web interface for Borg Backup repositories and jobs.": "Webové rozhranie na správu úložísk a úloh Borg Backup.",
"Web interface for managing 3D printers.": "Webové rozhranie na správu 3D tlačiarní.",
"Web interface to manage devices running Tasmota firmware.": "Webové rozhranie pre správu zariadení bežiacich na Tasmota firmware.",
"Web reverse proxy with an administration interface.": "Webový reverzný proxy server s administračným rozhraním.",
"WebCord can be summarized as a pack of security and privacy hardenings, Discord features reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, internal pages and wrapped https://discord.com page, designed to conform with ToS as much as it is possible (or hide the changes that might violate it from Discord's eyes).": "WebCord je klient obklopujúci stránku https://discord.com, ktorý zlepšuje bezpečnosť a súkromie, upravuje funkcie Discordu, obchádza chyby Electronu, Chromia a Discordu a pridáva štýly aj interné stránky. Snaží sa čo najviac dodržiavať podmienky používania alebo skryť pred Discordom úpravy, ktoré by ich mohli porušovať.",
"WebDAV": "WebDAV",
"WebDAV and dashboard password (leave empty to generate)": "Heslo pre WebDAV a panel (prázdne = generované)",
"WebDAV is available on container port 8080. Account linking is required before cloud file operations.": "WebDAV je dostupný na porte 8080 kontajnera. Pred prácou so súbormi v cloude je potrebné prepojiť účet.",
"Webgrabplus is a multi-site incremental xmltv epg grabber. It collects tv-program guide data from selected tvguide sites for your favourite channels.": "WebGrab+Plus priebežne získava elektronický programový sprievodca (EPG) vo formáte XMLTV z viacerých webov. Zhromažďuje televízny program vybraných staníc z podporovaných stránok.",
"Webservers & Proxies": "Webové servery a proxy",
"Website": "Webová stránka",
@@ -8262,6 +8353,7 @@
"Without a usable reset path, passthrough reliability is poor and VM": "Bez použiteľnej reset cesty je spoľahlivosť passthrough nízka a VM",
"Wizard cancelled": "Sprievodca zrušený",
"Wolfenstein: Blade of Agony is a story-driven WWII shooter inspired by Wolfenstein and Doom.": "Wolfenstein: Blade of Agony je príbehová strieľačka z druhej svetovej vojny inšpirovaná hrami Wolfenstein a Doom.",
"Word processing in your browser": "Spracovanie textu v prehliadači",
"Workflow automation tool": "Nástroj na automatizáciu pracovného toku",
"Working directory:": "Pracovný priečinok:",
"Works with LVM, ZFS, and BTRFS storage types": "Funguje s typmi úložísk LVM, ZFS a BTRFS",
@@ -8312,6 +8404,8 @@
"Your machine learning Env work with Jupyter Lab": "Prostredie strojového učenia s JupyterLab",
"Your next YouTube media manager": "Váš ďalší manažér médií YouTube",
"Your_spotify is a self-hosted application that tracks what you listen and offers you a dashboard to explore statistics about it! It's composed of a web server which polls the Spotify API every now and then and a web application on which you can explore your statistics.": "Your_spotify je aplikácia na vlastnom serveri, ktorá sleduje počúvanie hudby a zobrazuje štatistiky. Tvorí ju server pravidelne zisťujúci údaje cez Spotify API a webové rozhranie na ich prezeranie.",
"Z-Wave JS UI": "Z-Wave JS UI",
"Z-Wave JS UI admin login": "Prihlásenie správcu Z-Wave JS UI",
"ZFS ARC config removed (kernel defaults will apply on reboot)": "Nastavenie ZFS ARC bolo odstránené (predvolené hodnoty kernelu sa použijú po reštarte)",
"ZFS ARC maximum configured:": "Maximálna veľkosť ZFS ARC je nastavená na:",
"ZFS ARC optimization completed": "Optimalizácia ZFS ARC je dokončená",
@@ -8425,6 +8519,7 @@
"could not be compiled for kernel": "nepodarilo sa skompilovať pre jadro",
"could not validate NVIDIA; exit code": "nemohol potvrdiť NVIDIA; kód výstupu",
"cpuunits must be between 8 and 10000": "Hodnota cpuunits musí byť od 8 do 10000",
"curl -L -o /models/gemma-3-1b-it-Q4_K_M.gguf https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf": "curl -L -o /models/gemma-3-1b-it-Q4_K_M.gguf https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf",
"custom": "vlastné",
"custom dependency commands are not yet supported": "Vlastné príkazy závislosti ešte nie sú podporované",
"custom path(s) saved.": "uložených vlastných ciest.",
@@ -8631,6 +8726,7 @@
"kexec-tools is not installed or already removed.": "kexec-tools nie je nainštalovaný alebo už bol odstránený.",
"layers": "vrstvy",
"legacy .link file(s) to the ProxMenux-managed format": "staršie .link súbory do formátu spravovaného ProxMenuxom",
"llama.cpp shows every GGUF model saved in /models in its web UI and loads the one you choose.": "llama.cpp zobrazuje vo svojom webovom rozhraní všetky modely GGUF uložené v /models a načíta ten, ktorý si vyberiete.",
"log2ram completely removed from system": "log2ram bol úplne odstránený zo systému",
"main container of the application": "hlavný kontajner aplikácie",
"make cloned mount tree read-only": "nastavenie klonovaného stromu pripojenia iba na čítanie",
+96
View File
@@ -184,6 +184,7 @@
"A tunneling daemon by Cloudflare that safely exposes your web servers into the internet.": "En tunneldemon av Cloudflare som säkert avslöjar dina webbservrar på internet.",
"A unified email and collaboration server.": "En enhetlig server för e-post och samarbete.",
"A unified platform for logs, metrics and traces.": "En enhetlig plattform för loggar, mätvärden och spårningar.",
"A validating, recursive DNS resolver for your private network.": "En validerande, rekursiv DNS-resolver för ditt privata nätverk.",
"A versatile file conversion tool that supports multiple formats.": "Ett mångsidigt filkonverteringsverktyg som stöder flera format.",
"A visual tool for exploring and documenting database schemas.": "Ett visuellt verktyg för att utforska och dokumentera databasscheman.",
"A web GUI client of Project V which supports VMess, VLESS, SS, SSR, Trojan, Tuic and Juicity protocols": "En webb GUI klient av Project V som stöder VMess, VLESS, SS, SSR, Trojan, Tuic och Juicity protokoll",
@@ -245,6 +246,7 @@
"Aborted": "Avbruten",
"About to restore": "På väg att återställa",
"Absolute directory path to use as backup target:": "Absolut katalogsökväg att använda som mål för säkerhetskopiering:",
"Absolute path of the client SSH private key:": "Absolut sökväg till klientens privata SSH-nyckel:",
"Absolute path to a file or directory you want backed up:": "Absolut sökväg till en fil eller katalog som du vill säkerhetskopiera:",
"Acceleration": "Acceleration",
"Acceleration configuration cancelled": "Acceleration konfiguration inställd",
@@ -256,6 +258,7 @@
"Acceleration for llama.cpp": "Acceleration för llama.cpp",
"Accept routes from other nodes?": "Acceptera rutter från andra noder?",
"Accept this host monitoring profile?": "Acceptera denna värdövervakningsprofil?",
"Access Movistar and O2 Cloud from WebDAV clients and backup tools.": "Kom åt Movistar- och O2-molnet från WebDAV-klienter och säkerhetskopieringsverktyg.",
"Access Scope:": "Åtkomstomfång:",
"Access bridge": "Tillgång bridge",
"Access bridge for Immich": "Tillgångsbro för Immich",
@@ -410,6 +413,7 @@
"After the reboot, you will only be able to access the Proxmox host via:": "Efter omstarten kommer du bara att kunna komma åt Proxmox-värden via:",
"After this LXC → VM switch, reboot the host so the new binding state is applied cleanly.": "Efter denna LXC → VM-switch, starta om värden så att det nya bindningsläget tillämpas korrekt.",
"Agentless monitoring and observability platform.": "Agentlös plattform för övervakning och observerbarhet.",
"AirDC++ administrator": "AirDC++-administratör",
"Airsonic Advanced web interface": "Airsonic Advanced webbgränssnitt",
"Airsonic-advanced is a free, web-based media streamer, providing ubiquitious access to your music. Use it to share your music with friends, or to listen to your own music while at work. You can stream to multiple players simultaneously, for instance to one player in your kitchen and another in your living room.": "Airsonic-advanced är en gratis, webbaserad media streamer, som ger ubiquitious tillgång till din musik. Använd den för att dela din musik med vänner, eller för att lyssna på din egen musik på jobbet. Du kan strömma till flera spelare samtidigt, till exempel till en spelare i ditt kök och en annan i ditt vardagsrum.",
"Aliases added to .bashrc": "Alias har lagts till i .bashrc",
@@ -598,11 +602,15 @@
"Attention: Removing the subscription banner may cause issues in the web interface after a future update.": "Observera: Att ta bort prenumerationsbannern kan orsaka problem i webbgränssnittet efter en framtida uppdatering.",
"Audacity is an easy-to-use, multi-track audio editor and recorder. Developed by a group of volunteers as open source.": "Audacity är en lättanvänd, multi-track ljudredigerare och inspelare. Utvecklad av en grupp frivilliga som öppen källkod.",
"Audio device directory": "Ljudenhetskatalog",
"Audio recording and mixing in your browser": "Ljudinspelning och mixning i webbläsaren",
"Audiobookshelf is a self-hosted audiobook and podcast server.": "Audiobookshelf är en själv värd ljudbok och podcast server.",
"Audit completed. Press Enter to continue...": "Revision avslutad. Tryck på Enter för att fortsätta...",
"Audit socket disabled or not required": "Granskningsuttaget inaktiverat eller inte nödvändigt",
"Auth key is required.": "Auth-nyckel krävs.",
"Auth:": "Auth:",
"Authelia Web UI": "Authelias webbgränssnitt",
"Authelia administrator": "Authelia administratör",
"Authelia session cookie domain for this portal (for example example.com)": "Authelia sessionscookiedomän för denna portal (till exempel example.com)",
"Authentication": "Autentisering",
"Authentication & Security": "Autentisering och säkerhet",
"Authentication Error": "Autentiseringsfel",
@@ -612,6 +620,8 @@
"Authentication:": "Autentisering:",
"Authorization failed": "Auktorisering misslyckades",
"Authorization successful": "Auktoriseringen lyckades",
"Authorize a client SSH public key": "Auktorisera en klients offentliga SSH-nyckel",
"Authorize a dedicated client public key on the server first. The restricted USB/IP account cannot run a shell or forward other sockets. Verify the server host key before connecting; unknown keys are rejected.": "Auktorisera först en separat offentlig klientnyckel på servern. Det begränsade USB/IP-kontot kan inte starta ett skal eller vidarebefordra andra socklar. Verifiera serverns värdnyckel innan du ansluter; okända nycklar avvisas.",
"Authorize this key on the server": "Auktorisera denna nyckel på servern",
"Authorize via 'pct exec' (Borg server is an LXC on a PVE host I can SSH into)": "Auktorisera via 'pct exec' (Borg-servern är en LXC på en PVE-värd jag kan SSH till)",
"Authorized": "Auktoriserad",
@@ -642,6 +652,7 @@
"Available PVE Version": "Tillgänglig PVE-version",
"Available Shares:": "Tillgängliga andelar:",
"Available action": "Tillgänglig åtgärd",
"Available applications: {count}": "Tillgängliga appar: {count}",
"Available archives:": "Tillgängliga arkiv:",
"Available disks detected.": "Tillgängliga diskar har upptäckts.",
"Available host backups:": "Tillgängliga värdsäkerhetskopior:",
@@ -873,6 +884,7 @@
"Cannot write the image archive to {storage}. Check storage access and mount status.": "Kan inte skriva bildarkivet till {storage}. Kontrollera lagringsåtkomst och monteringsstatus.",
"Capabilities cannot be kept and all dropped at the same time": "Förmågor kan inte hållas och alla tappas samtidigt",
"Catalog options": "Katalogalternativ",
"Catalog refresh unavailable; using the local catalog.": "Katalogen kunde inte uppdateras; den lokala katalogen används.",
"Category": "Kategori",
"Caution: Maximum mode generates more heat.": "Varning: Maximalt läge genererar mer värme.",
"Central server for file and image backups.": "Central server för säkerhetskopiering av filer och bilder.",
@@ -1159,6 +1171,7 @@
"Compressing": "Komprimerar",
"Compression": "Kompression",
"Compression Tools": "Kompressionsverktyg",
"Computer-aided design and drafting in your browser": "CAD och teknisk ritning i webbläsaren",
"Concise output of logical volumes": "Kortfattad utdata av logiska volymer",
"Concise output of physical volumes": "Kortfattad utdata av fysiska volymer",
"Concise output of volume groups": "Kortfattad utdata av volymgrupper",
@@ -1289,6 +1302,7 @@
"Conflicting utilities removed": "Motstridiga verktyg har tagits bort",
"Connect Zigbee devices to MQTT with a browser-based setup interface.": "Anslut Zigbee-enheter till MQTT med ett webbaserat konfigurationsgränssnitt.",
"Connect a Coral Accelerator and try again.": "Anslut en Coral Accelerator och försök igen.",
"Connect a remote USB device": "Anslut en fjärransluten USB-enhet",
"Connect it, or remove it from the container in Proxmox (Resources), and run the recovery again.": "Anslut den, eller ta bort den från behållaren i Proxmox (Resurser), och kör återställningen igen.",
"Connect your devices and users together in your own secure virtual private network.": "Anslut dina enheter och användare tillsammans i ditt eget säkra virtuella privata nätverk.",
"Connect your devices into a secure WireGuard®-based overlay network with SSO, MFA and granular access controls.": "Anslut dina enheter till ett säkert WireGuard®-baserat överläggsnätverk med SSO, MFA och granulära åtkomstkontroller.",
@@ -1393,6 +1407,7 @@
"Controller + NVMe": "Styrenhet + NVMe",
"Controller + NVMe assignment will be written now and become active after host reboot.": "Tilldelningen av styrenhet + NVMe skrivs nu och aktiveras efter omstart av värden.",
"Controller + NVMe passthrough requires machine type q35. Skipping controller assignment.": "Styrenhets-/NVMe-passthrough kräver maskintypen q35. Hoppar över tilldelning av styrenheten.",
"Controller path on the Proxmox host; prefer /dev/serial/by-id/...": "Styrsökväg på Proxmox-värden;föredrar /dev/serial/by-id/...",
"Controller/NVMe Conflict Policy": "Konfliktpolicy för styrenhet/NVMe",
"Controller/NVMe already present in VM config": "Styrenhet/NVMe finns redan i VM-konfigurationen",
"Controller/NVMe already present in VM config (%s)": "Styrenhet/NVMe finns redan i VM-konfigurationen (%s)",
@@ -1927,6 +1942,7 @@
"Dgraph": "Dgraph",
"Diff: current system vs backup (--- system +++ backup)": "Diff: nuvarande system vs säkerhetskopia (--- system +++ säkerhetskopia)",
"Different host. Backup from:": "Annorlunda värd. Säkerhetskopiering från:",
"Direct Connect file sharing with a web interface": "Fildelning via Direct Connect med webbgränssnitt",
"Direct conversion completed for container": "Direkt konvertering slutförd för container",
"Directory Exists": "Katalog finns",
"Directory Not Empty": "Katalog inte tom",
@@ -1949,12 +1965,14 @@
"Directus administrator": "Directus-administratör",
"Disable NIC Offloading (Intel e1000e)": "Inaktivera NIC-avlastning (Intel e1000e)",
"Disable Secure Boot in the UEFI firmware and run the installer again. Nothing has been changed.": "Inaktivera Secure Boot i UEFI-firmware och kör installationsprogrammet igen. Inget har ändrats.",
"Disable USB/IP server": "Inaktivera USB/IP-servern",
"Disable autostart on conflicting VM": "Inaktivera autostart på VM i konflikt",
"Disable autostart on one VM to avoid startup conflicts.": "Inaktivera autostart på en virtuell dator för att undvika startkonflikter.",
"Disable job": "Inaktivera jobbet",
"Disable kernel audit messages (optional but recommended):": "Inaktivera kärngranskningsmeddelanden (valfritt men rekommenderas):",
"Disable onboot on affected VM(s)/CT(s)": "Inaktivera onboot på berörda virtuella dator(er)/CT(ar)",
"Disable portmapper/rpcbind": "Inaktivera portmapper/rpcbind",
"Disable the server and release all USB devices managed by ProxMenux? Saved selections are kept for the next enable.": "Inaktivera servern och frigör alla USB-enheter som hanteras av ProxMenux? Sparade val behålls till nästa aktivering.",
"Disabled": "Inaktiverad",
"Disabling High Availability services...": "Inaktiverar tjänster med hög tillgänglighet...",
"Disabling ZFS autotrim applied by ProxMenux...": "Inaktiverar ZFS autotrim som tillämpas av ProxMenux...",
@@ -2187,6 +2205,7 @@
"Enable Remote Desktop (RDP) before disabling the virtual display.": "Aktivera Remote Desktop (RDP) innan du inaktiverar den virtuella skärmen.",
"Enable SSD emulation for this disk?": "Vill du aktivera SSD-emulering för den här disken?",
"Enable TCP BBR/Fast Open control": "Aktivera TCP BBR/Fast Open-kontroll",
"Enable USB/IP server": "Aktivera USB/IP-servern",
"Enable VA-API transcoding and HDR10/Dolby Vision to SDR tone mapping": "Aktivera VA-API-transkodning och HDR10/Dolby Vision till SDR-tonkartläggning",
"Enable VA-API, hardware encoding and OpenCL tone mapping in Jellyfin": "Aktivera VA-API, hårdvarukodning och OpenCL tonkartläggning i Jellyfin",
"Enable VFIO IOMMU support": "Aktivera VFIO IOMMU-stöd",
@@ -3200,6 +3219,7 @@
"If pvesm path returned a DEVICE (LVM):": "Om pvesm path returnerade en ENHET (LVM):",
"If pvesm path returned a DIRECTORY (ZFS/BTRFS):": "Om pvesm path returnerade en KATALOG (ZFS/BTRFS):",
"If repositories error:": "Om förrådsfel:",
"If the USB/IP service stops unexpectedly, stop sharing while the device is still connected to release it. In rare cases only a host reboot releases it.": "Om USB/IP-tjänsten stoppas oväntat, sluta dela enheten medan den fortfarande är ansluten för att frigöra den. I sällsynta fall frigörs den bara genom en omstart av värden.",
"If the container had already been changed, its previous native backup is restored. Shared host directories are not reverted. The disks of the failed attempt are removed when the cleanup succeeds.": "Om behållaren redan hade ändrats, återställs dess tidigare inbyggda säkerhetskopia. Delade värdkataloger återställs inte. Diskarna för det misslyckade försöket tas bort när rensningen lyckas.",
"If the host freezes, remove hostpci entries from": "Om värden fryser, ta bort hostpci-poster från",
"If the image channel has a new version, the CT is stopped, backed up and verified, and replaced with the new image to update the container. If anything fails, the backup is restored.": "Om bildkanalen har en ny version stoppas CT, säkerhetskopieras och verifieras och ersätts med den nya bilden för att uppdatera behållaren. Om något misslyckas återställs säkerhetskopian.",
@@ -3340,6 +3360,7 @@
"Initial Stirling-PDF account": "Första Stirling-PDF-kontot",
"Initial Tandoor administrator": "Initial Tandoor administratör",
"Initial Umami administrator": "Umamis första administratör",
"Initial Z-Wave JS UI admin password": "Initialt Z-Wave JS UI administratörslösenord",
"Initial administrator created:": "Initial administratör skapad:",
"Initial administrator user": "Initial administratör användare",
"Initializing Borg repository if needed...": "Initierar Borg-arkivet om det behövs...",
@@ -3393,6 +3414,7 @@
"Install server packages inside CT:": "Installera serverpaket inuti CT:",
"Install terminal multiplexers": "Installera terminalmultiplexer",
"Install the Edge TPU runtime (libedgetpu1-std)": "Installera Edge TPU runtime (libedgetpu1-std)",
"Install the USB/IP dependencies from the configured Debian repositories?": "Installera USB/IP-beroendena från de konfigurerade Debian-paketförråden?",
"Install this image?": "Installera den här bilden?",
"Install with Cloud-Init script": "Installera med Cloud-Init-skript",
"Install with ISO from UUP Dump": "Installera med ISO från UUP Dump",
@@ -3525,6 +3547,7 @@
"Interface MTU": "Gränssnitt MTU",
"Interface Names (persistent)": "Gränssnittsnamn (beständig)",
"Interface Type": "Gränssnittstyp",
"Interface design and prototyping in your browser": "Gränssnittsdesign och prototyper i webbläsaren",
"Interface names will return to default systemd behavior.": "Gränssnittsnamn kommer att återgå till standardsystembeteende.",
"Interface type:": "Gränssnittstyp:",
"Interfaces configured": "Gränssnitt konfigurerade",
@@ -3582,6 +3605,7 @@
"Invalid check package:": "Ogiltigt checkpaket:",
"Invalid configuration path:": "Ogiltig konfigurationsväg:",
"Invalid consume/export volumes": "Ogiltiga konsum/exportvolymer",
"Invalid container device GID": "Ogiltigt enhets-GID i containern",
"Invalid container path:": "Invalid containerväg:",
"Invalid credential file path:": "Invalid credential filväg:",
"Invalid declarative entrypoint": "Invalid deklarativ ingång",
@@ -3740,6 +3764,7 @@
"Jupyter Lab (token only)": "Jupyter Lab (endast token)",
"JupyterLab": "JupyterLab",
"JupyterLab access token": "Åtkomsttoken för JupyterLab",
"KDE's twin-panel file manager in a browser-based desktop.": "KDE:s filhanterare med två paneler i ett webbläsarbaserat skrivbord.",
"KDF:": "KDF:",
"KROMA": "KROMA",
"KVM MSR options added to /etc/modprobe.d/kvm.conf": "KVM MSR-alternativ har lagts till i /etc/modprobe.d/kvm.conf",
@@ -3787,12 +3812,14 @@
"KiCad - A Cross Platform and Open Source Electronics Design Automation Suite.": "KiCad - En Cross Platform och Open Source Electronics Design Automation Suite.",
"Kimai has no default account. Enter the container with: pct enter {main_vmid}": "Kimai har inget standardkonto. Öppna ett skal i containern med: pct enter {main_vmid}",
"Kimai is a professional grade time-tracking application, free and open-source.": "Kimai är en professionell tidsspårningsapplikation, fri och öppen källkod.",
"KitchenOwl": "KitchenOwl",
"Kometa is a powerful tool designed to give you complete control over your media libraries. With Kometa, you can take your customization to the next level, with granular control over metadata, collections, overlays, and much more.": "Kometa är ett kraftfullt verktyg för att ge dig fullständig kontroll över dina mediebibliotek. Med Kometa kan du ta din anpassning till nästa nivå, med granulär kontroll över metadata, samlingar, överlagringar och mycket mer.",
"Kometa reads its configuration from /config/config.yml and the container only ships /config/config.yml.template. Copy the template to config.yml, fill in the required Plex and TMDb connections, then restart the container.": "Kometa läser sin konfiguration från /config/config.yml och behållaren endast fartyg /config/config.yml.template. Kopiera mallen till config.yml, fyll i required Plex och TMDb-anslutningar och starta sedan om behållaren.",
"Komga is a media server for your comics, mangas, BDs, magazines and eBooks.": "Komga är en mediaserver för dina serier, mangas, BD, tidskrifter och e-böcker.",
"Kopia Web UI": "Kopia-webbgränssnitt",
"Kopia Web UI login": "Inloggning till Kopias webbgränssnitt",
"Krita is a professional FREE and open source painting program. It is made by artists that want to see affordable art tools for everyone.": "Krita är ett professionellt gratis och öppen källkod målning program. Den är gjord av konstnärer som vill se prisvärda konstverktyg för alla.",
"Krusader Web UI": "Krusaders webbgränssnitt",
"LAN access to the kept containers (stack configuration incomplete):": "LAN tillgång till de bevarade behållarna (stack konfiguration ofullständig):",
"LAN address applied to the application URLs": "LAN-adress tillämpad på ansökningsadresserna",
"LLDAP": "LLDAP",
@@ -3873,9 +3900,11 @@
"Line to paste (single line, including \"command=...\" prefix):": "Rad att klistra in (en rad, inklusive \"command=...\" prefix):",
"LinkStack": "LinkStack",
"Linux Installation Options": "Linux installationsalternativ",
"Linux guest setup and migration notes": "Konfiguration av Linux-gäster och information om migrering",
"Linux/Mac path:": "Linux/Mac sökväg:",
"LinuxServer Jellyfin with optional GPU passthrough": "LinuxServer Jellyfin med valfri GPU genomgång",
"LinuxServer MariaDB requires a user, database and password": "LinuxServer MariaDB requires en användare, databas och lösenord",
"LinuxServer Nextcloud with MariaDB and Redis": "LinuxServer Nextcloud med MariaDB och Redis",
"List Available Disks": "Lista tillgängliga diskar",
"List IOMMU group mapping": "Lista IOMMU-gruppkartläggning",
"List NVMe devices": "Lista NVMe-enheter",
@@ -4020,6 +4049,7 @@
"Manage OCI stack": "Hantera OCI stack",
"Manage PBS encryption keyfile": "Hantera PBS-krypteringsnyckelfil",
"Manage Secure Gateway": "Hantera Secure Gateway",
"Manage a Z-Wave network from a web dashboard and WebSocket gateway.": "Hantera ett Z-Wave-nätverk från en webbinstrumentpanel och WebSocket-gateway.",
"Manage and inspect VM disk images": "Hantera och inspektera VM-diskavbildningar",
"Manage custom backup paths": "Hantera anpassade säkerhetskopieringsvägar",
"Manage custom paths (add / remove your folders)": "Hantera anpassade sökvägar (lägg till / ta bort dina mappar)",
@@ -4029,6 +4059,7 @@
"Manage local backup target": "Hantera lokalt mål för säkerhetskopiering",
"Manage private image registries.\nSaved credentials let ProxMenux access your private images.": "Hantera privata bildregister.\nSparade referenser låter ProxMenux komma åt dina privata bilder.",
"Manage registry accounts as root on the Proxmox node.": "Hantera registerkonton som root på Proxmox-noden.",
"Manage teams of AI agents from a web dashboard.": "Hantera team av AI-agenter från en webbpanel.",
"Managed disks must have backup enabled and a valid size": "Hanterade diskar måste ha backup aktiverad och en giltig storlek",
"Managed public route include is missing": "Konfigurationsfilen för de hanterade publika rutterna saknas",
"Managed public route installation failed": "Det gick inte att konfigurera de hanterade publika rutterna",
@@ -4134,6 +4165,7 @@
"Monitoring": "Övervakning",
"Monitoring & Analytics": "Övervakning och analys",
"Most common cause: the archive is corrupted (interrupted write, partial copy, or storage issue).": "Vanligaste orsaken: arkivet är skadat (avbruten skrivning, delvis kopiering eller lagringsproblem).",
"Motion graphics and compositing in your browser": "Rörlig grafik och komposition i webbläsaren",
"Mount Added Successfully:": "Montering har lagts till:",
"Mount CIFS share:": "Montera CIFS-andel:",
"Mount Configuration Summary:": "Sammanfattning av monteringskonfiguration:",
@@ -4293,6 +4325,7 @@
"NVIDIA (CUDA; official GPU image)": "NVIDIA (CUDA, officiell GPU-bild)",
"NVIDIA (NVDEC/CUDA)": "NVIDIA (NVDEC/CUDA)",
"NVIDIA (NVENC/NVDEC)": "NVIDIA (NVENC/NVDEC)",
"NVIDIA (Selkies rendering and NVENC)": "NVIDIA (Selkies-rendering och NVENC)",
"NVIDIA Actions": "NVIDIA-åtgärder",
"NVIDIA CPU hiding already configured": "NVIDIA CPU-döljning har redan konfigurerats",
"NVIDIA Container Toolkit": "NVIDIA Container Toolkit",
@@ -4376,6 +4409,7 @@
"Name or part of the option or of the application": "Namn eller del av alternativet eller applikationen",
"Name:": "Namn:",
"Named accounts need private mode. Stop the container, set public: false in /config/config.js, start it again and create each user with: pct exec <CTID> -- env THELOUNGE_HOME=/config s6-setuidgid abc thelounge add <user>": "Namngivna konton behöver privat läge. Stoppa behållaren, ställ in offentligt: falskt i /config/config.js, starta den igen och skapa varje användare med: pct exec <CTID> - env THELOUNGE_HOME=/config s6-setuidgid abc thelounge addera <user>",
"Native Borg is unavailable. Install the native borgbackup package on this host to use Borg backups.": "En inbyggd version av Borg är inte tillgänglig. Installera paketet borgbackup för värdens arkitektur för att använda Borg-säkerhetskopior.",
"Needed:": "Behövs:",
"Needs": "Kräver",
"Neither /etc/kernel/cmdline nor /etc/default/grub found.": "Varken /etc/kernel/cmdline eller /etc/default/grub hittades.",
@@ -4434,6 +4468,8 @@
"New Search": "Ny sökning",
"New VM:": "Ny VM:",
"New Virtual Machine": "Ny virtuell maskin",
"New applications ({count})": "Nya program ({count})",
"New applications since your last visit: {count}": "Nya appar sedan ditt senaste besök: {count}",
"New backup job": "Nytt säkerhetskopia jobb",
"New backups on this host will be unencrypted until a new keyfile is set up.": "Nya säkerhetskopior på denna värd kommer att vara okrypterade tills en ny nyckelfil ställs in.",
"New image compatible:": "Ny bildkompatibel:",
@@ -4449,6 +4485,7 @@
"Next Step Required": "Nästa steg krävs",
"Next Steps:": "Nästa steg:",
"Next step: stop that VM first, then run": "Nästa steg: stoppa den virtuella datorn först och kör sedan",
"Nextcloud Web UI": "Nextclouds webbgränssnitt",
"Nextcloud configuration cancelled": "Nextcloud konfiguration annullerad",
"Nextcloud gives you access to all your files wherever you are.": "Nextcloud ger dig tillgång till alla dina filer var du än är.",
"Nextcloud volume size in GB": "Nextcloud volymstorlek i GB",
@@ -4623,6 +4660,7 @@
"No duplicate IP addresses": "Inga dubbletter av IP-adresser",
"No duplicate repositories found": "Inga dubbletter av arkiv hittades",
"No eligible Controller/NVMe devices remain after SR-IOV filtering. Skipping.": "Inga lämpliga styrenhets-/NVMe-enheter återstår efter SR-IOV-filtreringen. Hoppar över.",
"No eligible USB devices found. Hubs, mass storage and network adapters are excluded.": "Inga lämpliga USB-enheter hittades. Hubbar, masslagringsenheter och nätverksadaptrar är undantagna.",
"No eligible controllers remain after SR-IOV filtering.": "Inga kvalificerade kontroller finns kvar efter SR-IOV-filtrering.",
"No encryption key is stored on this host. Choose how to set one up:": "Ingen krypteringsnyckel lagras på denna värd. Välj hur du ställer in en:",
"No exportable VM disks were found (CD-ROM/cloud-init are excluded).": "Inga exporterbara VM-diskar hittades (CD-ROM/cloud-init är undantagna).",
@@ -4707,6 +4745,7 @@
"No self-test log available for": "Ingen självtestlogg tillgänglig för",
"No server IP or hostname provided.": "Ingen server-IP eller värdnamn har angetts.",
"No share access test succeeded with guest authentication.": "Inget test av delad åtkomst lyckades med gästautentisering.",
"No shared devices are available on this server.": "Inga delade enheter är tillgängliga på denna server.",
"No shared media content.": "Inget delat medieinnehåll.",
"No shared mount detected. Applying standard local access.": "Inget delat fäste upptäcktes. Använder standard lokal åtkomst.",
"No shares configured.": "Inga delningar har konfigurerats.",
@@ -4896,6 +4935,8 @@
"Open the page of an application in the menu": "Öppna en applikations sida i menyn",
"Open the web address and create the first account: the daemon registers by itself and starts the first scan.": "Öppna webbadressen och skapa det första kontot: daemonen registrerar sig själv och startar den första skanningen.",
"Open the web address and create the password of the akadmin user in the first-run setup.": "Öppna webbadressen och skapa lösenordet för akadmin-användaren i den första körningen.",
"Open the web address and follow KitchenOwl’s onboarding to create the first account; no default account is configured.": "Öppna webbadressen och följ KitchenOwls introduktion för att skapa det första kontot;inget standardkonto är konfigurerat.",
"Open the web dashboard and link your Movistar/O2 account using its SMS flow.": "Öppna webbpanelen och koppla ditt Movistar/O2-konto med SMS-verifieringen.",
"Open-source AI-powered coding assistant": "Open-source AI-driven kodningsassistent",
"Open-source UI for building and debugging multi-agent and RAG applications": "Open-source UI för att bygga och debugga multi-agent- och RAG-applikationer",
"Open-source in-memory data store.": "Öppen datalagring i minnet.",
@@ -5018,6 +5059,7 @@
"Packages:": "Paket:",
"Packaging OVA file...": "Förpackning av OVA-fil...",
"Packing installer archive...": "Packar installationsarkiv...",
"Page layout and publishing in your browser": "Sidlayout och publicering i webbläsaren",
"PairDrop is a sublime alternative to AirDrop that works on all platforms. Send images, documents or text via peer to peer connection to devices in the same local network/Wi-Fi or to paired devices.": "PairDrop är ett sublimt alternativ till AirDrop som fungerar på alla plattformar. Skicka bilder, dokument eller text via peer till peer-anslutning till enheter i samma lokala nätverk / Wi-Fi eller till parade enheter.",
"Paperless configuration cancelled": "Papperslös konfiguration inställd",
"Paperless-ngx WebUI": "Paperless-ngx WebUI",
@@ -5036,6 +5078,7 @@
"Pass /dev/video12 to the LXC": "Pass /dev/video12 till LXC",
"Pass a host device to the LXC": "Passera en värdenhet till LXC",
"Pass the UPS to the LXC": "Skicka UPS:en till LXC",
"Pass through a Z-Wave USB or serial controller": "Passera genom en Z-Wave USB eller seriell styrenhet",
"Passing NVIDIA does not enable acceleration inside the application. The host needs NVIDIA Container Toolkit and a compatible image. Continue?": "Att passera NVIDIA möjliggör inte acceleration inuti applikationen. Värden behöver NVIDIA Container Toolkit och en kompatibel bild. Fortsätta?",
"Passkey-based identity provider for self-hosted apps.": "Identitetsleverantör med passkeys för självhostade appar.",
"Passphrase used to unlock the imported keyfile (leave blank if the keyfile is unencrypted / kdf=none):": "Lösenfras som används för att låsa upp den importerade nyckelfilen (lämna tomt om nyckelfilen är okrypterad / kdf=ingen):",
@@ -5101,6 +5144,7 @@
"Path of the Compose file": "Path of the Compose filen",
"Path of the oci-compose file": "Sökväg till oci-compose-filen",
"Path removed:": "Sökväg borttagen:",
"Path to the client SSH public key on this server:": "Sökväg till klientens offentliga SSH-nyckel på den här servern:",
"Path:": "Väg:",
"Paths applied:": "Tillämpade sökvägar:",
"Paths included in backup": "Sökvägar som ingår i säkerhetskopia",
@@ -5143,6 +5187,8 @@
"Personal finance management application": "Personlig ekonomi management ansökan",
"Personal media server for browsing and playing a local video library, with direct play and optional modules.": "Personlig medieserver för att bläddra bland och spela upp ett lokalt videobibliotek, med direktuppspelning och valfria moduler.",
"Photo and video library with optional GPU transcoding and machine learning": "Foto- och videobibliotek med valfri GPU-överkodning och maskininlärning",
"Photo editing in your browser": "Fotoredigering i webbläsaren",
"Photo library and RAW development in your browser": "Fotobibliotek och RAW-framkallning i webbläsaren",
"PhotoPrism": "PhotoPrism",
"Photofield": "Photofield",
"Phpmyadmin is a free software tool written in PHP, intended to handle the administration of MySQL over the Web. phpMyAdmin supports a wide range of operations on MySQL and MariaDB.": "Phpmyadmin är ett gratis mjukvaruverktyg skrivet i PHP, avsedd att hantera administrationen av MySQL över webben. phpMyAdmin stöder ett brett utbud av operations på MySQL och MariaDB.",
@@ -5235,6 +5281,7 @@
"Preparing the machine learning container for the new choice...": "Förbereder maskininlärningsbehållaren för det nya valet...",
"Preparing the recreation...": "Förbereda rekreationen...",
"Preparing the update...": "Förbereda uppdateringen...",
"Presentations and slide decks in your browser": "Presentationer och bildspel i webbläsaren",
"Preserving logs to /var/log.hdd before unmounting...": "Sparar loggar till /var/log.hdd innan avmontering...",
"Press 'q' to exit": "Tryck på 'q' för att avsluta",
"Press Ctrl+C to stop the server and return to menu.": "Tryck på Ctrl+C för att stoppa servern och återgå till menyn.",
@@ -5340,6 +5387,7 @@
"ProxMenux does not install them. The installation asks how to connect to them.": "ProxMenux installerar dem inte. Installationen frågar hur man ansluter till dem.",
"ProxMenux does not validate the contents; any keyfile your PBS accepts is accepted here.": "ProxMenux validerar inte innehållet; alla nyckelfiler som din PBS accepterar accepteras här.",
"ProxMenux files:": "ProxMenux filer:",
"ProxMenux generates the administrator password and shows it at the end of the installation. Change it after the first login.": "ProxMenux genererar administratörslösenordet och visar det i slutet av installationen. Ändra det efter första inloggningen.",
"ProxMenux logo applied": "ProxMenux-logotyp applicerad",
"ProxMenux only acts as a launcher — once the script starts, control leaves ProxMenux.": "ProxMenux fungerar bara som en start - när skriptet startar lämnar kontrollen ProxMenux.",
"ProxMenux saved it locally at:": "ProxMenux sparade det lokalt på:",
@@ -5395,6 +5443,7 @@
"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",
"Proxy address to reach the API (optional)": "Proxyadress för att nå API:t (valfritt)",
"Public HTTPS URL used to open this Authelia portal (for example https://auth.example.com)": "Offentlig HTTPS-URL som används för att öppna denna Authelia-portal (till exempel https://auth.example.com)",
"Public UDP port clients connect to": "Offentliga UDP-portklienter ansluter till",
"Public UDP port peers connect to": "Offentliga UDP-portpeers ansluter till",
"Public URL of phpMyAdmin when it is served behind a reverse proxy": "Public URL av phpMyAdmin när den serveras bakom en omvänd proxy",
@@ -5455,6 +5504,7 @@
"Re-running pre-check after repairs...": "Kör förkontroll igen efter reparationer...",
"Reachable": "Kan nåbar",
"Read an oci-compose from a file of this host": "Läs en oci-compose från en fil på denna värd",
"Read and edit PDF documents in your browser": "Läs och redigera PDF-dokument i webbläsaren",
"Read its Compose file from a file of this host": "Läs dess Compose-fil från en fil av denna värd",
"Read manga through a self-hosted server and web UI.": "Läs manga via en självhostad server och ett webbgränssnitt.",
"Read the link with pct console CTID on the Proxmox host, or from the Console panel of the container in the Proxmox web interface, then open the https://playit.gg/claim/ address it shows in a browser and sign in to playit.gg. Ctrl+a q leaves pct console.": "Läs länken med pct console CTID på Proxmox-värden, eller från Console-panelen i behållaren i Proxmox-webbgränssnittet, öppna sedan https://playit.gg/claim/adressen visas i en webbläsare och logga in för att spelait.gg. Ctrl+a q lämnar pct konsol.",
@@ -5558,8 +5608,10 @@
"Recreation prepared": "Rekreation förberedd",
"Recursive DNS resolver.": "Rekursiv DNS-resolver.",
"Recursive and authoritative DNS server.": "Rekursiv och auktoritativ DNS-server.",
"Redis locking is configured automatically. Existing Nextcloud configuration files are preserved.": "Fillåsning med Redis konfigureras automatiskt. Befintliga konfigurationsfiler för Nextcloud bevaras.",
"Redmine": "Redmine",
"Refresh APT index and verify repositories:": "Uppdatera APT-index och verifiera förråd:",
"Refresh catalog": "Uppdatera katalogen",
"Refresh the configured APT repositories and review the PBS package upgrade? Repository files will be preserved.": "Uppdatera de konfigurerade APT-paketförråden och granska PBS-paketuppgraderingen? Paketförrådens filer bevaras.",
"Refresh the index from the image sources": "Uppdatera indexet från avbildskällorna",
"Refresh token of the connector, from the Twingate admin console": "Uppdateringstoken för kontakten, från Twingate-administratörskonsolen",
@@ -5567,6 +5619,7 @@
"Refresh your browser to see changes (server restart may be required)": "Uppdatera din webbläsare för att se ändringar (serverns omstart kan krävas)",
"Refreshing apt cache...": "Uppdaterar apt cache...",
"Refreshing the NVIDIA runtime...": "Uppfriskande NVIDIA runtime...",
"Refreshing the application catalog...": "Uppdaterar appkatalogen...",
"Refusing an unexpected rootfs path:": "Vägrar en oväntad rootfs väg:",
"Regenerate the catalog templates": "Generera om katalogmallarna",
"Regenerate the template of one application": "Generera om mallen för en applikation",
@@ -5639,6 +5692,7 @@
"Remove Proxmox NFS storage:": "Ta bort Proxmox NFS-lagring:",
"Remove Proxmox iSCSI storage:": "Ta bort Proxmox iSCSI-lagring:",
"Remove Secure Gateway? State will be preserved.": "Ta bort Secure Gateway? Staten kommer att bevaras.",
"Remove a remote USB connection": "Ta bort en fjärransluten USB-anslutning",
"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 gasket DKMS-versioner",
@@ -5659,6 +5713,7 @@
"Remove the lock left on a container by an interrupted task": "Ta bort låset som en avbruten uppgift lämnat på en container",
"Remove the saved credentials for {registry}?\nRunning apps will keep working.": "Ta bort de sparade referenserna för {registry}?\nAppar som körs fortsätter att fungera.",
"Remove the unprivileged flag from configuration:": "Ta bort den oprivilegierade flaggan från konfigurationen:",
"Remove this connection and detach its USB device?": "Ta bort denna anslutning och koppla från dess USB-enhet?",
"Remove unused packages and their config": "Ta bort oanvända paket och deras konfiguration",
"Remove: delete the application and its containers": "Ta bort: ta bort programmet och dess behållare",
"Removed": "Borttagen",
@@ -5881,9 +5936,11 @@
"Run mode: Unattended": "Körläge: Oövervakad",
"Run now": "Kör nu",
"Run security audit now": "Kör säkerhetsgranskning nu",
"Run the client inside the Linux VM that needs the USB device. Install usbip, openssh-client and kmod, then copy usbip_manager.py to the same path as on the server. Configure key authentication and verify the server host key before adding a connection. The client uses the guest kernel and can reconnect after migration while the physical USB device stays on the server. Unprivileged LXC and Home Assistant OS need their own kernel/device or add-on setup. A physical device supports one attached client at a time.": "Kör klienten i den Linux-VM som behöver USB-enheten. Installera usbip, openssh-client och kmod och kopiera sedan usbip_manager.py till samma sökväg som på servern. Konfigurera nyckelautentisering och verifiera serverns värdnyckel innan du lägger till en anslutning. Klienten använder gästens kärna och kan återansluta efter migrering medan den fysiska USB-enheten stannar på servern. Oprivilegierade LXC och Home Assistant OS behöver en egen konfiguration av kärna, enheter eller tillägg. En fysisk enhet kan bara vara ansluten till en klient åt gången.",
"Run the following inside the VM:": "Kör följande inuti den virtuella datorn:",
"Run the release-channel switch from an SSH session or the Proxmox host console with:": "Kör release-kanalväxeln från en SSH-session eller Proxmox-värdkonsolen med:",
"Run the update from an SSH session or the Proxmox host console with:": "Kör uppdateringen från en SSH-session eller Proxmox-värdkonsolen med:",
"Run this menu as root.": "Kör denna meny som root.",
"Run this operation as root.": "Kör denna åtgärd som root.",
"Run upgrade checklist script:": "Kör skript för uppgraderingschecklista:",
"Running": "Spring",
@@ -6108,6 +6165,7 @@
"Select a new language for the menu:": "Välj ett nytt språk för menyn:",
"Select a post-installation script:": "Välj ett efterinstallationsskript:",
"Select a pre-configured Linux VM script to execute:": "Välj ett förkonfigurerat Linux VM-skript att köra:",
"Select a saved USB/IP device:": "Välj en sparad USB/IP-enhet:",
"Select a script or action:": "Välj ett skript eller en åtgärd:",
"Select a share to delete:": "Välj en delning att radera:",
"Select a specific Coral or USB node, not the whole /dev": "Välj en specifik Coral eller USB-nod, inte hela/dev",
@@ -6185,6 +6243,7 @@
"Select the Linux distribution to install:": "Välj Linux-distributionen att installera:",
"Select the NAS system to install:": "Välj det NAS-system som ska installeras:",
"Select the NVIDIA driver version to install:": "Välj NVIDIA-drivrutinsversionen att installera:",
"Select the USB device to share:": "Välj USB-enheten som ska delas:",
"Select the VM to add the GPU to:": "Välj den virtuella datorn för att lägga till GPU:n:",
"Select the VM to which you want to add disks:": "Välj den virtuella datorn som du vill lägga till diskar till:",
"Select the VM where you want to import the disk image:": "Välj den virtuella datorn där du vill importera skivavbildningen:",
@@ -6209,6 +6268,7 @@
"Select the parent job to attach to:": "Välj det överordnade jobbet som ska bifogas:",
"Select the paths to restore (one per backup entry):": "Välj sökvägarna som ska återställas (en per säkerhetskopia):",
"Select the privileged LXC container to convert:": "Välj den privilegierade LXC-behållaren att konvertera:",
"Select the remote USB device:": "Välj den fjärranslutna USB-enheten:",
"Select the storage that will receive the backups:": "Välj lagringsutrymmet som ska ta emot säkerhetskopiorna:",
"Select the storage volume for disk import:": "Välj lagringsvolym för diskimport:",
"Select the sync interval (in hours):": "Välj synkroniseringsintervall (i timmar):",
@@ -6258,6 +6318,7 @@
"Self-hosted file sync and sharing.": "Självhostad filsynkronisering och delning.",
"Self-hosted file toolkit for images, video, audio, PDFs, and files": "Självvärd filverktyg för bilder, video, ljud, PDF-filer och filer",
"Self-hosted forms and workflows.": "Självhostade formulär och arbetsflöden.",
"Self-hosted grocery list and recipe manager": "Self-hosted inköpslista och recept manager",
"Self-hosted household plant-care tracker with reminders, photos, and multiple user accounts.": "Självhostad skötselapp för krukväxter med påminnelser, foton och flera användarkonton.",
"Self-hosted image-hosting service with authenticated uploads, image processing, public links, and local storage.": "Självhostad bildtjänst med autentiserade uppladdningar, bildbehandling, offentliga länkar och lokal lagring.",
"Self-hosted internet archiving solution": "Självhäftad internetarkiveringslösning",
@@ -6294,6 +6355,7 @@
"Server IDs to test against, separated by commas (optional)": "Server-ID:n att testa mot, separerade med kommatecken (valfritt)",
"Server IP/hostname is correct": "Serverns IP/värdnamn är korrekt",
"Server IP:": "Server IP:",
"Server SSH port:": "Serverns SSH-port:",
"Server is accessible:": "Servern är tillgänglig:",
"Server is online": "Servern är online",
"Server is running": "Servern körs",
@@ -6355,6 +6417,7 @@
"Share Access Error": "Dela åtkomstfel",
"Share Name": "Dela namn",
"Share Options": "Delningsalternativ",
"Share a local USB device": "Dela en lokal USB-enhet",
"Share added successfully.": "Delningen har lagts till.",
"Share deleted and Samba service restarted.": "Delningen raderades och Samba-tjänsten startade om.",
"Share exists:": "Delning finns:",
@@ -6362,6 +6425,7 @@
"Share name:": "Dela namn:",
"Share not found on server:": "Delningen hittades inte på servern:",
"Share path:": "Dela sökväg:",
"Share selected USB devices through SSH, or connect this Linux machine to a USB/IP server.": "Dela valda USB-enheter via SSH eller anslut denna Linux-dator till en USB/IP-server.",
"Share updated successfully.": "Delningen har uppdaterats.",
"Share:": "Dela:",
"ShareCoveX panel": "ShareCoveX panel",
@@ -6452,6 +6516,7 @@
"Simple and easy to use DDNS": "Enkelt och enkelt att använda DDNS",
"Simple self-hosted file sharing.": "Enkel självhostad fildelning.",
"Single GPU Warning": "Varning för enkel GPU",
"Single sign-on and multi-factor authentication": "Enkel inloggning och multifaktorautentisering",
"Single target found — selected automatically:": "Enstaka mål hittades — väljs automatiskt:",
"Single-node log storage and query UI.": "Gränssnitt för logglagring och loggsökning på en enda nod.",
"Single-node observability database for metrics, logs and traces.": "Observabilitetsdatabas med en nod för mätvärden, loggar och spår.",
@@ -6520,7 +6585,9 @@
"Specific subnet (enter manually)": "Specifikt subnät (skriv in manuellt)",
"Speedtest Tracker web interface": "Speedtest Tracker webbgränssnitt",
"Speedtest-tracker is a self-hosted internet performance tracking application that runs speedtest checks against Ookla's Speedtest service.": "Speedtest-tracker är en självhäftad internetprestationsspårningsapplikation som kör snabbaste kontroller mot Ooklas Speedtest-tjänst.",
"Spoolman web interface": "Spoolman webbgränssnitt",
"Spotube is an open source, cross-platform Spotify client compatible across multiple platforms utilizing Spotify's data API and YouTube, Piped.video or JioSaavn as an audio source, eliminating the need for Spotify Premium": "Spotube är en öppen källkod, plattform Spotify klient kompatibel över flera plattformar som använder Spotifys data API och YouTube, Piped. video eller JioSaavn som ljudkälla, vilket eliminerar behovet av Spotify Premium",
"Spreadsheets in your browser": "Kalkylblad i webbläsaren",
"Sshwifty": "Sshwifty",
"Sshwifty web access (password only)": "Sshwifty-webbåtkomst (endast lösenord)",
"Stable (main branch)": "Stabil (huvudgren)",
@@ -6627,6 +6694,8 @@
"Still has issues": "Har fortfarande problem",
"Stop - shuts the guest down during backup": "Stopp - stänger av gästen under säkerhetskopiering",
"Stop it first and run this option again.": "Stoppa det först och kör det här alternativet igen.",
"Stop sharing a USB device": "Sluta dela en USB-enhet",
"Stop sharing this device? An attached remote client will disconnect.": "Sluta dela denna enhet? En ansluten fjärrklient kommer att kopplas från.",
"Stop that VM, then choose:": "Stoppa den VM och välj sedan:",
"Stop the CT, unmount the disk on the HOST, and remount with:": "Stoppa CT, avmontera disken på HOST och montera om med:",
"Stop the VM/CT before formatting this disk.": "Stoppa VM/CT innan du formaterar denna disk.",
@@ -6982,6 +7051,7 @@
"The container could not be removed automatically:": "Behållaren kunde inte tas bort automatiskt:",
"The container could not be started:": "Behållaren kunde inte startas:",
"The container creation does not match the prepared instance": "Behållarens skapelse matchar inte den förberedda instansen",
"The container device settings changed since the last recorded operation": "Inställningarna för enheten i containern har ändrats sedan den senaste registrerade åtgärden",
"The container devices do not match the saved record": "Container-enheterna matchar inte det sparade rekordet",
"The container did not stop to update its persistent configuration:": "Behållaren slutade inte uppdatera sin ihållande konfiguration:",
"The container did not stop; its disks are not touched": "Behållaren slutade inte; dess diskar rörs inte",
@@ -7263,6 +7333,7 @@
"The record no longer belongs to this operation": "Skivan tillhör inte längre denna operation",
"The record of a member was replaced; the assembly is not resumed": "En medlems rekord ersattes; församlingen återupptas inte.",
"The record or diagnosis could not be completed; no update was run.": "Rekordet eller diagnosen kunde inte slutföras; ingen uppdatering kördes.",
"The recorded container device GID does not match its configuration": "Det registrerade enhets-GID:t i containern stämmer inte med konfigurationen",
"The recovery did not complete. Review the log and choose \"Recover\" again for this container in the OCI management menu.": "Återhämtningen slutfördes inte. Granska loggen och välj \"Recover\" igen för den här behållaren i OCI-hanteringsmenyn.",
"The recovery did not complete. Review the log and choose \"{choice}\" again for this container in the OCI management menu.": "Återställningen slutfördes inte. Granska loggen och välj \"{choice}\" igen för den här containern i OCI-hanteringsmenyn.",
"The registry authentication file is invalid; it was not changed.": "Registerautentiseringsfilen är ogiltig; det ändrades inte.",
@@ -7330,6 +7401,7 @@
"The selected Intel GPU has non-FLR reset support and unknown subtype": "Den valda Intel GPU:n har stöd för icke-FLR-återställning och okänd undertyp",
"The selected Intel GPU is currently in power state D3cold": "Den valda Intel GPU:n är för närvarande i strömtillstånd D3cold",
"The selected Intel render device does not exist:": "Den valda Intel render-enheten finns inte:",
"The selected USB device will become unavailable to local applications and guests. Only one remote client can use it at a time. Share this device?": "Den valda USB-enheten blir otillgänglig för lokala program och gäster. Bara en fjärrklient kan använda den åt gången. Dela denna enhet?",
"The selected VM": "Den valda virtuella datorn",
"The selected VM is running.": "Den valda virtuella datorn körs.",
"The selected base folder does not exist and could not be created:": "Den valda basmappen finns inte och kunde inte skapas:",
@@ -7417,6 +7489,7 @@
"Then bind-mount to container": "Bind-montera sedan till behållaren",
"Then change the VM display to none (vga: none) when the guest is stable.": "Ändra sedan VM-skärmen till ingen (vga: ingen) när gästen är stabil.",
"Then change the VM display to none (vga: none) when the system is stable.": "Ändra sedan VM-skärmen till ingen (vga: ingen) när systemet är stabilt.",
"Then restart the container so the new model appears in the list.": "Starta sedan om containern så att den nya modellen visas i listan.",
"Then run this option again:": "Kör sedan det här alternativet igen:",
"Then update /etc/fstab on the host with the same options.": "Then update /etc/fstab on the host with the same options.",
"There are extra disks or bind mounts outside the journal; the rootfs is not replaced": "Det finns extra diskar eller binda fästen utanför tidskriften; rootfs ersätts inte",
@@ -7464,6 +7537,7 @@
"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 Frigate.",
"This container is managed by high availability. Remove ct:{vmid} from HA (Datacenter → HA, or ha-manager remove ct:{vmid}), repeat the operation and add it back to HA with the same settings.": "Den här containern hanteras av hög tillgänglighet. Ta bort ct:{vmid} från HA (Datacenter → HA, eller ha-manager remove ct:{vmid}), upprepa åtgärden och lägg sedan tillbaka den i HA med samma inställningar.",
"This container is not a member of a multi-container application": "Den här behållaren är inte medlem i ett program för flera behållare",
"This container is not a registered OCI instance.": "Denna behållare är inte en registrerad OCI-instans.",
"This container was restored or came back from another host after its record on this host was written. Open this menu again to recover it; nothing was changed.": "Den här behållaren återställdes eller kom tillbaka från en annan värd efter att dess post på denna värd skrevs. Öppna den här menyn igen för att återställa den; ingenting ändrades.",
@@ -7582,6 +7656,7 @@
"Tip: You can install the QEMU Guest Agent inside the VM with:": "Tips: Du kan installera QEMU Guest Agent inuti den virtuella datorn med:",
"Tip: zfs set acltype=posixacl xattr=sa <pool>/<dataset> enables full ACL support.": "Tips: zfs set acltype=posixacl xattr=sa <pool>/<dataset> möjliggör fullt ACL-stöd.",
"Tmpfs size in MiB for": "Tmpfs storlek i MiB för",
"To add a model, open the console of the container in Proxmox and download it into /models, for example:": "Om du vill lägga till en modell öppnar du containerns konsol i Proxmox och laddar ned den till /models, till exempel:",
"To allow LXC write access, change the NFS export on the server to include:": "För att tillåta LXC-skrivåtkomst, ändra NFS-exporten på servern så att den inkluderar:",
"To apply it to the current shell now, run:": "För att använda den i den aktuella shellsessionen nu, kör:",
"To assign VFs to VMs or LXCs, edit the configuration manually via the Proxmox web interface. The Physical Function will remain bound to the native driver.": "För att tilldela VF:er till virtuella datorer eller LXC:er, redigera konfigurationen manuellt via Proxmox webbgränssnitt. Den fysiska funktionen förblir bunden till den ursprungliga drivrutinen.",
@@ -7621,6 +7696,7 @@
"Total routes": "Totalt antal rutter",
"Total size:": "Total storlek:",
"Toxiproxy": "Toxiproxy",
"Track 3D printer filament spools and usage.": "Spåra 3D-skrivarens filamentspolar och användning.",
"Track movies, television, anime and games you want to enjoy.": "Håll koll på filmer, tv-serier, anime och spel som du vill se eller spela.",
"Track subscriptions and recurring expenses.": "Håll koll på prenumerationer och återkommande utgifter.",
"Track your music listening history on your own server.": "Följ din musikhistorik på din egen server.",
@@ -7665,6 +7741,9 @@
"USB drives mounted now:": "USB-enheter monterade nu:",
"USB libedgetpu1": "USB libedgetpu1",
"USB or serial device node": "USB eller seriell enhetsnod",
"USB/IP configuration updated. Open status to check the connection.": "USB/IP-konfigurationen har uppdaterats. Öppna status för att kontrollera anslutningen.",
"USB/IP over SSH": "USB/IP via SSH",
"USB/IP server IP address or DNS hostname:": "USB/IP-serverns IP-adress eller DNS-värdnamn:",
"UUP Dump script not found.": "UUP Dump-skript hittades inte.",
"UUp Dump ISO creator Custom": "UUp Dump ISO-skapare Anpassad",
"Ubooquity is a free, lightweight and easy-to-use home server for your comics and ebooks. Use it to access your files from anywhere, with a tablet, an e-reader, a phone or a computer.": "Ubooquity är en gratis, lätt och lättanvänd hemserver för dina serier och e-böcker. Använd den för att komma åt dina filer var som helst, med en surfplatta, en e-läsare, en telefon eller en dator.",
@@ -7821,6 +7900,7 @@
"Untrusted or modified NVIDIA hook": "Untrusted eller modifierad NVIDIA hook",
"Unused image removed from the cache:": "Oanvänd bild bort från cache:",
"Unused images removed from the cache:": "Oanvända bilder som tagits bort från cache:",
"Unused local loopback TCP port for this device:": "Ledig lokal TCP-port på loopback för denna enhet:",
"Update": "Uppdatering",
"Update Available": "Uppdatering tillgänglig",
"Update Ceph repository (Only if using Ceph):": "Uppdatera Ceph arkiv (endast om du använder Ceph):",
@@ -7855,6 +7935,7 @@
"Update the whole stack?": "Uppdatera hela stacken?",
"Update, modify or recreate one installed OCI instance": "Uppdatera, ändra eller återskapa en installerad OCI-instans",
"Updated": "Uppdaterad",
"Updated recipes since your last visit: {count}": "Uppdaterade recept sedan ditt senaste besök: {count}",
"Updated sharedfiles group to GID: 101000": "Uppdaterad sharedfiles-grupp till GID: 101000",
"Updated stack checked": "Uppdaterad stack kontrollerad",
"Updated:": "Uppdaterad:",
@@ -7918,6 +7999,7 @@
"Use a privileged LXC for NFS server/client workflows.": "Använd en privilegierad LXC för NFS-server/klient-arbetsflöden.",
"Use a privileged LXC for Samba client/server workflows.": "Använd en privilegierad LXC för Samba klient/server arbetsflöden.",
"Use a registry hostname, for example ghcr.io or registry.example.com:5000.": "Använd ett registervärdnamn, till exempel ghcr.io eller registry.example.com:5000.",
"Use a trusted HTTPS reverse proxy. Upgrade Nextcloud one major version at a time.": "Använd en omvänd HTTPS-proxy med ett betrott certifikat. Uppgradera Nextcloud till nästa huvudversion utan att hoppa över någon.",
"Use an existing SSH private key file on this host": "Använd en befintlig privat SSH-nyckelfil på denna värd",
"Use an existing keyfile": "Använd en befintlig nyckelfil",
"Use an image reference, for example ghcr.io/owner/app:latest.": "Använd en bildreferens, till exempel ghcr.io/owner/app:latest.",
@@ -7931,6 +8013,7 @@
"Use existing filesystem": "Använd befintligt filsystem",
"Use existing: mount without formatting": "Använd befintlig: montera utan formatering",
"Use images only if the directory is on suitable storage.": "Använd endast bilder om katalogen finns på lämplig lagring.",
"Use managed storage for /config and MariaDB. A host/NAS directory can be selected for /data and needs a separate backup.": "Använd hanterad lagring för /config och MariaDB. För /data kan du välja en katalog på värden/NAS som behöver säkerhetskopieras separat.",
"Use mp1/mp2/... for extra mount points.": "Använd mp1/mp2/... för extra monteringspunkter.",
"Use only when unprivileged containers cannot meet your needs": "Använd endast när oprivilegierade behållare inte kan uppfylla dina behov",
"Use option 1 to add a local disk (as Proxmox storage and/or as a host mount).": "Använd alternativ 1 för att lägga till en lokal disk (som Proxmox-lagring och/eller som värdmontering).",
@@ -8060,6 +8143,7 @@
"Variables": "Variables",
"Variables the installation asks for:": "Variabler som installationen begär:",
"Vaultwarden Web Vault": "Vaultwarden Web Vault",
"Vector illustration in your browser": "Vektorillustration i webbläsaren",
"Vector search engine with a built-in dashboard.": "Vektorsökmotor med inbyggd kontrollpanel.",
"Verbose pool status": "Utförlig poolstatus",
"Verification": "Kontroll",
@@ -8090,6 +8174,7 @@
"Versions shown belong to maintained NVIDIA branches that list your GPU PCI ID and are new enough to build against the running kernel. DKMS compilation is the final validation. The recommended version keeps the current branch, or uses the NVIDIA Production Branch on a fresh install.": "Versioner som visas tillhör underhållna NVIDIA-grenar som listar ditt GPU PCI-ID och är tillräckligt nya för att bygga mot den körande kärnan. DKMS kompilering är den slutliga valideringen. Den rekommenderade versionen behåller den aktuella grenen eller använder NVIDIA Production Branch på en nyinstallation.",
"VictoriaLogs": "VictoriaLogs",
"Video acceleration and object detection are independent choices; the installer does not write camera or detector YAML.": "Videoacceleration och objektdetektering är oberoende val; installatören skriver inte kamera eller detektor YAML.",
"Video editing in your browser": "Videoredigering i webbläsaren",
"Video transcoding acceleration": "Videoöverskridande acceleration",
"Video transcoding profile not implemented:": "Videokodningsprofilen har inte implementerats:",
"View CIFS Mounts (pvesm + fstab)": "Visa CIFS-fästen (pvesm + fstab)",
@@ -8099,6 +8184,7 @@
"View Disk Storages": "Visa disklagringar",
"View Mount Points": "Se Mount Points",
"View NFS Mounts (pvesm + fstab)": "Visa NFS-fästen (pvesm + fstab)",
"View USB/IP status": "Visa USB/IP-status",
"View backup metadata": "Visa metadata för säkerhetskopiering",
"View current paths": "Visa aktuella vägar",
"View existing folders in /mnt": "Visa befintliga mappar i /mnt",
@@ -8199,12 +8285,17 @@
"Web access": "Web access",
"Web address of the AdGuard Home that receives the settings (e.g. http://192.168.1.3)": "Webbadress för AdGuard Home som tar emot inställningarna (t.ex. http://192.168.1.3)",
"Web address of the main AdGuard Home, whose settings are copied (e.g. http://192.168.1.2)": "Webbadressen för AdGuard Home, vars inställningar kopieras (t.ex. http://192.168.1.2)",
"Web dashboard": "Webbpanel",
"Web dashboard and WebDAV": "Webbpanel och WebDAV",
"Web interface": "Webbgränssnitt",
"Web interface for Borg Backup repositories and jobs.": "Webbgränssnitt för Borg Backup-arkiv och jobb.",
"Web interface for managing 3D printers.": "Webbgränssnitt för hantering av 3D-skrivare.",
"Web interface to manage devices running Tasmota firmware.": "Webbgränssnitt för att hantera enheter som kör Tasmota firmware.",
"Web reverse proxy with an administration interface.": "Omvänd proxy för webben med administrationsgränssnitt.",
"WebCord can be summarized as a pack of security and privacy hardenings, Discord features reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, internal pages and wrapped https://discord.com page, designed to conform with ToS as much as it is possible (or hide the changes that might violate it from Discord's eyes).": "WebCord kan sammanfattas som ett paket av säkerhets- och sekretesshärdningar, Discord-funktioner reimplementations, Electron / Chromium / Discord bugs workarounds, stylesheets, interna sidor och wrapped https://discord.com sida, utformad för att överensstämma med ToS så mycket som möjligt (eller dölja de förändringar som kan bryta mot det från Discords ögon).",
"WebDAV": "WebDAV",
"WebDAV and dashboard password (leave empty to generate)": "Lösenord för WebDAV och panelen (tom = genererat)",
"WebDAV is available on container port 8080. Account linking is required before cloud file operations.": "WebDAV är tillgängligt på containerns port 8080. Kontot måste kopplas innan du arbetar med filerna i molnet.",
"Webgrabplus is a multi-site incremental xmltv epg grabber. It collects tv-program guide data from selected tvguide sites for your favourite channels.": "Webgrabplus är en multi-site inkrementell xmltv epg grabber. Det samlar in tv-programguide data från utvalda tvguide webbplatser för dina favoritkanaler.",
"Webservers & Proxies": "Webbservrar och proxyservrar",
"Website": "Webbplats",
@@ -8262,6 +8353,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",
"Wizard cancelled": "Wizard avbruten",
"Wolfenstein: Blade of Agony is a story-driven WWII shooter inspired by Wolfenstein and Doom.": "Wolfenstein: Blade of Agony är en story-driven WWII skytt inspirerad av Wolfenstein och Doom.",
"Word processing in your browser": "Ordbehandling i webbläsaren",
"Workflow automation tool": "Workflow automation verktyg",
"Working directory:": "Arbetskatalog:",
"Works with LVM, ZFS, and BTRFS storage types": "Fungerar med LVM, ZFS och BTRFS lagringstyper",
@@ -8312,6 +8404,8 @@
"Your machine learning Env work with Jupyter Lab": "Din maskininlärning Env arbetar med Jupyter Lab",
"Your next YouTube media manager": "Din nästa YouTube Media Manager",
"Your_spotify is a self-hosted application that tracks what you listen and offers you a dashboard to explore statistics about it! It's composed of a web server which polls the Spotify API every now and then and a web application on which you can explore your statistics.": "Your_spotify är en egen värd program som spårar vad du lyssnar och erbjuder dig en instrumentpanel för att utforska statistik om det! Den består av en webbserver som undersöker Spotify API då och då och en webbapplikation där du kan utforska din statistik.",
"Z-Wave JS UI": "Z-Wave JS UI",
"Z-Wave JS UI admin login": "Administratörsinloggning för Z-Wave JS UI",
"ZFS ARC config removed (kernel defaults will apply on reboot)": "ZFS ARC-konfigurationen togs bort (kärnans standardinställningar gäller vid omstart)",
"ZFS ARC maximum configured:": "ZFS ARC maximalt konfigurerat:",
"ZFS ARC optimization completed": "ZFS ARC-optimering slutförd",
@@ -8425,6 +8519,7 @@
"could not be compiled for kernel": "kunde inte kompileras för kärnan",
"could not validate NVIDIA; exit code": "kan inte validera NVIDIA; exitkod",
"cpuunits must be between 8 and 10000": "cpuunits måste vara mellan 8 och 10000",
"curl -L -o /models/gemma-3-1b-it-Q4_K_M.gguf https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf": "curl -L -o /models/gemma-3-1b-it-Q4_K_M.gguf https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf",
"custom": "anpassade",
"custom dependency commands are not yet supported": "Anpassade beroendekommandon stöds ännu inte",
"custom path(s) saved.": "anpassade sökvägar har sparats.",
@@ -8631,6 +8726,7 @@
"kexec-tools is not installed or already removed.": "kexec-tools är inte installerat eller redan borttaget.",
"layers": "Lager",
"legacy .link file(s) to the ProxMenux-managed format": "äldre .link-fil(er) till det ProxMenux-hanterade formatet",
"llama.cpp shows every GGUF model saved in /models in its web UI and loads the one you choose.": "llama.cpp visar alla GGUF-modeller som sparats i /models i sitt webbgränssnitt och läser in den du väljer.",
"log2ram completely removed from system": "log2ram helt borttagen från systemet",
"main container of the application": "applikationens huvudbehållare",
"make cloned mount tree read-only": "gör det klonade monteringsträdet skrivskyddat",
+69
View File
@@ -0,0 +1,69 @@
# Automatic catalog refresh
Opening OCI Manager displays its local catalog immediately and starts a separate
worker. The menu shows the available total, additions since the last displayed
catalog, and changed recipes. Returning from a search or installation does not
start another download. A running wizard keeps the catalog it started with.
The menu also offers **Refresh catalog** to check again manually or retry after
a connection failure. Selecting it during a refresh does not start a second worker.
Manual refresh bypasses the conditional check and verifies the complete manifest,
allowing it to repair damaged cached files even when the upstream revision has not
changed. A repaired snapshot gets a separate immutable directory so existing
readers retain their original snapshot until they return to the menu. Each
Catalog reader holds an OS file-lock lease. Every worker run, including unchanged
checks and failed downloads, prunes snapshots that are neither a channel's active
snapshot nor leased by an open reader. Reader exit or a crash releases its lease
automatically. Snapshot selection, publication and pruning share a short local
lock; opening a menu never waits for the worker's network lock.
The worker checks the latest commit affecting `oci/catalog` in the official
MacRimi/ProxMenux repository. GitHub's ETag avoids repeated transfers. When the
revision changes, its immutable Git tree supplies the file manifest. Only changed
JSON files are downloaded from that commit; Git blob hashes and sizes are checked.
The complete snapshot, including overlays, categories, volume policy and
verification records, is validated before publishing its pointer atomically.
Runtime Python or shell files are never downloaded by catalog refresh.
State and snapshots live in `/usr/local/share/proxmenux/oci/catalog-cache`, outside
the engine replaced by the normal ProxMenux updater. The bundled catalog remains
the fallback. A network failure, incomplete manifest, invalid recipe, different
template schema or unsupported catalog engine API leaves the previous catalog
active. The private `CHANNEL-result.json` records the diagnostic.
The revision, snapshot and ETag are committed together in one atomic pointer;
failure to publish it cannot acknowledge an update that was not applied.
The channel follows `install_branch`, an active beta program or `beta_version.txt`;
otherwise it is `main`. A host can explicitly select `main` or `develop` with
`/usr/local/share/proxmenux/oci/catalog-source.json`:
```json
{"channel": "develop", "local_apps": ["my-local-preview"]}
```
`local_apps` optionally keeps explicitly named bundled preview recipes available
when they are absent upstream. These are local overrides, not automatic retention
of withdrawn upstream applications. An upstream recipe with the same ID wins.
The first visit uses the bundled/current catalog as its baseline. Additions are
compared by application ID, not net growth, and only visible installable entries
are counted, using the same rule as the existing menu. A downloaded catalog is
acknowledged only after the menu displays it. Exiting during a download therefore
preserves its news for the next visit. The new-app count remains visible throughout
the current visit and becomes zero on the next visit after acknowledgement.
Downloaded recipes are also checked against the top-level `installer_profile`
keys used by the engine's bundled apps, curated recipes and overlays. A new app
using an unknown key is silently excluded; an existing app retains its previous
compatible, fully composed recipe and its matching settings. Hidden entries do
not contribute to the available/new counters, and retaining an old recipe does
not count it as an update. When a ProxMenux update adds support for that key, the
next background check re-evaluates the catalog even at the same remote revision.
This is a conservative key-presence gate, not validation of new values or nested
options of an already known key. Changes in meaning still require `engine_api`.
Catalog maintainers must increase `catalog/compatibility.json`'s `engine_api` when
recipes require incompatible runtime capabilities. The consumer currently
supports API 1. Changes to the template schema also require a ProxMenux engine
update. Catalog delivery alone neither changes installed CTs nor applies a new
recipe to an existing deployment; the established management actions remain in
charge of those changes.
+8
View File
@@ -111,6 +111,8 @@ Selecting an application, or giving a definition, opens the same sequence.
4. **Resolve.** The registry is queried, the architecture of the host is selected and the digest the tag points to at that moment is fixed.
5. **Download and verify.** Skopeo downloads the image as an OCI archive. Every layer is checked against its digest before anything is created.
6. **Build.** `pct create` builds the rootfs from the archive and imports `Entrypoint`, `Cmd`, `Env`, `User`, `WorkingDir` and `StopSignal` from the image.
Proxmox reads the image inside the container's user namespace. Readable template-storage archives use the existing path without a copy. If a verified archive or its parents are private, the native create wrapper makes a temporary root-owned copy under `/var/tmp`, readable only by the mapped root group, and removes it after creation, failure or a catchable interruption. The cached image, storage directories, registry credentials and caller permissions stay unchanged. Reflinks are used where available; otherwise this uncommon path needs temporary space for one image copy. Only the `pct create` child receives the normal Proxmox creation umask.
7. **Connect.** The volumes are added as mount points, then the devices, the environment, the network and the security settings the oci-compose declares.
8. **Prepare.** Each new volume is made ready for the first start: `lost+found` is removed and the directory is given to the user the application writes with. The files the oci-compose asks to write are written.
9. **Start and check.** The container starts, an address is waited for, the settings that need the running application are applied, and the service is checked. A failed first start is reported as a failed installation.
@@ -1117,3 +1119,9 @@ have not been tested. No custom supervisor or image entrypoint is introduced.
DeepSeek OCR remains deferred at the user's request: registry inspection on
2026-09-14 found only `v2.2.0` for both IceWhaleTech images and no `latest` tag.
No fixed-version exception or deployment has been introduced.
## Automatic catalog refresh
OCI Manager opens with its local catalog and checks for new applications and recipes
in the background. **Refresh catalog** repeats the check manually. See
[Automatic catalog refresh](CATALOG-REFRESH.md) for caching, channels and compatibility.
+9 -1
View File
@@ -2,7 +2,7 @@
<!-- Generated from oci/catalog/verification.json by .github/scripts/oci_validation.py. Do not edit by hand. -->
44 of 532 applications in the OCI catalog have been tested for real: 41 in the ProxMenux lab and 3 by the community. The OCI installer shows them as verified, with a ✓ in the lists.
52 of 555 applications in the OCI catalog have been tested for real: 49 in the ProxMenux lab and 3 by the community. The OCI installer shows them as verified, with a ✓ in the lists.
Each test describes the scenario that was run and names the image it ran on. It does not cover every possible configuration of the application, and a newer image has not been tested until someone reports it.
@@ -38,6 +38,7 @@ Questions and ideas about OCI testing go in [discussion #440](https://github.com
| Alby Hub ✨ | Finance & Budgeting |
| Alist | Files & Sharing |
| aMule | Files & Downloads |
| Authentik | Authentication & Security |
| Chromium | Browsers & Web Desktops |
| CodeProject.AI Server | AI |
| CopyParty | Files & Sharing |
@@ -50,26 +51,33 @@ Questions and ideas about OCI testing go in [discussion #440](https://github.com
| Flexget | *Arr Suite |
| Frigate | NVR & Cameras |
| Grafana | Monitoring & Analytics |
| HAOS One | IoT & Smart Home |
| Immich | Media |
| JDownloader | Files & Downloads |
| Jenkins CI/CD | AI / Coding & Dev-Tools |
| Linkwarden | Documents & Notes |
| Mariadb | Databases |
| Memos | Documents & Notes |
| MineOS | Gaming & Leisure |
| Motioneye | NVR & Cameras |
| Navidrome | Media & Streaming |
| Nextcloud | Productivity & Workflows |
| Nextcloud Stack | Productivity & Workflows |
| OpenList | Files & Sharing |
| Openssh Server | Remote Access & VPN |
| Paperless-ngx | Productivity & Workflows |
| Phpmyadmin | Databases |
| Prowlarr | *Arr Suite |
| Qbittorrent | Files & Downloads |
| Rclone WebUI | Backup & Recovery |
| Real-Debrid Torrent Client | Files & Downloads |
| Scanopy | Network & Firewall |
| ShareCoveX | Files & Sharing |
| SnapOtter | Media & Streaming |
| Sonarr | *Arr Suite |
| Tandoor Recipes | Productivity & Workflows |
| Thelounge | Communication & Community |
| Trilium | Documents & Notes |
| Vaultwarden | Authentication & Security |
| Wireguard | Remote Access & VPN |
| WireGuard Easy | Remote Access & VPN |
@@ -323,6 +323,9 @@
"AceStream HTTP Proxy has no web interface: a media player opens its streams.",
"HLS stream: port 6878, path /ace/manifest.m3u8?id= followed by the channel ID.",
"MPEG-TS stream: port 6878, path /ace/getstream?id= followed by the channel ID."
],
"non_persistent_image_volumes": [
"/home/appuser/.ACEStream"
]
}
},
+585
View File
@@ -0,0 +1,585 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-airdcpp-webclient",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "AirDC++ Web Client",
"es_ES": "AirDC++ Web Client"
},
"tagline": {
"en_US": "Direct Connect file sharing with a web interface",
"es_ES": "Intercambio de archivos Direct Connect con interfaz web"
},
"description": {
"en_US": "AirDC++ Web Client using the community-maintained gangefors image. Configuration, downloads and shared content use separate persistent paths.",
"es_ES": "AirDC++ Web Client con la imagen comunitaria de gangefors. La configuración, las descargas y los archivos compartidos usan rutas persistentes separadas."
},
"category": "downloads",
"category_label": "Files & Downloads",
"author": "gangefors",
"developer": "AirDC++",
"icon": "https://raw.githubusercontent.com/airdcpp-web/airdcpp-webui/eeeea5025a5e720f38dac53ced8e002940f00a74/resources/images/logo.svg",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64"
],
"launch": {
"scheme": "http",
"port": 5600,
"path": "/"
},
"website": "https://airdcpp-web.github.io/",
"documentation": "https://github.com/gangefors/docker-airdcpp-webclient",
"repository": "https://github.com/gangefors/docker-airdcpp-webclient",
"tips": [
"The upstream initial login is admin / password. Change it in Settings > System > Users before allowing access beyond a trusted LAN.",
"Configuration uses /.airdcpp on a managed Proxmox volume included in backups. /Downloads and /Share can use managed volumes or explicitly selected host directories.",
"Files under /Share are shared by AirDC++. Select the contents deliberately; router forwarding and hub configuration are separate administrator actions.",
"PUID and PGID default to 1000 and must be at least 101. The original entrypoint creates the application account; volume ownership follows these values.",
"Open HTTP port 5600 on the dedicated LXC address. HTTPS port 5601 uses the upstream self-signed certificate; use a trusted reverse proxy certificate for remote web access.",
"Incoming Direct Connect traffic uses TCP and UDP 21248 and TLS TCP 21249. ProxMenux keeps those native ports and does not configure your router."
],
"mini_changelog": [],
"display_version": null,
"updated_at": "2026-10-25"
},
"source": {
"provider": "gangefors",
"repository": "https://github.com/gangefors/docker-airdcpp-webclient",
"revision": "37f2e939c152fb2c0158bc83bc76cc972aed965e",
"image_repository_url": "https://hub.docker.com/r/gangefors/airdcpp-webclient",
"readme_pushed_at": "2026-10-25T11:51:53Z",
"compose_sha256": "4ce8aec542cfc3e7f5ca142e309a41f04aca444bd1724ca1741c96acb5c3d5bf",
"generated_at": "2026-11-03T11:47:04+00:00",
"default_branch": "master",
"readme_raw_url": "https://raw.githubusercontent.com/gangefors/docker-airdcpp-webclient/37f2e939c152fb2c0158bc83bc76cc972aed965e/docker-compose.yml"
},
"container_contract": {
"service_name": "airdcpp",
"container_name": "airdcpp",
"image": {
"reference": "docker.io/gangefors/airdcpp-webclient:latest",
"registry": "docker.io",
"repository": "docker.io/gangefors/airdcpp-webclient",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "PUID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PGID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "UMASK",
"example": "0022",
"required": true,
"sensitive": false,
"source": "upstream-compose"
}
],
"volumes": [
{
"id": "config",
"container_path": "/.airdcpp",
"compose_source_example": "./config",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
},
{
"id": "downloads",
"container_path": "/Downloads",
"compose_source_example": "./downloads",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 32
}
},
{
"id": "share",
"container_path": "/Share",
"compose_source_example": "./share",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 32
}
}
],
"ports": [
{
"container_port": 5600,
"published_example": 5600,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 5601,
"published_example": 5601,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 21248,
"published_example": 21248,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 21248,
"published_example": 21248,
"protocol": "udp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 21249,
"published_example": 21249,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "name: airdcpp-webclient\nservices:\n airdcpp:\n image: docker.io/gangefors/airdcpp-webclient:latest\n restart: unless-stopped\n environment:\n PUID: '1000'\n PGID: '1000'\n UMASK: '0022'\n ports:\n - 5600:5600\n - 5601:5601\n - 21248:21248/tcp\n - 21248:21248/udp\n - 21249:21249/tcp\n volumes:\n - ./config:/.airdcpp\n - ./downloads:/Downloads\n - ./share:/Share\n"
},
"compose_stack": {
"project_name": "airdcpp-webclient",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "airdcpp",
"service_count": 1,
"services": [
{
"name": "airdcpp",
"image": "docker.io/gangefors/airdcpp-webclient:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "docker.io/gangefors/airdcpp-webclient:latest",
"restart": "unless-stopped",
"environment": {
"PUID": "1000",
"PGID": "1000",
"UMASK": "0022"
},
"ports": [
"5600:5600",
"5601:5601",
"21248:21248/tcp",
"21248:21248/udp",
"21249:21249/tcp"
],
"volumes": [
"./config:/.airdcpp",
"./downloads:/Downloads",
"./share:/Share"
]
}
}
],
"top_level": {
"name": "airdcpp-webclient"
},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "airdcpp-volume-0",
"service": "airdcpp",
"container_path": "/.airdcpp",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "airdcpp-volume-1",
"service": "airdcpp",
"container_path": "/Downloads",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "airdcpp-volume-2",
"service": "airdcpp",
"container_path": "/Share",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"airdcpp"
],
"stop_order": [
"airdcpp"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": []
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "http",
"port": 5600,
"path": "/",
"source": "https://github.com/gangefors/docker-airdcpp-webclient"
}
],
"credentials": [
{
"label": "AirDC++ administrator",
"type": "static-default",
"username": "admin",
"password": "password",
"change_required": true,
"source": "https://github.com/gangefors/docker-airdcpp-webclient#run-the-application"
}
]
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
],
"installer_profile": {
"volume_preparations": [
{
"container_path": "/.airdcpp",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/Downloads",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/Share",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 5600,
"path": "/index.html",
"timeout_seconds": 180,
"request_timeout_seconds": 5,
"stability_seconds": 4,
"verify_tls": true
}
}
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Community image and single-LXC contract reviewed against the publisher Compose and entrypoint; Linux amd64 confirmed in the registry manifest. Runtime lifecycle checks remain pending."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "pending",
"service_health": "pending",
"restart_persistence": "pending",
"backup_restore": "pending",
"update_preserves_data": "pending",
"authenticated_login": "pending",
"advanced_install": "pending",
"host_bind_storage": "pending",
"managed_storage": "pending",
"removal": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+453
View File
@@ -0,0 +1,453 @@
{
"schema_version": "0.4.0",
"kind": "proxmenux.oci-template",
"id": "image-authelia",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "Authelia",
"es_ES": "Authelia"
},
"tagline": {
"en_US": "Single sign-on and multi-factor authentication",
"es_ES": "Inicio de sesión único y autenticación multifactor"
},
"description": {
"en_US": "An open-source authentication and authorization server for protecting web applications. This single-image profile provides a local SQLite database and file notifications; configure your domain, reverse proxy and access rules before protecting other services.",
"es_ES": "Servidor de autenticación y autorización de código abierto para proteger aplicaciones web. Este perfil de una sola imagen incluye una base de datos SQLite local y notificaciones en archivo; configura el dominio, el proxy inverso y las reglas de acceso antes de proteger otros servicios."
},
"category": "security",
"category_label": "Authentication & Security",
"author": "Authelia",
"developer": "Authelia",
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/authelia.webp",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "http",
"port": 9091,
"path": "/"
},
"website": "https://www.authelia.com/",
"documentation": "https://www.authelia.com/integration/deployment/docker/",
"repository": "https://github.com/authelia/authelia",
"tips": [
"The installer creates a unique admin password and stores only its Argon2id hash in /config/users_database.yml. The password is shown in the installation result.",
"Authelia requires an HTTPS portal URL and a cookie domain matching that hostname. If you use Nginx Proxy Manager, follow the official integration guide and configure trusted proxies and forward-auth separately.",
"The default notifier writes messages to /config/notification.txt. Configure SMTP in /config/configuration.yml if you want email delivery.",
"The initial access-control policy is one_factor. Add explicit access-control rules before attaching Authelia to protected proxy hosts."
],
"mini_changelog": [],
"display_version": "4.39.28",
"updated_at": "2026-09-17"
},
"source": {
"provider": "authelia",
"repository": "https://github.com/authelia/authelia",
"default_branch": "master",
"revision": "8da42b2348b0351c6284a2940a9c5eec3d4cd3fd",
"readme_raw_url": "https://raw.githubusercontent.com/authelia/authelia/v4.39.28/examples/compose/lite/compose.yml",
"readme_pushed_at": "2026-09-17T12:13:30Z",
"compose_sha256": "848ce0f70e502981a050ac200d9d1882978a6c3b0f9f0dfcc6d52ce66ca37fb5",
"generated_at": "2026-11-03T09:10:57+00:00",
"image_repository_url": "https://hub.docker.com/r/authelia/authelia"
},
"container_contract": {
"service_name": "authelia",
"container_name": "authelia",
"image": {
"reference": "docker.io/authelia/authelia:4.39.28",
"registry": "docker.io",
"repository": "docker.io/authelia/authelia",
"tag": "4.39.28",
"digest": null,
"pull_policy": "resolve-selected-tag-to-architecture-digest-at-install"
},
"environment": [
{
"name": "PROXMENUX_ADMIN_PASSWORD",
"example": "",
"required": true,
"sensitive": true,
"source": "proxmenux-first-start"
},
{
"name": "AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET",
"example": "",
"required": true,
"sensitive": true,
"source": "proxmenux-generated"
},
{
"name": "AUTHELIA_SESSION_SECRET",
"example": "",
"required": true,
"sensitive": true,
"source": "proxmenux-generated"
},
{
"name": "AUTHELIA_STORAGE_ENCRYPTION_KEY",
"example": "",
"required": true,
"sensitive": true,
"source": "proxmenux-generated"
},
{
"name": "X_AUTHELIA_CONFIG_FILTERS",
"example": "template",
"required": true,
"sensitive": false,
"source": "authelia-container"
},
{
"name": "PROXMENUX_AUTHELIA_COOKIE_DOMAIN",
"example": "",
"prompt": "Authelia session cookie domain for this portal (for example example.com)",
"required": true,
"sensitive": false,
"source": "administrator"
},
{
"name": "PROXMENUX_AUTHELIA_URL",
"example": "",
"prompt": "Public HTTPS URL used to open this Authelia portal (for example https://auth.example.com)",
"required": true,
"sensitive": false,
"source": "administrator"
}
],
"volumes": [
{
"id": "config",
"container_path": "/config",
"compose_source_example": "./authelia",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 4
}
}
],
"ports": [
{
"container_port": 9091,
"published_example": 9091,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n authelia:\n entrypoint:\n - /bin/sh\n - /usr/local/bin/proxmenux-authelia-bootstrap\n environment:\n AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET: ${GENERATED_RESET_PASSWORD_JWT_SECRET}\n AUTHELIA_SESSION_SECRET: ${GENERATED_SESSION_SECRET}\n AUTHELIA_STORAGE_ENCRYPTION_KEY: ${GENERATED_STORAGE_ENCRYPTION_KEY}\n PROXMENUX_ADMIN_PASSWORD: ${GENERATED_ADMIN_PASSWORD}\n PROXMENUX_AUTHELIA_COOKIE_DOMAIN: ${AUTHELIA_COOKIE_DOMAIN}\n PROXMENUX_AUTHELIA_URL: ${AUTHELIA_URL}\n X_AUTHELIA_CONFIG_FILTERS: template\n image: docker.io/authelia/authelia:4.39.28\n ports:\n - 9091:9091\n restart: unless-stopped\n volumes:\n - ./authelia:/config\n"
},
"first_run": {
"endpoints": [
{
"label": "Authelia Web UI",
"scheme": "http",
"port": 9091,
"path": "/",
"source": "official-image"
}
],
"credentials": [
{
"label": "Authelia administrator",
"type": "configured-or-installer-generated",
"username": "admin",
"password": null,
"password_environment": "PROXMENUX_ADMIN_PASSWORD",
"change_required": false,
"source": "Generated on first start and stored as an Argon2id hash in the persistent users file."
}
]
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 60
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"installer_profile": {
"runtime": {
"compose_entrypoint": [
"/bin/sh",
"/usr/local/bin/proxmenux-authelia-bootstrap"
]
},
"generated_sensitive_environment": {
"PROXMENUX_ADMIN_PASSWORD": {
"strategy": "token-hex",
"bytes": 24,
"prompt": false
},
"AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET": {
"strategy": "token-hex",
"bytes": 32,
"prompt": false
},
"AUTHELIA_SESSION_SECRET": {
"strategy": "token-hex",
"bytes": 32,
"prompt": false
},
"AUTHELIA_STORAGE_ENCRYPTION_KEY": {
"strategy": "token-hex",
"bytes": 32,
"prompt": false
}
},
"minimum_secret_length": {
"PROXMENUX_ADMIN_PASSWORD": 24,
"AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET": 32,
"AUTHELIA_SESSION_SECRET": 32,
"AUTHELIA_STORAGE_ENCRYPTION_KEY": 32
},
"generated_files": [
{
"container_path": "/config/configuration.yml",
"mode": "0600",
"owner": "mapped-root",
"only_if_missing": true,
"content": "---\nserver:\n address: 'tcp://:9091'\n\nlog:\n level: 'info'\n\ntotp:\n issuer: 'Authelia'\n\nidentity_validation:\n reset_password:\n jwt_secret: 'configured-by-environment'\n\nauthentication_backend:\n file:\n path: '/config/users_database.yml'\n watch: true\n\naccess_control:\n default_policy: 'one_factor'\n\nsession:\n secret: 'configured-by-environment'\n cookies:\n - name: 'authelia_session'\n domain: '{{ env \"PROXMENUX_AUTHELIA_COOKIE_DOMAIN\" }}'\n authelia_url: '{{ env \"PROXMENUX_AUTHELIA_URL\" }}'\n expiration: '1 hour'\n inactivity: '5 minutes'\n\nstorage:\n encryption_key: 'configured-by-environment'\n local:\n path: '/config/db.sqlite3'\n\nnotifier:\n filesystem:\n filename: '/config/notification.txt'\n"
},
{
"container_path": "/usr/local/bin/proxmenux-authelia-bootstrap",
"mode": "0700",
"owner": "mapped-root",
"only_if_missing": false,
"content": "#!/bin/sh\nset -eu\numask 077\n\nusers_file=/config/users_database.yml\nif [ ! -s \"$users_file\" ]; then\n : \"${PROXMENUX_ADMIN_PASSWORD:?ProxMenux did not provide an initial administrator password}\"\n mkdir -p /config\n hash_output=$(authelia crypto hash generate argon2 --password \"$PROXMENUX_ADMIN_PASSWORD\" --no-confirm)\n password_hash=$(printf '%s\\n' \"$hash_output\" | sed -n 's/^Digest: //p')\n case \"$password_hash\" in\n '$argon2id$'*) ;;\n *) printf '%s\\n' 'Authelia did not return an Argon2id password hash' >&2; exit 1 ;;\n esac\n temporary_file=\"${users_file}.tmp.$$\"\n cat >\"$temporary_file\" <<EOF\nusers:\n admin:\n disabled: false\n displayname: 'Authelia Administrator'\n password: \"$password_hash\"\n groups:\n - 'admins'\nEOF\n chmod 0600 \"$temporary_file\"\n mv -f \"$temporary_file\" \"$users_file\"\nfi\nunset PROXMENUX_ADMIN_PASSWORD\nexec /app/entrypoint.sh \"$@\"\n"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 9091,
"path": "/api/health",
"timeout_seconds": 240,
"request_timeout_seconds": 10,
"stability_seconds": 4,
"verify_tls": true
}
},
"adaptations": [
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "The application listens on the same container ports at its dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Users open the LXC address instead of the Proxmox host address.",
"validation": "pending-per-application"
},
{
"id": "compose-environment-overlay",
"upstream_behavior": "Compose environment values override OCI image environment values.",
"native_lxc_behavior": "ProxMenux merges the same values into lxc.environment.runtime while the CT is stopped.",
"reason": "PVE imports image Env automatically; Compose values still need to override it.",
"behavioral_impact": "None expected.",
"validation": "pending-per-application"
},
{
"id": "stop-grace-period",
"upstream_behavior": "Docker waits for Compose stop_grace_period before forcing termination.",
"native_lxc_behavior": "ProxMenux records the same timeout for its pct shutdown lifecycle operations.",
"reason": "Proxmox has no equivalent per-CT persistent restart-policy field; startup.down is not a shutdown timeout.",
"behavioral_impact": "Normal Proxmox node shutdown remains governed by the node-wide shutdown policy.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "pending-per-application"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "A single-image profile for the Authelia authentication portal. ProxMenux creates a unique initial administrator account; the local notifier and SQLite storage are kept in /config. Reverse-proxy trust and explicit access-control rules remain administrator settings."
},
"validation": {
"schema": "pending-local-validation",
"clean_install": "pending",
"service_health": "pending",
"restart_persistence": "pending",
"backup_restore": "pending",
"update_preserves_data": "pending"
},
"lifecycle": {
"update_strategy": "replace-rootfs-from-new-oci-image-preserve-managed-volumes",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+62 -2
View File
@@ -76,6 +76,38 @@
"backup": true,
"default_size_gb": 2
}
},
{
"id": "volume-1",
"container_path": "/etc/bind",
"compose_source_example": "./config",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 1
}
},
{
"id": "volume-2",
"container_path": "/var/lib/bind",
"compose_source_example": "./lib",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 1
}
}
],
"ports": [
@@ -123,7 +155,9 @@
"53:53/tcp"
],
"volumes": [
"./bind:/var/cache/bind"
"./bind:/var/cache/bind",
"./config:/etc/bind",
"./lib:/var/lib/bind"
]
}
}
@@ -151,6 +185,28 @@
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "bind9-volume-1",
"service": "bind9",
"container_path": "/etc/bind",
"mode": "managed-volume",
"user_selectable": true,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "bind9-volume-2",
"service": "bind9",
"container_path": "/var/lib/bind",
"mode": "managed-volume",
"user_selectable": true,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
@@ -349,7 +405,11 @@
"validation": "not-requested-by-compose"
}
],
"installer_profile": {},
"installer_profile": {
"non_persistent_image_volumes": [
"/var/log"
]
},
"catalog": {
"replaces_discovered_ids": []
}
+677
View File
@@ -0,0 +1,677 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-cadcraft",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "CADCraft",
"es_ES": "CADCraft"
},
"tagline": {
"en_US": "Computer-aided design and drafting in your browser",
"es_ES": "Diseño CAD y dibujo técnico en el navegador"
},
"description": {
"en_US": "CADCraft from the ArtCraft project, streamed from a native Linux application using the community-maintained junkerderprovinz image. Files are stored on the server, not in browser storage.",
"es_ES": "CADCraft del proyecto ArtCraft, con su aplicación nativa de Linux transmitida al navegador mediante la imagen comunitaria de junkerderprovinz. Los documentos se guardan en el servidor, no en el almacenamiento del navegador."
},
"category": "creative",
"category_label": "Creative & Design",
"author": "junkerderprovinz",
"developer": "ArtCraft",
"icon": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/.github/assets/icons/cadcraft.png",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "https",
"port": 3001,
"path": "/"
},
"website": "https://getartcraft.com/apps/cadcraft",
"documentation": "https://github.com/junkerderprovinz/artcraft-apps",
"repository": "https://github.com/storytold/cadcraft",
"tips": [
"This is the native Linux application streamed by Selkies, not the WebAssembly build. Processing and documents stay in the LXC and its mounted directories.",
"The image is maintained by junkerderprovinz; ArtCraft publishes the application packages. It is not an official ArtCraft container image.",
"Use a trusted HTTPS reverse proxy for browser access. Port 3001 uses the upstream self-signed certificate; port 3000 is for an HTTP reverse-proxy backend.",
"The upstream default has no login. Optional CUSTOM_USER and PASSWORD variables enable HTTP basic authentication; do not expose an unauthenticated desktop to untrusted networks.",
"/config holds settings and desktop state and is included in Proxmox backups. /storage holds documents and supports a managed volume or an explicitly selected host directory; host directories require separate backups.",
"The default installation draws on the CPU. The advanced installation can assign an Intel or AMD GPU, which the desktop, the application and the video stream then use; NVIDIA is offered when the host has its driver and the NVIDIA Container Toolkit.",
"Without a GPU, an application may ask to switch to CPU rendering. Choose the CPU option; the application remembers it."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "junkerderprovinz",
"repository": "https://github.com/junkerderprovinz/artcraft-apps",
"revision": "32bee0dea9bdaf5310c693210bea0d732a129ae8",
"image_repository_url": "https://hub.docker.com/r/junkerderprovinz/cadcraft",
"readme_pushed_at": "",
"compose_sha256": "ab46cb8e87addb261680a50fc8bdde1f9d689a0d14f6ca570eaf11e43868655a",
"generated_at": "2026-11-03T12:57:27+00:00",
"default_branch": "main",
"readme_raw_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/compose/cadcraft.yaml"
},
"container_contract": {
"service_name": "cadcraft",
"container_name": "cadcraft",
"image": {
"reference": "docker.io/junkerderprovinz/cadcraft:latest",
"registry": "docker.io",
"repository": "junkerderprovinz/cadcraft",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "TZ",
"example": "Europe/Vienna",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PUID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PGID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "UMASK",
"example": "022",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "CUSTOM_USER",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation"
},
{
"name": "PASSWORD",
"example": "",
"required": false,
"sensitive": true,
"source": "upstream-documentation"
},
{
"name": "LC_ALL",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation",
"prompt": "Language/locale (e.g. es_ES.UTF-8; translation of every application is not guaranteed)"
}
],
"volumes": [
{
"id": "config",
"container_path": "/config",
"compose_source_example": "./appdata",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "storage",
"container_path": "/storage",
"compose_source_example": "./storage",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
}
],
"ports": [
{
"container_port": 3001,
"published_example": 3001,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 3000,
"published_example": 3000,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n cadcraft:\n image: junkerderprovinz/cadcraft:latest\n container_name: cadcraft\n restart: unless-stopped\n shm_size: 1gb\n ports:\n - 3001:3001\n - 3000:3000\n volumes:\n - ./appdata:/config\n - ./storage:/storage\n environment:\n TZ: Europe/Vienna\n PUID: '1000'\n PGID: '1000'\n UMASK: '022'\n"
},
"compose_stack": {
"project_name": "cadcraft",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "cadcraft",
"service_count": 1,
"services": [
{
"name": "cadcraft",
"image": "junkerderprovinz/cadcraft:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "junkerderprovinz/cadcraft:latest",
"container_name": "cadcraft",
"restart": "unless-stopped",
"shm_size": "1gb",
"ports": [
"3001:3001",
"3000:3000"
],
"volumes": [
"./appdata:/config",
"./storage:/storage"
],
"environment": {
"TZ": "Europe/Vienna",
"PUID": "1000",
"PGID": "1000",
"UMASK": "022"
}
}
}
],
"top_level": {},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "cadcraft-volume-0",
"service": "cadcraft",
"container_path": "/config",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "cadcraft-volume-1",
"service": "cadcraft",
"container_path": "/storage",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"cadcraft"
],
"stop_order": [
"cadcraft"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": []
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "https",
"port": 3001,
"path": "/",
"source": "https://github.com/junkerderprovinz/artcraft-apps"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 2048,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"installer_profile": {
"tmpfs_mounts": [
{
"id": "compose-shm",
"container_path": "/dev/shm",
"default_size_mb": 1024,
"minimum_size_mb": 1,
"size_prompt": "Size of the /dev/shm shared memory in MB",
"mount_options": [
"rw",
"nosuid",
"nodev"
]
},
{
"id": "nginx-runtime",
"container_path": "/run/nginx",
"default_size_mb": 1,
"minimum_size_mb": 1,
"prompt_size": false,
"mount_options": [
"rw",
"nosuid",
"nodev",
"mode=0755"
]
}
],
"volume_preparations": [
{
"container_path": "/config",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/storage",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 3000,
"path": "/",
"timeout_seconds": 240,
"request_timeout_seconds": 5,
"stability_seconds": 8,
"accept_any_status": true,
"verify_tls": true
},
"selkies": {
"base": "FROM ghcr.io/linuxserver/baseimage-selkies:ubunturesolute@sha256:6efa3fd775a552938d862f75975d34c418ad26d028ba2c952da58682cfe1cb47",
"dockerfile_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/Dockerfile",
"dockerfile_sha256": "69ab1a81d1696d1bd143a6fa5a121c034ddfb3e83008969340e8cd2413547fe1",
"reviewed_on": "2026-11-04",
"documentation": "https://docs.linuxserver.io/images/docker-baseimage-selkies/",
"nvidia": "available-in-advanced-mode-with-compatible-host-driver-and-toolkit",
"validation": "Intel/AMD tested on a Radeon 680M: GL compositor and VAAPI encoding on the render node"
},
"device_requests": [],
"optional_devices": [],
"hardware_acceleration": {
"prompt": "Selkies desktop and streaming acceleration",
"default": "none",
"profiles": [
{
"id": "none",
"label": "No GPU (CPU)",
"device_requests": [],
"environment": [
{
"name": "AUTO_GPU",
"value": "false"
}
]
},
{
"id": "vaapi",
"label": "Intel/AMD (streaming rendering and encoding)",
"device_requests": [
{
"id": "selkies-render",
"kind": "character-device",
"path_prompt": "Intel/AMD render node",
"host_path_default": "/dev/dri/renderD128",
"container_path_strategy": "same-as-host",
"mode": "0660",
"deny_write": false,
"gid_strategy": "host-device-gid",
"drm_vendor_ids": [
"0x8086",
"0x1002"
]
}
],
"environment": [
{
"name": "PIXELFLUX_WAYLAND",
"value": "true"
},
{
"name": "AUTO_GPU",
"value": "false"
}
],
"environment_from_devices": {
"DRINODE": [
"selkies-render"
],
"DRI_NODE": [
"selkies-render"
],
"ATTACHED_DEVICES_PERMS": [
"selkies-render"
]
}
},
{
"id": "nvidia",
"label": "NVIDIA (Selkies rendering and NVENC)",
"device_requests": [
{
"id": "selkies-nvidia",
"kind": "nvidia-runtime",
"device_selection": "all-requested-by-compose"
}
],
"environment": [
{
"name": "AUTO_GPU",
"value": "true"
},
{
"name": "NVIDIA_VISIBLE_DEVICES",
"value": "all"
},
{
"name": "NVIDIA_DRIVER_CAPABILITIES",
"value": "compute,video,graphics,utility,display"
}
]
}
]
},
"gpu_validation": {
"device_inventory": "host-sysfs-and-stat",
"application_acceleration": "requires-workload-test",
"tone_mapping": "not-implied-by-device-access"
},
"device_permissions": {
"strategy": "linuxserver-native-init",
"service_user": "abc",
"environment": "ATTACHED_DEVICES_PERMS",
"paths": "all-resolved-selected-character-devices"
}
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "pending-per-application"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Community native-desktop image contract reviewed against its published Compose and Dockerfile. Linux amd64 and arm64 manifests exist; runtime, storage and lifecycle tests remain pending per architecture."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "pending",
"service_health": "pending",
"restart_persistence": "pending",
"backup_restore": "pending",
"update_preserves_data": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+7 -1
View File
@@ -339,7 +339,13 @@
"validation": "not-requested-by-compose"
}
],
"installer_profile": {}
"installer_profile": {
"non_persistent_image_volumes": [
"/etc/chrony",
"/run/chrony",
"/var/lib/chrony"
]
}
},
"compatibility": {
"automatic_install_candidate": true,
+677
View File
@@ -0,0 +1,677 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-deckcraft",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "DeckCraft",
"es_ES": "DeckCraft"
},
"tagline": {
"en_US": "Presentations and slide decks in your browser",
"es_ES": "Presentaciones y diapositivas en el navegador"
},
"description": {
"en_US": "DeckCraft from the ArtCraft project, streamed from a native Linux application using the community-maintained junkerderprovinz image. Files are stored on the server, not in browser storage.",
"es_ES": "DeckCraft del proyecto ArtCraft, con su aplicación nativa de Linux transmitida al navegador mediante la imagen comunitaria de junkerderprovinz. Los documentos se guardan en el servidor, no en el almacenamiento del navegador."
},
"category": "creative",
"category_label": "Creative & Design",
"author": "junkerderprovinz",
"developer": "ArtCraft",
"icon": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/.github/assets/icons/deckcraft.png",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "https",
"port": 3001,
"path": "/"
},
"website": "https://getartcraft.com/apps/deckcraft",
"documentation": "https://github.com/junkerderprovinz/artcraft-apps",
"repository": "https://github.com/storytold/deckcraft",
"tips": [
"This is the native Linux application streamed by Selkies, not the WebAssembly build. Processing and documents stay in the LXC and its mounted directories.",
"The image is maintained by junkerderprovinz; ArtCraft publishes the application packages. It is not an official ArtCraft container image.",
"Use a trusted HTTPS reverse proxy for browser access. Port 3001 uses the upstream self-signed certificate; port 3000 is for an HTTP reverse-proxy backend.",
"The upstream default has no login. Optional CUSTOM_USER and PASSWORD variables enable HTTP basic authentication; do not expose an unauthenticated desktop to untrusted networks.",
"/config holds settings and desktop state and is included in Proxmox backups. /storage holds documents and supports a managed volume or an explicitly selected host directory; host directories require separate backups.",
"The default installation draws on the CPU. The advanced installation can assign an Intel or AMD GPU, which the desktop, the application and the video stream then use; NVIDIA is offered when the host has its driver and the NVIDIA Container Toolkit.",
"Without a GPU, an application may ask to switch to CPU rendering. Choose the CPU option; the application remembers it."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "junkerderprovinz",
"repository": "https://github.com/junkerderprovinz/artcraft-apps",
"revision": "32bee0dea9bdaf5310c693210bea0d732a129ae8",
"image_repository_url": "https://hub.docker.com/r/junkerderprovinz/deckcraft",
"readme_pushed_at": "",
"compose_sha256": "38d24b673dd5fb50e00d1094e681112671cf04a8e99952021f476c8b2754ef05",
"generated_at": "2026-11-03T12:57:28+00:00",
"default_branch": "main",
"readme_raw_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/compose/deckcraft.yaml"
},
"container_contract": {
"service_name": "deckcraft",
"container_name": "deckcraft",
"image": {
"reference": "docker.io/junkerderprovinz/deckcraft:latest",
"registry": "docker.io",
"repository": "junkerderprovinz/deckcraft",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "TZ",
"example": "Europe/Vienna",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PUID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PGID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "UMASK",
"example": "022",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "CUSTOM_USER",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation"
},
{
"name": "PASSWORD",
"example": "",
"required": false,
"sensitive": true,
"source": "upstream-documentation"
},
{
"name": "LC_ALL",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation",
"prompt": "Language/locale (e.g. es_ES.UTF-8; translation of every application is not guaranteed)"
}
],
"volumes": [
{
"id": "config",
"container_path": "/config",
"compose_source_example": "./appdata",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "storage",
"container_path": "/storage",
"compose_source_example": "./storage",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
}
],
"ports": [
{
"container_port": 3001,
"published_example": 3001,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 3000,
"published_example": 3000,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n deckcraft:\n image: junkerderprovinz/deckcraft:latest\n container_name: deckcraft\n restart: unless-stopped\n shm_size: 1gb\n ports:\n - 3001:3001\n - 3000:3000\n volumes:\n - ./appdata:/config\n - ./storage:/storage\n environment:\n TZ: Europe/Vienna\n PUID: '1000'\n PGID: '1000'\n UMASK: '022'\n"
},
"compose_stack": {
"project_name": "deckcraft",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "deckcraft",
"service_count": 1,
"services": [
{
"name": "deckcraft",
"image": "junkerderprovinz/deckcraft:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "junkerderprovinz/deckcraft:latest",
"container_name": "deckcraft",
"restart": "unless-stopped",
"shm_size": "1gb",
"ports": [
"3001:3001",
"3000:3000"
],
"volumes": [
"./appdata:/config",
"./storage:/storage"
],
"environment": {
"TZ": "Europe/Vienna",
"PUID": "1000",
"PGID": "1000",
"UMASK": "022"
}
}
}
],
"top_level": {},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "deckcraft-volume-0",
"service": "deckcraft",
"container_path": "/config",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "deckcraft-volume-1",
"service": "deckcraft",
"container_path": "/storage",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"deckcraft"
],
"stop_order": [
"deckcraft"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": []
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "https",
"port": 3001,
"path": "/",
"source": "https://github.com/junkerderprovinz/artcraft-apps"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 2048,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"installer_profile": {
"tmpfs_mounts": [
{
"id": "compose-shm",
"container_path": "/dev/shm",
"default_size_mb": 1024,
"minimum_size_mb": 1,
"size_prompt": "Size of the /dev/shm shared memory in MB",
"mount_options": [
"rw",
"nosuid",
"nodev"
]
},
{
"id": "nginx-runtime",
"container_path": "/run/nginx",
"default_size_mb": 1,
"minimum_size_mb": 1,
"prompt_size": false,
"mount_options": [
"rw",
"nosuid",
"nodev",
"mode=0755"
]
}
],
"volume_preparations": [
{
"container_path": "/config",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/storage",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 3000,
"path": "/",
"timeout_seconds": 240,
"request_timeout_seconds": 5,
"stability_seconds": 8,
"accept_any_status": true,
"verify_tls": true
},
"selkies": {
"base": "FROM ghcr.io/linuxserver/baseimage-selkies:ubunturesolute@sha256:6efa3fd775a552938d862f75975d34c418ad26d028ba2c952da58682cfe1cb47",
"dockerfile_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/Dockerfile",
"dockerfile_sha256": "69ab1a81d1696d1bd143a6fa5a121c034ddfb3e83008969340e8cd2413547fe1",
"reviewed_on": "2026-11-04",
"documentation": "https://docs.linuxserver.io/images/docker-baseimage-selkies/",
"nvidia": "available-in-advanced-mode-with-compatible-host-driver-and-toolkit",
"validation": "Intel/AMD tested on a Radeon 680M: GL compositor and VAAPI encoding on the render node"
},
"device_requests": [],
"optional_devices": [],
"hardware_acceleration": {
"prompt": "Selkies desktop and streaming acceleration",
"default": "none",
"profiles": [
{
"id": "none",
"label": "No GPU (CPU)",
"device_requests": [],
"environment": [
{
"name": "AUTO_GPU",
"value": "false"
}
]
},
{
"id": "vaapi",
"label": "Intel/AMD (streaming rendering and encoding)",
"device_requests": [
{
"id": "selkies-render",
"kind": "character-device",
"path_prompt": "Intel/AMD render node",
"host_path_default": "/dev/dri/renderD128",
"container_path_strategy": "same-as-host",
"mode": "0660",
"deny_write": false,
"gid_strategy": "host-device-gid",
"drm_vendor_ids": [
"0x8086",
"0x1002"
]
}
],
"environment": [
{
"name": "PIXELFLUX_WAYLAND",
"value": "true"
},
{
"name": "AUTO_GPU",
"value": "false"
}
],
"environment_from_devices": {
"DRINODE": [
"selkies-render"
],
"DRI_NODE": [
"selkies-render"
],
"ATTACHED_DEVICES_PERMS": [
"selkies-render"
]
}
},
{
"id": "nvidia",
"label": "NVIDIA (Selkies rendering and NVENC)",
"device_requests": [
{
"id": "selkies-nvidia",
"kind": "nvidia-runtime",
"device_selection": "all-requested-by-compose"
}
],
"environment": [
{
"name": "AUTO_GPU",
"value": "true"
},
{
"name": "NVIDIA_VISIBLE_DEVICES",
"value": "all"
},
{
"name": "NVIDIA_DRIVER_CAPABILITIES",
"value": "compute,video,graphics,utility,display"
}
]
}
]
},
"gpu_validation": {
"device_inventory": "host-sysfs-and-stat",
"application_acceleration": "requires-workload-test",
"tone_mapping": "not-implied-by-device-access"
},
"device_permissions": {
"strategy": "linuxserver-native-init",
"service_user": "abc",
"environment": "ATTACHED_DEVICES_PERMS",
"paths": "all-resolved-selected-character-devices"
}
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "pending-per-application"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Community native-desktop image contract reviewed against its published Compose and Dockerfile. Linux amd64 and arm64 manifests exist; runtime, storage and lifecycle tests remain pending per architecture."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "pending",
"service_health": "pending",
"restart_persistence": "pending",
"backup_restore": "pending",
"update_preserves_data": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+677
View File
@@ -0,0 +1,677 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-designcraft",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "DesignCraft",
"es_ES": "DesignCraft"
},
"tagline": {
"en_US": "Page layout and publishing in your browser",
"es_ES": "Maquetación y publicación en el navegador"
},
"description": {
"en_US": "DesignCraft from the ArtCraft project, streamed from a native Linux application using the community-maintained junkerderprovinz image. Files are stored on the server, not in browser storage.",
"es_ES": "DesignCraft del proyecto ArtCraft, con su aplicación nativa de Linux transmitida al navegador mediante la imagen comunitaria de junkerderprovinz. Los documentos se guardan en el servidor, no en el almacenamiento del navegador."
},
"category": "creative",
"category_label": "Creative & Design",
"author": "junkerderprovinz",
"developer": "ArtCraft",
"icon": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/.github/assets/icons/designcraft.png",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "https",
"port": 3001,
"path": "/"
},
"website": "https://getartcraft.com/apps/designcraft",
"documentation": "https://github.com/junkerderprovinz/artcraft-apps",
"repository": "https://github.com/storytold/designcraft",
"tips": [
"This is the native Linux application streamed by Selkies, not the WebAssembly build. Processing and documents stay in the LXC and its mounted directories.",
"The image is maintained by junkerderprovinz; ArtCraft publishes the application packages. It is not an official ArtCraft container image.",
"Use a trusted HTTPS reverse proxy for browser access. Port 3001 uses the upstream self-signed certificate; port 3000 is for an HTTP reverse-proxy backend.",
"The upstream default has no login. Optional CUSTOM_USER and PASSWORD variables enable HTTP basic authentication; do not expose an unauthenticated desktop to untrusted networks.",
"/config holds settings and desktop state and is included in Proxmox backups. /storage holds documents and supports a managed volume or an explicitly selected host directory; host directories require separate backups.",
"The default installation draws on the CPU. The advanced installation can assign an Intel or AMD GPU, which the desktop, the application and the video stream then use; NVIDIA is offered when the host has its driver and the NVIDIA Container Toolkit.",
"Without a GPU, an application may ask to switch to CPU rendering. Choose the CPU option; the application remembers it."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "junkerderprovinz",
"repository": "https://github.com/junkerderprovinz/artcraft-apps",
"revision": "32bee0dea9bdaf5310c693210bea0d732a129ae8",
"image_repository_url": "https://hub.docker.com/r/junkerderprovinz/designcraft",
"readme_pushed_at": "",
"compose_sha256": "68fdc2548c3ecedc792ff41e1ce7002d8f0219e78781b89265ce77761685a0fd",
"generated_at": "2026-11-03T12:57:28+00:00",
"default_branch": "main",
"readme_raw_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/compose/designcraft.yaml"
},
"container_contract": {
"service_name": "designcraft",
"container_name": "designcraft",
"image": {
"reference": "docker.io/junkerderprovinz/designcraft:latest",
"registry": "docker.io",
"repository": "junkerderprovinz/designcraft",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "TZ",
"example": "Europe/Vienna",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PUID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PGID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "UMASK",
"example": "022",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "CUSTOM_USER",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation"
},
{
"name": "PASSWORD",
"example": "",
"required": false,
"sensitive": true,
"source": "upstream-documentation"
},
{
"name": "LC_ALL",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation",
"prompt": "Language/locale (e.g. es_ES.UTF-8; translation of every application is not guaranteed)"
}
],
"volumes": [
{
"id": "config",
"container_path": "/config",
"compose_source_example": "./appdata",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "storage",
"container_path": "/storage",
"compose_source_example": "./storage",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
}
],
"ports": [
{
"container_port": 3001,
"published_example": 3001,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 3000,
"published_example": 3000,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n designcraft:\n image: junkerderprovinz/designcraft:latest\n container_name: designcraft\n restart: unless-stopped\n shm_size: 1gb\n ports:\n - 3001:3001\n - 3000:3000\n volumes:\n - ./appdata:/config\n - ./storage:/storage\n environment:\n TZ: Europe/Vienna\n PUID: '1000'\n PGID: '1000'\n UMASK: '022'\n"
},
"compose_stack": {
"project_name": "designcraft",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "designcraft",
"service_count": 1,
"services": [
{
"name": "designcraft",
"image": "junkerderprovinz/designcraft:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "junkerderprovinz/designcraft:latest",
"container_name": "designcraft",
"restart": "unless-stopped",
"shm_size": "1gb",
"ports": [
"3001:3001",
"3000:3000"
],
"volumes": [
"./appdata:/config",
"./storage:/storage"
],
"environment": {
"TZ": "Europe/Vienna",
"PUID": "1000",
"PGID": "1000",
"UMASK": "022"
}
}
}
],
"top_level": {},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "designcraft-volume-0",
"service": "designcraft",
"container_path": "/config",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "designcraft-volume-1",
"service": "designcraft",
"container_path": "/storage",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"designcraft"
],
"stop_order": [
"designcraft"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": []
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "https",
"port": 3001,
"path": "/",
"source": "https://github.com/junkerderprovinz/artcraft-apps"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 2048,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"installer_profile": {
"tmpfs_mounts": [
{
"id": "compose-shm",
"container_path": "/dev/shm",
"default_size_mb": 1024,
"minimum_size_mb": 1,
"size_prompt": "Size of the /dev/shm shared memory in MB",
"mount_options": [
"rw",
"nosuid",
"nodev"
]
},
{
"id": "nginx-runtime",
"container_path": "/run/nginx",
"default_size_mb": 1,
"minimum_size_mb": 1,
"prompt_size": false,
"mount_options": [
"rw",
"nosuid",
"nodev",
"mode=0755"
]
}
],
"volume_preparations": [
{
"container_path": "/config",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/storage",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 3000,
"path": "/",
"timeout_seconds": 240,
"request_timeout_seconds": 5,
"stability_seconds": 8,
"accept_any_status": true,
"verify_tls": true
},
"selkies": {
"base": "FROM ghcr.io/linuxserver/baseimage-selkies:ubunturesolute@sha256:6efa3fd775a552938d862f75975d34c418ad26d028ba2c952da58682cfe1cb47",
"dockerfile_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/Dockerfile",
"dockerfile_sha256": "69ab1a81d1696d1bd143a6fa5a121c034ddfb3e83008969340e8cd2413547fe1",
"reviewed_on": "2026-11-04",
"documentation": "https://docs.linuxserver.io/images/docker-baseimage-selkies/",
"nvidia": "available-in-advanced-mode-with-compatible-host-driver-and-toolkit",
"validation": "Intel/AMD tested on a Radeon 680M: GL compositor and VAAPI encoding on the render node"
},
"device_requests": [],
"optional_devices": [],
"hardware_acceleration": {
"prompt": "Selkies desktop and streaming acceleration",
"default": "none",
"profiles": [
{
"id": "none",
"label": "No GPU (CPU)",
"device_requests": [],
"environment": [
{
"name": "AUTO_GPU",
"value": "false"
}
]
},
{
"id": "vaapi",
"label": "Intel/AMD (streaming rendering and encoding)",
"device_requests": [
{
"id": "selkies-render",
"kind": "character-device",
"path_prompt": "Intel/AMD render node",
"host_path_default": "/dev/dri/renderD128",
"container_path_strategy": "same-as-host",
"mode": "0660",
"deny_write": false,
"gid_strategy": "host-device-gid",
"drm_vendor_ids": [
"0x8086",
"0x1002"
]
}
],
"environment": [
{
"name": "PIXELFLUX_WAYLAND",
"value": "true"
},
{
"name": "AUTO_GPU",
"value": "false"
}
],
"environment_from_devices": {
"DRINODE": [
"selkies-render"
],
"DRI_NODE": [
"selkies-render"
],
"ATTACHED_DEVICES_PERMS": [
"selkies-render"
]
}
},
{
"id": "nvidia",
"label": "NVIDIA (Selkies rendering and NVENC)",
"device_requests": [
{
"id": "selkies-nvidia",
"kind": "nvidia-runtime",
"device_selection": "all-requested-by-compose"
}
],
"environment": [
{
"name": "AUTO_GPU",
"value": "true"
},
{
"name": "NVIDIA_VISIBLE_DEVICES",
"value": "all"
},
{
"name": "NVIDIA_DRIVER_CAPABILITIES",
"value": "compute,video,graphics,utility,display"
}
]
}
]
},
"gpu_validation": {
"device_inventory": "host-sysfs-and-stat",
"application_acceleration": "requires-workload-test",
"tone_mapping": "not-implied-by-device-access"
},
"device_permissions": {
"strategy": "linuxserver-native-init",
"service_user": "abc",
"environment": "ATTACHED_DEVICES_PERMS",
"paths": "all-resolved-selected-character-devices"
}
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "pending-per-application"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Community native-desktop image contract reviewed against its published Compose and Dockerfile. Linux amd64 and arm64 manifests exist; runtime, storage and lifecycle tests remain pending per architecture."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "pending",
"service_health": "pending",
"restart_persistence": "pending",
"backup_restore": "pending",
"update_preserves_data": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+677
View File
@@ -0,0 +1,677 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-effectcraft",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "EffectCraft",
"es_ES": "EffectCraft"
},
"tagline": {
"en_US": "Motion graphics and compositing in your browser",
"es_ES": "Animación gráfica y composición en el navegador"
},
"description": {
"en_US": "EffectCraft from the ArtCraft project, streamed from a native Linux application using the community-maintained junkerderprovinz image. Files are stored on the server, not in browser storage.",
"es_ES": "EffectCraft del proyecto ArtCraft, con su aplicación nativa de Linux transmitida al navegador mediante la imagen comunitaria de junkerderprovinz. Los documentos se guardan en el servidor, no en el almacenamiento del navegador."
},
"category": "creative",
"category_label": "Creative & Design",
"author": "junkerderprovinz",
"developer": "ArtCraft",
"icon": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/.github/assets/icons/effectcraft.png",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "https",
"port": 3001,
"path": "/"
},
"website": "https://getartcraft.com/apps/effectcraft",
"documentation": "https://github.com/junkerderprovinz/artcraft-apps",
"repository": "https://github.com/storytold/effectcraft",
"tips": [
"This is the native Linux application streamed by Selkies, not the WebAssembly build. Processing and documents stay in the LXC and its mounted directories.",
"The image is maintained by junkerderprovinz; ArtCraft publishes the application packages. It is not an official ArtCraft container image.",
"Use a trusted HTTPS reverse proxy for browser access. Port 3001 uses the upstream self-signed certificate; port 3000 is for an HTTP reverse-proxy backend.",
"The upstream default has no login. Optional CUSTOM_USER and PASSWORD variables enable HTTP basic authentication; do not expose an unauthenticated desktop to untrusted networks.",
"/config holds settings and desktop state and is included in Proxmox backups. /storage holds documents and supports a managed volume or an explicitly selected host directory; host directories require separate backups.",
"The default installation draws on the CPU. The advanced installation can assign an Intel or AMD GPU, which the desktop, the application and the video stream then use; NVIDIA is offered when the host has its driver and the NVIDIA Container Toolkit.",
"Without a GPU, an application may ask to switch to CPU rendering. Choose the CPU option; the application remembers it."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "junkerderprovinz",
"repository": "https://github.com/junkerderprovinz/artcraft-apps",
"revision": "32bee0dea9bdaf5310c693210bea0d732a129ae8",
"image_repository_url": "https://hub.docker.com/r/junkerderprovinz/effectcraft",
"readme_pushed_at": "",
"compose_sha256": "8dde56d083a5120e342967f15141e95d742d19ea0c6b782c5552d40438b46ef7",
"generated_at": "2026-11-03T12:57:28+00:00",
"default_branch": "main",
"readme_raw_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/compose/effectcraft.yaml"
},
"container_contract": {
"service_name": "effectcraft",
"container_name": "effectcraft",
"image": {
"reference": "docker.io/junkerderprovinz/effectcraft:latest",
"registry": "docker.io",
"repository": "junkerderprovinz/effectcraft",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "TZ",
"example": "Europe/Vienna",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PUID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PGID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "UMASK",
"example": "022",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "CUSTOM_USER",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation"
},
{
"name": "PASSWORD",
"example": "",
"required": false,
"sensitive": true,
"source": "upstream-documentation"
},
{
"name": "LC_ALL",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation",
"prompt": "Language/locale (e.g. es_ES.UTF-8; translation of every application is not guaranteed)"
}
],
"volumes": [
{
"id": "config",
"container_path": "/config",
"compose_source_example": "./appdata",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "storage",
"container_path": "/storage",
"compose_source_example": "./storage",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
}
],
"ports": [
{
"container_port": 3001,
"published_example": 3001,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 3000,
"published_example": 3000,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n effectcraft:\n image: junkerderprovinz/effectcraft:latest\n container_name: effectcraft\n restart: unless-stopped\n shm_size: 1gb\n ports:\n - 3001:3001\n - 3000:3000\n volumes:\n - ./appdata:/config\n - ./storage:/storage\n environment:\n TZ: Europe/Vienna\n PUID: '1000'\n PGID: '1000'\n UMASK: '022'\n"
},
"compose_stack": {
"project_name": "effectcraft",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "effectcraft",
"service_count": 1,
"services": [
{
"name": "effectcraft",
"image": "junkerderprovinz/effectcraft:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "junkerderprovinz/effectcraft:latest",
"container_name": "effectcraft",
"restart": "unless-stopped",
"shm_size": "1gb",
"ports": [
"3001:3001",
"3000:3000"
],
"volumes": [
"./appdata:/config",
"./storage:/storage"
],
"environment": {
"TZ": "Europe/Vienna",
"PUID": "1000",
"PGID": "1000",
"UMASK": "022"
}
}
}
],
"top_level": {},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "effectcraft-volume-0",
"service": "effectcraft",
"container_path": "/config",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "effectcraft-volume-1",
"service": "effectcraft",
"container_path": "/storage",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"effectcraft"
],
"stop_order": [
"effectcraft"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": []
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "https",
"port": 3001,
"path": "/",
"source": "https://github.com/junkerderprovinz/artcraft-apps"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 2048,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"installer_profile": {
"tmpfs_mounts": [
{
"id": "compose-shm",
"container_path": "/dev/shm",
"default_size_mb": 1024,
"minimum_size_mb": 1,
"size_prompt": "Size of the /dev/shm shared memory in MB",
"mount_options": [
"rw",
"nosuid",
"nodev"
]
},
{
"id": "nginx-runtime",
"container_path": "/run/nginx",
"default_size_mb": 1,
"minimum_size_mb": 1,
"prompt_size": false,
"mount_options": [
"rw",
"nosuid",
"nodev",
"mode=0755"
]
}
],
"volume_preparations": [
{
"container_path": "/config",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/storage",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 3000,
"path": "/",
"timeout_seconds": 240,
"request_timeout_seconds": 5,
"stability_seconds": 8,
"accept_any_status": true,
"verify_tls": true
},
"selkies": {
"base": "FROM ghcr.io/linuxserver/baseimage-selkies:ubunturesolute@sha256:6efa3fd775a552938d862f75975d34c418ad26d028ba2c952da58682cfe1cb47",
"dockerfile_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/Dockerfile",
"dockerfile_sha256": "69ab1a81d1696d1bd143a6fa5a121c034ddfb3e83008969340e8cd2413547fe1",
"reviewed_on": "2026-11-04",
"documentation": "https://docs.linuxserver.io/images/docker-baseimage-selkies/",
"nvidia": "available-in-advanced-mode-with-compatible-host-driver-and-toolkit",
"validation": "Intel/AMD tested on a Radeon 680M: GL compositor and VAAPI encoding on the render node"
},
"device_requests": [],
"optional_devices": [],
"hardware_acceleration": {
"prompt": "Selkies desktop and streaming acceleration",
"default": "none",
"profiles": [
{
"id": "none",
"label": "No GPU (CPU)",
"device_requests": [],
"environment": [
{
"name": "AUTO_GPU",
"value": "false"
}
]
},
{
"id": "vaapi",
"label": "Intel/AMD (streaming rendering and encoding)",
"device_requests": [
{
"id": "selkies-render",
"kind": "character-device",
"path_prompt": "Intel/AMD render node",
"host_path_default": "/dev/dri/renderD128",
"container_path_strategy": "same-as-host",
"mode": "0660",
"deny_write": false,
"gid_strategy": "host-device-gid",
"drm_vendor_ids": [
"0x8086",
"0x1002"
]
}
],
"environment": [
{
"name": "PIXELFLUX_WAYLAND",
"value": "true"
},
{
"name": "AUTO_GPU",
"value": "false"
}
],
"environment_from_devices": {
"DRINODE": [
"selkies-render"
],
"DRI_NODE": [
"selkies-render"
],
"ATTACHED_DEVICES_PERMS": [
"selkies-render"
]
}
},
{
"id": "nvidia",
"label": "NVIDIA (Selkies rendering and NVENC)",
"device_requests": [
{
"id": "selkies-nvidia",
"kind": "nvidia-runtime",
"device_selection": "all-requested-by-compose"
}
],
"environment": [
{
"name": "AUTO_GPU",
"value": "true"
},
{
"name": "NVIDIA_VISIBLE_DEVICES",
"value": "all"
},
{
"name": "NVIDIA_DRIVER_CAPABILITIES",
"value": "compute,video,graphics,utility,display"
}
]
}
]
},
"gpu_validation": {
"device_inventory": "host-sysfs-and-stat",
"application_acceleration": "requires-workload-test",
"tone_mapping": "not-implied-by-device-access"
},
"device_permissions": {
"strategy": "linuxserver-native-init",
"service_user": "abc",
"environment": "ATTACHED_DEVICES_PERMS",
"paths": "all-resolved-selected-character-devices"
}
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "pending-per-application"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Community native-desktop image contract reviewed against its published Compose and Dockerfile. Linux amd64 and arm64 manifests exist; runtime, storage and lifecycle tests remain pending per architecture."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "pending",
"service_health": "pending",
"restart_persistence": "pending",
"backup_restore": "pending",
"update_preserves_data": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+677
View File
@@ -0,0 +1,677 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-figcraft",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "FigCraft",
"es_ES": "FigCraft"
},
"tagline": {
"en_US": "Interface design and prototyping in your browser",
"es_ES": "Diseño de interfaces y prototipos en el navegador"
},
"description": {
"en_US": "FigCraft from the ArtCraft project, streamed from a native Linux application using the community-maintained junkerderprovinz image. Files are stored on the server, not in browser storage.",
"es_ES": "FigCraft del proyecto ArtCraft, con su aplicación nativa de Linux transmitida al navegador mediante la imagen comunitaria de junkerderprovinz. Los documentos se guardan en el servidor, no en el almacenamiento del navegador."
},
"category": "creative",
"category_label": "Creative & Design",
"author": "junkerderprovinz",
"developer": "ArtCraft",
"icon": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/.github/assets/icons/figcraft.png",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "https",
"port": 3001,
"path": "/"
},
"website": "https://getartcraft.com/apps/figcraft",
"documentation": "https://github.com/junkerderprovinz/artcraft-apps",
"repository": "https://github.com/storytold/figcraft",
"tips": [
"This is the native Linux application streamed by Selkies, not the WebAssembly build. Processing and documents stay in the LXC and its mounted directories.",
"The image is maintained by junkerderprovinz; ArtCraft publishes the application packages. It is not an official ArtCraft container image.",
"Use a trusted HTTPS reverse proxy for browser access. Port 3001 uses the upstream self-signed certificate; port 3000 is for an HTTP reverse-proxy backend.",
"The upstream default has no login. Optional CUSTOM_USER and PASSWORD variables enable HTTP basic authentication; do not expose an unauthenticated desktop to untrusted networks.",
"/config holds settings and desktop state and is included in Proxmox backups. /storage holds documents and supports a managed volume or an explicitly selected host directory; host directories require separate backups.",
"The default installation draws on the CPU. The advanced installation can assign an Intel or AMD GPU, which the desktop, the application and the video stream then use; NVIDIA is offered when the host has its driver and the NVIDIA Container Toolkit.",
"Without a GPU, an application may ask to switch to CPU rendering. Choose the CPU option; the application remembers it."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "junkerderprovinz",
"repository": "https://github.com/junkerderprovinz/artcraft-apps",
"revision": "32bee0dea9bdaf5310c693210bea0d732a129ae8",
"image_repository_url": "https://hub.docker.com/r/junkerderprovinz/figcraft",
"readme_pushed_at": "",
"compose_sha256": "b47cfa4e01943f509964b0027b9385d00fe6d233d31e24cdc117a4a4dd153262",
"generated_at": "2026-11-03T12:57:28+00:00",
"default_branch": "main",
"readme_raw_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/compose/figcraft.yaml"
},
"container_contract": {
"service_name": "figcraft",
"container_name": "figcraft",
"image": {
"reference": "docker.io/junkerderprovinz/figcraft:latest",
"registry": "docker.io",
"repository": "junkerderprovinz/figcraft",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "TZ",
"example": "Europe/Vienna",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PUID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PGID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "UMASK",
"example": "022",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "CUSTOM_USER",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation"
},
{
"name": "PASSWORD",
"example": "",
"required": false,
"sensitive": true,
"source": "upstream-documentation"
},
{
"name": "LC_ALL",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation",
"prompt": "Language/locale (e.g. es_ES.UTF-8; translation of every application is not guaranteed)"
}
],
"volumes": [
{
"id": "config",
"container_path": "/config",
"compose_source_example": "./appdata",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "storage",
"container_path": "/storage",
"compose_source_example": "./storage",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
}
],
"ports": [
{
"container_port": 3001,
"published_example": 3001,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 3000,
"published_example": 3000,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n figcraft:\n image: junkerderprovinz/figcraft:latest\n container_name: figcraft\n restart: unless-stopped\n shm_size: 1gb\n ports:\n - 3001:3001\n - 3000:3000\n volumes:\n - ./appdata:/config\n - ./storage:/storage\n environment:\n TZ: Europe/Vienna\n PUID: '1000'\n PGID: '1000'\n UMASK: '022'\n"
},
"compose_stack": {
"project_name": "figcraft",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "figcraft",
"service_count": 1,
"services": [
{
"name": "figcraft",
"image": "junkerderprovinz/figcraft:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "junkerderprovinz/figcraft:latest",
"container_name": "figcraft",
"restart": "unless-stopped",
"shm_size": "1gb",
"ports": [
"3001:3001",
"3000:3000"
],
"volumes": [
"./appdata:/config",
"./storage:/storage"
],
"environment": {
"TZ": "Europe/Vienna",
"PUID": "1000",
"PGID": "1000",
"UMASK": "022"
}
}
}
],
"top_level": {},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "figcraft-volume-0",
"service": "figcraft",
"container_path": "/config",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "figcraft-volume-1",
"service": "figcraft",
"container_path": "/storage",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"figcraft"
],
"stop_order": [
"figcraft"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": []
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "https",
"port": 3001,
"path": "/",
"source": "https://github.com/junkerderprovinz/artcraft-apps"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 2048,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"installer_profile": {
"tmpfs_mounts": [
{
"id": "compose-shm",
"container_path": "/dev/shm",
"default_size_mb": 1024,
"minimum_size_mb": 1,
"size_prompt": "Size of the /dev/shm shared memory in MB",
"mount_options": [
"rw",
"nosuid",
"nodev"
]
},
{
"id": "nginx-runtime",
"container_path": "/run/nginx",
"default_size_mb": 1,
"minimum_size_mb": 1,
"prompt_size": false,
"mount_options": [
"rw",
"nosuid",
"nodev",
"mode=0755"
]
}
],
"volume_preparations": [
{
"container_path": "/config",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/storage",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 3000,
"path": "/",
"timeout_seconds": 240,
"request_timeout_seconds": 5,
"stability_seconds": 8,
"accept_any_status": true,
"verify_tls": true
},
"selkies": {
"base": "FROM ghcr.io/linuxserver/baseimage-selkies:ubunturesolute@sha256:6efa3fd775a552938d862f75975d34c418ad26d028ba2c952da58682cfe1cb47",
"dockerfile_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/Dockerfile",
"dockerfile_sha256": "69ab1a81d1696d1bd143a6fa5a121c034ddfb3e83008969340e8cd2413547fe1",
"reviewed_on": "2026-11-04",
"documentation": "https://docs.linuxserver.io/images/docker-baseimage-selkies/",
"nvidia": "available-in-advanced-mode-with-compatible-host-driver-and-toolkit",
"validation": "Intel/AMD tested on a Radeon 680M: GL compositor and VAAPI encoding on the render node"
},
"device_requests": [],
"optional_devices": [],
"hardware_acceleration": {
"prompt": "Selkies desktop and streaming acceleration",
"default": "none",
"profiles": [
{
"id": "none",
"label": "No GPU (CPU)",
"device_requests": [],
"environment": [
{
"name": "AUTO_GPU",
"value": "false"
}
]
},
{
"id": "vaapi",
"label": "Intel/AMD (streaming rendering and encoding)",
"device_requests": [
{
"id": "selkies-render",
"kind": "character-device",
"path_prompt": "Intel/AMD render node",
"host_path_default": "/dev/dri/renderD128",
"container_path_strategy": "same-as-host",
"mode": "0660",
"deny_write": false,
"gid_strategy": "host-device-gid",
"drm_vendor_ids": [
"0x8086",
"0x1002"
]
}
],
"environment": [
{
"name": "PIXELFLUX_WAYLAND",
"value": "true"
},
{
"name": "AUTO_GPU",
"value": "false"
}
],
"environment_from_devices": {
"DRINODE": [
"selkies-render"
],
"DRI_NODE": [
"selkies-render"
],
"ATTACHED_DEVICES_PERMS": [
"selkies-render"
]
}
},
{
"id": "nvidia",
"label": "NVIDIA (Selkies rendering and NVENC)",
"device_requests": [
{
"id": "selkies-nvidia",
"kind": "nvidia-runtime",
"device_selection": "all-requested-by-compose"
}
],
"environment": [
{
"name": "AUTO_GPU",
"value": "true"
},
{
"name": "NVIDIA_VISIBLE_DEVICES",
"value": "all"
},
{
"name": "NVIDIA_DRIVER_CAPABILITIES",
"value": "compute,video,graphics,utility,display"
}
]
}
]
},
"gpu_validation": {
"device_inventory": "host-sysfs-and-stat",
"application_acceleration": "requires-workload-test",
"tone_mapping": "not-implied-by-device-access"
},
"device_permissions": {
"strategy": "linuxserver-native-init",
"service_user": "abc",
"environment": "ATTACHED_DEVICES_PERMS",
"paths": "all-resolved-selected-character-devices"
}
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "pending-per-application"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Community native-desktop image contract reviewed against its published Compose and Dockerfile. Linux amd64 and arm64 manifests exist; runtime, storage and lifecycle tests remain pending per architecture."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "pending",
"service_health": "pending",
"restart_persistence": "pending",
"backup_restore": "pending",
"update_preserves_data": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+677
View File
@@ -0,0 +1,677 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-filmcraft",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "FilmCraft",
"es_ES": "FilmCraft"
},
"tagline": {
"en_US": "Video editing in your browser",
"es_ES": "Edición de vídeo en el navegador"
},
"description": {
"en_US": "FilmCraft from the ArtCraft project, streamed from a native Linux application using the community-maintained junkerderprovinz image. Files are stored on the server, not in browser storage.",
"es_ES": "FilmCraft del proyecto ArtCraft, con su aplicación nativa de Linux transmitida al navegador mediante la imagen comunitaria de junkerderprovinz. Los documentos se guardan en el servidor, no en el almacenamiento del navegador."
},
"category": "creative",
"category_label": "Creative & Design",
"author": "junkerderprovinz",
"developer": "ArtCraft",
"icon": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/.github/assets/icons/filmcraft.png",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "https",
"port": 3001,
"path": "/"
},
"website": "https://getartcraft.com/apps/filmcraft",
"documentation": "https://github.com/junkerderprovinz/artcraft-apps",
"repository": "https://github.com/storytold/filmcraft",
"tips": [
"This is the native Linux application streamed by Selkies, not the WebAssembly build. Processing and documents stay in the LXC and its mounted directories.",
"The image is maintained by junkerderprovinz; ArtCraft publishes the application packages. It is not an official ArtCraft container image.",
"Use a trusted HTTPS reverse proxy for browser access. Port 3001 uses the upstream self-signed certificate; port 3000 is for an HTTP reverse-proxy backend.",
"The upstream default has no login. Optional CUSTOM_USER and PASSWORD variables enable HTTP basic authentication; do not expose an unauthenticated desktop to untrusted networks.",
"/config holds settings and desktop state and is included in Proxmox backups. /storage holds documents and supports a managed volume or an explicitly selected host directory; host directories require separate backups.",
"The default installation draws on the CPU. The advanced installation can assign an Intel or AMD GPU, which the desktop, the application and the video stream then use; NVIDIA is offered when the host has its driver and the NVIDIA Container Toolkit.",
"Without a GPU, an application may ask to switch to CPU rendering. Choose the CPU option; the application remembers it."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "junkerderprovinz",
"repository": "https://github.com/junkerderprovinz/artcraft-apps",
"revision": "32bee0dea9bdaf5310c693210bea0d732a129ae8",
"image_repository_url": "https://hub.docker.com/r/junkerderprovinz/filmcraft",
"readme_pushed_at": "",
"compose_sha256": "fa1e82ca686a530579d91c9d75184adb800453607baee37ad15ac3cfbf39d746",
"generated_at": "2026-11-03T12:57:28+00:00",
"default_branch": "main",
"readme_raw_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/compose/filmcraft.yaml"
},
"container_contract": {
"service_name": "filmcraft",
"container_name": "filmcraft",
"image": {
"reference": "docker.io/junkerderprovinz/filmcraft:latest",
"registry": "docker.io",
"repository": "junkerderprovinz/filmcraft",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "TZ",
"example": "Europe/Vienna",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PUID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PGID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "UMASK",
"example": "022",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "CUSTOM_USER",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation"
},
{
"name": "PASSWORD",
"example": "",
"required": false,
"sensitive": true,
"source": "upstream-documentation"
},
{
"name": "LC_ALL",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation",
"prompt": "Language/locale (e.g. es_ES.UTF-8; translation of every application is not guaranteed)"
}
],
"volumes": [
{
"id": "config",
"container_path": "/config",
"compose_source_example": "./appdata",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "storage",
"container_path": "/storage",
"compose_source_example": "./storage",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
}
],
"ports": [
{
"container_port": 3001,
"published_example": 3001,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 3000,
"published_example": 3000,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n filmcraft:\n image: junkerderprovinz/filmcraft:latest\n container_name: filmcraft\n restart: unless-stopped\n shm_size: 1gb\n ports:\n - 3001:3001\n - 3000:3000\n volumes:\n - ./appdata:/config\n - ./storage:/storage\n environment:\n TZ: Europe/Vienna\n PUID: '1000'\n PGID: '1000'\n UMASK: '022'\n"
},
"compose_stack": {
"project_name": "filmcraft",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "filmcraft",
"service_count": 1,
"services": [
{
"name": "filmcraft",
"image": "junkerderprovinz/filmcraft:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "junkerderprovinz/filmcraft:latest",
"container_name": "filmcraft",
"restart": "unless-stopped",
"shm_size": "1gb",
"ports": [
"3001:3001",
"3000:3000"
],
"volumes": [
"./appdata:/config",
"./storage:/storage"
],
"environment": {
"TZ": "Europe/Vienna",
"PUID": "1000",
"PGID": "1000",
"UMASK": "022"
}
}
}
],
"top_level": {},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "filmcraft-volume-0",
"service": "filmcraft",
"container_path": "/config",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "filmcraft-volume-1",
"service": "filmcraft",
"container_path": "/storage",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"filmcraft"
],
"stop_order": [
"filmcraft"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": []
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "https",
"port": 3001,
"path": "/",
"source": "https://github.com/junkerderprovinz/artcraft-apps"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 2048,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"installer_profile": {
"tmpfs_mounts": [
{
"id": "compose-shm",
"container_path": "/dev/shm",
"default_size_mb": 1024,
"minimum_size_mb": 1,
"size_prompt": "Size of the /dev/shm shared memory in MB",
"mount_options": [
"rw",
"nosuid",
"nodev"
]
},
{
"id": "nginx-runtime",
"container_path": "/run/nginx",
"default_size_mb": 1,
"minimum_size_mb": 1,
"prompt_size": false,
"mount_options": [
"rw",
"nosuid",
"nodev",
"mode=0755"
]
}
],
"volume_preparations": [
{
"container_path": "/config",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/storage",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 3000,
"path": "/",
"timeout_seconds": 240,
"request_timeout_seconds": 5,
"stability_seconds": 8,
"accept_any_status": true,
"verify_tls": true
},
"selkies": {
"base": "FROM ghcr.io/linuxserver/baseimage-selkies:ubunturesolute@sha256:6efa3fd775a552938d862f75975d34c418ad26d028ba2c952da58682cfe1cb47",
"dockerfile_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/Dockerfile",
"dockerfile_sha256": "69ab1a81d1696d1bd143a6fa5a121c034ddfb3e83008969340e8cd2413547fe1",
"reviewed_on": "2026-11-04",
"documentation": "https://docs.linuxserver.io/images/docker-baseimage-selkies/",
"nvidia": "available-in-advanced-mode-with-compatible-host-driver-and-toolkit",
"validation": "Intel/AMD tested on a Radeon 680M: GL compositor and VAAPI encoding on the render node"
},
"device_requests": [],
"optional_devices": [],
"hardware_acceleration": {
"prompt": "Selkies desktop and streaming acceleration",
"default": "none",
"profiles": [
{
"id": "none",
"label": "No GPU (CPU)",
"device_requests": [],
"environment": [
{
"name": "AUTO_GPU",
"value": "false"
}
]
},
{
"id": "vaapi",
"label": "Intel/AMD (streaming rendering and encoding)",
"device_requests": [
{
"id": "selkies-render",
"kind": "character-device",
"path_prompt": "Intel/AMD render node",
"host_path_default": "/dev/dri/renderD128",
"container_path_strategy": "same-as-host",
"mode": "0660",
"deny_write": false,
"gid_strategy": "host-device-gid",
"drm_vendor_ids": [
"0x8086",
"0x1002"
]
}
],
"environment": [
{
"name": "PIXELFLUX_WAYLAND",
"value": "true"
},
{
"name": "AUTO_GPU",
"value": "false"
}
],
"environment_from_devices": {
"DRINODE": [
"selkies-render"
],
"DRI_NODE": [
"selkies-render"
],
"ATTACHED_DEVICES_PERMS": [
"selkies-render"
]
}
},
{
"id": "nvidia",
"label": "NVIDIA (Selkies rendering and NVENC)",
"device_requests": [
{
"id": "selkies-nvidia",
"kind": "nvidia-runtime",
"device_selection": "all-requested-by-compose"
}
],
"environment": [
{
"name": "AUTO_GPU",
"value": "true"
},
{
"name": "NVIDIA_VISIBLE_DEVICES",
"value": "all"
},
{
"name": "NVIDIA_DRIVER_CAPABILITIES",
"value": "compute,video,graphics,utility,display"
}
]
}
]
},
"gpu_validation": {
"device_inventory": "host-sysfs-and-stat",
"application_acceleration": "requires-workload-test",
"tone_mapping": "not-implied-by-device-access"
},
"device_permissions": {
"strategy": "linuxserver-native-init",
"service_user": "abc",
"environment": "ATTACHED_DEVICES_PERMS",
"paths": "all-resolved-selected-character-devices"
}
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "pending-per-application"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Community native-desktop image contract reviewed against its published Compose and Dockerfile. Linux amd64 and arm64 manifests exist; runtime, storage and lifecycle tests remain pending per architecture."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "pending",
"service_health": "pending",
"restart_persistence": "pending",
"backup_restore": "pending",
"update_preserves_data": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+4 -1
View File
@@ -409,7 +409,10 @@
"request_timeout_seconds": 10,
"stability_seconds": 4,
"verify_tls": true
}
},
"non_persistent_image_volumes": [
"/gotosocial/.cache"
]
}
},
"compatibility": {
+677
View File
@@ -0,0 +1,677 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-gridcraft",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "GridCraft",
"es_ES": "GridCraft"
},
"tagline": {
"en_US": "Spreadsheets in your browser",
"es_ES": "Hojas de cálculo en el navegador"
},
"description": {
"en_US": "GridCraft from the ArtCraft project, streamed from a native Linux application using the community-maintained junkerderprovinz image. Files are stored on the server, not in browser storage.",
"es_ES": "GridCraft del proyecto ArtCraft, con su aplicación nativa de Linux transmitida al navegador mediante la imagen comunitaria de junkerderprovinz. Los documentos se guardan en el servidor, no en el almacenamiento del navegador."
},
"category": "creative",
"category_label": "Creative & Design",
"author": "junkerderprovinz",
"developer": "ArtCraft",
"icon": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/.github/assets/icons/gridcraft.png",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "https",
"port": 3001,
"path": "/"
},
"website": "https://getartcraft.com/apps/gridcraft",
"documentation": "https://github.com/junkerderprovinz/artcraft-apps",
"repository": "https://github.com/storytold/gridcraft",
"tips": [
"This is the native Linux application streamed by Selkies, not the WebAssembly build. Processing and documents stay in the LXC and its mounted directories.",
"The image is maintained by junkerderprovinz; ArtCraft publishes the application packages. It is not an official ArtCraft container image.",
"Use a trusted HTTPS reverse proxy for browser access. Port 3001 uses the upstream self-signed certificate; port 3000 is for an HTTP reverse-proxy backend.",
"The upstream default has no login. Optional CUSTOM_USER and PASSWORD variables enable HTTP basic authentication; do not expose an unauthenticated desktop to untrusted networks.",
"/config holds settings and desktop state and is included in Proxmox backups. /storage holds documents and supports a managed volume or an explicitly selected host directory; host directories require separate backups.",
"The default installation draws on the CPU. The advanced installation can assign an Intel or AMD GPU, which the desktop, the application and the video stream then use; NVIDIA is offered when the host has its driver and the NVIDIA Container Toolkit.",
"Without a GPU, an application may ask to switch to CPU rendering. Choose the CPU option; the application remembers it."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "junkerderprovinz",
"repository": "https://github.com/junkerderprovinz/artcraft-apps",
"revision": "32bee0dea9bdaf5310c693210bea0d732a129ae8",
"image_repository_url": "https://hub.docker.com/r/junkerderprovinz/gridcraft",
"readme_pushed_at": "",
"compose_sha256": "dcd244dd54033b4a00e1220ff8885ba26a5508414ab5069f7ab9456476fbb420",
"generated_at": "2026-11-03T12:57:29+00:00",
"default_branch": "main",
"readme_raw_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/compose/gridcraft.yaml"
},
"container_contract": {
"service_name": "gridcraft",
"container_name": "gridcraft",
"image": {
"reference": "docker.io/junkerderprovinz/gridcraft:latest",
"registry": "docker.io",
"repository": "junkerderprovinz/gridcraft",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "TZ",
"example": "Europe/Vienna",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PUID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PGID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "UMASK",
"example": "022",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "CUSTOM_USER",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation"
},
{
"name": "PASSWORD",
"example": "",
"required": false,
"sensitive": true,
"source": "upstream-documentation"
},
{
"name": "LC_ALL",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation",
"prompt": "Language/locale (e.g. es_ES.UTF-8; translation of every application is not guaranteed)"
}
],
"volumes": [
{
"id": "config",
"container_path": "/config",
"compose_source_example": "./appdata",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "storage",
"container_path": "/storage",
"compose_source_example": "./storage",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
}
],
"ports": [
{
"container_port": 3001,
"published_example": 3001,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 3000,
"published_example": 3000,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n gridcraft:\n image: junkerderprovinz/gridcraft:latest\n container_name: gridcraft\n restart: unless-stopped\n shm_size: 1gb\n ports:\n - 3001:3001\n - 3000:3000\n volumes:\n - ./appdata:/config\n - ./storage:/storage\n environment:\n TZ: Europe/Vienna\n PUID: '1000'\n PGID: '1000'\n UMASK: '022'\n"
},
"compose_stack": {
"project_name": "gridcraft",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "gridcraft",
"service_count": 1,
"services": [
{
"name": "gridcraft",
"image": "junkerderprovinz/gridcraft:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "junkerderprovinz/gridcraft:latest",
"container_name": "gridcraft",
"restart": "unless-stopped",
"shm_size": "1gb",
"ports": [
"3001:3001",
"3000:3000"
],
"volumes": [
"./appdata:/config",
"./storage:/storage"
],
"environment": {
"TZ": "Europe/Vienna",
"PUID": "1000",
"PGID": "1000",
"UMASK": "022"
}
}
}
],
"top_level": {},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "gridcraft-volume-0",
"service": "gridcraft",
"container_path": "/config",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "gridcraft-volume-1",
"service": "gridcraft",
"container_path": "/storage",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"gridcraft"
],
"stop_order": [
"gridcraft"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": []
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "https",
"port": 3001,
"path": "/",
"source": "https://github.com/junkerderprovinz/artcraft-apps"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 2048,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"installer_profile": {
"tmpfs_mounts": [
{
"id": "compose-shm",
"container_path": "/dev/shm",
"default_size_mb": 1024,
"minimum_size_mb": 1,
"size_prompt": "Size of the /dev/shm shared memory in MB",
"mount_options": [
"rw",
"nosuid",
"nodev"
]
},
{
"id": "nginx-runtime",
"container_path": "/run/nginx",
"default_size_mb": 1,
"minimum_size_mb": 1,
"prompt_size": false,
"mount_options": [
"rw",
"nosuid",
"nodev",
"mode=0755"
]
}
],
"volume_preparations": [
{
"container_path": "/config",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/storage",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 3000,
"path": "/",
"timeout_seconds": 240,
"request_timeout_seconds": 5,
"stability_seconds": 8,
"accept_any_status": true,
"verify_tls": true
},
"selkies": {
"base": "FROM ghcr.io/linuxserver/baseimage-selkies:ubunturesolute@sha256:6efa3fd775a552938d862f75975d34c418ad26d028ba2c952da58682cfe1cb47",
"dockerfile_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/Dockerfile",
"dockerfile_sha256": "69ab1a81d1696d1bd143a6fa5a121c034ddfb3e83008969340e8cd2413547fe1",
"reviewed_on": "2026-11-04",
"documentation": "https://docs.linuxserver.io/images/docker-baseimage-selkies/",
"nvidia": "available-in-advanced-mode-with-compatible-host-driver-and-toolkit",
"validation": "Intel/AMD tested on a Radeon 680M: GL compositor and VAAPI encoding on the render node"
},
"device_requests": [],
"optional_devices": [],
"hardware_acceleration": {
"prompt": "Selkies desktop and streaming acceleration",
"default": "none",
"profiles": [
{
"id": "none",
"label": "No GPU (CPU)",
"device_requests": [],
"environment": [
{
"name": "AUTO_GPU",
"value": "false"
}
]
},
{
"id": "vaapi",
"label": "Intel/AMD (streaming rendering and encoding)",
"device_requests": [
{
"id": "selkies-render",
"kind": "character-device",
"path_prompt": "Intel/AMD render node",
"host_path_default": "/dev/dri/renderD128",
"container_path_strategy": "same-as-host",
"mode": "0660",
"deny_write": false,
"gid_strategy": "host-device-gid",
"drm_vendor_ids": [
"0x8086",
"0x1002"
]
}
],
"environment": [
{
"name": "PIXELFLUX_WAYLAND",
"value": "true"
},
{
"name": "AUTO_GPU",
"value": "false"
}
],
"environment_from_devices": {
"DRINODE": [
"selkies-render"
],
"DRI_NODE": [
"selkies-render"
],
"ATTACHED_DEVICES_PERMS": [
"selkies-render"
]
}
},
{
"id": "nvidia",
"label": "NVIDIA (Selkies rendering and NVENC)",
"device_requests": [
{
"id": "selkies-nvidia",
"kind": "nvidia-runtime",
"device_selection": "all-requested-by-compose"
}
],
"environment": [
{
"name": "AUTO_GPU",
"value": "true"
},
{
"name": "NVIDIA_VISIBLE_DEVICES",
"value": "all"
},
{
"name": "NVIDIA_DRIVER_CAPABILITIES",
"value": "compute,video,graphics,utility,display"
}
]
}
]
},
"gpu_validation": {
"device_inventory": "host-sysfs-and-stat",
"application_acceleration": "requires-workload-test",
"tone_mapping": "not-implied-by-device-access"
},
"device_permissions": {
"strategy": "linuxserver-native-init",
"service_user": "abc",
"environment": "ATTACHED_DEVICES_PERMS",
"paths": "all-resolved-selected-character-devices"
}
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "pending-per-application"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Community native-desktop image contract reviewed against its published Compose and Dockerfile. Linux amd64 and arm64 manifests exist; runtime, storage and lifecycle tests remain pending per architecture."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "pending",
"service_health": "pending",
"restart_persistence": "pending",
"backup_restore": "pending",
"update_preserves_data": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+1 -1
View File
@@ -17,7 +17,7 @@
"category_label": "AI / Coding & Dev-Tools",
"author": "Nous Research",
"developer": "Nous Research",
"icon": "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@main/webp/hermes.webp",
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/hermes-agent.webp",
"thumbnail": null,
"screenshots": [],
"architectures": [
+5 -1
View File
@@ -345,7 +345,11 @@
"validation": "not-requested-by-compose"
}
],
"installer_profile": {},
"installer_profile": {
"non_persistent_image_volumes": [
"/tmp"
]
},
"catalog": {
"replaces_discovered_ids": []
}
+35 -1
View File
@@ -94,6 +94,22 @@
"backup": true,
"default_size_gb": 8
}
},
{
"id": "volume-2",
"container_path": "/etc/nginx/ssl",
"compose_source_example": "./ssl",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 1
}
}
],
"ports": [
@@ -134,7 +150,8 @@
],
"volumes": [
"./data:/var/www/app/data",
"./plugins:/var/www/app/plugins"
"./plugins:/var/www/app/plugins",
"./ssl:/etc/nginx/ssl"
]
}
}
@@ -171,6 +188,17 @@
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "kanboard-volume-2",
"service": "kanboard",
"container_path": "/etc/nginx/ssl",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
@@ -391,6 +419,12 @@
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/etc/nginx/ssl",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
}
],
"startup_healthcheck": {
+383
View File
@@ -0,0 +1,383 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-kitchenowl",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "KitchenOwl"
},
"tagline": {
"en_US": "Self-hosted grocery list and recipe manager"
},
"description": {
"en_US": "Manage shared shopping lists, recipes and meal plans in one self-hosted app."
},
"category": "productivity",
"category_label": "Productivity & Workflows",
"author": "Tom Bursch",
"developer": "Tom Bursch",
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/kitchenowl.webp",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "http",
"port": 80,
"path": "/"
},
"website": "https://kitchenowl.org/",
"documentation": "https://docs.kitchenowl.org/self-hosting/",
"repository": "https://github.com/TomBursch/kitchenowl",
"tips": [
"This recipe follows KitchenOwl’s standard official Compose deployment: a web frontend and backend in separate OCI LXCs.",
"The upstream sample uses PLEASE_CHANGE_ME for JWT_SECRET_KEY; this recipe generates a unique signing key at install time."
],
"mini_changelog": [],
"display_version": null,
"updated_at": "2026-11-01"
},
"source": {
"provider": "tombursch",
"repository": "https://github.com/TomBursch/kitchenowl",
"revision": "60a012ea5cae829878f78a46a585a7ee530b069a",
"image_repository_url": "https://hub.docker.com/r/tombursch/kitchenowl-web",
"readme_pushed_at": "2026-11-01T23:22:22Z",
"compose_sha256": "f620124c2a4943d4f2465ee304677bc9ed172a088f0fe43f5db7cbc8f6424263",
"generated_at": "2026-11-02T20:13:05+00:00",
"default_branch": "main",
"readme_raw_url": "https://raw.githubusercontent.com/TomBursch/kitchenowl/main/docker-compose.yml"
},
"container_contract": {
"service_name": "front",
"container_name": "front",
"image": {
"reference": "tombursch/kitchenowl-web:latest",
"registry": "docker.io",
"repository": "tombursch/kitchenowl-web",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [],
"volumes": [],
"ports": [
{
"container_port": 80,
"published_example": 80,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [
{
"name": "back",
"image": "tombursch/kitchenowl-backend:latest"
}
],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n back:\n environment:\n JWT_SECRET_KEY: ${GENERATED_JWT_SECRET_KEY}\n image: tombursch/kitchenowl-backend:latest\n restart: unless-stopped\n volumes:\n - read_only: false\n source: kitchenowl_data\n target: /data\n front:\n depends_on:\n - back\n image: tombursch/kitchenowl-web:latest\n ports:\n - 80:80\n restart: unless-stopped\n volumes: []\nvolumes:\n kitchenowl_data: null\n"
},
"compose_stack": {
"project_name": "kitchenowl",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "front",
"service_count": 2,
"services": [
{
"name": "back",
"image": "tombursch/kitchenowl-backend:latest",
"is_main": false,
"role": "dependency",
"vmid_offset": 1,
"depends_on": [],
"frontend_network": false,
"private_network": true,
"compose": {
"environment": {
"JWT_SECRET_KEY": "${GENERATED_JWT_SECRET_KEY}"
},
"image": "tombursch/kitchenowl-backend:latest",
"restart": "unless-stopped",
"volumes": [
{
"source": "kitchenowl_data",
"target": "/data",
"read_only": false
}
],
"healthcheck": {
"test": [
"CMD-SHELL",
"uwsgi_curl localhost:5000 /api/health/8M4F88S8ooi4sMbLBfkkV7ctWwgibW6V || exit 1"
],
"interval": "60s",
"timeout": "3s",
"retries": 3
}
}
},
{
"name": "front",
"image": "tombursch/kitchenowl-web:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [
"back"
],
"frontend_network": true,
"private_network": true,
"compose": {
"depends_on": [
"back"
],
"image": "tombursch/kitchenowl-web:latest",
"ports": [
"80:80"
],
"restart": "unless-stopped",
"volumes": [],
"healthcheck": {
"test": [
"CMD-SHELL",
"curl -f http://localhost/ || exit 1"
],
"interval": "30s",
"timeout": "3s",
"retries": 3
}
}
}
],
"top_level": {
"volumes": {
"kitchenowl_data": null
}
},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": true,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "back-volume-0",
"service": "back",
"container_path": "/data",
"mode": "managed-volume",
"user_selectable": true,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 2,
"start_order": [
"back",
"front"
],
"stop_order": [
"front",
"back"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": [
{
"id": "generated-jwt-secret-key",
"strategy": "generate-cryptographically-random-at-install",
"bindings": [
{
"service": "back",
"environment_variable": "JWT_SECRET_KEY"
}
]
}
]
}
},
"first_run": {
"endpoints": [
{
"label": "KitchenOwl",
"scheme": "http",
"port": 80,
"path": "/",
"source": "upstream-documentation"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"adaptations": [
{
"id": "generated-jwt-signing-key",
"upstream_behavior": "The official Compose example uses the placeholder PLEASE_CHANGE_ME for JWT_SECRET_KEY and instructs operators to replace it.",
"native_lxc_behavior": "ProxMenux generates a unique cryptographically random JWT signing key and supplies it to the backend service.",
"reason": "Avoid deploying the documented placeholder or placing a signing secret in the public recipe.",
"behavioral_impact": "The generated key is not an app login credential; KitchenOwl has no catalog-provided default account.",
"validation": "pending-runtime"
},
{
"id": "image-healthchecks-preserved",
"upstream_behavior": "The web and backend OCI images declare Docker healthchecks in image metadata.",
"native_lxc_behavior": "The current image healthchecks are recorded in the stack so ProxMenux can check backend readiness and frontend availability during first start.",
"reason": "The Compose file inherits these checks from its images instead of declaring them itself.",
"behavioral_impact": "Checks gate stack startup; Docker does not run as a separate health-monitoring daemon inside the LXCs.",
"validation": "pending-runtime"
}
],
"custom_compose_stack": true,
"custom_compose_interpolated": false,
"stack_image_entrypoints": {},
"installer_profile": {
"stack_driver": "generic-multi-lxc-stack",
"volume_preparations": [
{
"container_path": "/data",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
}
]
},
"stack_completion_notes": [
"Open the web address and follow KitchenOwl’s onboarding to create the first account; no default account is configured."
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "The official two-image Compose stack is mapped to native Proxmox OCI LXCs with private service networking. Lab checks confirmed installation, web/API behavior, persistence, backup and recovery, modification, managed storage, and host-bind storage. Advanced custom settings have not been validated."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "passed-default-official-two-service-stack-and-first-start",
"advanced_install": "pending-custom-install-summary-validation",
"service_health": "passed-web-api-and-created-user-household-list-item",
"restart_persistence": "passed-managed-and-host-bind-data",
"backup_restore": "passed-manager-recover-new-vmids-stack-network-and-data",
"update_preserves_data": "no-update-available-at-check",
"modification": "passed-added-managed-volume-without-image-pull-or-container-recreate",
"volumes": "passed-managed-storage-and-host-bind-with-owner-and-data-check",
"removal": "passed-manager-removal-temporary-data-cleaned-after-retention-check"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false,
"dependency_lifecycle": {
"implementation": "proxmox-hookscript",
"trigger": "main-lxc-pre-start",
"waits_for_dependency_healthchecks": true,
"stops_dependencies_with_main": false
}
}
}
+490
View File
@@ -0,0 +1,490 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-krusader",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "Krusader",
"es_ES": "Krusader"
},
"tagline": {
"en_US": "KDE's twin-panel file manager in a browser-based desktop.",
"es_ES": "El gestor de archivos de dos paneles de KDE, disponible desde el navegador."
},
"description": {
"en_US": "Open Krusader in a browser and manage files from a directory you explicitly mount at /storage. The maintained jlesage image provides the graphical desktop; ProxMenux runs it as one native OCI LXC.",
"es_ES": "Abre Krusader en el navegador y gestiona los archivos de una carpeta que montes expresamente en /storage. La imagen mantenida por jlesage incluye el escritorio gráfico; ProxMenux la ejecuta como un LXC OCI nativo."
},
"category": "desktop",
"category_label": "Browsers & Web Desktops",
"author": "jlesage",
"developer": "jlesage",
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/krusader.webp",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "https",
"port": 5800,
"path": "/"
},
"website": "https://krusader.org/",
"documentation": "https://github.com/jlesage/docker-krusader",
"repository": "https://github.com/jlesage/docker-krusader",
"tips": [
"The web login uses HTTPS with an automatically generated self-signed certificate and password. Accept the certificate warning on the first visit or configure a trusted certificate.",
"Krusader can read, change and delete files in the directory mounted at /storage. Mount only the directory you intend to manage; the rest of the Proxmox host is not exposed.",
"The VNC port is not published. Use the browser interface on port 5800."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "jlesage",
"repository": "https://github.com/jlesage/docker-krusader",
"revision": "855c8140e1bb65b2a2526d82db44c808f23eb49f",
"image_repository_url": "https://hub.docker.com/r/jlesage/krusader",
"readme_pushed_at": "2026-09-22T15:18:17Z",
"compose_sha256": "9dd16cc30aa19afe7e148598c9cfb0c65c31606d67f3f22254c33a4d05212c7f",
"generated_at": "2026-11-02T20:05:40+00:00",
"default_branch": "master",
"readme_raw_url": "https://raw.githubusercontent.com/jlesage/docker-krusader/855c8140e1bb65b2a2526d82db44c808f23eb49f/README.md"
},
"container_contract": {
"service_name": "krusader",
"container_name": "krusader",
"image": {
"reference": "jlesage/krusader:latest",
"registry": "docker.io",
"repository": "jlesage/krusader",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "USER_ID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-image-default"
},
{
"name": "GROUP_ID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-image-default"
},
{
"name": "TZ",
"example": "Europe/Madrid",
"required": true,
"sensitive": false,
"source": "ProxMenux-local-timezone"
},
{
"name": "VNC_LOCALHOST_ONLY",
"example": "1",
"required": true,
"sensitive": false,
"source": "upstream-image-security-setting"
},
{
"name": "WEB_AUTHENTICATION",
"example": "1",
"required": true,
"sensitive": false,
"source": "upstream-image-security-setting"
},
{
"name": "WEB_AUTHENTICATION_USERNAME",
"example": "admin",
"required": true,
"sensitive": false,
"source": "upstream-image-security-setting"
},
{
"name": "WEB_AUTHENTICATION_PASSWORD",
"example": "${GENERATED_WEB_PASSWORD}",
"required": true,
"sensitive": true,
"source": "ProxMenux-generated-credential"
},
{
"name": "SECURE_CONNECTION",
"example": "1",
"required": true,
"sensitive": false,
"source": "upstream-image-security-setting"
}
],
"volumes": [
{
"id": "krusader-config",
"container_path": "/config",
"compose_source_example": "krusader-config",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 4
}
},
{
"id": "krusader-storage",
"container_path": "/storage",
"compose_source_example": "/mnt/oci-shared/krusader/storage",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "host-bind",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
}
],
"ports": [
{
"container_port": 5800,
"published_example": 5800,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "name: krusader\nservices:\n krusader:\n image: jlesage/krusader:latest\n container_name: krusader\n restart: unless-stopped\n environment:\n USER_ID: '1000'\n GROUP_ID: '1000'\n TZ: Europe/Madrid\n VNC_LOCALHOST_ONLY: '1'\n WEB_AUTHENTICATION: '1'\n WEB_AUTHENTICATION_USERNAME: admin\n WEB_AUTHENTICATION_PASSWORD: ${GENERATED_WEB_PASSWORD}\n SECURE_CONNECTION: '1'\n ports:\n - 5800:5800/tcp\n volumes:\n - krusader-config:/config\n - /mnt/oci-shared/krusader/storage:/storage\nvolumes:\n krusader-config: {}\n"
},
"compose_stack": {
"project_name": "krusader",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "krusader",
"service_count": 1,
"services": [
{
"name": "krusader",
"image": "jlesage/krusader:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"environment": {
"GROUP_ID": "1000",
"SECURE_CONNECTION": "1",
"TZ": "Europe/Madrid",
"USER_ID": "1000",
"VNC_LOCALHOST_ONLY": "1",
"WEB_AUTHENTICATION": "1",
"WEB_AUTHENTICATION_PASSWORD": "${GENERATED_GENERATED_WEB_PASSWORD}",
"WEB_AUTHENTICATION_USERNAME": "admin"
},
"image": "jlesage/krusader:latest",
"ports": [
"5800:5800"
],
"volumes": [
"./config:/config",
"./storage:/storage"
]
}
}
],
"top_level": {
"name": "krusader"
},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "krusader-volume-0",
"service": "krusader",
"container_path": "/config",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "krusader-volume-1",
"service": "krusader",
"container_path": "/storage",
"mode": "user-selectable",
"user_selectable": true,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": "Host directory for Krusader:/storage",
"default": "host-bind",
"installation_choice": [
"managed-volume",
"host-bind"
]
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"krusader"
],
"stop_order": [
"krusader"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": [
{
"id": "generated-web-password",
"strategy": "generate-cryptographically-random-at-install",
"bindings": [
{
"service": "krusader",
"environment_variable": "WEB_AUTHENTICATION_PASSWORD"
}
]
}
]
}
},
"first_run": {
"endpoints": [
{
"label": "Krusader Web UI",
"scheme": "https",
"port": 5800,
"path": "/",
"source": "upstream-jlesage-secure-connection-and-web-authentication"
}
],
"credentials": [
{
"label": "Krusader Web UI",
"type": "configured-or-installer-generated",
"username": "admin",
"password": null,
"username_environment": "WEB_AUTHENTICATION_USERNAME",
"password_environment": "WEB_AUTHENTICATION_PASSWORD",
"change_required": false,
"source": "ProxMenux generated password and upstream image environment",
"retrieval": null
}
]
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 2048,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"adaptations": [
{
"id": "web-authentication-https",
"upstream_behavior": "The jlesage image can protect its browser GUI with WEB_AUTHENTICATION and requires SECURE_CONNECTION for authenticated web access.",
"native_lxc_behavior": "Enable authenticated HTTPS on port 5800, generate a unique password at install and keep VNC bound to localhost.",
"reason": "Krusader can modify files exposed under /storage, so the browser endpoint must not be unauthenticated.",
"behavioral_impact": "The image generates a self-signed TLS certificate; a browser may ask to trust it on first access.",
"validation": "pending"
},
{
"id": "scoped-storage-mount",
"upstream_behavior": "Docker Compose mounts the selected host directory at /storage.",
"native_lxc_behavior": "The same selected directory is mounted in the dedicated OCI LXC; no other host paths are exposed.",
"reason": "The file manager must only see data explicitly selected by the user.",
"behavioral_impact": "Write access permits changing or deleting files in that one directory.",
"validation": "pending"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes web port 5800 on the Docker host.",
"native_lxc_behavior": "The native LXC listens on its own IP at port 5800 without Docker NAT.",
"reason": "The LXC has a dedicated network namespace and address.",
"behavioral_impact": "The port is reached at the LXC address rather than through a host-published port.",
"validation": "pending"
}
],
"installer_profile": {
"volume_preparations": [
{
"container_path": "/config",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"uid": 1000,
"gid": 1000,
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/storage",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"uid": 1000,
"gid": 1000,
"only_when_mount_type": "managed-volume"
}
],
"startup_healthcheck": {
"scheme": "https",
"port": 5800,
"path": "/",
"timeout_seconds": 240,
"request_timeout_seconds": 10,
"stability_seconds": 4,
"verify_tls": false
},
"generated_sensitive_environment": {
"WEB_AUTHENTICATION_PASSWORD": {
"strategy": "token-hex",
"bytes": 16,
"prompt": false
}
},
"volume_owner": {
"uid": 1000,
"gid": 1000
}
}
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "passed-first-start",
"service_health": "passed-login-page-and-authenticated-session-http-200",
"restart_persistence": "passed-container-restart-and-host-bind-write-check",
"backup_restore": "pending",
"update_preserves_data": "pending",
"image_resolution": "passed-skopeo-327mb-11-layers-integrity",
"credentials": "passed-generated-password-login-and-session-cookie",
"advanced_install": "pending-custom-install-summary-validation",
"managed_volume": "passed-managed-config-volume",
"host_bind": "passed-storage-bind-owner-and-app-user-write",
"browser_visual": "pending-self-signed-certificate-review",
"modification": "pending",
"removal": "passed-manager-remove-ct-disks-record-and-empty-test-path-cleaned",
"web_authentication": "passed-generated-credential-post-and-session-cookie"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": "amd64",
"resolved_digest": "sha256:ecb77bb73b1d3c66720eefb07805f70289349b449d1ddaa15d120c399bd89cc4",
"image_version_label": "26.09.1",
"image_created": "2026-09-22T15:22:56.230858151Z"
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+677
View File
@@ -0,0 +1,677 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-lightcraft",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "LightCraft",
"es_ES": "LightCraft"
},
"tagline": {
"en_US": "Photo library and RAW development in your browser",
"es_ES": "Biblioteca de fotos y revelado RAW en el navegador"
},
"description": {
"en_US": "LightCraft from the ArtCraft project, streamed from a native Linux application using the community-maintained junkerderprovinz image. Files are stored on the server, not in browser storage.",
"es_ES": "LightCraft del proyecto ArtCraft, con su aplicación nativa de Linux transmitida al navegador mediante la imagen comunitaria de junkerderprovinz. Los documentos se guardan en el servidor, no en el almacenamiento del navegador."
},
"category": "creative",
"category_label": "Creative & Design",
"author": "junkerderprovinz",
"developer": "ArtCraft",
"icon": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/.github/assets/icons/lightcraft.png",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "https",
"port": 3001,
"path": "/"
},
"website": "https://getartcraft.com/apps/lightcraft",
"documentation": "https://github.com/junkerderprovinz/artcraft-apps",
"repository": "https://github.com/storytold/lightcraft",
"tips": [
"This is the native Linux application streamed by Selkies, not the WebAssembly build. Processing and documents stay in the LXC and its mounted directories.",
"The image is maintained by junkerderprovinz; ArtCraft publishes the application packages. It is not an official ArtCraft container image.",
"Use a trusted HTTPS reverse proxy for browser access. Port 3001 uses the upstream self-signed certificate; port 3000 is for an HTTP reverse-proxy backend.",
"The upstream default has no login. Optional CUSTOM_USER and PASSWORD variables enable HTTP basic authentication; do not expose an unauthenticated desktop to untrusted networks.",
"/config holds settings and desktop state and is included in Proxmox backups. /storage holds documents and supports a managed volume or an explicitly selected host directory; host directories require separate backups.",
"The default installation draws on the CPU. The advanced installation can assign an Intel or AMD GPU, which the desktop, the application and the video stream then use; NVIDIA is offered when the host has its driver and the NVIDIA Container Toolkit.",
"Without a GPU, an application may ask to switch to CPU rendering. Choose the CPU option; the application remembers it."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "junkerderprovinz",
"repository": "https://github.com/junkerderprovinz/artcraft-apps",
"revision": "32bee0dea9bdaf5310c693210bea0d732a129ae8",
"image_repository_url": "https://hub.docker.com/r/junkerderprovinz/lightcraft",
"readme_pushed_at": "",
"compose_sha256": "26d20ee6d028b198f569b66116ff5b55d7ab08f2cc26a13400d0e444ce10ba0f",
"generated_at": "2026-11-03T12:57:29+00:00",
"default_branch": "main",
"readme_raw_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/compose/lightcraft.yaml"
},
"container_contract": {
"service_name": "lightcraft",
"container_name": "lightcraft",
"image": {
"reference": "docker.io/junkerderprovinz/lightcraft:latest",
"registry": "docker.io",
"repository": "junkerderprovinz/lightcraft",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "TZ",
"example": "Europe/Vienna",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PUID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PGID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "UMASK",
"example": "022",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "CUSTOM_USER",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation"
},
{
"name": "PASSWORD",
"example": "",
"required": false,
"sensitive": true,
"source": "upstream-documentation"
},
{
"name": "LC_ALL",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation",
"prompt": "Language/locale (e.g. es_ES.UTF-8; translation of every application is not guaranteed)"
}
],
"volumes": [
{
"id": "config",
"container_path": "/config",
"compose_source_example": "./appdata",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "storage",
"container_path": "/storage",
"compose_source_example": "./storage",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
}
],
"ports": [
{
"container_port": 3001,
"published_example": 3001,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 3000,
"published_example": 3000,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n lightcraft:\n image: junkerderprovinz/lightcraft:latest\n container_name: lightcraft\n restart: unless-stopped\n shm_size: 1gb\n ports:\n - 3001:3001\n - 3000:3000\n volumes:\n - ./appdata:/config\n - ./storage:/storage\n environment:\n TZ: Europe/Vienna\n PUID: '1000'\n PGID: '1000'\n UMASK: '022'\n"
},
"compose_stack": {
"project_name": "lightcraft",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "lightcraft",
"service_count": 1,
"services": [
{
"name": "lightcraft",
"image": "junkerderprovinz/lightcraft:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "junkerderprovinz/lightcraft:latest",
"container_name": "lightcraft",
"restart": "unless-stopped",
"shm_size": "1gb",
"ports": [
"3001:3001",
"3000:3000"
],
"volumes": [
"./appdata:/config",
"./storage:/storage"
],
"environment": {
"TZ": "Europe/Vienna",
"PUID": "1000",
"PGID": "1000",
"UMASK": "022"
}
}
}
],
"top_level": {},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "lightcraft-volume-0",
"service": "lightcraft",
"container_path": "/config",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "lightcraft-volume-1",
"service": "lightcraft",
"container_path": "/storage",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"lightcraft"
],
"stop_order": [
"lightcraft"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": []
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "https",
"port": 3001,
"path": "/",
"source": "https://github.com/junkerderprovinz/artcraft-apps"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 2048,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"installer_profile": {
"tmpfs_mounts": [
{
"id": "compose-shm",
"container_path": "/dev/shm",
"default_size_mb": 1024,
"minimum_size_mb": 1,
"size_prompt": "Size of the /dev/shm shared memory in MB",
"mount_options": [
"rw",
"nosuid",
"nodev"
]
},
{
"id": "nginx-runtime",
"container_path": "/run/nginx",
"default_size_mb": 1,
"minimum_size_mb": 1,
"prompt_size": false,
"mount_options": [
"rw",
"nosuid",
"nodev",
"mode=0755"
]
}
],
"volume_preparations": [
{
"container_path": "/config",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/storage",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 3000,
"path": "/",
"timeout_seconds": 240,
"request_timeout_seconds": 5,
"stability_seconds": 8,
"accept_any_status": true,
"verify_tls": true
},
"selkies": {
"base": "FROM ghcr.io/linuxserver/baseimage-selkies:ubunturesolute@sha256:6efa3fd775a552938d862f75975d34c418ad26d028ba2c952da58682cfe1cb47",
"dockerfile_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/Dockerfile",
"dockerfile_sha256": "69ab1a81d1696d1bd143a6fa5a121c034ddfb3e83008969340e8cd2413547fe1",
"reviewed_on": "2026-11-04",
"documentation": "https://docs.linuxserver.io/images/docker-baseimage-selkies/",
"nvidia": "available-in-advanced-mode-with-compatible-host-driver-and-toolkit",
"validation": "Intel/AMD tested on a Radeon 680M: GL compositor and VAAPI encoding on the render node"
},
"device_requests": [],
"optional_devices": [],
"hardware_acceleration": {
"prompt": "Selkies desktop and streaming acceleration",
"default": "none",
"profiles": [
{
"id": "none",
"label": "No GPU (CPU)",
"device_requests": [],
"environment": [
{
"name": "AUTO_GPU",
"value": "false"
}
]
},
{
"id": "vaapi",
"label": "Intel/AMD (streaming rendering and encoding)",
"device_requests": [
{
"id": "selkies-render",
"kind": "character-device",
"path_prompt": "Intel/AMD render node",
"host_path_default": "/dev/dri/renderD128",
"container_path_strategy": "same-as-host",
"mode": "0660",
"deny_write": false,
"gid_strategy": "host-device-gid",
"drm_vendor_ids": [
"0x8086",
"0x1002"
]
}
],
"environment": [
{
"name": "PIXELFLUX_WAYLAND",
"value": "true"
},
{
"name": "AUTO_GPU",
"value": "false"
}
],
"environment_from_devices": {
"DRINODE": [
"selkies-render"
],
"DRI_NODE": [
"selkies-render"
],
"ATTACHED_DEVICES_PERMS": [
"selkies-render"
]
}
},
{
"id": "nvidia",
"label": "NVIDIA (Selkies rendering and NVENC)",
"device_requests": [
{
"id": "selkies-nvidia",
"kind": "nvidia-runtime",
"device_selection": "all-requested-by-compose"
}
],
"environment": [
{
"name": "AUTO_GPU",
"value": "true"
},
{
"name": "NVIDIA_VISIBLE_DEVICES",
"value": "all"
},
{
"name": "NVIDIA_DRIVER_CAPABILITIES",
"value": "compute,video,graphics,utility,display"
}
]
}
]
},
"gpu_validation": {
"device_inventory": "host-sysfs-and-stat",
"application_acceleration": "requires-workload-test",
"tone_mapping": "not-implied-by-device-access"
},
"device_permissions": {
"strategy": "linuxserver-native-init",
"service_user": "abc",
"environment": "ATTACHED_DEVICES_PERMS",
"paths": "all-resolved-selected-character-devices"
}
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "pending-per-application"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Community native-desktop image contract reviewed against its published Compose and Dockerfile. Linux amd64 and arm64 manifests exist; runtime, storage and lifecycle tests remain pending per architecture."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "pending",
"service_health": "pending",
"restart_persistence": "pending",
"backup_restore": "pending",
"update_preserves_data": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+42 -6
View File
@@ -68,11 +68,18 @@
"source": "docker-compose"
},
{
"name": "LLAMA_ARG_CONTEXT_SIZE",
"name": "LLAMA_ARG_CTX_SIZE",
"example": "8192",
"required": true,
"sensitive": false,
"source": "docker-compose"
},
{
"name": "LLAMA_ARG_MODELS_DIR",
"example": "/models",
"required": true,
"sensitive": false,
"source": "upstream-documentation"
}
],
"volumes": [
@@ -89,7 +96,7 @@
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
"default_size_gb": 32
}
}
],
@@ -135,7 +142,8 @@
],
"environment": [
"LLAMA_ARG_N_GPU_LAYERS=999",
"LLAMA_ARG_CONTEXT_SIZE=8192"
"LLAMA_ARG_CTX_SIZE=8192",
"LLAMA_ARG_MODELS_DIR=/models"
],
"devices": [
"/dev/dri:/dev/dri"
@@ -229,8 +237,8 @@
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 1024,
"cores": 4,
"memory_mb": 8192,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
@@ -334,6 +342,28 @@
"0x1002"
]
}
],
"environment": [
{
"name": "LLAMA_ARG_FLASH_ATTN",
"value": "off"
},
{
"name": "LLAMA_ARG_UBATCH",
"value": "32"
},
{
"name": "LLAMA_ARG_BATCH",
"value": "128"
},
{
"name": "GGML_VK_DISABLE_F16",
"value": "1"
},
{
"name": "GGML_VK_DISABLE_ASYNC",
"value": "1"
}
]
},
{
@@ -420,7 +450,13 @@
]
}
]
}
},
"completion_notes": [
"llama.cpp shows every GGUF model saved in /models in its web UI and loads the one you choose.",
"To add a model, open the console of the container in Proxmox and download it into /models, for example:",
"curl -L -o /models/gemma-3-1b-it-Q4_K_M.gguf https://huggingface.co/ggml-org/gemma-3-1b-it-GGUF/resolve/main/gemma-3-1b-it-Q4_K_M.gguf",
"Then restart the container so the new model appears in the list."
]
},
"adaptations": [
{
+609
View File
@@ -0,0 +1,609 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-movistar-webdav-proxy",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "Movistar / O2 Cloud WebDAV Proxy"
},
"tagline": {
"en_US": "Access Movistar and O2 Cloud from WebDAV clients and backup tools."
},
"description": {
"en_US": "Official uniextra image with a web dashboard for Movistar/O2 Cloud account linking. Persistent OAuth credentials, authenticated WebDAV and disk-backed temporary uploads."
},
"category": "backup",
"category_label": "Backup & Recovery",
"author": "uniextra",
"developer": "uniextra",
"icon": "https://raw.githubusercontent.com/uniextra/MovistarWebDAVProxy/main/static/favicon.svg",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "http",
"port": 5000,
"path": "/"
},
"website": "https://github.com/uniextra/MovistarWebDAVProxy",
"documentation": "https://github.com/uniextra/MovistarWebDAVProxy#readme",
"repository": "https://github.com/uniextra/MovistarWebDAVProxy",
"tips": [
"Link your Movistar or O2 account from the dashboard after installation.",
"Use the container IP and port 8080 for WebDAV. Docker's published port 5050 is not used by native OCI LXC.",
"Temporary uploads use a separate disk volume, excluded from backups, to avoid filling RAM."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "uniextra",
"repository": "https://github.com/uniextra/MovistarWebDAVProxy",
"revision": "e48485bc8bdf9745caa6249fdc92db6d28214549",
"image_repository_url": "https://hub.docker.com/r/uniextra/movistar-webdav-proxy",
"readme_pushed_at": "",
"compose_sha256": "e51607e979c1a776ececda038caeffb4195f443ebc017eba753a4b4ff8fd5c28",
"generated_at": "2026-11-02T23:42:04+00:00",
"readme_raw_url": "https://raw.githubusercontent.com/uniextra/MovistarWebDAVProxy/e48485bc8bdf9745caa6249fdc92db6d28214549/README.md"
},
"container_contract": {
"service_name": "movistar-webdav-proxy",
"container_name": "movistar-webdav-proxy",
"image": {
"reference": "uniextra/movistar-webdav-proxy:latest",
"registry": "docker.io",
"repository": "uniextra/movistar-webdav-proxy",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "WEBDAV_USER",
"example": "admin",
"required": true,
"sensitive": false,
"source": "docker-compose"
},
{
"name": "WEBDAV_PASSWORD",
"example": "",
"required": true,
"sensitive": true,
"source": "docker-compose",
"prompt": "WebDAV and dashboard password (leave empty to generate)"
},
{
"name": "REQUIRE_AUTH",
"example": "true",
"required": true,
"sensitive": false,
"source": "docker-compose"
},
{
"name": "TOKENS_ENCRYPTION_KEY",
"example": "",
"required": true,
"sensitive": true,
"source": "docker-compose"
},
{
"name": "MAX_UPLOAD_MB",
"example": "4096",
"required": false,
"sensitive": false,
"source": "docker-compose"
}
],
"volumes": [
{
"id": "tokens",
"container_path": "/app/tokens",
"compose_source_example": "./tokens",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
},
{
"id": "uploads",
"container_path": "/tmp",
"compose_source_example": "./tmp",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
}
],
"ports": [
{
"container_port": 5000,
"published_example": 5000,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 8080,
"published_example": 8080,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n movistar-webdav-proxy:\n image: uniextra/movistar-webdav-proxy:v2.1.0\n container_name: movistar-webdav-proxy\n restart: unless-stopped\n read_only: true\n tmpfs:\n - /tmp\n security_opt:\n - no-new-privileges:true\n environment:\n - WEBDAV_USER=${WEBDAV_USER:-}\n - WEBDAV_PASSWORD=${WEBDAV_PASSWORD:-}\n - WEBUI_USER=${WEBUI_USER:-}\n - WEBUI_PASSWORD=${WEBUI_PASSWORD:-}\n ports:\n - \"${BIND_IP:-0.0.0.0}:${WEB_PORT:-5000}:5000\" # Panel Web de gestión y logs (usa BIND_IP=127.0.0.1 para acceso solo local)\n - \"${BIND_IP:-0.0.0.0}:${WEBDAV_PORT:-5050}:8080\" # Endpoint WebDAV (Duplicati / Synology HyperBackup)\n volumes:\n - movistar_tokens:/app/tokens\n\nvolumes:\n movistar_tokens:\n name: movistar_webdav_tokens\n"
},
"compose_stack": {
"project_name": "movistar-webdav-proxy",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "movistar-webdav-proxy",
"service_count": 1,
"services": [
{
"name": "movistar-webdav-proxy",
"image": "uniextra/movistar-webdav-proxy:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"environment": {
"MAX_UPLOAD_MB": "4096",
"REQUIRE_AUTH": "true",
"TOKENS_ENCRYPTION_KEY": "${GENERATED_TOKENS_ENCRYPTION_KEY}",
"WEBDAV_PASSWORD": "${GENERATED_WEBDAV_PASSWORD}",
"WEBDAV_USER": "admin"
},
"image": "uniextra/movistar-webdav-proxy:latest",
"ports": [
"5000:5000",
"8080:8080"
],
"volumes": [
"./tokens:/app/tokens",
"./tmp:/tmp"
]
}
}
],
"top_level": {
"name": "movistar-webdav-proxy"
},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "movistar-webdav-proxy-volume-0",
"service": "movistar-webdav-proxy",
"container_path": "/app/tokens",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "movistar-webdav-proxy-volume-1",
"service": "movistar-webdav-proxy",
"container_path": "/tmp",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"movistar-webdav-proxy"
],
"stop_order": [
"movistar-webdav-proxy"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": [
{
"id": "tokens-encryption-key",
"strategy": "generate-cryptographically-random-at-install",
"bindings": [
{
"service": "movistar-webdav-proxy",
"environment_variable": "TOKENS_ENCRYPTION_KEY"
}
]
},
{
"id": "webdav-password",
"strategy": "generate-cryptographically-random-at-install",
"bindings": [
{
"service": "movistar-webdav-proxy",
"environment_variable": "WEBDAV_PASSWORD"
}
]
}
]
}
},
"first_run": {
"endpoints": [
{
"label": "Web dashboard",
"scheme": "http",
"port": 5000,
"path": "/",
"source": "upstream-documentation"
},
{
"label": "WebDAV",
"scheme": "http",
"port": 8080,
"path": "/",
"source": "native-container-port"
}
],
"credentials": [
{
"label": "Web dashboard and WebDAV",
"type": "configured-or-installer-generated",
"username": "admin",
"username_environment": "WEBDAV_USER",
"password": null,
"password_environment": "WEBDAV_PASSWORD",
"change_required": false,
"source": "installer-generated",
"retrieval": null
}
]
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 1,
"memory_mb": 512,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
},
{
"id": "disk-backed-upload-scratch",
"upstream_behavior": "Compose mounts /tmp as a tmpfs.",
"native_lxc_behavior": "A separate managed disk volume provides /tmp and is excluded from backups.",
"reason": "Uploads can reach 4096 MB; a disk-backed scratch volume avoids consuming the LXC RAM limit.",
"behavioral_impact": "Scratch data uses disk and can survive a restart; the application removes completed temporary uploads.",
"validation": "passed-in-lab"
},
{
"id": "native-rootfs-permissions",
"upstream_behavior": "Docker Compose requests read_only for the root filesystem.",
"native_lxc_behavior": "Proxmox uses a writable native root disk; /app is owned by root, while the upstream entrypoint drops to UID 10001. Tokens and upload scratch have separate writable volumes.",
"reason": "The Proxmox pre-start setup requires a writable root disk. Protect application code through root ownership instead of declaring unsupported read-only startup.",
"behavioral_impact": "This is not a fully read-only root filesystem; the application user cannot replace the root-owned application directory or binaries.",
"validation": "passed-in-lab"
}
],
"installer_profile": {
"volume_preparations": [
{
"container_path": "/app",
"remove_lost_found": false,
"owner_strategy": "mapped-root",
"mode": "0755"
},
{
"container_path": "/app/tokens",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"mode": "0700"
},
{
"container_path": "/tmp",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"mode": "1777"
}
],
"volume_owner": {
"uid": 10001,
"gid": 10001
},
"generated_sensitive_environment": {
"WEBDAV_PASSWORD": {
"strategy": "token-hex",
"bytes": 16,
"prompt": true
},
"TOKENS_ENCRYPTION_KEY": {
"strategy": "token-hex",
"bytes": 32,
"prompt": false
}
},
"security": {
"options": {
"no_new_privileges": true
}
},
"startup_healthcheck": {
"scheme": "http",
"port": 5000,
"path": "/health",
"timeout_seconds": 90,
"request_timeout_seconds": 5,
"stability_seconds": 4,
"verify_tls": false
},
"completion_notes": [
"Open the web dashboard and link your Movistar/O2 account using its SMS flow.",
"WebDAV is available on container port 8080. Account linking is required before cloud file operations."
]
}
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "passed",
"service_health": "passed",
"restart_persistence": "passed",
"backup_restore": "pending",
"update_preserves_data": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
File diff suppressed because one or more lines are too long
+505
View File
@@ -0,0 +1,505 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-paperclip",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "Paperclip"
},
"tagline": {
"en_US": "Manage teams of AI agents from a web dashboard."
},
"description": {
"en_US": "Official Paperclip image with its embedded PostgreSQL database, persistent agent workspaces and authenticated web interface."
},
"category": "ai",
"category_label": "AI / Coding & Dev-Tools",
"author": "Paperclip",
"developer": "Paperclip",
"icon": "https://raw.githubusercontent.com/paperclipai/paperclip/master/ui/public/favicon.svg",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "http",
"port": 3100,
"path": "/"
},
"website": "https://paperclip.ing",
"documentation": "https://github.com/paperclipai/paperclip/blob/master/doc/DOCKER.md",
"repository": "https://github.com/paperclipai/paperclip",
"tips": [
"Create an account and claim the instance from the first-run setup screen.",
"Configure provider credentials or external agents after installation; no API key is required to start the dashboard.",
"For HTTPS access, set PAPERCLIP_PUBLIC_URL to the canonical URL in Advanced settings.",
"Restore with the original network identity, or update PAPERCLIP_PUBLIC_URL in Modify when the address or hostname changes."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "official",
"repository": "https://github.com/paperclipai/paperclip",
"revision": "1b4c803816e82b0265c8422e1a804327a7ed8c54",
"image_repository_url": "https://github.com/paperclipai/paperclip/pkgs/container/paperclip",
"readme_pushed_at": "",
"compose_sha256": "53a71e7d1c6a47fb25ad68d5570140c525df30fcecf33a00cf84bd2b65bd15f4",
"generated_at": "2026-11-02T18:43:18+00:00",
"readme_raw_url": "https://github.com/paperclipai/paperclip/blob/master/doc/DOCKER.md"
},
"container_contract": {
"service_name": "paperclip",
"container_name": "paperclip",
"image": {
"reference": "ghcr.io/paperclipai/paperclip:latest",
"registry": "ghcr.io",
"repository": "ghcr.io/paperclipai/paperclip",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "HOST",
"example": "0.0.0.0",
"required": true,
"sensitive": false,
"source": "docker-compose",
"prompt_user": false
},
{
"name": "PAPERCLIP_HOME",
"example": "/paperclip",
"required": true,
"sensitive": false,
"source": "docker-compose",
"prompt_user": false
},
{
"name": "PAPERCLIP_DEPLOYMENT_MODE",
"example": "authenticated",
"required": true,
"sensitive": false,
"source": "docker-compose",
"prompt_user": false
},
{
"name": "PAPERCLIP_DEPLOYMENT_EXPOSURE",
"example": "private",
"required": true,
"sensitive": false,
"source": "docker-compose",
"prompt_user": false
},
{
"name": "PAPERCLIP_PUBLIC_URL",
"example": "http://localhost:3100",
"required": true,
"sensitive": false,
"source": "docker-compose",
"container_address": "http://@CONTAINER_ADDRESS@:3100"
},
{
"name": "BETTER_AUTH_SECRET",
"example": "${GENERATED_BETTER_AUTH_SECRET}",
"required": true,
"sensitive": true,
"source": "docker-compose"
},
{
"name": "PAPERCLIP_TOOL_ACTION_SIGNING_SECRET",
"example": "${GENERATED_PAPERCLIP_TOOL_ACTION_SIGNING_SECRET}",
"required": true,
"sensitive": true,
"source": "docker-compose"
},
{
"name": "OPENAI_API_KEY",
"example": "",
"required": false,
"sensitive": true,
"source": "official-documentation"
},
{
"name": "ANTHROPIC_API_KEY",
"example": "",
"required": false,
"sensitive": true,
"source": "official-documentation"
},
{
"name": "GEMINI_API_KEY",
"example": "",
"required": false,
"sensitive": true,
"source": "official-documentation"
},
{
"name": "OPENROUTER_API_KEY",
"example": "",
"required": false,
"sensitive": true,
"source": "official-documentation"
},
{
"name": "PAPERCLIP_ALLOWED_HOSTNAMES",
"example": "",
"required": false,
"sensitive": false,
"source": "official-documentation"
},
{
"name": "PAPERCLIP_MIGRATION_AUTO_APPLY",
"example": "true",
"required": true,
"sensitive": false,
"prompt_user": false,
"source": "official-server-startup"
}
],
"volumes": [
{
"id": "volume-0",
"container_path": "/paperclip",
"compose_source_example": "paperclip-data",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
}
],
"ports": [
{
"container_port": 3100,
"published_example": 3100,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": "90s",
"original_compose": "name: paperclip\nservices:\n paperclip:\n image: ghcr.io/paperclipai/paperclip:latest\n restart: unless-stopped\n stop_grace_period: 90s\n ports:\n - 3100:3100\n environment:\n HOST: 0.0.0.0\n PAPERCLIP_HOME: /paperclip\n PAPERCLIP_MIGRATION_AUTO_APPLY: \"true\"\n PAPERCLIP_DEPLOYMENT_MODE: authenticated\n PAPERCLIP_DEPLOYMENT_EXPOSURE: private\n PAPERCLIP_PUBLIC_URL: http://localhost:3100\n BETTER_AUTH_SECRET: ${GENERATED_BETTER_AUTH_SECRET}\n PAPERCLIP_TOOL_ACTION_SIGNING_SECRET: ${GENERATED_PAPERCLIP_TOOL_ACTION_SIGNING_SECRET}\n volumes:\n - paperclip-data:/paperclip\nvolumes:\n paperclip-data: {}\n"
},
"compose_stack": {
"project_name": "paperclip",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "paperclip",
"service_count": 1,
"services": [
{
"name": "paperclip",
"image": "ghcr.io/paperclipai/paperclip:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "ghcr.io/paperclipai/paperclip:latest",
"restart": "unless-stopped",
"stop_grace_period": "90s",
"ports": [
"3100:3100"
],
"environment": {
"HOST": "0.0.0.0",
"PAPERCLIP_HOME": "/paperclip",
"PAPERCLIP_DEPLOYMENT_MODE": "authenticated",
"PAPERCLIP_DEPLOYMENT_EXPOSURE": "private",
"PAPERCLIP_PUBLIC_URL": "http://localhost:3100",
"BETTER_AUTH_SECRET": "${GENERATED_BETTER_AUTH_SECRET}",
"PAPERCLIP_TOOL_ACTION_SIGNING_SECRET": "${GENERATED_PAPERCLIP_TOOL_ACTION_SIGNING_SECRET}",
"PAPERCLIP_MIGRATION_AUTO_APPLY": "true"
},
"volumes": [
"paperclip-data:/paperclip"
]
}
}
],
"top_level": {
"name": "paperclip",
"volumes": {
"paperclip-data": {}
}
},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "paperclip-volume-0",
"service": "paperclip",
"container_path": "/paperclip",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"paperclip"
],
"stop_order": [
"paperclip"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": [
{
"id": "better-auth-secret",
"strategy": "generate-cryptographically-random-at-install",
"bindings": [
{
"service": "paperclip",
"environment_variable": "BETTER_AUTH_SECRET"
}
]
},
{
"id": "paperclip-tool-action-signing-secret",
"strategy": "generate-cryptographically-random-at-install",
"bindings": [
{
"service": "paperclip",
"environment_variable": "PAPERCLIP_TOOL_ACTION_SIGNING_SECRET"
}
]
}
]
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "http",
"port": 3100,
"path": "/",
"source": "compose-metadata"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 4096,
"swap_mb": 512,
"rootfs_size_gb": 32,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 90
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"adaptations": [
{
"id": "official-embedded-postgresql-image",
"upstream_behavior": "The official image starts Paperclip and its embedded PostgreSQL database.",
"native_lxc_behavior": "Import the original Entrypoint, Cmd and WorkingDir into one unprivileged LXC.",
"reason": "Keep the developer image without Docker Engine or a custom image build.",
"behavioral_impact": "Provider credentials are configured separately after the first account is created.",
"validation": "passed-amd64-web-login-and-api-data"
},
{
"id": "persistent-application-home",
"upstream_behavior": "The root entrypoint prepares /paperclip and then switches to the node user.",
"native_lxc_behavior": "Prepare the volume for mapped root and let the official entrypoint set application ownership.",
"reason": "Preserve the embedded database, uploads, workspaces and local secrets across image replacement and restore.",
"behavioral_impact": "Managed volumes are backed up; host directories remain outside the LXC backup.",
"validation": "passed-managed-volume-host-bind-restart-and-restore"
},
{
"id": "noninteractive-database-migrations",
"upstream_behavior": "Existing databases with pending migrations trigger an interactive confirmation during startup.",
"native_lxc_behavior": "Set the upstream PAPERCLIP_MIGRATION_AUTO_APPLY=true option.",
"reason": "An OCI update must finish without waiting for input at a migration prompt.",
"behavioral_impact": "Paperclip applies its schema migrations when starting an updated image; the native update backup protects the previous installation.",
"validation": "passed-real-upgrade-2026.1012.0-to-2026.1023.0"
},
{
"id": "authenticated-instance-address",
"upstream_behavior": "Paperclip uses its canonical public URL for authentication origins and hostname checks.",
"native_lxc_behavior": "Use the installer container-address placeholder by default and allow a canonical URL in Advanced settings.",
"reason": "Avoid the upstream localhost URL on an LXC with its own address.",
"behavioral_impact": "When restoring under another address, change PAPERCLIP_PUBLIC_URL through Modify. Restoring the original network identity retains the URL.",
"validation": "passed-direct-ip-authenticated-setup-and-original-network-restore"
},
{
"id": "independent-signing-secrets",
"upstream_behavior": "Session signing and approval-gated tool actions use independent secrets.",
"native_lxc_behavior": "Generate two separate 32-byte hexadecimal secrets and keep their values sensitive.",
"reason": "Do not ship a shared password or regenerate signing keys during an update.",
"behavioral_impact": "The first administrator creates an account in the web interface. Provider API keys are optional and sensitive.",
"validation": "passed-first-admin-claim-and-update-account-persistence"
}
],
"installer_profile": {
"volume_preparations": [
{
"container_path": "/paperclip",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
}
],
"generated_sensitive_environment": {
"BETTER_AUTH_SECRET": {
"strategy": "token-hex",
"bytes": 32,
"prompt": false
},
"PAPERCLIP_TOOL_ACTION_SIGNING_SECRET": {
"strategy": "token-hex",
"bytes": 32,
"prompt": false
}
},
"startup_healthcheck": {
"scheme": "http",
"port": 3100,
"path": "/api/health",
"timeout_seconds": 300,
"request_timeout_seconds": 10,
"stability_seconds": 5,
"verify_tls": true
}
}
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available."
},
"validation": {
"schema": "passed",
"clean_install": "passed-default-resource-profile-and-advanced-settings-amd64",
"service_health": "passed-http-api-health-browser-login-and-first-admin-claim",
"restart_persistence": "passed-host-bind-reboot-and-managed-volume-restore",
"backup_restore": "passed-different-vmid-oci-recovery-with-original-network-identity",
"update_preserves_data": "passed-2026.1012.0-to-2026.1023.0-with-automatic-schema-migrations",
"rollback": "passed-explicit-native-Recover-after-failed-image-not-claimed-automatic",
"modification": "passed-native-cpu-and-ram-change-without-image-download-or-recreation",
"removal": "passed-guests-disks-records-and-test-backups-cleaned-host-data-preserved-by-Remove",
"browser_ui": "passed-account-login-and-company-dashboard",
"runtime_architecture": "amd64-tested-arm64-manifest-only",
"provider_agent_runs": "not-tested-no-real-provider-credentials-used",
"oci_engine_tests": "1158-run-4-skipped",
"offline_i18n_tests": "626-passed"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+677
View File
@@ -0,0 +1,677 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-pdfcraft",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "PdfCraft",
"es_ES": "PdfCraft"
},
"tagline": {
"en_US": "Read and edit PDF documents in your browser",
"es_ES": "Lectura y edición de documentos PDF en el navegador"
},
"description": {
"en_US": "PdfCraft from the ArtCraft project, streamed from a native Linux application using the community-maintained junkerderprovinz image. Files are stored on the server, not in browser storage.",
"es_ES": "PdfCraft del proyecto ArtCraft, con su aplicación nativa de Linux transmitida al navegador mediante la imagen comunitaria de junkerderprovinz. Los documentos se guardan en el servidor, no en el almacenamiento del navegador."
},
"category": "creative",
"category_label": "Creative & Design",
"author": "junkerderprovinz",
"developer": "ArtCraft",
"icon": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/.github/assets/icons/pdfcraft.png",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "https",
"port": 3001,
"path": "/"
},
"website": "https://getartcraft.com/apps/pdfcraft",
"documentation": "https://github.com/junkerderprovinz/artcraft-apps",
"repository": "https://github.com/storytold/pdfcraft",
"tips": [
"This is the native Linux application streamed by Selkies, not the WebAssembly build. Processing and documents stay in the LXC and its mounted directories.",
"The image is maintained by junkerderprovinz; ArtCraft publishes the application packages. It is not an official ArtCraft container image.",
"Use a trusted HTTPS reverse proxy for browser access. Port 3001 uses the upstream self-signed certificate; port 3000 is for an HTTP reverse-proxy backend.",
"The upstream default has no login. Optional CUSTOM_USER and PASSWORD variables enable HTTP basic authentication; do not expose an unauthenticated desktop to untrusted networks.",
"/config holds settings and desktop state and is included in Proxmox backups. /storage holds documents and supports a managed volume or an explicitly selected host directory; host directories require separate backups.",
"The default installation draws on the CPU. The advanced installation can assign an Intel or AMD GPU, which the desktop, the application and the video stream then use; NVIDIA is offered when the host has its driver and the NVIDIA Container Toolkit.",
"Without a GPU, an application may ask to switch to CPU rendering. Choose the CPU option; the application remembers it."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "junkerderprovinz",
"repository": "https://github.com/junkerderprovinz/artcraft-apps",
"revision": "32bee0dea9bdaf5310c693210bea0d732a129ae8",
"image_repository_url": "https://hub.docker.com/r/junkerderprovinz/pdfcraft",
"readme_pushed_at": "",
"compose_sha256": "4416cf187df8cccbc11fc14af6e4d5155cd386871f9514ae1ca10968a8b4a372",
"generated_at": "2026-11-03T12:57:29+00:00",
"default_branch": "main",
"readme_raw_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/compose/pdfcraft.yaml"
},
"container_contract": {
"service_name": "pdfcraft",
"container_name": "pdfcraft",
"image": {
"reference": "docker.io/junkerderprovinz/pdfcraft:latest",
"registry": "docker.io",
"repository": "junkerderprovinz/pdfcraft",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "TZ",
"example": "Europe/Vienna",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PUID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PGID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "UMASK",
"example": "022",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "CUSTOM_USER",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation"
},
{
"name": "PASSWORD",
"example": "",
"required": false,
"sensitive": true,
"source": "upstream-documentation"
},
{
"name": "LC_ALL",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation",
"prompt": "Language/locale (e.g. es_ES.UTF-8; translation of every application is not guaranteed)"
}
],
"volumes": [
{
"id": "config",
"container_path": "/config",
"compose_source_example": "./appdata",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "storage",
"container_path": "/storage",
"compose_source_example": "./storage",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
}
],
"ports": [
{
"container_port": 3001,
"published_example": 3001,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 3000,
"published_example": 3000,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n pdfcraft:\n image: junkerderprovinz/pdfcraft:latest\n container_name: pdfcraft\n restart: unless-stopped\n shm_size: 1gb\n ports:\n - 3001:3001\n - 3000:3000\n volumes:\n - ./appdata:/config\n - ./storage:/storage\n environment:\n TZ: Europe/Vienna\n PUID: '1000'\n PGID: '1000'\n UMASK: '022'\n"
},
"compose_stack": {
"project_name": "pdfcraft",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "pdfcraft",
"service_count": 1,
"services": [
{
"name": "pdfcraft",
"image": "junkerderprovinz/pdfcraft:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "junkerderprovinz/pdfcraft:latest",
"container_name": "pdfcraft",
"restart": "unless-stopped",
"shm_size": "1gb",
"ports": [
"3001:3001",
"3000:3000"
],
"volumes": [
"./appdata:/config",
"./storage:/storage"
],
"environment": {
"TZ": "Europe/Vienna",
"PUID": "1000",
"PGID": "1000",
"UMASK": "022"
}
}
}
],
"top_level": {},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "pdfcraft-volume-0",
"service": "pdfcraft",
"container_path": "/config",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "pdfcraft-volume-1",
"service": "pdfcraft",
"container_path": "/storage",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"pdfcraft"
],
"stop_order": [
"pdfcraft"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": []
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "https",
"port": 3001,
"path": "/",
"source": "https://github.com/junkerderprovinz/artcraft-apps"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 2048,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"installer_profile": {
"tmpfs_mounts": [
{
"id": "compose-shm",
"container_path": "/dev/shm",
"default_size_mb": 1024,
"minimum_size_mb": 1,
"size_prompt": "Size of the /dev/shm shared memory in MB",
"mount_options": [
"rw",
"nosuid",
"nodev"
]
},
{
"id": "nginx-runtime",
"container_path": "/run/nginx",
"default_size_mb": 1,
"minimum_size_mb": 1,
"prompt_size": false,
"mount_options": [
"rw",
"nosuid",
"nodev",
"mode=0755"
]
}
],
"volume_preparations": [
{
"container_path": "/config",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/storage",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 3000,
"path": "/",
"timeout_seconds": 240,
"request_timeout_seconds": 5,
"stability_seconds": 8,
"accept_any_status": true,
"verify_tls": true
},
"selkies": {
"base": "FROM ghcr.io/linuxserver/baseimage-selkies:ubunturesolute@sha256:6efa3fd775a552938d862f75975d34c418ad26d028ba2c952da58682cfe1cb47",
"dockerfile_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/Dockerfile",
"dockerfile_sha256": "69ab1a81d1696d1bd143a6fa5a121c034ddfb3e83008969340e8cd2413547fe1",
"reviewed_on": "2026-11-04",
"documentation": "https://docs.linuxserver.io/images/docker-baseimage-selkies/",
"nvidia": "available-in-advanced-mode-with-compatible-host-driver-and-toolkit",
"validation": "Intel/AMD tested on a Radeon 680M: GL compositor and VAAPI encoding on the render node"
},
"device_requests": [],
"optional_devices": [],
"hardware_acceleration": {
"prompt": "Selkies desktop and streaming acceleration",
"default": "none",
"profiles": [
{
"id": "none",
"label": "No GPU (CPU)",
"device_requests": [],
"environment": [
{
"name": "AUTO_GPU",
"value": "false"
}
]
},
{
"id": "vaapi",
"label": "Intel/AMD (streaming rendering and encoding)",
"device_requests": [
{
"id": "selkies-render",
"kind": "character-device",
"path_prompt": "Intel/AMD render node",
"host_path_default": "/dev/dri/renderD128",
"container_path_strategy": "same-as-host",
"mode": "0660",
"deny_write": false,
"gid_strategy": "host-device-gid",
"drm_vendor_ids": [
"0x8086",
"0x1002"
]
}
],
"environment": [
{
"name": "PIXELFLUX_WAYLAND",
"value": "true"
},
{
"name": "AUTO_GPU",
"value": "false"
}
],
"environment_from_devices": {
"DRINODE": [
"selkies-render"
],
"DRI_NODE": [
"selkies-render"
],
"ATTACHED_DEVICES_PERMS": [
"selkies-render"
]
}
},
{
"id": "nvidia",
"label": "NVIDIA (Selkies rendering and NVENC)",
"device_requests": [
{
"id": "selkies-nvidia",
"kind": "nvidia-runtime",
"device_selection": "all-requested-by-compose"
}
],
"environment": [
{
"name": "AUTO_GPU",
"value": "true"
},
{
"name": "NVIDIA_VISIBLE_DEVICES",
"value": "all"
},
{
"name": "NVIDIA_DRIVER_CAPABILITIES",
"value": "compute,video,graphics,utility,display"
}
]
}
]
},
"gpu_validation": {
"device_inventory": "host-sysfs-and-stat",
"application_acceleration": "requires-workload-test",
"tone_mapping": "not-implied-by-device-access"
},
"device_permissions": {
"strategy": "linuxserver-native-init",
"service_user": "abc",
"environment": "ATTACHED_DEVICES_PERMS",
"paths": "all-resolved-selected-character-devices"
}
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "pending-per-application"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Community native-desktop image contract reviewed against its published Compose and Dockerfile. Linux amd64 and arm64 manifests exist; runtime, storage and lifecycle tests remain pending per architecture."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "pending",
"service_health": "pending",
"restart_persistence": "pending",
"backup_restore": "pending",
"update_preserves_data": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+677
View File
@@ -0,0 +1,677 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-photocraft",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "PhotoCraft",
"es_ES": "PhotoCraft"
},
"tagline": {
"en_US": "Photo editing in your browser",
"es_ES": "Edición de fotos en el navegador"
},
"description": {
"en_US": "PhotoCraft from the ArtCraft project, streamed from a native Linux application using the community-maintained junkerderprovinz image. Files are stored on the server, not in browser storage.",
"es_ES": "PhotoCraft del proyecto ArtCraft, con su aplicación nativa de Linux transmitida al navegador mediante la imagen comunitaria de junkerderprovinz. Los documentos se guardan en el servidor, no en el almacenamiento del navegador."
},
"category": "creative",
"category_label": "Creative & Design",
"author": "junkerderprovinz",
"developer": "ArtCraft",
"icon": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/.github/assets/icons/photocraft.png",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "https",
"port": 3001,
"path": "/"
},
"website": "https://getartcraft.com/apps/photocraft",
"documentation": "https://github.com/junkerderprovinz/artcraft-apps",
"repository": "https://github.com/storytold/photocraft",
"tips": [
"This is the native Linux application streamed by Selkies, not the WebAssembly build. Processing and documents stay in the LXC and its mounted directories.",
"The image is maintained by junkerderprovinz; ArtCraft publishes the application packages. It is not an official ArtCraft container image.",
"Use a trusted HTTPS reverse proxy for browser access. Port 3001 uses the upstream self-signed certificate; port 3000 is for an HTTP reverse-proxy backend.",
"The upstream default has no login. Optional CUSTOM_USER and PASSWORD variables enable HTTP basic authentication; do not expose an unauthenticated desktop to untrusted networks.",
"/config holds settings and desktop state and is included in Proxmox backups. /storage holds documents and supports a managed volume or an explicitly selected host directory; host directories require separate backups.",
"The default installation draws on the CPU. The advanced installation can assign an Intel or AMD GPU, which the desktop, the application and the video stream then use; NVIDIA is offered when the host has its driver and the NVIDIA Container Toolkit.",
"Without a GPU, an application may ask to switch to CPU rendering. Choose the CPU option; the application remembers it."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "junkerderprovinz",
"repository": "https://github.com/junkerderprovinz/artcraft-apps",
"revision": "32bee0dea9bdaf5310c693210bea0d732a129ae8",
"image_repository_url": "https://hub.docker.com/r/junkerderprovinz/photocraft",
"readme_pushed_at": "",
"compose_sha256": "459ac4e3adbd7544f3d0acb2f34230e8a396566ff910288898f689d54a78e722",
"generated_at": "2026-11-03T12:57:29+00:00",
"default_branch": "main",
"readme_raw_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/compose/photocraft.yaml"
},
"container_contract": {
"service_name": "photocraft",
"container_name": "photocraft",
"image": {
"reference": "docker.io/junkerderprovinz/photocraft:latest",
"registry": "docker.io",
"repository": "junkerderprovinz/photocraft",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "TZ",
"example": "Europe/Vienna",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PUID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PGID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "UMASK",
"example": "022",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "CUSTOM_USER",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation"
},
{
"name": "PASSWORD",
"example": "",
"required": false,
"sensitive": true,
"source": "upstream-documentation"
},
{
"name": "LC_ALL",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation",
"prompt": "Language/locale (e.g. es_ES.UTF-8; translation of every application is not guaranteed)"
}
],
"volumes": [
{
"id": "config",
"container_path": "/config",
"compose_source_example": "./appdata",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "storage",
"container_path": "/storage",
"compose_source_example": "./storage",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
}
],
"ports": [
{
"container_port": 3001,
"published_example": 3001,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 3000,
"published_example": 3000,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n photocraft:\n image: junkerderprovinz/photocraft:latest\n container_name: photocraft\n restart: unless-stopped\n shm_size: 1gb\n ports:\n - 3001:3001\n - 3000:3000\n volumes:\n - ./appdata:/config\n - ./storage:/storage\n environment:\n TZ: Europe/Vienna\n PUID: '1000'\n PGID: '1000'\n UMASK: '022'\n"
},
"compose_stack": {
"project_name": "photocraft",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "photocraft",
"service_count": 1,
"services": [
{
"name": "photocraft",
"image": "junkerderprovinz/photocraft:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "junkerderprovinz/photocraft:latest",
"container_name": "photocraft",
"restart": "unless-stopped",
"shm_size": "1gb",
"ports": [
"3001:3001",
"3000:3000"
],
"volumes": [
"./appdata:/config",
"./storage:/storage"
],
"environment": {
"TZ": "Europe/Vienna",
"PUID": "1000",
"PGID": "1000",
"UMASK": "022"
}
}
}
],
"top_level": {},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "photocraft-volume-0",
"service": "photocraft",
"container_path": "/config",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "photocraft-volume-1",
"service": "photocraft",
"container_path": "/storage",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"photocraft"
],
"stop_order": [
"photocraft"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": []
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "https",
"port": 3001,
"path": "/",
"source": "https://github.com/junkerderprovinz/artcraft-apps"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 2048,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"installer_profile": {
"tmpfs_mounts": [
{
"id": "compose-shm",
"container_path": "/dev/shm",
"default_size_mb": 1024,
"minimum_size_mb": 1,
"size_prompt": "Size of the /dev/shm shared memory in MB",
"mount_options": [
"rw",
"nosuid",
"nodev"
]
},
{
"id": "nginx-runtime",
"container_path": "/run/nginx",
"default_size_mb": 1,
"minimum_size_mb": 1,
"prompt_size": false,
"mount_options": [
"rw",
"nosuid",
"nodev",
"mode=0755"
]
}
],
"volume_preparations": [
{
"container_path": "/config",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/storage",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 3000,
"path": "/",
"timeout_seconds": 240,
"request_timeout_seconds": 5,
"stability_seconds": 8,
"accept_any_status": true,
"verify_tls": true
},
"selkies": {
"base": "FROM ghcr.io/linuxserver/baseimage-selkies:ubunturesolute@sha256:6efa3fd775a552938d862f75975d34c418ad26d028ba2c952da58682cfe1cb47",
"dockerfile_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/Dockerfile",
"dockerfile_sha256": "69ab1a81d1696d1bd143a6fa5a121c034ddfb3e83008969340e8cd2413547fe1",
"reviewed_on": "2026-11-04",
"documentation": "https://docs.linuxserver.io/images/docker-baseimage-selkies/",
"nvidia": "available-in-advanced-mode-with-compatible-host-driver-and-toolkit",
"validation": "Intel/AMD tested on a Radeon 680M: GL compositor and VAAPI encoding on the render node"
},
"device_requests": [],
"optional_devices": [],
"hardware_acceleration": {
"prompt": "Selkies desktop and streaming acceleration",
"default": "none",
"profiles": [
{
"id": "none",
"label": "No GPU (CPU)",
"device_requests": [],
"environment": [
{
"name": "AUTO_GPU",
"value": "false"
}
]
},
{
"id": "vaapi",
"label": "Intel/AMD (streaming rendering and encoding)",
"device_requests": [
{
"id": "selkies-render",
"kind": "character-device",
"path_prompt": "Intel/AMD render node",
"host_path_default": "/dev/dri/renderD128",
"container_path_strategy": "same-as-host",
"mode": "0660",
"deny_write": false,
"gid_strategy": "host-device-gid",
"drm_vendor_ids": [
"0x8086",
"0x1002"
]
}
],
"environment": [
{
"name": "PIXELFLUX_WAYLAND",
"value": "true"
},
{
"name": "AUTO_GPU",
"value": "false"
}
],
"environment_from_devices": {
"DRINODE": [
"selkies-render"
],
"DRI_NODE": [
"selkies-render"
],
"ATTACHED_DEVICES_PERMS": [
"selkies-render"
]
}
},
{
"id": "nvidia",
"label": "NVIDIA (Selkies rendering and NVENC)",
"device_requests": [
{
"id": "selkies-nvidia",
"kind": "nvidia-runtime",
"device_selection": "all-requested-by-compose"
}
],
"environment": [
{
"name": "AUTO_GPU",
"value": "true"
},
{
"name": "NVIDIA_VISIBLE_DEVICES",
"value": "all"
},
{
"name": "NVIDIA_DRIVER_CAPABILITIES",
"value": "compute,video,graphics,utility,display"
}
]
}
]
},
"gpu_validation": {
"device_inventory": "host-sysfs-and-stat",
"application_acceleration": "requires-workload-test",
"tone_mapping": "not-implied-by-device-access"
},
"device_permissions": {
"strategy": "linuxserver-native-init",
"service_user": "abc",
"environment": "ATTACHED_DEVICES_PERMS",
"paths": "all-resolved-selected-character-devices"
}
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "pending-per-application"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Community native-desktop image contract reviewed against its published Compose and Dockerfile. Linux amd64 and arm64 manifests exist; runtime, storage and lifecycle tests remain pending per architecture."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "pending",
"service_health": "pending",
"restart_persistence": "pending",
"backup_restore": "pending",
"update_preserves_data": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+4 -1
View File
@@ -329,7 +329,10 @@
"request_timeout_seconds": 10,
"stability_seconds": 4,
"verify_tls": true
}
},
"non_persistent_image_volumes": [
"/tmp/jetty"
]
}
},
"compatibility": {
+3
View File
@@ -788,6 +788,9 @@
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
}
],
"non_persistent_image_volumes": [
"/romm"
]
}
},
+35 -1
View File
@@ -85,6 +85,22 @@
"backup": true,
"default_size_gb": 8
}
},
{
"id": "volume-1",
"container_path": "/etc/searxng",
"compose_source_example": "./config",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 1
}
}
],
"ports": [
@@ -127,7 +143,8 @@
"8080:8080"
],
"volumes": [
"./cache:/var/cache/searxng"
"./cache:/var/cache/searxng",
"./config:/etc/searxng"
]
}
}
@@ -153,6 +170,17 @@
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "searxng-volume-1",
"service": "searxng",
"container_path": "/etc/searxng",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
@@ -378,6 +406,12 @@
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/etc/searxng",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
}
],
"startup_healthcheck": {
+677
View File
@@ -0,0 +1,677 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-soundcraft",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "SoundCraft",
"es_ES": "SoundCraft"
},
"tagline": {
"en_US": "Audio recording and mixing in your browser",
"es_ES": "Grabación y mezcla de audio en el navegador"
},
"description": {
"en_US": "SoundCraft from the ArtCraft project, streamed from a native Linux application using the community-maintained junkerderprovinz image. Files are stored on the server, not in browser storage.",
"es_ES": "SoundCraft del proyecto ArtCraft, con su aplicación nativa de Linux transmitida al navegador mediante la imagen comunitaria de junkerderprovinz. Los documentos se guardan en el servidor, no en el almacenamiento del navegador."
},
"category": "creative",
"category_label": "Creative & Design",
"author": "junkerderprovinz",
"developer": "ArtCraft",
"icon": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/.github/assets/icons/soundcraft.png",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "https",
"port": 3001,
"path": "/"
},
"website": "https://getartcraft.com/apps/soundcraft",
"documentation": "https://github.com/junkerderprovinz/artcraft-apps",
"repository": "https://github.com/storytold/soundcraft",
"tips": [
"This is the native Linux application streamed by Selkies, not the WebAssembly build. Processing and documents stay in the LXC and its mounted directories.",
"The image is maintained by junkerderprovinz; ArtCraft publishes the application packages. It is not an official ArtCraft container image.",
"Use a trusted HTTPS reverse proxy for browser access. Port 3001 uses the upstream self-signed certificate; port 3000 is for an HTTP reverse-proxy backend.",
"The upstream default has no login. Optional CUSTOM_USER and PASSWORD variables enable HTTP basic authentication; do not expose an unauthenticated desktop to untrusted networks.",
"/config holds settings and desktop state and is included in Proxmox backups. /storage holds documents and supports a managed volume or an explicitly selected host directory; host directories require separate backups.",
"The default installation draws on the CPU. The advanced installation can assign an Intel or AMD GPU, which the desktop, the application and the video stream then use; NVIDIA is offered when the host has its driver and the NVIDIA Container Toolkit.",
"Without a GPU, an application may ask to switch to CPU rendering. Choose the CPU option; the application remembers it."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "junkerderprovinz",
"repository": "https://github.com/junkerderprovinz/artcraft-apps",
"revision": "32bee0dea9bdaf5310c693210bea0d732a129ae8",
"image_repository_url": "https://hub.docker.com/r/junkerderprovinz/soundcraft",
"readme_pushed_at": "",
"compose_sha256": "8fef65b5330dd21035acbd8bc587c597610e6db5fdf8a70a07b54dcab25b3695",
"generated_at": "2026-11-03T12:57:29+00:00",
"default_branch": "main",
"readme_raw_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/compose/soundcraft.yaml"
},
"container_contract": {
"service_name": "soundcraft",
"container_name": "soundcraft",
"image": {
"reference": "docker.io/junkerderprovinz/soundcraft:latest",
"registry": "docker.io",
"repository": "junkerderprovinz/soundcraft",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "TZ",
"example": "Europe/Vienna",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PUID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PGID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "UMASK",
"example": "022",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "CUSTOM_USER",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation"
},
{
"name": "PASSWORD",
"example": "",
"required": false,
"sensitive": true,
"source": "upstream-documentation"
},
{
"name": "LC_ALL",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation",
"prompt": "Language/locale (e.g. es_ES.UTF-8; translation of every application is not guaranteed)"
}
],
"volumes": [
{
"id": "config",
"container_path": "/config",
"compose_source_example": "./appdata",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "storage",
"container_path": "/storage",
"compose_source_example": "./storage",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
}
],
"ports": [
{
"container_port": 3001,
"published_example": 3001,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 3000,
"published_example": 3000,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n soundcraft:\n image: junkerderprovinz/soundcraft:latest\n container_name: soundcraft\n restart: unless-stopped\n shm_size: 1gb\n ports:\n - 3001:3001\n - 3000:3000\n volumes:\n - ./appdata:/config\n - ./storage:/storage\n environment:\n TZ: Europe/Vienna\n PUID: '1000'\n PGID: '1000'\n UMASK: '022'\n"
},
"compose_stack": {
"project_name": "soundcraft",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "soundcraft",
"service_count": 1,
"services": [
{
"name": "soundcraft",
"image": "junkerderprovinz/soundcraft:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "junkerderprovinz/soundcraft:latest",
"container_name": "soundcraft",
"restart": "unless-stopped",
"shm_size": "1gb",
"ports": [
"3001:3001",
"3000:3000"
],
"volumes": [
"./appdata:/config",
"./storage:/storage"
],
"environment": {
"TZ": "Europe/Vienna",
"PUID": "1000",
"PGID": "1000",
"UMASK": "022"
}
}
}
],
"top_level": {},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "soundcraft-volume-0",
"service": "soundcraft",
"container_path": "/config",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "soundcraft-volume-1",
"service": "soundcraft",
"container_path": "/storage",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"soundcraft"
],
"stop_order": [
"soundcraft"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": []
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "https",
"port": 3001,
"path": "/",
"source": "https://github.com/junkerderprovinz/artcraft-apps"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 2048,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"installer_profile": {
"tmpfs_mounts": [
{
"id": "compose-shm",
"container_path": "/dev/shm",
"default_size_mb": 1024,
"minimum_size_mb": 1,
"size_prompt": "Size of the /dev/shm shared memory in MB",
"mount_options": [
"rw",
"nosuid",
"nodev"
]
},
{
"id": "nginx-runtime",
"container_path": "/run/nginx",
"default_size_mb": 1,
"minimum_size_mb": 1,
"prompt_size": false,
"mount_options": [
"rw",
"nosuid",
"nodev",
"mode=0755"
]
}
],
"volume_preparations": [
{
"container_path": "/config",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/storage",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 3000,
"path": "/",
"timeout_seconds": 240,
"request_timeout_seconds": 5,
"stability_seconds": 8,
"accept_any_status": true,
"verify_tls": true
},
"selkies": {
"base": "FROM ghcr.io/linuxserver/baseimage-selkies:ubunturesolute@sha256:6efa3fd775a552938d862f75975d34c418ad26d028ba2c952da58682cfe1cb47",
"dockerfile_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/Dockerfile",
"dockerfile_sha256": "69ab1a81d1696d1bd143a6fa5a121c034ddfb3e83008969340e8cd2413547fe1",
"reviewed_on": "2026-11-04",
"documentation": "https://docs.linuxserver.io/images/docker-baseimage-selkies/",
"nvidia": "available-in-advanced-mode-with-compatible-host-driver-and-toolkit",
"validation": "Intel/AMD tested on a Radeon 680M: GL compositor and VAAPI encoding on the render node"
},
"device_requests": [],
"optional_devices": [],
"hardware_acceleration": {
"prompt": "Selkies desktop and streaming acceleration",
"default": "none",
"profiles": [
{
"id": "none",
"label": "No GPU (CPU)",
"device_requests": [],
"environment": [
{
"name": "AUTO_GPU",
"value": "false"
}
]
},
{
"id": "vaapi",
"label": "Intel/AMD (streaming rendering and encoding)",
"device_requests": [
{
"id": "selkies-render",
"kind": "character-device",
"path_prompt": "Intel/AMD render node",
"host_path_default": "/dev/dri/renderD128",
"container_path_strategy": "same-as-host",
"mode": "0660",
"deny_write": false,
"gid_strategy": "host-device-gid",
"drm_vendor_ids": [
"0x8086",
"0x1002"
]
}
],
"environment": [
{
"name": "PIXELFLUX_WAYLAND",
"value": "true"
},
{
"name": "AUTO_GPU",
"value": "false"
}
],
"environment_from_devices": {
"DRINODE": [
"selkies-render"
],
"DRI_NODE": [
"selkies-render"
],
"ATTACHED_DEVICES_PERMS": [
"selkies-render"
]
}
},
{
"id": "nvidia",
"label": "NVIDIA (Selkies rendering and NVENC)",
"device_requests": [
{
"id": "selkies-nvidia",
"kind": "nvidia-runtime",
"device_selection": "all-requested-by-compose"
}
],
"environment": [
{
"name": "AUTO_GPU",
"value": "true"
},
{
"name": "NVIDIA_VISIBLE_DEVICES",
"value": "all"
},
{
"name": "NVIDIA_DRIVER_CAPABILITIES",
"value": "compute,video,graphics,utility,display"
}
]
}
]
},
"gpu_validation": {
"device_inventory": "host-sysfs-and-stat",
"application_acceleration": "requires-workload-test",
"tone_mapping": "not-implied-by-device-access"
},
"device_permissions": {
"strategy": "linuxserver-native-init",
"service_user": "abc",
"environment": "ATTACHED_DEVICES_PERMS",
"paths": "all-resolved-selected-character-devices"
}
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "pending-per-application"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Community native-desktop image contract reviewed against its published Compose and Dockerfile. Linux amd64 and arm64 manifests exist; runtime, storage and lifecycle tests remain pending per architecture."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "pending",
"service_health": "pending",
"restart_persistence": "pending",
"backup_restore": "pending",
"update_preserves_data": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+477
View File
@@ -0,0 +1,477 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-spoolman",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "Spoolman"
},
"tagline": {
"en_US": "Track 3D printer filament spools and usage."
},
"description": {
"en_US": "A self-hosted filament inventory for 3D printers. Manage spools, materials, manufacturers, locations and labels in the web UI, and integrate with Moonraker, OctoPrint and other printer tools. The official image uses SQLite by default; no separate database container is required."
},
"category": "tools",
"category_label": "Tools",
"author": "Donkie",
"developer": "Donkie",
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/spoolman.webp",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "http",
"port": 8000,
"path": "/"
},
"website": "https://github.com/Donkie/Spoolman",
"documentation": "https://github.com/Donkie/Spoolman/wiki/Installation",
"repository": "https://github.com/Donkie/Spoolman",
"tips": [
"Spoolman has no built-in authentication. Keep it on a trusted network; do not expose it directly to the internet.",
"The official image uses SQLite by default and stores the database, automatic backups, logs and cache in the persistent data directory."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "Donkie",
"repository": "https://github.com/Donkie/Spoolman",
"revision": "ff8efd517b76a4b2783f29c89e9b9fbcd8cd167b",
"image_repository_url": "https://github.com/Donkie/Spoolman/pkgs/container/spoolman",
"readme_pushed_at": "2026-10-31T09:39:19Z",
"compose_sha256": "d9b115c4c37589f9813e54f926fdd22e7a10a44a6e56160f837b1247638fac83",
"generated_at": "2026-11-02T20:02:46+00:00",
"default_branch": "master",
"readme_raw_url": "https://github.com/Donkie/Spoolman/wiki/Installation"
},
"container_contract": {
"service_name": "spoolman",
"container_name": "spoolman",
"image": {
"reference": "ghcr.io/donkie/spoolman:latest",
"registry": "ghcr.io",
"repository": "ghcr.io/donkie/spoolman",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "PUID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-image-default",
"prompt_user": false
},
{
"name": "PGID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-image-default",
"prompt_user": false
},
{
"name": "TZ",
"example": "Etc/UTC",
"required": true,
"sensitive": false,
"source": "upstream-compose",
"prompt_user": false
}
],
"volumes": [
{
"id": "volume-0",
"container_path": "/home/app/.local/share/spoolman",
"compose_source_example": "./data",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 4
}
}
],
"ports": [
{
"container_port": 8000,
"published_example": 7912,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n spoolman:\n image: ghcr.io/donkie/spoolman:latest\n container_name: spoolman\n restart: unless-stopped\n ports:\n - \"7912:8000/tcp\"\n volumes:\n - ./data:/home/app/.local/share/spoolman\n environment:\n PUID: \"1000\"\n PGID: \"1000\"\n TZ: Etc/UTC\n"
},
"compose_stack": {
"project_name": "spoolman",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "spoolman",
"service_count": 1,
"services": [
{
"name": "spoolman",
"image": "ghcr.io/donkie/spoolman:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "ghcr.io/donkie/spoolman:latest",
"container_name": "spoolman",
"restart": "unless-stopped",
"ports": [
"7912:8000/tcp"
],
"volumes": [
"./data:/home/app/.local/share/spoolman"
],
"environment": {
"PUID": "1000",
"PGID": "1000",
"TZ": "Etc/UTC"
}
}
}
],
"top_level": {
"name": "spoolman"
},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "spoolman-volume-0",
"service": "spoolman",
"container_path": "/home/app/.local/share/spoolman",
"mode": "managed-volume",
"user_selectable": true,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"spoolman"
],
"stop_order": [
"spoolman"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": []
}
},
"first_run": {
"endpoints": [
{
"label": "Spoolman web interface",
"scheme": "http",
"port": 8000,
"path": "/",
"source": "upstream-image"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
],
"installer_profile": {
"startup_healthcheck": {
"scheme": "http",
"port": 8000,
"path": "/",
"timeout_seconds": 180,
"request_timeout_seconds": 10,
"stability_seconds": 4,
"verify_tls": true
},
"volume_preparations": [
{
"container_path": "/home/app/.local/share/spoolman",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
}
],
"volume_owner": {
"uid": 1000,
"gid": 1000
}
}
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Single-image definitions are installable when every declared Compose option has a native Proxmox translation. Multi-image and unsupported runtime features remain blocked until their orchestrator or mapping is available."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "passed-default-official-image-skopeo-and-first-start-http",
"advanced_install": "pending-custom-install-summary-validation",
"service_health": "passed-web-api-crud",
"restart_persistence": "passed-managed-and-host-bind-database-and-records",
"backup_restore": "passed-pbs-backup-and-manager-recover-record-preserved",
"update_preserves_data": "no-update-available-at-check",
"modification": "passed-cpu-ram-up-and-down-without-image-pull-or-recreate",
"volumes": "passed-managed-storage-and-host-bind-crud-owner-and-data-check",
"removal": "passed-manager-removal-host-path-retained-then-temporary-data-cleaned"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+8 -8
View File
@@ -44,9 +44,9 @@
"provider": "stirling-pdf",
"repository": "https://github.com/Stirling-Tools/Stirling-PDF",
"revision": "e7f6b5fe482945fca3527cc2f4035df717a526cf26c1ebd3e5a272ec140132f0",
"image_repository_url": "https://docker.stirlingpdf.com/stirlingtools/stirling-pdf",
"image_repository_url": "https://ghcr.io/stirling-tools/stirling-pdf",
"readme_pushed_at": "",
"compose_sha256": "6fa4793bff33f54b73a99364f26f3b69313a7c39dcd787c836d4f01f75e55146",
"compose_sha256": "9c68478ad9b0d9c9ffdc29917de8d33afbaae66a703daa4c02e0c148ecfb8a10",
"generated_at": "2026-10-25T16:06:01+00:00",
"readme_raw_url": "https://docs.stirlingpdf.com/Server/Install/Docker/"
},
@@ -54,9 +54,9 @@
"service_name": "stirling-pdf",
"container_name": "stirling-pdf",
"image": {
"reference": "docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest",
"registry": "docker.stirlingpdf.com",
"repository": "docker.stirlingpdf.com/stirlingtools/stirling-pdf",
"reference": "ghcr.io/stirling-tools/stirling-pdf:latest",
"registry": "ghcr.io",
"repository": "ghcr.io/stirling-tools/stirling-pdf",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-selected-tag-to-architecture-digest-at-install"
@@ -123,7 +123,7 @@
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "{\n \"name\": \"stirling-pdf\",\n \"services\": {\n \"stirling-pdf\": {\n \"image\": \"docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"8080:8080\"\n ],\n \"volumes\": [\n \"stirling-config:/configs\",\n \"stirling-storage:/storage\"\n ],\n \"environment\": {\n \"PUID\": \"1000\",\n \"PGID\": \"1000\"\n },\n \"deploy\": {\n \"resources\": {\n \"limits\": {\n \"memory\": \"4g\"\n }\n }\n }\n }\n }\n}"
"original_compose": "{\n \"name\": \"stirling-pdf\",\n \"services\": {\n \"stirling-pdf\": {\n \"image\": \"ghcr.io/stirling-tools/stirling-pdf:latest\",\n \"restart\": \"unless-stopped\",\n \"ports\": [\n \"8080:8080\"\n ],\n \"volumes\": [\n \"stirling-config:/configs\",\n \"stirling-storage:/storage\"\n ],\n \"environment\": {\n \"PUID\": \"1000\",\n \"PGID\": \"1000\"\n },\n \"deploy\": {\n \"resources\": {\n \"limits\": {\n \"memory\": \"4g\"\n }\n }\n }\n }\n }\n}"
},
"compose_stack": {
"project_name": "stirling-pdf",
@@ -134,7 +134,7 @@
"services": [
{
"name": "stirling-pdf",
"image": "docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest",
"image": "ghcr.io/stirling-tools/stirling-pdf:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
@@ -142,7 +142,7 @@
"frontend_network": true,
"private_network": false,
"compose": {
"image": "docker.stirlingpdf.com/stirlingtools/stirling-pdf:latest",
"image": "ghcr.io/stirling-tools/stirling-pdf:latest",
"restart": "unless-stopped",
"ports": [
"8080:8080"
+19 -29
View File
@@ -82,22 +82,6 @@
"backup": true,
"default_size_gb": 8
}
},
{
"id": "volume-1",
"container_path": "/dev/net/tun",
"compose_source_example": "/dev/net/tun",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
}
],
"ports": [],
@@ -153,7 +137,7 @@
"NET_ADMIN",
"NET_RAW"
],
"entrypoint": "/bin/sh -c \"tailscaled --state=/var/lib/tailscale/tailscaled.state & sleep 10; tailscale web --listen 0.0.0.0:5252\""
"entrypoint": "/bin/sh -c 'sysctl -w net.ipv4.ip_forward=1 net.ipv6.conf.all.forwarding=1 >/dev/null 2>&1; tailscaled --state=/var/lib/tailscale/tailscaled.state & i=0; while [ $i -lt 60 ]; do lan=$(ip -4 addr show dev eth0 2>/dev/null | sed -n \"s/.*inet \\([0-9.]*\\)\\/.*/\\1/p\" | head -n 1); [ -n \"$lan\" ] && break; i=$((i+1)); sleep 1; done; sleep 10; exec tailscale web --listen \"${lan:-0.0.0.0}:5252\"'"
}
}
],
@@ -180,17 +164,6 @@
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "tailscale-volume-1",
"service": "tailscale",
"container_path": "/dev/net/tun",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
@@ -270,7 +243,7 @@
},
"installer_profile": {
"runtime": {
"compose_entrypoint": "/bin/sh -c \"tailscaled --state=/var/lib/tailscale/tailscaled.state & sleep 10; tailscale web --listen 0.0.0.0:5252\""
"compose_entrypoint": "/bin/sh -c 'sysctl -w net.ipv4.ip_forward=1 net.ipv6.conf.all.forwarding=1 >/dev/null 2>&1; tailscaled --state=/var/lib/tailscale/tailscaled.state & i=0; while [ $i -lt 60 ]; do lan=$(ip -4 addr show dev eth0 2>/dev/null | sed -n \"s/.*inet \\([0-9.]*\\)\\/.*/\\1/p\" | head -n 1); [ -n \"$lan\" ] && break; i=$((i+1)); sleep 1; done; sleep 10; exec tailscale web --listen \"${lan:-0.0.0.0}:5252\"'"
},
"network": {
"compose_mode": "host"
@@ -288,6 +261,23 @@
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
}
],
"device_requests": [
{
"id": "dev-net-tun",
"kind": "character-device",
"purpose": "tun",
"enable_prompt": "Pass /dev/net/tun to the LXC",
"enabled_default": true,
"required_by_compose": true,
"path_prompt": "Host device for /dev/net/tun",
"host_path_default": "/dev/net/tun",
"container_path": "/dev/net/tun",
"mode": "preserve-host",
"deny_write": false,
"gid_strategy": "host-device-gid",
"source_mapping": "/dev/net/tun:/dev/net/tun"
}
]
},
"adaptations": [
+47 -3
View File
@@ -60,7 +60,24 @@
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [],
"volumes": [],
"volumes": [
{
"id": "volume-0",
"container_path": "/var/lib/tor",
"compose_source_example": "./tor-data",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 1
}
}
],
"ports": [
{
"container_port": 9050,
@@ -103,6 +120,9 @@
"ports": [
"9050:9050",
"8118:8118"
],
"volumes": [
"./tor-data:/var/lib/tor"
]
}
}
@@ -119,7 +139,19 @@
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [],
"storage": [
{
"id": "tor-volume-0",
"service": "tor",
"container_path": "/var/lib/tor",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
@@ -323,7 +355,19 @@
"SOCKS5 proxy: configure your application with the LXC IP address shown above and port 9050.",
"HTTP CONNECT proxy: use the same IP address and port 8118. These addresses are proxy settings, not web links.",
"Only applications configured to use this proxy send their traffic through Tor."
]
],
"volume_preparations": [
{
"container_path": "/var/lib/tor",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
}
],
"volume_owner": {
"uid": 101,
"gid": 102
}
}
},
"compatibility": {
+292
View File
@@ -0,0 +1,292 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-unbound",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "Unbound"
},
"tagline": {
"en_US": "A validating, recursive DNS resolver for your private network."
},
"description": {
"en_US": "Run the community-maintained klutchell image of Unbound as a DNS resolver on its own Proxmox LXC. It listens on TCP and UDP port 53 and can load optional custom configuration files."
},
"category": "adblock",
"category_label": "Adblock & DNS",
"author": "Kyle Harding",
"developer": "Kyle Harding (klutchell)",
"icon": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/unbound.webp",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64",
"armhf"
],
"launch": {
"scheme": "http",
"port": null,
"path": "/"
},
"website": "https://unbound.net/",
"documentation": "https://github.com/klutchell/unbound-docker#readme",
"repository": "https://github.com/klutchell/unbound-docker",
"tips": [
"Unbound has no web interface. Use the LXC IP as a DNS server on TCP and UDP port 53.",
"The default image config listens on all interfaces and accepts clients from private IPv4 ranges. Keep it behind your trusted LAN firewall; do not expose recursive DNS publicly.",
"The original GitHub repository has moved to klutchell/unbound-docker; the published Docker Hub image remains klutchell/unbound:main. The image is an unofficial community image, not published by NLnet Labs.",
"Optional custom .conf files go under /etc/unbound/custom.conf.d and must be readable by UID/GID 101:102 or world-readable."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "klutchell",
"repository": "https://github.com/klutchell/unbound-docker",
"revision": "1efbea960bf9462b6fb6dd71aa702ad32d6820d7",
"default_branch": "main",
"image_repository_url": "https://hub.docker.com/r/klutchell/unbound",
"readme_pushed_at": "2026-11-02T14:31:22Z",
"compose_sha256": "faf73a93c1f7d4d43f1eb61ba2e62a4418bd501f0c827b080ea9897964e75848",
"generated_at": "2026-11-02T21:21:54+00:00",
"readme_raw_url": "https://raw.githubusercontent.com/klutchell/unbound-docker/main/README.md"
},
"container_contract": {
"service_name": "unbound",
"container_name": "unbound",
"image": {
"reference": "klutchell/unbound:main",
"registry": "docker.io",
"repository": "klutchell/unbound",
"tag": "main",
"digest": null,
"pull_policy": "resolve-selected-tag-to-architecture-digest-at-install"
},
"environment": [],
"volumes": [
{
"id": "volume-0",
"container_path": "/etc/unbound/custom.conf.d",
"compose_source_example": "./config",
"read_only": false,
"required": false,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "host-bind",
"managed_volume": {
"backup": true,
"default_size_gb": 1
}
}
],
"ports": [
{
"container_port": 53,
"published_example": 53,
"protocol": "udp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 53,
"published_example": 53,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "name: unbound\nservices:\n unbound:\n image: klutchell/unbound:main\n container_name: unbound\n restart: unless-stopped\n ports:\n - 53:53/udp\n - 53:53/tcp\n volumes:\n - ./config:/etc/unbound/custom.conf.d\n"
},
"compose_stack": {
"project_name": "unbound",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "unbound",
"service_count": 1,
"services": [
{
"name": "unbound",
"image": "klutchell/unbound:main",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "klutchell/unbound:main",
"container_name": "unbound",
"restart": "unless-stopped",
"ports": [
"53:53/udp",
"53:53/tcp"
],
"volumes": [
"./config:/etc/unbound/custom.conf.d"
]
}
}
],
"top_level": {
"name": "unbound"
},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "unbound-volume-0",
"service": "unbound",
"container_path": "/etc/unbound/custom.conf.d",
"mode": "user-selectable",
"user_selectable": true,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": "Host directory containing optional custom Unbound .conf files",
"default": "host-bind",
"installation_choice": [
"managed-volume",
"host-bind"
]
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"unbound"
],
"stop_order": [
"unbound"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
]
}
},
"first_run": {
"endpoints": [],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 512,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 120
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"adaptations": [],
"installer_profile": {
"volume_preparations": [
{
"container_path": "/etc/unbound/custom.conf.d",
"owner_strategy": "mapped-root",
"remove_lost_found": true,
"only_when_mount_type": "managed-volume"
}
],
"startup_healthcheck": {
"type": "running",
"timeout_seconds": 90,
"stability_seconds": 20
}
},
"catalog": {
"replaces_discovered_ids": []
}
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"container_name",
"image",
"ports",
"restart",
"volumes"
],
"untranslated_blockers": [],
"policy": "This single-image Compose contract maps to one unprivileged Proxmox LXC. The optional custom-config directory can use a Proxmox-managed volume or a host directory; the image defaults work with an empty directory."
},
"validation": {
"schema": "passed-at-generation",
"image_resolution": "passed-skopeo-16-layers",
"clean_install": "passed-default-install-and-first-start-healthcheck",
"advanced_install": "pending",
"service_health": "passed-recursion-and-custom-local-data-over-udp-and-tcp",
"restart_persistence": "passed-custom-zone-after-pct-reboot",
"backup_restore": "pending",
"update_preserves_data": "pending-update-check-not-run",
"modification": "pending-manager-ui-unresponsive-no-changes-applied",
"managed_volume": "passed-config-volume-1g",
"host_bind": "pending",
"removal": "passed-manager-remove-ct-disks-and-record-cleaned"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+4 -1
View File
@@ -323,7 +323,10 @@
"request_timeout_seconds": 10,
"stability_seconds": 4,
"verify_tls": true
}
},
"non_persistent_image_volumes": [
"/var/log"
]
},
"adaptations": [
{
+677
View File
@@ -0,0 +1,677 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-vectorcraft",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "VectorCraft",
"es_ES": "VectorCraft"
},
"tagline": {
"en_US": "Vector illustration in your browser",
"es_ES": "Ilustración vectorial en el navegador"
},
"description": {
"en_US": "VectorCraft from the ArtCraft project, streamed from a native Linux application using the community-maintained junkerderprovinz image. Files are stored on the server, not in browser storage.",
"es_ES": "VectorCraft del proyecto ArtCraft, con su aplicación nativa de Linux transmitida al navegador mediante la imagen comunitaria de junkerderprovinz. Los documentos se guardan en el servidor, no en el almacenamiento del navegador."
},
"category": "creative",
"category_label": "Creative & Design",
"author": "junkerderprovinz",
"developer": "ArtCraft",
"icon": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/.github/assets/icons/vectorcraft.png",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "https",
"port": 3001,
"path": "/"
},
"website": "https://getartcraft.com/apps/vectorcraft",
"documentation": "https://github.com/junkerderprovinz/artcraft-apps",
"repository": "https://github.com/storytold/vectorcraft",
"tips": [
"This is the native Linux application streamed by Selkies, not the WebAssembly build. Processing and documents stay in the LXC and its mounted directories.",
"The image is maintained by junkerderprovinz; ArtCraft publishes the application packages. It is not an official ArtCraft container image.",
"Use a trusted HTTPS reverse proxy for browser access. Port 3001 uses the upstream self-signed certificate; port 3000 is for an HTTP reverse-proxy backend.",
"The upstream default has no login. Optional CUSTOM_USER and PASSWORD variables enable HTTP basic authentication; do not expose an unauthenticated desktop to untrusted networks.",
"/config holds settings and desktop state and is included in Proxmox backups. /storage holds documents and supports a managed volume or an explicitly selected host directory; host directories require separate backups.",
"The default installation draws on the CPU. The advanced installation can assign an Intel or AMD GPU, which the desktop, the application and the video stream then use; NVIDIA is offered when the host has its driver and the NVIDIA Container Toolkit.",
"Without a GPU, an application may ask to switch to CPU rendering. Choose the CPU option; the application remembers it."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "junkerderprovinz",
"repository": "https://github.com/junkerderprovinz/artcraft-apps",
"revision": "32bee0dea9bdaf5310c693210bea0d732a129ae8",
"image_repository_url": "https://hub.docker.com/r/junkerderprovinz/vectorcraft",
"readme_pushed_at": "",
"compose_sha256": "a62cf232ee367ccb49096aec28637b0e9b78fce44b52574a57fe05e918468a14",
"generated_at": "2026-11-03T12:57:29+00:00",
"default_branch": "main",
"readme_raw_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/compose/vectorcraft.yaml"
},
"container_contract": {
"service_name": "vectorcraft",
"container_name": "vectorcraft",
"image": {
"reference": "docker.io/junkerderprovinz/vectorcraft:latest",
"registry": "docker.io",
"repository": "junkerderprovinz/vectorcraft",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "TZ",
"example": "Europe/Vienna",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PUID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PGID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "UMASK",
"example": "022",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "CUSTOM_USER",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation"
},
{
"name": "PASSWORD",
"example": "",
"required": false,
"sensitive": true,
"source": "upstream-documentation"
},
{
"name": "LC_ALL",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation",
"prompt": "Language/locale (e.g. es_ES.UTF-8; translation of every application is not guaranteed)"
}
],
"volumes": [
{
"id": "config",
"container_path": "/config",
"compose_source_example": "./appdata",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "storage",
"container_path": "/storage",
"compose_source_example": "./storage",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
}
],
"ports": [
{
"container_port": 3001,
"published_example": 3001,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 3000,
"published_example": 3000,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n vectorcraft:\n image: junkerderprovinz/vectorcraft:latest\n container_name: vectorcraft\n restart: unless-stopped\n shm_size: 1gb\n ports:\n - 3001:3001\n - 3000:3000\n volumes:\n - ./appdata:/config\n - ./storage:/storage\n environment:\n TZ: Europe/Vienna\n PUID: '1000'\n PGID: '1000'\n UMASK: '022'\n"
},
"compose_stack": {
"project_name": "vectorcraft",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "vectorcraft",
"service_count": 1,
"services": [
{
"name": "vectorcraft",
"image": "junkerderprovinz/vectorcraft:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "junkerderprovinz/vectorcraft:latest",
"container_name": "vectorcraft",
"restart": "unless-stopped",
"shm_size": "1gb",
"ports": [
"3001:3001",
"3000:3000"
],
"volumes": [
"./appdata:/config",
"./storage:/storage"
],
"environment": {
"TZ": "Europe/Vienna",
"PUID": "1000",
"PGID": "1000",
"UMASK": "022"
}
}
}
],
"top_level": {},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "vectorcraft-volume-0",
"service": "vectorcraft",
"container_path": "/config",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "vectorcraft-volume-1",
"service": "vectorcraft",
"container_path": "/storage",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"vectorcraft"
],
"stop_order": [
"vectorcraft"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": []
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "https",
"port": 3001,
"path": "/",
"source": "https://github.com/junkerderprovinz/artcraft-apps"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 2048,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"installer_profile": {
"tmpfs_mounts": [
{
"id": "compose-shm",
"container_path": "/dev/shm",
"default_size_mb": 1024,
"minimum_size_mb": 1,
"size_prompt": "Size of the /dev/shm shared memory in MB",
"mount_options": [
"rw",
"nosuid",
"nodev"
]
},
{
"id": "nginx-runtime",
"container_path": "/run/nginx",
"default_size_mb": 1,
"minimum_size_mb": 1,
"prompt_size": false,
"mount_options": [
"rw",
"nosuid",
"nodev",
"mode=0755"
]
}
],
"volume_preparations": [
{
"container_path": "/config",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/storage",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 3000,
"path": "/",
"timeout_seconds": 240,
"request_timeout_seconds": 5,
"stability_seconds": 8,
"accept_any_status": true,
"verify_tls": true
},
"selkies": {
"base": "FROM ghcr.io/linuxserver/baseimage-selkies:ubunturesolute@sha256:6efa3fd775a552938d862f75975d34c418ad26d028ba2c952da58682cfe1cb47",
"dockerfile_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/Dockerfile",
"dockerfile_sha256": "69ab1a81d1696d1bd143a6fa5a121c034ddfb3e83008969340e8cd2413547fe1",
"reviewed_on": "2026-11-04",
"documentation": "https://docs.linuxserver.io/images/docker-baseimage-selkies/",
"nvidia": "available-in-advanced-mode-with-compatible-host-driver-and-toolkit",
"validation": "Intel/AMD tested on a Radeon 680M: GL compositor and VAAPI encoding on the render node"
},
"device_requests": [],
"optional_devices": [],
"hardware_acceleration": {
"prompt": "Selkies desktop and streaming acceleration",
"default": "none",
"profiles": [
{
"id": "none",
"label": "No GPU (CPU)",
"device_requests": [],
"environment": [
{
"name": "AUTO_GPU",
"value": "false"
}
]
},
{
"id": "vaapi",
"label": "Intel/AMD (streaming rendering and encoding)",
"device_requests": [
{
"id": "selkies-render",
"kind": "character-device",
"path_prompt": "Intel/AMD render node",
"host_path_default": "/dev/dri/renderD128",
"container_path_strategy": "same-as-host",
"mode": "0660",
"deny_write": false,
"gid_strategy": "host-device-gid",
"drm_vendor_ids": [
"0x8086",
"0x1002"
]
}
],
"environment": [
{
"name": "PIXELFLUX_WAYLAND",
"value": "true"
},
{
"name": "AUTO_GPU",
"value": "false"
}
],
"environment_from_devices": {
"DRINODE": [
"selkies-render"
],
"DRI_NODE": [
"selkies-render"
],
"ATTACHED_DEVICES_PERMS": [
"selkies-render"
]
}
},
{
"id": "nvidia",
"label": "NVIDIA (Selkies rendering and NVENC)",
"device_requests": [
{
"id": "selkies-nvidia",
"kind": "nvidia-runtime",
"device_selection": "all-requested-by-compose"
}
],
"environment": [
{
"name": "AUTO_GPU",
"value": "true"
},
{
"name": "NVIDIA_VISIBLE_DEVICES",
"value": "all"
},
{
"name": "NVIDIA_DRIVER_CAPABILITIES",
"value": "compute,video,graphics,utility,display"
}
]
}
]
},
"gpu_validation": {
"device_inventory": "host-sysfs-and-stat",
"application_acceleration": "requires-workload-test",
"tone_mapping": "not-implied-by-device-access"
},
"device_permissions": {
"strategy": "linuxserver-native-init",
"service_user": "abc",
"environment": "ATTACHED_DEVICES_PERMS",
"paths": "all-resolved-selected-character-devices"
}
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "pending-per-application"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Community native-desktop image contract reviewed against its published Compose and Dockerfile. Linux amd64 and arm64 manifests exist; runtime, storage and lifecycle tests remain pending per architecture."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "pending",
"service_health": "pending",
"restart_persistence": "pending",
"backup_restore": "pending",
"update_preserves_data": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+47 -3
View File
@@ -77,7 +77,24 @@
"source": "upstream-documentation"
}
],
"volumes": [],
"volumes": [
{
"id": "volume-0",
"container_path": "/config",
"compose_source_example": "./config",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 1
}
}
],
"ports": [
{
"container_port": 5000,
@@ -117,7 +134,10 @@
"environment": {
"WHOOGLE_USER": "admin",
"WHOOGLE_PASS": "${GENERATED_WHOOGLE_PASS}"
}
},
"volumes": [
"./config:/config"
]
}
}
],
@@ -133,7 +153,19 @@
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [],
"storage": [
{
"id": "whoogle-volume-0",
"service": "whoogle",
"container_path": "/config",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
@@ -378,6 +410,18 @@
"bytes": 24,
"prompt": false
}
},
"volume_preparations": [
{
"container_path": "/config",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user",
"only_when_mount_type": "managed-volume"
}
],
"volume_owner": {
"uid": 927,
"gid": 927
}
},
"catalog": {
+677
View File
@@ -0,0 +1,677 @@
{
"schema_version": "0.5.0",
"kind": "proxmenux.oci-template",
"id": "image-wordcraft",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "WordCraft",
"es_ES": "WordCraft"
},
"tagline": {
"en_US": "Word processing in your browser",
"es_ES": "Procesador de textos en el navegador"
},
"description": {
"en_US": "WordCraft from the ArtCraft project, streamed from a native Linux application using the community-maintained junkerderprovinz image. Files are stored on the server, not in browser storage.",
"es_ES": "WordCraft del proyecto ArtCraft, con su aplicación nativa de Linux transmitida al navegador mediante la imagen comunitaria de junkerderprovinz. Los documentos se guardan en el servidor, no en el almacenamiento del navegador."
},
"category": "creative",
"category_label": "Creative & Design",
"author": "junkerderprovinz",
"developer": "ArtCraft",
"icon": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/.github/assets/icons/wordcraft.png",
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "https",
"port": 3001,
"path": "/"
},
"website": "https://getartcraft.com/apps/wordcraft",
"documentation": "https://github.com/junkerderprovinz/artcraft-apps",
"repository": "https://github.com/storytold/wordcraft",
"tips": [
"This is the native Linux application streamed by Selkies, not the WebAssembly build. Processing and documents stay in the LXC and its mounted directories.",
"The image is maintained by junkerderprovinz; ArtCraft publishes the application packages. It is not an official ArtCraft container image.",
"Use a trusted HTTPS reverse proxy for browser access. Port 3001 uses the upstream self-signed certificate; port 3000 is for an HTTP reverse-proxy backend.",
"The upstream default has no login. Optional CUSTOM_USER and PASSWORD variables enable HTTP basic authentication; do not expose an unauthenticated desktop to untrusted networks.",
"/config holds settings and desktop state and is included in Proxmox backups. /storage holds documents and supports a managed volume or an explicitly selected host directory; host directories require separate backups.",
"The default installation draws on the CPU. The advanced installation can assign an Intel or AMD GPU, which the desktop, the application and the video stream then use; NVIDIA is offered when the host has its driver and the NVIDIA Container Toolkit.",
"Without a GPU, an application may ask to switch to CPU rendering. Choose the CPU option; the application remembers it."
],
"mini_changelog": [],
"display_version": null,
"updated_at": null
},
"source": {
"provider": "junkerderprovinz",
"repository": "https://github.com/junkerderprovinz/artcraft-apps",
"revision": "32bee0dea9bdaf5310c693210bea0d732a129ae8",
"image_repository_url": "https://hub.docker.com/r/junkerderprovinz/wordcraft",
"readme_pushed_at": "",
"compose_sha256": "cc6ac9c1448000c780e93d69e0ced1f39f3256fb2478fda4453442f62e2aa23f",
"generated_at": "2026-11-03T12:57:30+00:00",
"default_branch": "main",
"readme_raw_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/compose/wordcraft.yaml"
},
"container_contract": {
"service_name": "wordcraft",
"container_name": "wordcraft",
"image": {
"reference": "docker.io/junkerderprovinz/wordcraft:latest",
"registry": "docker.io",
"repository": "junkerderprovinz/wordcraft",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-written-reference-to-architecture-digest-at-install"
},
"environment": [
{
"name": "TZ",
"example": "Europe/Vienna",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PUID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "PGID",
"example": "1000",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "UMASK",
"example": "022",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "CUSTOM_USER",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation"
},
{
"name": "PASSWORD",
"example": "",
"required": false,
"sensitive": true,
"source": "upstream-documentation"
},
{
"name": "LC_ALL",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-documentation",
"prompt": "Language/locale (e.g. es_ES.UTF-8; translation of every application is not guaranteed)"
}
],
"volumes": [
{
"id": "config",
"container_path": "/config",
"compose_source_example": "./appdata",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "storage",
"container_path": "/storage",
"compose_source_example": "./storage",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume",
"host-bind"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 16
}
}
],
"ports": [
{
"container_port": 3001,
"published_example": 3001,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 3000,
"published_example": 3000,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "services:\n wordcraft:\n image: junkerderprovinz/wordcraft:latest\n container_name: wordcraft\n restart: unless-stopped\n shm_size: 1gb\n ports:\n - 3001:3001\n - 3000:3000\n volumes:\n - ./appdata:/config\n - ./storage:/storage\n environment:\n TZ: Europe/Vienna\n PUID: '1000'\n PGID: '1000'\n UMASK: '022'\n"
},
"compose_stack": {
"project_name": "wordcraft",
"deployment_model": "one-native-oci-lxc-per-compose-service",
"user_experience": "single-application-install",
"main_service": "wordcraft",
"service_count": 1,
"services": [
{
"name": "wordcraft",
"image": "junkerderprovinz/wordcraft:latest",
"is_main": true,
"role": "frontend",
"vmid_offset": 0,
"depends_on": [],
"frontend_network": true,
"private_network": false,
"compose": {
"image": "junkerderprovinz/wordcraft:latest",
"container_name": "wordcraft",
"restart": "unless-stopped",
"shm_size": "1gb",
"ports": [
"3001:3001",
"3000:3000"
],
"volumes": [
"./appdata:/config",
"./storage:/storage"
],
"environment": {
"TZ": "Europe/Vienna",
"PUID": "1000",
"PGID": "1000",
"UMASK": "022"
}
}
}
],
"top_level": {},
"networking": {
"frontend": "selected-proxmox-bridge",
"private_required": false,
"private_creation": "automatic-create-if-missing",
"private_address_allocation": "automatic-static-address-per-service",
"service_discovery": "private-addresses-with-compose-service-host-aliases",
"dependency_external_access": "disabled-unless-service-publishes-ports",
"prompt_user_for_private_network": false
},
"storage": [
{
"id": "wordcraft-volume-0",
"service": "wordcraft",
"container_path": "/config",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
},
{
"id": "wordcraft-volume-1",
"service": "wordcraft",
"container_path": "/storage",
"mode": "managed-volume",
"user_selectable": false,
"backup": true,
"shared_with_other_lxc": false,
"source_path": null,
"source_path_prompt": null
}
],
"orchestration": {
"reserve_vmids_atomically": 1,
"start_order": [
"wordcraft"
],
"stop_order": [
"wordcraft"
],
"dependency_readiness": "compose-healthcheck-then-port-or-process-fallback",
"rollback_on_failure": "remove-new-rootfs-preserve-created-persistent-volumes"
},
"installer_inputs": {
"prompted": [
"stack_name",
"base_vmid",
"rootfs_storage",
"persistent_data_destinations",
"frontend_bridge",
"frontend_ipv4_mode"
],
"automatic": [
"dependent_vmids",
"private_bridge",
"private_subnet",
"private_service_addresses",
"compose_service_aliases",
"generated_secrets",
"dependency_start_and_stop_order"
],
"generated_secrets": []
}
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "https",
"port": 3001,
"path": "/",
"source": "https://github.com/junkerderprovinz/artcraft-apps"
}
],
"credentials": []
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 2048,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": false,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 30
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "import-from-oci-image"
},
"installer_profile": {
"tmpfs_mounts": [
{
"id": "compose-shm",
"container_path": "/dev/shm",
"default_size_mb": 1024,
"minimum_size_mb": 1,
"size_prompt": "Size of the /dev/shm shared memory in MB",
"mount_options": [
"rw",
"nosuid",
"nodev"
]
},
{
"id": "nginx-runtime",
"container_path": "/run/nginx",
"default_size_mb": 1,
"minimum_size_mb": 1,
"prompt_size": false,
"mount_options": [
"rw",
"nosuid",
"nodev",
"mode=0755"
]
}
],
"volume_preparations": [
{
"container_path": "/config",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
},
{
"container_path": "/storage",
"remove_lost_found": true,
"owner_strategy": "mapped-application-user"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 3000,
"path": "/",
"timeout_seconds": 240,
"request_timeout_seconds": 5,
"stability_seconds": 8,
"accept_any_status": true,
"verify_tls": true
},
"selkies": {
"base": "FROM ghcr.io/linuxserver/baseimage-selkies:ubunturesolute@sha256:6efa3fd775a552938d862f75975d34c418ad26d028ba2c952da58682cfe1cb47",
"dockerfile_url": "https://raw.githubusercontent.com/junkerderprovinz/artcraft-apps/32bee0dea9bdaf5310c693210bea0d732a129ae8/Dockerfile",
"dockerfile_sha256": "69ab1a81d1696d1bd143a6fa5a121c034ddfb3e83008969340e8cd2413547fe1",
"reviewed_on": "2026-11-04",
"documentation": "https://docs.linuxserver.io/images/docker-baseimage-selkies/",
"nvidia": "available-in-advanced-mode-with-compatible-host-driver-and-toolkit",
"validation": "Intel/AMD tested on a Radeon 680M: GL compositor and VAAPI encoding on the render node"
},
"device_requests": [],
"optional_devices": [],
"hardware_acceleration": {
"prompt": "Selkies desktop and streaming acceleration",
"default": "none",
"profiles": [
{
"id": "none",
"label": "No GPU (CPU)",
"device_requests": [],
"environment": [
{
"name": "AUTO_GPU",
"value": "false"
}
]
},
{
"id": "vaapi",
"label": "Intel/AMD (streaming rendering and encoding)",
"device_requests": [
{
"id": "selkies-render",
"kind": "character-device",
"path_prompt": "Intel/AMD render node",
"host_path_default": "/dev/dri/renderD128",
"container_path_strategy": "same-as-host",
"mode": "0660",
"deny_write": false,
"gid_strategy": "host-device-gid",
"drm_vendor_ids": [
"0x8086",
"0x1002"
]
}
],
"environment": [
{
"name": "PIXELFLUX_WAYLAND",
"value": "true"
},
{
"name": "AUTO_GPU",
"value": "false"
}
],
"environment_from_devices": {
"DRINODE": [
"selkies-render"
],
"DRI_NODE": [
"selkies-render"
],
"ATTACHED_DEVICES_PERMS": [
"selkies-render"
]
}
},
{
"id": "nvidia",
"label": "NVIDIA (Selkies rendering and NVENC)",
"device_requests": [
{
"id": "selkies-nvidia",
"kind": "nvidia-runtime",
"device_selection": "all-requested-by-compose"
}
],
"environment": [
{
"name": "AUTO_GPU",
"value": "true"
},
{
"name": "NVIDIA_VISIBLE_DEVICES",
"value": "all"
},
{
"name": "NVIDIA_DRIVER_CAPABILITIES",
"value": "compute,video,graphics,utility,display"
}
]
}
]
},
"gpu_validation": {
"device_inventory": "host-sysfs-and-stat",
"application_acceleration": "requires-workload-test",
"tone_mapping": "not-implied-by-device-access"
},
"device_permissions": {
"strategy": "linuxserver-native-init",
"service_user": "abc",
"environment": "ATTACHED_DEVICES_PERMS",
"paths": "all-resolved-selected-character-devices"
}
},
"adaptations": [
{
"id": "imported-compose-source",
"upstream_behavior": "The source definition deploys the complete Docker Compose application model.",
"native_lxc_behavior": "The source model is preserved and remains blocked until every service option has a reviewed native Proxmox mapping.",
"reason": "Catalog import must not imply runtime compatibility.",
"behavioral_impact": "No automatic installation before review.",
"validation": "pending-per-application"
},
{
"id": "rolling-latest-image",
"upstream_behavior": "A discovered Compose may pin a release tag or digest.",
"native_lxc_behavior": "ProxMenux selects the same image repository with the latest tag for catalog installations.",
"reason": "The automatic catalog intentionally offers rolling latest images; pinned versions belong to the future manual installer.",
"behavioral_impact": "The installed release can be newer than the discovered Compose revision.",
"validation": "pending-per-application"
},
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes selected container ports on the Docker host.",
"native_lxc_behavior": "A reviewed native application will listen on its original container ports at a dedicated LXC address.",
"reason": "A native LXC has its own address and does not require Docker port NAT.",
"behavioral_impact": "Published ports are metadata; ProxMenux URLs use the matching container target port.",
"validation": "pending-per-application"
},
{
"id": "compose-shm-size",
"upstream_behavior": "Compose sets the size of the container /dev/shm tmpfs.",
"native_lxc_behavior": "ProxMenux mounts a native LXC tmpfs at /dev/shm with the same requested capacity.",
"reason": "The OCI image runs directly as an LXC and therefore needs the equivalent Proxmox mount entry.",
"behavioral_impact": "None expected.",
"validation": "pending-per-application"
},
{
"id": "compose-command",
"upstream_behavior": "Compose replaces the image Cmd while retaining its Entrypoint.",
"native_lxc_behavior": "ProxMenux reads the official OCI Entrypoint and combines it with the Compose command as the native LXC init command.",
"reason": "Proxmox stores the effective OCI process as one entrypoint string.",
"behavioral_impact": "None expected.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-privileged-mode",
"upstream_behavior": "Compose selects whether the container runs in privileged mode.",
"native_lxc_behavior": "ProxMenux keeps the LXC unprivileged by default and exposes the broad Compose privilege request only as an explicit compatibility option.",
"reason": "A Compose privilege request is source metadata, not proof that the image technically requires a privileged LXC.",
"behavioral_impact": "A privileged LXC has weaker isolation from the Proxmox host.",
"validation": "native-equivalent"
},
{
"id": "compose-process-runtime",
"upstream_behavior": "Compose can replace Entrypoint, User and WorkingDir and request an init process or interactive terminal.",
"native_lxc_behavior": "ProxMenux applies the process overrides through native LXC init directives; lxc-init provides PID 1 supervision and the CT console provides terminal access.",
"reason": "The OCI process must start with the same identity, command and working directory without Docker.",
"behavioral_impact": "Compose stdin_open and tty become access through the Proxmox LXC console.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-healthcheck",
"upstream_behavior": "Docker periodically executes the declared container healthcheck.",
"native_lxc_behavior": "For a single-service LXC, ProxMenux translates HTTP localhost checks into a mandatory first-start service check.",
"reason": "Proxmox has no persistent Docker health state, while the installer still must detect a failed first boot.",
"behavioral_impact": "The check runs during installation rather than continuously after installation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-cpu-priority",
"upstream_behavior": "Docker cpu_shares sets a relative scheduling weight with 1024 as its neutral value.",
"native_lxc_behavior": "ProxMenux converts the relative weight to Proxmox cpuunits with 100 as its neutral value and lets the user review it.",
"reason": "Both settings express relative CPU priority on different scales.",
"behavioral_impact": "Rounding and Proxmox minimum limits can slightly change very low weights.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-resource-limits",
"upstream_behavior": "mem_limit sets the memory ceiling; ulimits sets process soft/hard resource limits.",
"native_lxc_behavior": "mem_limit supplies the editable Proxmox memory default, rounded up to MiB; ulimits maps to lxc.prlimit with -1 represented as unlimited.",
"reason": "Use native Proxmox memory and LXC prlimits, without a wrapper or changing the host kernel configuration.",
"behavioral_impact": "User-selected memory overrides Compose. Swap is a separate choice. Kernel restrictions still apply; nproc counts processes by real UID, not by container.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-identity",
"upstream_behavior": "Compose can set hostname, MAC address, extra hosts and attach a service to Docker networks.",
"native_lxc_behavior": "ProxMenux applies hostname and MAC to net0, writes additional host aliases into the LXC and uses its dedicated bridge connection for single-service networks.",
"reason": "A dedicated LXC has its own network namespace and does not need a Docker bridge per service.",
"behavioral_impact": "host-gateway resolves to the IPv4 address of the selected Proxmox bridge.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-network-mode",
"upstream_behavior": "Docker host mode removes Docker network isolation; bridge and default use a Docker-managed network.",
"native_lxc_behavior": "The OCI process uses the dedicated LXC network namespace directly, so host, bridge and default all listen on the LXC address without Docker NAT.",
"reason": "The LXC is the application host and already has its own address and port namespace.",
"behavioral_impact": "host means the LXC host, never the Proxmox host; this preserves Proxmox network isolation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-capabilities-and-sysctls",
"upstream_behavior": "Compose can add Linux capabilities and set kernel parameters in the container network namespace.",
"native_lxc_behavior": "ProxMenux validates requested capabilities against the native LXC capability set and writes namespaced network settings as lxc.sysctl directives.",
"reason": "A native OCI-LXC already starts with the namespaced capability set; lxc.cap.keep would incorrectly discard unrelated required capabilities.",
"behavioral_impact": "Host-global capabilities such as SYS_MODULE remain blocked until their host prerequisite is explicitly adapted.",
"validation": "not-requested-by-compose"
},
{
"id": "docker-engine-metadata",
"upstream_behavior": "Compose labels annotate Docker objects and the json-file logging driver rotates Docker-managed logs.",
"native_lxc_behavior": "Labels remain source metadata; Docker json-file settings are not applied because the OCI process runs directly under LXC.",
"reason": "There is no Docker object or Docker json-file log behind a native OCI-LXC application.",
"behavioral_impact": "Docker-only label consumers and Docker log-driver rotation do not exist in the native deployment.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-device-passthrough",
"upstream_behavior": "Compose passes host character devices or requests an NVIDIA runtime GPU.",
"native_lxc_behavior": "ProxMenux converts recognized device declarations to native Proxmox dev resources; NVIDIA profiles also inject compatible host driver libraries read-only.",
"reason": "Native OCI-LXC does not execute Docker device or NVIDIA runtime hooks.",
"behavioral_impact": "Hardware is exposed only after explicit user confirmation and host-path validation.",
"validation": "not-requested-by-compose"
},
{
"id": "compose-host-ipc",
"upstream_behavior": "ipc: host shares the Docker host IPC namespace, commonly to avoid Docker's small default shared-memory allocation.",
"native_lxc_behavior": "The application keeps the LXC IPC namespace and receives a configurable 1 GiB /dev/shm instead of sharing Proxmox host IPC.",
"reason": "Processes in a single native LXC already share one IPC namespace; retaining isolation is safer than exposing host IPC.",
"behavioral_impact": "The application cannot exchange IPC objects with processes on the Proxmox host.",
"validation": "not-requested-by-compose"
}
]
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"cap_add",
"command",
"container_name",
"cpu_shares",
"deploy",
"devices",
"entrypoint",
"environment",
"extra_hosts",
"group_add",
"healthcheck",
"hostname",
"image",
"init",
"ipc",
"labels",
"logging",
"mac_address",
"mem_limit",
"network_mode",
"networks",
"ports",
"privileged",
"restart",
"runtime",
"security_opt",
"shm_size",
"stdin_open",
"stop_grace_period",
"stop_signal",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Community native-desktop image contract reviewed against its published Compose and Dockerfile. Linux amd64 and arm64 manifests exist; runtime, storage and lifecycle tests remain pending per architecture."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "pending",
"service_health": "pending",
"restart_persistence": "pending",
"backup_restore": "pending",
"update_preserves_data": "pending"
},
"lifecycle": {
"update_strategy": "resolve-latest-image-then-apply-reviewed-native-lxc-update",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": null,
"image_created": null
},
"change_detection": "compare-compose-sha256-and-resolved-latest-image-digest",
"automatic_unattended_updates": false
}
}
+302
View File
@@ -0,0 +1,302 @@
{
"schema_version": "0.3.0",
"kind": "proxmenux.oci-template",
"id": "image-zwave-js-ui",
"status": "generated-unvalidated",
"catalog_ui": {
"title": {
"en_US": "Z-Wave JS UI"
},
"tagline": {
"en_US": "Manage a Z-Wave network from a web dashboard and WebSocket gateway."
},
"description": {
"en_US": "A self-hosted Z-Wave control panel and MQTT gateway. Its web interface can start without a Z-Wave controller; device control requires a compatible USB or serial controller and network security keys."
},
"category": "smarthome",
"author": "Z-Wave JS",
"developer": "Z-Wave JS",
"icon": "https://raw.githubusercontent.com/zwave-js/zwave-js-ui/c38e0d2cbbb826bf2bab2db596a3452e59ce0e8e/public/apple-touch-icon-180x180.png",
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "http",
"port": 8091,
"path": "/"
},
"website": "https://zwave-js.github.io/zwave-js-ui/",
"documentation": "https://zwave-js.github.io/zwave-js-ui/#/getting-started/docker",
"repository": "https://github.com/zwave-js/zwave-js-ui",
"tips": [
"The web UI can start without a Z-Wave controller. To control devices, pass through a compatible USB/serial controller and select its stable /dev/serial/by-id/... path in Settings → Z-Wave → Serial Port.",
"Configure and securely back up the S0/S2 network keys in Settings → Z-Wave before pairing security-enabled devices.",
"Port 3000 is the Z-Wave JS WebSocket server for integrations such as Home Assistant; it listens only after a Z-Wave client is configured. Upstream documents it as unauthenticated, so expose it only to trusted integrations and networks.",
"ProxMenux enables the web login and generates the initial admin password. Configure trusted HTTPS before remote access over an untrusted network."
],
"mini_changelog": [],
"display_version": "11.25.2",
"updated_at": "2026-11-02",
"category_label": "IoT & Smart Home"
},
"source": {
"provider": "Z-Wave JS",
"repository": "https://github.com/zwave-js/zwave-js-ui",
"default_branch": "master",
"revision": "c38e0d2cbbb826bf2bab2db596a3452e59ce0e8e",
"readme_raw_url": "https://raw.githubusercontent.com/zwave-js/zwave-js-ui/c38e0d2cbbb826bf2bab2db596a3452e59ce0e8e/README.md",
"image_repository_url": "https://hub.docker.com/r/zwavejs/zwave-js-ui",
"compose_sha256": "ed371d9e9805db5d2abd356b54e3ff5fdb677d637857313f6aac3f498f480f87",
"generated_at": "2026-11-02T20:10:33+00:00"
},
"container_contract": {
"service_name": "zwave-js-ui",
"container_name": "zwave-js-ui",
"image": {
"reference": "docker.io/zwavejs/zwave-js-ui:latest",
"registry": "docker.io",
"repository": "zwavejs/zwave-js-ui",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-selected-tag-to-architecture-digest-at-install"
},
"environment": [
{
"name": "SESSION_SECRET",
"example": "${GENERATED_SESSION_SECRET}",
"required": true,
"sensitive": true,
"source": "ProxMenux-generated; supported by upstream image"
},
{
"name": "DEFAULT_PASSWORD",
"example": "${GENERATED_ADMIN_PASSWORD}",
"prompt": "Initial Z-Wave JS UI admin password",
"required": true,
"sensitive": true,
"source": "Upstream image; generated by ProxMenux"
}
],
"volumes": [
{
"id": "zwave-config",
"container_path": "/usr/src/app/store",
"compose_source_example": "zwave-config",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 4
}
}
],
"ports": [
{
"container_port": 8091,
"published_example": 8091,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 3000,
"published_example": 3000,
"protocol": "tcp",
"required": false,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "always",
"stop_grace_period": null,
"original_compose": "version: '3.7'\nservices:\n zwave-js-ui:\n container_name: zwave-js-ui\n image: zwavejs/zwave-js-ui:latest\n restart: always\n tty: true\n stop_signal: SIGINT\n environment:\n SESSION_SECRET: ${GENERATED_SESSION_SECRET}\n DEFAULT_PASSWORD: ${GENERATED_ADMIN_PASSWORD}\n networks:\n - zwave\n devices:\n - /dev/serial/by-id/insert_stick_reference_here:/dev/zwave\n volumes:\n - zwave-config:/usr/src/app/store\n ports:\n - '8091:8091'\n - '3000:3000'\nnetworks:\n zwave:\nvolumes:\n zwave-config:\n name: zwave-config\n"
},
"first_run": {
"endpoints": [
{
"label": "Z-Wave JS UI",
"scheme": "http",
"port": 8091,
"path": "/",
"source": "official-docker-documentation"
}
],
"credentials": [
{
"label": "Z-Wave JS UI admin login",
"type": "configured-or-installer-generated",
"username": "admin",
"password": null,
"password_environment": "DEFAULT_PASSWORD",
"change_required": false,
"source": "Upstream DEFAULT_PASSWORD, generated by ProxMenux",
"retrieval": null
}
]
},
"proxmox": {
"runtime": "native-oci-lxc",
"technology_status": "proxmox-technology-preview",
"defaults": {
"unprivileged": true,
"ostype": "auto-from-image",
"cores": 2,
"memory_mb": 1024,
"swap_mb": 512,
"rootfs_size_gb": 8,
"rootfs_storage": "local-lvm",
"volume_storage": "local-lvm",
"template_storage": "local",
"bridge": "vmbr0",
"ipv4": "dhcp",
"firewall": true,
"host_managed_network": true,
"onboot": true,
"features": [
"nesting=1"
],
"shutdown_timeout_seconds": 60
},
"image_metadata_policy": {
"entrypoint": "import-from-oci-image",
"cmd": "import-from-oci-image",
"environment": "import-image-env-then-apply-compose-overrides",
"user": "import-from-oci-image",
"working_dir": "import-from-oci-image",
"stop_signal": "apply-compose-override"
},
"adaptations": [
{
"id": "dedicated-lxc-network",
"upstream_behavior": "Docker publishes ports on a Docker host address and attaches the service to its Compose network.",
"native_lxc_behavior": "The OCI process listens on the dedicated LXC address; ProxMenux maps the single-service network to the LXC network namespace.",
"reason": "A one-service native OCI LXC has its own network namespace and address.",
"behavioral_impact": "Use the LXC address directly; no Docker port NAT or separate bridge is created.",
"validation": "pending-per-application"
},
{
"id": "generated-login-and-session-secret",
"upstream_behavior": "The image defaults to user admin and password zwave; web authentication is disabled by default, and the Compose example uses a sample session secret.",
"native_lxc_behavior": "ProxMenux generates a unique initial admin password and session secret, and seeds gateway.authEnabled=true before first boot.",
"reason": "Avoid shipping a shared password, sample session key or unauthenticated web UI.",
"behavioral_impact": "The installer must display the generated admin password; change it after first login.",
"validation": "pending-per-application"
},
{
"id": "stop-signal",
"upstream_behavior": "Compose requests SIGINT when stopping the container.",
"native_lxc_behavior": "ProxMenux uses the same signal for the OCI process shutdown lifecycle.",
"reason": "Preserve the upstream graceful-shutdown behavior.",
"behavioral_impact": "None expected.",
"validation": "pending-per-application"
}
],
"installer_profile": {
"generated_sensitive_environment": {
"SESSION_SECRET": {
"strategy": "token-hex",
"bytes": 32,
"prompt": false
},
"DEFAULT_PASSWORD": {
"strategy": "token-hex",
"bytes": 20,
"prompt": true
}
},
"generated_files": [
{
"container_path": "/usr/src/app/store/settings.json",
"mode": "0600",
"owner": "mapped-root",
"content": "{\"gateway\":{\"authEnabled\":true}}\n",
"only_if_missing": true
}
],
"volume_preparations": [
{
"container_path": "/usr/src/app/store",
"remove_lost_found": true,
"owner_strategy": "mapped-root",
"only_when_mount_type": "managed-volume"
}
],
"optional_devices": [
{
"id": "zwave-serial-controller",
"kind": "character-device",
"purpose": "serial",
"enable_prompt": "Pass through a Z-Wave USB or serial controller",
"enabled_default": false,
"required_by_compose": false,
"path_prompt": "Controller path on the Proxmox host; prefer /dev/serial/by-id/...",
"host_path_default": "/dev/serial/by-id/insert_stick_reference_here",
"container_path_strategy": "same-as-host",
"mode": "preserve-host",
"deny_write": false,
"gid_strategy": "host-device-gid"
}
],
"startup_healthcheck": {
"scheme": "http",
"port": 8091,
"path": "/",
"timeout_seconds": 180,
"request_timeout_seconds": 10,
"stability_seconds": 4,
"verify_tls": false
}
}
},
"compatibility": {
"automatic_install_candidate": true,
"validated": false,
"supported_compose_keys": [
"container_name",
"devices",
"environment",
"image",
"networks",
"ports",
"restart",
"stop_signal",
"tty",
"volumes"
],
"untranslated_blockers": [],
"policy": "The single-image recipe has passed installation, UI/login, restart, backup and recovery, modification, and engine checks. Host-bind storage has not been checked. Radio control remains untested because no compatible Z-Wave coordinator was attached during the lab test."
},
"validation": {
"schema": "passed-static-validation",
"image_resolution": "passed-skopeo-download-and-layer-verification",
"clean_install": "passed-default-install-and-health-check",
"advanced_install": "pending-custom-install-summary-validation",
"web_response": "passed-ui-and-generated-login",
"credentials": "passed-generated-login-before-and-after-restore",
"restart_persistence": "passed-restart-with-store-preserved",
"backup_restore": "passed-proxmox-backup-and-manager-recover-new-vmid",
"update_preserves_data": "no-update-available-at-check",
"modification": "passed-cpu-ram-up-down-without-recreation",
"managed_volume": "passed-store-volume-and-recovery",
"host_bind": "pending",
"hardware_radio": "not-tested-no-z-wave-coordinator-on-host",
"removal": "passed-remove-original-and-restored-ct-and-local-backup-cleanup"
},
"lifecycle": {
"update_strategy": "replace-rootfs-from-new-oci-image-preserve-managed-volumes",
"registry_state": {
"resolved_architecture": null,
"resolved_digest": null,
"image_version_label": "11.25.2",
"image_created": null
},
"change_detection": "compare-resolved-architecture-digest",
"automatic_unattended_updates": false
}
}
+5 -1
View File
@@ -432,6 +432,10 @@
"metabase": "monitoring",
"kopia": "backup",
"restic-rest-server": "backup",
"netalertx": "monitoring"
"netalertx": "monitoring",
"kitchenowl": "productivity",
"unbound": "adblock",
"spoolman": "tools",
"zwave-js-ui": "smarthome"
}
}
+4
View File
@@ -0,0 +1,4 @@
{
"engine_api": 1,
"description": "Increment engine_api when catalog recipes require runtime capabilities unavailable in earlier catalog-refresh clients."
}
@@ -323,6 +323,9 @@
"AceStream HTTP Proxy has no web interface: a media player opens its streams.",
"HLS stream: port 6878, path /ace/manifest.m3u8?id= followed by the channel ID.",
"MPEG-TS stream: port 6878, path /ace/getstream?id= followed by the channel ID."
],
"non_persistent_image_volumes": [
"/home/appuser/.ACEStream"
]
}
},

Some files were not shown because too many files have changed in this diff Show More