Ctrl K
ComunidadGuías…

README.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# aMule React UI

A reactive, browser-based operations console for [aMule](https://github.com/amule-org/amule). It is designed to be served by aMule's built-in `amuleapi`, using the REST API and SSE events on the same origin.

The application provides authenticated live status, download and upload activity, searches, server/network controls, categories, and confirmation dialogs for consequential actions. It stores no password or token in browser storage; authentication uses the API's HttpOnly cookie.

## Prerequisites

- A current [aMule source build](https://github.com/amule-org/amule#building-from-source) with `amuled` and `amuleapi` enabled.
- Node.js and pnpm.
- An `amuleapi` admin password configured on the target aMule instance.

## Runtime architecture

There is no custom backend or separate production Node server. The running stack is:

```text
browser → amuleapi (static files, REST, SSE) ← amuled (aMule core)
```

`amuled` starts the native `amuleapi` process. `amuleapi` serves this project's built `dist/` directory at `/`, while its own handlers serve `/api/v1/*` and `/api/v1/events`. This same-origin arrangement keeps the HttpOnly session cookie, REST requests, and live SSE updates together.

The legacy `amuleweb` service is independent of this SPA and is not required.
Enable it only when an operator intentionally wants a temporary fallback.

## Container deployment

This repository also contains a source-built, multi-platform container image
and a single-service Compose deployment. It runs `amuled` with its native
`amuleapi` child and serves the bundled SPA without a Node.js runtime. See
[docs/CONTAINER.md](docs/CONTAINER.md) for migration, backup, password
rotation, and reverse-proxy/TLS guidance.

### Recommended Docker Compose configuration

Use the supplied Compose file unchanged for a new installation. It keeps
configuration, completed downloads, and temporary downloads in three separate
named volumes; it exposes only the UI/API and aMule's TCP/UDP P2P ports. The
EC and legacy `amuleweb` ports stay private to the container.

Create a local Compose environment file and the first-boot admin-password
secret:

```bash
cp docker.env.example docker.env
mkdir -p secrets
chmod 700 secrets
umask 077
printf '%s' 'choose-a-long-unique-password' > secrets/amule-admin-password
```

Set the values below in `docker.env`. The template is deliberately safe to
copy: it is ignored by Git, contains no password, and uses local source-build
defaults.

```dotenv
# Ownership used for /config, /incoming, and /temp inside the container.
# Use: id -u ; id -g
PUID=1000
PGID=1000

# Host ports. Change only if these host ports are unavailable or restricted.
AMULE_UI_PORT=4713
AMULE_TCP_PORT=4662
AMULE_UDP_PORT=4672

# Build locally from this checkout. For a published deployment, pin both
# values to an immutable image and exact combined version tag.
AMULE_IMAGE=amule-console
AMULE_IMAGE_VERSION=local

# A file path used as a Docker secret source; never put the password here.
AMULE_ADMIN_PASSWORD_FILE=./secrets/amule-admin-password
```

For a published image, replace the two image settings with values such as:

```dotenv
AMULE_IMAGE=alvarogl91/amule-console
AMULE_IMAGE_VERSION=0.2.0-amule-3.0.1
```

Always use an exact image tag for upgrades and rollback; do not deploy
`latest`. Start a source build or an already-published image respectively:

```bash
# From this checkout: build the image, validate the resolved configuration,
# and start it.
docker compose --env-file docker.env config
docker compose --env-file docker.env up -d --build

# With an exact published image configured in docker.env:
docker compose --env-file docker.env pull
docker compose --env-file docker.env up -d
```

Check startup with `docker compose --env-file docker.env ps`, then open
`http://<docker-host>:<AMULE_UI_PORT>` and sign in with the password stored in
the secret file. The secret is consumed only to initialize the credential
record; changing that file later does not change the admin password.

The UI/API port grants administrative access. Limit TCP `4713` to trusted
operator networks using the host or network firewall. For HighID, allow and
port-forward both configured P2P ports (TCP `4662` and UDP `4672` by default).
Use a TLS reverse proxy for access beyond a trusted LAN, and proxy `/`,
`/api/v1/*`, and `/api/v1/events` together so login and live updates remain
same-origin.

## Run the stack

Build the UI and point `amuleapi` at its absolute output directory:

```bash
pnpm install --frozen-lockfile
pnpm build
```

In `amuleapi.conf`, configure `StaticRoot` with the absolute path to `dist/`. Ensure the `[AmuleApi]` section in the aMule configuration enables the API and points `Path` at the native `amuleapi` executable. Then start the aMule services using the unit names installed on the host, for example:

```bash
sudo systemctl enable --now amuled.service
sudo systemctl status amuled.service
```

Do not stop `amuled` when you only want to run the UI differently: it owns the core and its `amuleapi` child. To use the development UI, leave that stack running and start Vite separately.

For a complete first install, upgrade, rollback, and secure-network guide, see
[docs/DEPLOYMENT.md](docs/DEPLOYMENT.md). Generic non-secret configuration
templates are available at [docs/amule.conf.example](docs/amule.conf.example)
and [docs/amuleapi.conf.example](docs/amuleapi.conf.example).

## Local development

```bash
cd /opt/amule/web
pnpm install
cp .env.example .env
pnpm dev
```

Vite prints its local URL when it starts. It proxies `/api` and `/flags` to `VITE_DEV_API_ORIGIN` (by default `http://127.0.0.1:4713`); set that value to the reachable `amuleapi` listener for the development host. Sign in with the `amuleapi` admin password; do not add it to `.env`.

## Configuration

Copy `.env.example` to `.env` to override local values. `.env` is intentionally ignored by Git.

| Variable              | Default                 | Purpose                                                                 |
| --------------------- | ----------------------- | ----------------------------------------------------------------------- |
| `VITE_API_BASE`       | `/api/v1`               | Browser REST API base path. Keep relative when aMule serves the bundle. |
| `VITE_EVENTS_URL`     | `/api/v1/events`        | Browser SSE endpoint.                                                   |
| `VITE_DEV_API_ORIGIN` | `http://127.0.0.1:4713` | Vite development proxy target.                                          |

For the deployed SPA, keep browser paths relative and configure `amuleapi` to serve the generated `dist/` directory as its static root. This keeps the UI, cookie, REST API, and SSE stream on one origin.

## Build and deploy

```bash
pnpm build
```

The production bundle is static; Vite's proxy only applies to `pnpm dev`. Rebuild after UI changes. If the configured static-root path changes, restart `amuled` so it starts `amuleapi` with the new configuration.

For LAN access, restrict the API listener and firewall rules to the intended network. Put TLS in front of `amuleapi` before exposing it beyond a trusted local network; the deployment guide explains why the static UI and same-origin API must be secured together.

### Repeatable install and rollback

The deployment helper stages a built bundle, retains the previous static root,
and does not restart services. Preview its work first:

```bash
scripts/install-static-ui.sh --dry-run --static-root /absolute/path/to/static-root
```

To install, optionally pass the explicit aMule configuration files to patch
only their API startup/server settings. The helper never writes credentials or
replaces either complete configuration file:

```bash
scripts/install-static-ui.sh --static-root /absolute/path/to/static-root \
  --amule-conf /absolute/path/to/amule.conf \
  --amuleapi-conf /absolute/path/to/amuleapi.conf
```

It prints a rollback directory. Restore it with
`scripts/install-static-ui.sh --rollback /path/to/rollback-directory`.

### Create a release archive

After a production build, create an operator-ready archive and SHA-256
checksum with:

```bash
pnpm build
scripts/create-release-archive.sh
```

The output in `release/` contains the static bundle, deployment helper,
generic templates, documentation, and a release manifest. It deliberately
excludes `.env`, credentials, runtime configuration, and dependencies. Verify
the downloaded archive with `sha256sum --check release/*.sha256` before use.

Release-archive users can follow the archive-only install path in
[docs/DEPLOYMENT.md](docs/DEPLOYMENT.md#use-a-release-archive); Node.js and
pnpm are needed only when building from a checkout.

### Publish a GitHub Release

The `Release` workflow is manual-only. Stable releases run only from `main`.
Select the semantic version component to increment; after the quality,
deployment, browser, and archive checks pass, it commits the new version,
creates tag `v<version>`, and attaches the archive plus checksum to a generated
GitHub Release. It does not deploy to any aMule host.

For an early release from another branch, select **Create a beta prerelease**.
The workflow appends `-beta` to the calculated next version, pushes the release
commit to that branch, and creates a GitHub prerelease. A beta does not alter
`main` or become `latest`.

### Docker Hub releases

UI versions use independent semantic versioning. The bundled aMule source is
recorded separately in [docker/amule-version.env](docker/amule-version.env).
Each published image has an immutable combined tag such as
`0.2.0-amule-3.0.1`; a development aMule commit is labelled honestly, for
example `0.2.0-amule-git-d8d5720b`. `latest` is a moving alias for the newest
stable image and is unsuitable for deployments.

To enable publishing, create the Docker Hub repository and configure these
GitHub Actions values:

- Repository variable `DOCKERHUB_IMAGE` — image name without a registry, for
  example `alvarogl91/amule-console`.
- Repository secrets `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN` — a Docker Hub
  username and access token with permission to push that repository.

Selecting **Publish the multi-platform image to Docker Hub** runs the separate
**Docker release** workflow after the GitHub Release. It publishes
`linux/amd64` and `linux/arm64`, with provenance and an SBOM. The workflow
derives the exact combined image tag automatically from the new UI version and
the pinned aMule version; operators never enter an image tag manually.

Before building, Docker release rejects an existing exact image tag. It also
rejects a beta image if the corresponding final image tag already exists. Only
stable images update `latest`; beta images use their exact `-beta` tag only.

## License

This project is licensed under the [MIT License](LICENSE).

## Quality checks

```bash
pnpm exec prettier --write . --ignore-unknown
pnpm format:check
pnpm lint
pnpm test
pnpm test:deployment
pnpm test:e2e
pnpm build
pnpm test:release
```

## Continuous integration

GitHub Actions runs formatting, ESLint, unit/integration tests, deployment and
release-package checks, and a separate browser-test workflow for pull requests
and pushes to `main`. The manual-only Release workflow publishes verified
artifacts but never deploys to an aMule host. See
[CONTRIBUTING.md](CONTRIBUTING.md) for the contribution and review workflow
and [SECURITY.md](SECURITY.md) for responsible disclosure guidance.