Files
ProxMenux/oci/catalog/apps/amule.json
T
MacRimiandClaude Opus 5 bcabcb618c feat(oci): run official container images as native LXC containers
Adds the OCI manager: an engine that turns a Docker Compose file into an
LXC definition, a catalog of 365 applications drawn from LinuxServer.io
and other container image sources, and a per-instance registry recording
what each container was built from. Reachable from the main menu.

Catalog text is translated like every other string in the project: the
taglines go through translate() and land in lang/*.json, so the entries
read in all eight languages instead of only English.

Translation cache builder:
- a failed translation leaves the key absent rather than writing English,
  which previously made the string count as translated forever
- a result identical to a 3+ word source is rejected, catching a provider
  that silently returns the text it was given
- strings that are nothing but glossary terms keep their source spelling
  instead of being discarded as failures
- no backoff between attempts when the provider is deterministic
- application names are protected so "HAOS One" survives translation
- argos joins the provider list, and the workflow reads the OCI sources

Audit & Report:
- findings that moved in the wrong direction between runs are reported
  alongside the ones that improved
- an accepted risk can carry a review date and is flagged when it falls due
- backup checks explain in plain language what they looked at and what to
  do next

Monitor:
- disks can be excluded from periodic reads, and an idle disk says so
  instead of showing a stale temperature
- per-disk identity survives a controller or enclosure change
- scheduled Borg backups resolve their SSH key from the repository entry
- PVE upgrades log the package list and the resulting dpkg changes

The web build no longer copies scripts/ into public/: the documentation
links to GitHub, so nothing read that folder.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 18:24:59 +02:00

466 lines
20 KiB
JSON

{
"schema_version": "0.4.0",
"kind": "proxmenux.oci-template",
"id": "image-amule",
"status": "laboratory-validated",
"catalog_ui": {
"title": {
"en_US": "aMule"
},
"tagline": {
"en_US": "aMule is a multi-platform client for the ED2K file sharing network and based on the windows client eMule. aMule started in August 2003, as a fork of xMule, which is a fork of lMule."
},
"description": {
"en_US": "aMule is a multi-platform client for the ED2K file sharing network and based on the windows client eMule. aMule started in August 2003, as a fork of xMule, which is a fork of lMule."
},
"category": "downloads",
"category_label": "Files & Downloads",
"author": "ngosang",
"developer": "ngosang",
"icon": null,
"thumbnail": null,
"screenshots": [],
"architectures": [
"amd64",
"arm64"
],
"launch": {
"scheme": "http",
"port": 4711,
"path": "/"
},
"website": "https://github.com/amule-org/amule",
"documentation": "https://github.com/ngosang/docker-amule",
"repository": "https://github.com/ngosang/docker-amule",
"tips": [
"Configuration stays on a private managed Proxmox volume with backup enabled. Downloads may use a managed volume or an explicitly selected host directory.",
"Completed files use /downloads/incoming; incomplete files use /downloads/temp. Keeping both under one mount preserves moves on the same filesystem.",
"GUI_PWD and WEBUI_PWD are required upstream passwords, not built-in credentials. The web login requests no username.",
"Optional MOD variables are upstream features, not LinuxServer mods. They are not enabled automatically by this template.",
"Do not expose HTTP port 4711 or External Connections port 4712 directly to the Internet. Router port forwarding is a separate user action; this installer does not change the router."
],
"mini_changelog": [],
"display_version": null,
"updated_at": "2026-09-18"
},
"source": {
"provider": "ngosang",
"repository": "https://github.com/ngosang/docker-amule",
"default_branch": "master",
"revision": "356d94c46b8e1d02eac35ca23875d15fc01864d8",
"readme_raw_url": "https://raw.githubusercontent.com/ngosang/docker-amule/356d94c46b8e1d02eac35ca23875d15fc01864d8/README.md",
"readme_pushed_at": "2026-09-18",
"compose_sha256": "c491822b91bc3e0e8af1e63f3e3cf5f1659185688afc7d9510034924662a51e6",
"generated_at": "2026-09-18T20:05:19+00:00"
},
"container_contract": {
"service_name": "amule",
"container_name": "amule",
"image": {
"reference": "ngosang/amule:latest",
"registry": "docker.io",
"repository": "ngosang/amule",
"tag": "latest",
"digest": null,
"pull_policy": "resolve-selected-tag-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": "TZ",
"example": "Europe/London",
"required": true,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "GUI_PWD",
"example": "",
"required": true,
"sensitive": true,
"source": "upstream-compose",
"prompt": "Password for aMule external connections (remote client)"
},
{
"name": "WEBUI_PWD",
"example": "",
"required": true,
"sensitive": true,
"source": "upstream-compose",
"prompt": "Password to access the aMule web interface"
},
{
"name": "MOD_AUTO_RESTART_ENABLED",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "MOD_AUTO_RESTART_CRON",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "MOD_AUTO_SHARE_ENABLED",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-compose"
},
{
"name": "MOD_AUTO_SHARE_DIRECTORIES",
"example": "",
"required": false,
"sensitive": false,
"source": "upstream-compose"
}
],
"volumes": [
{
"id": "volume-0",
"container_path": "/home/amule/.aMule",
"compose_source_example": "<fill_amule_configuration_path>",
"read_only": false,
"required": true,
"installation_choice": [
"managed-volume"
],
"default": "managed-volume",
"managed_volume": {
"backup": true,
"default_size_gb": 8
}
},
{
"id": "volume-1",
"container_path": "/downloads",
"compose_source_example": "<fill_amule_downloads_path>",
"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": 4711,
"published_example": 4711,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 4712,
"published_example": 4712,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 4662,
"published_example": 4662,
"protocol": "tcp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 4665,
"published_example": 4665,
"protocol": "udp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
},
{
"container_port": 4672,
"published_example": 4672,
"protocol": "udp",
"required": true,
"proxmox_behavior": "listener-on-dedicated-lxc-address-no-nat"
}
],
"related_services": [],
"restart": "unless-stopped",
"stop_grace_period": null,
"original_compose": "---\nservices:\n amule:\n image: ngosang/amule\n container_name: amule\n environment:\n - PUID=1000\n - PGID=1000\n - TZ=Europe/London\n - GUI_PWD=<fill_password>\n - WEBUI_PWD=<fill_password>\n - MOD_AUTO_RESTART_ENABLED=true\n - MOD_AUTO_RESTART_CRON=0 6 * * *\n - MOD_AUTO_SHARE_ENABLED=false\n - MOD_AUTO_SHARE_DIRECTORIES=/downloads/incoming;/my_movies\n ports:\n - \"4711:4711\" # Web UI and REST API (amuleapi)\n - \"4712:4712\" # External connections (amuleapi, amulegui, amulecmd)\n - \"4662:4662\" # ED2K client-to-client TCP (required for High ID)\n - \"4665:4665/udp\" # ED2K server UDP (global searches, TCP port +3)\n - \"4672:4672/udp\" # Extended eMule protocol and Kademlia UDP\n volumes:\n - <fill_amule_configuration_path>:/home/amule/.aMule\n - <fill_amule_downloads_path>:/downloads\n restart: unless-stopped\n"
},
"first_run": {
"endpoints": [
{
"label": "Web UI",
"scheme": "http",
"port": 4711,
"path": "/",
"source": "upstream-documentation"
}
],
"credentials": [
{
"label": "aMule WebUI (password only, no username)",
"type": "configured-or-installer-generated",
"username": "Not required (password only)",
"password": null,
"password_environment": "WEBUI_PWD",
"change_required": false,
"source": "https://github.com/ngosang/docker-amule"
}
]
},
"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": "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": "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": {
"network": {
"compose_mode": "bridge"
},
"device_requests": [],
"startup_healthcheck": {
"scheme": "http",
"port": 4711,
"path": "/",
"timeout_seconds": 600,
"request_timeout_seconds": 10,
"stability_seconds": 4,
"verify_tls": false
}
}
},
"compatibility": {
"automatic_install_candidate": true,
"validated": true,
"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",
"sysctls",
"tty",
"ulimits",
"user",
"volumes",
"working_dir"
],
"untranslated_blockers": [],
"policy": "Reviewed official single-image mapping. Validated on amd64: clean install, authenticated web login, same-digest recreation and interrupted-candidate recovery with managed configuration and downloads. Cross-release migration, arm64 runtime and P2P downloads not tested."
},
"validation": {
"schema": "passed-at-generation",
"clean_install": "passed-amd64",
"service_health": "passed-amd64",
"authenticated_login": "passed-after-recovery-amd64",
"restart_persistence": "passed-through-recreation-amd64",
"backup_restore": "passed-managed-configuration-and-downloads-amd64",
"update_preserves_data": "passed-same-digest-recreation-amd64",
"cross_release_upgrade": "not-tested",
"p2p_download": "not-tested",
"evidence": "docs/lab/new-images-validation-20260918.json"
},
"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-resolved-architecture-digest",
"automatic_unattended_updates": false
}
}