Docker configuration for hosting HexVault, Lumina, and HexLicSrv.
Installer files go into each service’s ./<service>/image folder.
Supported version:
- IDA 9.0.240925 - September 30, 2024
 - IDA 9.1.250226 - February 28, 2025
 - IDA 9.2.250908 - September 8, 2025
 
.
├─ docker-compose.yml              # runs all services (hexlicsrv, hexvault, lumina + mysql)
├─ hexlicsrv/
│  ├─ image/                       # put hexlicsrv installer here (e.g., hexlicsrv_x64linux.run)
│  ├─ CA/                          # CA.pem + CA.key
│  ├─ config/                      # persistent config (mounted)
│  ├─ data/                        # persistent data (mounted)
│  └─ logs/                        # persistent logs (mounted)
├─ hexvault/
│  ├─ image/                       # put hexvault installer here (e.g., hexvault_x64linux.run)
│  ├─ CA/  config/  data/  logs/
└─ lumina/
   ├─ image/                       # put lumina installer here (e.g., lumina_x64linux.run)
   ├─ CA/  config/  data/  logs/
   └─ mysql/                       # MySQL persistent volume
- Linux host with Docker and Docker Compose
 - Your own internal Certificate Authority (CA) pair: 
CA.pem(cert) andCA.key(private key) - For Lumina: MySQL 8 (provided by the included 
mysqlservice) 
Create a CA once and place it into every service’s CA/ folder:
openssl req -x509 \
    -newkey rsa:4096 -sha512 -keyout CA.key -out CA.pem -days 3650 -nodes \
    -subj "/C=BE/L=Liège/O=Hex-Rays SA./CN=Hex-Rays SA. Root CA"The containers refuse to start if
CA/CA.pemorCA/CA.keyis missing.
- Create 
C:\Program Files\IDA Professional 9.0\CA - Copy your 
CA.keyandCA.peminto that folder - Copy 
license_patch.pyinto the IDA install root - Run as Administrator:
python3 license_patch.py ida-pro
 - Start IDA
 
The provided top-level docker-compose.yml brings up all services:
- hexlicsrv --> port 65434
 - hexvault --> port 65433
 - mysql for lumina
 - lumina --> port 443
 
hexlicsrv/image/hexlicsrv_x64linux.runhexvault/image/hexvault_x64linux.runlumina/image/lumina_x64linux.run
Copy CA.key and CA.pem into:
hexlicsrv/CA/hexvault/CA/lumina/CA/
Edit environment in docker-compose.yml:
LICENSE_HOSTfor hexlicsrvVAULT_HOSTfor hexvaultLUMINA_HOSTfor lumina
These become the CN/SAN in the auto-issued service certificates.
docker compose up -d --buildThe entrypoints run
license_patch.pyinside each container automatically.
- Mounts: 
./hexlicsrv/{CA,config,data,logs}-->/opt/hexlicsrv/... - Config file auto-generated at first start: 
config/hexlicsrv.conf 
- Mounts: 
./hexvault/{CA,config,data,logs}-->/opt/hexvault/... - Config file auto-generated at first start: 
config/hexvault.conf 
- Depends on the 
mysqlservice (health-checked) - DB env must match 
mysqlservice:MYSQL_HOST=mysql,MYSQL_PORT=3306,MYSQL_DATABASE=lumina,MYSQL_USER=lumina,MYSQL_PASSWORD=lumina
 - Mounts: 
./lumina/{CA,config,data,logs}-->/opt/lumina/... - Config file auto-generated at first start: 
config/lumina.conf 
All three services can backup/restore their state to GitHub in one of two modes:
- commits: push chunks + 
manifest.jsoninto a branch underbackups/<SYNC_HOST_ID>/ - releases: upload chunks + 
manifest.jsonas release assets of a tag 
- If local data is empty and a remote snapshot exists --> restore
 - Else package local state and push only if changed (SHA-256 compare)
 
- HexLicSrv / HexVault: 
tar-->zstd -19-->data.tar.zst--> split -->data.tar.zst.part_000,...001, ... - Lumina: 
mysqldump-->zstd -19-->dump.sql.zst--> split -->dump.sql.zst.part_000, ... 
manifest.json stores (among others): archive_sha256, chunk_count, chunk_size_mb, timestamp_utc.
Keep
SYNC_CHUNK_SIZE_MB ≤ 49for GitHub’s 50 MB file limit in repos (default is49).
In docker-compose.yml, per service set:
environment:
  SYNC_ENABLED: "true"                 # enable sync
  SYNC_METHOD: "releases"              # or "commits"
  GH_REMOTE: https://github.com/yourorg/yourrepo.git  # or SSH: [email protected]:yourorg/yourrepo.git
  SYNC_HOST_ID: "hexvault"             # logical node id, used in path under commits mode
  SYNC_CHUNK_SIZE_MB: "49"
  # For write access / private repos or releases:
  # SYNC_AUTH_TOKEN: github_pat_token_here
  # Commits mode (optional identity)
  # GH_BRANCH: main
  # GH_COMMIT_NAME: HexVault CI
  # GH_COMMIT_EMAIL: [email protected]
  # GH_SSH_PRIVATE_KEY: |-
  #   -----BEGIN OPENSSH PRIVATE KEY-----
  #   ...
  # GH_KNOWN_HOSTS: |-
  #   github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...
  # Releases mode
  # GH_RELEASE_TAG: hexvault
  # GH_RELEASE_NAME: HexVault
  # GH_API: https://ghe.example.com/api/v3         # for GHE
  # GH_UPLOAD: https://ghe.example.com/api/uploads # for GHEPAT vs SSH: For HTTPS URLs set
SYNC_AUTH_TOKEN(Bearer for releases, x-access-token for commits). For SSH, provideGH_SSH_PRIVATE_KEYand optionallyGH_KNOWN_HOSTS.
A *_schema.lock file prevents schema recreation on subsequent boots.
Delete the lock if you intentionally want the service to run --recreate-schema again.
- 
World-accessible config (HexLicSrv)
Symptom:
File "/opt/hexlicsrv/config/hexlicsrv.conf" is world-accessible; exiting
Fix:chmod 600 config/hexlicsrv.conf
 - 
World-accessible config (HexVault)
Symptom:
File "/opt/hexvault/config/hexvault.conf" is world-accessible; exiting
Fix:chmod 600 config/hexvault.conf
 - 
Missing tools
Images must include:git,ssh-keyscan,curl,tar,zstd,jq,sha256sum,split,openssl, and for Lumina alsomysql,mysqldump,nc. - 
Auth / permissions fail
VerifyGH_REMOTE, token/SSH key validity, and repo access. For SSH, either supplyGH_KNOWN_HOSTSor the entrypoint will disable strict host checking (less secure). - 
Checksum mismatch on restore
Means the assembled archive’s SHA-256 differs frommanifest.json.
Fix by republishing a clean snapshot (run withSYNC_AUTH_TOKENso the container uploads a fresh manifest and parts), or remove release/branch assets and let the container recreate them. - 
No changes to commit
Normal when the computed SHA-256 equals the remote manifest; nothing is pushed. 
Adds a context-menu entry to open files with IDA on Windows.
- Never commit tokens or private keys. Use Docker secrets, env injection in CI, or a secrets manager.
 - Your CA private key is sensitive; restrict filesystem permissions and repo access accordingly.