Ctrl K
ComunidadGuías…

INSTALL.md

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

Archivo original ↗Preguntar a KiBot
# Running Milvago Community locally

## Install Milvago Community

On a Linux server with Bash, `curl`, Internet access and `root` or `sudo` privileges, run:

```bash
curl -fsSL https://get.milvago.ai | bash
```

For shared access, enter your full public URL at the `Milvago public URL [http://localhost:4020]:` prompt, for example `https://milvago.example.com`.
The `http://` or `https://` prefix is required; no path, query string or fragment is allowed.
An invalid URL stops the installer. Public mode binds the gateway to the host network on port `4020`; prepare DNS and an HTTPS reverse proxy to the server private IP before sharing the console.

Press Enter for local access. It uses `http://localhost:4020` and binds port `4020` only to `127.0.0.1`. An explicit `http://localhost:4020` or `http://127.0.0.1:4020` selects the same local mode. Local mode opens no additional host ports; the application and identity service remain internal. Open it in a browser on the server, or from another computer create an SSH tunnel first:

```bash
ssh -L 4020:127.0.0.1:4020 user@server
```

Then open `http://localhost:4020` on that computer. The prompt reads from the terminal even when piped into Bash. Without a controlling terminal and no supplied URL, the installer selects local mode.

To provide the URL directly and skip that question:

```bash
curl -fsSL https://get.milvago.ai | MILVAGO_PUBLIC_URL=https://milvago.example.com bash
```

Replace the example address with your own. This does not suppress any required `sudo` password prompt.
For a non-interactive local installation, set an empty value instead:

```bash
curl -fsSL https://get.milvago.ai | MILVAGO_PUBLIC_URL='' bash
```

No GitHub account or token is needed.
The short URL serves the latest published installer, which pins an exact image version and digest.

For public access, the installer does not create DNS records or issue your HTTPS certificate. Keep the server clock synchronized.
At completion, open the displayed URL, retrieve `MILVAGO_SETUP_TOKEN` from the `.env` path printed by the
installer, and complete the browser wizard to create the administrator. Keep this file private.

With installer 1.0.3 and later, an existing Docker command is checked before installing prerequisites or Docker packages. Under WSL, a Docker command found under `/mnt/` is rejected with instructions to enable **Docker Desktop > Settings > Resources > WSL integration** for that distribution. If `docker --version` fails, repair or remove the existing command before retrying. A working Linux Docker command is preserved; missing Docker or Compose can still be installed on supported distributions.

## Install a specific version

The repository copy of `install-private.sh` is a non-executable template. Download the installer,
its checksum file, and its immutable release description anonymously from the public `v1.1.1`
release:

```bash
mkdir milvago-install && cd milvago-install
release_url=https://github.com/Milvago-AI/milvago-server/releases/download/v1.1.1
curl -fLO "$release_url/install-private.sh"
curl -fLO "$release_url/SHA256SUMS"
curl -fLO "$release_url/release.json"
sha256sum --check SHA256SUMS
bash install-private.sh
```

`wget` can replace each `curl -fLO` command. No GitHub CLI login, GitHub token, or registry
credential is required. The server image is pulled anonymously from
`ghcr.io/milvago-ai/milvago-server:1.1.1` using the exact digest recorded in `release.json`.

The release pipeline generates `install-private.sh`, `SHA256SUMS`, and `release.json` together.
They bind the server version, full commit, image digest, and cosign signature verification to
that release. `MILVAGO_VERSION`, when set, must equal `1.1.1`; the installer rejects a different
or floating value. It never uses `latest`.

On a first standalone installation only, the installer obtains the public server source pinned to
the release commit and places it in `$HOME/milvago-community`. Set `MILVAGO_DIR` to another absolute
path if needed. It does not synchronize an existing checkout. Every run preserves local
configuration and the database while replacing the application container only when the pinned
image changes.

Before detecting a host address or beginning installation, the script checks the core utilities,
`tar`, `gzip`, a CA certificate bundle, and either `curl` or `wget`; it keeps an existing `wget`.
When neither `ip` nor `hostname` is available and `MILVAGO_HOST_IP` is unset, it also needs the IP
utility. On Debian and Ubuntu, missing prerequisites are installed with `apt-get`; on RPM-family
systems, the script uses `dnf` or `yum`. It resolves an exact candidate version for every missing
package before the transaction, installs only those packages without a system-wide upgrade, and
verifies the tools after installation. Root or `sudo` is required only when packages are missing.

The script installs missing Docker Engine and incompatible or missing Compose packages through
Docker's official package repositories only on supported Ubuntu, Debian, Fedora, RHEL 8–10, and
their supported derivatives. Existing working Docker installations are left in place. Other Linux
distributions can run the installer when Docker, Compose, and the prerequisites already exist. If
missing prerequisites require an unsupported package manager, the installer stops with a clear
error; it does not claim support for every distribution or version.

The base image contains the server and console only. The installer also downloads the pinned
Community `0.7.44` Windows and Linux agent bundle anonymously from its public release, verifies its
SHA-256, Ed25519 signatures, and manifest expiration, then mounts the verified files read-only so the console can provide
agent downloads. Version `0.7.44` is shared by the Community agent and browser extension.
The console delivers one Windows ZIP containing the immutable MSI, its matching script, an
organization provisioning JSON and an installation `README.md`. The Windows MSI has no
Authenticode publisher signature yet. The base image does not host a browser extension. Before a
first installation, the script asks for the public HTTP or HTTPS origin where users will open
Milvago, for example `https://console.example.test`. It never guesses a LAN address. The value must
be an origin only: no path, query, or fragment. For unattended public installation, set
`MILVAGO_PUBLIC_URL=https://console.example.test`; this skips the prompt. Leaving the prompt blank,
setting `MILVAGO_PUBLIC_URL=''`, or explicitly choosing `http://localhost:4020` or
`http://127.0.0.1:4020` uses local mode: Caddy binds only `127.0.0.1:4020` and the application URL
is `http://localhost:4020`. With no controlling terminal and no URL, local mode is selected. Public
mode binds Caddy to the host network on port 4020. The script prints the selected URL and the path to
the owner-readable `.env` file at the end.
Caddy forwards the public realm, resources and JavaScript assets to Keycloak. It returns 404 for
`/admin` and `/realms/master`; the Keycloak administrator API is reachable only from the internal
container network. The application and Keycloak have no direct host port in this installation.
Public mode needs only TCP port 4020 through the host firewall. Local mode exposes only
`127.0.0.1:4020`; use a browser on the server or `ssh -L 4020:127.0.0.1:4020 user@server` from
another computer. No secret value is printed. Database and Mailpit ports remain on loopback. The installer waits for `/readyz` through the published Caddy
port before reporting success; if the gateway fails, it prints its recent logs.

HTTP on a LAN is intended for trusted test networks; use an HTTPS reverse proxy or gateway for
broader access. The front proxy must preserve the Host header and send `X-Forwarded-Proto: https`.
The installed profile runs Keycloak with `start` in production mode behind that proxy.

Mailpit is disabled by default in the installed profile. It is available only through the
`development-mail` profile when deliberately needed for development and is not a production mail
service. Configure and send a test message through a real SMTP server during setup or later in
**Administration > Settings** before depending on member invitations or password-reset email. Those
messages are unavailable without SMTP. On every installer run, an already-running development
Mailpit service is stopped without deleting its captured messages. The installer removes only the
factory SMTP configuration (`mail:1025`, `no-reply@milvago.test`) and preserves operator-configured
SMTP settings.

The gateway and development-mail containers run as `65532:65532` with all Linux capabilities
dropped; the gateway adds only the capability required to bind its port. Use a dedicated
sudo-capable installation account that is not in the `docker` group, and keep volume ownership
specific to its service. This installation does not promise rootless Docker. Docker `userns-remap`
is not enabled or qualified: test host-network readiness probing and volume ownership before
enabling it.

## Updating an existing installation

Back up the existing database and `.env`, then rerun the public installer with the Linux
account used for the original installation:

```bash
curl -fsSL https://get.milvago.ai | bash
```

The default directory is `~/milvago-community`. For an installation in a custom directory,
use its existing absolute path:

```bash
curl -fsSL https://get.milvago.ai | MILVAGO_DIR='/absolute/path/to/milvago-community' bash
```

Leaving `MILVAGO_PUBLIC_URL` unset and pressing Enter (or running without a
terminal) reuses the URL already confirmed in the database. The new release's verified application
image replaces the previous application image; the existing checkout, base Compose file, secrets
and database volume are preserved. A database container removed by `docker compose down` is
recreated against the configured volume before the stored URL is read. Generated installer Compose
and gateway files are regenerated.
An explicit `MILVAGO_PUBLIC_URL=''` still requests localhost. If a supplied or entered URL,
including a switch between local and public mode, conflicts with the confirmed URL, the installer
stops rather than silently changing it. An unreadable or incomplete existing database stops the
update; restore it rather than substituting a new URL. Change the URL in **Administration > Settings**;
this updates the console redirect and Keycloak through its private API. Already enrolled agents
retain their prior URL and must be re-enrolled to move.

If the final setup-wizard step returns `502` after an installation made with an earlier installer, rerun the current installer with the same public URL. It repairs the four required Keycloak service-account roles: `manage-clients`, `view-clients`, `manage-identity-providers`, and `view-identity-providers`; it does not grant `realm-admin`. The rerun preserves the database and existing accounts. A `502` can have other causes, so inspect the application and gateway logs when it persists after the rerun.

## Database connection budget

The supplied Compose application URL sets `pool_max_conns=12`, allowing up to 12 runtime
database connections per application instance. Migration and identity connections are separate.
Budget the total across all replicas and services against PostgreSQL's `max_connections`.

Running the server with your own `DATABASE_URL`, or replacing the application's environment
value in a Compose override, retains that URL's parameters. Change its existing `pool_max_conns`
value when you need a different runtime budget. If the parameter is absent, add `?pool_max_conns=8`,
or `&pool_max_conns=8` if the URL already has a query string. Smaller limits reduce the number of
concurrent database requests. A custom URL without this parameter uses PGX's CPU-derived default
and does not inherit the Compose limit.

The installer preserves an existing checkout and its base `compose.yaml`; it regenerates
`.local/generated/compose.private.yaml`. An image-only upgrade therefore keeps the base file's
previous connection budget. Adopt the new value explicitly in the application's database URL
or a separately applied operator-owned Compose override when upgrading.

## Build from source

## Requirements

- Docker with Compose v2
- Node.js 22 (for the local initialization script)
- Go 1.27.3 only if you want to run the server suite outside the containers

## 1. Generate a local configuration

```
node scripts/local-init.mjs
```

It writes, once and only if they are absent:

- `.env` — database, identity and cryptographic secrets, all randomly generated
- `.local/generated/realm.json` — the identity realm to import, with no user account in it
- `MILVAGO_SETUP_TOKEN` in `.env` — the one-time token that opens the setup wizard

The Keycloak bootstrap username is `bootstrap-admin`; its
`IDENTITY_ADMIN_PASSWORD` is generated from 32 random bytes. `SESSION_KEY` and
`CONTENT_KEYS` are separate random encryption roots. This stack has no
`ENCRYPTION_KEY` setting. Read their values and `MILVAGO_SETUP_TOKEN` only in the
owner-readable `.env` file.

A second run preserves these values rather than regenerating them, so restarting
never invalidates sessions or sealed content.

## 2. Start the stack

```
docker compose up -d --build
```

| Service | Address | Role |
|---|---|---|
| `application` | http://localhost:4020 | Server and console |
| `identity` | http://localhost:4080 | Keycloak, realm `milvago` |
| `mail` | http://localhost:4081 | Mailpit, catches outgoing mail |
| `database` | 127.0.0.1:55432 | PostgreSQL |

Every port is bound to the loopback interface.

## 3. Create the first administrator

Open http://localhost:4020: with no administrator yet, the console shows the setup wizard
instead of the sign-in page. Enter the `MILVAGO_SETUP_TOKEN` value from `.env`, then choose
the administrator account and its password, the second factor, the organization, the e-mail
server (Mailpit answers on host `mail`, port `1025`, no security) and the privacy defaults.
Nothing is saved before the last step. You then sign in with the account you chose, which
becomes the owner. Once an administrator exists the wizard is closed for good and the token
opens nothing; you may remove it from `.env`.

HTTP origins are accepted for testing over a trusted LAN. Use HTTPS through a reverse
proxy or gateway for broader access; session cookies carry `Secure` when the external
application URL uses HTTPS.

## Endpoint agent and browser extension

The new detection catalogue requires catalog engine `0.7.0` in both the agent and browser
extension. Upgrade both together before activating this server's catalogue, including when
the instance retains an older edited catalogue: this server conservatively signs every
catalogue with that minimum. Agent `0.6.4` cannot apply the new catalogue. Its previous cached
catalogue expires; an explicit upgrade-required refusal does not preserve detection forever.
The compatible signed Community agent and extension `0.7.44` are available in the
[public agent release](https://github.com/Milvago-AI/milvago-agent/releases/tag/community-agent-v0.7.44)
and are included in the bundle pinned by the public server installer. Deploy the compatible
agent and extension together on managed devices; updating the server alone does not prove
that those devices have been upgraded.

They live in their own repository. An image built from this source alone serves no extension (`/ext/*` answers `503 extension_unconfigured`) and no installer. The prepared installation script fetches and mounts the signed Community agent bundle separately.

The Linux installation archive and the signed executable update are distinct artifacts. When
upgrading from 0.6.x, run the full Linux installer to update the relay, updater and discovery
service as well. A binary update replaces the core agent executable; it does not install or
upgrade those system services.

## Running the tests

```
cd console && npm ci && npm test        # console
cd server && go test ./...              # server, Community edition
```

`docker compose build` runs the console and server suites inside the build itself: an image
is not produced from a red tree.