lumen: a private Lumina server for an IDA Pro team
A private Lumina server for IDA Pro
At a glance
- What is it?
- Lumen is a Rust implementation of a private Lumina server, the service behind IDA Pro's built-in function signature lookup, that a reversing team can run for itself with its own PostgreSQL database. The interesting parts are the parts nobody expects, the pinned certificate IDA refuses to let you replace without writing hexrays.crt, and the fact that the server refuses to merge conflicting function data and returns the highest scoring metadata instead.
- Who is it for?
- Adopt lumen if your team uses IDA Pro, if you want the function signature reuse that Lumina provides without sending your identifiers to a shared public server, and if you are prepared to deal with the certificate pinning. Do not adopt it if your team does not use IDA, or if your reversing is individual and a shared server would not be used, and note that the only tagged release is v0.1.0 from 2022-01-21 even though the last push was on 2026-10-01.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 22 days ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A Lumina server you run yourself
Lumen is a private Lumina server that can be used with IDA Pro 7.2 and newer, and the project is developed by Naim A. under the MIT licence. The public instance at lumen.abda.nl runs this server, and the protocol research behind it is written up in a post linked from the README.
Lumina is the feature in IDA Pro that lets a reversing team recognise a function it has already analysed. Signatures, comments and other metadata are looked up by hashes, so the second analyst of a binary does not start from nothing. The problem it solves for a team is that the default arrangement involves sending queries, and the metadata attached to those queries, to somebody else's server.
The features are three lines. It stores function signatures so you and your team can quickly identify functions that you found in the past using IDA's built-in Lumina features. It is backed by PostgreSQL. And it has an experimental HTTP API that allows querying the database for comments by file or function hash.
So this is a self hosted database of reverse engineering metadata with a protocol endpoint in front of it, and the HTTP API is the extra on top, useful for tooling that wants to search comments directly rather than through IDA.
The repository is a Cargo workspace with two members, common and lumen, with the release profile set to fat link time optimisation, and the tree carries a Dockerfile, a build.Dockerfile, a docker-compose.yml, a docker-init.sh, a config-example.toml and a CHANGELOG.md.
The maintenance record needs reading carefully. The last push was on 2026-10-01, so the code is being worked on, but the only published release is v0.1.0 from 2022-01-21, which means there is no versioned artefact to point at.
What IDA sends to your server
The README states plainly what data may leave your machine, and this is the section to read before pointing a team at an instance.
The following information may get sent to the lumen server: IDA key, Hostname, IDB path, original file path, file MD5, function signature, stack frames and comments.
That list is the honest cost of the feature, and it explains why a private server exists at all. The hostname and the IDB path identify the analyst and the project. The original file path and the file MD5 identify the binary. The function signature, the stack frames and the comments are the payload of the lookup itself, and the IDA key identifies your licence to the service.
For a team that works on third party binaries, some of these are commercially sensitive even when the binary is not, and that is the argument for running the server yourself. It is also the argument for reading the list before you decide.
The second design decision is equally explicit. No attempt is made to merge function data, and the README notes this may cause a situation where metadata is inconsistent. Instead, the metadata with the highest calculated score is returned to the user.
That is a different philosophy from the one most collaborative tools use. A merging service would try to combine the comments of two analysts, and two analysts often disagree about what a function does. Lumen does not merge, it picks. The result is always internally consistent, and it is always one person's view, and a comment written by a colleague is never silently woven into your own database.
Docker Compose is the recommended route
The Getting Started section offers two methods and marks the first as recommended, the Docker method, in which precompiled docker images will be downloaded and all you need is the docker-compose.yml in the repository.
The steps are short. Install docker-engine and docker-compose. If you are using a custom TLS certificate, copy the private key, with a .p12 or .pfx extension, to ./dockershare and set the key password in .env as PKCSPASSWD. If you are using a custom Lumen config, copy it to ./dockershare/config.toml. Otherwise, or once those steps are done, just run docker-compose up.
One output is easy to miss and is needed later. Regardless, if TLS is enabled in the config.toml, a hexrays.crt will be generated in ./dockershare to be copied to the IDA install directory.
The compose file itself is a good picture of the deployment. The database service is postgres:15.1-alpine with a health check that runs pg_isready, a named volume for the data, mem_swappiness set to 0, and credentials of lumina and lumina with the password 1, on a port that is only exposed to the compose network rather than published to the host.
lumina:
build: .
image: ghcr.io/naim94a/lumen:master
depends_on:
db:
condition: service_healthy
ports:
- 1234:1234
- 8082:8082
environment:
PKCSPASSWD: $PKCSPASSWD
DATABASE_URL: postgres://lumina:1@db/lumina
volumes:
- ./dockershare:/dockershareTwo ports are published, 1234 and 8082, the first being the Lumina protocol listener and the second the experimental HTTP API. The database is reachable only as db on the internal network, and the ./dockershare volume is where the configuration, the key and the generated certificate live, so they survive a rebuild of the container.
Building from source with diesel migrations
The alternative to the prebuilt image is a Rust build, and the README gives the full sequence, starting with a clone of the repository and a Rust toolchain, then changing into the lumen directory.
The database is set up by installing postgres and then installing diesel-cli and running the migrations:
cargo install diesel_cli --no-default-features -Fpostgres
diesel --config-file common/diesel.toml \
--database-url postgres://postgres:password@localhost/lumen \
migration runThe build itself is cargo build --release, and the server is started with the config file:
./lumen -c config.tomlThe Dockerfile shows how that build is packaged, and it is a careful multi stage image. The builder is rust:1.93.1-slim-bookworm with pkg-config, libssl-dev and libpq-dev installed, the cargo registry protocol set to sparse, and diesel_cli installed at a pinned version, 2.2.10, with the postgres feature only. The source is copied in and built with cargo build --release, and the resulting binary is moved to /root/.
The runtime stage is debian:bookworm-slim with openssl and libpq5, and it copies only what is needed to run: the diesel binary, the migrations directory, the diesel.toml, the lumen binary, the example configuration and the init script, which is what the container runs as its command.
One line in that runtime stage deserves attention. The Dockerfile appends extendedKeyUsage = serverAuth to the v3_req section of openssl.cnf, which is a small but deliberate change to the system OpenSSL configuration so that a certificate the server generates is usable for the TLS listener.
The pinned certificate and hexrays.crt
The TLS section explains a problem that would otherwise cost an afternoon.
IDA Pro uses a pinned certificate for Lumina's communication, so adding a self-signed certificate to your root certificates will not work. The README gives the way out: you can override the hard-coded public key by writing a DER-base64 encoded certificate to hexrays.crt in IDA's installation directory.
So a private server with TLS is a short sequence of openssl commands, and the README provides them:
# create a certificate
openssl req -x509 -newkey rsa:4096 -keyout lumen_key.pem -out lumen_crt.pem -days 365 -nodes
# convert to pkcs12 for lumen; used for `lumen.tls` in config
openssl pkcs12 -export -out lumen.p12 -inkey lumen_key.pem -in lumen_crt.pem
# export public-key for IDA; Copy hexrays.crt to IDA installation folder
openssl x509 -in lumen_crt.pem -out hexrays.crtThe certificate is created, converted to the pkcs12 form the server configuration refers to, and the public part is exported for IDA. The Docker method generates the same hexrays.crt file for you, which is why the README mentions it in the Docker steps as well as here.
The server side of TLS is a listener configuration, and the design is unusually flexible. A listener is plain TCP unless its tls table includes a certificate, which permits both connection types on separate ports.
[lumina]
server_name = "lumen"
[[lumina.listeners]]
bind_addr = "0.0.0.0:1234" # TLS
[lumina.listeners.tls]
server_cert = "lumen.p12"
[[lumina.listeners]]
bind_addr = "0.0.0.0:1235" # plain TCPConfigure TLS capable IDA clients to use port 1234, and configure plain clients to use port 1235 and set LUMINA_TLS = NO. Running a plain listener alongside a TLS one is what lets you try the server without generating certificates at all, and what lets you keep a plaintext listener for local tooling while the analysts use TLS.
Pointing IDA at your instance
The README splits the client setup by IDA version, because the configuration mechanism changed.
For IDA Pro 8.1 and newer, the settings are in the interface. Go to Options, General, Lumina, select Use a private server, then set your host and port and guest as username and password. The guest credentials are the values the README tells you to enter for both fields.
For IDA Pro below 8.1, the configuration is a text file. Open cfg\ida.cfg in the installation directory, locate the commented out LUMINA_HOST and LUMINA_PORT, and change their values to the address of your lumen server. If you did not configure TLS, add LUMINA_TLS = NO after the line with LUMINA_PORT.
LUMINA_HOST = "192.168.1.1";
LUMINA_PORT = 1234
// Only if TLS isn't used:
LUMINA_TLS = NOThere is a migration warning in between. If you used Lumen in the past, remove the LUMINA settings in the ida.cfg or idauser.cfg files, otherwise you will get a warning about bad config parameters.
There is also a wrapper script route for the older setup, which is how you set an environment variable for the IDA process on Linux or Windows. On Linux, a shell script that exports LUMINA_TLS=false and then runs the program given as its first argument, saved as ida_lumen.sh and made executable, so IDA is started with./ida_lumen.sh./ida or./ida_lumen./ida64. On Windows, the same thing as a batch file with set LUMINA_TLS=false and %1, saved as ida_lumen.bat.
The minimum is IDA Pro 7.2, and the README is explicit that you need it in order to use lumen.
Editorial conclusion
Adopt lumen if your team uses IDA Pro, if you want the function signature reuse that Lumina provides without sending your identifiers to a shared public server, and if you are prepared to deal with the certificate pinning. Do not adopt it if your team does not use IDA, or if your reversing is individual and a shared server would not be used, and note that the only tagged release is v0.1.0 from 2022-01-21 even though the last push was on 2026-10-01. Verify first that the metadata IDA will send, which the README lists item by item, is acceptable for your environment, that your IDA version is 7.2 or newer, and that the certificate handling works with your IDA installation before you point a team at it.
Frequently asked questions
What is the lumen server and what does it store?
Lumen is a private Lumina server for IDA Pro 7.2 and newer that stores function signatures so you and your team can identify functions found in the past using IDA's built-in Lumina features. It is backed by PostgreSQL and also offers an experimental HTTP API for querying comments by file or function hash.
What data does IDA send to a private lumen server?
The README states that the following may get sent: IDA key, Hostname, IDB path, original file path, file MD5, function signature, stack frames and comments. That list is the reason to run the server yourself rather than use a shared one.
How do I install and run lumen with Docker?
The recommended method is Docker, and all you need is the docker-compose.yml in the repository. Install docker-engine and docker-compose, put a custom TLS key in ./dockershare with the password in .env as PKCSPASSWD and a custom config in ./dockershare/config.toml, then run docker-compose up. If TLS is enabled, a hexrays.crt is generated in ./dockershare to copy to the IDA install directory.
Why does lumen need a hexrays.crt file?
IDA Pro uses a pinned certificate for Lumina's communication, so adding a self-signed certificate to your root certificates will not work. The README says you can override the hard-coded public key by writing a DER-base64 encoded certificate to hexrays.crt in IDA's installation directory, and gives the openssl commands to create, convert and export it.
How does lumen handle conflicting function metadata?
No attempt is made to merge function data, and the README notes this may cause a situation where metadata is inconsistent. Instead, the metadata with the highest calculated score is returned to the user.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/naim94a-lumen)Was this useful?