> For the complete documentation index, see [llms.txt](https://docs.hex-rays.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.hex-rays.com/ida-9.5/add-ons/lumina/admin/lumina-server.md).

# Lumina Server Administration

## Introduction

{% hint style="success" %}
The Lumina server is a single self-contained program. If you are coming from an earlier one, this is what changed:

* **Nothing to install**, and **no separate database server to run**: unzip the download and run it. Metadata is kept in an embedded database unless you ask for MariaDB.
* **One command sets it up.** [`setup`](#installation) writes the configuration, creates the database, makes the first administrator account, and registers the system service.
* **The server license is no longer tied to a MAC address**, so a deployment can move between machines.
* An existing `lumina_server_pro` deployment can be [migrated](#migrating-an-existing-deployment).

Existing IDA clients remain protocol-compatible. Update their server address only if the deployment address changes.
{% endhint %}

This manual describes the installation, management, and interaction with an on-the-premises IDA Pro Private Lumina server.

It is primarily intended for administrators, and will focus on the Lumina server component, that can be purchased for IDA Pro.

{% hint style="info" %}
Refer to the [Lumina Server Installation Checklist](/ida-9.5/add-ons/lumina/admin/lumina-server/lumina-server-checklist.md) for a concise set of steps to follow.
{% endhint %}

## Prerequisites

After your purchase of Lumina server, open the [Download Center](https://my.hex-rays.com/dashboard/download-center), select the appropriate release channel, then open **ida-lumina-server** and the release you want to install. Before you begin, have the two files issued for this deployment:

* a `lumina_server_<LID>.hexlic` (where \<LID> is your license ID)
* the certificate bundle for the connection between IDA and the server

{% hint style="info" %}
You should not try to create the certificate yourself: IDA checks the server certificate against a single Hex-Rays root, and rejects a certificate from any other authority.
{% endhint %}

The server will not start without both files, so download them before you begin.

You need `root` on the host only if you want the server to run as a system service that starts at boot.

### Storage

The Lumina server keeps its metadata in an **embedded database**, in a single file inside the deployment, and that is the default. There is no separate database server to install, configure or operate. The embedded database still needs to be backed up before upgrades; see [Backup and restore](#backup-and-restore).

**MariaDB** remains available for a multi-user or production deployment, and is what a migrated `lumina_server_pro` deployment keeps using. Choose it at setup time with `--db mariadb` and the `--mysql-*` options; the configuration file then holds the database password, and is written so that only its owner can read it.

{% hint style="info" %}
The previous server required a MySQL instance, a database created by hand, and a specific password plugin. None of that applies unless you deliberately choose MariaDB.
{% endhint %}

## Installation

### What you download

The download is one zip per platform, and it contains a folder with everything in it:

```
lumina-server-<version>-<target>.zip
└── lumina-<version>-<target>/
    ├── lumina-server     the server
    ├── lumina-client     the admin client
    └── README.md
```

Unzip it and both programs are ready to run — the executable bit survives the archive, so there is no `chmod` step. `cd` into the folder, and every command in this manual works as written.

{% hint style="info" %}
These are not the names the previous Lumina server used. It shipped `lumina_server_pro` and `lc`; a script written against that install needs those two words changed.

IDA Pro 9.4 and later install their own `lc`, which is a different program from the `lumina-client` here — so the two can no longer be confused.
{% endhint %}

Both programs say which platform they are for: `./lumina-server version` prints the version, build date and target.

### Supported platforms

The Lumina server runs on **Linux x64 and Linux arm64**. We have tested it on Debian and Ubuntu, but other major flavors of Linux should be fine too.

{% hint style="info" %}
The Lumina Server has its own version and release schedule. Check the installed version with `./lumina-server version`.

What governs whether a client can talk to a server is the protocol between them, not the version numbers — and on that, nothing has narrowed: this server speaks the protocol IDA's Lumina client already uses and still accepts the older revisions of it, so an IDA installation that worked with your previous Lumina server works with this one. Only the address it connects to may need changing.

Run a current server release and include the output of `./lumina-server version` when reporting a problem.
{% endhint %}

### Supported architectures

Lumina functionality in IDA Pro is **currently available only when analyzing binaries compiled for the following architectures**:

* PC (x86/x64)
* ARM
* PPC
* MIPS
* RISC-V

If a user loads a binary compiled for an unsupported architecture, the Lumina menu will not appear in IDA Pro and pushing or pulling metadata will not be possible.

### Where to unzip it, and whether to use `sudo`

Where the folder goes depends on how the server will run, so decide the two together. `sudo` is what makes the deployment belong to **the machine** rather than to your user account, and only a machine-wide deployment can be registered as a system service that starts at boot. Nothing else in `setup` needs `root`.

| What you want                     | Run setup as                 | Unzip it                               |
| --------------------------------- | ---------------------------- | -------------------------------------- |
| Try it out, or run it yourself    | `./lumina-server setup`      | anywhere                               |
| A system service, started at boot | `sudo ./lumina-server setup` | somewhere the service account can read |

The second row carries a constraint the first does not. A system service runs under an account of its own — `lumina-server`, created by `setup` — which is in neither the owner nor the group of your home directory. To read the deployment's data it needs execute permission for others on **every** directory on the path, and a home directory does not give it (`0750` on Ubuntu since 21.04, `0700` on RHEL).

So for a system service, put the folder somewhere that account can reach. `/opt` is where add-on software goes and every account can pass through it:

```bash
sudo mv lumina-<version>-<target> /opt/lumina-server
cd /opt/lumina-server
```

{% hint style="info" %}
Use an unversioned path. An upgrade replaces the program where it stands and keeps the data beside it.
{% endhint %}

If you run `sudo ./lumina-server setup` from somewhere the service cannot reach, `setup` says so and stops **before writing anything**, naming the directory that is closed and the ways forward.

### Running setup

Hand `setup` the two files issued for this deployment and it does the rest:

```bash
sudo ./lumina-server setup --defaults \
  --cert-bundle <your-bundle>.zip \
  --license <your-license>.hexlic
```

`setup` writes the configuration, creates the data directory and database, places the license and the certificate **before** the service starts, creates the first administrator account, and registers and starts the system service.

{% hint style="warning" %}
**The administrator password is printed once**, in the closing summary, and only to the terminal — never to a log. Store it before you close the terminal. If it is lost, reset it with `./lumina-server admin reset-password`.
{% endhint %}

Run `setup` with no flags for the guided version. It asks the same questions, and it looks for your two files in the folder holding the program and in the one your terminal is in, offering the newest match it can read. For a license file it also prints when that license expires — **read that line**, because a folder that has been through a renewal still holds the old file, and an expired license gives you a setup that reports success and a server that will not start.

The deployment keeps its data in `data/` beside the program:

| Path                                  | What it holds                                            |
| ------------------------------------- | -------------------------------------------------------- |
| `data/config/config.yaml`             | ports, storage backend, authentication mode, TLS paths   |
| `data/config/*.hexlic`                | the server license, if you place it by hand              |
| `data/config/lumina_server.{crt,key}` | the certificate and key from your bundle                 |
| `data/db/lumina.db`                   | the metadata, users and history, on the embedded backend |

{% hint style="info" %}
`setup` records the path of the program it was run from, and every later command reads it back. If you move or delete that file, the deployment stops working — `service register` refuses, and `service status` says so.
{% endhint %}

### Choosing how IDA users authenticate

The Lumina server can decide who may connect in one of two ways, and **the choice is recorded in the database at setup time and cannot be changed afterwards without starting from an empty one**. Decide before you run `setup`. Most deployments use `lumina`; choose `vault` only if you already run a Hex-Rays Vault (Teams) server.

* **`lumina`** *(default)* — this server holds the user names and passwords. Nothing registers itself over the network: an unknown user name is refused whatever the state of the user list, so every account is created by an administrator. Choose this unless you already run Teams.
* **`vault`** — the user name and password are forwarded to your Hex-Rays Vault (Teams) server, and its answer decides. Choose this if you already run Vault-backend Teams: your analysts are in that directory already, they keep one set of credentials, and disabling an account in Teams disables it here.

```bash
# Teams (vault) deployment
sudo ./lumina-server setup --defaults --no-service \
  --db sqlite --auth-mode vault \
  --vault-host <teams-host>:65433 \
  --cert-bundle <your-bundle>.zip --license <your-license>.hexlic
```

#### Installation in a Teams setup

In a Teams deployment the Lumina server must be told **which** vault it may trust, because that connection carries your users' passwords. You approve the exact certificate your vault serves, once:

```bash
sudo ./lumina-server vault-trust
sudo ./lumina-server service register
```

The unattended command above leaves the service unregistered until you approve the certificate. A guided `setup` asks for the same approval when it can reach the vault. If it cannot — a firewall not open yet, or a vault not deployed yet — the installation still finishes, and the server will refuse to start in `vault` mode until the certificate is approved.

{% hint style="warning" %}
**Check the fingerprint against the vault itself before accepting it.** Ask the vault administrator for the expected fingerprint, or read it from the certificate file on the vault host:

```bash
openssl x509 -in vault.crt -noout -fingerprint -sha256
```

A renewed vault certificate means approving the new one with `vault-trust` again, and until you do, logins are refused.
{% endhint %}

### Activating the server license

The server needs its own `.hexlic` to start. Unlike the previous Lumina server, **it is not bound to a MAC address**: there is no host ID to collect, so a deployment can move machines or run in a container without the license being reissued.

The gate checks the signature, that the file is a Lumina server license, that it has at least one seat, and that it is still valid. It runs before any listener binds, so a refusal leaves nothing running.

Expiry follows a 30/30-day pattern: more than 30 days out it starts silently; inside 30 days it starts and warns; expired it starts and warns for another 30 days; past that it refuses.

### Installing the server license

`setup --license <path>` is the normal route, and it is what the quick start above uses.

To place the file yourself instead, put it in the deployment's `data/config/` directory under a name beginning `lumina_server` and ending `.hexlic`, then start the server. Several licenses may sit side by side: the first one that passes is used, so dropping a renewal beside an expiring license is safe.

{% hint style="warning" %}
**Keep it readable by the service account.** A license file placed by hand as `root` with restrictive permissions can be unreadable to the service. A `.hexlic` carries no secret — mode `0644` is the safe choice, and it is what `setup --license` uses.
{% endhint %}

### Creating the initial database schema

There is nothing to do: `setup` creates the database, and schema changes are applied automatically when a newer version starts. There is no `--recreate-schema` step, and no flag that will erase your data.

### Testing the server

**If you installed it as a system service:**

```bash
sudo ./lumina-server service status
```

**If you are running it yourself**, start it in the foreground and leave it running:

```bash
./lumina-server start
```

Either way, confirm the server answers on the administration port — 8080 unless you changed it:

```bash
curl http://<host>:8080/api/health
```

Then confirm it answers a client on the Lumina port, 7443 by default:

```bash
./lumina-client -h <host>:7443 -u <user> info
```

{% hint style="info" %}
`start` and `service start` are different commands. `start` runs the program in your terminal; `service start` drives the installed service. Running both at once makes them collide on the ports.
{% endhint %}

## Initial configuration

### Creating the administrator

The first administrator is created by `setup`, which prints the user name and password once, in its closing summary.

{% hint style="warning" %}
This is a change from the previous Lumina server, where **the first user to log in became the administrator**. That no longer happens: accounts are never created by connecting. If you have a runbook that says to log in with `lc` to create the administrator, it no longer applies.
{% endhint %}

In a `lumina` deployment, add the rest of your users on the Users page of the administration console, or with the server CLI. Use `--no-admin` for an analyst who should not have administrative access:

```bash
./lumina-server admin create --username <name> --no-admin
./lumina-server admin list
```

In a Teams deployment there is nothing to provision here: an account works on Lumina as soon as it works in Teams.

### The administration console

The server serves a web console on its admin port — `http://<host>:8080/admin` by default — with pages for users, the metadata history, what clients asked for and did not find, and the state of the stored metadata.

Sign in with the administrator account `setup` created.

{% hint style="warning" %}
The console admits administrators only, and a correct password from a non-administrator account is refused exactly as a wrong one would be. Keep the admin port on a trusted network: only the Lumina port needs to be reachable by your analysts.
{% endhint %}

## Useful environment variables

For the **admin client**, so you do not repeat yourself:

```bash
export LUMINA_CLIENT_PASSWORD=<password>
./lumina-client -h lumina.acme.com:7443 -u alice info
```

Passing the password in the environment keeps it out of the list of running processes, which `-p` does not.

For **IDA**, the Lumina server is normally configured in IDA's own Lumina options. For unattended or scripted runs, IDA also reads the connection from the environment:

```bash
export LUMINA_PRIMARY="alice:<password>@lumina.acme.com:7443"
export LUMINA_PRIMARY_TLS=YES
```

The connection string accepts `host:port`, `user@host:port` or `user:pass@host:port`. `LUMINA_SECONDARY` configures the secondary server the same way.

{% hint style="info" %}
Without a password in the connection string, IDA takes it from the operating system's credential store, which a batch run without an unlocked keyring does not have. Put the credentials in the connection string for unattended runs.
{% endhint %}

For the **server**, every setting has an `LS_`-prefixed variable, and the configuration file wins over the environment.

## Lumina server command-line options

| Command       | What it does                                                                                         |
| ------------- | ---------------------------------------------------------------------------------------------------- |
| `setup`       | Set up the deployment: configuration, data directory, first administrator, service                   |
| `start`       | Run the server in this terminal                                                                      |
| `service`     | Manage the installed service: `register`, `unregister`, `start`, `stop`, `restart`, `status`, `logs` |
| `admin`       | Manage accounts: `create`, `list`, `reset-password`, `delete`                                        |
| `vault-trust` | Approve the vault server's certificate, in a Teams deployment                                        |
| `teardown`    | Stop and unregister the service and forget the deployment; `--purge` also deletes the data           |
| `version`     | Print the version, build date and platform                                                           |
| `notices`     | Print the third-party notices for the libraries the program is built from                            |

The options most often used with `setup`:

| Option                       | Purpose                                                                                      |
| ---------------------------- | -------------------------------------------------------------------------------------------- |
| `--defaults`                 | Accept every default; do not ask                                                             |
| `--license <path>`           | The server license                                                                           |
| `--cert-bundle <path>`       | The certificate bundle as issued; `--tls-key`/`--tls-crt` if you keep the two files yourself |
| `--rest-port` / `--rpc-port` | Administration port (8080) and Lumina port (7443)                                            |
| `--auth-mode lumina\|vault`  | How IDA users authenticate; requires `--db`, and `vault` also needs `--vault-host`           |
| `--db sqlite\|mariadb`       | Storage backend, with the `--mysql-*` options for MariaDB                                    |
| `--data-dir <path>`          | Data directory, if not `data/` beside the program                                            |
| `--no-service`               | Do not register a system service                                                             |
| `--from-legacy <dir>`        | Migrate an existing `lumina_server_pro` deployment                                           |

`./lumina-server --help` lists them all, and `--help` after any command explains that one.

### The admin client

`lumina-client` replaces `lc` for server administration, and keeps its commands: `info`, `users`, `user`, `passwd`, `hist`, `session`, `stats`, plus `trust` for the server certificates this machine has approved. Give it the server with `-h <host>:<port>` and the user with `-u`.

## Backup and restore

Nothing is backed up automatically. **Back up before every upgrade.**

On the embedded backend everything worth keeping is in the deployment's data directory:

```bash
sqlite3 /opt/lumina-server/data/db/lumina.db \
  "VACUUM INTO '/backup/lumina-$(date +%Y%m%d).db'"

tar czf /backup/lumina-config-$(date +%Y%m%d).tgz \
  -C /opt/lumina-server/data config
```

On MariaDB, use `mysqldump` or your usual mechanism for the database, and copy `data/config` the same way.

## Upgrading the server

The upgrade is a replacement of the program, in place:

1. Stop it: `sudo ./lumina-server service stop`
2. **Back up the database** (above).
3. Put the new `lumina-server` where the old one was — the folder the deployment was set up from.
4. Start it: `sudo ./lumina-server service start`

Schema changes are applied automatically at startup. A database a newer server has opened can still be read by the previous one, so putting the old program back works — but the database is never converted back, which is why the backup matters.

{% hint style="warning" %}
**In a Teams deployment, approve the vault's certificate before step 4** if you are coming from a server that never did: `sudo ./lumina-server vault-trust`. The startup message names the command if you reach it the other way round.
{% endhint %}

## Migrating an existing deployment

`setup` can migrate an existing `lumina_server_pro` deployment. The new server reuses its database, its Lumina port, its certificate and key, its server license and its authentication mode.

**Stop and disable the old server first** — setup refuses while it is running or still enabled, because two servers writing the same tables is the one outcome nobody recovers from:

```bash
sudo systemctl stop lumina
sudo systemctl disable lumina
```

Then put the new folder somewhere the service account can read — **not** the old install's directory, which has to stay as it is until the migration has read it.

{% hint style="info" %}
**Upgrading from `lumina_server_pro`?**

When you run `setup` interactively, this is the first prompt:

```
Migrate an existing Hex-Rays Lumina Server install?
```

Answer **Yes**. Setup then asks for the legacy installation directory. The default answer is **No**, for a new deployment.
{% endhint %}

For an unattended or scripted migration, skip the prompts by passing the legacy installation directory with `--from-legacy`.

This mode normally registers and starts the service automatically. The example adds `--no-service` to postpone the first start until after a Teams deployment has approved the vault certificate with `vault-trust`.

In a non-Teams deployment, you can omit `--no-service`. Setup then registers and starts the service, so skip the later `service register` step.

```bash
sudo mv lumina-<version>-<target> /opt/lumina-server
cd /opt/lumina-server

sudo ./lumina-server setup --from-legacy /opt/lumina --no-service
```

`setup` prints what it placed for the license and the certificate. If the old directory held no usable server license, it says so, and the deployment needs one before it will start.

In a Teams deployment, approve the vault's certificate before the service starts — the old deployment never recorded one:

```bash
sudo ./lumina-server vault-trust
```

Then register, start and verify the service:

```bash
sudo ./lumina-server service register
sudo ./lumina-server service status
```

{% hint style="info" %}
The old install's folder is only ever read: the certificate and the license are copied out of it, nothing is written into it and nothing is removed. The MariaDB database is not copied: the new server keeps using it and updates its schema. The old server can still read and write the updated schema, so going back keeps the data recorded in the meantime. Back up the database before you migrate all the same. To go back, remove this service and re-enable the old one:

```bash
sudo ./lumina-server service unregister    # also keeps it from starting at boot
sudo systemctl enable --now lumina
```

{% endhint %}

## Troubleshooting

### The service starts, then keeps restarting

Almost always a missing or rejected server license: the server refuses to start, and the service restarts it. `./lumina-server service logs` names the reason, which is one of: no license found, bad signature, wrong product, no seats, not yet valid, or expired.

Check too that the file is in `data/config/`, that its name begins `lumina_server` and ends `.hexlic`, and that the service account can read it.

### IDA says "login failed"

In a `lumina` deployment an unknown user name is refused whatever the state of the user list — accounts are never created by connecting. Check the account exists with `./lumina-server admin list`, or on the console's Users page.

If the account exists and the password is right, check that the client is sending a password at all: IDA takes it from the operating system's credential store unless it is given in the connection string.

### A correct password is refused by the console

The console admits administrators only, and a non-administrator account is refused exactly as a wrong password would be. The audit log records the difference, so an administrator can tell the two apart.

### The admin client refuses to connect: certificate not the one approved

`lumina-client` remembers the certificate a server presented the first time it connected, and refuses if it changes:

```
error: the certificate at <host>:7443 is NOT the one this machine approved.
```

That is expected after the server is reinstalled with a new certificate, or a renewed one. Review and update what this machine has approved with `./lumina-client trust`. If you cannot explain the change, treat it as one worth investigating rather than approving.

### Every login fails in a Teams deployment

IDA reports the same message for several causes. The server log separates them: nothing listening at the address, host and port written into one field, a vault certificate that no longer matches the approved one, or a credential the vault itself rejected. `./lumina-server service logs` names which.

### The server refuses to start after the configuration was moved or deleted

A missing configuration file is an error, not a warning: the server will not silently fall back to defaults and ignore the deployment you configured. Restore or mount it, or tear down and set up again.

### A system service and a custom data directory

The service account needs execute permission for others on every directory leading to the data directory. If the data belongs on a separate volume, mount it and point `--data-dir` at it; nothing else is needed as long as the path is traversable.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.hex-rays.com/ida-9.5/add-ons/lumina/admin/lumina-server.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
